comparison pkg-src/tree-x/input.c @ 163:0132846995bd r20-3b8

Import from CVS: tag r20-3b8
author cvs
date Mon, 13 Aug 2007 09:43:35 +0200
parents
children 85ec50267440
comparison
equal deleted inserted replaced
162:4de2936b4e77 163:0132846995bd
1 /* ----------------------------------------------------------------------------
2 * File : input.c
3 * Purpose : input routine to create a Tree from an input file
4 * ----------------------------------------------------------------------------
5 */
6
7 #include <ctype.h>
8 #include <string.h>
9 #include "defs.h"
10 #include "tree.h"
11 #include "input.h"
12
13 char *EnvNm; /* Stores name of current Envir file */
14 static int tokDepth = 0; /* Depth in tree of current token */
15 static int prevTokDepth; /* Depth in tree of prev token */
16
17 static void SaveSubtree();
18
19 /* ----------------------------------------------------------------------------
20 *
21 * GetNextToken() reads the next token from the file indicated by 'fp' and
22 * returns a token. If the token is TOKEN_LABEL, the lexeme is returned
23 * in 'lexeme'. If memory could not be allocated for 'lexeme', it is NULL.
24 *
25 * The following tokens are supported:
26 *
27 * - TOKEN_LABEL: a string of characters, up to 'TOKEN-MAXSIZ'
28 * characters, delimited by number of leading spaces and newlines.
29 * If a label has more than this number of characters, the rest are
30 * ignored.
31 * - TOKEN_EOF
32 *
33 * ----------------------------------------------------------------------------
34 */
35
36 int
37 GetNextToken(fp, lexeme)
38 FILE *fp;
39 char **lexeme;
40 {
41 static char lexbuf[INPUT_BUFSIZ];
42 register char *curbuf = lexbuf;
43 register int charct = 0;
44 register int c;
45 int done = FALSE;
46
47 prevTokDepth = tokDepth;
48 tokDepth = 0;
49
50 c = getc(fp);
51
52 /* skip over leading whitespace */
53 while (c == ' ')
54 {
55 tokDepth++;
56 c = getc(fp);
57 }
58 tokDepth /= 2;
59
60 while (1)
61 {
62 switch (c)
63 {
64 case EOF:
65 return (TOKEN_EOF);
66 case '\n':
67 *curbuf = '\0';
68 *lexeme = strdup(lexbuf);
69 return (TOKEN_LABEL);
70 break;
71 default:
72 *curbuf++ = c;
73 charct++;
74 /* check for buffer overflow */
75 if (charct >= TOKEN_MAXSIZ)
76 {
77 *curbuf = '\0';
78 *lexeme = strdup(lexbuf);
79 /* since buffer is full, skip over remaining chars */
80 c = getc(fp);
81 while (c != '\n' && c != EOF)
82 c = getc(fp);
83 if (c == EOF)
84 ungetc(c, fp);
85 return (TOKEN_LABEL);
86 }
87 else
88 c = getc(fp);
89 }
90 }
91 }
92
93
94 /* ----------------------------------------------------------------------------
95 *
96 * SetNodeLabelAndValue() sets the label text of the specified node and
97 * stores any string value following the label and preceded by a "^^"
98 * delimiter.
99 *
100 * ----------------------------------------------------------------------------
101 */
102
103 void
104 SetNodeLabelAndValue(node, label_and_value)
105 Tree *node;
106 char *label_and_value;
107 {
108 char* val;
109
110 if (val = strstr(label_and_value, "^^"))
111 {
112 /* Set node value to string following ^^ delimiter. */
113 node->value = val+2;
114 /* Erase value from input string, leaving only label. */
115 *val = '\0';
116 }
117 else
118 { node->value = NULL; }
119 SetNodeLabel(node, label_and_value);
120 }
121
122
123 /* ----------------------------------------------------------------------------
124 *
125 * ReadTreeFromFile() takes a filename argument and constructs
126 * a Tree from the labels in the file. If a tree could be constructed,
127 * even partially, it is returned by the function. NULL is returned if
128 * the file could not be opened or there was insufficient memory for
129 * creating the tree.
130 *
131 * ----------------------------------------------------------------------------
132 */
133
134 Tree*
135 ReadTreeFromFile(fname, error)
136 char *fname;
137 ErrCode *error;
138 {
139 FILE *infile;
140 int inside_list = 0; /* for semantic checking */
141 int first_child = TRUE;
142
143 int token;
144 char *label;
145
146 Tree *tree = NULL; /* the return value of this function */
147 Tree *parent = NULL; /* parent of 'node' */
148 Tree *node; /* current node */
149 Tree *new_node; /* new node to add after current node */
150
151 *error = ERR_NONE;
152
153 infile = fopen(fname, "r");
154 if (infile == NULL)
155 {
156 *error = ERR_OPENFAIL;
157 return (NULL);
158 }
159
160 /* first line of file is Envir file name, save */
161 token = GetNextToken(infile, &label);
162 if (token == TOKEN_EOF)
163 {
164 *error = ERR_EMPTYFILE;
165 fclose(infile);
166 return (NULL);
167 }
168 else if (token == TOKEN_LABEL)
169 {
170 if (label == NULL)
171 {
172 *error = ERR_MEMALLOC;
173 fclose(infile);
174 return (NULL);
175 }
176 EnvNm = strdup(label);
177 }
178
179 /* set up root node */
180 token = GetNextToken(infile, &label);
181 if (token == TOKEN_EOF)
182 {
183 *error = ERR_EMPTYFILE;
184 fclose(infile);
185 return (NULL);
186 }
187 else if (token == TOKEN_LABEL)
188 {
189 if (label == NULL)
190 {
191 *error = ERR_MEMALLOC;
192 fclose(infile);
193 return (NULL);
194 }
195 tree = MakeNode();
196 if (tree == NULL)
197 {
198 *error = ERR_MEMALLOC;
199 fclose(infile);
200 free(label);
201 return(NULL);
202 }
203 SetNodeLabelAndValue(tree, label);
204 tree->parent = NULL;
205 node = tree;
206 }
207 else
208 {
209 *error = ERR_NOROOT;
210 fclose(infile);
211 return (NULL);
212 }
213
214 /* add children and siblings */
215 while (1)
216 {
217 token = GetNextToken(infile, &label);
218 if (token == TOKEN_EOF)
219 break;
220
221 if (tokDepth > prevTokDepth) /* then new subtree */
222 {
223 inside_list++;
224 first_child = TRUE;
225 parent = node;
226 }
227 else if (tokDepth < prevTokDepth) /* then end of subtree */
228 if (!inside_list)
229 {
230 *error = ERR_NOBEGIN;
231 fclose(infile);
232 return (tree);
233 }
234 else
235 while (tokDepth < inside_list)
236 {
237 inside_list--;
238 node = node->parent;
239 parent = node->parent;
240 }
241
242 if (label == NULL)
243 {
244 *error = ERR_MEMALLOC;
245 fclose(infile);
246 return (tree);
247 }
248 if (parent == NULL)
249 {
250 *error = ERR_MANYROOT;
251 fclose(infile);
252 free(label);
253 return (tree);
254 }
255 else
256 {
257 new_node = MakeNode();
258 if (new_node == NULL)
259 {
260 *error = ERR_MEMALLOC;
261 fclose(infile);
262 free(label);
263 return (tree);
264 }
265 SetNodeLabelAndValue(new_node, label);
266 new_node->parent = parent;
267
268 if (first_child)
269 {
270 new_node->parent->child = new_node;
271 first_child = FALSE;
272 }
273 else
274 node->sibling = new_node;
275
276 node = new_node;
277 /*
278 * printf("%3d tok: '%s'; tokDepth: %d; prevTokDepth: %d; inside_list: %d\n",
279 * NumNodes, node->label.text, tokDepth, prevTokDepth, inside_list);
280 */
281 }
282 }
283 fclose(infile);
284 return (tree);
285 }
286
287
288 /* ----------------------------------------------------------------------------
289 *
290 * SaveTreeToFile() takes a tree and saves it to a file specified by 'fname.'
291 * If the file could not be opened for writing, False is returned. Otherwise,
292 * True is returned.
293 *
294 * ----------------------------------------------------------------------------
295 */
296
297 SaveTreeToFile(tree, fname)
298 Tree *tree;
299 char *fname;
300 {
301 FILE *outfile;
302
303 outfile = fopen(fname, "w");
304 if (outfile == NULL)
305 return (FALSE);
306
307 fprintf(outfile, "%s\n", EnvNm); /* Save Env File Name */
308 fprintf(outfile, "%s\n", tree->label.text);
309 if (tree->child)
310 SaveSubtree(tree->child, 0, outfile);
311
312 fclose(outfile);
313 return (TRUE);
314 }
315
316
317 /* ----------------------------------------------------------------------------
318 *
319 * SaveSubtree() is the recursive procedure that supports SaveTreeToFile().
320 *
321 * ----------------------------------------------------------------------------
322 */
323
324 static void
325 SaveSubtree(tree, level, fp)
326 Tree *tree;
327 int level;
328 FILE *fp;
329 {
330 int i;
331
332 level++;
333 for ( ; tree ; tree = tree->sibling)
334 {
335 for (i = 0 ; i < level ; i++)
336 {
337 putc(' ', fp);
338 putc(' ', fp);
339 }
340 fprintf(fp, "%s\n", tree->label.text);
341 if (tree->child)
342 SaveSubtree(tree->child, level, fp);
343 }
344 level--;
345 }
346
347