11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci*******************************************************************************
51cb0ef41Sopenharmony_ci*
61cb0ef41Sopenharmony_ci*   Copyright (C) 2000-2015, International Business Machines
71cb0ef41Sopenharmony_ci*   Corporation and others.  All Rights Reserved.
81cb0ef41Sopenharmony_ci*
91cb0ef41Sopenharmony_ci*******************************************************************************
101cb0ef41Sopenharmony_ci*   file name:  uoptions.c
111cb0ef41Sopenharmony_ci*   encoding:   UTF-8
121cb0ef41Sopenharmony_ci*   tab size:   8 (not used)
131cb0ef41Sopenharmony_ci*   indentation:4
141cb0ef41Sopenharmony_ci*
151cb0ef41Sopenharmony_ci*   created on: 2000apr17
161cb0ef41Sopenharmony_ci*   created by: Markus W. Scherer
171cb0ef41Sopenharmony_ci*
181cb0ef41Sopenharmony_ci*   This file provides a command line argument parser.
191cb0ef41Sopenharmony_ci*/
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci#include "unicode/utypes.h"
221cb0ef41Sopenharmony_ci#include "cstring.h"
231cb0ef41Sopenharmony_ci#include "uoptions.h"
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciU_CAPI int U_EXPORT2
261cb0ef41Sopenharmony_ciu_parseArgs(int argc, char* argv[],
271cb0ef41Sopenharmony_ci            int optionCount, UOption options[]) {
281cb0ef41Sopenharmony_ci    char *arg;
291cb0ef41Sopenharmony_ci    int i=1, remaining=1;
301cb0ef41Sopenharmony_ci    char c, stopOptions=0;
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci    while(i<argc) {
331cb0ef41Sopenharmony_ci        arg=argv[i];
341cb0ef41Sopenharmony_ci        if(!stopOptions && *arg=='-' && (c=arg[1])!=0) {
351cb0ef41Sopenharmony_ci            /* process an option */
361cb0ef41Sopenharmony_ci            UOption *option=nullptr;
371cb0ef41Sopenharmony_ci            arg+=2;
381cb0ef41Sopenharmony_ci            if(c=='-') {
391cb0ef41Sopenharmony_ci                /* process a long option */
401cb0ef41Sopenharmony_ci                if(*arg==0) {
411cb0ef41Sopenharmony_ci                    /* stop processing options after "--" */
421cb0ef41Sopenharmony_ci                    stopOptions=1;
431cb0ef41Sopenharmony_ci                } else {
441cb0ef41Sopenharmony_ci                    /* search for the option string */
451cb0ef41Sopenharmony_ci                    int j;
461cb0ef41Sopenharmony_ci                    for(j=0; j<optionCount; ++j) {
471cb0ef41Sopenharmony_ci                        if(options[j].longName && uprv_strcmp(arg, options[j].longName)==0) {
481cb0ef41Sopenharmony_ci                            option=options+j;
491cb0ef41Sopenharmony_ci                            break;
501cb0ef41Sopenharmony_ci                        }
511cb0ef41Sopenharmony_ci                    }
521cb0ef41Sopenharmony_ci                    if(option==nullptr) {
531cb0ef41Sopenharmony_ci                        /* no option matches */
541cb0ef41Sopenharmony_ci                        return -i;
551cb0ef41Sopenharmony_ci                    }
561cb0ef41Sopenharmony_ci                    option->doesOccur=1;
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci                    if(option->hasArg!=UOPT_NO_ARG) {
591cb0ef41Sopenharmony_ci                        /* parse the argument for the option, if any */
601cb0ef41Sopenharmony_ci                        if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
611cb0ef41Sopenharmony_ci                            /* argument in the next argv[], and there is not an option in there */
621cb0ef41Sopenharmony_ci                            option->value=argv[++i];
631cb0ef41Sopenharmony_ci                        } else if(option->hasArg==UOPT_REQUIRES_ARG) {
641cb0ef41Sopenharmony_ci                            /* there is no argument, but one is required: return with error */
651cb0ef41Sopenharmony_ci                            option->doesOccur=0;
661cb0ef41Sopenharmony_ci                            return -i;
671cb0ef41Sopenharmony_ci                        }
681cb0ef41Sopenharmony_ci                    }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci                    if(option->optionFn!=nullptr && option->optionFn(option->context, option)<0) {
711cb0ef41Sopenharmony_ci                        /* the option function was called and returned an error */
721cb0ef41Sopenharmony_ci                        option->doesOccur=0;
731cb0ef41Sopenharmony_ci                        return -i;
741cb0ef41Sopenharmony_ci                    }
751cb0ef41Sopenharmony_ci                }
761cb0ef41Sopenharmony_ci            } else {
771cb0ef41Sopenharmony_ci                /* process one or more short options */
781cb0ef41Sopenharmony_ci                do {
791cb0ef41Sopenharmony_ci                    /* search for the option letter */
801cb0ef41Sopenharmony_ci                    int j;
811cb0ef41Sopenharmony_ci                    for(j=0; j<optionCount; ++j) {
821cb0ef41Sopenharmony_ci                        if(c==options[j].shortName) {
831cb0ef41Sopenharmony_ci                            option=options+j;
841cb0ef41Sopenharmony_ci                            break;
851cb0ef41Sopenharmony_ci                        }
861cb0ef41Sopenharmony_ci                    }
871cb0ef41Sopenharmony_ci                    if(option==nullptr) {
881cb0ef41Sopenharmony_ci                        /* no option matches */
891cb0ef41Sopenharmony_ci                        return -i;
901cb0ef41Sopenharmony_ci                    }
911cb0ef41Sopenharmony_ci                    option->doesOccur=1;
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci                    if(option->hasArg!=UOPT_NO_ARG) {
941cb0ef41Sopenharmony_ci                        /* parse the argument for the option, if any */
951cb0ef41Sopenharmony_ci                        if(*arg!=0) {
961cb0ef41Sopenharmony_ci                            /* argument following in the same argv[] */
971cb0ef41Sopenharmony_ci                            option->value=arg;
981cb0ef41Sopenharmony_ci                            /* do not process the rest of this arg as option letters */
991cb0ef41Sopenharmony_ci                            break;
1001cb0ef41Sopenharmony_ci                        } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
1011cb0ef41Sopenharmony_ci                            /* argument in the next argv[], and there is not an option in there */
1021cb0ef41Sopenharmony_ci                            option->value=argv[++i];
1031cb0ef41Sopenharmony_ci                            /* this break is redundant because we know that *arg==0 */
1041cb0ef41Sopenharmony_ci                            break;
1051cb0ef41Sopenharmony_ci                        } else if(option->hasArg==UOPT_REQUIRES_ARG) {
1061cb0ef41Sopenharmony_ci                            /* there is no argument, but one is required: return with error */
1071cb0ef41Sopenharmony_ci                            option->doesOccur=0;
1081cb0ef41Sopenharmony_ci                            return -i;
1091cb0ef41Sopenharmony_ci                        }
1101cb0ef41Sopenharmony_ci                    }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci                    if(option->optionFn!=nullptr && option->optionFn(option->context, option)<0) {
1131cb0ef41Sopenharmony_ci                        /* the option function was called and returned an error */
1141cb0ef41Sopenharmony_ci                        option->doesOccur=0;
1151cb0ef41Sopenharmony_ci                        return -i;
1161cb0ef41Sopenharmony_ci                    }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci                    /* get the next option letter */
1191cb0ef41Sopenharmony_ci                    option=nullptr;
1201cb0ef41Sopenharmony_ci                    c=*arg++;
1211cb0ef41Sopenharmony_ci                } while(c!=0);
1221cb0ef41Sopenharmony_ci            }
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci            /* go to next argv[] */
1251cb0ef41Sopenharmony_ci            ++i;
1261cb0ef41Sopenharmony_ci        } else {
1271cb0ef41Sopenharmony_ci            /* move a non-option up in argv[] */
1281cb0ef41Sopenharmony_ci            argv[remaining++]=arg;
1291cb0ef41Sopenharmony_ci            ++i;
1301cb0ef41Sopenharmony_ci        }
1311cb0ef41Sopenharmony_ci    }
1321cb0ef41Sopenharmony_ci    return remaining;
1331cb0ef41Sopenharmony_ci}
134