home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / TOOLS2.ZIP / XREF.C < prev    next >
C/C++ Source or Header  |  1988-03-21  |  25KB  |  939 lines

  1. /*
  2.     HEADER:        CUG000.00;
  3.     TITLE:        Cross Reference Generator;
  4.     DATE:        04/05/1987;
  5.     DESCRIPTION:    "Generic version of programmer's cross-reference
  6.             generator originally for BDS.";
  7.     VERSION:    2.2;
  8.     KEYWORDS:    Cross Reference;
  9.     FILENAME:    XC.C;
  10.     SEE-ALSO:    CUG126, CUG171;
  11.     COMPILERS:    vanilla;
  12.     AUTHORS:    Phillip N. Hisley, W. H. Rauser, W. C. Colley III;
  13. */
  14.  
  15. /************************************************************************/
  16. /*   5 APR 1987      Portable C Conversion        WCC                */
  17. /*     -  Epson init string changed from hex (\x00) to octal (\000).    */
  18. /*     -  Use () with A?(c=B):(c=C) for portability.  If it's an error, */
  19. /*        it seems to be a very common one.            */
  20. /*     -  Made use of host compiler's strcmp() and strcpy() as they are */
  21. /*        usually written in assembly and run faster.        */
  22. /*     -  Globally replaced "alpha_" with "alp_", "alloc_" with        */
  23. /*        "allo_", and "tmpchr" with "tmpch" to avoid multiply    */
  24. /*        defined symbol errors on compilers that only support    */
  25. /*        @$%&*&?>}\~~@# 6-character names.            */
  26. /*     -  Added abs() macro for compilers that don't have one.          */
  27. /*     -  Used some data initialization to kill off some code.        */
  28. /*     -  Made miscellaneous small tweaks for portability.        */
  29. /*     -  Cleaned out old BDS C stuff to improve readability.        */
  30. /*     -  Cleaned up abortion with use of rf_blk.rf_cnt as a pointer    */
  31. /*        link to the next rf_blk.  This construct will NOT work    */
  32. /*        in environments like the MSDOS large model where ints    */
  33. /*        are smaller than pointers!                */
  34. /*                                    */
  35. /*   9-26-83   Microsoft C 1.04     Conversion    WHR            */
  36. /*     -  \t between line numbers and text to fix indenting problem.    */
  37. /*     -  added option -e for output to Epson in condensed print.    */
  38. /*     -  toupper() and isupper() are macros, not functions.        */
  39. /*     -  eliminate side effect in toupper(*++arg) in main().        */
  40. /*     -  change alloc() to malloc().                    */
  41. /*     -  add #define NAMES that are not in stdio.h            */
  42. /*     -  MS-C requires () in statement A?(c=B):(c=C)    error or not??    */
  43. /*                                    */
  44. /*   4-30-83   Computer Innovations C-86 1.31 Conversion    WHR        */
  45. /*     -  #include filename changed to allow a disk drive prefix, D:    */
  46. /*     -  convert if(fprintf(...) == ERROR) lst_err(); to fprintf(..);    */
  47. /*     -  convert if(fopen(...) == ERROR) statements to == NULL.    */
  48. /*     -  C86 requires () in statement A?(c=B):(c=C)    error or not??    */
  49. /*     -  remove getc() == ERROR check in fil_chr().            */
  50. /*     -  convert file conventions from BDS C to C-86.            */
  51. /*     -  comment out BDS unique statements, mark revised statements.    */
  52. /*      keep all BDS statements to document conversion effort.    */
  53. /*                                    */
  54. /**  4-19-83   BDS C Version file XC.CQ copied from Laurel RCPM       WHR    */
  55. /************************************************************************/
  56. /*                               */
  57. /*    XC  -  A 'C' Concordance Utility               */
  58. /*                               */
  59. /*    Version 1.0   January, 1982               */
  60. /*                               */
  61. /*    Copyright (c) 1982 by Philip N. Hisley           */
  62. /*                               */
  63. /*    Released for non-commercial distribution only       */
  64. /*                               */
  65. /*    Abstract:                           */
  66. /*                               */
  67. /*    'XC' is a cross-reference utility for 'C' programs.  */
  68. /*    Its has the ability to handle nested include files   */
  69. /*    to a depth of 8 levels and properly processes nested */
  70. /*    comments as supported by BDS C. Option flags support */
  71. /*    the following features:                   */
  72. /*                               */
  73. /*    - Routing of list output to disk               */
  74. /*    - Cross-referencing of reserved words           */
  75. /*    - Processing of nested include files           */
  76. /*    - Generation of listing only               */
  77. /*                               */
  78. /*    Usage: xc <filename> <flag(s)>               */
  79. /*                               */
  80. /*    Flags: -i           = Enable file inclusion       */
  81. /*         -l           = Generate listing only       */
  82. /*         -r           = Cross-ref reserved words       */
  83. /*         -o <filename> = Write output to named file       */
  84. /*                               */
  85. /*    Please report bugs/fixes/enhancements to:           */
  86. /*                               */
  87. /*          Philip N. Hisley                   */
  88. /*          548H Jamestown Court               */
  89. /*          Edgewood, Maryland 21040               */
  90. /*          (301) 679-4606                   */
  91. /*          Net Addr: PNH@MIT-AI               */
  92. /*                               */
  93. /***********************************************************/
  94.  
  95. #include <stdio.h>
  96.  
  97. /*
  98.  * Portability Note:  The AZTEC C compilers handle the binary/text file
  99.  * dichotomy differently from most other compilers.  Uncomment the following
  100.  * pair of #defines if you are running AZTEC C:
  101.  */
  102.  
  103. /*
  104. #define getc(f)        agetc(f)
  105. #define putc(c,f)    aputc(c,f)
  106. */
  107.  
  108. /*  Portability Note:  8-bit systems often don't have header files
  109.     ctype.h and string.h.  If your system doesn't have these,
  110.     uncomment the #defines NO_STRING_H and NO_CTYPE_H.           WCC    */
  111.  
  112. /*
  113. #define     NO_STRING_H
  114. #define     NO_CTYPE_H
  115. */
  116.  
  117. /*  Portability Note:  Some older compilers call the function malloc()
  118.     by its older name alloc().    If you have one of these older
  119.     compilers, uncomment the following #define.            WCC    */
  120.  
  121. /*
  122. #define     malloc(x)    alloc(x)
  123. */
  124.  
  125. /*  Portability Note:  A few compilers don't know the additional type
  126.     void.  If yours is one of these, uncomment the following #define.    */
  127.  
  128. /* #define    void        int                    */
  129.  
  130. #ifdef     NO_CTYPE_H                        /* WCC */
  131. int isalpha(), isdigit(), isupper(), toupper();
  132. #else
  133. #include <ctype.h>                        /* WHR */
  134. #endif
  135.  
  136. #ifdef     NO_STRING_H                        /* WCC */
  137. int strcmp();  
  138. char *strcpy();
  139. #else
  140. #include <string.h>
  141. #endif
  142.  
  143. #ifndef     abs                            /* WCC */
  144. #define     abs(x)        ((x < 0) ? (-x) : (x))
  145. #endif
  146.  
  147. /*  Portability Note:  Some stdio.h files define various of these
  148.     constants.    Some don't.  Therefore, each definition is
  149.     compiled only if needed.                       WCC */
  150.  
  151. #ifndef     NULL                            /* WCC */
  152. #define     NULL        0
  153. #endif
  154.  
  155. #ifndef     FALSE                            /* WCC */
  156. #define     FALSE        0                        /* WHR */
  157. #endif
  158.  
  159. #ifndef     TRUE                            /* WCC */
  160. #define     TRUE        1                        /* WHR */
  161. #endif
  162.  
  163. #define     MAX_REF    5        /* maximum refs per ref-block */
  164. #define     MAX_LEN    20        /* maximum identifier length  */
  165. #define     MAX_WRD   749        /* maximum number of identifiers */
  166. #define     MAX_ALPHA  53        /* maximum alpha chain heads */
  167. #define     REFS_PER_LINE    8    /* maximum refs per line */
  168. #define     LINES_PER_PAGE 60
  169. #define     FF 0x0C         /* formfeed */
  170.  
  171. /*  Order of the next two structure declarations reversed to avoid
  172.     a forward reference that chokes some compilers.            WCC */
  173.  
  174. struct rf_blk {
  175.     int ref_item[MAX_REF];
  176.     int ref_cnt;
  177.     struct rf_blk *ref_lnk;
  178. onerf;
  179.  
  180. struct id_blk {
  181.     char id_name[MAX_LEN];
  182.     struct id_blk *alp_lnk;
  183.     struct rf_blk *top_lnk;
  184.     struct rf_blk *lst_lnk;
  185. oneid, *id_vector[MAX_WRD];
  186.  
  187. struct alp_hdr { 
  188.     struct id_blk *alp_top;
  189.     struct id_blk *alp_lst;
  190. alp_vector[MAX_ALPHA];
  191.  
  192. int    linum;        /* line number */
  193. int    edtnum;        /* edit line number */
  194. int    fil_cnt;    /* active file index */
  195. int    wrd_cnt;    /* token count */
  196. int    pagno;        /* page number */
  197. int    id_cnt;        /* number of unique identifiers */
  198. int    rhsh_cnt;    /* number of conflict hits */
  199. int    filevl;        /* file level  */
  200. int    paglin;        /* page line counter */
  201. int    prt_ref = FALSE;
  202. char    act_fil[MAX_LEN];
  203. char    lst_fil[MAX_LEN];
  204. char    gbl_fil[MAX_LEN];
  205. FILE   *l_buffer;                         /* WHR */
  206. int    e_flg = FALSE, i_flg = FALSE, o_flg = FALSE;         /* WHR */
  207. int    r_flg = FALSE, l_flg = FALSE, debug = FALSE;         /* WCC */
  208. char    Epson[]     = "\033@\017\033Q\204";             /* WCC */
  209.  
  210. void exit();
  211.  
  212. /*-------------------------------------------*/
  213.  
  214. void main(argc,argv)
  215. int    argc;
  216. char    **argv;
  217. {
  218.     char  *arg, cc;
  219.     void nl(), prnt_tbl(), proc_file(), use_err();
  220.  
  221.     if (argc < 2) use_err();
  222.     (void)strcpy(gbl_fil,*++argv);
  223.     --argc;
  224.     if(gbl_fil[0] == '-')
  225.         use_err();
  226.     while(--argc != 0)
  227.     {      
  228.         if(*(arg=*++argv) == '-')
  229.             /*****{    switch( toupper(*++arg) )     *** side effect in Microsoft C */
  230.         {    
  231.             switch( cc=*++arg, toupper(cc) )             /* Microsoft C */
  232.             {   
  233.             case 'I':  
  234.                 i_flg++;
  235.                 break;
  236.             case 'R':  
  237.                 r_flg++;
  238.                 break;
  239.             case 'L':  
  240.                 l_flg++;
  241.                 break;
  242.             case 'O': 
  243.                 {
  244.                     o_flg++;
  245.                     if(--argc == 0) use_err();
  246.                     (void)strcpy(lst_fil,*++argv);
  247.                     if(lst_fil[0] == '-') use_err();
  248.                     if(debug) printf("lst_fil=>%s<",lst_fil);
  249.                     break;
  250.                 }
  251.             case 'D':  
  252.                 debug++;
  253.                 break;
  254.             case 'E':  
  255.                 e_flg++;                  /* WHR */
  256.                 o_flg++;
  257.                 (void)strcpy(lst_fil,"LPT1:");
  258.                 break;
  259.             default:   
  260.                 use_err();
  261.             }
  262.         }
  263.         else use_err();
  264.     }
  265.     if (debug) printf("\ni_flg=%d, r_flg=%d, l_flg=%d", i_flg,r_flg,l_flg);
  266.     if (debug) printf("\no_flg=%d, debug=%d", o_flg,debug);
  267.     if (o_flg)
  268.     {      
  269.         if ( (l_buffer = fopen(lst_fil,"w")) == NULL)      /*** output file ***/
  270.         {    
  271.             printf("ERROR Unable to create list file - %s\n",lst_fil);
  272.             exit(0);
  273.         }
  274.         printf("\nXC ....... 'C' Concordance Utility  v2.3\n");
  275.         printf("    Portable C,  Conversion 5 APR 1987\n\n");        /* WCC */
  276.         if (e_flg) fprintf(l_buffer,"%s",Epson);
  277.     }
  278.     for(linum=0;linum < MAX_WRD;linum++) {
  279.         id_vector[linum] = NULL;
  280.     }
  281.     for(linum=0;linum < MAX_ALPHA;linum++)
  282.     {
  283.         alp_vector[linum].alp_top =
  284.             alp_vector[linum].alp_lst = NULL;
  285.     }
  286.     fil_cnt = wrd_cnt = linum = 0;
  287.     filevl=paglin=pagno=edtnum=0;
  288.     id_cnt=rhsh_cnt=0;
  289.     proc_file(gbl_fil);
  290.     if(!l_flg) {
  291.         printf("Cross reference for file %s\n\n", gbl_fil ) ;
  292.         prnt_tbl();
  293.         printf("\nAllowable Symbols: %d\n",MAX_WRD);
  294.         printf("Unique    Symbols: %d\n",id_cnt);
  295.     }
  296.     if(o_flg) {
  297.         nl();
  298.         fprintf(l_buffer,"\nAllowable Symbols: %d\n",MAX_WRD);   /* WHR */
  299.         fprintf(l_buffer,"Unique    Symbols: %d\n",id_cnt);       /* WHR */
  300.         fprintf(l_buffer,"%c",FF);                   /* WHR */
  301.         fflush(l_buffer);
  302.         fclose(l_buffer);
  303.     }
  304. }/*main.
  305. ----------------------------------------*/
  306.  
  307. void use_err()
  308. {
  309.     printf("\nERROR: Invalid parameter specification\n\n");
  310.     printf("Usage: xc <filename> <flag(s)>\n\n");
  311.     printf("Flags: -e             = Emit printer initialization string\n");
  312.     printf("       -i             = Enable file inclusion\n");
  313.     printf("       -l             = Generate listing only\n");
  314.     printf("       -r             = Cross-reference reserved words\n");
  315.     printf("       -o <filename>  = Write output to named file\n");
  316.     exit(0);
  317. }/*use_err.
  318. -------------------------------------------*/
  319.  
  320.  
  321. void proc_file(filnam)
  322. char    *filnam;
  323.  
  324. {
  325.     FILE  *buffer;       /* allocated buffer pointer */
  326.     /* WHR */
  327.     char  token[MAX_LEN]; /* token buffer */
  328.     int   eof_flg;       /* end-of-file indicator */
  329.     int   tok_len;       /* token length */
  330.     int   incnum;       /* included line number */
  331.     int chk_token(), get_token();
  332.     void nl(), put_token();
  333.  
  334.     (void)strcpy(act_fil,filnam);
  335.     if ((buffer = fopen(filnam,"r")) == NULL)    /*** input file ***/ /* WHR */
  336.     {      
  337.         printf("\nERROR: Unable to open input file: %s\n",filnam);
  338.         exit(0);
  339.     }
  340.  
  341.     eof_flg = FALSE;
  342.  
  343.     do {
  344.         if(get_token(buffer,token,&tok_len,&eof_flg,0))
  345.         {    
  346.             if (debug) printf("\ntoken: %s   length: %d\n",token,&tok_len);
  347.             if (chk_token(token))
  348.             {
  349.                 /* #include processing changed to accept drive:   WHR */
  350.                 if (strcmp(token,"#include") == 0)
  351.                 {     
  352.                     if (get_token(buffer,token,&tok_len,&eof_flg,1))
  353.                     {    
  354.                         if (debug) printf("\ntoken: %s   length: %d\n",
  355.                         token,&tok_len);
  356.                         if (!i_flg) continue;
  357.                         else
  358.                             {       
  359.                             incnum=edtnum;
  360.                             edtnum=0;
  361.                             nl();
  362.                             proc_file(token);
  363.                             edtnum=incnum;
  364.                             (void)strcpy(act_fil,filnam);
  365.                             continue;
  366.                         }
  367.                     }
  368.                 }
  369.                 put_token(token,linum);
  370.             }
  371.         }
  372.     } 
  373.     while (!eof_flg);
  374.  
  375.     filevl -= 1;
  376.     fclose(buffer);
  377.     /***     free(sav_buffer);  */
  378. }/*proc_file.
  379. -------------------------------------------*/
  380.  
  381. int get_token(g_buffer,g_token,g_toklen,g_eoflg,g_flg)
  382. FILE    *g_buffer;
  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. {
  397.     int     c, rdchr();
  398.     char    *h_token;
  399.     char    tmpch;
  400.     char    tmpch2;              /* WHR fix for B:filename.ext */
  401.  
  402.     h_token = g_token;
  403.  
  404. gtk:                   /* top of loop, get new token */
  405.     *g_toklen = 0;
  406.     g_token = h_token;
  407.  
  408.     /*
  409.          *    Scan and discard any characters until an alphabetic or
  410.          *    '_' (underscore) character is encountered or an end-of-file
  411.          *    condition occurs
  412.          */
  413.  
  414.     while(  (!isalpha(*g_token = rdchr(g_buffer,g_eoflg,g_flg)))
  415.         &&     !*g_eoflg    &&  *g_token != '_'
  416.         && *g_token != '0' &&  *g_token != '#' );
  417.     if(*g_eoflg) return(FALSE);
  418.  
  419.     *g_toklen += 1;
  420.  
  421.     /*
  422.          *     Scan and collect identified alpanumeric token until
  423.          *     a non-alphanumeric character is encountered or and
  424.          *     end-of-file condition occurs
  425.          */
  426.  
  427.     if(g_flg) {
  428.         tmpch     = '.';
  429.         tmpch2 = ':';              /* WHR fix for B:filename.ext */
  430.     }
  431.     else {
  432.         tmpch     = '_';
  433.         tmpch2 = '_';              /* WHR fix for B:filename.ext */
  434.     }
  435.     while( (isalpha(c=rdchr(g_buffer,g_eoflg,g_flg)) ||
  436.         isdigit(c) || c == '_' || c == tmpch || c == tmpch2)
  437.         && !*g_eoflg)           /* WHR fix for B:filename.ext */
  438.     {      
  439.         if(*g_toklen < MAX_LEN)
  440.         {    
  441.             *++g_token = c;
  442.             *g_toklen += 1;
  443.         }
  444.     }
  445.  
  446.  
  447.     /*
  448.          *        Check to see if a numeric hex or octal constant has
  449.          *        been encountered ... if so dump it and try again
  450.          */
  451.  
  452.  
  453.     if (*h_token == '0') goto gtk;
  454.  
  455.  
  456.     /*
  457.          *        Tack a NULL character onto the end of the token
  458.          */
  459.  
  460.     *++g_token = NULL;
  461.  
  462.     /*
  463.          *        Screen out all #token strings except #include
  464.          */
  465.  
  466.     if (*h_token == '#' && strcmp(h_token,"#include")) goto gtk;
  467.  
  468.     return (TRUE);
  469. }/*get_token.
  470. -----------------------------------------*/
  471.  
  472. int fil_chr(f_buffer,f_eof)
  473. FILE *f_buffer;
  474. int *f_eof;
  475. {
  476.     int fc;
  477.     if ((fc = getc(f_buffer)) == EOF) {
  478.         *f_eof = TRUE;
  479.         fc = NULL;
  480.     }
  481.     return(fc);
  482. }/*fil_chr.
  483. ----------------------------------------*/
  484.  
  485. int rdchr(r_buffer,r_eoflg,rd_flg)
  486. int     *r_eoflg, rd_flg;
  487. FILE    *r_buffer;
  488.  
  489. /*
  490.     'rdchr' returns the next valid character in a file
  491.     and an end-of-file indicator. A valid character is
  492.     defined as any which does not appear in either a
  493.     commented or a quoted string ... 'rdchr' will correctly
  494.     handle comment tokens which appear within a quoted
  495.     string
  496. */
  497.  
  498. {
  499.     int     c;
  500.     int     q_flg;         /* double quoted string flag */
  501.     int     q1_flg;         /* single quoted string flag */
  502.     int     cs_flg;         /* comment start flag */
  503.     int     ce_flg;         /* comment end flag */
  504.     int     c_cnt;         /* comment nesting level */
  505.     int     t_flg;         /* transparency flag */
  506.     void nl();
  507.  
  508.     q_flg = q1_flg = cs_flg = ce_flg = t_flg = FALSE;
  509.     c_cnt  = 0;
  510.  
  511. rch:
  512.  
  513.     /*
  514.          *     Fetch character from file
  515.          */
  516.  
  517.     c = fil_chr(r_buffer,r_eoflg);
  518.  
  519.     if (*r_eoflg) return(c);    /* EOF encountered */
  520.     if (c == '\n')
  521.     {
  522.         ++linum ;
  523.         ++edtnum ;
  524.     }
  525. /*
  526.         nl();
  527.     else
  528.         if (o_flg) fprintf(l_buffer,"%c",c);
  529.         else printf("%c",c);
  530. */
  531.  
  532.     if (rd_flg) return(c);
  533.  
  534.     if (t_flg) {
  535.         t_flg = !t_flg;
  536.         goto rch;
  537.     }
  538.  
  539.     if (c == '\\') {
  540.         t_flg = TRUE;
  541.         goto rch;
  542.     }
  543.     /*
  544.         If the character is not part of a quoted string
  545.         check for and process commented strings...
  546.         nested comments are handled correctly but unbalanced
  547.         comments are not ... the assumption is made that
  548.         the syntax of the program being xref'd is correct
  549.         */
  550.  
  551.     if (!q_flg     &&  !q1_flg) {
  552.         if (c == '*'    &&  c_cnt  &&  !cs_flg) {
  553.             ce_flg = TRUE;
  554.             goto rch;
  555.         }
  556.         if (c == '/'    &&  ce_flg) {
  557.             c_cnt -= 1;
  558.             ce_flg = FALSE;
  559.             goto rch;
  560.         }
  561.         ce_flg = FALSE;
  562.         if (c == '/') {
  563.             cs_flg = TRUE;
  564.             goto rch;
  565.         }
  566.         if (c == '*'    &&  cs_flg) {
  567.             c_cnt += 1;
  568.             cs_flg = FALSE;
  569.             goto rch;
  570.         }
  571.         cs_flg = FALSE;
  572.  
  573.         if (c_cnt) goto rch;
  574.     }
  575.  
  576.     /*
  577.         Check for and process quoted strings
  578.         */
  579.  
  580.     if ( c == '"'  &&    !q1_flg) {    /* toggle quote flag */
  581.         q_flg =  !q_flg;
  582.         if(debug) printf("\nq_flg toggled to: %d\n" ,q_flg);
  583.         goto rch;
  584.     }
  585.     if (q_flg) goto rch;
  586.  
  587.     if (c == '\'') {         /* toggle quote flag */
  588.         q1_flg = !q1_flg;
  589.         if(debug) printf("\nq1_flg toggled to: %d\n" ,q1_flg);
  590.         goto rch;
  591.     }
  592.     if (q1_flg) goto rch;
  593.  
  594.     /*
  595.         Valid character ... return to caller
  596.         */
  597.  
  598.     return (c);
  599. }/*rdchr.
  600. -----------------------------------------------*/
  601.  
  602.  
  603. int chk_token(c_token)
  604. char    *c_token;
  605. {
  606.     char  u_token[MAX_LEN];
  607.     int   i;
  608.  
  609.     {
  610.         if (r_flg) return(TRUE);
  611.         i = 0;
  612.         do { 
  613.             u_token[i] = toupper(c_token[i]);
  614.         } 
  615.         while (c_token[i++] != NULL);
  616.  
  617.         switch(u_token[0]) {
  618.         case 'A': 
  619.             if (strcmp(u_token,"AUTO") == 0) return(FALSE);
  620.             break;
  621.         case 'B': 
  622.             if (strcmp(u_token,"BREAK") == 0) return(FALSE);
  623.             break;
  624.         case 'C': 
  625.             if (strcmp(u_token,"CHAR") == 0) return (FALSE);
  626.             if (strcmp(u_token,"CONTINUE") == 0) return (FALSE);
  627.             if (strcmp(u_token,"CASE") == 0) return (FALSE);
  628.             break;
  629.  
  630.         case 'D': 
  631.             if(strcmp(u_token,"DOUBLE") == 0) return(FALSE);
  632.             if(strcmp(u_token,"DO") == 0) return(FALSE);
  633.             if(strcmp(u_token,"DEFAULT") == 0) return(FALSE);
  634.             break;
  635.         case 'E': 
  636.             if(strcmp(u_token,"EXTERN") == 0) return(FALSE);
  637.             if(strcmp(u_token,"ELSE") == 0) return(FALSE);
  638.             if(strcmp(u_token,"ENTRY") == 0) return(FALSE);
  639.             break;
  640.         case 'F': 
  641.             if(strcmp(u_token,"FLOAT") == 0) return(FALSE);
  642.             if(strcmp(u_token,"FOR") == 0) return(FALSE);
  643.             break;
  644.         case 'G': 
  645.             if(strcmp(u_token,"GOTO") == 0) return(FALSE);
  646.             break;
  647.         case 'I': 
  648.             if(strcmp(u_token,"INT") == 0) return(FALSE);
  649.             if(strcmp(u_token,"IF") == 0) return(FALSE);
  650.             break;
  651.         case 'L': 
  652.             if(strcmp(u_token,"LONG") == 0) return(FALSE);
  653.             break;
  654.         case 'R': 
  655.             if(strcmp(u_token,"RETURN") == 0) return(FALSE);
  656.             if(strcmp(u_token,"REGISTER") == 0) return(FALSE);
  657.             break;
  658.         case 'S': 
  659.             if(strcmp(u_token,"STRUCT") == 0) return(FALSE);
  660.             if(strcmp(u_token,"SHORT") == 0) return(FALSE);
  661.             if(strcmp(u_token,"STATIC") == 0) return(FALSE);
  662.             if(strcmp(u_token,"SIZEOF") == 0) return(FALSE);
  663.             if(strcmp(u_token,"SWITCH") == 0) return(FALSE);
  664.             break;
  665.         case 'T': 
  666.             if(strcmp(u_token,"TYPEDEF") == 0) return(FALSE);
  667.             break;
  668.         case 'U': 
  669.             if(strcmp(u_token,"UNION") == 0) return(FALSE);
  670.             if(strcmp(u_token,"UNSIGNED") == 0) return(FALSE);
  671.             break;
  672.         case 'W': 
  673.             if(strcmp(u_token,"WHILE") == 0) return(FALSE);
  674.             break; 
  675.         }
  676.     }
  677.     return (TRUE);
  678. }/*chk_token.
  679. ---------------------------------------------*/
  680.  
  681.  
  682. /*
  683.    *    Install parsed token and line reference in linked structure
  684.    */
  685.  
  686. void put_token(p_token,p_ref)
  687. char *p_token;
  688. int  p_ref;
  689. {
  690.     int  d, found, hsh_index, i, j;
  691.     struct id_blk *idptr, *allo_id();
  692.     struct rf_blk *allo_rf(), *add_rf();
  693.     void chain_alpha();
  694.  
  695.     if (l_flg) return;
  696.     j=0;
  697.     for (i=0; p_token[i] != NULL; i++)     /* Hashing algorithm is far from */
  698.     {                     /* optimal but is adequate for a */
  699.         j = j * 10 + p_token[i];     /* memory-bound index vector!      */
  700.     }
  701.     hsh_index = abs(j) % MAX_WRD;
  702.  
  703.     found = FALSE;
  704.     d = 1;
  705.     do
  706.         {      
  707.         idptr = id_vector[hsh_index];
  708.         if (idptr == NULL)
  709.         {    
  710.             id_cnt++;
  711.             idptr = id_vector[hsh_index] = allo_id(p_token);
  712.             chain_alpha(idptr,p_token);
  713.             idptr->top_lnk = idptr->lst_lnk = allo_rf(p_ref);
  714.             found = TRUE;
  715.         }
  716.         else
  717.             if (strcmp(p_token,idptr->id_name) == 0)
  718.         {    
  719.             idptr->lst_lnk = add_rf(idptr->lst_lnk,p_ref);
  720.             found = TRUE;
  721.         }
  722.         else
  723.             {    
  724.             hsh_index += d;
  725.             d += 2;
  726.             rhsh_cnt++;
  727.             if (hsh_index >= MAX_WRD)
  728.                 hsh_index -= MAX_WRD;
  729.             if (d == MAX_WRD)
  730.             {    
  731.                 printf("\nERROR: Symbol table overflow\n");
  732.                 exit(0);
  733.             }
  734.         }
  735.     } 
  736.     while (!found);
  737. }/*put_token.
  738. --------------------------------------------*/
  739.  
  740.  
  741. void chain_alpha(ca_ptr,ca_token)
  742. struct id_blk *ca_ptr;
  743. char  *ca_token;
  744. {
  745.     char  c;
  746.     struct id_blk *cur_ptr;
  747.     struct id_blk *lst_ptr;
  748.  
  749.     c = ca_token[0];
  750.     if (c == '_')  c = 0;
  751.     else
  752.         /**  isupper(c) ? c=1+((c-'A')*2) : c=2+((c-'a')*2) ;     error or not??
  753.               **  A good one for the puzzle book! Is the () required around (c=..)?
  754.               **  C86 and Microsoft C both req the ()'s, BDS C did not.
  755.               **  Is it required because = has lower precedence than ?: ????
  756.               **/
  757.         isupper(c) ? (c=1+((c-'A')*2)) : (c=2+((c-'a')*2)) ;
  758.  
  759.     if(alp_vector[c].alp_top == NULL)
  760.     {      
  761.         alp_vector[c].alp_top =
  762.             alp_vector[c].alp_lst = ca_ptr;
  763.         ca_ptr->alp_lnk = NULL;
  764.         return;
  765.     }
  766.  
  767.     /*    check to see if new id_blk should be inserted between
  768.          *    the alp_vector header block and the first id_blk in
  769.          *    the current alpha chain
  770.          */
  771.  
  772.     if(strcmp(alp_vector[c].alp_top->id_name,ca_token) >0)
  773.     {      
  774.         ca_ptr->alp_lnk=alp_vector[c].alp_top;
  775.         alp_vector[c].alp_top=ca_ptr;
  776.         return;
  777.     }
  778.  
  779.     if(strcmp(alp_vector[c].alp_lst->id_name,ca_token) < 0)
  780.     {      
  781.         alp_vector[c].alp_lst->alp_lnk = ca_ptr;
  782.         ca_ptr->alp_lnk = NULL;
  783.         alp_vector[c].alp_lst=ca_ptr;
  784.         return;
  785.     }
  786.  
  787.     cur_ptr = alp_vector[c].alp_top;
  788.     while(strcmp(cur_ptr->id_name,ca_token) < 0)
  789.     {      
  790.         lst_ptr = cur_ptr;
  791.         cur_ptr = lst_ptr->alp_lnk;
  792.     }
  793.  
  794.     lst_ptr->alp_lnk = ca_ptr;
  795.     ca_ptr->alp_lnk = cur_ptr;
  796.     return;
  797. }/*chain_alpha.
  798. -----------------------------------------*/
  799.  
  800. struct id_blk *allo_id(aid_token)
  801. char  *aid_token;
  802. {
  803.     int  ai;
  804.     struct id_blk *aid_ptr;
  805.     char *malloc();                         /* Microsoft C */
  806.  
  807.     /*** if((aid_ptr =  alloc(sizeof(oneid))) == 0) { ***/         /* Microsoft C */
  808.     if((aid_ptr = (struct id_blk *) malloc(sizeof(oneid))) == 0) { /* MS C */
  809.  
  810.         printf("\nERROR: Unable to allocate identifier block\n");
  811.         exit(0);
  812.     }
  813.     ai=0;
  814.     do {
  815.         aid_ptr->id_name[ai] = aid_token[ai];
  816.     } 
  817.     while (aid_token[ai++] != NULL);
  818.     return (aid_ptr);
  819. }/*id_blk.
  820. -----------------------------------------*/
  821.  
  822. struct rf_blk *allo_rf(arf_ref)
  823. int  arf_ref;
  824. {
  825.     int ri;
  826.     struct rf_blk *arf_ptr;
  827.     char *malloc();                       /* Microsoft C */
  828.  
  829.     /** if((arf_ptr = alloc(sizeof(onerf))) == 0) { **/    /* Microsoft C */
  830.     if((arf_ptr = (struct rf_blk *) malloc(sizeof(onerf))) == 0) { /* MS C */
  831.         printf("\nERROR: Unable to allocate reference block\n");
  832.         exit(0);
  833.     }
  834.     arf_ptr->ref_item[0] = arf_ref;
  835.     arf_ptr->ref_cnt = 1;  
  836.     arf_ptr->ref_lnk = NULL;
  837.     for (ri=1;ri<MAX_REF;ri++)
  838.         arf_ptr->ref_item[ri] = NULL;
  839.     return (arf_ptr);
  840. }/*allo_rf.
  841. ------------------------------------------*/
  842.  
  843.  
  844. struct rf_blk *add_rf(adr_ptr,adr_ref)
  845. struct rf_blk *adr_ptr;
  846. int adr_ref;
  847. {
  848.     if(adr_ptr->ref_cnt == MAX_REF)
  849.         return adr_ptr->ref_lnk = allo_rf(adr_ref);
  850.     else {
  851.         adr_ptr->ref_item[adr_ptr->ref_cnt++] = adr_ref;
  852.         return (adr_ptr);
  853.     }
  854. }/*rf_blk.
  855. ------------------------------------------*/
  856.  
  857. void prnt_tbl()
  858. {
  859.     int lin_cnt, pref, prf_cnt, pti;
  860.     struct id_blk *pid_ptr;
  861.     struct rf_blk *ptb_ptr;
  862.     void nl();
  863.  
  864.     prt_ref = TRUE;
  865.  
  866.     for (pti=0;pti<MAX_ALPHA;pti++)
  867.     {      
  868.         if ((pid_ptr = alp_vector[pti].alp_top) != NULL)
  869.         {    
  870.             do
  871.                 {    
  872.                 if(o_flg)                          /* WHR */
  873.                     fprintf(l_buffer,"%-14.13s: ",pid_ptr->id_name);
  874.                 else printf("%-14.13s: ",pid_ptr->id_name);
  875.                 ptb_ptr=pid_ptr->top_lnk;
  876.                 lin_cnt=prf_cnt=0;
  877.                 do
  878.                     {     
  879.                     if(prf_cnt == MAX_REF)
  880.                     {    
  881.                         prf_cnt=0;
  882.                         ptb_ptr = ptb_ptr->ref_lnk;
  883.                     }
  884.                     if(ptb_ptr)
  885.                     {
  886.                         if((pref=ptb_ptr->ref_item[prf_cnt++]) != 0)
  887.                         {
  888.                             if (lin_cnt++ == REFS_PER_LINE)
  889.                             {    
  890.                                 nl();             /* WHR,WCC */
  891.                                 if (o_flg) fprintf(l_buffer,"\t\t");
  892.                                 else printf("\t\t");
  893.                                 lin_cnt = 1;
  894.                             }
  895.                             if(o_flg) fprintf(l_buffer,"%-4d  ",pref);
  896.                             else printf("%-4d  ",pref);
  897.                         }
  898.                     }
  899.                     else pref=0;
  900.                 } 
  901.                 while (pref);
  902.                 nl();
  903.             } 
  904.             while ((pid_ptr=pid_ptr->alp_lnk) != NULL);
  905.         }
  906.     }
  907. }/*prnt_tbl.
  908. ---------------------------------------*/
  909.  
  910. void nl()
  911. {
  912.     if (o_flg) 
  913.         fprintf(l_buffer,"\n");                 
  914.     else
  915.         printf("\n");
  916.  
  917.     if(!prt_ref)
  918.     {    
  919. /*
  920.            if (o_flg) fprintf(l_buffer,"%-4d %4d:\t",
  921.                 ++linum,++edtnum);           
  922.            else printf("%-4d %4d:\t",++linum,++edtnum);'
  923. */
  924.         ++linum ;
  925.         ++edtnum ;
  926.  
  927.         if(o_flg)
  928.             if(linum % 60 == 1) printf("\n<%d>\t",linum);
  929.         else printf(".");
  930.     }
  931.     return;
  932. }/*nl.
  933. -------------------------------------------*/
  934. /*============= end of file xc.c ==========================*/
  935.  
  936.