Back to index

tetex-bin  3.0
mkind.c
Go to the documentation of this file.
00001 /*
00002  *
00003  *  This file is part of
00004  *     MakeIndex - A formatter and format independent index processor
00005  *
00006  *  Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
00007  *  Copyright (C) 1988 by Olivetti Research Center
00008  *  Copyright (C) 1987 by Regents of the University of California
00009  *
00010  *  Author:
00011  *     Pehong Chen
00012  *     Chen & Harrison International Systems, Inc.
00013  *     Palo Alto, California
00014  *     USA
00015  *     (phc@renoir.berkeley.edu or chen@orc.olivetti.com)
00016  *
00017  *  Contributors:
00018  *     Please refer to the CONTRIB file that comes with this release
00019  *     for a list of people who have contributed to this and/or previous
00020  *     release(s) of MakeIndex.
00021  *
00022  *  All rights reserved by the copyright holders.  See the copyright
00023  *  notice distributed with this software for a complete description of
00024  *  the conditions under which it is made available.
00025  *
00026  */
00027 
00028 #define MKIND_C      1
00029 #include    "mkind.h"
00030 #undef MKIND_C
00031 
00032 int     letter_ordering = FALSE;
00033 int     compress_blanks = FALSE;
00034 int     merge_page = TRUE;
00035 int     init_page = FALSE;
00036 int     even_odd = -1;
00037 int     verbose = TRUE;
00038 int     german_sort = FALSE;
00039 int     thai_sort = FALSE;
00040 int     locale_sort = FALSE;
00041 int     fn_no = -1;                /* total number of files */
00042 int     idx_dot = TRUE;                   /* flag which shows dot in ilg being
00043                                    * active */
00044 int     idx_tt = 0;                /* total entry count (all files) */
00045 int     idx_et = 0;                /* erroneous entry count (all files) */
00046 int     idx_gt = 0;                /* good entry count (all files) */
00047 
00048 FIELD_PTR *idx_key;
00049 FILE   *log_fp;
00050 FILE   *sty_fp;
00051 FILE   *idx_fp;
00052 FILE   *ind_fp;
00053 FILE   *ilg_fp;
00054 
00055 char   *pgm_fn;
00056 char    sty_fn[LINE_MAX];
00057 char   *idx_fn;
00058 char    ind[STRING_MAX];
00059 char   *ind_fn;
00060 char    ilg[STRING_MAX];
00061 char   *ilg_fn;
00062 char    pageno[NUMBER_MAX];
00063 
00064 static char log_fn[STRING_MAX];
00065 static char base[STRING_MAX];
00066 static int need_version = TRUE;
00067 
00068 static void   check_all ARGS((char *fn,int ind_given,int ilg_given,
00069                      int log_given));
00070 static void   check_idx ARGS((char *fn,int open_fn));
00071 static void   find_pageno ARGS((void));
00072 static void   open_sty ARGS((char *fn));
00073 static void   prepare_idx ARGS((void));
00074 static void   process_idx ARGS((char * *fn,int use_stdin,int sty_given,
00075                      int ind_given,int ilg_given,int log_given));
00076 
00077 #ifdef DEBUG
00078 long totmem = 0L;                  /* for debugging memory usage */
00079 #endif /* DEBUG */
00080 
00081 int
00082 #if STDC
00083 main(int argc, char *argv[])
00084 #else
00085 main(argc, argv)
00086 int     argc;
00087 char   *argv[];
00088 #endif
00089 {
00090     char   *fns[ARRAY_MAX];
00091     char   *ap;
00092     int     use_stdin = FALSE;
00093     int     sty_given = FALSE;
00094     int     ind_given = FALSE;
00095     int     ilg_given = FALSE;
00096     int     log_given = FALSE;
00097 
00098     /* determine program name */
00099     pgm_fn = strrchr(*argv, DIR_DELIM);
00100 #ifdef ALT_DIR_DELIM
00101     {
00102       char *alt_delim = strrchr(*argv, ALT_DIR_DELIM);
00103 
00104       if (pgm_fn == NULL || (alt_delim != NULL && alt_delim > pgm_fn))
00105        pgm_fn = alt_delim;
00106     }
00107 #endif
00108     if (pgm_fn == NULL)
00109        pgm_fn = *argv;
00110     else
00111        pgm_fn++;
00112 
00113 #if USE_KPATHSEA
00114     kpse_set_progname (pgm_fn);  /* use the same name as the intro message */
00115 #endif
00116 
00117 
00118     /* process command line options */
00119     while (--argc > 0) {
00120        if (**++argv == SW_PREFIX) {
00121            if (*(*argv + 1) == NUL)
00122               break;
00123            for (ap = ++*argv; *ap != NUL; ap++)
00124               switch (*ap) {
00125                   /* use standard input */
00126               case 'i':
00127                   use_stdin = TRUE;
00128                   break;
00129 
00130                   /* enable letter ordering */
00131               case 'l':
00132                   letter_ordering = TRUE;
00133                   break;
00134 
00135                   /* disable range merge */
00136               case 'r':
00137                   merge_page = FALSE;
00138                   break;
00139 
00140                   /* supress progress message -- quiet mode */
00141               case 'q':
00142                   verbose = FALSE;
00143                   break;
00144 
00145                   /* compress blanks */
00146               case 'c':
00147                   compress_blanks = TRUE;
00148                   break;
00149 
00150                   /* style file */
00151               case 's':
00152                   argc--;
00153                   if (argc <= 0)
00154                      FATAL("Expected -s <stylefile>\n","");
00155                   open_sty(*++argv);
00156                   sty_given = TRUE;
00157                   break;
00158 
00159                   /* output index file name */
00160               case 'o':
00161                   argc--;
00162                   if (argc <= 0)
00163                      FATAL("Expected -o <ind>\n","");
00164                   ind_fn = *++argv;
00165                   ind_given = TRUE;
00166                   break;
00167 
00168                   /* transcript file name */
00169               case 't':
00170                   argc--;
00171                   if (argc <= 0)
00172                      FATAL("Expected -t <logfile>\n","");
00173                   ilg_fn = *++argv;
00174                   ilg_given = TRUE;
00175                   break;
00176 
00177                   /* initial page */
00178               case 'p':
00179                   argc--;
00180                   if (argc <= 0)
00181                      FATAL("Expected -p <num>\n","");
00182                   strcpy(pageno, *++argv);
00183                   init_page = TRUE;
00184                   if (STREQ(pageno, EVEN)) {
00185                      log_given = TRUE;
00186                      even_odd = 2;
00187                   } else if (STREQ(pageno, ODD)) {
00188                      log_given = TRUE;
00189                      even_odd = 1;
00190                   } else if (STREQ(pageno, ANY)) {
00191                      log_given = TRUE;
00192                      even_odd = 0;
00193                   }
00194                   break;
00195 
00196                   /* enable german sort */
00197               case 'g':
00198                   german_sort = TRUE;
00199                   break;
00200 
00201 #ifdef HAVE_SETLOCALE
00202                   /* enable locale-based sort */
00203               case 'L':
00204                   locale_sort = TRUE;
00205                   break;
00206 
00207                   /* enable Thai sort */
00208               case 'T':
00209                   thai_sort = locale_sort = TRUE;
00210                   break;
00211 #endif
00212 
00213                   /* bad option */
00214               default:
00215                   FATAL("Unknown option -%c.\n", *ap);
00216                   break;
00217               }
00218        } else {
00219            if (fn_no < ARRAY_MAX) {
00220               check_idx(*argv, FALSE);
00221               fns[++fn_no] = *argv;
00222            } else {
00223               FATAL("Too many input files (max %d).\n", ARRAY_MAX);
00224            }
00225        }
00226     }
00227 
00228        if (fn_no == 0 && !sty_given)
00229        {
00230               char tmp[STRING_MAX + 5];
00231               
00232               /* base set by last call to check_idx */
00233               sprintf (tmp, "%s%s", base, INDEX_STY);
00234               if (0 == access(tmp, R_OK)) {
00235                      open_sty (tmp);
00236                      sty_given = TRUE;
00237               }
00238        }
00239  
00240     process_idx(fns, use_stdin, sty_given, ind_given, ilg_given, log_given);
00241     idx_gt = idx_tt - idx_et;
00242     ALL_DONE;
00243     if (idx_gt > 0) {
00244        prepare_idx();
00245        sort_idx();
00246        gen_ind();
00247        MESSAGE("Output written in %s.\n", ind_fn);
00248     } else
00249        MESSAGE("Nothing written in %s.\n", ind_fn);
00250 
00251     MESSAGE("Transcript written in %s.\n", ilg_fn);
00252     CLOSE(ind_fp);
00253     CLOSE(ilg_fp);
00254     EXIT(0);
00255 
00256     return (0);                           /* never executed--avoids complaints */
00257     /* about no return value */
00258 }
00259 
00260 
00261 static void
00262 prepare_idx(VOID_ARG)
00263 {
00264     NODE_PTR ptr = head;
00265     int     i = 0;
00266 
00267 #ifdef DEBUG
00268     totmem += idx_gt * sizeof(FIELD_PTR);
00269     (void)fprintf(stderr,"prepare_idx(): calloc(%d,%d)\ttotmem = %ld\n",
00270        idx_gt,sizeof(FIELD_PTR),totmem);
00271 #endif /* DEBUG */
00272 
00273     if (head == (NODE_PTR)NULL)
00274        FATAL("No valid index entries collected.\n", "");
00275 
00276     if ((idx_key = (FIELD_PTR *) calloc(idx_gt, sizeof(FIELD_PTR))) == NULL) {
00277        FATAL("Not enough core...abort.\n", "");
00278     }
00279     for (i = 0; i < idx_gt; i++) {
00280        idx_key[i] = &(ptr->data);
00281        ptr = ptr->next;
00282     }
00283 }
00284 
00285 
00286 static void
00287 #if STDC
00288 process_idx(char *fn[], int use_stdin, int sty_given, int ind_given,
00289            int ilg_given, int log_given)
00290 #else
00291 process_idx(fn, use_stdin, sty_given, ind_given, ilg_given, log_given)
00292 char   *fn[];
00293 int     use_stdin;
00294 int     sty_given;
00295 int     ind_given;
00296 int     ilg_given;
00297 int     log_given;
00298 #endif
00299 {
00300     int     i;
00301 
00302     if (fn_no == -1)
00303        /* use stdin if no input files specified */
00304        use_stdin = TRUE;
00305     else {
00306        check_all(fn[0], ind_given, ilg_given, log_given);
00307        PUT_VERSION;
00308        if (sty_given)
00309            scan_sty();
00310        if (german_sort && (idx_quote == '"'))
00311 FATAL("Option -g invalid, quote character must be different from '%c'.\n",
00312 '"');
00313        scan_idx();
00314        ind_given = TRUE;
00315        ilg_given = TRUE;
00316        for (i = 1; i <= fn_no; i++) {
00317            check_idx(fn[i], TRUE);
00318            scan_idx();
00319        }
00320     }
00321 
00322     if (use_stdin) {
00323        idx_fn = "stdin";
00324        idx_fp = stdin;
00325 
00326        if (ind_given) {
00327            if (!ind_fp && ((ind_fp = OPEN_OUT(ind_fn)) == NULL))
00328               FATAL("Can't create output index file %s.\n", ind_fn);
00329        } else {
00330            ind_fn = "stdout";
00331            ind_fp = stdout;
00332        }
00333 
00334        if (ilg_given) {
00335            if (!ilg_fp && ((ilg_fp = OPEN_OUT(ilg_fn)) == NULL))
00336               FATAL("Can't create transcript file %s.\n", ilg_fn);
00337        } else {
00338            ilg_fn = "stderr";
00339            ilg_fp = stderr;
00340             /* This is already equivalent to verbose mode... */
00341             verbose = FALSE;
00342        }
00343 
00344        if ((fn_no == -1) && (sty_given))
00345            scan_sty();
00346        if (german_sort && (idx_quote == '"'))
00347 FATAL("Option -g ignored, quote character must be different from '%c'.\n",
00348 '"');
00349 
00350        if (need_version) {
00351            PUT_VERSION;
00352        }
00353        scan_idx();
00354        fn_no++;
00355     }
00356 }
00357 
00358 
00359 static void
00360 #if STDC
00361 check_idx(char *fn, int open_fn)
00362 #else
00363 check_idx(fn, open_fn)
00364 char   *fn;
00365 int     open_fn;
00366 #endif
00367 {
00368     char   *ptr = fn;
00369     char   *ext;
00370     int     with_ext = FALSE;
00371     int     i = 0;
00372 
00373     ext = strrchr(fn, EXT_DELIM);
00374     if ((ext != NULL) && (ext != fn) && (strchr(ext + 1, DIR_DELIM) == NULL)
00375 #ifdef ALT_DIR_DELIM
00376        && (strchr(ext + 1, ALT_DIR_DELIM) == NULL)
00377 #endif
00378        ) {
00379        with_ext = TRUE;
00380        while ((ptr != ext) && (i < STRING_MAX))
00381            base[i++] = *ptr++;
00382     } else
00383        while ((*ptr != NUL) && (i < STRING_MAX))
00384            base[i++] = *ptr++;
00385 
00386     if (i < STRING_MAX)
00387        base[i] = NUL;
00388     else
00389        FATAL2("Index file name %s too long (max %d).\n",
00390               base, STRING_MAX);
00391 
00392     idx_fn = fn;
00393 
00394     if ( ( open_fn && 
00395         ((idx_fp = OPEN_IN(idx_fn)) == NULL)
00396         ) ||
00397        ((!open_fn) && (access(idx_fn, R_OK) != 0)))
00398        if (with_ext) {
00399            FATAL("Input index file %s not found.\n", idx_fn);
00400        } else {
00401 
00402 #ifdef DEBUG
00403            totmem += STRING_MAX;
00404            (void)fprintf(stderr,"check_idx()-2: malloc(%d)\ttotmem = %ld\n",
00405                   STRING_MAX,totmem);
00406 #endif /* DEBUG */
00407 
00408            if ((idx_fn = (char *) malloc(STRING_MAX)) == NULL)
00409               FATAL("Not enough core...abort.\n", "");
00410            sprintf(idx_fn, "%s%s", base, INDEX_IDX);
00411            if ((open_fn && 
00412         ((idx_fp = OPEN_IN(idx_fn)) == NULL)
00413        ) ||
00414               ((!open_fn) && (access(idx_fn, R_OK) != 0))) {
00415               FATAL2("Couldn't find input index file %s nor %s.\n", base,
00416                      idx_fn);
00417            }
00418        }
00419 }
00420 
00421 
00422 static void
00423 #if STDC
00424 check_all(char *fn, int ind_given, int ilg_given, int log_given)
00425 #else
00426 check_all(fn, ind_given, ilg_given, log_given)
00427 char   *fn;
00428 int     ind_given;
00429 int     ilg_given;
00430 int     log_given;
00431 #endif
00432 {
00433     check_idx(fn, TRUE);
00434 
00435     /* index output file */
00436     if (!ind_given) {
00437        sprintf(ind, "%s%s", base, INDEX_IND);
00438        ind_fn = ind;
00439     }
00440     if ((ind_fp = OPEN_OUT(ind_fn)) == NULL)
00441        FATAL("Can't create output index file %s.\n", ind_fn);
00442 
00443     /* index transcript file */
00444     if (!ilg_given) {
00445        sprintf(ilg, "%s%s", base, INDEX_ILG);
00446        ilg_fn = ilg;
00447     }
00448     if ((ilg_fp = OPEN_OUT(ilg_fn)) == NULL)
00449        FATAL("Can't create transcript file %s.\n", ilg_fn);
00450 
00451     if (log_given) {
00452        sprintf(log_fn, "%s%s", base, INDEX_LOG);
00453        if ((log_fp = OPEN_IN(log_fn)) == NULL) {
00454            FATAL("Source log file %s not found.\n", log_fn);
00455        } else {
00456            find_pageno();
00457            CLOSE(log_fp);
00458        }
00459     }
00460 }
00461 
00462 
00463 static void
00464 find_pageno(VOID_ARG)
00465 {
00466     int     i = 0;
00467     int     p, c;
00468 
00469     fseek(log_fp, -1L, 2);
00470     p = GET_CHAR(log_fp);
00471     fseek(log_fp, -2L, 1);
00472     do {
00473        c = p;
00474        p = GET_CHAR(log_fp);
00475     } while (!(((p == LSQ) && isdigit(c)) || (fseek(log_fp, -2L, 1) != 0)));
00476     if (p == LSQ) {
00477        while ((c = GET_CHAR(log_fp)) == SPC);
00478        do {
00479            pageno[i++] = (char) c;
00480            c = GET_CHAR(log_fp);
00481        } while (isdigit(c));
00482        pageno[i] = NUL;
00483     } else {
00484        fprintf(ilg_fp, "Couldn't find any page number in %s...ignored\n",
00485               log_fn);
00486        init_page = FALSE;
00487     }
00488 }
00489 
00490 static void
00491 #if STDC
00492 open_sty(char *fn)
00493 #else
00494 open_sty(fn)
00495 char   *fn;
00496 #endif
00497 {
00498     char   *path;
00499     char   *ptr;
00500     int     i;
00501     int     len;
00502 #if USE_KPATHSEA
00503     char   *found;
00504 
00505   if ((found = kpse_find_file (fn, kpse_ist_format, 1)) == NULL) {
00506      FATAL("Index style file %s not found.\n", fn);
00507   } else {
00508     strcpy(sty_fn,found);
00509     if ((sty_fp = OPEN_IN(sty_fn)) == NULL) {
00510       FATAL("Could not open style file %s.\n", sty_fn);
00511     }
00512   }
00513 #else
00514     if ((path = getenv(STYLE_PATH)) == NULL) {
00515        /* style input path not defined */
00516        strcpy(sty_fn, fn);
00517        sty_fp = OPEN_IN(sty_fn);
00518     } else {
00519        len = ARRAY_MAX - strlen(fn) - 1;
00520        while (*path != NUL) {
00521            ptr = strchr(path, ENV_SEPAR);
00522            i = 0;
00523            if (ptr == (char*)NULL)
00524            {
00525               int j = strlen(path);
00526 
00527               while (i < j)
00528                   sty_fn[i++] = *path++;
00529            }
00530            else
00531            {
00532               while ((path != ptr) && (i < len))
00533                   sty_fn[i++] = *path++;
00534            }
00535            if (i == len) {
00536               FATAL2("Path %s too long (max %d).\n", sty_fn, ARRAY_MAX);
00537            } else {
00538               sty_fn[i++] = DIR_DELIM;
00539               sty_fn[i] = NUL;
00540               strcat(sty_fn, fn);
00541               if ((sty_fp = OPEN_IN(sty_fn)) == NULL)
00542                   path++;
00543               else
00544                   break;
00545            }
00546        }
00547     }
00548 
00549     if (sty_fp == NULL)
00550        FATAL("Index style file %s not found.\n", fn);
00551 #endif
00552 }
00553 
00554 
00555 int
00556 #if STDC
00557 strtoint(char *str)
00558 #else
00559 strtoint(str)
00560 char   *str;
00561 #endif
00562 {
00563     int     val = 0;
00564 
00565     while (*str != NUL) {
00566        val = 10 * val + *str - 48;
00567        str++;
00568     }
00569     return (val);
00570 }