home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3648 / pindex.c < prev    next >
C/C++ Source or Header  |  1991-07-16  |  7KB  |  271 lines

  1. /*
  2.  * pindex  Brian Rice  rice@dg-rtp.dg.com  1989-91
  3.  *
  4.  * This produces one or more indexed files from the raw input file.
  5.  *
  6.  * $Date: 91/07/03 12:29:00 $
  7.  */
  8.  
  9. static char rcsid[] = "$What: <@(#) pindex.c,v    2.3> $";
  10.  
  11. #include <stdio.h>
  12. #define MY_FILENAME_LENGTH 64
  13. #define MAX_WORD_LEN 128
  14. #define USAGE "%s: usage: %s [ -number ] inputfile outputfile1 ...\n"
  15.  
  16. #ifdef unix
  17. #define TEMPFILE_PATTERN "/tmp/index.%d.%d"
  18. #else
  19. #define TEMPFILE_PATTERN "index%d"
  20. #endif
  21.  
  22. #ifndef TRUE
  23. #define TRUE 1
  24. #endif
  25.  
  26. main(argc,argv)
  27. int argc;
  28. char *argv[];
  29. {
  30.     long int bytecount = 0L;
  31.     long int numrecs = 0L;
  32.         long int headersize = 0L;
  33.         long int sofar = 0L;
  34.         char buff[MAX_WORD_LEN];
  35.     char temp_filename[MY_FILENAME_LENGTH];
  36.     char temp2_filename[MY_FILENAME_LENGTH];
  37.     char *cmdname;
  38.     static char *usage = USAGE;
  39.     int lines_per_entry = 1;
  40.     char *infilename;
  41.     char **outfilenames;
  42.     char **tempfilenames;
  43.     FILE *raw, *thislen, *thisout;
  44.     FILE **lenfiles;
  45.     FILE **outfiles;
  46.     char *malloc();
  47.     int inx;
  48.     int maxfiles();
  49.  
  50.         /* A bit of initialization. */
  51.  
  52.     cmdname = argv[0];
  53.     argc--; argv++;
  54.  
  55.     if (argc == 0) {
  56.         (void) fprintf(stderr,usage,cmdname,cmdname);
  57.         exit(1);
  58.     }
  59.     
  60.     /* What's next, the number of lines per entry or the
  61.        input file name? */
  62.  
  63.     if (*argv[0] == '-') {
  64.         lines_per_entry = atoi(argv[0]+1);
  65.         argc--; argv++;
  66.     }
  67.  
  68.     if (lines_per_entry > maxfiles() - 3) {
  69.         fprintf(stderr, "%s: can't open that many files\n", cmdname);
  70.         exit(2);
  71.     }
  72.  
  73.     /* Let's grab some space for our dynamically allocated arrays. */
  74.  
  75.     outfilenames = (char **) malloc(lines_per_entry * sizeof (char *));
  76.     tempfilenames = (char **) malloc(lines_per_entry * sizeof (char *));
  77.     lenfiles = (FILE **) malloc(lines_per_entry * sizeof (FILE *));
  78.     outfiles = (FILE **) malloc(lines_per_entry * sizeof (FILE *));
  79.     if (outfilenames == NULL || tempfilenames == NULL ||
  80.         lenfiles == NULL || outfiles == NULL) {
  81.         (void) fprintf(stderr, "%s: malloc failed\n", cmdname);
  82.         exit(2);
  83.     }
  84.  
  85.     if (argc == 0) {
  86.         (void) fprintf(stderr,usage,cmdname,cmdname);
  87.         exit(1);
  88.     }
  89.  
  90.     infilename = argv[0];
  91.     argc--; argv++;
  92.  
  93.     if (argc == 0) {
  94.         (void) fprintf(stderr,usage,cmdname,cmdname);
  95.         exit(1);
  96.     }
  97.  
  98.     /* This loop sets up our freshly-allocated arrays of output
  99.        filenames and temporary-file names. */
  100.  
  101.     for (inx = 0; inx < lines_per_entry; inx++) {
  102.         if (argc == 0) {
  103.             (void) fprintf(stderr,
  104.                            "%s: too few filenames\n", cmdname);
  105.             exit(1);
  106.         } 
  107.         outfilenames[inx] = argv[0];
  108.         tempfilenames[inx] = malloc(MY_FILENAME_LENGTH);
  109.         if (tempfilenames[inx] == NULL) {
  110.             (void) fprintf(stderr,"%s: malloc failed\n",cmdname);
  111.             exit(2);
  112.         }
  113. #ifdef unix
  114.         (void) sprintf(tempfilenames[inx],
  115.                        TEMPFILE_PATTERN,inx,getpid());
  116. #else
  117.         (void) sprintf(tempfilenames[inx],TEMPFILE_PATTERN,inx);
  118. #endif
  119.         argc--; argv++;
  120.     }
  121.  
  122.     if (argc > 0) {
  123.         /* Since this program is destructive (i.e., it over-
  124.            writes its output files), we'd better be cautious. */
  125.         (void) fprintf(stderr,"%s: too many filenames\n",cmdname);
  126.         exit(1);
  127.     }
  128.  
  129.     /* First we go through the input file, noting the length of
  130.        each input item. */
  131.  
  132.     raw = fopen(infilename,"r");
  133.     if (raw == NULL) {
  134.         (void) fprintf(stderr,"%s: can't open %s for reading\n",
  135.                        cmdname, infilename);
  136.         exit(1);
  137.     }
  138.  
  139.     for (inx = 0; inx < lines_per_entry; inx++) {
  140.         lenfiles[inx] = fopen(tempfilenames[inx],"w");
  141.         if (lenfiles[inx] == NULL) {
  142.             (void) fprintf(stderr,"%s: can't open %s for writing\n",
  143.                            cmdname, tempfilenames[inx]);
  144.             exit(1);
  145.         }
  146.     }
  147.  
  148.     /* Here we write the length of each item in turn to its 
  149.        temporary file... */
  150.  
  151.     while (TRUE) {
  152.         for (inx = 0; inx < lines_per_entry; inx++) {
  153.             bytecount = (long) fngetline(raw,buff,MAX_WORD_LEN);
  154.             if (bytecount != 0) {
  155.                 (void) fwrite(&bytecount,
  156.                               sizeof bytecount,1,lenfiles[inx]);
  157.             } else {
  158.                 if (inx == 0) {
  159.                     goto alldone; /* E.W. Dijkstra 
  160.                                      considered harmful */
  161.                 } else {
  162.                     (void) fprintf(stderr,
  163.                              "%s: premature eof on read\n",
  164.                              cmdname);
  165.             
  166.                     exit(2);
  167.                 }
  168.             }
  169.         }
  170.         numrecs++;
  171.     }
  172.  
  173. alldone:
  174.         (void) fclose(raw);
  175.     for (inx = 0; inx < lines_per_entry; inx++) {
  176.                (void) fclose(lenfiles[inx]);
  177.     }
  178.  
  179.     /* Now we'll write the index part of the output files. */
  180.  
  181.         headersize = (sizeof bytecount) * (numrecs + 1) + sizeof numrecs;
  182.  
  183.     for (inx = 0; inx < lines_per_entry; inx++) {
  184.         sofar = headersize;
  185.             thislen = fopen(tempfilenames[inx],"r");
  186.         if (thislen == NULL) {
  187.             (void) fprintf(stderr,"%s: can't open %s for reading\n",
  188.                            cmdname, tempfilenames[inx]);
  189.             exit(1);
  190.         }
  191.         thisout = fopen(outfilenames[inx],"w");
  192.         if (thisout == NULL) {
  193.             (void) fprintf(stderr,"%s: can't open %s for writing\n",
  194.                            cmdname, outfilenames[inx]);
  195.             exit(1);
  196.         } 
  197.  
  198.     /* Thing one is the number of records in the file. */
  199.  
  200.         (void) fwrite(&numrecs,sizeof numrecs,1,thisout);
  201.  
  202.     /* So suppose we have a forty-byte-long header, then the first
  203.        item is six bytes long.  The starting address of the
  204.        first item will be 40 (the header will lie in 0-39).  The
  205.        next item will begin in location 44 (the first item will lie
  206.        in locations 40-43).  And so forth. */
  207.  
  208.             while (fread(&bytecount,
  209.                       sizeof bytecount,1,thislen) == 1) {
  210.             (void) fwrite(&sofar,sizeof bytecount,1,thisout);
  211.             sofar += bytecount;
  212.         }
  213.     
  214.     /* Since the expected way of figuring out how long an item is 
  215.            to subtract its starting address from that of its successor, 
  216.            we have to write the starting address of an imaginary item 
  217.        one past the last one.  Not to worry...if someone asks for 
  218.        that item, they've made a mistake-o. */
  219.  
  220.         (void) fwrite(&sofar,sizeof bytecount,1,thisout);
  221.  
  222.                (void) fclose(thislen);
  223.         (void) unlink(tempfilenames[inx]);
  224.                (void) fclose(thisout);
  225.     }
  226.  
  227.     /* Finally, we copy the input records to the appropriate
  228.        output files. */
  229.  
  230.     raw = fopen(infilename,"r");
  231.     if (raw == NULL) {
  232.         (void) fprintf(stderr,
  233.                        "%s: can't open %s for reading\n", 
  234.                        cmdname, infilename); 
  235.         exit(1);
  236.     } 
  237.  
  238.     for (inx = 0; inx < lines_per_entry; inx++) {
  239.         outfiles[inx] = fopen(outfilenames[inx],"a");
  240.     }
  241.  
  242.     inx = 0;
  243.     while (TRUE) {
  244.         if ((bytecount = (long) fngetline(raw,buff,MAX_WORD_LEN)) 
  245.                != 0) {
  246.             (void) fwrite(buff,
  247.                           sizeof(char),bytecount,outfiles[inx]);
  248.             inx++;
  249.             if (inx == lines_per_entry) {
  250.                 inx = 0;
  251.             }
  252.         } else {
  253.             if (inx == 0) {
  254.                 break;
  255.             } else {
  256.                 fprintf(stderr,
  257.                         "%s: premature eof on read [A]\n",
  258.                         cmdname);
  259.                 exit(5);
  260.             }
  261.         }
  262.     }
  263.     (void) fclose(raw);
  264.     for (inx = 0; inx < lines_per_entry; inx++) {
  265.         (void) fclose(outfiles[inx]);
  266.     }
  267.  
  268.     exit(0);
  269. }
  270.  
  271.