/* mkindex.c */ /* Version 2.1a (C) 1996-2002 Norbert H. Doerry SYNTAX: MKINDEX INFILE -pPROFILE -d -? where INFILE = Input file PROFILE = Parameter file d = Set the DEBUG flag ? = Help The format of the INFILE is: 3 columns separated by a whitespace column 1: INDEX_FILE: The name of the index file to write this entry in column 2: DATA_FILE: The hypertext link for this entry column 3: LINK_TEXT: The text to print for the hypertext link column 4: INDEX_TEXT: Text to print after the DATA_FILE hypertext link The format of the PROFILE is: [header] Text to print at the top of each INDEX_FILE &FILENAME is replaced with the filename INDEX_FILE &FILEDATE is replaced with the current date &FILETIME is replaced with the current time [footer] Text to print at the bottom of each INDEX_FILE The same fields as in the header can be used [commands] Title Text to be used for the title of the INDEX_FILE, fields can be used Link_Extension Up to 4 characters to add as an extension to DATA_FILE Link_Path The Path precede DATA_FILE Version1 Use only 3 columns of data, [EOF] **** VERSION 1.0a **** December 19, 1996: Norbert H. Doerry fixed minor bug with printing out file extensions in printline() **** VERSION 2.0 **** January 6, 1997: Norbert H. Doerry Changed to 4 columns, but added Version1 command to provide compatiblility to version 1.0 3 column PROFILE files (omits column 3) Allowed one to not specify an extension with the Link_Extension by not providing an extension. **** VERSION 2.0a **** February 1997: Norbert Doerry fixed minor bug with &FILENAME field ... eliminated printing the extension **** VERSION 2.1 ***** December 1997: Norbert Doerry Changed Link_Path to allow spaces in the path. **** VERSUIB 2.1a **** JUNE 2002: Norbert Doerry Added GNU GPL, recompiled with 32 bit compiler --------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --------------------------------------------------------------- If you discover any bugs, or have any questions concerning these programs, please send me an email (doerry@aol.com) */ #include #include #include #include #include #define VERSION "2.1a" #define MAXCHAR 256 #define VER_1 1 #define VER_2 2 typedef struct MkIndex { char *infile; FILE *in; char *header; char *footer; char *title; char *Link_Extension; char *Link_Path; char filedate[10]; char filetime[10]; int version; struct IndexFile *indxf; int debug; } MKINDEX; typedef struct IndexFile { char *filename; struct IndexFile *next; } INDEXFILE; /***************************************************************************/ void init_mkindex(MKINDEX *); void read_command_line(MKINDEX *,int,char **); void read_profile(MKINDEX *,char *); void read_profile_header(MKINDEX *,FILE *,char *); void read_profile_footer(MKINDEX *,FILE *,char *); void read_profile_commands(MKINDEX *,FILE *,char *); void print_help(void); char *copystring(char *); char *strextract(char *,int); char *strsplit(char *,int); void strstrip(char *); void insert_fields(MKINDEX *,char *,char *); void print_header(MKINDEX *,FILE *,char *); void print_line(MKINDEX *,FILE *,char *,char *,char *); void print_footer(MKINDEX *,FILE *,char *); void print_debug(MKINDEX *); FILE *open_index_file(MKINDEX *,char *); void terminate_index_file(MKINDEX *,INDEXFILE *); void process_input_file(MKINDEX *); /***************************************************************************/ int main(int argc,char **argv) { MKINDEX mk; init_mkindex(&mk); read_command_line(&mk,argc,argv); if (mk.debug) print_debug(&mk); process_input_file(&mk); return EXIT_SUCCESS; } void init_mkindex(MKINDEX *mk) { time_t t; char *ct; int i; t = time((time_t *) NULL); ct = ctime(&t); /* Wed Jan 02 02:03:55 1980\n\0 */ /* 012345678901234567890123 4 5 */ mk->infile = (char *) NULL; mk->in = (FILE *) NULL; mk->header = (char *) NULL; mk->footer = (char *) NULL; mk->title = (char *) NULL; mk->Link_Extension = (char *) NULL; mk->Link_Path = (char *) NULL; mk->filedate[0] = ct[8]; mk->filedate[1] = ct[9]; mk->filedate[2] = '-'; mk->filedate[3] = ct[4]; mk->filedate[4] = ct[5]; mk->filedate[5] = ct[6]; mk->filedate[6] = '-'; mk->filedate[7] = ct[22]; mk->filedate[8] = ct[23]; mk->filedate[9]= (char) NULL; for (i=11 ; i < 19 ; i++) mk->filetime[i-11] = ct[i]; mk->filetime[8] = ' '; mk->filetime[9] = (char) NULL; mk->indxf = (INDEXFILE *) NULL; mk->version = VER_2; mk->debug = 0; } void read_command_line(MKINDEX *mk,int argc,char **argv) { int i; for (i = 1 ; i < argc ; i++) { if (argv[i][0] == '-' || argv[i][0] == '/') { if (argv[i][1] == 'p') read_profile(mk,argv[i]+2); else if (argv[i][1] == 'd') mk->debug = 1; else if (argv[i][1] == '?') print_help(); else { fprintf(stderr," ***ERROR: Unknown Command Line Option: %s\n",argv[i]); exit(EXIT_FAILURE); } } else /* infile */ { if (mk->infile != (char *) NULL) { fprintf(stderr," ***ERROR: Multiple Input Files Defined\n"); exit(EXIT_FAILURE); } else { mk->infile = copystring(argv[i]); mk->in = fopen(mk->infile,"r"); if (mk->in == (FILE *) NULL) { fprintf(stderr," ***ERROR: Unable to open File %s\n",mk->infile); exit(EXIT_FAILURE); } } } /* end of code for infile handling */ } /* end of loop for command line arguments */ } void read_profile(MKINDEX *mk,char *profile) { FILE *pro; char rdline[MAXCHAR]; int i; pro = fopen(profile,"r"); if (pro == (FILE *) NULL) { fprintf(stderr," ***ERROR: Unable to open File %s\n",profile); exit(EXIT_FAILURE); } while (fgets(rdline,MAXCHAR-1,pro)) { if (rdline[0] == '[') /* skip lines that aren't a section head */ break; } while(rdline[0] == '[') { for (i=1; isalpha((int)rdline[i]) ; i++) /* convert to upper case */ rdline[i] = (char) toupper((int)rdline[i]); if (strncmp(rdline,"[HEADER]",8) == 0) /* look for HEADER */ read_profile_header(mk,pro,rdline); else if (strncmp(rdline,"[FOOTER]",8) == 0) /* look for footer section */ read_profile_footer(mk,pro,rdline); else if (strncmp(rdline,"[COMMANDS]",10)==0) read_profile_commands(mk,pro,rdline); else if (strncmp(rdline,"[EOF]",5) == 0) break; else /* skip unknown sections */ { while (fgets(rdline,MAXCHAR-1,pro)) { if (rdline[0] == '[') /* skip lines that aren't a section head */ break; } } } } void read_profile_header(MKINDEX *mk,FILE *pro,char *rdline) { while (fgets(rdline,MAXCHAR-1,pro)) { if (rdline[0] == '[') /* see if the start of the next section */ break; if (rdline[0] == '!') /* skip comment lines */ continue; if (mk->header == (char *) NULL) mk->header = copystring(rdline); else { mk->header = (char *)realloc(mk->header, strlen(rdline)+1+strlen(mk->header)); if (mk->header == (char *) NULL) { fprintf(stderr, " ***ERROR: Out of Memory in read_profile_header() <%d>\n", __LINE__); exit(EXIT_FAILURE); } strcat(mk->header,rdline); } } } void read_profile_footer(MKINDEX *mk,FILE *pro,char *rdline) { while (fgets(rdline,MAXCHAR-1,pro)) { if (rdline[0] == '[') /* see if the start of the next section */ break; if (rdline[0] == '!') /* skip comment lines */ continue; if (mk->footer == (char *) NULL) mk->footer = copystring(rdline); else { mk->footer = (char *)realloc(mk->footer, strlen(rdline)+1+strlen(mk->footer)); if (mk->footer == (char *) NULL) { fprintf(stderr, " ***ERROR: Out of Memory in read_profile_footer() <%d>\n", __LINE__); exit(EXIT_FAILURE); } strcat(mk->footer,rdline); } } } /* Title Text to be used for the title of the INDEX_FILE, fields can be used Link_Extension Up to 4 characters to add as an extension to DATA_FILE Link_Path The Path precede DATA_FILE */ void read_profile_commands(MKINDEX *mk,FILE *pro,char *rdline) { int i,j; while (fgets(rdline,MAXCHAR-1,pro)) { if (rdline[0] == '[') /* see if the start of the next section */ break; if (rdline[0] == '!') /* skip comment lines */ continue; strstrip(rdline); if (strncmp("Title",rdline,5) == 0) { if (mk->title == (char *) NULL && strlen(rdline) > 6) mk->title = copystring(rdline+6); } else if (strncmp("Link_Extension",rdline,14) == 0) { if (mk->Link_Extension == (char *) NULL) { mk->Link_Extension = copystring(". "); for (i=14 ; isspace(rdline[i]) ; i++); if (rdline[i] == (char) NULL) { mk->Link_Extension[0] = (char) NULL; continue; } if (rdline[i] == '.') i++; for (j=0 ; j < 3 && rdline[i+j] != (char) NULL ; j++) mk->Link_Extension[j+1] = rdline[j+i]; } } else if (strncmp("Link_Path",rdline,9) == 0) { if (mk->Link_Path == (char *) NULL) { /* mk->Link_Path = strextract(rdline,2);*/ /* copy the path */ mk->Link_Path = copystring(rdline+10); strstrip(mk->Link_Path); } } else if (strncmp("Version1",rdline,8) == 0) { mk->version = VER_1; } } } void print_help(void) { printf("MKINDEX Version %s (%s)\n",VERSION,__DATE__); printf("COPYRIGHT (C) 1996-2002 Norbert Doerry\n"); printf("SYNTAX: MKINDEX INFILE -pPROFILE\n"); printf("where: INFILE = INPUT FILE\n"); printf(" PROFILE = PARAMETER FILE\n"); printf("\n"); printf(" INFILE consists of 4 columns:\n"); printf(" Column 1: INDEX_FILE Name of index file to write entry in\n"); printf(" Column 2: DATA_FILE Hypertext link for this entry\n"); printf(" Column 3: LINK_TEXT Text to print for Hypertext link\n"); printf(" Column 4: INDEX_TEXT Text to print after DATA_FILE link\n"); printf("\n"); printf(" PROFILE consists of 3 sections:\n"); printf(" [header]\n"); printf(" Text to print at the top of each INDEX_FILE. Can contain fields\n"); printf(" [footer]\n"); printf(" Text to print at the bottom of each INDEX_FILE. Fields are ok\n"); printf(" [commands]\n"); printf(" TITLE text to used for the title of the INDEX_FILE. Fields ok\n"); printf(" LINK_EXTENSION up to 4 characters to add as a file extension\n"); printf(" LINK_PATH the path to insert before DATA_FILE\n"); printf(" ---------------------------------------------------------------\n"); printf(" FIELDS: &FILENAME &FILEDATE &FILETIME\n"); exit(EXIT_SUCCESS); } char *copystring(char *s) { char *ps; if (s == (char *) NULL) ps = (char *) calloc((size_t) 1,sizeof(char)); else ps = (char *) calloc(strlen(s)+1,sizeof(char)); if (ps == (char *) NULL) { fprintf(stderr," ***ERROR: OUT OF MEMORY IN COPYSTRING() <%d>\n",__LINE__); exit(EXIT_FAILURE); } if (s == (char *) NULL) *ps = (char) NULL; else { strcpy(ps,s); } return ps; } char *strextract(char *s,int n) /* returns string holding nth word */ { char *ps; int i,j; int ncnt; if (s ==(char *) NULL) return s; ps = copystring(s); /* allocate a big enough string */ if (n < 1) /* error checking on n */ { ps[0] =(char) NULL; return ps; } for (ncnt=1,i=0; ncnt < n ; ncnt++) /* skip the first n-1 words */ { for (;isspace(s[i]);i++); /* find first non space */ if (s[i] == (char) NULL) break; /* read to end of line without hitting the nth word */ for (;isgraph(s[i]);i++); /* read the ncnt word */ } for (;isspace(s[i]);i++); /* find first non space */ for (j=0;isgraph(s[i]);i++,j++) /* copy the nth word */ ps[j] = s[i]; ps[j] = (char) NULL; return ps; } char *strsplit(char *s,int n) /* returns string starting with nth word */ { char *ps; int i,j; int ncnt; if (s ==(char *) NULL) return s; ps = copystring(s); /* allocate a big enough string */ if (n < 1) /* error checking on n */ { ps[0] =(char) NULL; return ps; } for (ncnt=1,i=0; ncnt < n ; ncnt++) /* skip the first n-1 words */ { for (;isspace(s[i]);i++); /* find first non space */ if (s[i] == (char) NULL) break; /* read to end of line without hitting the nth word */ for (;isgraph(s[i]);i++); /* read the ncnt word */ } for (;isspace(s[i]);i++); /* find first non space */ for (j=0; s[i] != (char) NULL;i++,j++) /* copy the nth word */ ps[j] = s[i]; ps[j] = (char) NULL; /* strip off white characters at the end */ for (j--;isspace(ps[j])&&j>=0;j--) ps[j] = (char) NULL; return ps; } void strstrip(char *s) { int i,j; if (s == (char *) NULL) return; /* find first non space */ for (i=0;s[i] != (char) NULL && isspace((int)s[i]) ; i++); /* move the entire string left */ for (j=0;s[i] != (char) NULL ;i++,j++) s[j] = s[i]; s[j] = (char) NULL; /* strip trailing spaces */ for (j-- ; j >= 0 && isspace((int)s[j]) ; j--) s[j] = (char) NULL; } void insert_fields(MKINDEX *mk,char *string,char *filename) { int i,j; char file[10]; /* find the start of the filename base */ for (i = strlen(filename)-1 ; i >= 0 ; i--) { if (filename[i] == '/' || filename[i] == '\\') break; } i++; /* copy the filename */ strncpy(file,filename+i,9); /* delete the extension */ for (i = strlen(file)-1 ; i >= 0 ; i--) if (file[i] == '.') break; if (i >= 0) file[i] = (char) NULL; /* pad filename with spaces */ for (i = strlen(file) ; i < 9 ; i++) file[i] = ' '; /* search the string for fields */ for (i = 0 ; i + 8 < (int) strlen(string) ; i++) { if (strncmp(string+i,"&FILENAME",9) == 0) { for (j=0;j<9;j++) *(string+i+j) = file[j]; } else if (strncmp(string+i,"&FILEDATE",9) == 0) { for (j=0;j<9;j++) *(string+i+j) = mk->filedate[j]; } else if (strncmp(string+i,"&FILETIME",9) == 0) { for (j=0;j<9;j++) *(string+i+j) = mk->filetime[j]; } } } void print_header(MKINDEX *mk,FILE *out,char *filename) { char *header; char *title; title = copystring(mk->title); header = copystring(mk->header); insert_fields(mk,title, filename); insert_fields(mk,header,filename); fprintf(out,"%s\n",title); fprintf(out,"%s",header); fprintf(out,"

"); fprintf(out,"%s",footer); fprintf(out,"\n"); free(footer); } void print_debug(MKINDEX *mk) { printf(" infile: %s\n",mk->infile); printf(" header:\n%s\n",mk->header); printf(" footer:\n%s\n",mk->footer); printf(" title:\n%s\n",mk->title); printf(" Link_Extension: %s\n",mk->Link_Extension); printf(" Link_Path: %s\n",mk->Link_Path); printf(" filedate: %s\n", mk->filedate); printf(" filetime: %s\n", mk->filetime); } FILE *open_index_file(MKINDEX *mk,char *index_file) { FILE *out; INDEXFILE *indxf; for (indxf = mk->indxf ; indxf != (INDEXFILE *) NULL ; indxf = indxf->next) { if (strcmp(index_file,indxf->filename) == 0) break; } if (indxf == (INDEXFILE *) NULL) { out = fopen(index_file,"w"); if (out == (FILE *) NULL) { fprintf(stderr," ***ERROR: Unable to open file %s\n",index_file); return (FILE *) NULL; } else { print_header(mk,out,index_file); indxf = (INDEXFILE *) calloc((size_t)1, sizeof(INDEXFILE)); if (indxf == (INDEXFILE *) NULL) { fprintf(stderr," ***ERROR: Out of Memory in open_file() <%d>\n", __LINE__); exit(EXIT_FAILURE); } indxf->filename = copystring(index_file); indxf->next = mk->indxf; mk->indxf = indxf; } } else { out = fopen(index_file,"a"); if (out == (FILE *) NULL) { fprintf(stderr," ***ERROR: Unable to open file %s\n",index_file); return (FILE *) NULL; } } return out; } void terminate_index_file(MKINDEX *mk,INDEXFILE *indxf) { FILE *out; out = fopen(indxf->filename,"a"); if (out == (FILE *) NULL) { fprintf(stderr," ***ERROR: Unable to open file %s\n",indxf->filename); return; } print_footer(mk,out,indxf->filename); fclose(out); } void process_input_file(MKINDEX *mk) { FILE *in; FILE *out; int i,len; char index_file[MAXCHAR]; char *column_1; char *data_file; char *link_text; char *index_text; char rdline[MAXCHAR]; char last_index_file[MAXCHAR]; INDEXFILE *indxf; if (mk->in == (FILE *) NULL) in = stdin; else in = mk->in; out = (FILE *) NULL; last_index_file[0] = (char) NULL; while(fgets(rdline,MAXCHAR-1,in)) { if (rdline[0] == '!') /* ignore comment lines */ continue; strstrip(rdline); /* eliminate leading and trailing spaces */ if (mk->debug) printf("%s\n",rdline); if (rdline[0] == (char) NULL) continue; /* ignore blank lines */ column_1 = strextract(rdline,1); /* index_file */ data_file = strextract(rdline,2); if (mk->version == VER_1) { link_text = copystring(data_file); index_text = strsplit(rdline,3); } else { link_text = strextract(rdline,3); index_text = strsplit(rdline,4); } /* check to see if the index_file has an extension */ len = strlen(column_1); for (i=len-1; i > 0 && i > len-5; i--) if (column_1[i] == '.') break; /* if no extension, add .htm */ if (i == 0 || i == len-5) { strncpy(index_file,column_1,MAXCHAR-5); index_file[MAXCHAR-5] = (char) NULL; strcat(index_file,".htm"); } else { strncpy(index_file,column_1,MAXCHAR-1); index_file[MAXCHAR-1] = (char) NULL; } if (mk->debug) printf("index_file=<%s> data_file=<%s> index_text=<%s>\n", index_file,data_file,index_text); /* see if need to open the index_file */ if (strcmp(index_file,last_index_file) != 0) { if (out != (FILE *) NULL && out != stdout) fclose(out); out = open_index_file(mk,index_file); strcpy(last_index_file,index_file); } if (out == (FILE *) NULL) continue; print_line(mk,out,data_file,link_text,index_text); free((void *) column_1); free((void *) data_file); free((void *) link_text); free((void *) index_text); } if (out != (FILE *) NULL && out != stdout) fclose(out); for (indxf = mk->indxf ; indxf != (INDEXFILE *)NULL ; indxf = indxf->next) { terminate_index_file(mk,indxf); } }