📄 project.c
字号:
/*Copyright (c) 2000, Red Hat, Inc.This file is part of Source-Navigator.Source-Navigator is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public License as publishedby the Free Software Foundation; either version 2, or (at your option)any later version.Source-Navigator is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public License alongwith Source-Navigator; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330, Boston,MA 02111-1307, USA.*//* project.c: Project-file I/O routines. Routines included: Shared routines: void proj_file_out() writes data from symbol table to project file. void proj_file_in() reads data from project file to symbol table. Private routines: int has_defn() TRUE if external has defn in current file int has_call() TRUE if external has call in current file int count_com_defns() Counts multiple common defns. void proj_alist_out() Outputs argument lists void proj_clist_out() Outputs common lists void proj_arg_info_in() Inputs argument lists void proj_com_info_in() Inputs common lists*/#include <stdio.h>#include <string.h>#include "ftnchek.h"#define PROJECT#include "symtab.h"#include <string.h>#include <tcl.h>#if defined (__MSVC__) || defined(__STDC__) || defined(__osf__)#include <stdlib.h>#elsevoid exit();#endif/* Note: compilation option PROJ_KEEPALL Define the symbol PROJ_KEEPALL to make Ftnchek create project files with complete global symbol table information. Otherwise, the default action is: in library mode, keep only subprogram definitions, those external references not defined in the current file, and only one instance of each common block. In non-library mode, the default is to keep, besides the above, one call of a given routine from each module, and all common block declarations. PROJ_KEEPALL is useful mainly for debugging purposes.*/#define PROJFILE_COOKIE "FTNCHEK_" /* first part of magic cookie */PRIVATE int has_defn(), has_call();PRIVATE void proj_alist_out(),proj_clist_out(), proj_arg_info_in(),proj_com_info_in();PRIVATE int count_com_defns();static void * SN_calloc (int size1, int size2){ void * p; p = ckalloc (size1*size2); memset (p, 0, size1*size2); return p;}PRIVATE inthas_defn(alist) /* Returns TRUE if list has defns */ ArgListHeader *alist;{ while( alist != NULL && alist->topfile == top_filename ) { if(alist->is_defn) return TRUE; alist = alist->next; } return FALSE;}PRIVATE inthas_call(alist) /* Returns TRUE if list has calls or defns */ ArgListHeader *alist;{ while( alist != NULL && alist->topfile == top_filename) { if( alist->is_call || alist->actual_arg ) return TRUE; alist = alist->next; } return FALSE;}PRIVATE intcount_com_defns(clist) /* Returns number of common decls in list */ ComListHeader *clist;{ int count=0; while( clist != NULL && clist->topfile == top_filename ) { ++count; clist = clist->next; } return count;} /* proj_file_out: writes data from symbol table to project file. */#define WRITE_STR(LEADER,S) (fprintf(fd,LEADER), fprintf(fd," %s",S))#define WRITE_NUM(LEADER,NUM) (fprintf(fd,LEADER), fprintf(fd," %ld",NUM))#define NEXTLINE fprintf(fd,"\n")voidproj_file_out(fd) FILE *fd;{ Gsymtab *sym_list[GLOBSYMTABSZ]; /* temp. list of symtab entries to print */ BYTE sym_has_defn[GLOBSYMTABSZ]; BYTE sym_has_call[GLOBSYMTABSZ]; if(fd == NULL) return; WRITE_STR(PROJFILE_COOKIE,PROJECT_VERSION); /* magic cookie */ NEXTLINE; WRITE_STR("file",top_filename); NEXTLINE; { /* Make list of subprograms defined or referenced in this file */ int i,numexts,numdefns,numcalls,do_defns,pass; ArgListHeader *alist; for(i=0,numexts=numdefns=numcalls=0;i<glob_symtab_top;i++) { if(storage_class_of(glob_symtab[i].type) == class_SUBPROGRAM && (alist=glob_symtab[i].info.arglist) != NULL) { /* Look for defns and calls of this guy. */ if( (sym_has_defn[numexts]=has_defn(alist)) != (BYTE) FALSE ) numdefns++; if( (sym_has_call[numexts]= (has_call(alist) /* keep only externals not satisfied in this file */#ifndef PROJ_KEEPALL && (!library_mode || !sym_has_defn[numexts])#endif )) != (BYTE) FALSE ) numcalls++; if(sym_has_defn[numexts] || sym_has_call[numexts]) sym_list[numexts++] = &glob_symtab[i]; } } /* List all subprogram defns, then all calls */ for(pass=0,do_defns=TRUE; pass<2; pass++,do_defns=!do_defns) { if(do_defns) WRITE_NUM(" entries",(long)numdefns); else WRITE_NUM(" externals",(long)numcalls); NEXTLINE; for(i=0; i<numexts; i++) { if( (do_defns && sym_has_defn[i]) || (!do_defns && sym_has_call[i]) ){ if(do_defns) WRITE_STR(" entry",sym_list[i]->name); else WRITE_STR(" external",sym_list[i]->name); WRITE_NUM(" class",(long)storage_class_of(sym_list[i]->type)); WRITE_NUM(" type",(long)datatype_of(sym_list[i]->type)); WRITE_NUM(" size",(long)sym_list[i]->size); fprintf(fd," flags %d %d %d %d %d %d %d %d", sym_list[i]->used_flag, sym_list[i]->set_flag, sym_list[i]->invoked_as_func, sym_list[i]->declared_external, /* N.B. library_module included here but is not restored */ sym_list[i]->library_module, 0, /* Flags for possible future use */ 0, 0); NEXTLINE; proj_alist_out(sym_list[i],fd,do_defns,(int)sym_has_defn[i]); } }/* end for i */ NEXTLINE; }/*end for pass */ } { int i,numblocks,numdefns; ComListHeader *clist; for(i=0,numblocks=numdefns=0;i<glob_symtab_top;i++) { if(storage_class_of(glob_symtab[i].type) == class_COMMON_BLOCK && (clist=glob_symtab[i].info.comlist) != NULL && clist->topfile == top_filename ) {#ifndef PROJ_KEEPALL /* No keepall: save only one com decl if -lib mode */ if(library_mode) numdefns++; else#endif /* keepall or -nolib mode: keep all com decls */ numdefns += count_com_defns(clist); sym_list[numblocks++] = &glob_symtab[i]; } } WRITE_NUM(" comblocks",(long)numdefns); NEXTLINE; for(i=0; i<numblocks; i++) { proj_clist_out(sym_list[i],fd); } NEXTLINE; }} /* proj_alist_out: writes arglist data from symbol table to project file. */PRIVATE voidproj_alist_out(gsymt,fd,do_defns,locally_defined) Gsymtab *gsymt; FILE *fd; int do_defns,locally_defined;{ ArgListHeader *a=gsymt->info.arglist; ArgListElement *arg; int i,n; unsigned long diminfo; Gsymtab *last_calling_module; /* This loop runs thru only those arglists that were created in the current top file. */ last_calling_module = NULL; while( a != NULL && a->topfile == top_filename) { /* do_defns mode: output only definitions */ if( (do_defns && a->is_defn) || (!do_defns && !a->is_defn) )#ifndef PROJ_KEEPALL /* keep only externals not satisfied in this file in -lib mode, otherwise keep one actual call from each module. */ if( a->is_defn || !locally_defined || (!library_mode && (a->is_call || a->actual_arg) && a->module != last_calling_module))#endif { last_calling_module = a->module; if(a->is_defn) fprintf(fd," defn\n"); else fprintf(fd," call\n"); WRITE_STR(" module",a->module->name); WRITE_STR(" file",a->filename); WRITE_NUM(" line",(long)a->line_num); WRITE_NUM(" class",(long)storage_class_of(a->type)); WRITE_NUM(" type",(long)datatype_of(a->type)); WRITE_NUM(" size",(long)a->size); fprintf(fd," flags %d %d %d %d", a->is_defn, a->is_call, a->external_decl, a->actual_arg); NEXTLINE; n=a->numargs; if(a->is_defn || a->is_call) { WRITE_NUM(" args",(long)n); NEXTLINE; } /* Next lines, 1 per argument: type, array dims, array size, flags */ arg = a->arg_array; for(i=0; i<n; i++) { WRITE_NUM(" arg",(long)i+1); WRITE_NUM(" class",(long)storage_class_of(arg[i].type)); WRITE_NUM(" type",(long)datatype_of(arg[i].type)); WRITE_NUM(" size",(long)arg[i].size); diminfo = ( ((storage_class_of(arg[i].type) == class_VAR) && is_computational_type(datatype_of(arg[i].type))) ? arg[i].info.array_dim: 0 ); WRITE_NUM(" dims",(long)array_dims(diminfo)); WRITE_NUM(" elts",(long)array_size(diminfo)); fprintf(fd," flags %d %d %d %d %d %d %d %d", arg[i].is_lvalue, arg[i].set_flag, arg[i].assigned_flag, arg[i].used_before_set, arg[i].array_var, arg[i].array_element, arg[i].declared_external, 0); /* possible flag for future use */ NEXTLINE; } }/* end if(do_defn...)*/ a = a->next; }/* end while(a!=NULL)*/ fprintf(fd," end\n");}/*proj_alist_out*/ /* proj_clist_out writes common var list data from symbol table to project file. */PRIVATE voidproj_clist_out(gsymt,fd) Gsymtab *gsymt; FILE *fd;{ ComListHeader *c=gsymt->info.comlist; ComListElement *cvar; int i,n; while( c != NULL && c->topfile == top_filename ) { WRITE_STR(" block",gsymt->name); WRITE_NUM(" class",(long)storage_class_of(gsymt->type)); WRITE_NUM(" type",(long)datatype_of(gsymt->type)); NEXTLINE; WRITE_STR(" module",c->module->name); WRITE_STR(" file",c->filename); WRITE_NUM(" line",(long)c->line_num); fprintf(fd," flags %d %d %d %d", c->any_used, c->any_set, c->saved, 0); /* Flag for possible future use */ NEXTLINE; WRITE_NUM(" vars",(long)(n=c->numargs)); NEXTLINE; /* Next lines, 1 per variable: class, type, array dims, array size */ cvar = c->com_list_array; for(i=0; i<n; i++) { WRITE_NUM(" var",(long)i+1); WRITE_NUM(" class",(long)storage_class_of(cvar[i].type)); WRITE_NUM(" type",(long)datatype_of(cvar[i].type)); WRITE_NUM(" size",(long)cvar[i].size); WRITE_NUM(" dims",(long)array_dims(cvar[i].dimen_info)); WRITE_NUM(" elts",(long)array_size(cvar[i].dimen_info)); fprintf(fd," flags %d %d %d %d %d %d %d %d", cvar[i].used, cvar[i].set, cvar[i].used_before_set, cvar[i].assigned, 0, /* possible flags for future use */ 0, 0, 0); NEXTLINE; } /* keepall or -nolib: loop thru all defns. Otherwise only keep the first. */#ifndef PROJ_KEEPALL if(library_mode) break;#endif c = c->next; }/* end while c != NULL */}#undef WRITE_STR#undef WRITE_NUM#undef NEXTLINE /* proj_file_in: Reads a project file, storing info in global symbol table. See proj_file_out and its subroutines for the current project file format. */#define MAXNAME 127 /* Max string that will be read in: see READ_STR below */ /* Macros for error-flagging input */PRIVATE int nil()/* to make lint happy */{ return 0; }#define READ_ERROR (oops_message(OOPS_FATAL,proj_line_num,NO_COL_NUM,\ "error reading project file"),nil())#define READ_OK nil()#define READ_FIRST_STR(LEADER,STR) (fscanf(fd,LEADER),fscanf(fd,"%127s",STR))#define READ_STR(LEADER,STR) ((fscanf(fd,LEADER),\ fscanf(fd,"%127s",STR))==1? READ_OK:READ_ERROR)#define READ_NUM(LEADER,NUM) ((fscanf(fd,LEADER),\ fscanf(fd,"%d",&NUM))==1? READ_OK:READ_ERROR)#define READ_LONG(LEADER,NUM) ((fscanf(fd,LEADER),\ fscanf(fd,"%ld",&NUM))==1? READ_OK:READ_ERROR)#define NEXTLINE {int c;while( (c=fgetc(fd)) != EOF && c != '\n') continue;\ if(c == EOF) READ_ERROR; else ++proj_line_num;}unsigned proj_line_num; /* Line number in proj file for diagnostic output */voidproj_file_in(fd) FILE *fd;{ char buf[MAXNAME+1],*topfilename=NULL; int retval; unsigned numentries,ientry, numexts,iext, numblocks,iblock; proj_line_num = 1; while( (retval=READ_FIRST_STR(PROJFILE_COOKIE,buf)) == 1) { if( strcmp(buf,PROJECT_VERSION) != 0 ) { fprintf(stderr, "\nProject file is not correct version -- must be re-created\n"); exit(1); } /* Save filename in permanent storage */ READ_STR("file",buf); topfilename = strcpy(ckalloc(strlen(buf)+1),buf); NEXTLINE;#ifdef DEBUG_PROJECT printf("read file %s\n",topfilename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -