GRASS Programmer's Manual
6.4.1(2011)
|
00001 /* LIBDGL -- a Directed Graph Library implementation 00002 * Copyright (C) 2002 Roberto Micarelli 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 /* best view tabstop=4 00020 */ 00021 00022 #include <stdio.h> 00023 #include <stdlib.h> 00024 #include <string.h> 00025 00026 #include "opt.h" 00027 00028 static int _ParseLongOption(GnoOption_s * pOpt, char *pszArg) 00029 { 00030 char *pszLong; 00031 char *pszPar; 00032 char *pszMatch = NULL; 00033 int nret; 00034 00035 00036 if (pOpt->pszLong == NULL) { 00037 return 0; 00038 } 00039 00040 pszLong = strdup(pOpt->pszLong); 00041 00042 if ((pszPar = strchr(pszArg, '=')) != NULL) { 00043 *pszPar = 0; 00044 } 00045 pszMatch = strdup(pszArg); 00046 if (pszPar) 00047 *pszPar++ = '='; 00048 00049 if (strcmp(pszLong, pszMatch + 2) == 0) { 00050 00051 /* * mandatory parameter not found 00052 * */ 00053 if (pszPar == NULL) { 00054 nret = -1; 00055 goto free_and_exit; 00056 } 00057 00058 if (pOpt->ppszValue) { 00059 if (pOpt->ppszValue[0]) 00060 free(pOpt->ppszValue[0]); 00061 pOpt->ppszValue[0] = strdup(pszPar); 00062 } 00063 00064 nret = 1; 00065 goto free_and_exit; 00066 } 00067 00068 nret = 0; 00069 00070 free_and_exit: 00071 00072 free(pszLong); 00073 free(pszMatch); 00074 00075 return nret; 00076 } 00077 00078 static int _ParseLongSwitch(GnoOption_s * pOpt, char *pszArg) 00079 { 00080 00081 if (pOpt->pszLong == NULL) { 00082 return 0; 00083 } 00084 00085 if (strcmp(pOpt->pszLong, pszArg + 2) == 0) { 00086 if (pOpt->pfValue) 00087 *pOpt->pfValue = True; 00088 00089 return 1; 00090 } 00091 00092 return 0; 00093 } 00094 00095 00096 static int _ParseShortOption(GnoOption_s * pOpt, char *pszArg, char *pszPar) 00097 { 00098 char *pszShort; 00099 int ich; 00100 00101 if (pOpt->pszShort == NULL) 00102 return 0; 00103 00104 pszShort = strdup(pOpt->pszShort); 00105 00106 for (ich = 1; pszArg[ich]; ich++) { 00107 if (pszShort[0] == pszArg[ich]) { 00108 if (pszPar == NULL || pszPar[0] == 0) { 00109 free(pszShort); 00110 00111 return -1; 00112 } 00113 00114 if (pszPar[0] == '-' && pszPar[1] != 0) { 00115 free(pszShort); 00116 00117 return -1; 00118 } 00119 00120 if (pOpt->ppszValue) { 00121 if (pOpt->ppszValue[0]) 00122 free(pOpt->ppszValue[0]); 00123 pOpt->ppszValue[0] = strdup(pszPar); 00124 } 00125 00126 free(pszShort); 00127 00128 return 2; 00129 } 00130 } 00131 00132 free(pszShort); 00133 00134 return 0; 00135 } 00136 00137 static int _ParseShortSwitch(GnoOption_s * pOpt, char *pszArg) 00138 { 00139 int ich; 00140 00141 if (pOpt->pszShort == NULL) 00142 return 0; 00143 00144 for (ich = 1; pszArg[ich]; ich++) { 00145 if (pOpt->pszShort[0] == pszArg[ich]) { 00146 if (pOpt->pfValue) 00147 *pOpt->pfValue = True; 00148 00149 return 1; 00150 } 00151 } 00152 00153 return 0; 00154 } 00155 00156 /*********************************************************************** 00157 * CALLBACKS 00158 **********************************************************************/ 00159 00160 /*********************************************************************** 00161 * PUBLIC FUNCTIONS 00162 **********************************************************************/ 00163 00164 /*@*-------------------------------------------------------------------- 00165 * @func: GnoParse() 00166 * @descr: Parse argc, argv against the option array and setup option 00167 * values in the array. 00168 * 00169 * @args: I: argc = count of argv entries 00170 * I: argv -> array of pointer to string 00171 * I: pOpt -> option array pointer 00172 * 00173 * @ret: The number of 'orphan' entries found in the argv. 00174 * @see: GnoOption_s 00175 * 00176 * @notes: The argv array will be modified: each argv entry that contains a 00177 * recognized option ( '-.' or '--...' ) or each entry recognized as 00178 * a parametric option parameter, will be set to NULL. 00179 * Thus, at the function return the argv entries not set to NULL are 00180 * those of orphan entries (those not related to any option). 00181 * The user can then scan argv to find out orphans. 00182 * However the number of argv entries will not be altered. 00183 * 00184 *--------------------------------------------------------------------*/ 00185 00186 int GnoParse(int argc, char **argv, GnoOption_s * pOpt) 00187 { 00188 char *pszArgv; 00189 char *pszArgvNxt; 00190 int iArg, iOpt, cOrphan = 0; 00191 int nret, cret; 00192 Boolean fParseError = False; 00193 00194 /* * this first loop setup default values 00195 * * strdup is used for non-switch options 00196 * * to make life easier when freeing the field 00197 * */ 00198 for (iOpt = 0; pOpt[iOpt].pszShort || pOpt[iOpt].pszLong; iOpt++) { 00199 if (pOpt[iOpt].nFlg & GNO_FLG_SWITCH) { 00200 if (pOpt[iOpt].pfValue) { 00201 pOpt[iOpt].pfValue[0] = pOpt[iOpt].fDef; 00202 } 00203 } 00204 else { 00205 if (pOpt[iOpt].pszDef) { 00206 if (pOpt[iOpt].ppszValue) { 00207 pOpt[iOpt].ppszValue[0] = strdup(pOpt[iOpt].pszDef); 00208 } 00209 } 00210 else { 00211 if (pOpt[iOpt].ppszValue) { 00212 pOpt[iOpt].ppszValue[0] = NULL; 00213 } 00214 } 00215 } 00216 } 00217 00218 /* * for each arg in argv lookup the matching options 00219 * */ 00220 for (iArg = 0, pszArgv = NULL; 00221 iArg < argc && (pszArgv = strdup(argv[iArg])) != NULL; 00222 iArg++, free(pszArgv), pszArgv = NULL) { 00223 00224 if (pszArgv[0] == '-' && pszArgv[1] == '-' && pszArgv[2]) { /* long style */ 00225 for (iOpt = 0; 00226 (pOpt[iOpt].pszShort || pOpt[iOpt].pszLong) && argv[iArg]; 00227 iOpt++) { 00228 if (pOpt[iOpt].pszLong) { 00229 if (pOpt[iOpt].nFlg & GNO_FLG_SWITCH) { 00230 nret = _ParseLongSwitch(&pOpt[iOpt], pszArgv); 00231 } 00232 else { 00233 nret = _ParseLongOption(&pOpt[iOpt], pszArgv); 00234 } 00235 00236 if (nret < 0) { 00237 fprintf(stderr, 00238 "parse option: syntax error at <%s>\n", 00239 pszArgv); 00240 fParseError = True; 00241 } 00242 00243 if (nret == 1) { 00244 argv[iArg] = NULL; 00245 } 00246 } 00247 } 00248 00249 if (argv[iArg]) { 00250 fprintf(stderr, "parse option: <%s> is out of scope\n", 00251 pszArgv); 00252 fParseError = True; 00253 } 00254 } 00255 else if (argv[iArg][0] == '-' && argv[iArg][1]) { /* short style */ 00256 if (iArg + 1 < argc) { 00257 pszArgvNxt = strdup(argv[iArg + 1]); 00258 } 00259 else { 00260 pszArgvNxt = NULL; 00261 } 00262 00263 for (cret = iOpt = 0; 00264 pOpt[iOpt].pszShort || pOpt[iOpt].pszLong; iOpt++) { 00265 if (pOpt[iOpt].pszShort) { 00266 if (pOpt[iOpt].nFlg & GNO_FLG_SWITCH) { 00267 nret = _ParseShortSwitch(&pOpt[iOpt], pszArgv); 00268 } 00269 else { 00270 nret = 00271 _ParseShortOption(&pOpt[iOpt], pszArgv, 00272 pszArgvNxt); 00273 } 00274 if (nret < 0) { 00275 fprintf(stderr, 00276 "parse option: syntax error at <%s>\n", 00277 pszArgv); 00278 fParseError = True; 00279 } 00280 else { 00281 cret = (nret > cret) ? nret : cret; 00282 } 00283 } 00284 } 00285 00286 if (pszArgvNxt) { 00287 free(pszArgvNxt); 00288 } 00289 00290 if (cret == 1) { 00291 argv[iArg] = NULL; 00292 } 00293 else if (cret == 2) { 00294 argv[iArg++] = NULL; 00295 argv[iArg] = NULL; 00296 } 00297 00298 } 00299 else { 00300 cOrphan++; 00301 } 00302 } 00303 00304 if (pszArgv) 00305 free(pszArgv); 00306 00307 return (fParseError == True) ? -1 : cOrphan; 00308 } 00309 00310 00311 /*@*-------------------------------------------------------------------- 00312 * @func: GnoFree() 00313 * @descr: Free resource previously created with a call to GnoParse() 00314 * 00315 * @args: I: pOpt -> option array pointer 00316 * 00317 * @see: GnoOption_s, GnoParse() 00318 * 00319 *--------------------------------------------------------------------*/ 00320 void GnoFree(GnoOption_s * pOpt) 00321 { 00322 int iOpt; 00323 00324 for (iOpt = 0; pOpt[iOpt].pszShort || pOpt[iOpt].pszLong; iOpt++) { 00325 if (pOpt[iOpt].ppszValue) { 00326 if (pOpt[iOpt].ppszValue[0]) { 00327 free(pOpt[iOpt].ppszValue[0]); 00328 pOpt[iOpt].ppszValue[0] = NULL; 00329 } 00330 } 00331 } 00332 00333 } 00334 00335 /*@*-------------------------------------------------------------------- 00336 * @func: GnoHelp() 00337 * @descr: Print a brief option's help on the standard error 00338 * 00339 * @args: I: pszHead -> help header string 00340 * 00341 * @args: I: pOpt -> option array pointer 00342 * 00343 * @see: GnoOption_s 00344 * 00345 *--------------------------------------------------------------------*/ 00346 void GnoHelp(char *pszHead, GnoOption_s * pOpt) 00347 { 00348 int iOpt; 00349 00350 fprintf(stderr, "%s\n", (pszHead) ? pszHead : "options"); 00351 00352 for (iOpt = 0; pOpt[iOpt].pszShort || pOpt[iOpt].pszLong; iOpt++) { 00353 00354 if (pOpt[iOpt].nFlg & GNO_FLG_SWITCH) { 00355 if (pOpt[iOpt].pszShort) { 00356 fprintf(stderr, "-%s ", pOpt[iOpt].pszShort); 00357 } 00358 00359 if (pOpt[iOpt].pszLong) { 00360 fprintf(stderr, "--%s", pOpt[iOpt].pszLong); 00361 } 00362 00363 fprintf(stderr, "\n\t%s\n", (pOpt[iOpt].pszDescr) 00364 ? pOpt[iOpt].pszDescr : "No description available."); 00365 } 00366 else { 00367 if (pOpt[iOpt].pszShort) { 00368 fprintf(stderr, "-%s ", pOpt[iOpt].pszShort); 00369 00370 fprintf(stderr, "<value> "); 00371 } 00372 00373 if (pOpt[iOpt].pszLong) { 00374 fprintf(stderr, "--%s", pOpt[iOpt].pszLong); 00375 00376 fprintf(stderr, "=<value>"); 00377 } 00378 00379 fprintf(stderr, "\n\t%s\n", (pOpt[iOpt].pszDescr) 00380 ? pOpt[iOpt].pszDescr : "No description available."); 00381 } 00382 } 00383 00384 } 00385 00386 /******************************* END OF FILE **************************/