]> git.zerfleddert.de Git - micropolis/blob - src/tcl/tclassem.c
Import Micropolis from http://www.donhopkins.com/home/micropolis/
[micropolis] / src / tcl / tclassem.c
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 \f
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 \f
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 \f
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 }
Impressum, Datenschutz