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

📄 tclparse.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * tclParse.c -- * *	This file contains a collection of procedures that are used *	to parse Tcl commands or parts of commands (like quoted *	strings or nested sub-commands). * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclParse.c 1.56 97/07/29 18:40:03 */#include "tclInt.h"#include "tclPort.h"/* * Function prototypes for procedures local to this file: */static char *	QuoteEnd _ANSI_ARGS_((char *string, char *lastChar,		    int term));static char *	ScriptEnd _ANSI_ARGS_((char *p, char *lastChar,		    int nested));static char *	VarNameEnd _ANSI_ARGS_((char *string,  char *lastChar));/* *-------------------------------------------------------------- * * TclParseQuotes -- * *	This procedure parses a double-quoted string such as a *	quoted Tcl command argument or a quoted value in a Tcl *	expression.  This procedure is also used to parse array *	element names within parentheses, or anything else that *	needs all the substitutions that happen in quotes. * * Results: *	The return value is a standard Tcl result, which is *	TCL_OK unless there was an error while parsing the *	quoted string.  If an error occurs then interp->result *	contains a standard error message.  *TermPtr is filled *	in with the address of the character just after the *	last one successfully processed;  this is usually the *	character just after the matching close-quote.  The *	fully-substituted contents of the quotes are stored in *	standard fashion in *pvPtr, null-terminated with *	pvPtr->next pointing to the terminating null character. * * Side effects: *	The buffer space in pvPtr may be enlarged by calling its *	expandProc. * *-------------------------------------------------------------- */intTclParseQuotes(interp, string, termChar, flags, termPtr, pvPtr)    Tcl_Interp *interp;		/* Interpreter to use for nested command				 * evaluations and error messages. */    char *string;		/* Character just after opening double-				 * quote. */    int termChar;		/* Character that terminates "quoted" string				 * (usually double-quote, but sometimes				 * right-paren or something else). */    int flags;			/* Flags to pass to nested Tcl_Eval calls. */    char **termPtr;		/* Store address of terminating character				 * here. */    ParseValue *pvPtr;		/* Information about where to place				 * fully-substituted result of parse. */{    register char *src, *dst, c;    char *lastChar = string + strlen(string);    src = string;    dst = pvPtr->next;    while (1) {	if (dst == pvPtr->end) {	    /*	     * Target buffer space is about to run out.  Make more space.	     */	    pvPtr->next = dst;	    (*pvPtr->expandProc)(pvPtr, 1);	    dst = pvPtr->next;	}	c = *src;	src++;	if (c == termChar) {	    *dst = '\0';	    pvPtr->next = dst;	    *termPtr = src;	    return TCL_OK;	} else if (CHAR_TYPE(src-1, lastChar) == TCL_NORMAL) {	    copy:	    *dst = c;	    dst++;	    continue;	} else if (c == '$') {	    int length;	    char *value;	    value = Tcl_ParseVar(interp, src-1, termPtr);	    if (value == NULL) {		return TCL_ERROR;	    }	    src = *termPtr;	    length = strlen(value);	    if ((pvPtr->end - dst) <= length) {		pvPtr->next = dst;		(*pvPtr->expandProc)(pvPtr, length);		dst = pvPtr->next;	    }	    strcpy(dst, value);	    dst += length;	    continue;	} else if (c == '[') {	    int result;	    pvPtr->next = dst;	    result = TclParseNestedCmd(interp, src, flags, termPtr, pvPtr);	    if (result != TCL_OK) {		return result;	    }	    src = *termPtr;	    dst = pvPtr->next;	    continue;	} else if (c == '\\') {	    int numRead;	    src--;	    *dst = Tcl_Backslash(src, &numRead);	    dst++;	    src += numRead;	    continue;	} else if (c == '\0') {	    char buf[30];	    	    Tcl_ResetResult(interp);	    sprintf(buf, "missing %c", termChar);	    Tcl_SetResult(interp, buf, TCL_VOLATILE);	    *termPtr = string-1;	    return TCL_ERROR;	} else {	    goto copy;	}    }}/* *-------------------------------------------------------------- * * TclParseNestedCmd -- * *	This procedure parses a nested Tcl command between *	brackets, returning the result of the command. * * Results: *	The return value is a standard Tcl result, which is *	TCL_OK unless there was an error while executing the *	nested command.  If an error occurs then interp->result *	contains a standard error message.  *TermPtr is filled *	in with the address of the character just after the *	last one processed;  this is usually the character just *	after the matching close-bracket, or the null character *	at the end of the string if the close-bracket was missing *	(a missing close bracket is an error).  The result returned *	by the command is stored in standard fashion in *pvPtr, *	null-terminated, with pvPtr->next pointing to the null *	character. * * Side effects: *	The storage space at *pvPtr may be expanded. * *-------------------------------------------------------------- */intTclParseNestedCmd(interp, string, flags, termPtr, pvPtr)    Tcl_Interp *interp;		/* Interpreter to use for nested command				 * evaluations and error messages. */    char *string;		/* Character just after opening bracket. */    int flags;			/* Flags to pass to nested Tcl_Eval. */    char **termPtr;		/* Store address of terminating character				 * here. */    register ParseValue *pvPtr;	/* Information about where to place				 * result of command. */{    int result, length, shortfall;    Interp *iPtr = (Interp *) interp;    iPtr->evalFlags = flags | TCL_BRACKET_TERM;    result = Tcl_Eval(interp, string);    *termPtr = (string + iPtr->termOffset);    if (result != TCL_OK) {	/*	 * The increment below results in slightly cleaner message in	 * the errorInfo variable (the close-bracket will appear).	 */	if (**termPtr == ']') {	    *termPtr += 1;	}	return result;    }    (*termPtr) += 1;    length = strlen(iPtr->result);    shortfall = length + 1 - (pvPtr->end - pvPtr->next);    if (shortfall > 0) {	(*pvPtr->expandProc)(pvPtr, shortfall);    }    strcpy(pvPtr->next, iPtr->result);    pvPtr->next += length;        Tcl_FreeResult(interp);    iPtr->result = iPtr->resultSpace;    iPtr->resultSpace[0] = '\0';    return TCL_OK;}/* *-------------------------------------------------------------- * * TclParseBraces -- * *	This procedure scans the information between matching *	curly braces. * * Results: *	The return value is a standard Tcl result, which is *	TCL_OK unless there was an error while parsing string. *	If an error occurs then interp->result contains a *	standard error message.  *TermPtr is filled *	in with the address of the character just after the *	last one successfully processed;  this is usually the *	character just after the matching close-brace.  The *	information between curly braces is stored in standard *	fashion in *pvPtr, null-terminated with pvPtr->next *	pointing to the terminating null character. * * Side effects: *	The storage space at *pvPtr may be expanded. * *-------------------------------------------------------------- */intTclParseBraces(interp, string, termPtr, pvPtr)    Tcl_Interp *interp;		/* Interpreter to use for nested command				 * evaluations and error messages. */    char *string;		/* Character just after opening bracket. */    char **termPtr;		/* Store address of terminating character				 * here. */    register ParseValue *pvPtr;	/* Information about where to place				 * result of command. */{    int level;    register char *src, *dst, *end;    register char c;    char *lastChar = string + strlen(string);    src = string;    dst = pvPtr->next;    end = pvPtr->end;    level = 1;    /*     * Copy the characters one at a time to the result area, stopping     * when the matching close-brace is found.     */    while (1) {	c = *src;	src++;	if (dst == end) {	    pvPtr->next = dst;	    (*pvPtr->expandProc)(pvPtr, 20);	    dst = pvPtr->next;	    end = pvPtr->end;	}	*dst = c;	dst++;	if (CHAR_TYPE(src-1, lastChar) == TCL_NORMAL) {	    continue;	} else if (c == '{') {	    level++;	} else if (c == '}') {	    level--;	    if (level == 0) {		dst--;			/* Don't copy the last close brace. */		break;	    }	} else if (c == '\\') {	    int count;	    /*	     * Must always squish out backslash-newlines, even when in	     * braces.  This is needed so that this sequence can appear	     * anywhere in a command, such as the middle of an expression.	     */	    if (*src == '\n') {		dst[-1] = Tcl_Backslash(src-1, &count);		src += count - 1;	    } else {		(void) Tcl_Backslash(src-1, &count);		while (count > 1) {                    if (dst == end) {                        pvPtr->next = dst;                        (*pvPtr->expandProc)(pvPtr, 20);                        dst = pvPtr->next;                        end = pvPtr->end;                    }		    *dst = *src;		    dst++;		    src++;		    count--;		}	    }	} else if (c == '\0') {	    Tcl_SetResult(interp, "missing close-brace", TCL_STATIC);	    *termPtr = string-1;	    return TCL_ERROR;	}    }    *dst = '\0';    pvPtr->next = dst;    *termPtr = src;    return TCL_OK;}/* *-------------------------------------------------------------- * * TclExpandParseValue -- * *	This procedure is commonly used as the value of the *	expandProc in a ParseValue.  It uses malloc to allocate *	more space for the result of a parse. * * Results: *	The buffer space in *pvPtr is reallocated to something *	larger, and if pvPtr->clientData is non-zero the old *	buffer is freed.  Information is copied from the old *	buffer to the new one. * * Side effects: *	None. * *-------------------------------------------------------------- */voidTclExpandParseValue(pvPtr, needed)    register ParseValue *pvPtr;		/* Information about buffer that					 * must be expanded.  If the clientData					 * in the structure is non-zero, it					 * means that the current buffer is					 * dynamically allocated. */    int needed;				/* Minimum amount of additional space					 * to allocate. */{    int newSpace;    char *new;    /*     * Either double the size of the buffer or add enough new space     * to meet the demand, whichever produces a larger new buffer.     */    newSpace = (pvPtr->end - pvPtr->buffer) + 1;    if (newSpace < needed) {	newSpace += needed;    } else {	newSpace += newSpace;    }    new = (char *) ckalloc((unsigned) newSpace);    /*     * Copy from old buffer to new, free old buffer if needed, and     * mark new buffer as malloc-ed.     */    memcpy((VOID *) new, (VOID *) pvPtr->buffer,	    (size_t) (pvPtr->next - pvPtr->buffer));    pvPtr->next = new + (pvPtr->next - pvPtr->buffer);    if (pvPtr->clientData != 0) {	ckfree(pvPtr->buffer);    }    pvPtr->buffer = new;    pvPtr->end = new + newSpace - 1;    pvPtr->clientData = (ClientData) 1;}/* *---------------------------------------------------------------------- * * TclWordEnd -- * *	Given a pointer into a Tcl command, find the end of the next *	word of the command. * * Results: *	The return value is a pointer to the last character that's part *	of the word pointed to by "start".  If the word doesn't end *	properly within the string then the return value is the address *	of the null character at the end of the string. * * Side effects: *	None. * *---------------------------------------------------------------------- */char *TclWordEnd(start, lastChar, nested, semiPtr)    char *start;		/* Beginning of a word of a Tcl command. */    char *lastChar;		/* Terminating character in string. */    int nested;			/* Zero means this is a top-level command.				 * One means this is a nested command (close				 * bracket is a word terminator). */    int *semiPtr;		/* Set to 1 if word ends with a command-				 * terminating semi-colon, zero otherwise.				 * If NULL then ignored. */{    register char *p;    int count;    if (semiPtr != NULL) {	*semiPtr = 0;    }    /*     * Skip leading white space (backslash-newline must be treated like     * white-space, except that it better not be the last thing in the     * command).     */    for (p = start; ; p++) {	if (isspace(UCHAR(*p))) {	    continue;	}	if ((p[0] == '\\') && (p[1] == '\n')) {	    if (p+2 == lastChar) {		return p+2;	    }	    continue;	}	break;    }    /*     * Handle words beginning with a double-quote or a brace.     */    if (*p == '"') {	p = QuoteEnd(p+1, lastChar, '"');	if (p == lastChar) {	    return p;	}	p++;    } else if (*p == '{') {	int braces = 1;	while (braces != 0) {

⌨️ 快捷键说明

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