1) modified test to display callback val field
authorErik Troan <ewt@src.gnome.org>
Sun, 27 Sep 1998 15:56:18 +0000 (15:56 +0000)
committerErik Troan <ewt@src.gnome.org>
Sun, 27 Sep 1998 15:56:18 +0000 (15:56 +0000)
2) split popt stuff into multiple iles

svn path=/trunk/; revision=412

support/poptconfig.c [new file with mode: 0644]
support/popthelp.c [new file with mode: 0644]
support/poptparse.c [new file with mode: 0644]

diff --git a/support/poptconfig.c b/support/poptconfig.c
new file mode 100644 (file)
index 0000000..cd4e239
--- /dev/null
@@ -0,0 +1,143 @@
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#include "popt.h"
+#include "poptint.h"
+
+static void configLine(poptContext con, char * line) {
+    int nameLength = strlen(con->appName);
+    char * opt;
+    struct poptAlias alias;
+    char * entryType;
+    char * longName = NULL;
+    char shortName = '\0';
+    
+    if (strncmp(line, con->appName, nameLength)) return;
+    line += nameLength;
+    if (!*line || !isspace(*line)) return;
+    while (*line && isspace(*line)) line++;
+    entryType = line;
+
+    while (!*line || !isspace(*line)) line++;
+    *line++ = '\0';
+    while (*line && isspace(*line)) line++;
+    if (!*line) return;
+    opt = line;
+
+    while (!*line || !isspace(*line)) line++;
+    *line++ = '\0';
+    while (*line && isspace(*line)) line++;
+    if (!*line) return;
+
+    if (opt[0] == '-' && opt[1] == '-')
+       longName = opt + 2;
+    else if (opt[0] == '-' && !opt[2])
+       shortName = opt[1];
+
+    if (!strcmp(entryType, "alias")) {
+       if (poptParseArgvString(line, &alias.argc, &alias.argv)) return;
+       alias.longName = longName, alias.shortName = shortName;
+       poptAddAlias(con, alias, 0);
+    } else if (!strcmp(entryType, "exec")) {
+       con->execs = realloc(con->execs, 
+                               sizeof(*con->execs) * (con->numExecs + 1));
+       if (longName)
+           con->execs[con->numExecs].longName = strdup(longName);
+       else
+           con->execs[con->numExecs].longName = NULL;
+
+       con->execs[con->numExecs].shortName = shortName;
+       con->execs[con->numExecs].script = strdup(line);
+       
+       con->numExecs++;
+    }
+}
+
+int poptReadConfigFile(poptContext con, char * fn) {
+    char * file, * chptr, * end;
+    char * buf, * dst;
+    int fd, rc;
+    int fileLength;
+
+    fd = open(fn, O_RDONLY);
+    if (fd < 0) {
+       if (errno == ENOENT)
+           return 0;
+       else 
+           return POPT_ERROR_ERRNO;
+    }
+
+    fileLength = lseek(fd, 0, SEEK_END);
+    lseek(fd, 0, 0);
+
+    file = alloca(fileLength + 1);
+    if ((fd = read(fd, file, fileLength)) != fileLength) {
+       rc = errno;
+       close(fd);
+       errno = rc;
+       return POPT_ERROR_ERRNO;
+    }
+    close(fd);
+
+    dst = buf = alloca(fileLength + 1);
+
+    chptr = file;
+    end = (file + fileLength);
+    while (chptr < end) {
+       switch (*chptr) {
+         case '\n':
+           *dst = '\0';
+           dst = buf;
+           while (*dst && isspace(*dst)) dst++;
+           if (*dst && *dst != '#') {
+               configLine(con, dst);
+           }
+           chptr++;
+           break;
+         case '\\':
+           *dst++ = *chptr++;
+           if (chptr < end) {
+               if (*chptr == '\n') 
+                   dst--, chptr++;     
+                   /* \ at the end of a line does not insert a \n */
+               else
+                   *dst++ = *chptr++;
+           }
+           break;
+         default:
+           *dst++ = *chptr++;
+       }
+    }
+
+    return 0;
+}
+
+int poptReadDefaultConfig(poptContext con, int useEnv) {
+    char * fn, * home;
+    int rc;
+
+    if (!con->appName) return 0;
+
+    rc = poptReadConfigFile(con, "/etc/popt");
+    if (rc) return rc;
+    if (getuid() != geteuid()) return 0;
+
+    if ((home = getenv("HOME"))) {
+       fn = alloca(strlen(home) + 20);
+       strcpy(fn, home);
+       strcat(fn, "/.popt");
+       rc = poptReadConfigFile(con, fn);
+       if (rc) return rc;
+    }
+
+    return 0;
+}
+
diff --git a/support/popthelp.c b/support/popthelp.c
new file mode 100644 (file)
index 0000000..326f0ae
--- /dev/null
@@ -0,0 +1,242 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "popt.h"
+#include "poptint.h"
+
+static void displayArgs(poptContext con, int key, const char * arg, 
+                       void * data) {
+    if (key == '?')
+       poptPrintHelp(con, stderr, 0);
+    else
+       poptPrintUsage(con, stderr, 0);
+    exit(0);
+}
+
+struct poptOption poptHelpOptions[] = {
+    { NULL, '\0', POPT_ARG_CALLBACK, &displayArgs, '\0', NULL },
+    { "help", '?', 0, NULL, '?', "Show this help message" },
+    { "usage", '\0', 0, NULL, 'u', "Display brief usage message" },
+    { NULL, '\0', 0, NULL, 0 }
+} ;
+
+static void singleOptionHelp(FILE * f, int maxLeftCol, 
+                            const struct poptOption * opt) {
+    int indentLength = maxLeftCol + 5;
+    int lineLength = 79 - indentLength;
+    const char * help = opt->descrip;
+    int helpLength;
+    const char * ch;
+    char format[10];
+    char * left = alloca(maxLeftCol + 1);
+
+    *left = '\0';
+    if (opt->longName && opt->shortName)
+       sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
+    else if (opt->shortName) 
+       sprintf(left, "-%c", opt->shortName);
+    else if (opt->longName)
+       sprintf(left, "--%s", opt->longName);
+    if (!*left) return ;
+    if (opt->argDescrip) {
+       strcat(left, "=");
+       strcat(left, opt->argDescrip);
+    }
+
+    if (help)
+       fprintf(f,"  %-*s   ", maxLeftCol, left);
+    else {
+       fprintf(f,"  %s\n", left); 
+       return;
+    }
+
+    helpLength = strlen(help);
+    while (helpLength > lineLength) {
+       ch = help + lineLength - 1;
+       while (ch > help && !isspace(*ch)) ch--;
+       if (ch == help) break;          /* give up */
+       while (ch > (help + 1) && isspace(*ch)) ch--;
+       ch++;
+
+       sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
+       fprintf(f, format, help, " ");
+       help = ch;
+       while (isspace(*help) && *help) help++;
+       helpLength = strlen(help);
+    }
+
+    if (helpLength) fprintf(f, "%s\n", help);
+}
+
+static int maxArgWidth(const struct poptOption * opt) {
+    int max = 0;
+    int this;
+    
+    while (opt->longName || opt->shortName || opt->arg) {
+       if (opt->argInfo == POPT_ARG_INCLUDE_TABLE) {
+           this = maxArgWidth(opt->arg);
+       } else {
+           this = opt->shortName ? 2 : 0;
+           if (opt->longName) {
+               if (this) this += 2;
+               this += strlen(opt->longName) + 2;
+           }
+
+           if (opt->argDescrip)
+               this += strlen(opt->argDescrip) + 1;
+       }
+
+       if (this > max) max = this;
+
+       opt++;
+    }
+    
+    return max;
+}
+
+static void singleTableHelp(FILE * f, const struct poptOption * table, 
+                           int left) {
+    const struct poptOption * opt;
+
+    opt = table;
+    while (opt->longName || opt->shortName || opt->arg) {
+       if (opt->longName || opt->shortName)
+           singleOptionHelp(f, left, opt);
+       opt++;
+    }
+
+    opt = table;
+    while (opt->longName || opt->shortName || opt->arg) {
+       if (opt->argInfo == POPT_ARG_INCLUDE_TABLE) {
+           if (opt->descrip)
+               fprintf(f, "\n%s\n", opt->descrip);
+           singleTableHelp(f, opt->arg, left);
+       }
+       opt++;
+    }
+}
+
+static int showHelpIntro(poptContext con, FILE * f) {
+    int len = 6;
+    char * fn;
+
+    fprintf(f, "Usage:");
+    if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
+       fn = con->optionStack->argv[0];
+       if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
+       fprintf(f, " %s", fn);
+       len += strlen(fn) + 1;
+    }
+
+    return len;
+}
+
+void poptPrintHelp(poptContext con, FILE * f, int flags) {
+    int leftColWidth;
+
+    showHelpIntro(con, f);
+    if (con->otherHelp)
+       fprintf(f, " %s\n", con->otherHelp);
+    else
+       fprintf(f, " [OPTION...]\n");
+
+    leftColWidth = maxArgWidth(con->options);
+    singleTableHelp(f, con->options, leftColWidth);
+}
+
+static int singleOptionUsage(FILE * f, int cursor, 
+                             const struct poptOption * opt) {
+    int len = 3;
+    char shortStr[2];
+    const char * item = shortStr;
+
+    if (opt->shortName) {
+       if (!opt->argInfo) return cursor;       /* we did these already */
+       len++;
+       *shortStr = opt->shortName;
+       shortStr[1] = '\0';
+    } else if (opt->longName) {
+       len += 1 + strlen(opt->longName);
+       item = opt->longName;
+    }
+
+    if (len == 3) return cursor;
+
+    if (opt->argDescrip) 
+       len += strlen(opt->argDescrip) + 1;
+
+    if ((cursor + len) > 79) {
+       fprintf(f, "\n       ");
+       cursor = 7;
+    } 
+
+    fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
+           opt->argDescrip ? "=" : "", 
+           opt->argDescrip ? opt->argDescrip : "");
+
+    return cursor + len + 1;
+}
+
+int singleTableUsage(FILE * f, int cursor, const struct poptOption * table) {
+    const struct poptOption * opt;
+    
+    opt = table;
+    while (opt->longName || opt->shortName || opt->arg) {
+       if (opt->longName || opt->shortName)
+           cursor = singleOptionUsage(f, cursor, opt);
+       else if (opt->argInfo == POPT_ARG_INCLUDE_TABLE) 
+           cursor = singleTableUsage(f, cursor, opt->arg);
+       opt++;
+    }
+
+    return cursor;
+}
+
+static int showShortOptions(const struct poptOption * opt, FILE * f, 
+                           char * str) {
+    char s[300];               /* this is larger then the ascii set, so
+                                  it should do just fine */
+
+    if (!str) {
+       str = s;
+       memset(str, 0, sizeof(str));
+    }
+
+    while (opt->longName || opt->shortName || opt->arg) {
+       if (opt->shortName && !opt->argInfo)
+           str[strlen(str)] = opt->shortName;
+       else if (opt->argInfo == POPT_ARG_INCLUDE_TABLE)
+           showShortOptions(opt->arg, f, str);
+
+       opt++;
+    } 
+
+    if (s != str || !*s)
+       return 0;
+
+    fprintf(f, " [-%s]", s);
+    return strlen(s) + 4;
+}
+
+void poptPrintUsage(poptContext con, FILE * f, int flags) {
+    int cursor;
+
+    cursor = showHelpIntro(con, f);
+    cursor += showShortOptions(con->options, f, NULL);
+    singleTableUsage(f, cursor, con->options);
+
+    if (con->otherHelp) {
+       cursor += strlen(con->otherHelp) + 1;
+       if (cursor > 79) fprintf(f, "\n       ");
+       fprintf(f, " %s", con->otherHelp);
+    }
+
+    fprintf(f, "\n");
+}
+
+void poptSetOtherOptionHelp(poptContext con, const char * text) {
+    if (con->otherHelp) free(con->otherHelp);
+    con->otherHelp = strdup(text);
+}
diff --git a/support/poptparse.c b/support/poptparse.c
new file mode 100644 (file)
index 0000000..ade5a79
--- /dev/null
@@ -0,0 +1,85 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "popt.h"
+
+int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) {
+    char * buf = strcpy(alloca(strlen(s) + 1), s);
+    char * bufStart = buf;
+    char * src, * dst;
+    char quote = '\0';
+    int argvAlloced = 5;
+    char ** argv = malloc(sizeof(*argv) * argvAlloced);
+    char ** argv2;
+    int argc = 0;
+    int i;
+
+    src = s;
+    dst = buf;
+    argv[argc] = buf;
+
+    memset(buf, '\0', strlen(s) + 1);
+
+    while (*src) {
+       if (quote == *src) {
+           quote = '\0';
+       } else if (quote) {
+           if (*src == '\\') {
+               src++;
+               if (!*src) {
+                   free(argv);
+                   return POPT_ERROR_BADQUOTE;
+               }
+               if (*src != quote) *buf++ = '\\';
+           }
+           *buf++ = *src;
+       } else if (isspace(*src)) {
+           if (*argv[argc]) {
+               buf++, argc++;
+               if (argc == argvAlloced) {
+                   argvAlloced += 5;
+                   argv = realloc(argv, sizeof(*argv) * argvAlloced);
+               }
+               argv[argc] = buf;
+           }
+       } else switch (*src) {
+         case '"':
+         case '\'':
+           quote = *src;
+           break;
+         case '\\':
+           src++;
+           if (!*src) {
+               free(argv);
+               return POPT_ERROR_BADQUOTE;
+           }
+           /* fallthrough */
+         default:
+           *buf++ = *src;
+       }
+
+       src++;
+    }
+
+    if (strlen(argv[argc])) {
+       argc++, buf++;
+    }
+
+    dst = malloc(argc * sizeof(*argv) + (buf - bufStart));
+    argv2 = (void *) dst;
+    dst += argc * sizeof(*argv);
+    memcpy(argv2, argv, argc * sizeof(*argv));
+    memcpy(dst, bufStart, buf - bufStart);
+
+    for (i = 0; i < argc; i++) {
+       argv2[i] = dst + (argv[i] - bufStart);
+    }
+
+    free(argv);
+
+    *argvPtr = argv2;
+    *argcPtr = argc;
+
+    return 0;
+}