cg_args.c (8534B)
1 /* Copyright (C) 2022 Université de Pau et des Pays de l'Adour UPPA 2 * Copyright (C) 2022 CNRS 3 * Copyright (C) 2022 Sorbonne Université 4 * Copyright (C) 2022 Université Paul Sabatier 5 * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com) 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "cg_args.h" 21 #include "cg_catalog_parsing.h" 22 #include "cg_default.h" 23 #include "cg_version.h" 24 #include "cg_default.h" 25 #include "cg.h" 26 27 #include <rsys/rsys.h> 28 #include <rsys/logger.h> 29 #include <rsys/cstr.h> 30 31 #include <getopt.h> 32 #include <stdio.h> 33 34 void 35 print_version(void) 36 { 37 printf( 38 "city-generator2 version %i.%i.%i\n", 39 CG2_VERSION_MAJOR, CG2_VERSION_MINOR, CG2_VERSION_PATCH); 40 } 41 42 void 43 short_help(void) 44 { 45 #ifndef NDEBUG 46 printf("Running debug binary.\n"); 47 #endif 48 49 print_version(); 50 printf("\nUsage:\n" 51 "city_generator2 -m <FILENAME> {-c <FILENAME>}+ [-%c] [-s] [-V verbosity] [-k] [-f <NAME>] [-F <level>] [-E]\n" 52 "city_generator2 [-h]\n" 53 "city_generator2 [-v]\n", 54 CG2_ARGS_CHANGE_BINARY_DEFAULT_OPTION 55 ); 56 printf( 57 "\nMandatory options\n" 58 "-----------------\n" 59 "-m <city_map_filename>\n" 60 " Read a yaml file that describes the city map.\n" 61 "-c <filename>\n" 62 " Read a yaml file containing datasets for a given construction mode.\n" 63 " Can be used more than once.\n" 64 "\nOther options\n" 65 "-------------\n" 66 "-h\n" 67 " Print this help and exit.\n" 68 "-%c\n" 69 " Set the format of output files to "STR(CG2_ARGS_STL_NON_DEFAULT_STR) 70 " (default "STR(CG2_ARGS_STL_DEFAULT_STR)").\n" 71 "-k\n" 72 " Keep running on errors.\n" 73 "-E\n" 74 " Don't use escape characters in logs.\n" 75 " Use as first option to avoid escape characters in initial log messages.\n" 76 "-f <NAME>\n" 77 " Dump the footprint of the building with the given name.\n" 78 " Can be used more than once.\n" 79 "-F <level>\n" 80 " Dump the footprint of some buildings, depending on level:\n" 81 " - With level 1 dump the footprint of any building not generated due to an error.\n" 82 " - With level 2 dump the footprint of any building.\n" 83 " Process the whole file regardless of errors, and exit if any error was found unless -k is used.\n" 84 "-s\n" 85 " Force single threaded execution. By default use as many threads as available.\n" 86 "-v\n" 87 " Print the software version and exit.\n" 88 "-V <LEVEL>\n" 89 " Set the verbosity level (default %i)\n", 90 CG2_ARGS_CHANGE_BINARY_DEFAULT_OPTION, 91 CG2_ARGS_DEFAULT_VERBOSITY_LEVEL 92 ); 93 printf( 94 "\nCopyright (C) 2022-2023 Université de Pau et des Pays de l'Adour UPPA.\n" 95 "Copyright (C) 2022-2023 CNRS.\n" 96 "Copyright (C) 2022-2023 Sorbonne Université.\n" 97 "Copyright (C) 2022-2023 Université Paul Sabatier.\n" 98 "Copyright (C) 2022-2023 |Meso|Star> (contact@meso-star.com).\n" 99 "city_generator2 is free software released under the GNU GPL license,\n" 100 "version 3 or later.\n" 101 "You are free to change or redistribute it under certain conditions\n" 102 "<http://gnu.org/licenses/gpl.html>.\n"); 103 } 104 105 res_T 106 parse_args 107 (struct mem_allocator* allocator, 108 struct logger* logger, 109 int argc, 110 char** argv, 111 struct args** out_args) 112 { 113 res_T res = RES_OK; 114 int opt; 115 int info_provided = 0, c_provided = 0, m_provided = 0, s_provided = 0; 116 struct args* args; 117 char option_list[] = "?c:m:hkEF:f:s:vV:1"; 118 119 ASSERT(allocator && logger && argv && out_args); 120 121 /* Patch option_list[] according to stl format default */ 122 option_list[0] = CG2_ARGS_CHANGE_BINARY_DEFAULT_OPTION; 123 124 args = MEM_CALLOC(allocator, 1, sizeof(*args)); 125 if(!args) { 126 res = RES_MEM_ERR; 127 goto error; 128 } 129 130 args->allocator = allocator; 131 args->logger = logger; 132 darray_names_init(allocator, &args->catalog_files); 133 darray_names_init(allocator, &args->dump_footprint_names); 134 135 /* Set non-zero default values */ 136 args->binary_export = CG2_ARGS_BINARY_STL_DEFAULT; 137 args->verbosity_level = CG2_ARGS_DEFAULT_VERBOSITY_LEVEL; 138 args->stardis_basename = CG2_ARGS_DEFAULT_STARDIS_FILES_BASENAME; 139 140 opterr = 0; /* No default error messages */ 141 while((opt = getopt(argc, argv, option_list)) != -1) { 142 const char* name; 143 switch (opt) { 144 145 case '?': /* Unrecognized option */ 146 { 147 char* ptr = strchr(option_list, optopt); 148 if(ptr && ptr[1] == ':') { 149 logger_print(logger, LOG_ERROR, 150 "Missing argument for option -%c\n", 151 optopt); 152 } else { 153 logger_print(logger, LOG_ERROR, "Invalid option -%c.\n", optopt); 154 } 155 res = RES_BAD_ARG; 156 goto error; 157 } 158 159 case 'c': 160 c_provided = 1; 161 name = optarg; 162 ERR(darray_names_push_back(&args->catalog_files, &name)); 163 break; 164 165 case 'm': 166 if(m_provided) { 167 logger_print(logger, LOG_ERROR, "Option -%c provided twice.\n", opt); 168 res = RES_BAD_ARG; 169 goto error; 170 } 171 args->city_filename = optarg; 172 m_provided = 1; 173 break; 174 175 case CG2_ARGS_CHANGE_BINARY_DEFAULT_OPTION: 176 args->binary_export = !CG2_ARGS_BINARY_STL_DEFAULT; 177 break; 178 179 /* Optional */ 180 181 case 'E': 182 args->no_escape = 1; 183 /* Immediate effect on logs */ 184 logger_set_stream(logger, LOG_OUTPUT, log_prt_fn_ne, NULL); 185 logger_set_stream(logger, LOG_WARNING, log_warn_fn_ne, NULL); 186 logger_set_stream(logger, LOG_ERROR, log_err_fn_ne, NULL); 187 break; 188 189 case 'F': 190 res = cstr_to_int(optarg, &args->dump_footprints_level); 191 if(res != RES_OK 192 || args->dump_footprints_level < 1 || args->dump_footprints_level > 2) 193 { 194 if(res == RES_OK) res = RES_BAD_ARG; 195 logger_print(logger, LOG_ERROR, "Invalid arg for option %c: '%s'.\n", 196 opt, optarg); 197 goto error; 198 } 199 break; 200 201 case 'f': 202 name = optarg; 203 ERR(darray_names_push_back(&args->dump_footprint_names, &name)); 204 break; 205 206 case 'h': 207 info_provided = 1; 208 args->print_help = 1; 209 break; 210 211 case 'k': 212 args->keep_running_on_errors = 1; 213 break; 214 215 case 's': 216 if(s_provided) { 217 logger_print(logger, LOG_ERROR, "Option -%c provided twice.\n", opt); 218 res = RES_BAD_ARG; 219 goto error; 220 } 221 args->stardis_basename = optarg; 222 s_provided = 1; 223 break; 224 225 case 'v': 226 info_provided = 1; 227 args->print_version = 1; 228 break; 229 230 case 'V': 231 res = cstr_to_int(optarg, &args->verbosity_level); 232 if(res != RES_OK 233 || args->verbosity_level < 0 234 || args->verbosity_level > 3) 235 { 236 if(res == RES_OK) res = RES_BAD_ARG; 237 logger_print(logger, LOG_ERROR, 238 "Invalid argument for option -%c: %s\n", 239 opt, optarg); 240 goto error; 241 } 242 break; 243 244 case '1': 245 args->single_thread = 1; 246 break; 247 } 248 } 249 250 if(argc > optind) { 251 int i; 252 for(i = optind; i < argc; i++) { 253 logger_print(logger, LOG_ERROR, "Unexpected argument: %s.\n", argv[i]); 254 } 255 res = RES_BAD_ARG; 256 goto error; 257 } 258 259 if(!c_provided && !info_provided) { 260 ERR(logger_print(logger, LOG_ERROR, 261 "Missing mandatory argument: -c <construction_mode_filename>\n")); 262 res = RES_BAD_ARG; 263 goto error; 264 } 265 266 if(!m_provided && !info_provided) { 267 ERR(logger_print(logger, LOG_ERROR, 268 "Missing mandatory argument: -m <city_filename>\n")); 269 res = RES_BAD_ARG; 270 goto error; 271 } 272 273 exit: 274 *out_args = args; 275 return res; 276 error: 277 release_args(args); 278 args = NULL; 279 goto exit; 280 } 281 282 void 283 release_args 284 (struct args* args) 285 { 286 if(!args) return; 287 288 darray_names_release(&args->catalog_files); 289 darray_names_release(&args->dump_footprint_names); 290 MEM_RM(args->allocator, args); 291 }