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