From: Dick Porter <dick@acm.org> --
authorjbj <devnull@localhost>
Thu, 18 Nov 1999 17:10:15 +0000 (17:10 +0000)
committerjbj <devnull@localhost>
Thu, 18 Nov 1999 17:10:15 +0000 (17:10 +0000)
Here is a patch for popt to implement selective argument stripping from argv.
With this patch I can use popt in ORBit (the CORBA spec requires ORBs to
remove all ORB options from argv), which allows me to export a popt option
table to the rest of Gnome.
There is also a bug fix included where a string was realloc()d into a space
too small to hold the trailing NULL.

CVS patchset: 3428
CVS date: 1999/11/18 17:10:15

popt/po/popt.pot
popt/popt.c
popt/popt.h
popt/poptint.h

index 1691522..6a3a1b4 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 1999-11-18 11:50-0500\n"
+"POT-Creation-Date: 1999-11-18 11:59-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
index 0de68fd..ae608f1 100644 (file)
@@ -67,6 +67,7 @@ poptContext poptGetContext(const char * name, int argc, const char ** argv,
     con->finalArgvAlloced = argc * 2;
     con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
     con->execAbsolute = 1;
+    con->arg_strip = NULL;
 
     if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
        con->flags |= POPT_CONTEXT_POSIXMEHARDER;
@@ -123,6 +124,11 @@ void poptResetContext(poptContext con) {
     }
 
     con->finalArgvCount = 0;
+
+    if (con->arg_strip) {
+       PBM_FREE(con->arg_strip);
+       con->arg_strip = NULL;
+    }
 }
 
 /* Only one of longName, shortName may be set at a time */
@@ -378,6 +384,14 @@ static /*@only@*/ const char * expandNextArg(poptContext con, const char * s)
     return t;
 }
 
+static void poptStripArg(poptContext con, int which)
+{
+    if(con->arg_strip == NULL) {
+       con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
+    }
+    PBM_SET(which, con->arg_strip);
+}
+
 /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
 int poptGetNextOpt(poptContext con)
 {
@@ -389,6 +403,7 @@ int poptGetNextOpt(poptContext con)
        poptCallbackType cb = NULL;
        const void * cbData = NULL;
        const char * longArg = NULL;
+       int canstrip = 0;
 
        while (!con->os->nextCharArg && con->os->next == con->os->argc
                && con->os > con->optionStack) {
@@ -403,11 +418,13 @@ int poptGetNextOpt(poptContext con)
        /* Process next long option */
        if (!con->os->nextCharArg) {
            char * localOptString, * optString;
+           int thisopt;
 
            if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
                con->os->next++;
                continue;
            }
+           thisopt=con->os->next;
            origOptString = con->os->argv[con->os->next++];
 
            if (con->restLeftover || *origOptString != '-') {
@@ -459,8 +476,15 @@ int poptGetNextOpt(poptContext con)
                    return POPT_ERROR_BADOPT;
            }
 
-           if (!opt)
+           if (!opt) {
                con->os->nextCharArg = origOptString + 1;
+           } else {
+               if(con->os == con->optionStack &&
+                  opt->argInfo & POPT_ARGFLAG_STRIP) {
+                   canstrip = 1;
+                   poptStripArg(con, thisopt);
+               }
+           }
        }
 
        /* Process next short option */
@@ -510,6 +534,14 @@ int poptGetNextOpt(poptContext con)
                if (con->os->next == con->os->argc)
                    return POPT_ERROR_NOARG;
 
+               /* make sure this isn't part of a short arg or the
+                   result of an alias expansion */
+               if(con->os == con->optionStack &&
+                  opt->argInfo & POPT_ARGFLAG_STRIP &&
+                  canstrip) {
+                   poptStripArg(con, con->os->next);
+               }
+               
                con->os->nextArg = expandNextArg(con, con->os->argv[con->os->next++]);
            }
 
@@ -624,6 +656,8 @@ void poptFreeContext(poptContext con) {
     if (con->aliases) free(con->aliases);
     if (con->otherHelp) xfree(con->otherHelp);
     if (con->execPath) xfree(con->execPath);
+    if (con->arg_strip) PBM_FREE(con->arg_strip);
+    
     free(con);
 }
 
@@ -713,3 +747,28 @@ int poptStuffArgs(poptContext con, const char ** argv) {
 const char * poptGetInvocationName(poptContext con) {
     return con->os->argv[0];
 }
+
+int poptStrippedArgv(poptContext con, int argc, char **argv)
+{
+    int i,j=1, numargs=argc;
+    
+    for(i=1; i<argc; i++) {
+       if(PBM_ISSET(i, con->arg_strip)) {
+           numargs--;
+       }
+    }
+    
+    for(i=1; i<argc; i++) {
+       if(PBM_ISSET(i, con->arg_strip)) {
+           continue;
+       } else {
+           if(j<numargs) {
+               argv[j++]=argv[i];
+           } else {
+               argv[j++]='\0';
+           }
+       }
+    }
+    
+    return(numargs);
+}
index 5046fad..e6fa8bd 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 #define POPT_ARG_MASK          0x0000FFFF
 #define POPT_ARGFLAG_ONEDASH   0x80000000  /* allow -longoption */
 #define POPT_ARGFLAG_DOC_HIDDEN 0x40000000  /* don't show in help/usage */
+#define POPT_ARGFLAG_STRIP     0x20000000  /* strip this arg from argv (only applies to long args) */
 #define POPT_CBFLAG_PRE                0x80000000  /* call the callback before parse */
 #define POPT_CBFLAG_POST       0x40000000  /* call the callback after parse */
 #define POPT_CBFLAG_INC_DATA   0x20000000  /* use data from the include line,
@@ -119,6 +120,8 @@ void poptPrintHelp(poptContext con, FILE * f, int flags);
 void poptPrintUsage(poptContext con, FILE * f, int flags);
 void poptSetOtherOptionHelp(poptContext con, const char * text);
 /*@observer@*/ const char * poptGetInvocationName(poptContext con);
+/* shuffles argv pointers to remove stripped args, returns new argc */
+int poptStrippedArgv(poptContext con, int argc, char **argv);
 
 #ifdef  __cplusplus
 }
index 1688095..a1edb97 100644 (file)
@@ -59,6 +59,7 @@ struct poptContext_s {
     /*@only@*/ const char * execPath;
     int execAbsolute;
     /*@only@*/ const char * otherHelp;
+    pbm_set * arg_strip;
 };
 
 #define        xfree(_a)       free((void *)_a)