/* */ /* descc - compile info file into describe database file */ /* */ /* v1.0.1 - Added -h and -V flags [Sat May 06 1995] */ /* Extracted certain #defines to "desc.h" */ /* Now uses getopt for command line parsing. */ /* Fixed some potential bugs. */ /* */ /* v1.0.0 - James Brookes [Sat Oct 23 1993] */ /* released [Thu Mar 31 1994] [!!!!!!!!!!!] */ /* */ /* This version implements the following features: */ /* */ /* o Compiles a text file which follows the specifications in the */ /* included file 'describe.format'. The format of the describe */ /* database is as follows: */ /* */ /* Header */ /* */ /* 2 bytes: Short Int, number of Name Entries */ /* */ /* Name Entries */ /* */ /* 34 bytes: Null-terminated string; name of utility */ /* 4 bytes: Long Int, offset of record in file. */ /* */ /* Records */ /* */ /* 7 variable-length Null-terminated strings. */ /* */ #pragma optimize 15 #include #include #include #include #include #include "desc.h" #define _VERSION_ "v1.0.1" /* prototypes */ void usage(char *callname); void version(char *callname); void puke(int error,int lines); int mygets(char *buffer, int2 *lines, FILE *FInPtr); int Vflag; /* version - print it out */ void version (char *callname) { Vflag++; fprintf(stderr,"%s version %s\n",callname,_VERSION_); return; } /* */ /* usage - you know what to do */ /* */ void usage (char *callname) { if (!Vflag) version(callname); fprintf(stderr,"usage: %s [-hV] \n",callname); exit(-1); } /* */ /* puke - stdlib errors */ /* */ void puke (int error,int lines) { fprintf(stderr,"\nError $%x in line %d of script\n",error,lines); fflush(stdout); exit(error); } /* */ /* mygets - get a line (skipping commented lines) and increment line count */ /* */ int mygets (char *buffer, int2 *lines, FILE *FInPtr) { char *p, c; do { if (fgets(buffer,MAX_LINE_LENGTH,FInPtr)==NULL) { return(-1); } p = buffer + strlen(buffer) - 1; /* remove trailing \n */ if (*p == '\n') { *p = '\0'; } else { fprintf(stderr,"Line %d exceeds %d characters. Remainder ignored.\n", *lines,MAX_LINE_LENGTH-1); do { c = fgetc(FInPtr); } while ((c!='\n') && !feof(FInPtr)); } (*lines)++; } while(buffer[0] == QUOTE_CHAR || buffer[0] == '\n'); return(0); } /* */ /* Mainline */ /* */ int main (int argc, char **argv) { FILE *FInPtr, *FOutPtr; long int *record_locs, currLoc, endOfFile; char *buffer; int2 lines, namecount, i, j; nameEntry nameStruct; int c, errflag; /* initialize globals */ Vflag=0; errflag=0; #ifdef STACK_CHECK begin_stack_check(); #endif assert(sizeof(int2)==2); assert(sizeof(int4)==4); /* parse command line */ while ((c = getopt(argc, argv, "hV")) != EOF) { switch (c) { case 'V': version(basename(argv[0])); break; case 'h': /*FALLTHROUGH*/ default: errflag++; break; } } if (errflag || (argc-optind != 1)) usage(basename(argv[0])); /* open input and output files */ if ((buffer = malloc (MAX_LINE_LENGTH)) == NULL) { fprintf(stderr,"couldn't allocate line buffer\n"); exit (-1); } if ((FInPtr = fopen(argv[argc-1],"r")) == NULL) { fprintf(stderr,"Error opening %s; exiting.\n",argv[argc-1]); free(buffer); exit(1); } if ((FOutPtr = fopen(DATABASE,"wb+")) == NULL) { fprintf(stderr,"Error opening database file %s; exiting.\n",DATABASE); free(buffer); exit(1); } /* Compile array of names */ lines = 0; namecount = 0; /* space for # of array entries */ fwrite(&namecount,sizeof(namecount),1,FOutPtr); while(mygets(buffer,&lines,FInPtr) != -1) { if (!strncmp(buffer,NAME,FIELD_LEN)) { /* found a match */ strncpy(nameStruct.name,&buffer[FIELD_LEN],NAME_LEN-1); nameStruct.name[NAME_LEN-1] = '\0'; fwrite(&nameStruct,sizeof(nameStruct),1,FOutPtr); namecount++; } } if ((record_locs = malloc (namecount*sizeof(long int)))==NULL) { fprintf(stderr,"malloc of record_locs failed (%ld bytes); exiting\n", (long) namecount*sizeof(long int)); exit(-1); } rewind(FInPtr); fflush(FInPtr); buffer[0] = '\0'; lines = 0; fprintf(FOutPtr,"\t"); /* Increment to first field */ while (strncmp(buffer,NAME,FIELD_LEN)) /* found a match! */ mygets(buffer,&lines,FInPtr); /* Write out records and keep track of their file offsets */ for (i = 0; i < namecount; i++) { record_locs[i] = ftell(FOutPtr); /* print out , , , , */ for (j = 0; j < FIELD_COUNT-1; j++) { buffer[FIELD_LEN] = '\0'; mygets(buffer,&lines,FInPtr); fprintf(FOutPtr,"%s\n",&buffer[FIELD_LEN]); } /* handle field */ for (;;) { if (mygets(buffer,&lines,FInPtr) == -1) break; if (!strncmp(buffer,NAME,FIELD_LEN)) break; fprintf(FOutPtr,"%s ",buffer); } fprintf(FOutPtr,"\n"); } endOfFile = ftell(FOutPtr); fflush(FOutPtr); /*gdr 1*/ rewind(FOutPtr); fwrite(&namecount,sizeof(namecount),1,FOutPtr); fflush(FOutPtr); /*gdr 1*/ /* time to go through the record_locs array and backpatch in */ /* all the record locations. A little slower than necessary */ /* perhaps, but it gets the job done. */ for (i = 0; i < namecount; i++) { fread(&nameStruct,sizeof(nameStruct),1,FOutPtr); fseek(FOutPtr,-(sizeof(nameStruct)),SEEK_CUR); nameStruct.offset = record_locs[i]; fwrite(&nameStruct,sizeof(nameStruct),(size_t) 1,FOutPtr); fflush(FOutPtr); } fseek(FOutPtr,endOfFile,SEEK_SET); fclose(FOutPtr); free(record_locs); free(buffer); #ifdef STACK_CHECK fprintf(stderr,"stack usage: %d bytes\n",end_stack_check()); #endif return 0; }