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