summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Troan <ewt@src.gnome.org>1997-01-17 21:58:27 +0000
committerErik Troan <ewt@src.gnome.org>1997-01-17 21:58:27 +0000
commit943cbcdb0898e818bc0f6eaaae8236ca3c2b06f4 (patch)
tree1ac7650b6cb3b0dd3d6645c09a920d3b75e00af4
parenta0a678e03978fa4eb122470c980c60fdd5cc0411 (diff)
downloadgnome-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.h14
-rw-r--r--support/popt.c247
-rw-r--r--support/popt.h14
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);