Ejemplo n.º 1
0
Archivo: tkOption.c Proyecto: das/tcltk
static int
AddFromString(
    Tcl_Interp *interp,		/* Interpreter to use for reporting results. */
    Tk_Window tkwin,		/* Token for window: options are entered for
				 * this window's main window. */
    char *string,		/* String containing option specifiers. */
    int priority)		/* Priority level to use for options in this
				 * string, such as TK_USER_DEFAULT_PRIO or
				 * TK_INTERACTIVE_PRIO. Must be between 0 and
				 * TK_MAX_PRIO. */
{
    register char *src, *dst;
    char *name, *value;
    int lineNum;

    src = string;
    lineNum = 1;
    while (1) {
	/*
	 * Skip leading white space and empty lines and comment lines, and
	 * check for the end of the spec.
	 */

	while ((*src == ' ') || (*src == '\t')) {
	    src++;
	}
	if ((*src == '#') || (*src == '!')) {
	    do {
		src++;
		if ((src[0] == '\\') && (src[1] == '\n')) {
		    src += 2;
		    lineNum++;
		}
	    } while ((*src != '\n') && (*src != 0));
	}
	if (*src == '\n') {
	    src++;
	    lineNum++;
	    continue;
	}
	if (*src == '\0') {
	    break;
	}

	/*
	 * Parse off the option name, collapsing out backslash-newline
	 * sequences of course.
	 */

	dst = name = src;
	while (*src != ':') {
	    if ((*src == '\0') || (*src == '\n')) {
		char buf[32 + TCL_INTEGER_SPACE];

		sprintf(buf, "missing colon on line %d", lineNum);
		Tcl_SetResult(interp, buf, TCL_VOLATILE);
		return TCL_ERROR;
	    }
	    if ((src[0] == '\\') && (src[1] == '\n')) {
		src += 2;
		lineNum++;
	    } else {
		*dst = *src;
		dst++;
		src++;
	    }
	}

	/*
	 * Eliminate trailing white space on the name, and null-terminate
	 * it.
	 */

	while ((dst != name) && ((dst[-1] == ' ') || (dst[-1] == '\t'))) {
	    dst--;
	}
	*dst = '\0';

	/*
	 * Skip white space between the name and the value.
	 */

	src++;
	while ((*src == ' ') || (*src == '\t')) {
	    src++;
	}
	if (*src == '\0') {
	    char buf[32 + TCL_INTEGER_SPACE];

	    sprintf(buf, "missing value on line %d", lineNum);
	    Tcl_SetResult(interp, buf, TCL_VOLATILE);
	    return TCL_ERROR;
	}

	/*
	 * Parse off the value, squeezing out backslash-newline sequences
	 * along the way.
	 */

	dst = value = src;
	while (*src != '\n') {
	    if (*src == '\0') {
		char buf[32 + TCL_INTEGER_SPACE];

		sprintf(buf, "missing newline on line %d", lineNum);
		Tcl_SetResult(interp, buf, TCL_VOLATILE);
		return TCL_ERROR;
	    }
	    if ((src[0] == '\\') && (src[1] == '\n')) {
		src += 2;
		lineNum++;
	    } else {
		*dst = *src;
		dst++;
		src++;
	    }
	}
	*dst = 0;

	/*
	 * Enter the option into the database.
	 */

	Tk_AddOption(tkwin, name, value, priority);
	src++;
	lineNum++;
    }
    return TCL_OK;
}
Ejemplo n.º 2
0
int
Tk_ParseArgv(
    Tcl_Interp *interp,		/* Place to store error message. */
    Tk_Window tkwin,		/* Window to use for setting Tk options. NULL
				 * means ignore Tk option specs. */
    int *argcPtr,		/* Number of arguments in argv. Modified to
				 * hold # args left in argv at end. */
    CONST char **argv,		/* Array of arguments. Modified to hold those
				 * that couldn't be processed here. */
    Tk_ArgvInfo *argTable,	/* Array of option descriptions */
    int flags)			/* Or'ed combination of various flag bits,
				 * such as TK_ARGV_NO_DEFAULTS. */
{
    register Tk_ArgvInfo *infoPtr;
				/* Pointer to the current entry in the table
				 * of argument descriptions. */
    Tk_ArgvInfo *matchPtr;	/* Descriptor that matches current argument. */
    CONST char *curArg;		/* Current argument */
    register char c;		/* Second character of current arg (used for
				 * quick check for matching; use 2nd char.
				 * because first char. will almost always be
				 * '-'). */
    int srcIndex;		/* Location from which to read next argument
				 * from argv. */
    int dstIndex;		/* Index into argv to which next unused
				 * argument should be copied (never greater
				 * than srcIndex). */
    int argc;			/* # arguments in argv still to process. */
    size_t length;		/* Number of characters in current argument. */
    int i;

    if (flags & TK_ARGV_DONT_SKIP_FIRST_ARG) {
	srcIndex = dstIndex = 0;
	argc = *argcPtr;
    } else {
	srcIndex = dstIndex = 1;
	argc = *argcPtr-1;
    }

    while (argc > 0) {
	curArg = argv[srcIndex];
	srcIndex++;
	argc--;
	length = strlen(curArg);
	if (length > 0) {
	    c = curArg[1];
	} else {
	    c = 0;
	}

	/*
	 * Loop throught the argument descriptors searching for one with the
	 * matching key string. If found, leave a pointer to it in matchPtr.
	 */

	matchPtr = NULL;
	for (i = 0; i < 2; i++) {
	    if (i == 0) {
		infoPtr = argTable;
	    } else {
		infoPtr = defaultTable;
	    }
	    for (; (infoPtr != NULL) && (infoPtr->type != TK_ARGV_END);
		    infoPtr++) {
		if (infoPtr->key == NULL) {
		    continue;
		}
		if ((infoPtr->key[1] != c)
			|| (strncmp(infoPtr->key, curArg, length) != 0)) {
		    continue;
		}
		if ((tkwin == NULL)
			&& ((infoPtr->type == TK_ARGV_CONST_OPTION)
			|| (infoPtr->type == TK_ARGV_OPTION_VALUE)
			|| (infoPtr->type == TK_ARGV_OPTION_NAME_VALUE))) {
		    continue;
		}
		if (infoPtr->key[length] == 0) {
		    matchPtr = infoPtr;
		    goto gotMatch;
		}
		if (flags & TK_ARGV_NO_ABBREV) {
		    continue;
		}
		if (matchPtr != NULL) {
		    Tcl_AppendResult(interp, "ambiguous option \"", curArg,
			    "\"", NULL);
		    return TCL_ERROR;
		}
		matchPtr = infoPtr;
	    }
	}
	if (matchPtr == NULL) {
	    /*
	     * Unrecognized argument. Just copy it down, unless the caller
	     * prefers an error to be registered.
	     */

	    if (flags & TK_ARGV_NO_LEFTOVERS) {
		Tcl_AppendResult(interp, "unrecognized argument \"",
			curArg, "\"", NULL);
		return TCL_ERROR;
	    }
	    argv[dstIndex] = curArg;
	    dstIndex++;
	    continue;
	}

	/*
	 * Take the appropriate action based on the option type
	 */

    gotMatch:
	infoPtr = matchPtr;
	switch (infoPtr->type) {
	case TK_ARGV_CONSTANT:
	    *((int *) infoPtr->dst) = PTR2INT(infoPtr->src);
	    break;
	case TK_ARGV_INT:
	    if (argc == 0) {
		goto missingArg;
	    } else {
		char *endPtr;

		*((int *) infoPtr->dst) = strtol(argv[srcIndex], &endPtr, 0);
		if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
		    Tcl_AppendResult(interp,"expected integer argument for \"",
			    infoPtr->key, "\" but got \"", argv[srcIndex],
			    "\"", NULL);
		    return TCL_ERROR;
		}
		srcIndex++;
		argc--;
	    }
	    break;
	case TK_ARGV_STRING:
	    if (argc == 0) {
		goto missingArg;
	    }
	    *((CONST char **)infoPtr->dst) = argv[srcIndex];
	    srcIndex++;
	    argc--;
	    break;
	case TK_ARGV_UID:
	    if (argc == 0) {
		goto missingArg;
	    }
	    *((Tk_Uid *)infoPtr->dst) = Tk_GetUid(argv[srcIndex]);
	    srcIndex++;
	    argc--;
	    break;
	case TK_ARGV_REST:
	    *((int *) infoPtr->dst) = dstIndex;
	    goto argsDone;
	case TK_ARGV_FLOAT:
	    if (argc == 0) {
		goto missingArg;
	    } else {
		char *endPtr;

		*((double *) infoPtr->dst) = strtod(argv[srcIndex], &endPtr);
		if ((endPtr == argv[srcIndex]) || (*endPtr != 0)) {
		    Tcl_AppendResult(interp, "expected floating-point ",
			    "argument for \"", infoPtr->key, "\" but got \"",
			    argv[srcIndex], "\"", NULL);
		    return TCL_ERROR;
		}
		srcIndex++;
		argc--;
	    }
	    break;
	case TK_ARGV_FUNC: {
	    typedef int (ArgvFunc)(char *, char *, CONST char *);
	    ArgvFunc *handlerProc = (ArgvFunc *) infoPtr->src;

	    if ((*handlerProc)(infoPtr->dst, infoPtr->key, argv[srcIndex])) {
		srcIndex++;
		argc--;
	    }
	    break;
	}
	case TK_ARGV_GENFUNC: {
	    typedef int (ArgvGenFunc)(char *, Tcl_Interp *, char *, int,
		    CONST char **);
	    ArgvGenFunc *handlerProc = (ArgvGenFunc *) infoPtr->src;

	    argc = (*handlerProc)(infoPtr->dst, interp, infoPtr->key,
		    argc, argv+srcIndex);
	    if (argc < 0) {
		return TCL_ERROR;
	    }
	    break;
	}
	case TK_ARGV_HELP:
	    PrintUsage(interp, argTable, flags);
	    return TCL_ERROR;
	case TK_ARGV_CONST_OPTION:
	    Tk_AddOption(tkwin, infoPtr->dst, infoPtr->src,
		    TK_INTERACTIVE_PRIO);
	    break;
	case TK_ARGV_OPTION_VALUE:
	    if (argc < 1) {
		goto missingArg;
	    }
	    Tk_AddOption(tkwin, infoPtr->dst, argv[srcIndex],
		    TK_INTERACTIVE_PRIO);
	    srcIndex++;
	    argc--;
	    break;
	case TK_ARGV_OPTION_NAME_VALUE:
	    if (argc < 2) {
		Tcl_AppendResult(interp, "\"", curArg,
			"\" option requires two following arguments", NULL);
		return TCL_ERROR;
	    }
	    Tk_AddOption(tkwin, argv[srcIndex], argv[srcIndex+1],
		    TK_INTERACTIVE_PRIO);
	    srcIndex += 2;
	    argc -= 2;
	    break;
	default: {
	    char buf[64 + TCL_INTEGER_SPACE];

	    sprintf(buf, "bad argument type %d in Tk_ArgvInfo", infoPtr->type);
	    Tcl_SetResult(interp, buf, TCL_VOLATILE);
	    return TCL_ERROR;
	}
	}
    }

    /*
     * If we broke out of the loop because of an OPT_REST argument, copy the
     * remaining arguments down.
     */

  argsDone:
    while (argc) {
	argv[dstIndex] = argv[srcIndex];
	srcIndex++;
	dstIndex++;
	argc--;
    }
    argv[dstIndex] = NULL;
    *argcPtr = dstIndex;
    return TCL_OK;

  missingArg:
    Tcl_AppendResult(interp, "\"", curArg,
	    "\" option requires an additional argument", NULL);
    return TCL_ERROR;
}
Ejemplo n.º 3
0
Archivo: tkOption.c Proyecto: das/tcltk
int
Tk_OptionObjCmd(
    ClientData clientData,	/* Main window associated with interpreter. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of Tcl_Obj arguments. */
    Tcl_Obj *const objv[])	/* Tcl_Obj arguments. */
{
    Tk_Window tkwin = clientData;
    int index, result;
    ThreadSpecificData *tsdPtr =
	    Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));

    static const char *const optionCmds[] = {
	"add", "clear", "get", "readfile", NULL
    };

    enum optionVals {
	OPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "cmd arg ?arg ...?");
	return TCL_ERROR;
    }

    result = Tcl_GetIndexFromObj(interp, objv[1], optionCmds, "option", 0,
	    &index);
    if (result != TCL_OK) {
	return result;
    }

    result = TCL_OK;
    switch ((enum optionVals) index) {
    case OPTION_ADD: {
	int priority;

	if ((objc != 4) && (objc != 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?");
	    return TCL_ERROR;
	}

	if (objc == 4) {
	    priority = TK_INTERACTIVE_PRIO;
	} else {
	    priority = ParsePriority(interp, Tcl_GetString(objv[4]));
	    if (priority < 0) {
		return TCL_ERROR;
	    }
	}
	Tk_AddOption(tkwin, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]),
		priority);
	break;
    }

    case OPTION_CLEAR: {
	TkMainInfo *mainPtr;

	if (objc != 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, "");
	    return TCL_ERROR;
	}
	mainPtr = ((TkWindow *) tkwin)->mainPtr;
	if (mainPtr->optionRootPtr != NULL) {
	    ClearOptionTree(mainPtr->optionRootPtr);
	    mainPtr->optionRootPtr = NULL;
	}
	tsdPtr->cachedWindow = NULL;
	break;
    }

    case OPTION_GET: {
	Tk_Window window;
	Tk_Uid value;

	if (objc != 5) {
	    Tcl_WrongNumArgs(interp, 2, objv, "window name class");
	    return TCL_ERROR;
	}
	window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
	if (window == NULL) {
	    return TCL_ERROR;
	}
	value = Tk_GetOption(window, Tcl_GetString(objv[3]),
		Tcl_GetString(objv[4]));
	if (value != NULL) {
	    Tcl_SetResult(interp, (char *) value, TCL_STATIC);
	}
	break;
    }

    case OPTION_READFILE: {
	int priority;

	if ((objc != 3) && (objc != 4)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?");
	    return TCL_ERROR;
	}

	if (objc == 4) {
	    priority = ParsePriority(interp, Tcl_GetString(objv[3]));
	    if (priority < 0) {
		return TCL_ERROR;
	    }
	} else {
	    priority = TK_INTERACTIVE_PRIO;
	}
	result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]),
		priority);
	break;
    }
    }
    return result;
}