home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / fchk294s.zip / ftnchek-2.9.4 / project.c < prev    next >
C/C++ Source or Header  |  1996-03-14  |  28KB  |  974 lines

  1. /* project.c:
  2.     Project-file I/O routines.  Routines included:
  3.  
  4.     Shared routines:
  5.        void proj_file_out() writes data from symbol table to project file.
  6.        void proj_file_in() reads data from project file to symbol table.
  7.  
  8.     Private routines:
  9.         int has_defn()        TRUE if external has defn in current file
  10.         int has_call()        TRUE if external has call in current file
  11.         int count_com_defns() Counts multiple common defns.
  12.         void proj_alist_out() Outputs argument lists
  13.         void proj_clist_out() Outputs common lists
  14.         void proj_arg_info_in()  Inputs argument lists
  15.         void proj_com_info_in()  Inputs common lists
  16. */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "ftnchek.h"
  21. #define PROJECT
  22. #include "symtab.h"
  23. #include <string.h>
  24.  
  25. /* Note: compilation option PROJ_KEEPALL
  26.  
  27.    Define the symbol PROJ_KEEPALL to make Ftnchek create project files
  28.    with complete global symbol table information.  Otherwise, the default
  29.    action is: in library mode, keep only subprogram definitions, those
  30.    external references not defined in the current file, and only one
  31.    instance of each common block.  In non-library mode, the default is to
  32.    keep, besides the above, one call of a given routine from each module,
  33.    and all common block declarations.
  34.    PROJ_KEEPALL is useful mainly for debugging purposes.
  35. */
  36. #define PROJFILE_COOKIE "FTNCHEK_" /* first part of magic cookie */
  37.  
  38.  
  39. PROTO(PRIVATE int count_com_defns,( ComListHeader *clist ));
  40. PROTO(PRIVATE char *getstrn,(char s[], int n, FILE *fd));
  41. PROTO(PRIVATE int has_call,( ArgListHeader *alist ));
  42. PROTO(PRIVATE int has_defn,( ArgListHeader *alist ));
  43. PROTO(PRIVATE int nil,( void ));
  44. PROTO(PRIVATE void proj_alist_out,( Gsymtab *gsymt, FILE *fd, int
  45.                 do_defns, int locally_defined ));
  46. PROTO(PRIVATE void proj_arg_info_in,( FILE *fd, char *filename, int is_defn ));
  47. PROTO(PRIVATE void proj_clist_out,( Gsymtab *gsymt, FILE *fd ));
  48. PROTO(PRIVATE void proj_com_info_in,( FILE *fd, char *filename ));
  49.  
  50.  
  51.  
  52. PRIVATE int
  53. #if HAVE_STDC
  54. has_defn(ArgListHeader *alist)            /* Returns TRUE if list has defns */
  55. #else /* K&R style */
  56. has_defn(alist)            /* Returns TRUE if list has defns */
  57.    ArgListHeader *alist;
  58. #endif /* HAVE_STDC */
  59. {
  60.   while( alist != NULL && alist->topfile == top_filename ) {
  61.     if(alist->is_defn)
  62.       return TRUE;
  63.     alist = alist->next;
  64.   }
  65.   return FALSE;
  66. }
  67.  
  68.  
  69. PRIVATE int
  70. #if HAVE_STDC
  71. has_call(ArgListHeader *alist)        /* Returns TRUE if list has calls or defns  */
  72. #else /* K&R style */
  73. has_call(alist)        /* Returns TRUE if list has calls or defns  */
  74.    ArgListHeader *alist;
  75. #endif /* HAVE_STDC */
  76. {
  77.   while( alist != NULL && alist->topfile == top_filename) {
  78.     if( alist->is_call || alist->actual_arg )
  79.     return TRUE;
  80.     alist = alist->next;
  81.   }
  82.   return FALSE;
  83. }
  84.  
  85. PRIVATE int
  86. #if HAVE_STDC
  87. count_com_defns(ComListHeader *clist)        /* Returns number of common decls in list  */
  88. #else /* K&R style */
  89. count_com_defns(clist)        /* Returns number of common decls in list  */
  90.    ComListHeader *clist;
  91. #endif /* HAVE_STDC */
  92. {
  93.   int count=0;
  94.   while( clist != NULL && clist->topfile == top_filename ) {
  95.     ++count;
  96.     clist = clist->next;
  97.   }
  98.   return count;
  99. }
  100.  
  101.  
  102.     /* proj_file_out: writes data from symbol table to project file. */
  103.  
  104. #define WRITE_STR(LEADER,S)    (void)(fprintf(fd,LEADER), fprintf(fd," %s",S))
  105. #define WRITE_ARG(LEADER,S)    (void)(fprintf(fd,LEADER), fprintf(fd," %s",S))
  106. #define WRITE_NUM(LEADER,NUM)    (void)(fprintf(fd,LEADER), fprintf(fd," %ld",NUM))
  107. #define NEXTLINE        (void)fprintf(fd,"\n")
  108.  
  109. void
  110. #if HAVE_STDC
  111. proj_file_out(FILE *fd)
  112. #else /* K&R style */
  113. proj_file_out(fd)
  114.      FILE *fd;
  115. #endif /* HAVE_STDC */
  116. {
  117.   Gsymtab *sym_list[GLOBSYMTABSZ]; /* temp. list of symtab entries to print */
  118.   BYTE sym_has_defn[GLOBSYMTABSZ];
  119.   BYTE sym_has_call[GLOBSYMTABSZ];
  120.  
  121.   if(fd == NULL)
  122.     return;
  123.  
  124.   WRITE_STR(PROJFILE_COOKIE,PROJECT_VERSION); /* magic cookie */
  125.   NEXTLINE;
  126.  
  127.   WRITE_STR("file",top_filename);
  128.   NEXTLINE;
  129.  
  130.   {    /* Make list of subprograms defined or referenced in this file */
  131.     int i,numexts,numdefns,numcalls,do_defns,pass;
  132.     ArgListHeader *alist;
  133.     for(i=0,numexts=numdefns=numcalls=0;i<glob_symtab_top;i++) {
  134.       if(storage_class_of(glob_symtab[i].type) == class_SUBPROGRAM &&
  135.     (alist=glob_symtab[i].info.arglist) != NULL) {
  136.             /* Look for defns and calls of this guy. */
  137.  
  138.     if( (sym_has_defn[numexts]=has_defn(alist)) != (BYTE) FALSE )
  139.        numdefns++;
  140.     if( (sym_has_call[numexts]= (has_call(alist)
  141.         /* keep only externals not satisfied in this file */
  142. #ifndef PROJ_KEEPALL
  143.             && (!library_mode || !sym_has_defn[numexts])
  144. #endif
  145.                   )) != (BYTE) FALSE )
  146.        numcalls++;
  147.     if(sym_has_defn[numexts] || sym_has_call[numexts])
  148.       sym_list[numexts++] = &glob_symtab[i];
  149.       }
  150.     }
  151.  
  152.         /* List all subprogram defns, then all calls */
  153.     for(pass=0,do_defns=TRUE; pass<2; pass++,do_defns=!do_defns) {
  154.  
  155.       if(do_defns)
  156.     WRITE_NUM(" entries",(long)numdefns);
  157.       else
  158.     WRITE_NUM(" externals",(long)numcalls);
  159.       NEXTLINE;
  160.  
  161.       for(i=0; i<numexts; i++) {
  162.     if( (do_defns && sym_has_defn[i]) || (!do_defns && sym_has_call[i]) ){
  163.       if(do_defns)
  164.         WRITE_STR(" entry",sym_list[i]->name);
  165.       else
  166.         WRITE_STR(" external",sym_list[i]->name);
  167.  
  168.       WRITE_NUM(" class",(long)storage_class_of(sym_list[i]->type));
  169.       WRITE_NUM(" type",(long)datatype_of(sym_list[i]->type));
  170.       WRITE_NUM(" size",(long)sym_list[i]->size);
  171.       (void)fprintf(fd," flags %d %d %d %d %d %d %d %d",
  172.           sym_list[i]->used_flag,
  173.           sym_list[i]->set_flag,
  174.           sym_list[i]->invoked_as_func,
  175.           sym_list[i]->declared_external,
  176.           /* N.B. library_module included here but is not restored */
  177.           sym_list[i]->library_module,
  178.           0,    /* Flags for possible future use */
  179.           0,
  180.           0);
  181.       NEXTLINE;
  182.       proj_alist_out(sym_list[i],fd,do_defns,(int)sym_has_defn[i]);
  183.     }
  184.       }/* end for i */
  185.       NEXTLINE;
  186.     }/*end for pass */
  187.   }
  188.  
  189.   {
  190.     int i,numblocks,numdefns;
  191.     ComListHeader *clist;
  192.     for(i=0,numblocks=numdefns=0;i<glob_symtab_top;i++) {
  193.       if(storage_class_of(glob_symtab[i].type) == class_COMMON_BLOCK
  194.      && (clist=glob_symtab[i].info.comlist) != NULL &&
  195.      clist->topfile == top_filename ) {
  196. #ifndef PROJ_KEEPALL
  197.             /* No keepall: save only one com decl if -lib mode */
  198.     if(library_mode)
  199.       numdefns++;
  200.     else
  201. #endif            /* keepall or -nolib mode: keep all com decls */
  202.       numdefns += count_com_defns(clist);
  203.  
  204.     sym_list[numblocks++] = &glob_symtab[i];
  205.       }
  206.     }
  207.     WRITE_NUM(" comblocks",(long)numdefns);
  208.     NEXTLINE;
  209.     for(i=0; i<numblocks; i++) {
  210.       proj_clist_out(sym_list[i],fd);
  211.     }
  212.     NEXTLINE;
  213.   }
  214. }
  215.  
  216.  
  217.  
  218.  
  219.     /* proj_alist_out: writes arglist data from symbol table to
  220.        project file. */
  221.  
  222. PRIVATE void
  223. #if HAVE_STDC
  224. proj_alist_out(Gsymtab *gsymt, FILE *fd, int do_defns, int locally_defined)
  225. #else /* K&R style */
  226. proj_alist_out(gsymt,fd,do_defns,locally_defined)
  227.      Gsymtab *gsymt;
  228.      FILE *fd;
  229.      int do_defns,locally_defined;
  230. #endif /* HAVE_STDC */
  231. {
  232.   ArgListHeader *a=gsymt->info.arglist;
  233.   ArgListElement *arg;
  234.   int i,n;
  235.   unsigned long diminfo;
  236.   Gsymtab *last_calling_module;
  237.  
  238.  
  239.         /* This loop runs thru only those arglists that were
  240.             created in the current top file. */
  241.     last_calling_module = NULL;
  242.     while( a != NULL && a->topfile == top_filename) {
  243.         /* do_defns mode: output only definitions */
  244.      if( (do_defns && a->is_defn) || (!do_defns && !a->is_defn) )
  245. #ifndef PROJ_KEEPALL
  246.         /* keep only externals not satisfied in this file in -lib
  247.            mode, otherwise keep one actual call from each module. */
  248.     if( a->is_defn
  249.        || !locally_defined
  250.        || (!library_mode && (a->is_call || a->actual_arg)
  251.        && a->module != last_calling_module))
  252. #endif
  253.      {
  254.       last_calling_module = a->module;
  255.       if(a->is_defn)
  256.      (void)fprintf(fd," defn\n");
  257.       else
  258.      (void)fprintf(fd," call\n");
  259.  
  260.       WRITE_STR(" module",a->module->name);
  261.       WRITE_STR(" file",a->filename);
  262.       WRITE_NUM(" line",(long)a->line_num);
  263.       WRITE_NUM(" top",(long)a->top_line_num);
  264.       WRITE_NUM(" class",(long)storage_class_of(a->type));
  265.       WRITE_NUM(" type",(long)datatype_of(a->type));
  266.       WRITE_NUM(" size",(long)a->size);
  267.       (void)fprintf(fd," flags %d %d %d %d",
  268.           a->is_defn,
  269.           a->is_call,
  270.           a->external_decl,
  271.           a->actual_arg);
  272.       NEXTLINE;
  273.       n=a->numargs;
  274.       if(a->is_defn || a->is_call) {
  275.     WRITE_NUM(" args",(long)n);
  276.     NEXTLINE;
  277.       }
  278.  
  279.       /* Next lines, 2 per argument.
  280.        1st line: position number & name or source text of expr
  281.        2nd line: type, array dims, array size, flags
  282.        */
  283.       arg = a->arg_array;
  284.       for(i=0; i<n; i++) {
  285.     WRITE_NUM(" arg",(long)i+1);
  286.     WRITE_ARG(" name",arg[i].name);
  287.     NEXTLINE;
  288.     WRITE_NUM(" class",(long)storage_class_of(arg[i].type));
  289.     WRITE_NUM(" type",(long)datatype_of(arg[i].type));
  290.     WRITE_NUM(" size",(long)arg[i].size);
  291.     diminfo = (
  292.            ((storage_class_of(arg[i].type) == class_VAR) &&
  293.            is_computational_type(datatype_of(arg[i].type))) ?
  294.              arg[i].info.array_dim: 0 );
  295.     WRITE_NUM(" dims",(long)array_dims(diminfo));
  296.     WRITE_NUM(" elts",(long)array_size(diminfo));
  297.     (void)fprintf(fd," flags %d %d %d %d %d %d %d %d",
  298.         arg[i].is_lvalue,
  299.         arg[i].set_flag,
  300.         arg[i].assigned_flag,
  301.         arg[i].used_before_set,
  302.         arg[i].array_var,
  303.         arg[i].array_element,
  304.         arg[i].declared_external,
  305.         0);        /* possible flag for future use */
  306.     NEXTLINE;
  307.       }
  308.      }/* end if(do_defn...)*/
  309.      a = a->next;
  310.    }/* end while(a!=NULL)*/
  311.    (void)fprintf(fd," end\n");
  312. }/*proj_alist_out*/
  313.  
  314.  
  315.  
  316.     /* proj_clist_out writes common var list data from symbol
  317.        table to project file. */
  318.  
  319. PRIVATE void
  320. #if HAVE_STDC
  321. proj_clist_out(Gsymtab *gsymt, FILE *fd)
  322. #else /* K&R style */
  323. proj_clist_out(gsymt,fd)
  324.      Gsymtab *gsymt;
  325.      FILE *fd;
  326. #endif /* HAVE_STDC */
  327. {
  328.     ComListHeader *c=gsymt->info.comlist;
  329.     ComListElement *cvar;
  330.     int i,n;
  331.  
  332.     while( c != NULL && c->topfile == top_filename ) {
  333.  
  334.       WRITE_STR(" block",gsymt->name);
  335.       WRITE_NUM(" class",(long)storage_class_of(gsymt->type));
  336.       WRITE_NUM(" type",(long)datatype_of(gsymt->type));
  337.       NEXTLINE;
  338.       WRITE_STR(" module",c->module->name);
  339.       WRITE_STR(" file",c->filename);
  340.       WRITE_NUM(" line",(long)c->line_num);
  341.       WRITE_NUM(" top",(long)c->top_line_num);
  342.       (void)fprintf(fd," flags %d %d %d %d",
  343.           c->any_used,
  344.           c->any_set,
  345.           c->saved,
  346.           0);        /* Flag for possible future use */
  347.       NEXTLINE;
  348.       WRITE_NUM(" vars",(long)(n=c->numargs));
  349.       NEXTLINE;
  350.  
  351.     /* Next lines, 2 per variable.
  352.          1st line: position number, name.
  353.      2nd line: class, type, array dims, array size
  354.      */
  355.       cvar = c->com_list_array;
  356.       for(i=0; i<n; i++) {
  357.     WRITE_NUM(" var",(long)i+1);
  358.     WRITE_STR(" name",cvar[i].name);
  359.     NEXTLINE;
  360.     WRITE_NUM(" class",(long)storage_class_of(cvar[i].type));
  361.     WRITE_NUM(" type",(long)datatype_of(cvar[i].type));
  362.     WRITE_NUM(" size",(long)cvar[i].size);
  363.     WRITE_NUM(" dims",(long)array_dims(cvar[i].dimen_info));
  364.     WRITE_NUM(" elts",(long)array_size(cvar[i].dimen_info));
  365.     (void)fprintf(fd," flags %d %d %d %d %d %d %d %d",
  366.         cvar[i].used,
  367.         cvar[i].set,
  368.         cvar[i].used_before_set,
  369.         cvar[i].assigned,
  370.         0,        /* possible flags for future use */
  371.         0,
  372.         0,
  373.         0);
  374.       NEXTLINE;
  375.       }
  376.             /* keepall or -nolib: loop thru all defns.
  377.                Otherwise only keep the first. */
  378. #ifndef PROJ_KEEPALL
  379.       if(library_mode)
  380.     break;
  381. #endif
  382.       c = c->next;
  383.     }/* end while c != NULL */
  384. }
  385.  
  386. #undef WRITE_STR
  387. #undef WRITE_NUM
  388. #undef NEXTLINE
  389.  
  390.  
  391.     /* proj_file_in:
  392.        Reads a project file, storing info in global symbol table.
  393.        See proj_file_out and its subroutines for the current
  394.        project file format.
  395.      */
  396. #define MAXNAME 127 /* Max string that will be read in: see READ_STR below */
  397.  
  398.  
  399.             /* Macros for error-flagging input */
  400.  
  401. PRIVATE int nil(VOID)/* to make lint happy */
  402. { return 0; }
  403.  
  404. #define READ_ERROR (oops_message(OOPS_FATAL,proj_line_num,NO_COL_NUM,\
  405.      "error reading project file"),nil())
  406. #define READ_OK nil()
  407.  
  408. #define READ_FIRST_STR(LEADER,STR) (fscanf(fd,LEADER), \
  409.                     fscanf(fd,"%127s",STR))
  410. #define READ_STR(LEADER,STR) ((fscanf(fd,LEADER)==0 &&\
  411.                    fscanf(fd,"%127s",STR)==1)? READ_OK:READ_ERROR)
  412. #define READ_ARG(LEADER,STR) ((fscanf(fd,LEADER)==0 && fgetc(fd)==' ' &&\
  413.             (getstrn(STR,MAXNAME+1,fd)!=NULL)==1)? READ_OK:READ_ERROR)
  414. #define READ_NUM(LEADER,NUM) ((fscanf(fd,LEADER)==0 &&\
  415.                    fscanf(fd,"%d",&NUM)==1)? READ_OK:READ_ERROR)
  416. #define READ_LONG(LEADER,NUM) ((fscanf(fd,LEADER)==0 &&\
  417.                    fscanf(fd,"%ld",&NUM)==1)? READ_OK:READ_ERROR)
  418. #define NEXTLINE {int c;while( (c=fgetc(fd)) != EOF && c != '\n') continue;\
  419.             if(c == EOF) READ_ERROR; else ++proj_line_num;}
  420.  
  421.  
  422. PRIVATE unsigned proj_line_num;        
  423.             /* Line number in proj file for diagnostic output */
  424.  
  425. void
  426. #if HAVE_STDC
  427. proj_file_in(FILE *fd)
  428. #else /* K&R style */
  429. proj_file_in(fd)
  430.   FILE *fd;
  431. #endif /* HAVE_STDC */
  432. {
  433.   char buf[MAXNAME+1],*topfilename=NULL;
  434.   int retval;
  435.   unsigned numentries,ientry, numexts,iext, numblocks,iblock;
  436.  
  437.   proj_line_num = 1;
  438.  
  439.  while( (retval=READ_FIRST_STR(PROJFILE_COOKIE,buf)) == 1) {
  440.    if( strcmp(buf,PROJECT_VERSION) != 0 ) {
  441.      (void)fprintf(stderr,
  442.      "\nProject file is not correct version -- must be re-created\n");
  443.      exit(1);
  444.    }
  445.    NEXTLINE;
  446.         /* Save filename in permanent storage */
  447.    READ_STR("file",buf);
  448.    topfilename = new_global_string(buf);
  449.    NEXTLINE;
  450. #ifdef DEBUG_PROJECT
  451.  printf("\nread file %s\n",topfilename);
  452. #endif
  453.  
  454.  
  455.   READ_NUM(" entries",numentries); /* Get no. of entry points */
  456.   NEXTLINE;
  457. #ifdef DEBUG_PROJECT
  458.  printf("read entries %d\n",numentries);
  459. #endif
  460.                 /* Read defn arglists */
  461.   for(ientry=0; ientry<numentries; ientry++) {
  462.       proj_arg_info_in(fd,topfilename,TRUE);
  463.   }
  464.   NEXTLINE;
  465.  
  466.   READ_NUM(" externals",numexts);    /* Get no. of external refs */
  467. #ifdef DEBUG_PROJECT
  468.  printf("read exts %d\n",numexts);
  469. #endif
  470.   NEXTLINE;
  471.  
  472.                 /* Read invocation & ext def arglists */
  473.   for(iext=0; iext<numexts; iext++) {
  474.     proj_arg_info_in(fd,topfilename,FALSE);
  475.   }
  476.   NEXTLINE;
  477.  
  478.  
  479.             /* Read common block info */
  480.  
  481.    READ_NUM(" comblocks",numblocks);
  482. #ifdef DEBUG_PROJECT
  483.  printf("read num blocks %d\n",numblocks);
  484. #endif
  485.    NEXTLINE;
  486.  
  487.    for(iblock=0; iblock<numblocks; iblock++) {
  488.      proj_com_info_in(fd,topfilename);
  489.    }
  490.    NEXTLINE;
  491.  
  492.  }/* end while(retval == 1) */
  493.  
  494.  if(retval != EOF) READ_ERROR;
  495.  
  496.  init_symtab();        /* Clear out local strspace */
  497. }
  498.  
  499. static char *prev_file_name="";/* used to reduce number of callocs */
  500.  
  501.             /* Read arglist info */
  502. PRIVATE void
  503. #if HAVE_STDC
  504. proj_arg_info_in(FILE *fd, char *filename, int is_defn)
  505.                            /* name of toplevel file */
  506. #else /* K&R style */
  507. proj_arg_info_in(fd,filename,is_defn)
  508.     FILE *fd;
  509.     char *filename;        /* name of toplevel file */
  510.     int is_defn;
  511. #endif /* HAVE_STDC */
  512. {
  513.     char id_name[MAXNAME+1],module_name[MAXNAME+1],sentinel[6];
  514.     char file_name[MAXNAME+1];
  515.     char arg_name[MAXNAME+1];
  516.  
  517. #ifndef KEEP_ARG_NAMES
  518.     static char var[]="var",    /* text strings to use for now */
  519.             expr[]="expr";
  520. #endif
  521.     int id_class,id_type;
  522.     long id_size;
  523.     unsigned
  524.           id_used_flag,
  525.           id_set_flag,
  526.           id_invoked,
  527.           id_declared,
  528.           id_library_module,
  529.           future1,future2,future3;
  530.  
  531.     unsigned h;
  532.     Gsymtab *gsymt, *module;
  533.     unsigned alist_class,alist_type,alist_is_defn,alist_is_call,
  534.        alist_external_decl,alist_actual_arg;
  535.     unsigned alist_line, alist_topline;
  536.     long alist_size;
  537.     unsigned numargs,iarg,arg_num,arg_class,arg_type,arg_dims;
  538.     unsigned long arg_elts;
  539.     long arg_size;
  540.     unsigned            /* Flags for arguments */
  541.         arg_is_lvalue,
  542.         arg_set_flag,
  543.         arg_assigned_flag,
  544.         arg_used_before_set,
  545.         arg_array_var,
  546.         arg_array_element,
  547.         arg_declared_external,
  548.         arg_future_flag;    /* possible flag for future use */
  549.  
  550.     if(is_defn)
  551.     READ_STR(" entry",id_name); /* Entry point name */
  552.     else
  553.     READ_STR(" external",id_name); /* External name */
  554.     READ_NUM(" class",id_class); /* class as in symtab */
  555.     READ_NUM(" type",id_type); /* type as in symtab */
  556.     READ_LONG(" size",id_size); /* size as in symtab */
  557.     if(fscanf(fd," flags %d %d %d %d %d %d %d %d",
  558.           &id_used_flag,
  559.           &id_set_flag,
  560.           &id_invoked,
  561.           &id_declared,
  562.           &id_library_module,
  563.           &future1,&future2,&future3) != 8) READ_ERROR;
  564.     NEXTLINE;
  565.  
  566. #ifdef DEBUG_PROJECT
  567.  printf("read id name %s class %d type %d\n",
  568. id_name,id_class,id_type);
  569. #endif
  570.  
  571.                 /* Create global symtab entry */
  572.     h = hash_lookup(id_name);
  573.     if( (gsymt = hashtab[h].glob_symtab) == NULL) {
  574.       gsymt = install_global((int)h,id_type,class_SUBPROGRAM);
  575.       gsymt->size = id_size;
  576.     }
  577.     else if(is_defn)
  578.       gsymt->size = id_size;
  579.  
  580.         /* Set library_module flag if project file was created
  581.            with -lib mode in effect, or is now taken in -lib mode */
  582.     if(is_defn && (library_mode || id_library_module)) {
  583.       gsymt->library_module = TRUE;
  584.     }
  585.     if(is_defn)
  586.       gsymt->defined = TRUE;
  587.     if(id_used_flag)
  588.       gsymt->used_flag = TRUE;
  589.     if(id_set_flag)
  590.       gsymt->set_flag = TRUE;
  591.     if(id_invoked)
  592.       gsymt->invoked_as_func = TRUE;
  593.     if(id_declared)
  594.       gsymt->declared_external = TRUE;
  595.  
  596.    while(   fscanf(fd,"%5s",sentinel),
  597. #ifdef DEBUG_PROJECT
  598.  printf("sentinel=[%s]\n",sentinel),
  599. #endif
  600.      strcmp(sentinel,(is_defn?"defn":"call")) == 0) {
  601.       ArgListHeader *ahead;
  602.       ArgListElement *alist;
  603. #ifdef KEEP_ARG_NAMES
  604.       ArgListHeader *prev_ahead;
  605.       ArgListElement *prev_alist;
  606.       int prev_n;
  607. #endif
  608.  
  609.       NEXTLINE;
  610.  
  611.       READ_STR(" module",module_name);
  612.       READ_STR(" file",file_name);
  613.       READ_NUM(" line",alist_line); /* line number */
  614.       READ_NUM(" top",alist_topline); /* topfile line number */
  615.       READ_NUM(" class",alist_class);    /* class as in ArgListHeader */
  616.       READ_NUM(" type",alist_type); /* type as in ArgListHeader */
  617.       READ_LONG(" size",alist_size); /* size as in ArgListHeader */
  618.       if(fscanf(fd," flags %d %d %d %d",
  619.         &alist_is_defn,
  620.         &alist_is_call,
  621.         &alist_external_decl,
  622.         &alist_actual_arg) != 4) READ_ERROR;
  623.       NEXTLINE;
  624. #ifdef DEBUG_PROJECT
  625.  printf("read alist class %d type %d line %d\n",
  626. alist_class,alist_type,alist_line);
  627. #endif
  628.         /* Find current module in symtab. If not there, make
  629.            a global symtab entry for it. It will be filled
  630.            in eventually when processing corresponding entry.
  631.          */
  632.  
  633.       h = hash_lookup(module_name);
  634.       if( (module = hashtab[h].glob_symtab) == NULL) {
  635.     module = install_global((int)h,type_UNDECL,class_SUBPROGRAM);
  636.       }
  637.       if(module->internal_entry) {
  638.     warning(NO_LINE_NUM,NO_COL_NUM,
  639.         "entry point redefined as module");
  640.     msg_tail(module->name);
  641.     msg_tail(": redefinition ignored");
  642.       }
  643.       else {
  644.     if(is_defn) {
  645.       if(module != gsymt) {
  646. #ifdef DEBUG_PROJECT
  647.         printf("\nLinking entry %s to module %s",
  648.            gsymt->name,module->name);
  649. #endif
  650.         gsymt->internal_entry = TRUE;
  651.         gsymt->link.module=module; /* interior entry: link it to module */
  652.       }
  653.     }
  654.     else {            /* call: add to child list */
  655.         /* Avoid duplication on child list.  It will have just
  656.            been placed there on previous project-file entry,
  657.            so it will be the first child on the list.
  658.         */
  659. #ifdef DEBUG_PROJECT
  660.       printf("\nChild %s of module %s",
  661.          gsymt->name,module->name);
  662. #endif
  663.       if(module->link.child_list == NULL
  664.          || module->link.child_list->child != gsymt) {
  665.         ChildList *node=
  666.           (ChildList *)calloc(1,sizeof(ChildList));
  667. #ifdef DEBUG_PROJECT
  668.         printf(" linked in");
  669. #endif
  670.         node->child = gsymt;
  671.         node->next = module->link.child_list;
  672.         module->link.child_list = node;
  673.       }
  674. #ifdef DEBUG_PROJECT
  675.       else {
  676.         printf(" (duplicate)");
  677.       }
  678. #endif
  679.     }
  680.       }
  681.  
  682.       if(alist_is_defn || alist_is_call) {
  683.       READ_NUM(" args",numargs);
  684.       NEXTLINE;
  685.       }
  686.       else
  687.     numargs = 0;
  688.  
  689. #ifdef DEBUG_PROJECT
  690.  printf("read numargs %d\n",numargs);
  691. #endif
  692. /*
  693. **      if(!is_defn) {
  694. **    gsymt->used_flag = TRUE;
  695. **      }
  696. */
  697.                 /* Create arglist structure */
  698.       if(((ahead=(ArgListHeader *) calloc(1, sizeof(ArgListHeader)))
  699.                   == (ArgListHeader *) NULL) ||
  700.       (numargs != 0 &&
  701.           ((alist=(ArgListElement *) calloc(numargs,sizeof(ArgListElement)))
  702.                  == (ArgListElement *) NULL))){
  703.         oops_message(OOPS_FATAL,proj_line_num,NO_COL_NUM,
  704.                  "out of malloc space for argument list");
  705.       }
  706.  
  707.             /* Initialize arglist and link it to symtab */
  708.       ahead->type = type_byte(alist_class,alist_type);
  709.       ahead->size = alist_size;
  710.       ahead->numargs = (short)numargs;
  711.       ahead->arg_array = (numargs==0? NULL: alist);
  712.       ahead->module = module;
  713.       ahead->topfile = filename;
  714.             /* try to avoid reallocating space for same name */
  715.       ahead->filename =
  716.     (strcmp(file_name,filename)==0? filename:
  717.      (strcmp(file_name,prev_file_name)==0? prev_file_name:
  718.       (prev_file_name=new_global_string(file_name))));
  719.  
  720.       ahead->line_num = alist_line;
  721.       ahead->top_line_num = alist_topline;
  722.       ahead->is_defn = alist_is_defn;
  723.       ahead->is_call = alist_is_call;
  724.       ahead->external_decl = alist_external_decl;
  725.       ahead->actual_arg = alist_actual_arg;
  726.       ahead->next = prev_ahead = gsymt->info.arglist;
  727.       gsymt->info.arglist = ahead;
  728.       if(prev_ahead != NULL) {
  729.     prev_n = prev_ahead->numargs;
  730.     prev_alist = prev_ahead->arg_array;
  731.       }
  732.  
  733.             /* Fill arglist array from project file */
  734.       for(iarg=0; iarg<numargs; iarg++) {
  735.     READ_NUM(" arg",arg_num);    if(arg_num != iarg+1) READ_ERROR;
  736.     READ_ARG(" name",arg_name);
  737.     READ_NUM(" class",arg_class);
  738.     READ_NUM(" type",arg_type);
  739.     READ_LONG(" size",arg_size);
  740.     READ_NUM(" dims",arg_dims);
  741.     READ_LONG(" elts",arg_elts);
  742.     if(fscanf(fd," flags %d %d %d %d %d %d %d %d",
  743.         &arg_is_lvalue,
  744.         &arg_set_flag,
  745.         &arg_assigned_flag,
  746.         &arg_used_before_set,
  747.         &arg_array_var,
  748.         &arg_array_element,
  749.         &arg_declared_external,
  750.         &arg_future_flag) != 8) READ_ERROR;
  751.  
  752. #ifdef KEEP_ARG_NAMES
  753.             /* Economize storage by re-using previously allocated
  754.                space for same name in prior call if any */
  755.     alist[iarg].name = (prev_ahead != NULL && iarg < prev_n &&
  756.               strcmp(arg_name,prev_alist[iarg].name) == 0) ?
  757.                 prev_alist[iarg].name:
  758.                 new_global_string(arg_name);
  759. #else
  760.     if(strcmp(arg_name,expr) == 0) /* For now, just use "var" and "expr" */
  761.       alist[iarg].name = expr;
  762.     else
  763.       alist[iarg].name = var;
  764. #endif
  765.     alist[iarg].info.array_dim = array_dim_info(arg_dims,arg_elts);
  766.     alist[iarg].type = type_byte(arg_class,arg_type);
  767.     alist[iarg].size = arg_size;
  768.     alist[iarg].is_lvalue = arg_is_lvalue;
  769.     alist[iarg].set_flag = arg_set_flag;
  770.     alist[iarg].assigned_flag = arg_assigned_flag;
  771.     alist[iarg].used_before_set = arg_used_before_set;
  772.     alist[iarg].array_var = arg_array_var;
  773.     alist[iarg].array_element = arg_array_element;
  774.     alist[iarg].declared_external = arg_declared_external;
  775.     NEXTLINE;
  776. #ifdef DEBUG_PROJECT
  777.  printf("read arg num %d name %s\n",arg_num,arg_name);
  778. #endif
  779.       }
  780.  
  781.     }/* end while( sentinel == "defn"|"call") */
  782.  
  783.     if(strcmp(sentinel,"end") != 0) READ_ERROR;
  784.     NEXTLINE;
  785. }
  786.  
  787.  
  788. PRIVATE void
  789. #if HAVE_STDC
  790. proj_com_info_in(FILE *fd, char *filename)
  791. #else /* K&R style */
  792. proj_com_info_in(fd,filename)
  793.      FILE *fd;
  794.      char *filename;
  795. #endif /* HAVE_STDC */
  796. {
  797.     char id_name[MAXNAME+1],module_name[MAXNAME+1];
  798.     char file_name[MAXNAME+1];
  799.     char var_name[MAXNAME+1];
  800.     unsigned id_class,id_type;
  801.     unsigned            /* Flags in ComListHeader */
  802.         clist_any_used,
  803.         clist_any_set,
  804.         clist_saved,
  805.         clist_future;
  806.     unsigned clist_line,clist_topline;
  807.     unsigned numvars,prev_n,ivar,var_num,var_class,var_type,var_dims;
  808.     unsigned long var_elts;
  809.     unsigned            /* Flags for common variables */
  810.         var_used,
  811.         var_set,
  812.         var_used_before_set,
  813.         var_assigned,
  814.         var_future_4,
  815.         var_future_3,
  816.         var_future_2,
  817.         var_future_1;
  818.     long var_size;
  819.       int h;
  820.       Gsymtab *gsymt, *module;
  821.       ComListHeader *chead,*prev_chead;
  822.       ComListElement *clist,*prev_clist;
  823.  
  824.  
  825.     READ_STR(" block",id_name);
  826.     READ_NUM(" class",id_class);
  827.     READ_NUM(" type",id_type);
  828. #ifdef DEBUG_PROJECT
  829.  printf("read com name %s class %d type %d\n",
  830. id_name,id_class,id_type);
  831. #endif
  832.     NEXTLINE;
  833.  
  834.     READ_STR(" module",module_name);
  835.     READ_STR(" file",file_name);
  836.     READ_NUM(" line",clist_line);
  837.     READ_NUM(" top",clist_topline);
  838.     if(fscanf(fd," flags %d %d %d %d",
  839.         &clist_any_used,
  840.         &clist_any_set,
  841.         &clist_saved,
  842.         &clist_future) != 4) READ_ERROR;
  843.     NEXTLINE;
  844.  
  845.     READ_NUM(" vars",numvars);
  846. #ifdef DEBUG_PROJECT
  847.  printf("read module %s file %s",module_name,file_name);
  848.  printf(" flags %d %d %d %d line %d\n",
  849.     clist_any_used,
  850.     clist_any_set,
  851.     clist_saved,
  852.     clist_future,
  853.     clist_line);
  854. #endif
  855.     NEXTLINE;
  856.                 /* Create global symtab entry */
  857.     h = hash_lookup(id_name);
  858.     if( (gsymt = hashtab[h].com_glob_symtab) == NULL)
  859.       gsymt = install_global(h,(int)id_type,(int)id_class);
  860.  
  861.  
  862.                 /* Create arglist structure */
  863.     if(((chead=(ComListHeader *) calloc(1, sizeof(ComListHeader)))
  864.                   == (ComListHeader *) NULL) ||
  865.       (numvars != 0 &&
  866.           ((clist=(ComListElement *) calloc(numvars,sizeof(ComListElement)))
  867.                  == (ComListElement *) NULL))){
  868.         oops_message(OOPS_FATAL,proj_line_num,NO_COL_NUM,
  869.                  "out of malloc space for common list");
  870.       }
  871.  
  872.         /* Find current module in symtab. If not there, make
  873.            a global symtab entry for it.  This is bogus, since
  874.            all modules should have been defined previously. */
  875.  
  876.       h = hash_lookup(module_name);
  877.       if( (module = hashtab[h].glob_symtab) == NULL) {
  878.     (void)fprintf(stderr,"\nWarning-- something's bogus in project file\n");
  879.     module = install_global(h,type_UNDECL,class_SUBPROGRAM);
  880.       }
  881.  
  882.             /* Initialize arglist and link it to symtab */
  883.       chead->numargs = (short)numvars;
  884.       chead->line_num = clist_line;
  885.       chead->top_line_num = clist_topline;
  886.       chead->com_list_array = (numvars==0? NULL: clist);
  887.       chead->module = module;
  888.       chead->topfile = filename;
  889.       chead->any_used = clist_any_used;
  890.       chead->any_set = clist_any_set;
  891.       chead->saved = clist_saved;
  892.             /* try to avoid reallocating space for same name */
  893.       chead->filename =
  894.     (strcmp(file_name,filename)==0? filename:
  895.      (strcmp(file_name,prev_file_name)==0? prev_file_name:
  896.       (prev_file_name=new_global_string(file_name))));
  897.  
  898.       chead->next = prev_chead = gsymt->info.comlist;
  899.       gsymt->info.comlist = chead;
  900.       if(prev_chead != NULL) {
  901.     prev_n = prev_chead->numargs;
  902.     prev_clist = prev_chead->com_list_array;
  903.       }
  904.  
  905.             /* Fill comlist array from project file */
  906.     for(ivar=0; ivar<numvars; ivar++) {
  907.       READ_NUM(" var",var_num); if(var_num != ivar+1) READ_ERROR;
  908.       READ_STR(" name",var_name);
  909.       NEXTLINE;
  910.       READ_NUM(" class",var_class);
  911.       READ_NUM(" type",var_type);
  912.       READ_LONG(" size",var_size);
  913.       READ_NUM(" dims",var_dims);
  914.       READ_LONG(" elts",var_elts);
  915.     if(fscanf(fd," flags %d %d %d %d %d %d %d %d",
  916.         &var_used,
  917.         &var_set,
  918.         &var_used_before_set,
  919.         &var_assigned,
  920.         &var_future_4,
  921.         &var_future_3,
  922.         &var_future_2,
  923.         &var_future_1) != 8) READ_ERROR;
  924.       NEXTLINE;
  925. #ifdef DEBUG_PROJECT
  926.  printf("read name %s class %d type %d dims %d size %d\n",
  927. var_name,var_class,var_type,var_dims,var_size);
  928. #endif
  929.             /* Economize storage by re-using previously allocated
  930.                space for same name in prior decl if any */
  931.       clist[ivar].name = (prev_chead != NULL && ivar < prev_n &&
  932.               strcmp(var_name,prev_clist[ivar].name) == 0) ?
  933.                 prev_clist[ivar].name:
  934.                 new_global_string(var_name);
  935.  
  936.       clist[ivar].dimen_info = array_dim_info(var_dims,var_elts);
  937.       clist[ivar].type = type_byte(var_class,var_type);
  938.       clist[ivar].size = var_size;
  939.       clist[ivar].used = var_used;
  940.       clist[ivar].set = var_set;
  941.       clist[ivar].used_before_set = var_used_before_set;
  942.       clist[ivar].assigned = var_assigned;
  943.     }
  944. }/*proj_com_info_in*/
  945.  
  946.     /*  Function to read n-1 characters, or up to newline, whichever
  947.      *  comes first.  Differs from fgets in that the newline is replaced
  948.      *  by null, and characters up to newline (if any) past the n-1st
  949.      *  are read and thrown away.
  950.      *  Returns NULL when end-of-file or error is encountered.
  951.      */
  952. PRIVATE char *
  953. #if HAVE_STDC
  954. getstrn(char *s, int n, FILE *fd)
  955. #else /* K&R style */
  956. getstrn(s,n,fd)
  957.     char s[];
  958.     int n;
  959.     FILE *fd;
  960. #endif /* HAVE_STDC */
  961. {
  962.     int i=0,c;
  963.  
  964.     while( (c=getc(fd)) != '\n' ) {
  965.         if(c == EOF)
  966.             return NULL;
  967.  
  968.         if(i < n-1)
  969.             s[i++] = c;
  970.     }
  971.     s[i] = '\0';
  972.     return s;
  973. }
  974.