Mercurial > hg > xemacs-beta
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg-src/tree-x/input.c Mon Aug 13 09:43:35 2007 +0200 @@ -0,0 +1,347 @@ +/* ---------------------------------------------------------------------------- + * File : input.c + * Purpose : input routine to create a Tree from an input file + * ---------------------------------------------------------------------------- + */ + +#include <ctype.h> +#include <string.h> +#include "defs.h" +#include "tree.h" +#include "input.h" + +char *EnvNm; /* Stores name of current Envir file */ +static int tokDepth = 0; /* Depth in tree of current token */ +static int prevTokDepth; /* Depth in tree of prev token */ + +static void SaveSubtree(); + +/* ---------------------------------------------------------------------------- + * + * GetNextToken() reads the next token from the file indicated by 'fp' and + * returns a token. If the token is TOKEN_LABEL, the lexeme is returned + * in 'lexeme'. If memory could not be allocated for 'lexeme', it is NULL. + * + * The following tokens are supported: + * + * - TOKEN_LABEL: a string of characters, up to 'TOKEN-MAXSIZ' + * characters, delimited by number of leading spaces and newlines. + * If a label has more than this number of characters, the rest are + * ignored. + * - TOKEN_EOF + * + * ---------------------------------------------------------------------------- + */ + +int + GetNextToken(fp, lexeme) +FILE *fp; +char **lexeme; +{ + static char lexbuf[INPUT_BUFSIZ]; + register char *curbuf = lexbuf; + register int charct = 0; + register int c; + int done = FALSE; + + prevTokDepth = tokDepth; + tokDepth = 0; + + c = getc(fp); + + /* skip over leading whitespace */ + while (c == ' ') + { + tokDepth++; + c = getc(fp); + } + tokDepth /= 2; + + while (1) + { + switch (c) + { + case EOF: + return (TOKEN_EOF); + case '\n': + *curbuf = '\0'; + *lexeme = strdup(lexbuf); + return (TOKEN_LABEL); + break; + default: + *curbuf++ = c; + charct++; + /* check for buffer overflow */ + if (charct >= TOKEN_MAXSIZ) + { + *curbuf = '\0'; + *lexeme = strdup(lexbuf); + /* since buffer is full, skip over remaining chars */ + c = getc(fp); + while (c != '\n' && c != EOF) + c = getc(fp); + if (c == EOF) + ungetc(c, fp); + return (TOKEN_LABEL); + } + else + c = getc(fp); + } + } +} + + +/* ---------------------------------------------------------------------------- + * + * SetNodeLabelAndValue() sets the label text of the specified node and + * stores any string value following the label and preceded by a "^^" + * delimiter. + * + * ---------------------------------------------------------------------------- + */ + +void +SetNodeLabelAndValue(node, label_and_value) + Tree *node; + char *label_and_value; +{ + char* val; + + if (val = strstr(label_and_value, "^^")) + { + /* Set node value to string following ^^ delimiter. */ + node->value = val+2; + /* Erase value from input string, leaving only label. */ + *val = '\0'; + } + else + { node->value = NULL; } + SetNodeLabel(node, label_and_value); +} + + +/* ---------------------------------------------------------------------------- + * + * ReadTreeFromFile() takes a filename argument and constructs + * a Tree from the labels in the file. If a tree could be constructed, + * even partially, it is returned by the function. NULL is returned if + * the file could not be opened or there was insufficient memory for + * creating the tree. + * + * ---------------------------------------------------------------------------- + */ + +Tree* + ReadTreeFromFile(fname, error) +char *fname; +ErrCode *error; +{ + FILE *infile; + int inside_list = 0; /* for semantic checking */ + int first_child = TRUE; + + int token; + char *label; + + Tree *tree = NULL; /* the return value of this function */ + Tree *parent = NULL; /* parent of 'node' */ + Tree *node; /* current node */ + Tree *new_node; /* new node to add after current node */ + + *error = ERR_NONE; + + infile = fopen(fname, "r"); + if (infile == NULL) + { + *error = ERR_OPENFAIL; + return (NULL); + } + + /* first line of file is Envir file name, save */ + token = GetNextToken(infile, &label); + if (token == TOKEN_EOF) + { + *error = ERR_EMPTYFILE; + fclose(infile); + return (NULL); + } + else if (token == TOKEN_LABEL) + { + if (label == NULL) + { + *error = ERR_MEMALLOC; + fclose(infile); + return (NULL); + } + EnvNm = strdup(label); + } + + /* set up root node */ + token = GetNextToken(infile, &label); + if (token == TOKEN_EOF) + { + *error = ERR_EMPTYFILE; + fclose(infile); + return (NULL); + } + else if (token == TOKEN_LABEL) + { + if (label == NULL) + { + *error = ERR_MEMALLOC; + fclose(infile); + return (NULL); + } + tree = MakeNode(); + if (tree == NULL) + { + *error = ERR_MEMALLOC; + fclose(infile); + free(label); + return(NULL); + } + SetNodeLabelAndValue(tree, label); + tree->parent = NULL; + node = tree; + } + else + { + *error = ERR_NOROOT; + fclose(infile); + return (NULL); + } + + /* add children and siblings */ + while (1) + { + token = GetNextToken(infile, &label); + if (token == TOKEN_EOF) + break; + + if (tokDepth > prevTokDepth) /* then new subtree */ + { + inside_list++; + first_child = TRUE; + parent = node; + } + else if (tokDepth < prevTokDepth) /* then end of subtree */ + if (!inside_list) + { + *error = ERR_NOBEGIN; + fclose(infile); + return (tree); + } + else + while (tokDepth < inside_list) + { + inside_list--; + node = node->parent; + parent = node->parent; + } + + if (label == NULL) + { + *error = ERR_MEMALLOC; + fclose(infile); + return (tree); + } + if (parent == NULL) + { + *error = ERR_MANYROOT; + fclose(infile); + free(label); + return (tree); + } + else + { + new_node = MakeNode(); + if (new_node == NULL) + { + *error = ERR_MEMALLOC; + fclose(infile); + free(label); + return (tree); + } + SetNodeLabelAndValue(new_node, label); + new_node->parent = parent; + + if (first_child) + { + new_node->parent->child = new_node; + first_child = FALSE; + } + else + node->sibling = new_node; + + node = new_node; +/* + * printf("%3d tok: '%s'; tokDepth: %d; prevTokDepth: %d; inside_list: %d\n", + * NumNodes, node->label.text, tokDepth, prevTokDepth, inside_list); + */ + } + } + fclose(infile); + return (tree); +} + + +/* ---------------------------------------------------------------------------- + * + * SaveTreeToFile() takes a tree and saves it to a file specified by 'fname.' + * If the file could not be opened for writing, False is returned. Otherwise, + * True is returned. + * + * ---------------------------------------------------------------------------- + */ + +SaveTreeToFile(tree, fname) + Tree *tree; + char *fname; +{ + FILE *outfile; + + outfile = fopen(fname, "w"); + if (outfile == NULL) + return (FALSE); + + fprintf(outfile, "%s\n", EnvNm); /* Save Env File Name */ + fprintf(outfile, "%s\n", tree->label.text); + if (tree->child) + SaveSubtree(tree->child, 0, outfile); + + fclose(outfile); + return (TRUE); +} + + +/* ---------------------------------------------------------------------------- + * + * SaveSubtree() is the recursive procedure that supports SaveTreeToFile(). + * + * ---------------------------------------------------------------------------- + */ + +static void + SaveSubtree(tree, level, fp) +Tree *tree; +int level; +FILE *fp; +{ + int i; + + level++; + for ( ; tree ; tree = tree->sibling) + { + for (i = 0 ; i < level ; i++) + { + putc(' ', fp); + putc(' ', fp); + } + fprintf(fp, "%s\n", tree->label.text); + if (tree->child) + SaveSubtree(tree->child, level, fp); + } + level--; +} + +