home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / forth / pfe-0.000 / pfe-0 / pfe-0.9.13 / src / helpidx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-17  |  5.5 KB  |  297 lines

  1. /*
  2.  * This file is part of the portable Forth environment written in ANSI C.
  3.  * Copyright (C) 1995  Dirk Uwe Zoller
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13.  * See the GNU Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * This file is version 0.9.13 of 17-July-95
  20.  * Check for the latest version of this package via anonymous ftp at
  21.  *    roxi.rz.fht-mannheim.de:/pub/languages/forth/pfe-VERSION.tar.gz
  22.  * or    sunsite.unc.edu:/pub/languages/forth/pfe-VERSION.tar.gz
  23.  * or    ftp.cygnus.com:/pub/forth/pfe-VERSION.tar.gz
  24.  *
  25.  * Please direct any comments via internet to
  26.  *    duz@roxi.rz.fht-mannheim.de.
  27.  * Thank You.
  28.  */
  29. /*
  30.  * helpindex.c --- read help files and create an index
  31.  * (duz 13Sep94)
  32.  */
  33.  
  34. #define _XOPEN_SOURCE 1
  35. #define _ALL_SOURCE 1
  36.  
  37. #include "config.h"
  38. #include "const.h"
  39. #include "options.h"
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44.  
  45. #if defined HAVE_GETOPT_H
  46. # include <getopt.h>
  47. #else
  48. # if defined HAVE_LIBC_H
  49. #  include <libc.h>
  50. # endif
  51. # if defined HAVE_UNISTD_H
  52. #  include <unistd.h>
  53. # endif
  54. #endif
  55.  
  56. #include "missing.h"        /* SEEK_SET */
  57. #include "help.h"
  58.  
  59. #define NEW(P,N)    ((P) = xalloc ((N) * sizeof *(P)))
  60.  
  61. /*
  62.  * Data structures.
  63.  */
  64.  
  65. typedef struct node Node;    /* record in binary tree in memory */
  66. struct node
  67.   {
  68.     HRecord rec;
  69.     Node *left, *right;
  70.   };
  71.  
  72. static HHeader hheader = {{'H', 'E', 'L', 'P'}};
  73. static char (*file)[PATH_LENGTH];
  74. static Node *root = NULL;
  75.  
  76. static int
  77. insert (HRecord *new)
  78. /*
  79.  * Insert *new into a binary tree starting at root.
  80.  * Result: 1 if ok, 0 if record with same name already in tree.
  81.  */
  82. {
  83.   Node **p = &root, *q;
  84.  
  85.   while (*p != NULL)
  86.     {
  87.       int cmp = strcmp (new->name, (*p)->rec.name);
  88.  
  89.       if (cmp == 0)
  90.     {
  91.       fprintf (stderr, "\"%s\" is redefined\n", new->name);
  92.       return 0;
  93.     }
  94.       if (cmp < 0)
  95.     p = &(*p)->left;
  96.       else if (cmp > 0)
  97.     p = &(*p)->right;
  98.     }
  99.   NEW (q, 1);
  100.   q->rec = *new;
  101.   q->left = q->right = NULL;
  102.   *p = q;
  103.   return 1;
  104. }
  105.  
  106. /*
  107.  * Read records from file and insert them in the tree.
  108.  */
  109.  
  110. static long
  111. scan_record (FILE * f, char *name)
  112. /*
  113.  * Reads the file until a `:' is found in column 0. Returns the name in *name.
  114.  * Returns position of `:' or -1 at end of file.
  115.  */
  116. {
  117.   for (;;)
  118.     {
  119.       long pos = ftell (f);
  120.       char line[0x80];
  121.       char *p = fgets (line, sizeof line, f);
  122.  
  123.       if (p == NULL)
  124.     {
  125.       if (ferror (f))
  126.         sys_error ();
  127.       else
  128.         return -1;
  129.     }
  130.       if (line[0] == ':')
  131.     {
  132.       sscanf (line, ":%s", name);
  133.       return pos;
  134.     }
  135.     }
  136. }
  137.  
  138. static void
  139. skip_record (FILE* f)
  140. /*
  141.  * Skip over all lines in file until either two empty lines
  142.  * or a `:' in column 0 is found.
  143.  */
  144. {
  145.   int empty = 0;
  146.  
  147.   for (;;)
  148.     {
  149.       long pos = ftell (f);
  150.       char line[0x80];
  151.       char *p = fgets (line, sizeof line, f);
  152.  
  153.       if (p == NULL)
  154.     {
  155.       if (ferror (f))
  156.         sys_error ();
  157.       else
  158.         return;
  159.     }
  160.       if (line[0] == '\n' || line[0] == '#')
  161.     {
  162.       if (++empty == 2)
  163.         return;
  164.       else
  165.         empty = 0;
  166.     }
  167.       if (line[0] == ':')
  168.     {
  169.       fseek (f, pos, SEEK_SET);
  170.       return;
  171.     }
  172.     }
  173. }
  174.  
  175. static void
  176. read_file (FILE *f, int fidx)
  177. {
  178.   HRecord x;
  179.  
  180.   for (;;)
  181.     {
  182.       x.pos = scan_record (f, x.name);
  183.       x.fidx = fidx;
  184.       if (x.pos == -1)
  185.     return;
  186.       skip_record (f);
  187.       if (insert (&x))
  188.     hheader.nitems++;
  189.     }
  190. }
  191.  
  192. /*
  193.  * Write file.
  194.  */
  195.  
  196. static void
  197. write_tree (Node *p, FILE * f)
  198. {
  199.   if (p == NULL)
  200.     return;
  201.   write_tree (p->left, f);
  202.   if (fwrite (&p->rec, sizeof p->rec, 1, f) != 1)
  203.     sys_error ();
  204.   write_tree (p->right, f);
  205. }
  206.  
  207. static void
  208. write_file (FILE * f)
  209. {
  210.   fwrite (&hheader, 1, sizeof hheader, f);
  211.   fwrite (file, hheader.nfiles, sizeof *file, f);
  212.   if (ferror (f))
  213.     sys_error ();
  214.   write_tree (root, f);
  215. }
  216.  
  217. /*
  218.  * Main program, process command line.
  219.  */
  220.  
  221. static void
  222. usage (void)
  223. {
  224.   fatal ("usage:\t%s [-o file] file ..."
  225.      "\n    -o\toutput index to file (default: standard output)",
  226.      progname);
  227. }
  228.  
  229. int
  230. main (int argc, char *argv[])
  231. {
  232.   char *outfile = NULL;
  233.   FILE *in, *out;
  234.   int c, i, n;
  235.  
  236.   /*
  237.    * get program name for error messages
  238.    */
  239.   progname = strrchr (argv[0], '/');
  240.   if (progname)
  241.     progname++;
  242.   else
  243.     progname = argv[0];
  244.  
  245.   /*
  246.    * parse command line options
  247.    */
  248.   while ((c = getopt (argc, argv, ":ho:")) != EOF)
  249.     {
  250.       switch (c)
  251.     {
  252.     case '?':
  253.       fatal ("illegal option %s", argv[optind]);
  254.     case ':':
  255.       fatal ("option %s requires an argument", argv[optind]);
  256.     case 'h':
  257.       usage ();
  258.     case 'o':
  259.       outfile = optarg;
  260.       break;
  261.     }
  262.     }
  263.   n = argc - optind;
  264.   if (n <= 0)
  265.     usage ();
  266.  
  267.   /*
  268.    * process
  269.    */
  270.   hheader.nfiles = 0;
  271.   hheader.nitems = 0;
  272.   NEW (file, n);
  273.   for (i = 0; i < n; i++)
  274.     {
  275.       strcpy (file[i], argv[optind + i]);
  276.       in = fopen (file[i], "r");
  277.       if (in == NULL)
  278.     file_errorz (argv[i]);
  279.       read_file (in, i);
  280.       hheader.nfiles++;
  281.       fclose (in);
  282.     }
  283.  
  284.   if (outfile)
  285.     {
  286.       out = fopen (outfile, "wb");
  287.       if (out == NULL)
  288.     file_errorz (outfile);
  289.     }
  290.   else
  291.     {
  292.       out = stdout;
  293.     }
  294.   write_file (out);
  295.   return 0;
  296. }
  297.