diff options
author | Erik Troan <ewt@src.gnome.org> | 1998-09-27 15:56:18 +0000 |
---|---|---|
committer | Erik Troan <ewt@src.gnome.org> | 1998-09-27 15:56:18 +0000 |
commit | d38f4f030efc6a68420e683a749756f1e338bef4 (patch) | |
tree | f6bd0b337a2860a1e9cb662dcf0a04eb4744d8db /support | |
parent | 7e8d04d2ac6e9b8015a0e299ce7a7fcf27afc963 (diff) | |
download | shared-mime-info-d38f4f030efc6a68420e683a749756f1e338bef4.tar.gz |
1) modified test to display callback val field
2) split popt stuff into multiple iles
svn path=/trunk/; revision=412
Diffstat (limited to 'support')
-rw-r--r-- | support/poptconfig.c | 143 | ||||
-rw-r--r-- | support/popthelp.c | 242 | ||||
-rw-r--r-- | support/poptparse.c | 85 |
3 files changed, 470 insertions, 0 deletions
diff --git a/support/poptconfig.c b/support/poptconfig.c new file mode 100644 index 00000000..cd4e239f --- /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 00000000..326f0ae7 --- /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 00000000..ade5a791 --- /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; +} |