/* sortindex.c Read from standard input a set of concatenated index files. Sort them and output the result to standard output. The index files will contain many lines. Each line will contain text, followed by three blanks, followed by page number information. The index files will be sorted in the basis of the text preceding the three blanks. Sorting will be case insensitive. Lines which would sort as equal, ie. containing the same text before the three blanks, will be kept in the order of receipt, enabling the page number information to be concatenated before output. Usage: sortindex file2 */ #include #include #define _tolower(c) (((c)>='A'&&(c)<='Z')?(c)+'a'-'A':(c)) typedef struct iitem { char *text; char *pages; } indexitem; int indexcompare( void *first, void *second ); int strcmpnc( char one[], char two[] ); int main(int argc, char *argv[]) { char line[500]; indexitem *items; indexitem **list; long int listlen = 0; long int listcap = 1000; long int i, j; FILE *input = stdin, *output = stdout; for (i=1; i') { char *mode = "w"; j = 1; if (argv[i][j] == '>') { mode = "a"; ++j; } if (strlen(&argv[i][j]) == 0) { ++i; j = 0; } if ( (output = fopen(&argv[i][j], mode)) == NULL) { fprintf(stderr, "sortindx: unable to open output file %s\n", &argv[i][j]); exit(1); } } } /* Allocate initial space for index data */ items = (indexitem *) malloc(listcap*sizeof(indexitem)); /* Read the data from standard input */ fprintf(stderr,"Reading data\n"); while (fgets(line,500,input) != NULL) { char *blanks = strstr(line," "); char *pages = &blanks[3]; if (blanks == NULL) { fprintf(stderr,"Bad line for sorting: \n%s\n",line); continue; } blanks[0] = '\0'; pages[strlen(pages)-1] = '\0'; /* remove '\n' */ if (listlen == listcap) { listcap += 80; items = (indexitem *) realloc(items,listcap*sizeof(indexitem)); } items[listlen].text = (char *) malloc(blanks-line+1); strcpy( items[listlen].text, line); items[listlen].pages = (char *) malloc(strlen(pages)+1); strcpy( items[listlen].pages, pages); listlen ++; } list = (indexitem **) malloc(listlen*sizeof(indexitem *)); for (i=0; itext, list[j]->text) == 0; ++j) { list[i]->pages = (char *) realloc( list[i]->pages, strlen(list[i]->pages) + strlen(list[j]->pages) + 3); strcat(list[i]->pages,", "); strcat(list[i]->pages,list[j]->pages); free(list[j]->pages); free(list[j]->text); list[j]->pages = NULL; list[j]->text = NULL; } } /* Output the sorted and consolidated index */ fprintf(stderr,"Output index\n"); for (i=0; itext != NULL) { fputs(list[i]->text,output); fputs(" ",output); fputs(list[i]->pages,output); fputc('\n',output); } } } int indexcompare( void *first, void *second ) { indexitem *one = (indexitem *)first; indexitem *two = (indexitem *)second; int i; return strcmpnc(one->text, two->text); } /** Compare two strings, ignoring differences in upper/lower case. */ int strcmpnc( char one[], char two[] ) { int i; for (i=0; i < strlen(one); ++i) { int dif = _tolower(one[i]) - _tolower(two[i]); if (dif != 0) return(dif); } if (strlen(two) > i) return -1; else return 0; }