|
|
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.