⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 popt.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *
 * Written by Erik Troan (ewt@redhat.com).
 *
 */
#include <config.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#ifdef HAVE_MMAP
#    include <sys/mman.h>
#else
#    include "util.h"
#endif
#ifdef HAVE_UNISTD_H
#    include <unistd.h>
#endif
#ifdef OS2_NT
#    include <io.h>
#endif

#include "popt.h"

struct optionStackEntry {
    int argc;
    char ** argv;
    int next;
    char * nextArg;
    char * nextCharArg;
    struct poptAlias * currAlias;
};

struct poptContext_s {
    struct optionStackEntry optionStack[POPT_OPTION_DEPTH], * os;
    char ** leftovers;
    int numLeftovers;
    int nextLeftover;
    struct poptOption * options;
    int restLeftover;
    char * appName;
    struct poptAlias * aliases;
    int numAliases;
    int flags;
};

poptContext poptGetContext(char * name ,int argc, char ** argv,
			   struct poptOption * options, int flags) {
    poptContext con = malloc(sizeof(*con));

    con->os = con->optionStack;
    con->os->argc = argc;
    con->os->argv = argv;
    con->os->currAlias = NULL;
    con->os->nextCharArg = NULL;
    con->os->nextArg = NULL;

    if (flags & POPT_KEEP_FIRST)
	con->os->next = 0;			/* include argv[0] */
    else
	con->os->next = 1;			/* skip argv[0] */

    con->leftovers = malloc(sizeof(char *) * (argc + 1));
    con->numLeftovers = 0;
    con->nextLeftover = 0;
    con->restLeftover = 0;
    con->options = options;
    con->aliases = NULL;
    con->numAliases = 0;
    con->flags = 0;

    if (!name)
	con->appName = NULL;
    else
	con->appName = strcpy(malloc(strlen(name) + 1), name);

    return con;
}

void poptResetContext(poptContext con) {
    con->os = con->optionStack;
    con->os->currAlias = NULL;
    con->os->nextCharArg = NULL;
    con->os->nextArg = NULL;
    con->os->next = 1;			/* skip argv[0] */

    con->numLeftovers = 0;
    con->nextLeftover = 0;
    con->restLeftover = 0;
}

/* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
int poptGetNextOpt(poptContext con) {
    char * optString, * chptr, * localOptString;
    char * longArg = NULL;
    char * origOptString;
    long aLong;
    char * end;
    struct poptOption * opt = NULL;
    int done = 0;
    int i;

    while (!done) {
	while (!con->os->nextCharArg && con->os->next == con->os->argc
		&& con->os > con->optionStack)
	    con->os--;
	if (!con->os->nextCharArg && con->os->next == con->os->argc)
	    return -1;

	if (!con->os->nextCharArg) {

	    origOptString = con->os->argv[con->os->next++];

	    if (con->restLeftover || *origOptString != '-') {
		con->leftovers[con->numLeftovers++] = origOptString;
		continue;
	    }

	    if (!origOptString[0])
		return POPT_ERROR_BADOPT;

	    /* Make a copy we can hack at */
	    localOptString = optString =
			strcpy(malloc(strlen(origOptString) + 1),
			origOptString);

	    if (optString[1] == '-' && !optString[2]) {
		con->restLeftover = 1;
		free(localOptString);
		continue;
	    } else if (optString[1] == '-') {
		optString += 2;

		if (!con->os->currAlias || !con->os->currAlias->longName ||
		    strcmp(con->os->currAlias->longName, optString)) {

		    i = con->numAliases - 1;
		    while (i >= 0 && (!con->aliases[i].longName ||
			strcmp(con->aliases[i].longName, optString))) i--;

		    if (i >= 0) {
			free(localOptString);
			if ((con->os - con->optionStack + 1)
				== POPT_OPTION_DEPTH)
			    return POPT_ERROR_OPTSTOODEEP;

			con->os++;
			con->os->next = 0;
			con->os->nextArg = con->os->nextCharArg = NULL;
			con->os->currAlias = con->aliases + i;
			con->os->argc = con->os->currAlias->argc;
			con->os->argv = con->os->currAlias->argv;
			continue;
		    }
		}

		chptr = optString;
		while (*chptr && *chptr != '=') chptr++;
		if (*chptr == '=') {
		    longArg = origOptString + (chptr - localOptString) + 1;
		    *chptr = '\0';
		}

		opt = con->options;
		while (opt->longName || opt->shortName) {
		    if (opt->longName && !strcmp(optString, opt->longName))
			break;
		    opt++;
		}

		if (!opt->longName && !opt->shortName) {
                    free(localOptString);
                    return POPT_ERROR_BADOPT;
                }
	    } else
		con->os->nextCharArg = origOptString + 1;
    	    free(localOptString);
	}

	if (con->os->nextCharArg) {
	    origOptString = con->os->nextCharArg;

	    con->os->nextCharArg = NULL;

	    if (!con->os->currAlias || *origOptString !=
		con->os->currAlias->shortName) {

		i = con->numAliases - 1;
		while (i >= 0 &&
		    con->aliases[i].shortName != *origOptString) i--;

		if (i >= 0) {
		    if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
			return POPT_ERROR_OPTSTOODEEP;

		    /* We'll need this on the way out */
		    origOptString++;
		    if (*origOptString)
			con->os->nextCharArg = origOptString;

		    con->os++;
		    con->os->next = 0;
		    con->os->nextArg = con->os->nextCharArg = NULL;
		    con->os->currAlias = con->aliases + i;
		    con->os->argc = con->os->currAlias->argc;
		    con->os->argv = con->os->currAlias->argv;
		    continue;
		}
	    }

	    opt = con->options;
	    while ((opt->longName || opt->shortName) &&
		    *origOptString != opt->shortName) opt++;
	    if (!opt->longName && !opt->shortName) return POPT_ERROR_BADOPT;

	    origOptString++;
	    if (*origOptString)
		con->os->nextCharArg = origOptString;
	}

	if (opt->arg && opt->argInfo == POPT_ARG_NONE)
	    *((int *)opt->arg) = 1;
	else if (opt->argInfo != POPT_ARG_NONE) {
	    if (longArg) {
		con->os->nextArg = longArg;
	    } else if (con->os->nextCharArg) {
		con->os->nextArg = con->os->nextCharArg;
		con->os->nextCharArg = NULL;
	    } else {
		while (con->os->next == con->os->argc &&
		       con->os > con->optionStack)
		    con->os--;
		if (con->os->next == con->os->argc)
		    return POPT_ERROR_NOARG;

		con->os->nextArg = con->os->argv[con->os->next++];
	    }

	    if (opt->arg) {
		switch (opt->argInfo) {
		  case POPT_ARG_STRING:
		    *((char **) opt->arg) = con->os->nextArg;
		    break;

		  case POPT_ARG_INT:
		  case POPT_ARG_LONG:
		    aLong = strtol(con->os->nextArg, &end, 0);
		    if (*end)
			return POPT_ERROR_BADNUMBER;

		    if (aLong == LONG_MIN || aLong == LONG_MAX)
			return POPT_ERROR_OVERFLOW;
		    if (opt->argInfo == POPT_ARG_LONG) {
			*((long *) opt->arg) = aLong;
		    } else {
			if (aLong > INT_MAX || aLong < INT_MIN)
			    return POPT_ERROR_OVERFLOW;
			*((int *) opt->arg) =aLong;
		    }
		    break;

		  default:
		    printf("option type not implemented in popt\n");
		    exit(1);
		}
	    }
	}

	if (opt->val) done = 1;
    }

    return opt->val;
}

char * poptGetOptArg(poptContext con) {
    char * ret = con->os->nextArg;
    con->os->nextArg = NULL;
    return ret;
}

char * poptGetArg(poptContext con) {
    if (con->numLeftovers == con->nextLeftover) return NULL;
    return (con->leftovers[con->nextLeftover++]);
}

char * poptPeekArg(poptContext con) {
    if (con->numLeftovers == con->nextLeftover) return NULL;
    return (con->leftovers[con->nextLeftover]);
}

char ** poptGetArgs(poptContext con) {
    if (con->numLeftovers == con->nextLeftover) return NULL;

    /* some apps like [like RPM ;-) ] need this NULL terminated */
    con->leftovers[con->numLeftovers] = NULL;

    return (con->leftovers + con->nextLeftover);
}

void poptFreeContext(poptContext con) {
    int i;

    for (i = 0; i < con->numAliases; i++) {
	free(con->aliases[i].longName);
	free(con->aliases[i].argv);
    }

    free(con->leftovers);
    if (con->appName) free(con->appName);
    if (con->aliases) free(con->aliases);
    free(con);
}

int poptAddAlias(poptContext con, struct poptAlias newAlias, int flags) {
    int aliasNum = con->numAliases++;
    struct poptAlias * alias;

    /* SunOS won't realloc(NULL, ...) */
    if (!con->aliases)
	con->aliases = malloc(sizeof(newAlias) * con->numAliases);
    else
	con->aliases = realloc(con->aliases,
			       sizeof(newAlias) * con->numAliases);
    alias = con->aliases + aliasNum;

    *alias = newAlias;
    if (alias->longName)
	alias->longName = strcpy(malloc(strlen(alias->longName) + 1),
				    alias->longName);
    else
	alias->longName = NULL;

    return 0;
}

int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) {
    char * buf = strcpy(malloc(strlen(s) + 1), s);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -