|
|
1.1 ! root 1: /* ! 2: * tclAssem.c -- ! 3: * ! 4: * This file contains procedures to help assemble Tcl commands ! 5: * from an input source where commands may arrive in pieces, e.g. ! 6: * several lines of type-in corresponding to one command. ! 7: * ! 8: * Copyright 1990-1991 Regents of the University of California ! 9: * Permission to use, copy, modify, and distribute this ! 10: * software and its documentation for any purpose and without ! 11: * fee is hereby granted, provided that the above copyright ! 12: * notice appear in all copies. The University of California ! 13: * makes no representations about the suitability of this ! 14: * software for any purpose. It is provided "as is" without ! 15: * express or implied warranty. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclAssem.c,v 1.9 92/07/02 09:14:05 ouster Exp $ SPRITE (Berkeley)"; ! 20: #endif /* not lint */ ! 21: ! 22: #include "tclint.h" ! 23: ! 24: /* ! 25: * The structure below is the internal representation for a command ! 26: * buffer, which is used to hold a piece of a command until a full ! 27: * command is available. When a full command is available, it will ! 28: * be returned to the user, but it will also be retained in the buffer ! 29: * until the NEXT call to Tcl_AssembleCmd, at which point it will be ! 30: * removed. ! 31: */ ! 32: ! 33: typedef struct { ! 34: char *buffer; /* Storage for command being assembled. ! 35: * Malloc-ed, and grows as needed. */ ! 36: int bufSize; /* Total number of bytes in buffer. */ ! 37: int bytesUsed; /* Number of bytes in buffer currently ! 38: * occupied (0 means there is not a ! 39: * buffered incomplete command). */ ! 40: } CmdBuf; ! 41: ! 42: /* ! 43: * Default amount of space to allocate in command buffer: ! 44: */ ! 45: ! 46: #define CMD_BUF_SIZE 100 ! 47: ! 48: /* ! 49: *---------------------------------------------------------------------- ! 50: * ! 51: * Tcl_CreateCmdBuf -- ! 52: * ! 53: * Allocate and initialize a command buffer. ! 54: * ! 55: * Results: ! 56: * The return value is a token that may be passed to ! 57: * Tcl_AssembleCmd and Tcl_DeleteCmdBuf. ! 58: * ! 59: * Side effects: ! 60: * Memory is allocated. ! 61: * ! 62: *---------------------------------------------------------------------- ! 63: */ ! 64: ! 65: Tcl_CmdBuf ! 66: Tcl_CreateCmdBuf() ! 67: { ! 68: register CmdBuf *cbPtr; ! 69: ! 70: cbPtr = (CmdBuf *) ckalloc(sizeof(CmdBuf)); ! 71: cbPtr->buffer = (char *) ckalloc(CMD_BUF_SIZE); ! 72: cbPtr->buffer[0] = '\0'; ! 73: cbPtr->bufSize = CMD_BUF_SIZE; ! 74: cbPtr->bytesUsed = 0; ! 75: return (Tcl_CmdBuf) cbPtr; ! 76: } ! 77: ! 78: /* ! 79: *---------------------------------------------------------------------- ! 80: * ! 81: * Tcl_DeleteCmdBuf -- ! 82: * ! 83: * Release all of the resources associated with a command buffer. ! 84: * The caller should never again use buffer again. ! 85: * ! 86: * Results: ! 87: * None. ! 88: * ! 89: * Side effects: ! 90: * Memory is released. ! 91: * ! 92: *---------------------------------------------------------------------- ! 93: */ ! 94: ! 95: void ! 96: Tcl_DeleteCmdBuf(buffer) ! 97: Tcl_CmdBuf buffer; /* Token for command buffer (return value ! 98: * from previous call to Tcl_CreateCmdBuf). */ ! 99: { ! 100: register CmdBuf *cbPtr = (CmdBuf *) buffer; ! 101: ! 102: ckfree(cbPtr->buffer); ! 103: ckfree((char *) cbPtr); ! 104: } ! 105: ! 106: /* ! 107: *---------------------------------------------------------------------- ! 108: * ! 109: * Tcl_AssembleCmd -- ! 110: * ! 111: * This is a utility procedure to assist in situations where ! 112: * commands may be read piece-meal from some input source. Given ! 113: * some input text, it adds the text to an input buffer and returns ! 114: * whole commands when they are ready. ! 115: * ! 116: * Results: ! 117: * If the addition of string to any currently-buffered information ! 118: * results in one or more complete Tcl commands, then the return value ! 119: * is a pointer to the complete command(s). The command value will ! 120: * only be valid until the next call to this procedure with the ! 121: * same buffer. If the addition of string leaves an incomplete ! 122: * command at the end of the buffer, then NULL is returned. ! 123: * ! 124: * Side effects: ! 125: * If string leaves a command incomplete, the partial command ! 126: * information is buffered for use in later calls to this procedure. ! 127: * Once a command has been returned, that command is deleted from ! 128: * the buffer on the next call to this procedure. ! 129: * ! 130: *---------------------------------------------------------------------- ! 131: */ ! 132: ! 133: char * ! 134: Tcl_AssembleCmd(buffer, string) ! 135: Tcl_CmdBuf buffer; /* Token for a command buffer previously ! 136: * created by Tcl_CreateCmdBuf. */ ! 137: char *string; /* Bytes to be appended to command stream. ! 138: * Note: if the string is zero length, ! 139: * then whatever is buffered will be ! 140: * considered to be a complete command ! 141: * regardless of whether parentheses are ! 142: * matched or not. */ ! 143: { ! 144: register CmdBuf *cbPtr = (CmdBuf *) buffer; ! 145: int length, totalLength; ! 146: register char *p; ! 147: ! 148: /* ! 149: * If an empty string is passed in, just pretend the current ! 150: * command is complete, whether it really is or not. ! 151: */ ! 152: ! 153: length = strlen(string); ! 154: if (length == 0) { ! 155: cbPtr->bytesUsed = 0; ! 156: return cbPtr->buffer; ! 157: } ! 158: ! 159: /* ! 160: * Add the new information to the buffer. If the current buffer ! 161: * isn't large enough, grow it by at least a factor of two, or ! 162: * enough to hold the new text. ! 163: */ ! 164: ! 165: length = strlen(string); ! 166: totalLength = cbPtr->bytesUsed + length + 1; ! 167: if (totalLength > cbPtr->bufSize) { ! 168: unsigned int newSize; ! 169: char *newBuf; ! 170: ! 171: newSize = cbPtr->bufSize*2; ! 172: if (newSize < totalLength) { ! 173: newSize = totalLength; ! 174: } ! 175: newBuf = (char *) ckalloc(newSize); ! 176: strcpy(newBuf, cbPtr->buffer); ! 177: ckfree(cbPtr->buffer); ! 178: cbPtr->buffer = newBuf; ! 179: cbPtr->bufSize = newSize; ! 180: } ! 181: strcpy(cbPtr->buffer+cbPtr->bytesUsed, string); ! 182: cbPtr->bytesUsed += length; ! 183: ! 184: /* ! 185: * See if there is now a complete command in the buffer. ! 186: */ ! 187: ! 188: p = cbPtr->buffer; ! 189: while (1) { ! 190: int gotNewLine = 0; ! 191: ! 192: while (isspace(*p)) { ! 193: if (*p == '\n') { ! 194: gotNewLine = 1; ! 195: } ! 196: p++; ! 197: } ! 198: if (*p == 0) { ! 199: if (gotNewLine) { ! 200: cbPtr->bytesUsed = 0; ! 201: return cbPtr->buffer; ! 202: } ! 203: return NULL; ! 204: } ! 205: p = TclWordEnd(p, 0); ! 206: } ! 207: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.