]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/tools/toolutil/uoptions.cpp
ICU-59117.0.1.tar.gz
[apple/icu.git] / icuSources / tools / toolutil / uoptions.cpp
diff --git a/icuSources/tools/toolutil/uoptions.cpp b/icuSources/tools/toolutil/uoptions.cpp
new file mode 100644 (file)
index 0000000..53a77bc
--- /dev/null
@@ -0,0 +1,133 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+*******************************************************************************
+*
+*   Copyright (C) 2000-2015, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+*******************************************************************************
+*   file name:  uoptions.c
+*   encoding:   UTF-8
+*   tab size:   8 (not used)
+*   indentation:4
+*
+*   created on: 2000apr17
+*   created by: Markus W. Scherer
+*
+*   This file provides a command line argument parser.
+*/
+
+#include "unicode/utypes.h"
+#include "cstring.h"
+#include "uoptions.h"
+
+U_CAPI int U_EXPORT2
+u_parseArgs(int argc, char* argv[],
+            int optionCount, UOption options[]) {
+    char *arg;
+    int i=1, remaining=1;
+    char c, stopOptions=0;
+
+    while(i<argc) {
+        arg=argv[i];
+        if(!stopOptions && *arg=='-' && (c=arg[1])!=0) {
+            /* process an option */
+            UOption *option=NULL;
+            arg+=2;
+            if(c=='-') {
+                /* process a long option */
+                if(*arg==0) {
+                    /* stop processing options after "--" */
+                    stopOptions=1;
+                } else {
+                    /* search for the option string */
+                    int j;
+                    for(j=0; j<optionCount; ++j) {
+                        if(options[j].longName && uprv_strcmp(arg, options[j].longName)==0) {
+                            option=options+j;
+                            break;
+                        }
+                    }
+                    if(option==NULL) {
+                        /* no option matches */
+                        return -i;
+                    }
+                    option->doesOccur=1;
+
+                    if(option->hasArg!=UOPT_NO_ARG) {
+                        /* parse the argument for the option, if any */
+                        if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
+                            /* argument in the next argv[], and there is not an option in there */
+                            option->value=argv[++i];
+                        } else if(option->hasArg==UOPT_REQUIRES_ARG) {
+                            /* there is no argument, but one is required: return with error */
+                            option->doesOccur=0;
+                            return -i;
+                        }
+                    }
+
+                    if(option->optionFn!=NULL && option->optionFn(option->context, option)<0) {
+                        /* the option function was called and returned an error */
+                        option->doesOccur=0;
+                        return -i;
+                    }
+                }
+            } else {
+                /* process one or more short options */
+                do {
+                    /* search for the option letter */
+                    int j;
+                    for(j=0; j<optionCount; ++j) {
+                        if(c==options[j].shortName) {
+                            option=options+j;
+                            break;
+                        }
+                    }
+                    if(option==NULL) {
+                        /* no option matches */
+                        return -i;
+                    }
+                    option->doesOccur=1;
+
+                    if(option->hasArg!=UOPT_NO_ARG) {
+                        /* parse the argument for the option, if any */
+                        if(*arg!=0) {
+                            /* argument following in the same argv[] */
+                            option->value=arg;
+                            /* do not process the rest of this arg as option letters */
+                            break;
+                        } else if(i+1<argc && !(argv[i+1][0]=='-' && argv[i+1][1]!=0)) {
+                            /* argument in the next argv[], and there is not an option in there */
+                            option->value=argv[++i];
+                            /* this break is redundant because we know that *arg==0 */
+                            break;
+                        } else if(option->hasArg==UOPT_REQUIRES_ARG) {
+                            /* there is no argument, but one is required: return with error */
+                            option->doesOccur=0;
+                            return -i;
+                        }
+                    }
+
+                    if(option->optionFn!=NULL && option->optionFn(option->context, option)<0) {
+                        /* the option function was called and returned an error */
+                        option->doesOccur=0;
+                        return -i;
+                    }
+
+                    /* get the next option letter */
+                    option=NULL;
+                    c=*arg++;
+                } while(c!=0);
+            }
+
+            /* go to next argv[] */
+            ++i;
+        } else {
+            /* move a non-option up in argv[] */
+            argv[remaining++]=arg;
+            ++i;
+        }
+    }
+    return remaining;
+}