home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / proglc / cxref.lzh / XC.C next >
Encoding:
C/C++ Source or Header  |  1987-09-27  |  21.4 KB  |  929 lines

  1. /**********************************************************
  2.  
  3.       XC  -  A 'C' Concordance Utility
  4.  
  5.       Version 1.0   January, 1982
  6.  
  7.       Copyright (c) 1982 by Philip N. Hisley
  8.  
  9.           Philip N. Hisley
  10.           548H Jamestown Court
  11.           Edgewood, Maryland 21040
  12.           (301) 679-4606
  13.  
  14.       Released for non-commercial distribution only
  15.  
  16.  
  17.  
  18.  
  19.       Converted to IBM/PC CI/C86 by David N. Smith, May/June 1983
  20.       with enhancements and Lattice compiler support in December 1983.
  21.  
  22.           David N. Smith
  23.           44 Ole Musket Lane
  24.           Danbury, CT 06810
  25.           (203) 748-5934
  26.           CompuServe: 73145,153
  27.  
  28.       Changes Copyright (c) 1983 by David N. Smith
  29.       Permission granted to copy for non-commercial purporses.
  30.  
  31.       PC Enhancements include:
  32.  
  33.        1)  Nested #INCLUDE statements
  34.        2)  Single spaced cross-reference list
  35.        3)  Removal of tabbing on output device
  36.            (Since many printers don't support it)
  37.        4)  #INCLUDE statements with both "--" and <-->
  38.            syntax and with a full fileid in the quotes.
  39.        5)  Multiple input filenames on command line.
  40.  
  41.  
  42.  
  43.       Abstract:
  44.  
  45.       'XC' is a cross-reference utility for 'C' programs.
  46.       Its has the ability to handle nested include files
  47.       to a depth of 8 levels and properly processes nested
  48.       comments as supported by BDS C. Option flags support
  49.       the following features:
  50.  
  51.       - Routing of list output to disk
  52.       - Cross-referencing of reserved words
  53.       - Processing of nested include files
  54.       - Generation of listing only
  55.  
  56.       Usage: xc <filename> <flag(s)>
  57.  
  58.       Flags: -i        = Enable file inclusion
  59.          -l        = Generate listing only
  60.          -r        = Cross-ref reserved words
  61.          -o <filename> = Write output to named file
  62.  
  63.  
  64. ***********************************************************/
  65.  
  66. #include "stdio.h"
  67.  
  68. /* Compiler specific stuff */
  69.  
  70. #ifdef Lattice
  71. #include "ctype.h"
  72. #endif
  73. /* end compiler specific section */
  74.  
  75. #ifndef  TRUE
  76. #define  TRUE         1
  77. #define  FALSE         0
  78. #endif
  79.  
  80. #define  ERROR        -1
  81. #define  MAX_REF     5       /* maximum refs per ref-block */
  82. #define  MAX_LEN    20       /* maximum identifier length  */
  83. #define  MAX_WRD   749       /* maximum number of identifiers */
  84. #define  MAX_ALPHA  53       /* maximum alpha chain heads */
  85. #define  REFS_PER_LINE    10 /* maximum refs per line */
  86. #define  LINES_PER_PAGE 60
  87. #define  MAXCOL     78       /* default maximum column # for listing line */
  88. #define  MINCOL     30       /* minimum value for -w option */
  89. #define  FF 0x0C       /* formfeed */
  90.  
  91. struct    rf_blk {
  92.          int  ref_item[MAX_REF];
  93.          int  ref_cnt;
  94.            } onerf;
  95.  
  96. struct    id_blk {
  97.          char  id_name[MAX_LEN];
  98.          struct id_blk *alpha_lnk;
  99.          struct rf_blk *top_lnk;
  100.          struct rf_blk *lst_lnk;
  101.            } oneid;
  102.  
  103. struct id_blk *id_vector[MAX_WRD];
  104.  
  105. struct alpha_hdr { struct id_blk *alpha_top;
  106.            struct id_blk *alpha_lst;
  107.          };
  108.  
  109. struct alpha_hdr alpha_vector[MAX_ALPHA];
  110.  
  111. int    linum;        /* line number */
  112. int    edtnum;     /* edit line number */
  113. int    fil_cnt;    /* active file index */
  114. int    wrd_cnt;    /* token count */
  115. int    pagno;        /* page number */
  116. int    id_cnt;     /* number of unique identifiers */
  117. int    rhsh_cnt;    /* number of conflict hits */
  118. int    filevl;     /* file level  */
  119. int    paglin;     /* page line counter */
  120. int    dummy;        /* dummy integer */
  121. int    maxcol=MAXCOL;    /* maximum right column for listing line */
  122. int    prt_ref;
  123. char    act_fil[MAX_LEN];
  124. char    lst_fil[MAX_LEN];
  125. char    gbl_fil[MAX_LEN];
  126. FILE    *f_lst_fil;
  127. int    i_flg,
  128.     o_flg,
  129.     r_flg,
  130.     l_flg;
  131.  
  132. long atoi();
  133.  
  134.  
  135. /*************************************************************************/
  136.  
  137. main(p_argc, p_argv)
  138. int    p_argc;
  139. char    **p_argv;
  140.  
  141. {
  142.     char  *arg;
  143.     int argc;
  144.     char **argv;
  145.     char c;
  146.     int i;
  147.  
  148.     argc = p_argc;
  149.     argv = p_argv;
  150.     if (argc < 2) use_err();
  151.     i_flg=r_flg=o_flg=l_flg=FALSE;
  152.     while(--argc != 0)
  153.      { if(*(arg=*++argv) == '-')
  154.     {switch(*++arg)
  155.      {
  156.        case 'i':
  157.        case 'I': i_flg++;
  158.              break;
  159.        case 'r':
  160.        case 'R': r_flg++;
  161.              break;
  162.        case 'l':
  163.        case 'L':  l_flg++;
  164.               break;
  165.        case 'o':
  166.        case 'O': { o_flg++;
  167.                if(--argc == 0) use_err();
  168.                strcpy(lst_fil,*++argv);
  169.                if(lst_fil[0] == '-') use_err();
  170.             break;}
  171.        case 'w':
  172.        case 'W': { if(--argc == 0) use_err();
  173.                i = atoi(*++argv);
  174.                if( i<=MINCOL || i>=255 ) use_err();
  175.                maxcol = i;
  176.                break;
  177.                }
  178.        default: use_err();
  179.      }
  180.        }
  181.      }
  182.  
  183.      if(o_flg)
  184.        {if( (f_lst_fil=fopen(lst_fil,"w")) == NULL)
  185.     { printf("ERROR: Unable to create list file - %s\n",lst_fil);
  186.       exit(0);}
  187.        printf("XC ... 'C' Concordance Utility  v1.0\n\n");
  188.     }
  189.  
  190.     prt_ref = FALSE;
  191.     for(linum=0;linum < MAX_WRD;linum++) {
  192.        id_vector[linum] = NULL; }
  193.     for(linum=0;linum < MAX_ALPHA;linum++)
  194.      {
  195.        alpha_vector[linum].alpha_top =
  196.        alpha_vector[linum].alpha_lst = NULL;
  197.      }
  198.     fil_cnt = wrd_cnt = linum = 0;
  199.     filevl=paglin=pagno=edtnum=0;
  200.     id_cnt=rhsh_cnt=0;
  201.  
  202.     argc = p_argc;  argc--;
  203.     argv = p_argv;
  204.     while(argc--) {
  205.        strcpy(gbl_fil,*++argv);
  206.        if(*gbl_fil == '-')  break;
  207.        proc_file(gbl_fil,dummy);
  208.        }
  209.     if(!l_flg) {
  210.       gbl_fil[0] = '\0';
  211.       prnt_tbl();
  212.       printf("\nAllowable Symbols: %d\n",MAX_WRD);
  213.       printf("Unique    Symbols: %d\n",id_cnt);}
  214.     if(o_flg) {
  215.      nl();
  216.      /* if(fprintf(f_lst_fil,"%c",CPMEOF) == ERROR) lst_err(); */
  217.      fclose(f_lst_fil);
  218.     }
  219. }
  220.  
  221. /*************************************************************************/
  222.  
  223. lst_err()
  224.  
  225. { printf("\nERROR: Write error on list output file - %s\n",
  226.    lst_fil);
  227.   exit(0);
  228. }
  229.  
  230. /*************************************************************************/
  231.  
  232. use_err()
  233.  
  234.        { printf("\nERROR: Invalid parameter specification\n\n");
  235.        printf("Usage: xc <filename>... <flag(s)>\n\n");
  236.        printf("Flags: -i            = Enable file inclusion\n");
  237.        printf("       -l            = Generate listing only\n");
  238.        printf("       -r            = Cross-reference reserved words\n");
  239.        printf("       -o <outfile>  = Write output to named file\n");
  240.        printf("       -w width      = Width of output page; default=78\n");
  241.        printf("Flags must follow all input file names");
  242.        exit(0); }
  243.  
  244. /*************************************************************************/
  245.  
  246. proc_file(filnam,incnum)
  247. char    *filnam;
  248. int     incnum;    /* prev. included line number (return to caller) */
  249.  
  250. {
  251.   char    token[MAX_LEN]; /* token buffer */
  252.   int    eof_flg;    /* end-of-file indicator */
  253.   int    tok_len;    /* token length */
  254.   FILE    *infile;    /* input file */
  255.  
  256.  
  257.   strcpy(act_fil,filnam);
  258.   edtnum=0;
  259.  
  260.   if((infile=fopen(filnam,"r")) == NULL)
  261.       {printf("\nERROR: Unable to open input file: %s\n",filnam);
  262.     return;}  /* ignore error */
  263.   if(filevl++ == 0) prt_hdr();
  264.   eof_flg = FALSE;
  265.   do {
  266.        if(getoken(infile,token,&tok_len,&eof_flg,0))
  267.       if(chk_token(token))
  268.          {
  269.          if(strcmp(token,"#include") == 0)
  270.         {
  271.         get_include_id(token,infile);
  272.         if(!i_flg) continue;
  273.         else
  274.            {
  275.            nl();
  276.            edtnum=proc_file(token,edtnum);
  277.            strcpy(act_fil,filnam);
  278.            continue;
  279.            }
  280.         }
  281.         putoken(token,linum);
  282.         }
  283.      } while (!eof_flg);
  284.  
  285.      filevl -= 1;
  286.      fclose(infile);
  287.  
  288.      return( incnum );
  289. }
  290.  
  291. /*************************************************************************/
  292.  
  293. get_include_id(token,infile)
  294. char *token;
  295. FILE *infile;
  296. {
  297.  
  298.    char c, term;
  299.  
  300.    while ( (term=getc(infile)) == ' ' )  echo(term);
  301.    echo(term);
  302.    if ( term=='<' ) term='>';   /* terminator is > or " */
  303.    if ( (term!='>') && (term!='"') )
  304.       {
  305.       printf("Error scanning #INCLUDE fileid: %c\n", term);
  306.       exit(1);
  307.       }
  308.  
  309.    do {
  310.       if ( (c = getc(infile)) != ' ')
  311.      {
  312.      *token++ = c;
  313.      echo(c);
  314.      }
  315.       else
  316.      echo(c);
  317.       }
  318.       while ( c!=term );
  319.  
  320.    *--token = '\0';
  321.  
  322. }
  323.  
  324. /*************************************************************************/
  325.  
  326. echo(c)
  327. char c;
  328. {
  329.    static int col = 11;
  330.    int i;
  331.    echochar(c);
  332.    if( c == '\n' )
  333.       col = 11;
  334.    else if( ++col > maxcol )  {
  335.       col = 11;
  336.       paglin++;
  337.       echochar('\n');
  338.       for( i=1; i<=11; i++ )  echochar(' ');
  339.       }
  340. }
  341.  
  342. echochar(c)
  343. char c;
  344. {
  345.    if(o_flg)  {
  346.       if(fprintf(f_lst_fil,"%c",c) == ERROR)  lst_err();
  347.       }
  348.    else
  349.       printf("%c",c);
  350. }
  351. /*************************************************************************/
  352.  
  353. getoken(infile,g_token,g_toklen,g_eoflg,g_flg)
  354.  
  355. FILE    *infile;
  356. char    *g_token;
  357. int    *g_toklen;
  358. int    *g_eoflg;
  359. int    g_flg;
  360.  
  361. /*
  362.     'getoken' returns the next valid identifier or
  363.     reserved word from a given file along with the
  364.     character length of the token and an end-of-file
  365.     indicator
  366. */
  367.  
  368. {
  369. int    c;
  370. char    *h_token;
  371. char    tmpchr;
  372.  
  373. h_token = g_token;
  374.  
  375. gtk:
  376. *g_toklen = 0;
  377. g_token = h_token;
  378.  
  379. /*
  380.     Scan and discard any characters until an alphabetic or
  381.     '_' (underscore) character is encountered or an end-of-file
  382.     condition occurs
  383. */
  384.  
  385. while( (!isalpha(*g_token = rdchr(infile,g_eoflg,g_flg)))
  386.   && !*g_eoflg
  387.   && *g_token != '_'
  388.   && *g_token != '0'
  389.   && *g_token != '#');
  390. if(*g_eoflg) return(FALSE);
  391. *g_toklen += 1;
  392.  
  393. /*
  394.     Scan and collect identified alpanumeric token until
  395.     a non-alphanumeric character is encountered or and
  396.     end-of-file condition occurs
  397. */
  398.  
  399. if(g_flg) tmpchr = '.';
  400.      else tmpchr = '_';
  401. while( (isalpha(c=rdchr(infile,g_eoflg,g_flg))
  402.     || isdigit(c)
  403.     || c == '_'
  404.     || c == tmpchr)
  405.      && !*g_eoflg)
  406.     {
  407.      if(*g_toklen < MAX_LEN)
  408.       { *++g_token = c;
  409.       *g_toklen += 1; }
  410.     }
  411.  
  412. /*
  413.     Check to see if a numeric hex or octal constant has
  414.     been encountered ... if so dump it and try again
  415. */
  416.  
  417.     if (*h_token == '0') goto gtk;
  418.  
  419.  
  420. /*
  421.     Tack a NULL character onto the end of the token
  422. */
  423.  
  424.  *++g_token = NULL;
  425.  
  426. /*
  427.     Screen out all #token strings except #include
  428. */
  429.  
  430. if (*h_token == '#' && strcmp(h_token,"#include")) goto gtk;
  431.  
  432.  return(TRUE);
  433. }
  434.  
  435. /*************************************************************************/
  436.  
  437.  fil_chr(infile,f_eof)
  438.    FILE *infile;
  439.    int *f_eof;
  440.    { int fc;
  441.    fc=getc(infile);
  442. /* if(fc == ERROR) {  /* omit since ERROR and EOF have save value for GETC  */
  443. /*   printf("\nERROR: Error while processing input file - %s\n",            */
  444. /*   act_fil);                                    */
  445. /*   exit(0);                                    */
  446. /*   }                                        */
  447.     if (fc == EOF) { *f_eof = TRUE;
  448.                      fc = NULL; }
  449.     return(fc);
  450. }
  451.  
  452. /*************************************************************************/
  453.  
  454. rdchr(infile,r_eoflg,rd_flg)
  455.  
  456. int    *r_eoflg;
  457. FILE    *infile;
  458. int    rd_flg;
  459.  
  460. /*
  461.     'rdchr' returns the next valid character in a file
  462.     and an end-of-file indicator. A valid character is
  463.     defined as any which does not appear in either a
  464.     commented or a quoted string ... 'rdchr' will correctly
  465.     handle comment tokens which appear within a quoted
  466.     string
  467. */
  468.  
  469. {
  470. int    c;
  471. int    q_flg;        /* double quoted string flag */
  472. int    q1_flg;     /* single quoted string flag */
  473. int    cs_flg;     /* comment start flag */
  474. int    ce_flg;     /* comment end flag */
  475. int    c_cnt;        /* comment nesting level */
  476. int    t_flg;        /* transparency flag */
  477.  
  478. q_flg = FALSE;
  479. q1_flg = FALSE;
  480. cs_flg = FALSE;
  481. ce_flg = FALSE;
  482. t_flg = FALSE;
  483. c_cnt  = 0;
  484.  
  485. rch:
  486.  
  487. /*
  488.     Fetch character from file
  489. */
  490.  
  491. c=fil_chr(infile,r_eoflg);
  492. if(*r_eoflg) return(c);   /* EOF encountered */
  493. if(c == '\n')
  494.         nl();
  495.          else
  496.         echo(c);
  497.  
  498. if(rd_flg) return(c);
  499.  
  500. if(t_flg) { t_flg = !t_flg;
  501.         goto rch;}
  502.  
  503. if(c == '\\') { t_flg = TRUE;
  504.         goto rch;}
  505. /*
  506.     If the character is not part of a quoted string
  507.     check for and process commented strings...
  508.     nested comments are handled correctly but unbalanced
  509.     comments are not ... the assumption is made that
  510.     the syntax of the program being xref'd is correct
  511. */
  512.  
  513. if (!q_flg && !q1_flg) {
  514.      if (c == '*' && c_cnt && !cs_flg) { ce_flg = TRUE;
  515.               goto rch;}
  516.      if (c == '/' && ce_flg) { c_cnt -= 1;
  517.               ce_flg = FALSE;
  518.               goto rch; }
  519.      ce_flg = FALSE;
  520.      if (c == '/') { cs_flg = TRUE;
  521.         goto rch; }
  522.      if (c == '*' && cs_flg) { c_cnt += 1;
  523.               cs_flg = FALSE;
  524.               goto rch; }
  525.      cs_flg = FALSE;
  526.      if (c_cnt) goto rch;
  527. }
  528.  
  529. /*
  530.     Check for and process quoted strings
  531. */
  532.  
  533. if ( c == '"' && !q1_flg) { q_flg =  !q_flg; /* toggle quote flag */
  534.             goto rch;}
  535. if (q_flg) goto rch;
  536.  
  537. if (c == '\'') { q1_flg = !q1_flg; /* toggle quote flag */
  538.         goto rch; }
  539. if (q1_flg) goto rch;
  540.  
  541. /*
  542.     Valid character ... return to caller
  543. */
  544.  
  545. return(c);
  546. }
  547.  
  548. /*************************************************************************/
  549.  
  550. chk_token(c_token)
  551. char    *c_token;
  552.  
  553. {
  554.   char    u_token[MAX_LEN];
  555.   int    i;
  556.  
  557.     {
  558.       if(r_flg) return(TRUE);
  559.       i = 0;
  560.       do { u_token[i] = toupper(c_token[i]); }
  561.      while (c_token[i++] != NULL);
  562.  
  563.       switch(u_token[0]) {
  564.     case 'A': if (strcmp(u_token,"AUTO") == 0) return(FALSE);
  565.           break;
  566.     case 'B': if (strcmp(u_token,"BREAK") == 0) return(FALSE);
  567.           break;
  568.     case 'C': if (strcmp(u_token,"CHAR") == 0) return (FALSE);
  569.           if (strcmp(u_token,"CONTINUE") == 0) return (FALSE);
  570.           if (strcmp(u_token,"CASE") == 0) return (FALSE);
  571.           break;
  572.     case 'D': if(strcmp(u_token,"DOUBLE") == 0) return(FALSE);
  573.           if(strcmp(u_token,"DO") == 0) return(FALSE);
  574.           if(strcmp(u_token,"DEFAULT") == 0) return(FALSE);
  575.           break;
  576.     case 'E': if(strcmp(u_token,"EXTERN") == 0) return(FALSE);
  577.           if(strcmp(u_token,"ELSE") == 0) return(FALSE);
  578.           if(strcmp(u_token,"ENTRY") == 0) return(FALSE);
  579.           break;
  580.     case 'F': if(strcmp(u_token,"FLOAT") == 0) return(FALSE);
  581.           if(strcmp(u_token,"FOR") == 0) return(FALSE);
  582.           break;
  583.     case 'G': if(strcmp(u_token,"GOTO") == 0) return(FALSE);
  584.           break;
  585.     case 'I': if(strcmp(u_token,"INT") == 0) return(FALSE);
  586.           if(strcmp(u_token,"IF") == 0) return(FALSE);
  587.           break;
  588.     case 'L': if(strcmp(u_token,"LONG") == 0) return(FALSE);
  589.           break;
  590.     case 'R': if(strcmp(u_token,"RETURN") == 0) return(FALSE);
  591.           if(strcmp(u_token,"REGISTER") == 0) return(FALSE);
  592.           break;
  593.     case 'S': if(strcmp(u_token,"STRUCT") == 0) return(FALSE);
  594.           if(strcmp(u_token,"SHORT") == 0) return(FALSE);
  595.           if(strcmp(u_token,"STATIC") == 0) return(FALSE);
  596.           if(strcmp(u_token,"SIZEOF") == 0) return(FALSE);
  597.           if(strcmp(u_token,"SWITCH") == 0) return(FALSE);
  598.           break;
  599.     case 'T': if(strcmp(u_token,"TYPEDEF") == 0) return(FALSE);
  600.           break;
  601.     case 'U': if(strcmp(u_token,"UNION") == 0) return(FALSE);
  602.           if(strcmp(u_token,"UNSIGNED") == 0) return(FALSE);
  603.           break;
  604.     case 'W': if(strcmp(u_token,"WHILE") == 0) return(FALSE);
  605.           break; }
  606.     }
  607.   return(TRUE);
  608. }
  609.  
  610. /*************************************************************************/
  611.  
  612. /*
  613.    Install parsed token and line reference in linked structure
  614. */
  615.  
  616. putoken(p_token,p_ref)
  617.  
  618. char *p_token;
  619. int  p_ref;
  620.  
  621. {
  622.   int  hsh_index;
  623.   int  i;
  624.   int  j;
  625.   int  d;
  626.   int  found;
  627.   struct id_blk *idptr;
  628.   struct rf_blk *rfptr;
  629.   struct id_blk *alloc_id();
  630.   struct rf_blk *alloc_rf();
  631.   struct rf_blk *add_rf();
  632.  
  633.   if(l_flg) return;
  634.   j=0;
  635.   for (i=0; p_token[i] != NULL; i++)  /* Hashing algorithm is far from */
  636.   {                      /* optimal but is adequate for a */
  637.       j = j * 10 + p_token[i];          /* memory-bound index vector!    */
  638.    }
  639.   hsh_index = abs(j) % MAX_WRD;
  640.   found = FALSE;
  641.   d = 1;
  642.   do {
  643.        idptr = id_vector[hsh_index];
  644.        if(idptr == NULL) {
  645.      id_cnt++;
  646.      idptr = id_vector[hsh_index] = alloc_id(p_token);
  647.      chain_alpha(idptr,p_token);
  648.      idptr->top_lnk = idptr->lst_lnk = alloc_rf(p_ref);
  649.      found = TRUE;
  650.        }
  651.        else
  652.        if(strcmp(p_token,idptr->id_name) == 0) {
  653.      idptr->lst_lnk = add_rf(idptr->lst_lnk,p_ref);
  654.        found = TRUE;
  655.      }
  656.        else
  657.        { hsh_index += d;
  658.      d += 2;
  659.      rhsh_cnt++;
  660.      if (hsh_index >= MAX_WRD)
  661.         hsh_index -= MAX_WRD;
  662.      if (d == MAX_WRD) {
  663.         printf("\nERROR: Symbol table overflow\n");
  664.         exit(0);
  665.      }
  666.        }
  667.       } while (!found);
  668. }
  669.  
  670. /*************************************************************************/
  671.  
  672. chain_alpha(ca_ptr,ca_token)
  673.  
  674. struct id_blk *ca_ptr;
  675. char  *ca_token;
  676.  
  677. {
  678.   char    c;
  679.   int    f;
  680.   struct id_blk *cur_ptr;
  681.   struct id_blk *lst_ptr;
  682.  
  683.   c = ca_token[0];
  684.   if(c == '_') c = 0;
  685.     else
  686.       if (isupper(c))  c=1+((c-'A')*2);
  687.       else           c=2+((c-'a')*2);
  688.  
  689.   if(alpha_vector[c].alpha_top == NULL)
  690.     { alpha_vector[c].alpha_top =
  691.       alpha_vector[c].alpha_lst = ca_ptr;
  692.       ca_ptr->alpha_lnk = NULL;
  693.       return;
  694.     }
  695.  
  696. /* check to see if new id_blk should be inserted between
  697.    the alpha_vector header block and the first id_blk in
  698.    the current alpha chain
  699. */
  700.  
  701.  if(strcmp(alpha_vector[c].alpha_top->id_name,ca_token) >0)
  702.   {
  703.     ca_ptr->alpha_lnk=alpha_vector[c].alpha_top;
  704.     alpha_vector[c].alpha_top=ca_ptr;
  705.     return;
  706.   }
  707.  
  708.   if(strcmp(alpha_vector[c].alpha_lst->id_name,ca_token) < 0)
  709.     { alpha_vector[c].alpha_lst->alpha_lnk = ca_ptr;
  710.       ca_ptr->alpha_lnk = NULL;
  711.       alpha_vector[c].alpha_lst=ca_ptr;
  712.       return;
  713.     }
  714.  
  715.   cur_ptr = alpha_vector[c].alpha_top;
  716.   while(strcmp(cur_ptr->id_name,ca_token) < 0)
  717.    { lst_ptr = cur_ptr;
  718.      cur_ptr = lst_ptr->alpha_lnk;
  719.    }
  720.  
  721.   lst_ptr->alpha_lnk = ca_ptr;
  722.   ca_ptr->alpha_lnk = cur_ptr;
  723.   return;
  724. }
  725.  
  726. /*************************************************************************/
  727.  
  728. struct id_blk *alloc_id(aid_token)
  729.   char    *aid_token;
  730.  
  731.   {
  732.     int  ai;
  733.     struct id_blk *aid_ptr;
  734.  
  735.      if((aid_ptr = alloc(sizeof(struct id_blk))) == 0) {
  736.        printf("\nERROR: Unable to allocate identifier block\n");
  737.        exit(0);
  738.      }
  739.      ai=0;
  740.      do {
  741.       aid_ptr->id_name[ai] = aid_token[ai];
  742.     } while (aid_token[ai++] != NULL);
  743.      return (aid_ptr);
  744. }
  745.  
  746. /*************************************************************************/
  747.  
  748. struct rf_blk *alloc_rf(arf_ref)
  749.  
  750.   int  arf_ref;
  751.  
  752.   {
  753.     int ri;
  754.     struct rf_blk *arf_ptr;
  755.  
  756.     if((arf_ptr = alloc(sizeof(struct rf_blk))) == 0) {
  757.       printf("\nERROR: Unable to allocate reference block\n");
  758.       exit(0);
  759.     }
  760.     arf_ptr->ref_item[0] = arf_ref;
  761.     arf_ptr->ref_cnt = 1;
  762.     for(ri=1;ri<MAX_REF;ri++)
  763.       arf_ptr->ref_item[ri] = NULL;
  764.     return (arf_ptr);
  765.   }
  766.  
  767. /*************************************************************************/
  768.  
  769. struct rf_blk *add_rf(adr_ptr,adr_ref)
  770.  
  771.   struct rf_blk *adr_ptr;
  772.   int adr_ref;
  773.  
  774.   {
  775.     struct rf_blk *tmp_ptr;
  776.  
  777.     tmp_ptr = adr_ptr;
  778.     if(adr_ptr->ref_cnt == MAX_REF) {
  779.       tmp_ptr = adr_ptr->ref_cnt = alloc_rf(adr_ref);
  780.     }
  781.     else
  782.     { adr_ptr->ref_item[adr_ptr->ref_cnt++] = adr_ref;
  783.     }
  784.     return (tmp_ptr);
  785.   }
  786.  
  787. /*************************************************************************/
  788.  
  789. prnt_tbl()
  790. {  int prf_cnt;
  791.    int pti;
  792.    int pref;
  793.    int lin_cnt;
  794.    struct id_blk *pid_ptr;
  795.    struct rf_blk *ptb_ptr;
  796.  
  797.   prt_ref = TRUE;
  798.   prt_hdr();
  799.   for (pti=0;pti<MAX_ALPHA;pti++)
  800.   { if ((pid_ptr = alpha_vector[pti].alpha_top) != NULL)
  801.       { do
  802.      { if(o_flg)
  803.      {if(fprintf(f_lst_fil,"%-20.19s: ",pid_ptr->id_name) == ERROR)
  804.         lst_err();}
  805.        else
  806.       printf("%-20.19s: ",pid_ptr->id_name);
  807.        ptb_ptr=pid_ptr->top_lnk;
  808.        lin_cnt=prf_cnt=0;
  809.        do { if(prf_cnt == MAX_REF)
  810.           { prf_cnt=0;
  811.         ptb_ptr = ptb_ptr->ref_cnt;
  812.           }
  813.        if(ptb_ptr > MAX_REF)
  814.         {
  815.          if((pref=ptb_ptr->ref_item[prf_cnt++]) != 0)
  816.         { if(o_flg)
  817.          {if(fprintf(f_lst_fil,"%4d ",pref) == ERROR) lst_err();}
  818.         else
  819.         printf("%4d ",pref);
  820.         if (++lin_cnt == REFS_PER_LINE)
  821.             { nl();
  822.               if(o_flg)
  823.              {if(fprintf(f_lst_fil,"                      ") == ERROR) lst_err();}
  824.               else
  825.              printf("                      ");
  826.               lin_cnt=0;
  827.             }
  828.         }
  829.           } else pref=0;
  830.        } while (pref);
  831.     nl();
  832.     } while ((pid_ptr=pid_ptr->alpha_lnk) != NULL);
  833.       }
  834.    }/*for*/
  835.  
  836.    echo( '\n' );
  837.  
  838. }
  839.  
  840. /*************************************************************************/
  841.  
  842. prt_hdr()
  843.  
  844. {
  845.   if (pagno++ != 0)    { echo( '\n' ); echo( FF ); }
  846.   if (o_flg)
  847.    {if(fprintf(f_lst_fil,
  848.       "XC ... 'C' Concordance Utility   %-20s       Page %d",
  849.      gbl_fil,pagno) == ERROR) lst_err();}
  850.   else
  851.    printf("XC ... 'C' Concordance Utility   %-20s       Page %d",
  852.      gbl_fil,pagno);
  853.   echo('\n');
  854.   paglin = 3;
  855.   nl();
  856. }
  857.  
  858. /*************************************************************************/
  859.  
  860. nl()
  861.  
  862. {
  863.   echo('\n');
  864.   if(++paglin >= LINES_PER_PAGE) prt_hdr();
  865.     else
  866.   if(!prt_ref) {
  867.     if(o_flg) {
  868.        if(fprintf(f_lst_fil,"%-4d %4d: ",    ++linum,++edtnum) == ERROR)
  869.        lst_err();
  870.        }
  871.     else
  872.        printf("%-4d %4d: ",    ++linum,++edtnum);
  873.     if(o_flg)
  874.        if(linum % 60 == 1)
  875.       printf("\n<%d> ",linum);
  876.        else {
  877.       printf(".");
  878. #ifdef Lattice
  879.       fflush(stdout);
  880. #endif
  881.       }
  882.  
  883.     }
  884.  return;
  885. }
  886.  
  887. /*************************************************************************/
  888.  
  889. #ifndef Lattice
  890. abs(i)
  891. int i;
  892. {
  893.    if (i<0) return(-i);
  894.    else     return( i);
  895. }
  896. #endif
  897.  
  898. /*************************************************************************/
  899.  
  900. #ifdef Lattice
  901. /*    cvt ascii to int or long     */
  902.  
  903. long atoi(s)
  904. char *s;
  905. {
  906.    long n;
  907.    int sign = 0;
  908.  
  909.    while(*s==' ' || *s=='\t')  ++s;   /* move over blanks & tabs */
  910.    if (*s=='-')
  911.       sign=1;
  912.    else
  913.       if (*s!='+')  --s;
  914.    ++s;                   /* skip sign */
  915.    for( n=0; *s>='0' && *s<='9'; )
  916.       n = n * 10 + (*s++ - '0');
  917.    if (sign)   n = -n;
  918.    return n;
  919. }
  920. #endif
  921.  
  922. /*************************************************************************/
  923.  
  924. alloc(i)
  925. int i;
  926. {
  927.    return malloc(i);
  928. }
  929.