home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 152_01 / xc.c < prev    next >
Text File  |  1985-03-10  |  26KB  |  956 lines

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