sphor_main.c (5542B)
1 /* Copyright (C) 2024-2026 Centre National de la Recherche Scientifique 2 * Copyright (C) 2024-2026 Clermont Auvergne INP 3 * Copyright (C) 2024-2026 INSA Lyon 4 * Copyright (C) 2024-2026 Institut Mines Télécom Albi-Carmaux 5 * Copyright (C) 2024-2026 Institut National Polytechnique de Toulouse 6 * Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com) 7 * Copyright (C) 2024-2026 PhotonLyX (info@photonlyx.com) 8 * Copyright (C) 2024-2026 Université de Lorraine 9 * Copyright (C) 2024-2026 Université Paul Sabatier 10 * Copyright (C) 2024-2026 Université Toulouse - Jean Jaurès 11 * 12 * This program is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 24 25 #define _POSIX_C_SOURCE 200112L /* for getopt support */ 26 27 #include "sphor.h" 28 29 #include <rsys/cstr.h> 30 #include <rsys/mem_allocator.h> 31 #include <rsys/rsys.h> 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 37 struct args { 38 int verbose; /* Verbosity level. Bigger values => more verbosity */ 39 int quit; /* Either stop (1) or continue (0) the execution */ 40 unsigned nthreads; /* hint: number of threads; defaults to all available 41 threads in the computer */ 42 size_t samples; /* number of realisations used during the Monte Carlo 43 integrating algorithm */ 44 char* input_filename; /* May be NULL <=> uses stdin */ 45 char* output_filename; /* May be NULL <=> uses stdout */ 46 int force; /* Either force overwriting (1) or return an error (0) 47 if the output file already exists */ 48 }; 49 50 #define ARGS_DEFAULT__ {0, 0, UINT_MAX, 10000, NULL, NULL, 0} 51 52 static const struct args ARGS_DEFAULT = 53 ARGS_DEFAULT__; 54 55 static void 56 usage(FILE* stream) 57 { 58 ASSERT(NULL != stream); 59 fprintf(stream, 60 "Usage: star-phor [-hvf] [-n samples] [-o output] [-t threads] [file]\n"); 61 } 62 63 static res_T 64 parse_args 65 (struct args* args, 66 int argc, 67 char** argv) 68 { 69 unsigned long nreal; 70 unsigned int nthreads; 71 int opt = 0; 72 char* arglist = "hfn:o:t:v"; 73 res_T res = RES_OK; 74 75 ASSERT(NULL != args); 76 ASSERT(NULL != argv); 77 ASSERT(argc > 0); 78 79 *args = ARGS_DEFAULT; 80 81 while((opt = getopt(argc, argv, arglist)) != -1) { 82 switch(opt) { 83 case 'h': 84 usage(stdout); 85 args->quit = 1; 86 break; 87 /* Verbosity level */ 88 case 'v': 89 /* Increase the verbosity level counter for each 'v' entered, up to a 90 * maximum of 3. We use the boolean value of (3 > args->verbose): if 91 * the condition is true, it evaluates to 1, increasing the counter. 92 * Otherwise, it evaluates to 0, leaving the counter unchanged. */ 93 args->verbose += (3 > args->verbose); 94 break; 95 /* Output filename */ 96 case 'o': 97 args->output_filename = optarg; 98 break; 99 /* Force overwrite */ 100 case 'f': 101 args->force = 1; 102 break; 103 /* Number of samples */ 104 case 'n': 105 res = cstr_to_ulong(optarg, &nreal); 106 if (res == RES_OK && nreal == 0) res = RES_BAD_ARG; 107 args->samples = (size_t)nreal; 108 break; 109 /* Number of threads */ 110 case 't': 111 res = cstr_to_uint(optarg, &nthreads); 112 if (res == RES_OK && nthreads == 0) res = RES_BAD_ARG; 113 args->nthreads = nthreads; 114 break; 115 default: 116 res = RES_BAD_ARG; 117 break; 118 } 119 if (RES_OK != res) { 120 if (NULL != optarg) { 121 fprintf(stderr, "Invalid option argument: %s -- %c\n", optarg, opt); 122 } 123 goto error; 124 } 125 } 126 127 /* optind is a global variable that indexes the next argv to be processed */ 128 if (optind < argc) { /* True if not all the args have been processed */ 129 args->input_filename = argv[optind]; 130 } 131 132 exit: 133 return res; 134 error: 135 usage(stderr); 136 goto exit; 137 } 138 139 int 140 main (int argc, char** argv) 141 { 142 struct sphor* sphor = NULL; 143 struct args args = ARGS_DEFAULT; 144 struct sphor_create_args sphor_create_args = SPHOR_CREATE_ARGS_DEFAULT; 145 size_t sz = 0; 146 int err = EXIT_SUCCESS; 147 res_T res = RES_OK; 148 149 /* Process command line args */ 150 res = parse_args(&args, argc, argv); 151 if (RES_OK != res) { goto error; } 152 if (0 != args.quit) { goto exit; } 153 154 /* Create sphor struct */ 155 sphor_create_args.verbose = args.verbose; 156 sphor_create_args.samples = args.samples; 157 sphor_create_args.nthreads = args.nthreads; 158 sphor_create_args.force = args.force; 159 sphor_create_args.input_filename = args.input_filename; 160 sphor_create_args.output_filename = args.output_filename; 161 162 res = sphor_create(&sphor_create_args, &sphor); 163 if (RES_OK != res) { goto error; } 164 165 /* Run simulation */ 166 res = sphor_run(sphor); 167 if (RES_OK != res) { goto error; } 168 169 exit: 170 if (NULL != sphor) { SPHOR(ref_put(sphor)); } 171 sz = mem_allocated_size(); 172 if (sz != 0) { 173 char buffer[64] = {0}; /* Initialize all fields to 0 */ 174 size_to_cstr(sz, SIZE_ALL, NULL, buffer, sizeof(buffer)); 175 fprintf(stderr, "Memory leaks: %s\n", buffer); 176 err = EXIT_FAILURE; 177 } 178 return err; 179 error: 180 err = EXIT_FAILURE; 181 goto exit; 182 }