Home | History | Annotate | Download | only in toolutil
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 2000, International Business Machines
      5 *   Corporation and others.  All Rights Reserved.
      6 *
      7 *******************************************************************************
      8 *   file name:  uoptions.c
      9 *   encoding:   US-ASCII
     10 *   tab size:   8 (not used)
     11 *   indentation:4
     12 *
     13 *   created on: 2000apr17
     14 *   created by: Markus W. Scherer
     15 *
     16 *   This file provides a command line argument parser.
     17 */
     18 
     19 #include "unicode/utypes.h"
     20 #include "cstring.h"
     21 #include "uoptions.h"
     22 
     23 U_CAPI int U_EXPORT2
     24 u_parseArgs(int argc, char* argv[],
     25             int optionCount, UOption options[]) {
     26     char *arg;
     27     int i=1, remaining=1;
     28     char c, stopOptions=0;
     29 
     30     while(i<argc) {
     31         arg=argv[i];
     32         if(!stopOptions && *arg=='-' && (c=arg[1])!=0) {
     33             /* process an option */
     34             UOption *option=NULL;
     35             arg+=2;
     36             if(c=='-') {
     37                 /* process a long option */
     38                 if(*arg==0) {
     39                     /* stop processing options after "--" */
     40                     stopOptions=1;
     41                 } else {
     42                     /* search for the option string */
     43                     int j;
     44                     for(j=0; j<optionCount; ++j) {
     45                         if(options[j].longName && uprv_strcmp(arg, options[j].longName)==0) {
     46                             option=options+j;
     47                             break;
     48                         }
     49                     }
     50                     if(option==NULL) {
     51                         /* no option matches */
     52                         return -i;
     53                     }
     54                     option->doesOccur=1;
     55 
     56                     if(option->hasArg!=UOPT_NO_ARG) {
     57                         /* parse the argument for the option, if any */
     58                         if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
     59                             /* argument in the next argv[], and there is not an option in there */
     60                             option->value=argv[++i];
     61                         } else if(option->hasArg==UOPT_REQUIRES_ARG) {
     62                             /* there is no argument, but one is required: return with error */
     63                             return -i;
     64                         }
     65                     }
     66                 }
     67             } else {
     68                 /* process one or more short options */
     69                 do {
     70                     /* search for the option letter */
     71                     int j;
     72                     for(j=0; j<optionCount; ++j) {
     73                         if(c==options[j].shortName) {
     74                             option=options+j;
     75                             break;
     76                         }
     77                     }
     78                     if(option==NULL) {
     79                         /* no option matches */
     80                         return -i;
     81                     }
     82                     option->doesOccur=1;
     83 
     84                     if(option->hasArg!=UOPT_NO_ARG) {
     85                         /* parse the argument for the option, if any */
     86                         if(*arg!=0) {
     87                             /* argument following in the same argv[] */
     88                             option->value=arg;
     89                             /* do not process the rest of this arg as option letters */
     90                             break;
     91                         } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
     92                             /* argument in the next argv[], and there is not an option in there */
     93                             option->value=argv[++i];
     94                             /* this break is redundant because we know that *arg==0 */
     95                             break;
     96                         } else if(option->hasArg==UOPT_REQUIRES_ARG) {
     97                             /* there is no argument, but one is required: return with error */
     98                             return -i;
     99                         }
    100                     }
    101 
    102                     /* get the next option letter */
    103                     option=NULL;
    104                     c=*arg++;
    105                 } while(c!=0);
    106             }
    107 
    108             if(option!=0 && option->optionFn!=0 && option->optionFn(option->context, option)<0) {
    109                 /* the option function was called and returned an error */
    110                 return -i;
    111             }
    112 
    113             /* go to next argv[] */
    114             ++i;
    115         } else {
    116             /* move a non-option up in argv[] */
    117             argv[remaining++]=arg;
    118             ++i;
    119         }
    120     }
    121     return remaining;
    122 }
    123