diff options
author | Erik Troan <ewt@src.gnome.org> | 1997-01-17 21:58:27 +0000 |
---|---|---|
committer | Erik Troan <ewt@src.gnome.org> | 1997-01-17 21:58:27 +0000 |
commit | 943cbcdb0898e818bc0f6eaaae8236ca3c2b06f4 (patch) | |
tree | 1ac7650b6cb3b0dd3d6645c09a920d3b75e00af4 | |
parent | a0a678e03978fa4eb122470c980c60fdd5cc0411 (diff) | |
download | gnome-common-943cbcdb0898e818bc0f6eaaae8236ca3c2b06f4.tar.gz |
1) added parsing options for option args
2) added alias config files
svn path=/trunk/; revision=3
-rw-r--r-- | support/popt-gnome.h | 14 | ||||
-rw-r--r-- | support/popt.c | 247 | ||||
-rw-r--r-- | support/popt.h | 14 |
3 files changed, 219 insertions, 56 deletions
diff --git a/support/popt-gnome.h b/support/popt-gnome.h index 831974a..fab92bc 100644 --- a/support/popt-gnome.h +++ b/support/popt-gnome.h @@ -4,7 +4,9 @@ #define POPT_OPTION_DEPTH 10 #define POPT_ARG_NONE 0 -#define POPT_ARG_YES 1 +#define POPT_ARG_STRING 1 +#define POPT_ARG_INT 2 +#define POPT_ARG_LONG 3 #define POPT_ERROR_NOARG -10 #define POPT_ERROR_BADOPT -11 @@ -12,12 +14,13 @@ #define POPT_ERROR_OPTSTOODEEP -13 #define POPT_ERROR_UNEXPARG -14 #define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ +#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ struct poptOption { const char * longName; /* may be NULL */ char shortName; /* may be '\0' */ - int takesArg; - int *flag; /* may be NULL */ + int argInfo; + void * arg; /* depends on argInfo */ int val; /* 0 means don't return, just update flag */ }; @@ -31,6 +34,7 @@ typedef struct poptContext_s * poptContext; poptContext poptGetContext(char * name, int argc, char ** argv, struct poptOption * options, int flags); +void poptResetContext(poptContext con); /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ int poptGetNextOpt(poptContext con); @@ -42,6 +46,10 @@ char * poptPeekArg(poptContext con); char ** poptGetArgs(poptContext con); void poptFreeContext(poptContext con); int poptAddAlias(poptContext con, struct poptAlias alias); +int poptReadConfigFile(poptContext con, char * fn); +/* like above, but reads /etc/popt and $HOME/.popt along with environment + vars */ +int poptReadDefaultConfig(poptContext con, int useEnv); /* argv should be freed -- this allows ', ", and \ quoting, but ' is treated the same as " and both may include \ quotes */ int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr); diff --git a/support/popt.c b/support/popt.c index ed4510c..2659dd2 100644 --- a/support/popt.c +++ b/support/popt.c @@ -1,6 +1,11 @@ +#include <errno.h> #include <ctype.h> +#include <fcntl.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/mman.h> +#include <unistd.h> #include "popt.h" @@ -20,7 +25,7 @@ struct poptContext_s { int restLeftover; char * nextArg; char * nextCharArg; - int aliasLocation; + char * appName; struct poptAlias * aliases; int numAliases; }; @@ -28,8 +33,6 @@ struct poptContext_s { poptContext poptGetContext(char * name ,int argc, char ** argv, struct poptOption * options, int flags) { poptContext con = malloc(sizeof(*con)); - char * envName, * envValue, * chptr; - struct poptAlias alias; con->os = con->optionStack; con->os->argc = argc; @@ -46,42 +49,25 @@ poptContext poptGetContext(char * name ,int argc, char ** argv, con->nextArg = NULL; con->aliases = NULL; con->numAliases = 0; - con->aliasLocation = 0; - - if (!name) return con; - - envName = alloca(strlen(name) + 20); - strcpy(envName, name); - strcat(envName, "_POPT_ALIASES"); - - if ((envValue = getenv(envName))) { - envValue = strcpy(alloca(strlen(envValue) + 1), envValue); - - while (envValue && *envValue) { - chptr = strchr(envValue, '='); - if (!chptr) { - envValue = strchr(envValue, '\n'); - if (envValue) envValue++; - continue; - } - - *chptr = '\0'; - alias.longName = envValue; - envValue = chptr + 1; - chptr = strchr(envValue, '\n'); - if (chptr) *chptr = '\0'; + + if (!name) + con->appName = NULL; + else + con->appName = strcpy(malloc(strlen(name) + 1), name); - poptParseArgvString(envValue, &alias.argc, &alias.argv); - poptAddAlias(con, alias); + return con; +} - if (chptr) - envValue = chptr + 1; - else - envValue = NULL; - } - } +void poptResetContext(poptContext con) { + con->os = con->optionStack; + con->os->currAlias = NULL; + con->os->next = 1; /* skip argv[0] */ - return con; + con->numLeftovers = 0; + con->nextLeftover = 0; + con->restLeftover = 0; + con->nextCharArg = NULL; + con->nextArg = NULL; } /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ @@ -89,7 +75,7 @@ int poptGetNextOpt(poptContext con) { char * optString, * chptr, * localOptString; char * longArg = NULL; char * origOptString; - struct poptOption * opt = con->options; + struct poptOption * opt = NULL; int done = 0; int i; @@ -147,6 +133,7 @@ int poptGetNextOpt(poptContext con) { *chptr = '\0'; } + opt = con->options; while (opt->longName || opt->shortName) { if (opt->longName && !strcmp(optString, opt->longName)) break; @@ -163,6 +150,7 @@ int poptGetNextOpt(poptContext con) { con->nextCharArg = NULL; + opt = con->options; while ((opt->longName || opt->shortName) && *origOptString != opt->shortName) opt++; if (!opt->longName && !opt->shortName) return POPT_ERROR_BADOPT; @@ -172,7 +160,9 @@ int poptGetNextOpt(poptContext con) { con->nextCharArg = origOptString; } - if (opt->takesArg == POPT_ARG_YES) { + if (opt->arg && opt->argInfo == POPT_ARG_NONE) + *((int *)opt->arg) = 1; + else if (opt->argInfo != POPT_ARG_NONE) { if (longArg) { con->nextArg = longArg; } else if (con->nextCharArg) { @@ -187,9 +177,18 @@ int poptGetNextOpt(poptContext con) { con->nextArg = con->os->argv[con->os->next++]; } - } - if (opt->flag) *opt->flag = 1; + if (opt->arg) { + switch (opt->argInfo) { + case POPT_ARG_STRING: + *((char **) opt->arg) = con->nextArg; + break; + default: + printf("option type not implemented in popt\n"); + exit(1); + } + } + } if (opt->val) done = 1; } @@ -220,6 +219,7 @@ char ** poptGetArgs(poptContext con) { void poptFreeContext(poptContext con) { free(con->leftovers); + if (con->appName) free(con->appName); free(con); } @@ -231,6 +231,8 @@ int poptAddAlias(poptContext con, struct poptAlias newAlias) { alias = con->aliases + aliasNum; *alias = newAlias; + alias->longName = strcpy(malloc(strlen(alias->longName) + 1), + alias->longName); return 0; } @@ -253,16 +255,7 @@ int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) { memset(buf, '\0', strlen(s) + 1); while (*src) { - if (isspace(*src)) { - if (*argv[argc]) { - buf++, argc++; - if (argc == argvAlloced) { - argvAlloced += 5; - argv = realloc(argv, sizeof(*argv) * argvAlloced); - } - argv[argc] = buf; - } - } else if (quote == *src) { + if (quote == *src) { quote = '\0'; } else if (quote) { if (*src == '\\') { @@ -271,8 +264,18 @@ int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) { 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 '\'': @@ -312,3 +315,147 @@ int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) { return 0; } + +static void configLine(poptContext con, char * line) { + int nameLength = strlen(con->appName); + char * opt; + struct poptAlias alias; + + if (strncmp(line, con->appName, nameLength)) return; + line += nameLength; + if (!*line || !isspace(*line)) return; + while (*line && isspace(*line)) line++; + + if (!strncmp(line, "alias", 5)) { + line += 5; + if (!*line || !isspace(*line)) return; + while (*line && isspace(*line)) line++; + if (!*line) return; + + opt = line; + while (*line && !isspace(*line)) line++; + if (!*line) return; + *line++ = '\0'; + while (*line && isspace(*line)) line++; + if (!*line) return; + + if (poptParseArgvString(line, &alias.argc, &alias.argv)) return; + alias.longName = opt; + + poptAddAlias(con, alias); + } +} + +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 = mmap(NULL, fileLength, PROT_READ, MAP_PRIVATE, fd, 0); + if (file == (void *) -1) { + 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 - 1) = *chptr++; + else + *dst++ = *chptr++; + } + break; + default: + *dst++ = *chptr++; + } + } + + return 0; +} + +int poptReadDefaultConfig(poptContext con, int useEnv) { + char * envName, * envValue; + char * fn, * home, * chptr; + int rc; + struct poptAlias alias; + + if (!con->appName) return 0; + + rc = poptReadConfigFile(con, "/etc/popt"); + if (rc) return rc; + if ((home = getenv("HOME"))) { + fn = alloca(strlen(home) + 20); + sprintf(fn, "%s/.popt", home); + rc = poptReadConfigFile(con, fn); + if (rc) return rc; + } + + envName = alloca(strlen(con->appName) + 20); + strcpy(envName, con->appName); + chptr = envName; + while (*chptr) { + *chptr = toupper(*chptr); + chptr++; + } + strcat(envName, "_POPT_ALIASES"); + + if (useEnv && (envValue = getenv(envName))) { + envValue = strcpy(alloca(strlen(envValue) + 1), envValue); + + while (envValue && *envValue) { + chptr = strchr(envValue, '='); + if (!chptr) { + envValue = strchr(envValue, '\n'); + if (envValue) envValue++; + continue; + } + + *chptr = '\0'; + alias.longName = envValue; + envValue = chptr + 1; + chptr = strchr(envValue, '\n'); + if (chptr) *chptr = '\0'; + + poptParseArgvString(envValue, &alias.argc, &alias.argv); + poptAddAlias(con, alias); + + if (chptr) + envValue = chptr + 1; + else + envValue = NULL; + } + } + + return 0; +} diff --git a/support/popt.h b/support/popt.h index 831974a..fab92bc 100644 --- a/support/popt.h +++ b/support/popt.h @@ -4,7 +4,9 @@ #define POPT_OPTION_DEPTH 10 #define POPT_ARG_NONE 0 -#define POPT_ARG_YES 1 +#define POPT_ARG_STRING 1 +#define POPT_ARG_INT 2 +#define POPT_ARG_LONG 3 #define POPT_ERROR_NOARG -10 #define POPT_ERROR_BADOPT -11 @@ -12,12 +14,13 @@ #define POPT_ERROR_OPTSTOODEEP -13 #define POPT_ERROR_UNEXPARG -14 #define POPT_ERROR_BADQUOTE -15 /* only from poptParseArgString() */ +#define POPT_ERROR_ERRNO -16 /* only from poptParseArgString() */ struct poptOption { const char * longName; /* may be NULL */ char shortName; /* may be '\0' */ - int takesArg; - int *flag; /* may be NULL */ + int argInfo; + void * arg; /* depends on argInfo */ int val; /* 0 means don't return, just update flag */ }; @@ -31,6 +34,7 @@ typedef struct poptContext_s * poptContext; poptContext poptGetContext(char * name, int argc, char ** argv, struct poptOption * options, int flags); +void poptResetContext(poptContext con); /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */ int poptGetNextOpt(poptContext con); @@ -42,6 +46,10 @@ char * poptPeekArg(poptContext con); char ** poptGetArgs(poptContext con); void poptFreeContext(poptContext con); int poptAddAlias(poptContext con, struct poptAlias alias); +int poptReadConfigFile(poptContext con, char * fn); +/* like above, but reads /etc/popt and $HOME/.popt along with environment + vars */ +int poptReadDefaultConfig(poptContext con, int useEnv); /* argv should be freed -- this allows ', ", and \ quoting, but ' is treated the same as " and both may include \ quotes */ int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr); |