Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
last change of Tesh2
[simgrid.git] / tools / tesh2 / w32 / src / getopt.c
1 #include <stdio.h>\r
2 #include <string.h>\r
3 \r
4 #include <getopt.h>\r
5 \r
6 char* \r
7 optarg = NULL;\r
8 \r
9 int \r
10 optind = 0;\r
11 \r
12 int \r
13 optopt = '?';\r
14 \r
15 int \r
16 opterr = 1;\r
17 \r
18 static char*\r
19 nextchar;\r
20 \r
21 static \r
22 int first_nonopt;\r
23 \r
24 static int \r
25 last_nonopt;\r
26 \r
27 \r
28 static enum\r
29 {\r
30         REQUIRE_ORDER, \r
31         PERMUTE, \r
32         RETURN_IN_ORDER\r
33 }ordering;\r
34 \r
35 \r
36 static const char *\r
37 __getopt_initialize (const char *optstring);\r
38 \r
39 static int\r
40 __getopt_internal (int argc, char *const *argv, const char* optstring, const struct option *longopts, int* longind, int long_only);\r
41 \r
42 static void\r
43 __exchange (char **argv);\r
44 \r
45 int \r
46 getopt (int argc, char * const argv[], const char *optstring)\r
47 {\r
48         return __getopt_internal(argc, argv, optstring,(const struct option *) 0,(int *) 0,0);\r
49 }\r
50 \r
51 static const char *\r
52 __getopt_initialize (const char *optstring)\r
53 {\r
54         /* Start processing options with ARGV-element 1 (since ARGV-element 0\r
55         is the program name); the sequence of previously skipped\r
56         non-option ARGV-elements is empty.  */\r
57         \r
58         first_nonopt = last_nonopt = optind = 1;\r
59         nextchar = NULL;\r
60         \r
61         /* Determine how to handle the ordering of options and nonoptions.  */\r
62         \r
63         if (optstring[0] == '-')\r
64         {\r
65                 ordering = RETURN_IN_ORDER;\r
66                 ++optstring;\r
67         }\r
68         /* si la chaîne d'options commence par un + alors la fonction getopt() s'arrête\r
69          * dès qu'un argument de la ligne de commande n'est pas une option\r
70          */\r
71         else if (optstring[0] == '+')\r
72         {\r
73                 ordering = REQUIRE_ORDER;\r
74                 ++optstring;\r
75         }\r
76         else\r
77         {\r
78                 ordering = PERMUTE;\r
79         }\r
80         \r
81         return optstring;\r
82 }\r
83 \r
84 int\r
85 __getopt_internal (int argc, char *const *argv, const char* optstring, const struct option *longopts, int* longind, int long_only)\r
86 {\r
87         optarg = NULL;\r
88         \r
89         if (optind == 0)\r
90                 optstring = __getopt_initialize (optstring);\r
91         \r
92         if (nextchar == NULL || *nextchar == '\0')\r
93         {\r
94                 /* Advance to the next ARGV-element.  */\r
95         \r
96                 if (ordering == PERMUTE)\r
97                 {\r
98                         /* If we have just processed some options following some non-options,\r
99                         __exchange them so that the options come first.  */\r
100         \r
101                         if (first_nonopt != last_nonopt && last_nonopt != optind)\r
102                                 __exchange ((char **) argv);\r
103                         else if (last_nonopt != optind)\r
104                                 first_nonopt = optind;\r
105         \r
106                         /* Skip any additional non-options\r
107                         and extend the range of non-options previously skipped.  */\r
108         \r
109                         while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0'))\r
110                                 optind++;\r
111                         \r
112                         last_nonopt = optind;\r
113                 }\r
114         \r
115                 /* The special ARGV-element `--' means premature end of options.\r
116                 Skip it like a null option,\r
117                 then __exchange with previous non-options as if it were an option,\r
118                 then skip everything else like a non-option.  */\r
119         \r
120                 if (optind != argc && !strcmp (argv[optind], "--"))\r
121                 {\r
122                         optind++;\r
123         \r
124                         if (first_nonopt != last_nonopt && last_nonopt != optind)\r
125                                 __exchange ((char **) argv);\r
126                         else if (first_nonopt == last_nonopt)\r
127                                 first_nonopt = optind;\r
128                         \r
129                         last_nonopt = argc;\r
130         \r
131                         optind = argc;\r
132                 }\r
133         \r
134                 /* If we have done all the ARGV-elements, stop the scan\r
135                 and back over any non-options that we skipped and permuted.  */\r
136         \r
137                 if (optind == argc)\r
138                 {\r
139                         /* Set the next-arg-index to point at the non-options\r
140                         that we previously skipped, so the caller will digest them.  */\r
141                         if (first_nonopt != last_nonopt)\r
142                                 optind = first_nonopt;\r
143                         \r
144                         return EOF;\r
145                 }\r
146         \r
147                 /* If we have come to a non-option and did not permute it,\r
148                 either stop the scan or describe it to the caller and pass it by.  */\r
149         \r
150                 if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))\r
151                 {\r
152                         if (ordering == REQUIRE_ORDER)\r
153                                 return EOF;\r
154                         optarg = argv[optind++];\r
155                                 return 1;\r
156                 }\r
157         \r
158                 /* We have found another option-ARGV-element.\r
159                 Skip the initial punctuation.  */\r
160         \r
161                 nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-'));\r
162         }\r
163         \r
164         /* Decode the current option-ARGV-element.  */\r
165         \r
166         /* Check whether the ARGV-element is a long option.\r
167         \r
168         If long_only and the ARGV-element has the form "-f", where f is\r
169         a valid short option, don't consider it an abbreviated form of\r
170         a long option that starts with f.  Otherwise there would be no\r
171         way to give the -f short option.\r
172         \r
173         On the other hand, if there's a long option "fubar" and\r
174         the ARGV-element is "-fu", do consider that an abbreviation of\r
175         the long option, just like "--fu", and not "-f" with arg "u".\r
176         \r
177         This distinction seems to be the most useful approach.  */\r
178         \r
179         if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !strchr (optstring, argv[optind][1])))))\r
180         {\r
181                 char *nameend;\r
182                 const struct option *p;\r
183                 const struct option *pfound = NULL;\r
184                 int exact = 0;\r
185                 int ambig = 0;\r
186                 int indfound = 0;\r
187                 int option_index;\r
188         \r
189                 for (nameend = nextchar; *nameend !='\0' && *nameend != '='; nameend++)\r
190                         /* Do nothing.  */ ;\r
191         \r
192                 /* Test all long options for either exact match\r
193                 or abbreviated matches.  */\r
194                 for (p = longopts, option_index = 0; p->name; p++, option_index++)\r
195                 {\r
196                         if(!strncmp (p->name, nextchar, nameend - nextchar))\r
197                         {\r
198 \r
199                                 if (nameend - nextchar == strlen (p->name))\r
200                                 {\r
201                                         /* Exact match found.  */\r
202                                         pfound = p;\r
203                                         indfound = option_index;\r
204                                         exact = 1;\r
205                                         break;\r
206                                 }\r
207                                 else if (pfound == NULL)\r
208                                 {\r
209                                         /* First nonexact match found.  */\r
210                                         exact = 0;\r
211                                         /* begin change\r
212                                         pfound = p;\r
213                                         indfound = option_index;\r
214                                         end change */\r
215                                         break;\r
216                                 }\r
217                                 else\r
218                                 {\r
219 \r
220                                         /* Second or later nonexact match found.  */\r
221                                         ambig = 1;\r
222                                 }\r
223                         }\r
224                 }\r
225         \r
226                 if (ambig && !exact)\r
227                 {\r
228                         if (opterr)\r
229                                 fprintf (stderr, "error   : %s: option `%s' is ambiguous\n",argv[0], argv[optind]);\r
230                         \r
231                         nextchar += strlen (nextchar);\r
232                         optind++;\r
233                         return '?';\r
234                 }\r
235         \r
236                 if (pfound != NULL)\r
237                 {\r
238                         option_index = indfound;\r
239                         optind++;\r
240                         \r
241                         if (*nameend)\r
242                         {\r
243                                 /* Don't test has_arg with >, because some C compilers don't\r
244                                 allow it to be used on enums.  */\r
245                                 if (pfound->has_arg)\r
246                                         optarg = nameend + 1;\r
247                                 else\r
248                                 {\r
249                                         if (opterr)\r
250                                         {\r
251                                                 if (argv[optind - 1][1] == '-')\r
252                                                         /* --option */\r
253                                                         fprintf (stderr,"error   : %s: option `--%s' doesn't allow an argument\n",argv[0], pfound->name);\r
254                                                 else\r
255                                                         /* +option or -option */\r
256                                                         fprintf (stderr,"error   : %s: option `%c%s' doesn't allow an argument\n",argv[0], argv[optind - 1][0], pfound->name);\r
257                                         }\r
258                                         \r
259                                         nextchar += strlen (nextchar);\r
260                                         return '?';\r
261                                 }\r
262                         }\r
263                         else if (pfound->has_arg == 1)\r
264                         {\r
265                                 if (optind < argc)\r
266                                         optarg = argv[optind++];\r
267                                 else\r
268                                 {\r
269                                         if (opterr)\r
270                                                 fprintf (stderr, "error   : %s: option `%s' requires an argument\n",argv[0], argv[optind - 1]);\r
271                                         \r
272                                         nextchar += strlen (nextchar);\r
273                                         return optstring[0] == ':' ? ':' : '?';\r
274                                 }\r
275                         }\r
276                         \r
277                         nextchar += strlen (nextchar);\r
278                         \r
279                         if (longind != NULL)\r
280                                 *longind = option_index;\r
281                         \r
282                         if (pfound->flag)\r
283                         {\r
284                                 *(pfound->flag) = pfound->val;\r
285                                 return 0;\r
286                         }\r
287                         \r
288                         return pfound->val;\r
289                 }\r
290         \r
291                 /* Can't find it as a long option.  If this is not getopt_long_only,\r
292                 or the option starts with '--' or is not a valid short\r
293                 option, then it's an error.\r
294                 Otherwise interpret it as a short option.  */\r
295                 if (!long_only || argv[optind][1] == '-'|| strchr (optstring, *nextchar) == NULL)\r
296                 {\r
297                         if (opterr)\r
298                         {\r
299                                 if (argv[optind][1] == '-')\r
300                                         /* --option */\r
301                                         fprintf (stderr, "error   : %s: unrecognized option `--%s'\n",argv[0], nextchar);\r
302                                 else\r
303                                         /* +option or -option */\r
304                                         fprintf (stderr, "error   : %s: unrecognized option `%c%s'\n",argv[0], argv[optind][0], nextchar);\r
305                         }\r
306                         \r
307                         nextchar = (char *) "";\r
308                         optind++;\r
309                         return '?';\r
310                 }\r
311         }\r
312         \r
313         /* Look at and handle the next short option-character.  */\r
314         \r
315         {\r
316                 char c = *nextchar++;\r
317                 char *temp = strchr (optstring, c);\r
318         \r
319                 /* Increment `optind' when we start to process its last character.  */\r
320                 if (*nextchar == '\0')\r
321                         ++optind;\r
322         \r
323                 if (temp == NULL || c == ':')\r
324                 {\r
325                         if (opterr)\r
326                                         fprintf (stderr, "error   : %s: invalid option -- %c\n", argv[0], c);\r
327                         \r
328                         optopt = c;\r
329                         return '?';\r
330                 }\r
331                 \r
332                 if (temp[1] == ':')\r
333                 {\r
334                         if (temp[2] == ':')\r
335                         {\r
336                                 /* This is an option that accepts an argument optionally.  */\r
337                                 if (*nextchar != '\0')\r
338                                 {\r
339                                         optarg = nextchar;\r
340                                         optind++;\r
341                                 }\r
342                                 else\r
343                                         optarg = NULL;\r
344                                 \r
345                                 nextchar = NULL;\r
346                         }\r
347                         else\r
348                         {\r
349                                 /* This is an option that requires an argument.  */\r
350                                 if (*nextchar != '\0')\r
351                                 {\r
352                                         optarg = nextchar;\r
353                                         /* If we end this ARGV-element by taking the rest as an arg,\r
354                                         we must advance to the next element now.  */\r
355                                         optind++;\r
356                                 }\r
357                                 else if (optind == argc)\r
358                                 {\r
359                                         if (opterr)\r
360                                         {\r
361                                                 /* 1003.2 specifies the format of this message.  */\r
362                                                 fprintf (stderr, "error   : %s: option requires an argument -- %c\n",argv[0], c);\r
363                                         }\r
364                                         optopt = c;\r
365                                         \r
366                                         if (optstring[0] == ':')\r
367                                                 c = ':';\r
368                                         else\r
369                                                 c = '?';\r
370                                 }\r
371                                 else\r
372                                         /* We already incremented `optind' once;\r
373                                         increment it again when taking next ARGV-elt as argument.  */\r
374                                         optarg = argv[optind++];\r
375                                 \r
376                                 nextchar = NULL;\r
377                         }\r
378                 }\r
379         return c;\r
380         \r
381         }\r
382 }\r
383 \r
384 \r
385 static void\r
386 __exchange (char **argv)\r
387 {\r
388         int bottom = first_nonopt;\r
389         int middle = last_nonopt;\r
390         int top = optind;\r
391         char *tem;\r
392         \r
393         /* Exchange the shorter segment with the far end of the longer segment.\r
394         That puts the shorter segment into the right place.\r
395         It leaves the longer segment in the right place overall,\r
396         but it consists of two parts that need to be swapped next.  */\r
397         \r
398         while (top > middle && middle > bottom)\r
399         {\r
400                 if (top - middle > middle - bottom)\r
401                 {\r
402                         /* Bottom segment is the short one.  */\r
403                         int len = middle - bottom;\r
404                         register int i;\r
405         \r
406                         /* Swap it with the top part of the top segment.  */\r
407                         for (i = 0; i < len; i++)\r
408                         {\r
409                                 tem = argv[bottom + i];\r
410                                 argv[bottom + i] = argv[top - (middle - bottom) + i];\r
411                                 argv[top - (middle - bottom) + i] = tem;\r
412                         }\r
413                         /* Exclude the moved bottom segment from further swapping.  */\r
414                         \r
415                         top -= len;\r
416                 }\r
417                 else\r
418                 {\r
419                         /* Top segment is the short one.  */\r
420                         int len = top - middle;\r
421                         register int i;\r
422                 \r
423                         /* Swap it with the bottom part of the bottom segment.  */\r
424                         for (i = 0; i < len; i++)\r
425                         {\r
426                                 tem = argv[bottom + i];\r
427                                 argv[bottom + i] = argv[middle + i];\r
428                                 argv[middle + i] = tem;\r
429                         }\r
430                         /* Exclude the moved top segment from further swapping.  */\r
431                         bottom += len;\r
432                 }\r
433         }\r
434         \r
435         /* Update records for the slots the non-options now occupy.  */\r
436         \r
437         first_nonopt += (optind - last_nonopt);\r
438         last_nonopt = optind;\r
439 }\r
440 \r
441 int\r
442 getopt_long (int argc, char *const *argv, const char *options, const struct option *long_options, int *opt_index)\r
443 {\r
444         return __getopt_internal (argc, argv, options, long_options, opt_index, 0);\r
445 }\r
446 \r
447 \r
448 int\r
449 getopt_long_only(int argc, char *const *argv, const char *options, const struct option *long_options,int *opt_index)\r
450 {\r
451         return __getopt_internal (argc, argv, options, long_options, opt_index, 1);\r
452 }\r
453 \r
454 \r