summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Troan <ewt@src.gnome.org>1998-09-27 15:56:18 +0000
committerErik Troan <ewt@src.gnome.org>1998-09-27 15:56:18 +0000
commitd38f4f030efc6a68420e683a749756f1e338bef4 (patch)
treef6bd0b337a2860a1e9cb662dcf0a04eb4744d8db
parent7e8d04d2ac6e9b8015a0e299ce7a7fcf27afc963 (diff)
downloadgnome-common-d38f4f030efc6a68420e683a749756f1e338bef4.tar.gz
1) modified test to display callback val field
2) split popt stuff into multiple iles svn path=/trunk/; revision=412
-rw-r--r--support/poptconfig.c143
-rw-r--r--support/popthelp.c242
-rw-r--r--support/poptparse.c85
3 files changed, 470 insertions, 0 deletions
diff --git a/support/poptconfig.c b/support/poptconfig.c
new file mode 100644
index 0000000..cd4e239
--- /dev/null
+++ b/support/poptconfig.c
@@ -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
index 0000000..326f0ae
--- /dev/null
+++ b/support/popthelp.c
@@ -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
index 0000000..ade5a79
--- /dev/null
+++ b/support/poptparse.c
@@ -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;
+}