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