getopt_long()函数应该是最重要的解析函数。
main(int argc, char **argv)
{
923 longindex = -1;
924 int retconf;
925 bool use_userconfig = false;
926
927 while ((retconf = getopt_long (argc, argv,
928 short_options, long_options, &longindex)) != -1) 1、____-------> /lib/getoptl.c*/
929 {
930 int confval;
931 bool userrc_ret = true;
932 struct cmdline_option *config_opt;
933 confval = long_options[longindex].val; /*这里是控制数组大小在1024以内,因为1024以外的是错误的*/
934 config_opt = &option_data[confval & ~BOOLEAN_NEG_MARKER];
935 if (strcmp (config_opt->long_name, "config") == 0) /*看是否此长类型名已经注册*/
936 {
937 userrc_ret &= run_wgetrc (optarg); /*如果注册,那么就读刚刚到配置文件*/
938 use_userconfig = true; /*use_userconfig 表示可用*/
939 }
940 if (!userrc_ret)
941 {
942 printf ("Exiting due to error in %s\n", optarg);/*如果没有,那么就返回错误*/
943 exit (2);
944 }
945 else
946 break;
947 }
1、_____-------------->
39 int
40 getopt_long (int argc, char *__getopt_argv_const *argv, const char *optio ns,
41 const struct option *long_options, int *opt_index) /*+++++=====>/lib/getopt.in.h*/
42 {
43 return _getopt_internal (argc, (char **) argv, options, long_options,
44 opt_index, 0, 0);/*2、________---------->lib/getopt.c*/
45 }
+++++=========>
/* 如果独立的程序获得正确的getopt_long()和getopt_long_only()函数;声明char **argv。但是libc用char * const * argv这是不正确的,因为getopt_long()和getopt_long_only()可以改变argv的值*/
95 #if !defined __need_getopt /*这原来是#if defined __GETOPT_PREFIX && !defined __need_getopt,但是这会引起重定义警告,如果unistd.h和getopt.h被包含, 因为unistd.h包含了已经原来定义__need_getopt的getopt.h。*/
96 # if defined __GETOPT_PREFIX /*如果包含了getopt.h,那么就使用使用char **argv。
97 # define __getopt_argv_const /* empty */
98 # else /*如果没有包含,就定义为 char *const *argv*/
99 # define __getopt_argv_const const
100 # endif
101 #endif
2、_____________---------------->
1127 int
1128 _getopt_internal (int argc, char **argv, const char *optstring,
1129 const struct option *longopts, int *longind, int long_only,
1130 int posixly_correct)
1131 {
1132 int result;
1133
1134 getopt_data.optind = optind; /*初始化为 1。++++++++======>getopt_data[]数组 类型为*/
1135 getopt_data.opterr = opterr; /*初始化为1*/
1136
1137 result = _getopt_internal_r (argc, argv, optstring, longopts,
1138 longind, long_only, &getopt_data,
1139 posixly_correct); /*3、_______------->初始化getopt_data/
1140
1141 optind = getopt_data.optind; /*表示下一个选项字符的索引值*/
1142 optarg = getopt_data.optarg; /*下一个选项字符*/
1143 optopt = getopt_data.optopt; /*
1144
1145 return result;
1146 }
++++=============>
97 static struct _getopt_data getopt_data;
/*见前面*/
3、____________------------->
345 int
346 _getopt_internal_r (int argc, char **argv, const char *optstring,
347 const struct option *longopts, int *longind,
348 int long_only, struct _getopt_data *d, int posixly_correct)
349 {
350 int print_errors = d->opterr;
351
352 if (argc < 1) /*argc小于0是不可能的*/
353 return -1;
354
355 d->optarg = NULL; /*是否带有参数*/
356
357 if (d->optind == 0 || !d->__initialized) /*如果没有初始化,或者d->optind == 0*/
358 {
359 if (d->optind == 0)
360 d->optind = 1; /* Don't scan ARGV[0], the program name. */
361 optstring = _getopt_initialize (argc, argv, optstring, d,
362 posixly_correct); /*4、________-------->lib/getopt.c*/
363 d->__initialized = 1; /*已经初始化*/
364 }
365 else if (optstring[0] == '-' || optstring[0] == '+')
366 optstring++;
367 if (optstring[0] == ':') /*表示带有参数*/
368 print_errors = 0;
374 #if defined _LIBC && defined USE_NONOPTION_FLAGS 如果使用零选项标记 例子:su -
375 # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
376 || (d->optind < d->__nonoption_flags_len \
377 && __getopt_nonoption_flags[d->optind] == '1'))
378 #else
379 # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
380 #endif
381
382 if (d->__nextchar == NULL || *d->__nextchar == '\0') /*如果下一个选项字符为 NULL*/
388 if (d->__last_nonopt > d->optind) /*d->optind表示下一个选项字符的索引*/
389 d->__last_nonopt = d->optind;
390 if (d->__first_nonopt > d->optind)
391 d->__first_nonopt = d->optind;
392
393 if (d->__ordering == PERMUTE) /*如果是PERMUTE处理方法*/
394 {
395 /* If we have just processed some options following some non-options,
396 exchange them so that the options come first. */
397
398 if (d->__first_nonopt != d->__last_nonopt
399 && d->__last_nonopt != d->optind)
400 exchange ((char **) argv, d); /*交换空选项和非空选项的位置5、______----->*/
401 else if (d->__last_nonopt != d->optind)
402 d->__first_nonopt = d->optind; /*交换后,地址互换*/
403
404
405
406
407 while (d->optind < argc && NONOPTION_P) /*如果下个要取的索引小于参数总数和. . . . . . . .*/
408 d->optind++;
409 d->__last_nonopt = d->optind;
410 }
/*这里处理的就是长选项*/
417 if (d->optind != argc && !strcmp (argv[d->optind], "--"))
418 {
419 d->optind++;
420
421 if (d->__first_nonopt != d->__last_nonopt
422 && d->__last_nonopt != d->optind)
423 exchange ((char **) argv, d);
424 else if (d->__first_nonopt == d->__last_nonopt)
425 d->__first_nonopt = d->optind; /*如果两者相等说明没有空选项*/
426 d->__last_nonopt = argc;
427
428 d->optind = argc;
429 }
434 if (d->optind == argc)
435 {
436 /* Set the next-arg-index to point at the non-options
437 that we previously skipped, so the caller will digest them. */
438 if (d->__first_nonopt != d->__last_nonopt)
439 d->optind = d->__first_nonopt;
440 return -1;
441 }
442
443 /* If we have come to a non-option and did not permute it,
444 either stop the scan or describe it to the caller and pass it by. */
445
446 if (NONOPTION_P)
447 {
448 if (d->__ordering == REQUIRE_ORDER)
449 return -1;
450 d->optarg = argv[d->optind++];
451 return 1;
452 }
457 d->__nextchar = (argv[d->optind] + 1
458 + (longopts != NULL && argv[d->optind][1] == '-'));
459 }
476 if (longopts != NULL /*这句判断是为了检查是否为"--"开头,是长选项*/
477 && (argv[d->optind][1] == '-'
478 || (long_only && (argv[d->optind][2]
479 || !strchr (optstring, argv[d->optind][1])))))
480 {
481 char *nameend;
482 unsigned int namelen;
483 const struct option *p;
484 const struct option *pfound = NULL;
485 struct option_list
486 {
487 const struct option *p;
488 struct option_list *next;
489 } *ambig_list = NULL;
490 int exact = 0;
491 int indfound = -1;
492 int option_index;
493
494 for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
495 /* Do nothing. */ ;
496 namelen = nameend - d->__nextchar;
500 for (p = longopts, option_index = 0; p->name; p++, option_index++) /*整个测试,来检测到底是哪个长选项*/
501 if (!strncmp (p->name, d->__nextchar, namelen))
502 {
503 if (namelen == (unsigned int) strlen (p->name))
504 {
505 /* Exact match found. */
506 pfound = p; /*如果找到了,对应选项*/
507 indfound = option_index; /*索引项赋给给indfound*/
508 exact = 1;
509 break;
510 }
/*一般是查找第一次使用的*/
511 else if (pfound == NULL)
512 {
513 pfound = p;
515 indfound = option_index;
516 }在匹配长选项的条件下,如果参数不同的话就把它们链入链表中*/
517 else if (long_only
518 || pfound->has_arg != p->has_arg
519 || pfound->flag != p->flag
520 || pfound->val != p->val)
521 {
522 /* Second or later nonexact match found. */
523 struct option_list *newp = malloc (sizeof (*newp));
524 newp->p = p;
525 newp->next = ambig_list;
526 ambig_list = newp;
527 }
528 }
530 if (ambig_list != NULL && !exact)
531 {
532 if (print_errors)
533 {
534 struct option_list first;
535 first.p = pfound;
536 first.next = ambig_list;
537 ambig_list = &first;
539 #if defined _LIBC && defined USE_IN_LIBIO
540 char *buf = NULL;
541 size_t buflen = 0;
542
543 FILE *fp = open_memstream (&buf, &buflen);
}
4、_________________----------->
224 static const char *
225 _getopt_initialize (int argc _GL_UNUSED,
226 char **argv _GL_UNUSED, const char *optstring,
227 struct _getopt_data *d, int posixly_correct)
228 {
229
232
233 d->__first_nonopt = d->__last_nonopt = d->optind; /*初始化为1*/
234
235 d->__nextchar = NULL; /*下一个选项字符*/
236
237 d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); /*返回getenv()是返回环境的常量值*/
238
239
240
241 if (optstring[0] == '-')
242 {
243 d->__ordering = RETURN_IN_ORDER; /*根据开头的字符来判断检测选项类型的方法,见前面的分析*/
244 ++optstring;
245 }
246 else if (optstring[0] == '+')
247 {
248 d->__ordering = REQUIRE_ORDER;
249 ++optstring;
250 }
251 else if (d->__posixly_correct)
5、_________--------->
143 static void
144 exchange (char **argv, struct _getopt_data *d)
145 {
146 int bottom = d->__first_nonopt; /*第一个空选项索引*/
147 int middle = d->__last_nonopt; /*空选项后的第一个字符索引*/
148 int top = d->optind; /*下一次要去访问的字符选项的索引*/
149 char *tem;
160 if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
161 {
162 /* We must extend the array. 如果下一次要访问的索引大于整个大小,所以要拓展到top+1*/
163 presents new arguments. */
164 char *new_str = malloc (top + 1);
165 if (new_str == NULL)
166 d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
167 else
168 {
169 memset (__mempcpy (new_str, __getopt_nonoption_flags,
170 d->__nonoption_flags_max_len),
171 '\0', top + 1 - d->__nonoption_flags_max_len); /*__mempcpy()函数是memcpy()的类似函数,不同的是它返回指向最后一个元素\0的指针,然后初始化为\0*/
172 d->__nonoption_flags_max_len = top + 1;
173 __getopt_nonoption_flags = new_str; /*
174 }
175 }
176 #endif
177
178 while (top > middle && middle > bottom)
179 {
180 if (top - middle > middle - bottom)
181 {
182 /* Bottom segment is the short one. */
183 int len = middle - bottom; /*如果空选项所占字符小于非空选项大小,那么只移动空字符大小的那部分*/
184 register int i;
187 for (i = 0; i < len; i++)
188 {
189 tem = argv[bottom + i];
190 argv[bottom + i] = argv[top - (middle - bottom) + i];
191 argv[top - (middle - bottom) + i] = tem;
192 SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
193 }
194 /* Exclude the moved bottom segment from further swapping. */
195 top -= len; /*top空选项首位置*/
196 }
197 else
198 {
199 /* Top segment is the short one. */
200 int len = top - middle;
201 register int i;
202
203 /* Swap it with the bottom part of the bottom segment. */
204 for (i = 0; i < len; i++)
205 { /*典型的交换算法*/
206 tem = argv[bottom + i];
207 argv[bottom + i] = argv[middle + i];
208 argv[middle + i] = tem;
209 SWAP_FLAGS (bottom + i, middle + i);
210 }
212 bottom += len; /*空选项的开始所在索引*/
213 }
214 }
215
216 /* Update records for the slots the non-options now occupy. */
217
218 d->__first_nonopt += (d->optind - d->__last_nonopt); /*更新位置,*/
219 d->__last_nonopt = d->optind;
220 }
阅读(811) | 评论(0) | 转发(0) |