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