home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / gawk-2.15.5-src.lha / gawk-2.15.5 / support / texindex.c next >
C/C++ Source or Header  |  1991-10-29  |  38KB  |  1,606 lines

  1. /* Prepare Tex index dribble output into an actual index.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <errno.h>
  21.  
  22. #ifdef VMS
  23. #ifndef VAX11C
  24. #define noshare
  25. #endif
  26.  
  27. #include <perror.h>
  28. #include <file.h>
  29.  
  30. #define EXIT_SUCCESS ((1 << 28) | 1)
  31. #define EXIT_FATAL ((1 << 28) | 4)
  32. #define unlink delete
  33. #define tell(fd) lseek(fd, 0L, 1)
  34.  
  35. #else /* Not VMS */
  36.  
  37. #ifdef USG
  38. #include <sys/types.h>
  39. #include <sys/fcntl.h>
  40. #endif
  41. #include <sys/file.h>
  42.  
  43. #define EXIT_SUCCESS 0
  44. #define EXIT_FATAL 1
  45.  
  46. #endif /* Not VMS */
  47.  
  48.  
  49. #ifndef L_XTND
  50. #define L_XTND 2
  51. #endif
  52.  
  53. #ifdef VMS
  54. extern noshare int sys_nerr;
  55. extern noshare char *sys_errlist[];
  56. #else
  57. extern int sys_nerr;
  58. extern char *sys_errlist[];
  59. #endif
  60.  
  61. /* When sorting in core, this structure describes one line
  62.  and the position and length of its first keyfield.  */
  63.  
  64. struct lineinfo
  65.   {
  66.     char *text;        /* The actual text of the line */
  67.     union
  68.       {            /* The start of the key (for textual comparison) */
  69.     char *text;
  70.     long number;    /* or the numeric value (for numeric comparison) */
  71.       } key;
  72.     long keylen;    /* Length of key field */
  73.   };
  74.  
  75. /* This structure describes a field to use as a sort key */
  76.  
  77. struct keyfield
  78.   {
  79.     int startwords;        /* # words to skip  */
  80.     int startchars;        /*  and # additional chars to skip, to start of field */
  81.     int endwords;        /* similar, from beg (or end) of line, to find end of field */
  82.     int endchars;
  83.     char ignore_blanks;        /* Ignore spaces and tabs within the field */
  84.     char fold_case;        /* Convert upper case to lower before comparing */
  85.     char reverse;        /* Compare in reverse order */
  86.     char numeric;        /* Parse text as an integer and compare the integers */
  87.     char positional;        /* Sort according to position within the file */
  88.     char braced;        /* Count balanced-braced groupings as fields */
  89.   };
  90.  
  91. /* Vector of keyfields to use */
  92.  
  93. struct keyfield keyfields[3];
  94.  
  95. /* Number of keyfields stored in that vector.  */
  96.  
  97. int num_keyfields = 3;
  98.  
  99. /* Vector of input file names, terminated with a zero (null pointer) */
  100.  
  101. char **infiles;
  102.  
  103. /* Vector of corresponding output file names, or zero meaning default it */
  104.  
  105. char **outfiles;
  106.  
  107. /* Length of `infiles' */
  108.  
  109. int num_infiles;
  110.  
  111. /* Pointer to the array of pointers to lines being sorted */
  112.  
  113. char **linearray;
  114.  
  115. /* The allocated length of `linearray'. */
  116.  
  117. long nlines;
  118.  
  119. /* Directory to use for temporary files.  On Unix, it ends with a slash.  */
  120.  
  121. char *tempdir;
  122.  
  123. /* Start of filename to use for temporary files.  */
  124.  
  125. char *tempbase;
  126.  
  127. /* Number of last temporary file.  */
  128.  
  129. int tempcount;
  130.  
  131. /* Number of last temporary file already deleted.
  132.  Temporary files are deleted by `flush_tempfiles' in order of creation.  */
  133.  
  134. int last_deleted_tempcount;
  135.  
  136. /* During in-core sort, this points to the base of the data block
  137.  which contains all the lines of data.  */
  138.  
  139. char *text_base;
  140.  
  141. /* Additional command switches */
  142.  
  143. int keep_tempfiles;    /* Nonzero means do not delete tempfiles -- for debugging */
  144.  
  145. /* Forward declarations of functions in this file */
  146.  
  147. void decode_command ();
  148. void sort_in_core ();
  149. void sort_offline ();
  150. char **parsefile ();
  151. char *find_field ();
  152. char *find_pos ();
  153. long find_value ();
  154. char *find_braced_pos ();
  155. char *find_braced_end ();
  156. void writelines ();
  157. int compare_full ();
  158. long readline ();
  159. int merge_files ();
  160. int merge_direct ();
  161. char *concat ();
  162. char *maketempname ();
  163. void flush_tempfiles ();
  164. char *tempcopy ();
  165.  
  166. extern char *mktemp ();
  167.  
  168. #define MAX_IN_CORE_SORT 500000
  169.  
  170. int
  171. main (argc, argv)
  172.      int argc;
  173.      char **argv;
  174. {
  175.   int i;
  176.  
  177.   tempcount = 0;
  178.   last_deleted_tempcount = 0;
  179.  
  180.   /* Describe the kind of sorting to do. */
  181.   /* The first keyfield uses the first braced field and folds case */
  182.   keyfields[0].braced = 1;
  183.   keyfields[0].fold_case = 1;
  184.   keyfields[0].endwords = -1;
  185.   keyfields[0].endchars = -1;
  186.   /* The second keyfield uses the second braced field, numerically */
  187.   keyfields[1].braced = 1;
  188.   keyfields[1].numeric = 1;
  189.   keyfields[1].startwords = 1;
  190.   keyfields[1].endwords = -1;
  191.   keyfields[1].endchars = -1;
  192.   /* The third keyfield (which is ignored while discarding duplicates)
  193.      compares the whole line */
  194.   keyfields[2].endwords = -1;
  195.   keyfields[2].endchars = -1;
  196.  
  197.   decode_command (argc, argv);
  198.  
  199.   tempbase = mktemp (concat ("txiXXXXXX", "", ""));
  200.  
  201.   /* Process input files completely, one by one.  */
  202.  
  203.   for (i = 0; i < num_infiles; i++)
  204.     {
  205.       int desc;
  206.       long ptr;
  207.       char *outfile;
  208.       char *p;
  209.  
  210.       desc = open (infiles[i], 0, 0);
  211.       if (desc < 0) pfatal_with_name (infiles[i]);
  212.       lseek (desc, 0, L_XTND);
  213.       ptr = tell (desc);
  214.       close (desc);
  215.  
  216.       outfile = outfiles[i];
  217.       if (!outfile)
  218.     {
  219.       outfile = concat (infiles[i], "s", "");
  220.     }
  221.  
  222.       if (ptr < MAX_IN_CORE_SORT)
  223.         /* Sort a small amount of data */
  224.         sort_in_core (infiles[i], ptr, outfile);
  225.       else
  226.         sort_offline (infiles[i], ptr, outfile);
  227.     }
  228.  
  229.   flush_tempfiles (tempcount);
  230.   exit (EXIT_SUCCESS);
  231. }
  232.  
  233. /* This page decodes the command line arguments to set the parameter variables
  234.  and set up the vector of keyfields and the vector of input files */
  235.  
  236. void
  237. decode_command (argc, argv)
  238.      int argc;
  239.      char **argv;
  240. {
  241.   int i;
  242.   char **ip;
  243.   char **op;
  244.  
  245.   /* Store default values into parameter variables */
  246.  
  247. #ifdef VMS
  248.   tempdir = "sys$scratch:";
  249. #else
  250.   tempdir = "/tmp/";
  251. #endif
  252.  
  253.   keep_tempfiles = 0;
  254.  
  255.   /* Allocate argc input files, which must be enough.  */
  256.  
  257.   infiles = (char **) xmalloc (argc * sizeof (char *));
  258.   outfiles = (char **) xmalloc (argc * sizeof (char *));
  259.   ip = infiles;
  260.   op = outfiles;
  261.  
  262.   /* First find all switches that control the default kind-of-sort */
  263.  
  264.   for (i = 1; i < argc; i++)
  265.     {
  266.       int tem = classify_arg (argv[i]);
  267.       char c;
  268.       char *p;
  269.  
  270.       if (tem <= 0)
  271.     {
  272.       *ip++ = argv[i];
  273.       *op++ = 0;
  274.       continue;
  275.     }
  276.       if (tem > 1)
  277.     {
  278.       if (i + 1 == argc)
  279.         fatal ("switch %s given with no argument following it", argv[i]);
  280.       else if (!strcmp (argv[i], "-T"))
  281.         tempdir = argv[i + 1];
  282.       else if (!strcmp (argv[i], "-o"))
  283.         *(op - 1) = argv[i + 1];
  284.       i += tem - 1;
  285.       continue;
  286.     }
  287.  
  288.       p = &argv[i][1];
  289.       while (c = *p++)
  290.     switch (c)
  291.       {
  292.       case 'k':
  293.         keep_tempfiles = 1;
  294.         break;
  295.  
  296.       default:
  297.         fatal ("invalid command switch %c", c);
  298.       }
  299.     switchdone: ;
  300.     }
  301.  
  302.   /* Record number of keyfields, terminate list of filenames */
  303.  
  304.   num_infiles = ip - infiles;
  305.   *ip = 0;
  306. }
  307.  
  308. /* Return 0 for an argument that is not a switch;
  309.  for a switch, return 1 plus the number of following arguments that the switch swallows.
  310. */
  311.  
  312. int
  313. classify_arg (arg)
  314.      char *arg;
  315. {
  316.   if (!strcmp (arg, "-T") || !strcmp (arg, "-o"))
  317.     return 2;
  318.   if (arg[0] == '-')
  319.     return 1;
  320.   return 0;
  321. }
  322.  
  323. /* Create a name for a temporary file */
  324.  
  325. char *
  326. maketempname (count)
  327.      int count;
  328. {
  329.   char tempsuffix[10];
  330.   sprintf (tempsuffix, "%d", count);
  331.   return concat (tempdir, tempbase, tempsuffix);
  332. }
  333.  
  334. /* Delete all temporary files up to the specified count */
  335.  
  336. void
  337. flush_tempfiles (to_count)
  338.      int to_count;
  339. {
  340.   if (keep_tempfiles) return;
  341.   while (last_deleted_tempcount < to_count)
  342.     unlink (maketempname (++last_deleted_tempcount));
  343. }
  344.  
  345. /* Copy an input file into a temporary file, and return the temporary file name */
  346.  
  347. #define BUFSIZE 1024
  348.  
  349. char *
  350. tempcopy (idesc)
  351.      int idesc;
  352. {
  353.   char *outfile = maketempname (++tempcount);
  354.   int odesc;
  355.   char buffer[BUFSIZE];
  356.  
  357.   odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
  358.  
  359.   if (odesc < 0) pfatal_with_name (outfile);
  360.  
  361.   while