home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / lisp / oobr / tree-x / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-20  |  7.7 KB  |  348 lines

  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.  
  348.