Chinaunix首页 | 论坛 | 博客

分类: LINUX

2011-10-06 16:54:49

    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 }

阅读(767) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~