gwenhywfar 4.0.3

args.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id$
00005     begin       : Sat Apr 24 2004
00006     copyright   : (C) 2004 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU Lesser General Public            *
00013  *   License as published by the Free Software Foundation; either          *
00014  *   version 2.1 of the License, or (at your option) any later version.    *
00015  *                                                                         *
00016  *   This library is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00019  *   Lesser General Public License for more details.                       *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU Lesser General Public      *
00022  *   License along with this library; if not, write to the Free Software   *
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00024  *   MA  02111-1307  USA                                                   *
00025  *                                                                         *
00026  ***************************************************************************/
00027 
00028 
00029 #ifdef HAVE_CONFIG_H
00030 # include <config.h>
00031 #endif
00032 
00033 #include "args_p.h"
00034 #include <gwenhywfar/misc.h>
00035 #include <gwenhywfar/debug.h>
00036 #include <gwenhywfar/text.h>
00037 #include <string.h>
00038 
00039 #define DISABLE_DEBUGLOG
00040 
00041 
00042 
00043 
00044 int GWEN_Args_Check(int argc, char **argv,
00045                     int startAt,
00046                     uint32_t mode,
00047                     const GWEN_ARGS *args,
00048                     GWEN_DB_NODE *db){
00049   int i;
00050   const char *p;
00051   const GWEN_ARGS *tmpArgs;
00052   GWEN_DB_NODE *counts;
00053   int stop;
00054 
00055   i=startAt;
00056 
00057   counts=GWEN_DB_Group_new("counts");
00058 
00059   stop=0;
00060   while(i<argc && !stop) {
00061     GWEN_ARGS_ELEMENT_TYPE t;
00062     char *tmpBuf;
00063     const char *v;
00064     int value;
00065 
00066     DBG_INFO(GWEN_LOGDOMAIN, "Argument[%d] is \"%s\"", i, argv[i]);
00067     p=argv[i];
00068     if (*p=='-') {
00069       p++;
00070       if (*p=='-') {
00071         p++;
00072         t=GWEN_ArgsElementTypeLong;
00073       }
00074       else
00075         t=GWEN_ArgsElementTypeShort;
00076     }
00077     else
00078       t=GWEN_ArgsElementTypeFreeParam;
00079 
00080     switch(t) {
00081     case GWEN_ArgsElementTypeFreeParam:
00082       if (mode & GWEN_ARGS_MODE_ALLOW_FREEPARAM) {
00083         GWEN_DB_SetCharValue(db,
00084                              GWEN_DB_FLAGS_DEFAULT,
00085                              "params", p);
00086         i++;
00087       }
00088       else {
00089         DBG_ERROR(GWEN_LOGDOMAIN, "Only options are allowed, but argument \"%s\" was not recognized as a known option.", p);
00090         GWEN_DB_Group_free(counts);
00091         return GWEN_ARGS_RESULT_ERROR;
00092       }
00093       if (mode & GWEN_ARGS_MODE_STOP_AT_FREEPARAM) {
00094         DBG_DEBUG(GWEN_LOGDOMAIN, "Free parameter found, stopping as requested");
00095         stop=1;
00096       }
00097       break;
00098 
00099     case GWEN_ArgsElementTypeShort:
00100       for(tmpArgs=args;;tmpArgs++) {
00101         if (tmpArgs->shortOption) {
00102           if (strcmp(tmpArgs->shortOption, p)==0) {
00103             /* found option */
00104             GWEN_DB_SetIntValue(counts, GWEN_DB_FLAGS_OVERWRITE_VARS,
00105                                 tmpArgs->name,
00106                                 GWEN_DB_GetIntValue(counts,
00107                                                     tmpArgs->name, 0, 0)+1);
00108             break;
00109           }
00110         } /* if shortOption */
00111 
00112         if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
00113           DBG_ERROR(GWEN_LOGDOMAIN, "Unknown short option \"%s\"", p);
00114           GWEN_DB_Group_free(counts);
00115           return GWEN_ARGS_RESULT_ERROR;
00116         }
00117       } /* for */
00118       i++;
00119 
00120       if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
00121         /* argument needed */
00122         if (i>=argc) {
00123           DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
00124           GWEN_DB_Group_free(counts);
00125           return GWEN_ARGS_RESULT_ERROR;
00126         }
00127         switch(tmpArgs->type) {
00128         case GWEN_ArgsType_Char:
00129           GWEN_DB_SetCharValue(db,
00130                                GWEN_DB_FLAGS_DEFAULT,
00131                                tmpArgs->name, argv[i]);
00132           break;
00133 
00134         case GWEN_ArgsType_Int:
00135           if (sscanf(argv[i], "%i", &value)!=1) {
00136             DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for short option \"%s\"", p);
00137             GWEN_DB_Group_free(counts);
00138             return GWEN_ARGS_RESULT_ERROR;
00139           }
00140           GWEN_DB_SetIntValue(db,
00141                               GWEN_DB_FLAGS_DEFAULT,
00142                               tmpArgs->name, value);
00143           break;
00144 
00145         default:
00146           DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"",
00147                     tmpArgs->type);
00148           GWEN_DB_Group_free(counts);
00149           return GWEN_ARGS_RESULT_ERROR;
00150         } /* switch */
00151         i++;
00152       }
00153       else {
00154         if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
00155           GWEN_DB_Group_free(counts);
00156           return GWEN_ARGS_RESULT_HELP;
00157         }
00158         GWEN_DB_SetIntValue(db,
00159                             GWEN_DB_FLAGS_OVERWRITE_VARS,
00160                             tmpArgs->name,
00161                             GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
00162       }
00163       break;
00164 
00165     case GWEN_ArgsElementTypeLong:
00166       /* copy option name up to (but excluding) the "=" if any,
00167        * determine the start of possible argument */
00168       v=p;
00169       while(*v && *v!='=') v++;
00170       tmpBuf=(char*)malloc(v-p+1);
00171       assert(tmpBuf);
00172       memmove(tmpBuf, p, v-p);
00173       tmpBuf[v-p]=0;
00174 
00175       for(tmpArgs=args;;tmpArgs++) {
00176         if (tmpArgs->longOption) {
00177           if (strcmp(tmpArgs->longOption, tmpBuf)==0) {
00178             /* found option */
00179             GWEN_DB_SetIntValue(counts, GWEN_DB_FLAGS_OVERWRITE_VARS,
00180                                 tmpArgs->name,
00181                                 GWEN_DB_GetIntValue(counts,
00182                                                     tmpArgs->name, 0, 0)+1);
00183             break;
00184           }
00185         } /* if longOption */
00186 
00187         if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) {
00188           DBG_ERROR(GWEN_LOGDOMAIN, "Unknown long option \"%s\"", tmpBuf);
00189           free(tmpBuf);
00190           GWEN_DB_Group_free(counts);
00191           return GWEN_ARGS_RESULT_ERROR;
00192         }
00193       } /* for */
00194       i++;
00195 
00196       if (*v=='=') {
00197         if (!(tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)) {
00198           DBG_ERROR(GWEN_LOGDOMAIN, "No argument allowed for option \"%s\"",
00199                     tmpArgs->name);
00200           free(tmpBuf);
00201           GWEN_DB_Group_free(counts);
00202           return GWEN_ARGS_RESULT_ERROR;
00203         }
00204         v++;
00205       }
00206 
00207       if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
00208         /* argument needed */
00209         if (*v==0) {
00210           DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name);
00211           free(tmpBuf);
00212           GWEN_DB_Group_free(counts);
00213           return GWEN_ARGS_RESULT_ERROR;
00214         }
00215         switch(tmpArgs->type) {
00216         case GWEN_ArgsType_Char:
00217           GWEN_DB_SetCharValue(db,
00218                                GWEN_DB_FLAGS_DEFAULT,
00219                                tmpArgs->name, v);
00220           break;
00221 
00222         case GWEN_ArgsType_Int:
00223           if (sscanf(v, "%i", &value)!=1) {
00224             DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for long option \"%s\"",
00225                       tmpBuf);
00226             free(tmpBuf);
00227             GWEN_DB_Group_free(counts);
00228             return GWEN_ARGS_RESULT_ERROR;
00229           }
00230           GWEN_DB_SetIntValue(db,
00231                               GWEN_DB_FLAGS_DEFAULT,
00232                               tmpArgs->name, value);
00233           break;
00234 
00235         default:
00236           DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"", tmpArgs->type);
00237           GWEN_DB_Group_free(counts);
00238           return GWEN_ARGS_RESULT_ERROR;
00239         } /* switch */
00240       }
00241       else {
00242         if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) {
00243           GWEN_DB_Group_free(counts);
00244           return GWEN_ARGS_RESULT_HELP;
00245         }
00246         GWEN_DB_SetIntValue(db,
00247                             GWEN_DB_FLAGS_OVERWRITE_VARS,
00248                             tmpArgs->name,
00249                             GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0));
00250       }
00251       free(tmpBuf);
00252 
00253       break;
00254 
00255     default:
00256       DBG_ERROR(GWEN_LOGDOMAIN, "Internal error (unknown argv type \"%d\")",
00257                 t);
00258       GWEN_DB_Group_free(counts);
00259       return GWEN_ARGS_RESULT_ERROR;
00260       break;
00261     } /* switch */
00262   } /* while */
00263 
00264   /* check argument counts */
00265   for(tmpArgs=args;;tmpArgs++) {
00266     const char *s;
00267     int c;
00268 
00269     if (tmpArgs->longOption)
00270       s=tmpArgs->longOption;
00271     else
00272       s=tmpArgs->shortOption;
00273 
00274     c=GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0);
00275 
00276     /* check minnum */
00277     if (tmpArgs->minNum && ((unsigned int)c<tmpArgs->minNum)) {
00278       if (tmpArgs->minNum>1) {
00279         DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed %d times (have %d)",
00280                   s, tmpArgs->minNum, c);
00281       }
00282       else {
00283         DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed", s);
00284       }
00285       GWEN_DB_Group_free(counts);
00286       return GWEN_ARGS_RESULT_ERROR;
00287     }
00288 
00289     /* check maxnum */
00290     if (tmpArgs->maxNum && ((unsigned int)c>tmpArgs->maxNum)) {
00291       DBG_ERROR(GWEN_LOGDOMAIN,
00292                 "Option \"%s\" needed at most %d times (have %d)",
00293                 s, tmpArgs->maxNum, c);
00294       GWEN_DB_Group_free(counts);
00295       return GWEN_ARGS_RESULT_ERROR;
00296     }
00297 
00298     if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
00299       break;
00300   } /* for */
00301   GWEN_DB_Group_free(counts);
00302 
00303   return i;
00304 }
00305 
00306 
00307 int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins){
00308   unsigned int i;
00309 
00310   while(*s) {
00311     for (i=0; i<ins; i++) GWEN_Buffer_AppendByte(ubuf, ' ');
00312     while(*s) {
00313       char c;
00314 
00315       c=*s;
00316       s++;
00317       GWEN_Buffer_AppendByte(ubuf, c);
00318       if (c=='\n')
00319         break;
00320     } /* while */
00321   } /* while */
00322 
00323   return 0;
00324 }
00325 
00326 
00327 
00328 int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf){
00329   const GWEN_ARGS *tmpArgs;
00330 
00331   for(tmpArgs=args;;tmpArgs++) {
00332     const char *s;
00333 
00334     GWEN_Buffer_AppendString(ubuf, "\n");
00335     if (tmpArgs->shortOption || tmpArgs->longOption) {
00336       if (tmpArgs->shortOption) {
00337         GWEN_Buffer_AppendString(ubuf, " ");
00338         if (tmpArgs->minNum==0)
00339           GWEN_Buffer_AppendString(ubuf, "[");
00340         else
00341           GWEN_Buffer_AppendString(ubuf, " ");
00342         GWEN_Buffer_AppendString(ubuf, "-");
00343         GWEN_Buffer_AppendString(ubuf, tmpArgs->shortOption);
00344         if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
00345           GWEN_Buffer_AppendString(ubuf, " PARAM");
00346         if (tmpArgs->minNum==0)
00347           GWEN_Buffer_AppendString(ubuf, "]");
00348         GWEN_Buffer_AppendString(ubuf, "\n");
00349       } /* if short option */
00350 
00351       if (tmpArgs->longOption) {
00352         GWEN_Buffer_AppendString(ubuf, " ");
00353         if (tmpArgs->minNum==0)
00354           GWEN_Buffer_AppendString(ubuf, "[");
00355         else
00356           GWEN_Buffer_AppendString(ubuf, " ");
00357         GWEN_Buffer_AppendString(ubuf, "--");
00358         GWEN_Buffer_AppendString(ubuf, tmpArgs->longOption);
00359         if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)
00360           GWEN_Buffer_AppendString(ubuf, "=PARAM");
00361         if (tmpArgs->minNum==0)
00362           GWEN_Buffer_AppendString(ubuf, "]");
00363         GWEN_Buffer_AppendString(ubuf, "\n");
00364       } /* if short option */
00365 
00366       s=tmpArgs->longDescription;
00367       if (!s)
00368         s=tmpArgs->shortDescription;
00369 
00370       if (s) {
00371         GWEN_Args__AppendTXT(ubuf, s, 3);
00372         GWEN_Buffer_AppendString(ubuf, "\n");
00373       }
00374     } /* if any option */
00375     else {
00376       DBG_ERROR(GWEN_LOGDOMAIN,
00377                 "Option \"%s\" has neither a long nor a short name",
00378                 tmpArgs->name);
00379       return -1;
00380     }
00381 
00382     if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST)
00383       break;
00384   } /* for */
00385 
00386   return 0;
00387 }
00388 
00389 
00390 
00391 int GWEN_Args_UsageHTML(GWEN_UNUSED const GWEN_ARGS *args,
00392                         GWEN_UNUSED GWEN_BUFFER *ubuf){
00393   return 0;
00394 }
00395 
00396 
00397 
00398 int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf,
00399                     GWEN_ARGS_OUTTYPE ot){
00400   int rv;
00401 
00402   switch(ot) {
00403   case GWEN_ArgsOutType_Txt:
00404     rv=GWEN_Args_UsageTXT(args, ubuf);
00405     break;
00406   case GWEN_ArgsOutType_Html:
00407     rv=GWEN_Args_UsageHTML(args, ubuf);
00408     break;
00409   default:
00410     DBG_ERROR(GWEN_LOGDOMAIN, "Unknown output type %d", ot);
00411     rv=-1;
00412   } /* switch */
00413 
00414   return rv;
00415 }
00416 
00417 
00418 
00419 int GWEN_Args_ShortUsage(GWEN_UNUSED const GWEN_ARGS *args,
00420                          GWEN_UNUSED GWEN_BUFFER *ubuf,
00421                          GWEN_UNUSED GWEN_ARGS_OUTTYPE ot){
00422   return 0;
00423 }
00424 
00425 
00426 
00427 
00428 
00429 
00430