1 /* ----------------------------------------------------------------------------
3 * Purpose : input routine to create a Tree from an input file
4 * ----------------------------------------------------------------------------
7 /* SunOS 5.4+ way to ask for all functions in header files. */
8 #define __EXTENSIONS__ 1
19 char *EnvNm; /* Stores name of current Envir file */
20 static int tokDepth = 0; /* Depth in tree of current token */
21 static int prevTokDepth; /* Depth in tree of prev token */
23 static void SaveSubtree(Tree *tree, int level, FILE *fp);
25 /* ----------------------------------------------------------------------------
27 * GetNextToken() reads the next token from the file indicated by 'fp' and
28 * returns a token. If the token is TOKEN_LABEL, the lexeme is returned
29 * in 'lexeme'. If memory could not be allocated for 'lexeme', it is NULL.
31 * The following tokens are supported:
33 * - TOKEN_LABEL: a string of characters, up to 'TOKEN-MAXSIZ'
34 * characters, delimited by number of leading spaces and newlines.
35 * If a label has more than this number of characters, the rest are
39 * ----------------------------------------------------------------------------
43 GetNextToken(FILE *fp, char **lexeme)
45 static char lexbuf[INPUT_BUFSIZ];
46 register char *curbuf = lexbuf;
47 register int charct = 0;
50 prevTokDepth = tokDepth;
55 /* skip over leading whitespace */
71 *lexeme = strdup(lexbuf);
76 /* check for buffer overflow */
77 if (charct >= TOKEN_MAXSIZ)
80 *lexeme = strdup(lexbuf);
81 /* since buffer is full, skip over remaining chars */
83 while (c != '\n' && c != EOF)
96 /* ----------------------------------------------------------------------------
98 * SetNodeLabelAndValue() sets the label text of the specified node and
99 * stores any string value following the label and preceded by a "^^"
102 * ----------------------------------------------------------------------------
106 SetNodeLabelAndValue(Tree *node, char *label_and_value)
110 if ((val = strstr(label_and_value, "^^")))
112 /* Set node value to string following ^^ delimiter. */
114 /* Erase value from input string, leaving only label. */
118 { node->value = NULL; }
119 SetNodeLabel(node, label_and_value);
123 /* ----------------------------------------------------------------------------
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
131 * ----------------------------------------------------------------------------
135 ReadTreeFromFile(char *fname, ErrCode *error)
138 int inside_list = 0; /* for semantic checking */
139 int first_child = TRUE;
144 Tree *tree = NULL; /* the return value of this function */
145 Tree *parent = NULL; /* parent of 'node' */
146 Tree *node; /* current node */
147 Tree *new_node; /* new node to add after current node */
151 infile = fopen(fname, "r");
154 *error = ERR_OPENFAIL;
158 /* first line of file is Envir file name, save */
159 token = GetNextToken(infile, &label);
160 if (token == TOKEN_EOF)
162 *error = ERR_EMPTYFILE;
166 else if (token == TOKEN_LABEL)
170 *error = ERR_MEMALLOC;
174 EnvNm = strdup(label);
177 /* set up root node */
178 token = GetNextToken(infile, &label);
179 if (token == TOKEN_EOF)
181 *error = ERR_EMPTYFILE;
185 else if (token == TOKEN_LABEL)
189 *error = ERR_MEMALLOC;
196 *error = ERR_MEMALLOC;
201 SetNodeLabelAndValue(tree, label);
212 /* add children and siblings */
215 token = GetNextToken(infile, &label);
216 if (token == TOKEN_EOF)
219 if (tokDepth > prevTokDepth) /* then new subtree */
225 else if (tokDepth < prevTokDepth) /* then end of subtree */
228 *error = ERR_NOBEGIN;
233 while (tokDepth < inside_list)
237 parent = node->parent;
242 *error = ERR_MEMALLOC;
248 *error = ERR_MANYROOT;
255 new_node = MakeNode();
256 if (new_node == NULL)
258 *error = ERR_MEMALLOC;
263 SetNodeLabelAndValue(new_node, label);
264 new_node->parent = parent;
268 new_node->parent->child = new_node;
272 node->sibling = new_node;
276 * printf("%3d tok: '%s'; tokDepth: %d; prevTokDepth: %d; inside_list: %d\n",
277 * NumNodes, node->label.text, tokDepth, prevTokDepth, inside_list);
286 /* ----------------------------------------------------------------------------
288 * SaveTreeToFile() takes a tree and saves it to a file specified by 'fname.'
289 * If the file could not be opened for writing, False is returned. Otherwise,
292 * ----------------------------------------------------------------------------
296 SaveTreeToFile(Tree *tree, char *fname)
300 outfile = fopen(fname, "w");
304 fprintf(outfile, "%s\n", EnvNm); /* Save Env File Name */
305 fprintf(outfile, "%s\n", tree->label.text);
307 SaveSubtree(tree->child, 0, outfile);
314 /* ----------------------------------------------------------------------------
316 * SaveSubtree() is the recursive procedure that supports SaveTreeToFile().
318 * ----------------------------------------------------------------------------
322 SaveSubtree(Tree *tree, int level, FILE *fp)
327 for ( ; tree ; tree = tree->sibling)
329 for (i = 0 ; i < level ; i++)
334 fprintf(fp, "%s\n", tree->label.text);
336 SaveSubtree(tree->child, level, fp);