home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fonts 1 / freshfonts1.bin / bbs / programs / amiga / makeindex.lha / makeindex-2.12 / src / genind.c next >
C/C++ Source or Header  |  1993-05-26  |  11KB  |  478 lines

  1. /*
  2.  *
  3.  *  This file is part of
  4.  *    MakeIndex - A formatter and format independent index processor
  5.  *
  6.  *  Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
  7.  *  Copyright (C) 1988 by Olivetti Research Center
  8.  *  Copyright (C) 1987 by Regents of the University of California
  9.  *
  10.  *  Author:
  11.  *    Pehong Chen
  12.  *    Chen & Harrison International Systems, Inc.
  13.  *    Palo Alto, California
  14.  *    USA
  15.  *    (phc@renoir.berkeley.edu or chen@orc.olivetti.com)
  16.  *
  17.  *  Contributors:
  18.  *    Please refer to the CONTRIB file that comes with this release
  19.  *    for a list of people who have contributed to this and/or previous
  20.  *    release(s) of MakeIndex.
  21.  *
  22.  *  All rights reserved by the copyright holders.  See the copyright
  23.  *  notice distributed with this software for a complete description of
  24.  *  the conditions under which it is made available.
  25.  *
  26.  */
  27.  
  28. #include    "mkind.h"
  29. #include    "genind.h"
  30.  
  31. #if sun                /* avoid conflict with symbol in */
  32.                 /* /usr/lang/SC1.0/include/CC/stdlib.h */
  33. #define end    the_end
  34. #endif
  35.  
  36. static FIELD_PTR curr = NULL;
  37. static FIELD_PTR prev = NULL;
  38. static FIELD_PTR begin = NULL;
  39. static FIELD_PTR end = NULL;
  40. static FIELD_PTR range_ptr;
  41. static int level = 0;
  42. static int prev_level = 0;
  43. static char *encap = NULL;
  44. static char *prev_encap = NULL;
  45. static int in_range = FALSE;
  46. static int encap_range = FALSE;
  47. static char buff[2 * ARGUMENT_MAX];
  48. static char line[2 * ARGUMENT_MAX];    /* output buffer */
  49. static int ind_lc = 0;            /* overall line count */
  50. static int ind_ec = 0;            /* erroneous line count */
  51. static int ind_indent;
  52.  
  53. static    void    flush_line ARGS((int print));
  54. static    void    insert_page ARGS((void));
  55. static    int    make_entry ARGS((int n));
  56. static    void    make_item ARGS((char* term));
  57. static    void    new_entry ARGS((void));
  58. static    void    old_entry ARGS((void));
  59. static    int    page_diff ARGS((struct KFIELD *a,struct KFIELD *b));
  60. static    void    put_header ARGS((int let));
  61. static    void    wrap_line ARGS((int print));
  62.  
  63. void
  64. gen_ind(VOID_ARG)
  65. {
  66.     int     n;
  67.     int     tmp_lc;
  68.  
  69.     MESSAGE("Generating output file %s...", ind_fn);
  70.     PUT(preamble);
  71.     ind_lc += prelen;
  72.     if (init_page)
  73.     insert_page();
  74.  
  75.     /* reset counters for putting out dots */
  76.     idx_dc = 0;
  77.     for (n = 0; n < idx_gt; n++) {
  78.     if (idx_key[n]->type != DUPLICATE)
  79.         if (make_entry(n)) {
  80.         IDX_DOT(DOT_MAX);
  81.         }
  82.     }
  83.     tmp_lc = ind_lc;
  84.     if (in_range) {
  85.     curr = range_ptr;
  86.     IND_ERROR("Unmatched range opening operator %c.\n", idx_ropen);
  87.     }
  88.     prev = curr;
  89.     flush_line(TRUE);
  90.     PUT(delim_t);
  91.     PUT(postamble);
  92.     tmp_lc = ind_lc + postlen;
  93.     if (ind_ec == 1) {
  94.     DONE(tmp_lc, "lines written", ind_ec, "warning");
  95.     } else {
  96.     DONE(tmp_lc, "lines written", ind_ec, "warnings");
  97.     }
  98. }
  99.  
  100.  
  101. static int
  102. #if STDC
  103. make_entry(int n)
  104. #else
  105. make_entry(n)
  106. int     n;
  107. #endif
  108. {
  109.     int     let;
  110.  
  111.     /* determine current and previous pointer */
  112.     prev = curr;
  113.     curr = idx_key[n];
  114.     /* check if current entry is in range */
  115.     if ((*curr->encap == idx_ropen) || (*curr->encap == idx_rclose))
  116.     encap = &(curr->encap[1]);
  117.     else
  118.     encap = curr->encap;
  119.  
  120.     /* determine the current nesting level */
  121.     if (n == 0) {
  122.     prev_level = level = 0;
  123.     let = *curr->sf[0];
  124.     put_header(let);
  125.     make_item(NIL);
  126.     } else {
  127.     prev_level = level;
  128.     for (level = 0; level < FIELD_MAX; level++)
  129.         if (STRNEQ(curr->sf[level], prev->sf[level]) ||
  130.         STRNEQ(curr->af[level], prev->af[level]))
  131.         break;
  132.     if (level < FIELD_MAX)
  133.         new_entry();
  134.     else
  135.         old_entry();
  136.     }
  137.  
  138.     if (*curr->encap == idx_ropen)
  139.     if (in_range) {
  140.         IND_ERROR("Extra range opening operator %c.\n", idx_ropen);
  141.     } else {
  142.         in_range = TRUE;
  143.         range_ptr = curr;
  144.     }
  145.     else if (*curr->encap == idx_rclose)
  146.     if (in_range) {
  147.         in_range = FALSE;
  148.         if (STRNEQ(&(curr->encap[1]), "") &&
  149.         STRNEQ(prev_encap, &(curr->encap[1]))) {
  150. IND_ERROR("Range closing operator has an inconsistent encapsulator %s.\n",
  151.               &(curr->encap[1]));
  152.         }
  153.     } else {
  154.         IND_ERROR("Unmatched range closing operator %c.\n", idx_rclose);
  155.     }
  156.     else if ((*curr->encap != NUL) &&
  157.          STRNEQ(curr->encap, prev_encap) && in_range)
  158.     IND_ERROR("Inconsistent page encapsulator %s within range.\n",
  159.           curr->encap);
  160.     return (1);
  161. }
  162.  
  163.  
  164. static void
  165. #if STDC
  166. make_item(char *term)
  167. #else
  168. make_item(term)
  169. char   *term;
  170. #endif
  171. {
  172.     int     i;
  173.  
  174.     if (level > prev_level) {
  175.     /* ascending level */
  176.     if (*curr->af[level] == NUL)
  177.         sprintf(line, "%s%s%s", term, item_u[level], curr->sf[level]);
  178.     else
  179.         sprintf(line, "%s%s%s", term, item_u[level], curr->af[level]);
  180.     ind_lc += ilen_u[level];
  181.     } else {
  182.     /* same or descending level */
  183.     if (*curr->af[level] == NUL)
  184.         sprintf(line, "%s%s%s", term, item_r[level], curr->sf[level]);
  185.     else
  186.         sprintf(line, "%s%s%s", term, item_r[level], curr->af[level]);
  187.     ind_lc += ilen_r[level];
  188.     }
  189.  
  190.     i = level + 1;
  191.     while (i < FIELD_MAX && *curr->sf[i] != NUL) {
  192.     PUT(line);
  193.     if (*curr->af[i] == NUL)
  194.         sprintf(line, "%s%s", item_x[i], curr->sf[i]);
  195.     else
  196.         sprintf(line, "%s%s", item_x[i], curr->af[i]);
  197.     ind_lc += ilen_x[i];
  198.     level = i;        /* Added at 2.11 <brosig@gmdzi.gmd.de> */
  199.     i++;
  200.     }
  201.  
  202.     ind_indent = 0;
  203.     strcat(line, delim_p[level]);
  204.     SAVE;
  205. }
  206.  
  207.  
  208. static void
  209. new_entry(VOID_ARG)
  210. {
  211.     int    let;
  212.     FIELD_PTR ptr;
  213.  
  214.     if (in_range) {
  215.     ptr = curr;
  216.     curr = range_ptr;
  217.     IND_ERROR("Unmatched range opening operator %c.\n", idx_ropen);
  218.     in_range = FALSE;
  219.     curr = ptr;
  220.     }
  221.     flush_line(TRUE);
  222.  
  223.     /* beginning of a new group? */
  224.  
  225.     if (((curr->group != ALPHA) && (curr->group != prev->group) &&
  226.      (prev->group == SYMBOL)) ||
  227.     ((curr->group == ALPHA) &&
  228.      ((unsigned char)(let = TOLOWER(curr->sf[0][0])) 
  229.       != (TOLOWER(prev->sf[0][0])))) ||
  230.     (german_sort &&
  231.      (curr->group != ALPHA) && (prev->group == ALPHA))) {
  232.     PUT(delim_t);
  233.     PUT(group_skip);
  234.     ind_lc += skiplen;
  235.     /* beginning of a new letter? */
  236.     put_header(let);
  237.     make_item(NIL);
  238.     } else
  239.     make_item(delim_t);
  240. }
  241.  
  242.  
  243. static void
  244. old_entry(VOID_ARG)
  245. {
  246.     int     diff;
  247.  
  248.     /* current entry identical to previous one: append pages */
  249.     diff = page_diff(end, curr);
  250.  
  251.     if ((prev->type == curr->type) && (diff != -1) &&
  252.     (((diff == 0) && (prev_encap != NULL) && STREQ(encap, prev_encap)) ||
  253.      (merge_page && (diff == 1) &&
  254.       (prev_encap != NULL) && STREQ(encap, prev_encap)) ||
  255.      in_range)) {
  256.     end = curr;
  257.     /* extract in-range encaps out */
  258.     if (in_range &&
  259.         (*curr->encap != NUL) &&
  260.         (*curr->encap != idx_rclose) &&
  261.         STRNEQ(curr->encap, prev_encap)) {
  262.         sprintf(buff, "%s%s%s%s%s", encap_p, curr->encap,
  263.             encap_i, curr->lpg, encap_s);
  264.         wrap_line(FALSE);
  265.     }
  266.     if (in_range)
  267.         encap_range = TRUE;
  268.     } else {
  269.     flush_line(FALSE);
  270.     if ((diff == 0) && (prev->type == curr->type)) {
  271. IND_ERROR(
  272. "Conflicting entries: multiple encaps for the same page under same key.\n",
  273. "");
  274.     } else if (in_range && (prev->type != curr->type)) {
  275. IND_ERROR(
  276. "Illegal range formation: starting & ending pages are of different types.\n",
  277. "");
  278.     } else if (in_range && (diff == -1)) {
  279. IND_ERROR(
  280. "Illegal range formation: starting & ending pages cross chap/sec breaks.\n",
  281. "");
  282.     }
  283.     SAVE;
  284.     }
  285. }
  286.  
  287.  
  288. static int
  289. #if STDC
  290. page_diff(FIELD_PTR a,FIELD_PTR b)
  291. #else
  292. page_diff(a, b)
  293. FIELD_PTR a;
  294. FIELD_PTR b;
  295. #endif
  296. {
  297.     short   i;
  298.  
  299.     if (a->count != b->count)
  300.     return (-1);
  301.     for (i = 0; i < a->count - 1; i++)
  302.     if (a->npg[i] != b->npg[i])
  303.         return (-1);
  304.     return (b->npg[b->count - 1] - a->npg[a->count - 1]);
  305. }
  306.  
  307. static void
  308. #if STDC
  309. put_header(int let)
  310. #else
  311. put_header(let)
  312. int    let;
  313. #endif
  314. {
  315.     if (headings_flag)
  316.     {
  317.     PUT(heading_pre);
  318.     ind_lc += headprelen;
  319.     switch (curr->group)
  320.     {
  321.     case SYMBOL:
  322.         if (headings_flag > 0)
  323.         {
  324.         PUT(symhead_pos);
  325.         }
  326.         else
  327.         {
  328.         PUT(symhead_neg);
  329.         }
  330.         break;
  331.     case ALPHA:
  332.         if (headings_flag > 0)
  333.         {
  334.         let = TOUPPER(let);
  335.         PUTC(let);
  336.         }
  337.         else
  338.         {
  339.         let = TOLOWER(let);
  340.         PUTC(let);
  341.         }
  342.         break;
  343.     default:
  344.         if (headings_flag > 0)
  345.         {
  346.         PUT(numhead_pos);
  347.         }
  348.         else
  349.         {
  350.         PUT(numhead_neg);
  351.         }
  352.         break;
  353.     }
  354.     PUT(heading_suf);
  355.     ind_lc += headsuflen;
  356.     }
  357. }
  358.  
  359.  
  360. /* changes for 2.12 (May 20, 1993) by Julian Reschke (jr@ms.maus.de):
  361.    Use keywords suffix_2p, suffix_3p or suffix_mp for one, two or
  362.    multiple page ra