&q SAVE.SETV#SAVE.SET0BACKUP/LOG [.NEWDRV]*.* SAVE.SET/SAVE/BLOCK=8192 YOUNGDALE :#?V5.3 _V6550C::  _DUA1: V5.3  *[ERIC.NEWDRV]AAAREADME.TXT;1+,:./: 4P-7%0123KPWO56z6<>7`q<>8`q\m˔9 `?G:HJF The files PRF.MAR and PROFILE.C should be compiled and put in GCCLIB.2These are needed for function and block profiling.. GCC.C and GCC.COM are the new compiler driver3 GCC.CLD is the CLD description of the gcc command,H GCC.HLP and GCC.RNH are the help for VMS help that describes all of thePactive options in the compiler driver. If changes are to be made, edit GCC.RNH,Gand use runoff to rebuild gcc.hlp (It stays nicely formatted that way).*[ERIC.NEWDRV]GCC.C;80+,b./: 4i:-7%0123KPWO56\?7 ,ҷ?8 ,-I͔9G:HJ/* *C * A DCL driver for GNU "CC". It accepts a CLD syntax identical to * VAX-11 "C". *C * Since GCC consists of more than 1 pass we have to do the parsingF * here and have a DCL Command (.COM) file do the real work -- so thatH * multiple images can be invoked WITHOUT having to resort to LIB$SPAWN. */#include #include #define GLOBAL 1#define LOCAL 08char *Input_Files[100]; /* Input file specifications */4char *Defines[100]; /* /DEFINE specifications */5char *Includes[100]; /* /INCLUDE specifications */6char *Undefines[100]; /* /UNDEFINE specifications */2char *Scans[100]; /* List of files to scan */.char *Debug; /* /DEBUG specification */-char *Object =0; /* Object file name */.char *List_File =0; /* List file name */6char *Assembly_File =0; /* Assembly file name *//int Optimize; /* Do optimized compile */7int G_Float=0; /* Use G double precision floating */4int Machine_Code=0; /* Output assembly lang */0int Verbose=0; /* Make noise while compiling*/)int Plus=0; /* Use C++ compiler */&int Show=0; /* Show options */0int Profile=0; /* Use compiler profiler */-int Warn=0; /* Generate warning messages */3int Case_Hack=1; /* Hack symbols with upper case*/-int List=0; /* Save preprocessor output */3int Version=0; /* Show compiler version number */7int Generate_Object=0; /* Shoule we generate obj? */.int Ndefines=0; /* Number of defines */1int Nincludes=0; /* Number of incude specs */2int Nundefines=0; /* Number of undefines *//int Nscans=0; /* Number of files to scan */7char cc1_Options[256]; /* Options for the CC1 pass */7char cpp_Options[256]; /* Options for the CPP pass */7char gas_Options[256]; /* Options for the GAS pass */ /*" * Save a string in dynamic memory */char *savestr(String)register char *String;{ register char *cp,*New_String; /* * Allocate it *// New_String = (char *)malloc(strlen(String)+1); /* * Copy it */ cp = New_String;" while((*cp++ = *String++) != 0) ; /* * Return it */ return(New_String);} /* * Do the parsing */checkswitches(int flag){ register char *cp,*cp1; char Temp[256]; /* * Do the /DEFINE qualifier */( if (cli_present("VCG$DEFINE",0,flag)) {8 while(cli_get_value("VCG$DEFINE",Temp,sizeof(Temp))) {) Defines[Ndefines++] = savestr(Temp); #ifdef notdef% Euniceify(&Defines[Ndefines-1]); #endif notdef } } /* * Do the /DEBUG qualifier */' if (cli_present("VCG$DEBUG",0,flag)) { /*" * Get the value (Default = ALL) */4 if (!cli_get_value("VCG$DEBUG",Temp,sizeof(Temp))) strcpy(Temp,"ALL"); /* * Save it */ Debug = savestr(Temp); } /*) * Do the "/INCLUDE_DIRECTORY" qualifier */) if (cli_present("VCG$INCLUDE",0,flag)) {7 while(cli_get_value("VCG$INCLUDE",Temp,sizeof(Temp)))+ Includes[Nincludes++] = savestr(Temp); } /*" * Do the /MACHINE_CODE qualifier */A if(Machine_Code = cli_present("VCG$MACHINE",Machine_Code,flag)){* if(Assembly_File) free(Assembly_File); 6 if (cli_get_value("VCG$MACHINE",Temp,sizeof(Temp)))" Assembly_File = savestr(Temp); else Assembly_File = 0; }; /* * Do the /OBJECT qualifier */D if(Generate_Object=cli_present("VCG$OBJECT",Generate_Object,flag)){ if(Object) free(Object);5 if (cli_get_value("VCG$OBJECT",Temp,sizeof(Temp))) Object = savestr(Temp); else Object = 0; }; /* * Do the /UNDEFINE qualifier */* if (cli_present("VCG$UNDEFINE",0,flag)) {: while(cli_get_value("VCG$UNDEFINE",Temp,sizeof(Temp))) {- Undefines[Nundefines++] = savestr(Temp); #ifdef notdef) Euniceify(&Undefines[Nundefines-1]); #endif notdef } } /* * Do the /SCAN qualifier */& if (cli_present("VCG$SCAN",0,flag)) {6 while(cli_get_value("VCG$SCAN",Temp,sizeof(Temp))) {% Scans[Nscans++] = savestr(Temp); } } /*! * Do the /CC1_OPTIONS qualifier */+ if (cli_present("VCG$CC1_OPTIONS",0,flag))C cli_get_value("VCG$CC1_OPTIONS",cc1_Options,sizeof(cc1_Options)); /* * Do the /VERBOSE qualifier */9 Case_Hack = cli_present("VCG$CASE_HACK",Case_Hack,flag);- Warn = cli_present("VCG$WARNING",Warn,flag);3 Version = cli_present("VCG$VERSION",Version,flag);* Plus = cli_present("VCG$PLUS",Plus,flag);) if (cli_present("VCG$PROFILE",0,flag)) {6 if(!cli_get_value("VCG$PROFILE",Temp,sizeof(Temp)))  Profile = 1; /* all */ else{4 if(!strncmp(Temp,"ALL",strlen(Temp))) Profile = 3;6 if(!strncmp(Temp,"BLOCK",strlen(Temp))) Profile = 2;9 if(!strncmp(Temp,"FUNCTION",strlen(Temp))) Profile = 1; }; };& if (cli_present("VCG$SHOW",0,flag)) {3 if(!cli_get_value("VCG$SHOW",Temp,sizeof(Temp)))  Show = 3; /* all */ else{1 if(!strncmp(Temp,"ALL",strlen(Temp))) Show = 3;3 if(!strncmp(Temp,"RULES",strlen(Temp))) Show = 2;9 if(!strncmp(Temp,"DEFINITIONS",strlen(Temp))) Show = 1;2 if(!strncmp(Temp,"NONE",strlen(Temp))) Show = 0; }; };2 Verbose= cli_present("VCG$VERBOSE",Verbose,flag);3 G_Float = cli_present("VCG$G_FLOAT",G_Float,flag);1 if(List = cli_present("VCG$LISTING",List,flag)){! if(List_File) free(List_File);6 if (cli_get_value("VCG$LISTING",Temp,sizeof(Temp))) List_File = savestr(Temp); else List_File = 0; };3 Optimize = cli_present("VCG$OPTIM",Optimize,flag);})int mystrcat(char* string,char * append){ char* pnt, *pnt1;3 pnt = string + strlen(string); /* point to null */ pnt1 = append; while(*pnt1){4 if(*pnt1 == '"') *pnt++ = '"'; /* double quotes */ *pnt++ = *pnt1++; };, *pnt = '\0'; /* and terminate the string */})char* locate(char* target, char* source){ char* pnt, *pnt1; pnt=source; while(*pnt){4 if(!strncmp(pnt,target,strlen(target))) return pnt; pnt++; }; return 0;} /* * Do the parsing */main(){ register char *cp,*cp1; int i; char Temp[256]; /* 1 * create the default name for the scratch files */ strcpy(Temp,"GCC_");& sprintf(&Temp[4],"%8x.CPP",getpid());2 for(i=4;i<12;i++) if(Temp[i] == ' ') Temp[i]='0'; List_File = savestr(Temp); strcpy(&Temp[12],".S"); Assembly_File = savestr(Temp); /* * Get the Input files */ i = 0; checkswitches(GLOBAL);5 while(cli_get_value("VCG$INPUT",Temp,sizeof(Temp))){% Input_Files[i++] = savestr(Temp); checkswitches(LOCAL);};' /* find the name of the source file */) cp = (char*) strchr(Input_FilesR SAVE.SETb7%[ERIC.NEWDRV]GCC.C;80i@[0],']');* cp1 = (char*) strchr(Input_Files[0],':'); if(!cp) cp=cp1; if(cp1 < cp && !cp1) cp = cp1; if(!cp) cp = Input_Files[0]; cp1 = Temp;/ while(*cp != '.' && *cp != ';' && *cp != '\0') *cp1++ = *cp++;F /* Next check to see if we need to change the name of the list file*/ if(Show){ Generate_Object = 0; Machine_Code =0; if(!List && List_File) { free(List_File);9 List_File = 0; /* force the selection of a new name */ }; List = 1; switch (Show){ case 1: strcat(cpp_Options,"-d "); if(!List_File){ strcpy(cp1,".DEF");! List_File = savestr(Temp); }; break; case 2:# strcat(cpp_Options,"\"-MM\" "); if(!List_File){ strcpy(cp1,".");! List_File = savestr(Temp); }; break; case 3:" strcat(cpp_Options,"\"-M\" "); if(!List_File){ strcpy(cp1,".");! List_File = savestr(Temp); }; break; }; };A /* Next check and see if we need to supply default file names */ if(!List_File){ strcpy(cp1,".CPP"); List_File = savestr(Temp); }; if(!Assembly_File){ strcpy(cp1,".S");" Assembly_File = savestr(Temp); }; if(!Object){ strcpy(cp1,".OBJ"); Object = savestr(Temp); };i /* now process some of the commands here, to generate switches for the various phases of the compiler */1 if( !Generate_Object && !Machine_Code && !List){8 printf("%%GCC-I-NOOUTPUT No output was requested.\n"); exit(0); };' strcat(cpp_Options,"\"-D__GNUC__\" ");./* if (List) strcat(cpp_Options,"\"-C\" "); */) if (G_Float) strcat(cc1_Options,"-mg ");+ if (Optimize) strcat(cc1_Options,"-opt "); if(Debug){* if(Plus) strcat(cc1_Options,"\"-G0\" ");& else strcat(cc1_Options,"\"-G\" "); };f if(Optimize && Debug) printf("%%GCC-I-DEBUG Caution: /debug specified with optimization enabled.\n"); if(Warn) {# strcat(cc1_Options,"\"-Wall\" ");# strcat(cpp_Options,"\"-Wall\" "); }; if(Version){" strcat(cc1_Options,"-version "); strcat(cpp_Options,"-v "); };+ if(Profile & 1) strcat(cc1_Options,"-p ");+ if(Profile & 2) strcat(cc1_Options,"-a ");, if(!Verbose) strcat(cc1_Options,"-quiet ");* if(!Case_Hack) strcat(gas_Options,"-h "); if(Plus) { strcat(gas_Options,"-+ ");> strcat(cpp_Options," -+ \"-D__GNUG__\" \"-D__cplusplus\" "); };3 if(Verbose && Plus) strcat(gas_Options,"\"-H\" ");3 if( cp = locate("-mdont-save-r2-r5",cc1_Options)){ cp1 = cp+17; while(*cp1) *cp++ = *cp1++; *cp = '\0';V strcat(cc1_Options," -fcall-used-r2 -fcall-used-r3 -fcall-used-r4 -fcall-used-r5 "); };0 if(cp = locate("-mpcc-alignment",cc1_Options)){ cp1 = cp+15; while(*cp1) *cp++ = *cp1++; *cp = '\0';. strcat(cpp_Options," \"-DPCC_ALIGNMENT\" "); } else {* strcat(cc1_Options,"-mvaxc-alignment "); }; /* * Generate the command */ cp = Temp; /* Invoke the .COM file */ cp1 = "@GNU_CC:[000000]GCC"; while(*cp1) *cp++ = *cp1++; /* P1 = File to compile */ *cp++ = ' '; cp1 = Input_Files[0]; while(*cp1) *cp++ = *cp1++; /* P2 = Options */ *cp++ = ' '; *cp++ = '"'; if (Plus==1) *cp++ = 'P'; if (List == 1) *cp++ = 'L';' if (Generate_Object == 1) *cp++ = '*'; if (Machine_Code)*cp++ = 'M'; if (Verbose) *cp++ = 'V'; *cp++ = '"'; /* P3 = Name of object file */ *cp++ = ' ';* if(Object != (char*) NULL) {cp1 = Object; while(*cp1) *cp++ = *cp1++; } else { *cp++ = '"'; *cp++ = '"'; } /* P4 = Name of listing file */ *cp++ = ' ';0 if(List_File != (char*) NULL) {cp1 = List_File; while(*cp1) *cp++ = *cp1++; } else { *cp++ = '"'; *cp++ = '"'; }! /* P5 = Name of assembly file */ *cp++ = ' ';9 if( Assembly_File != (char*) NULL) {cp1 = Assembly_File; while(*cp1) *cp++ = *cp1++; } else { *cp++ = '"'; *cp++ = '"'; } /* Defines */ i=0; while(Defines[i]){ strcat(cpp_Options,"\"-D");# mystrcat(cpp_Options,Defines[i]); strcat(cpp_Options,"\" "); i++; }; /* Scans */ i=0; while(Scans[i]){ strcat(cpp_Options,"\"-i");! mystrcat(cpp_Options,Scans[i]); strcat(cpp_Options,"\" "); i++; }; /* Undefines */ i=0; while(Undefines[i]){ strcat(cpp_Options,"\"-U");% mystrcat(cpp_Options,Undefines[i]); strcat(cpp_Options,"\" "); i++; }; /* Include directories */ i=0; while(Includes[i]){ strcat(cpp_Options,"\"-I");$ mystrcat(cpp_Options,Includes[i]); strcat(cpp_Options,"\" "); i++; };/*L * The symbols are assigned in this way, since we do not have to worry aboutJ * DCL parsing them. This reduces the complexity, since we do not have to; * double the single quotes, treble the double quotes, etc. *I * Any single quotes within an include, define, undefine, or scan will be< * doubled up, since we do require these to be passed along. */+ lib_set_symbol("cc1_Options",cc1_Options);+ lib_set_symbol("cpp_Options",cpp_Options);+ lib_set_symbol("gas_Options",gas_Options); /* * Do it */! lib_do_command(Temp, cp - Temp);} /* * Execute the given DCL command */lib_do_command(Text,Size) char *Text; int Size;{% struct {int Size; char *Ptr;} Descr; Descr.Ptr = Text; Descr.Size = Size; lib$do_command(&Descr);}lib_set_symbol(Symbol,Text)char * Symbol; char *Text;{ int i;8 struct {int Size; char *Ptr;} Symbol_Descr, Text_Descr; Symbol_Descr.Ptr = Symbol;$ Symbol_Descr.Size = strlen(Symbol); Text_Descr.Ptr = Text; Text_Descr.Size = strlen(Text); i=1;. lib$set_symbol(&Symbol_Descr,&Text_Descr,&i);} 0/************ DCL PARSING ROUTINES **********/#define CLI$_ABSENT 0x381f0#define CLI$_NEGATED 0x381f8#define CLI$_LOCNEG 0x38230#define CLI$_PRESENT 0x3fd19#define CLI$_DEFAULTED 0x3fd21#define CLI$_LOCPRES 0x3fd31#define CLI$_COMMA 0x3fd39/*/ * See if "NAME" is present, absent or negated. */5int cli_present(char *Name, int oldflag, int gblflag){ int flagstatus;% struct {int Size; char *Ptr;} Descr; Descr.Ptr = Name; Descr.Size = strlen(Name); flagstatus=cli$present(&Descr); switch(flagstatus){ case CLI$_ABSENT : return oldflag; case CLI$_NEGATED:' if(gblflag == LOCAL) return oldflag; case CLI$_LOCNEG: return 0; case CLI$_PRESENT: case CLI$_DEFAULTED:' if(gblflag == LOCAL) return oldflag; case CLI$_LOCPRES: return 1; };}/* * Get value of "NAME" */#int cli_get_value(Name,Buffer,Size) char *Name; char *Buffer;{- struct {int Size; char *Ptr;} Descr1,Descr2; Descr1.Ptr = Name; Descr1.Size = strlen(Name); Descr2.Ptr = Buffer; Descr2.Size = Size-1;7 if (cli$get_value(&Descr1,&Descr2,&Descr2.Size) & 1) { Buffer[Descr2.Size] = 0; return(1); } return(0);} #ifdef notdef/*D * TEMPORARY: Fixup define/undefine strings for Eunice command line * processing */ Euniceify(sp) char **sp;{-#define isupper(c) ((c >= 'A') && (c <= 'Z'))"#define tolower(c) (c - 'A' + 'a') register char *cp,*cp1; char Local[512]; cp = *sp; cp1 = Local; while(*cp) { if (isupper(*cp)) { *cp1++ = '^'; *cp1 = tolower(*cp); } else { *cp1 = *cp; } cp++; cp1++; } *cp1++ = 0;& cp = (char *)malloc(strlen(Local)+1); strcpy(cp,Local); *sp = cp;} #endif notdef80 SAVE.SET:7%[ERIC.NEWDRV]GCC.CLD;14P"*[ERIC.NEWDRV]GCC.CLD;14+,:./: 4Pf-7%0123KPWO 56@ 7 <>8`}C߭˔9 `?G:HJP!**************************************GCC**************************************define type PROFILE_OPTIONS keyword ALL keyword FUNCTION keyword BLOCKdefine type LIST_OPTIONS keyword CPP_OUTPUT,default keyword DEFINES keyword MAKERULES keyword LOCALRULESdefine type DEBUG_OPTIONS keyword ALL keyword NONE keyword TRACEBACK negatable keyword SYMBOLS negatable define type MACHINE_LIST_OPTIONS keyword INTERSPERSED keyword AFTER keyword BEFOREdefine type PRECISION_OPTIONS keyword SINGLE keyword DOUBLEdefine type SHOW_OPTIONS keyword ALL keyword NONE keyword INCLUDE negatable keyword STATISTICS negatable keyword SYMBOLS negatable keyword SOURCE negatable keyword HEADER negatable keyword EXPANSION negatable keyword INTERMEDIATE negatable keyword BRIEF negatable keyword TERMINAL negatable keyword DICTIONARY negatable keyword TRANSLATION negatable keyword DEFINITIONS negatable keyword RULES negatable,defaultdefine type STANDARD_OPTIONS keyword ALL keyword NONE keyword PORTABLE negatabledefine type WARNING_OPTIONS keyword ALL keyword NONE keyword NOINFORMATIONALS keyword NOWARNINGSdefine verb GCC image GNU_CC:[000000]GCC.EXE1 parameter P1 , label=VCG$INPUT , prompt="File"( value (required,list,type=$infile)9 qualifier ANALYSIS_DATA , label=VCG$ANALYSIS_DATA_FILE value (type=$outfile) placement=positional. qualifier CROSS_REFERENCE , label=VCG$CROSS placement=positional& qualifier DEFINE , label=VCG$DEFINE value (list) placement=positional, qualifier CASE_HACK , label=VCG$CASE_HACK negatable default" qualifier PLUS , label=VCG$PLUS( qualifier PROFILE , label=VCG$PROFILE# value (type=PROFILE_OPTIONS) $ qualifier DEBUG , label=VCG$DEBUG% value (list,type=DEBUG_OPTIONS)- qualifier DIAGNOSTICS , label=VCG$PSE_FILE value (type=$outfile) placement=positional( qualifier G_FLOAT , label=VCG$G_FLOAT placement=positional2 qualifier INCLUDE_DIRECTORY , label=VCG$INCLUDE value (required,list) placement=positional( qualifier LIBRARY , label=VCG$LIBRARY nonnegatable placement=local% qualifier LIST , label=VCG$LISTING value (type=$outfile) placement=positional- qualifier MACHINE_CODE , label=VCG$MACHINE' value (type=MACHINE_LIST_OPTIONS) placement=positional& qualifier OBJECT , label=VCG$OBJECT default value (type=$outfile) placement=positional' qualifier OPTIMIZE , label=VCG$OPTIM default value (list) placement=positional, qualifier PRECISION , label=VCG$PRECISION nonnegatable- value (required,type=PRECISION_OPTIONS) placement=positional! qualifier SCAN, label=VCG$SCAN( value (required,list,type=$infile) placement=positional" qualifier SHOW , label=VCG$SHOW nonnegatable$ value (list,type=SHOW_OPTIONS) placement=positional' qualifier STANDARD , label=VCG$CHECK( value (list,type=STANDARD_OPTIONS) placement=positional# qualifier TRACE , label=VCG$DIAG nonnegatable value (list) placement=positional* qualifier UNDEFINE , label=VCG$UNDEFINE value (list) placement=positional( qualifier VERBOSE , label=VCG$VERBOSE( qualifier VERSION , label=VCG$VERSION) qualifier WARNINGS , label=VCG$WARNING' value (list,type=WARNING_OPTIONS) placement=positional0 qualifier CC1_OPTIONS , label=VCG$CC1_OPTIONS value (required)F outputs(VCG$OBJECT,VCG$LISTING,VCG$PSE_FILE,VCG$ANALYSIS_DATA_FILE)*[ERIC.NEWDRV]GCC.COM;99+,:./: 4P-7%0123KPWO56Ρ: 7n <>8߭˔9 `?G:HJ $ Verifying:= 'f$verify(0)'5$ if "''gcc_debugging'".eqs."" then gcc_debugging = 0N$! 'f$verify(GCC_DEBUGGING)' Even though this line is commented, the verify $! Is still set correctly !!!$!!$! GNU "CC" Compiler command fileA$! This has been extensively reworked from the previous version,4$! and a number of things are now handled by GCC.C.$!:$! Invoked from the GCC compile driver via LIB$DO_COMMAND:$! P1 = File to compile$! P2 = Options:$! P - Use C++ compiler,$! V - Be verbose during compilation2$! L - Save preprocessor output as listing*$! M - Generate/Save machine code. $! * - Generate OBJ file$! P3 = Name of object file $! P4 = Name of listing file $! P5 = Name of assembly file $!I$! cpp_Options: Options for preprocessor, including all defines,undef,inc$$! gas_Options: All options for gas.D$! cc1_Options: Options for compiler. This should *not* include the?$! following switches, as they are taken care of in the driver $! program:$! driver program);2$! -mdont-save-r2-r5 (PCC style register saving).$! -mpcc-alignment (PCC style struct align)$!$!$! Constants:$!7$ Command_Line_Options:= 'P2' ! just so we can see them$Compile_Phase = 0'$ Version:='f$trnlnm("GNU_CC_VERSION")'#$ gcc_cpp="$GNU_CC:[000000]GCC-CPP"#$ gcc_cc1="$GNU_CC:[000000]GCC-CC1")$ gcc_cplus="$GNU_CC:[000000]GCC-CC1PLUS"+$ gcc_collect="$GNU_CC:[000000]VMS-COLLECT"<$ gcc_as= "$GNU_CC:[000000]GCC-AS ""-vGNU CC V''Version'"""F$ Now = f$time() ! We save this so we know if a file should be deleted$ Now[11,1] :=+$!$! Parse the options$! -----------------A$ P2_Length = f$length(P2) ! So we only have to calculate it once/$ Plus = "" ! Default = Regular C compiler*$ Quiet = " -quiet" ! Default = Silent2$ Machine_Code = 0 ! Default = No Machine Code/$ List = 0 ! Default = Do full compilation4$ Generate_Object = 0 ! Default = No object file:$ if f$locate("M",p2) .ne. P2_Length then Machine_Code = 12$ if f$locate("P",p2) .ne. P2_Length then Plus = 12$ if f$locate("L",p2) .ne. P2_Length then List = 1=$ if f$locate("*",p2) .ne. P2_Length then Generate_Object = 14$ if f$locate("V",p2) .ne. P2_Length then Quiet = ""$!-$ Temp_File = "" ! For Control_Y abort check#$ On Control_Y then Goto Ctly_Abort$!'$! Do the CC1 compilation phase options$!$!5$! Do the filename (default to ".C" or ".CC" if G++)$!$ Filename:='p1'1$ Extension:='f$parse(p1,,,"TYPE","SYNTAX_ONLY")'@$ if (Plus.eq.0).and.(Extension .eqs. ".") then Filename:='p1'.CA$ if (Plus.eq.1).and.(Extension .eqs. ".") then Filename:='p1'.CC$ Object_File = P3$ List_File = P4$ Assembly_File = p5@$ if Extension.eqs.".CPP" then List = 1 !Do not delete the input3$ if Extension.eqs.".CPP" then List_File = Filename.$ if Extension.eqs.".CPP" then goto do_compileF$ if Extension.eqs.".S" then Machine_Code = 1 !Do not delete the input5$ if Extension.eqs.".S" then Assembly_File = Filename-$ if Extension.e ï SAVE.SET:7%[ERIC.NEWDRV]GCC.COM;99Pqs.".S" then goto do_assembly$!$!$! Do the "C" pre-processor$!$on error then goto CPP_Error$Compile_Phase = 1#$ if Quiet .eqs. "" then set verify.$ gcc_cpp 'cpp_Options' 'Filename' 'List_File',$ Status=$status ! 'f$verify(GCC_DEBUGGING)'2$ if Status .nes. "%X00000001" then goto CPP_Error$9$ if Machine_Code + Generate_Object .eq. 0 then goto Exit$!$! Do the "C" compilation$! $do_compile:$Compile_Phase = 2$if plus.eq.1 then goto gxx$on error then goto CC1_Error#$ if Quiet .eqs. "" then set verify,$ gcc_cc1 'List_File' -dumpbase 'Filename' -* -mgnu 'CC1_Options' -o 'Assembly_File',$ Status=$status ! 'f$verify(GCC_DEBUGGING)' $goto assemb$gxx:$on error then goto CC1_Error#$ if Quiet .eqs. "" then set verify.$ gcc_cplus 'List_File' -dumpbase 'Filename' -7 -mgnu 'CC1_Options' -fforce-addr -o 'Assembly_File',$ Status=$status ! 'f$verify(GCC_DEBUGGING)'$assemb:7$ if List.eq.0 then delete/nolog/noconfirm 'List_File';2$ if Status .nes. "%X00000001" then goto CC1_Error$!;$! Append constructor/destructor information to the .s file$!$Compile_Phase = 3/$if plus.eq.1 then gcc_collect 'Assembly_File'$!$!$! Do the assembly$! $do_assembly:($ if Generate_Object.eq.0 then goto Exit$Compile_Phase = 4$on error then goto Gas_Error#$ if Quiet .eqs. "" then set verify7$ gcc_as 'Assembly_File' 'gas_Options' -o 'Object_File',$ Status=$status ! 'f$verify(GCC_DEBUGGING)'C$ if Machine_Code.eq.0 then delete/nolog/noconfirm 'Assembly_File';2$ if Status .nes. "%X00000001" then goto Gas_Error $ goto Exit$! $! ERRORS: $! ------)$ Ctly_Abort: ! 'f$verify(GCC_DEBUGGING)',$if Compile_Phase .eq. 0 then goto ctly_exit?$if ((Compile_Phase.gt.1).and.(List.eq.1)) then goto ctly_ckasm&$ if f$search(List_File).nes."" then -2 delete/nolog/noconf/since="''Now'" 'List_File';+$ if Compile_Phase.eq.1 then goto ctly_exit$! $ctly_ckasm:G$if ((Compile_Phase.gt.3).and.(Machine_Code.eq.1)) then goto ctly_ckobj/$ if Assembly_File .eqs. "" then goto ctly_exit*$ if f$search(Assembly_File).nes."" then -5 delete/nolog/noconf/since="''Now'" 'Assembly_File';+$ if Compile_Phase.lt.4 then goto ctly_exit$! $ctly_ckobj:($ if f$search(Object_File).nes."" then -3 delete/nolog/noconf/since="''Now'" 'Object_File'; $ctly_exit: $ Status = 44'$ exit Status + 0 * f$verify(verifying)$!P$! This is a little tricky - DCL substitutes all symbols (even ones in comments)N$! before it echos commands, so the f$verify(0) is executed before the line is $! echoed$!$7$ Gas_Error: Status=$status ! 'f$verify(GCC_DEBUGGING)''$ delete/nolog/noconfirm 'Object_File';8$write sys$output "%GCC-I-NOOBJECT Object file deleted."$! if verifying then set verify@$ exit Status + 0 * f$verify(verifying)! Error in Assembly phase$!7$ CC1_Error: Status=$status ! 'f$verify(GCC_DEBUGGING)'9$ if List.eq.0 then delete/nolog/noconfirm 'List_File';D$ if Machine_Code.eq.0 then delete/nolog/noconfirm 'Assembly_File';@$write sys$output "%GCC-I-NOOBJECT No object file was produced."$! if verifying then set verifyH$ exit Status + 0 * f$verify(verifying) ! Error in "C" Compilation phase$!7$ CPP_Error: Status=$status ! 'f$verify(GCC_DEBUGGING)';$ if (List.eq.0) .and. (f$search(List_File).nes."") then - &$ delete/nolog/noconfirm 'List_File';@$write sys$output "%GCC-I-NOOBJECT No object file was produced."$! if verifying then set verifyJ$ exit Status + 0 * f$verify(verifying) ! Error in "C" Pre-Processor phase$!$! Done$!$ Exit:$ if verifying then set verify*[ERIC.NEWDRV]GCC.HLP;22+,]:./: 4Jt-7%0123KPWO56[>7V[>8Vy˔9 `?G:HJ ! E! Thinking about editing this file???? DON'T!!!! Edit GCC.RNH B! to make the changes you need and then use RUNOFF on your ! modified help file. ! 1 GCC  . The GCC command invokes the GNU C compiler.   GCC file-spec  2 Parameters  file-spec  H A C source file. If no input file extension is specified, GNU C H assumes .C as the default extension unless the /PLUS qualifier is @ given, in which case .CC is assumed as the default extension.  H If an extension of .CPP is given, then the source file is assumed to H be the output of the preprocessor, and thus the preprocessor is not executed.  H If an extension of .S is given, then the source file is assumed to be H the assembly code output of the compiler, and only the assembler is % called to generate an object file.  2 Qualifiers  H GNU C command qualifiers modify the way the compiler handles the  compilation.  ? The following is the list of available qualifiers for GNU C:   /CASE_HACK , /CC1_OPTIONS=(option [,option...]])  /DEBUG 0 /DEFINE=(identifier[=definition][,...])  /G_FLOAT . /INCLUDE_DIRECTORY=(path [,path...]])  /LIST[=filename]  /MACHINE_CODE  /OBJECT[=filename]  /OPTIMIZE  /PLUS  /PROFILE[=identifier]  /SCAN=(file[,file...])  /SHOW[=option] 0 /UNDEFINE=(identifier[,identifier,...])  /VERBOSE  /VERSION  /WARNING  2 Linking  H When linking programs compiled with GNU C, you should include the GNU 4 C library before the VAX C library. For example,  G LINK object-file,GNU_CC:[000000]GCCLIB/LIB,SYS$LIBRARY:VAXCRTL/LIB  H You can also link your program with the shared VAX C library. This H can reduce the size of the .EXE file, as well as make it smaller when  it's running. For example,  @ $ LINK object-file, GNU_CC:[000000]GCCLIB/LIB,SYS$INPUT/OPT  SYS$SHARE:VAXCRTL/SHARE  H (If you use the second example and type it in by hand, be sure to H type ^Z after the last carriage return). A simpler alternative would  be to place the single line:   SYS$SHARE:VAXCRTL/SHARE  A into a file called VAXCRTL.OPT, and then use the link command:  B $ LINK object-file, GNU_CC:[000000]GCCLIB/LIB,VAXCRTL.OPT/OPT  H If a program has been compiled with /G_FLOAT, then the linking H instructions are slightly different. If you are linking with the E non-shared library, then the command that you should use would be:  J LINK object-file,GNU_CC:[000000]GCCLIB/LIB,SYS$LIBRARY:VAXCRTLG/LIB - : ,SYS$LIBRARY:VAXCRTL/LIB  H Note that both VAXCRTL and VAXCRTLG must be linked to. If you are F using the shared VAX C library, then you should use a command like:  E $ LINK object-file, GNU_CC:[000000]GCCLIB/LIB,SYS$INPUT:/OPTIONS  @#> SAVE.SET]:7%[ERIC.NEWDRV]GCC.HLP;22J9 SYS$SHARE:VAXCRTLG/SHARE  H In the case of the sharable library, only one library needs to be linked to.  2 /CASE_HACK  % /[NO]CASE_HACK D=/CASE_HACK  H Since the VMS Linker and Librarian are not case sensitive with H respect to symbol names, a "case-hack" is appended to a symbol name 2 when the symbol contains upper case characters.  H There are cases where this is undesirable, (mainly when using certain H applications where modules have been precompiled, perhaps in another H language) and thus we want to compile without case hacking. For = these cases the /NOCASE_HACK switch disables case hacking.  2 /CC1_OPTIONS  H This specifies additional switches to the compiler itself which 1 cannot be set by means of the compiler driver.  2 /DEBUG  H /DEBUG includes additional information in the object file output so C that the program can be debugged with the VAX Symbolic Debugger.  H To use the debugger it is also necessary to link the debugger to your H program, which is done by specifying the /DEBUG qualifier to the link H command. With the debugger it is possible to set breakpoints, H examine variables, and set variables to new values. See the VAX H Symbolic Debugger manual for more information, or type "HELP" from  the debugger prompt.  2 /DEFINE  * /DEFINE=(identifier[=definition][,...])  H /DEFINE defines a string or macro ('definition') to be substituted H for every occurrence of a given string ('identifier') in a program. : It is equivalent to the #define preprocessor directive.  H All definitions and identifiers are converted to uppercase unless  they are in quotation marks.  , The simple form of the /DEFINE qualifier:   /DEFINE=vms  D results in a definition equivalent to the preprocessor directive:   #define VMS 1  H You must enclose macro definitions in quotation marks, as in this example:   /DEFINE="C(x)=((x) & 0xff)"  > This definition is the same as the preprocessor definition:   #define C(x) ((x) & 0xff)  H If more than one /DEFINE is present on the GCC command line, only the  last /DEFINE is used.  H If both /DEFINE and /UNDEFINE are present on a command line, /DEFINE ! is evaluated before /UNDEFINE.  2 /G_FLOAT  H Instructs the compiler to use "G" floating point arithmetic instead H of "D". The difference is that double precision has a range of H approximately +/-0.56e-308 to +/-0.9 e+308, with approximately 15  decimal digits precision.  H "D" floating point has the same range as single precision floating 9 point, with approximately 17 decimal digits precision.  H If you use the /G_FLOAT qualifier, the linking instructions are 1 different. See "Linking" for further details.  2 /LIST   /LIST[=list_file_name]  H This does not generate a listing file in the usual sense, however it H does direct the compiler to save the preprocessor output. If a file H is not specified, then this output is written into a file with the 9 same name as the source file and an extension of .CPP.  2 /INCLUDE_DIRECTORY  ( /INCLUDE_DIRECTORY=(path [,path...])  H The /INCLUDE_DIRECTORY qualifier provides additional directories to H search for user-defined include files. 'path' can be either a - logical name or a directory specification.  H There are two forms for specifying include files - #include H "file-spec" and #include . For the #include "file-spec"  form, the search order is:  1 1. The directory containing the source file.  ; 2. The directories in the /INCLUDE qualifier (if any).  D 3. The directory (or directories) specified in the logical name  GNU_CC_INCLUDE.  D 4. The directory (or directories) specified in the logical name  SYS$LIBRARY.  ; For the #include form, the search order is:  E 1. The directories specified in the /INCLUDE qualifier (if any).  D 2. The directory (or directories) specified in the logical name  GNU_CC_INCLUDE.  D 3. The directory (or directories) specified in the logical name  SYS$LIBRARY.  2 /MACHINE_CODE  H Tells GNU C to output the machine code generated by the compiler. H The machine code is output to a file with the same name as the input H file, with the extension .S. An object file is still generated, # unless /NOOBJ is also specified.  2 /OBJECT   /OBJECT[=filename]  /NOOBJECT  H Controls whether or not an object file is generated by the compiler.  2 /OPTIMIZE   /[NO]OPTIMIZE  H Controls whether optimization is performed by the compiler. By D default, optimization is on. /NOOPTIMIZE turns optimization off.  2 /PLUS  H Instructs the compiler driver to use the GNU-C++ compiler instead of H the GNU-C compiler. Note that the default extension of source files + is .CC when this qualifier is in effect. s 2 /PROFILE   /PROFILE[=identifier]  H Instructs the compiler to generate function profiling code. You must H link your program to the profiler when you use this options. The H profile statistics are automatically printed out on the terminal H during image exit. (i.e. no modifications to your source file are * required in order to use the profiler).  H There are three identifiers that can be used with the /PROFILE H switch. These are ALL, FUNCTION, and BLOCK. If /PROFILE is given 3 without an identifier, then FUNCTION is assumed. i 3 Block_Profiler  H The block profiler counts how many times control of the program H passes certain points in your program. This is useful in determining H which portions of a program would benefit from recoding for  optimization.  H The report for the block profiler contains the function name, file H name, PC, and the source file line number as well as the count of how C many times control has passed through the specified source line.  3 Function_Profiler / H The function profiler counts how many times each function is entered, E and keeps track of how much CPU time is used within each function. / H You should be careful about interpreting the results of profiles H where there are inline functions. When a function is included as H inline, then there is no call to the internal data collection routine H used by the profiler, and thus there will be no record of this H function being called. The compiler does generate a callable version H of each inline function, and if this called version is used, then the 5 profiler's data collection routine will be called. y 2 /SCAN n  /SCAN=(file[,file...]) l H This qualifier supplies a list of files that will be read as input, H and the output will be discarded before processing the regular input H file. Because the output generated from the files is discarded, the H only effect of this qualifier is to make the macros defined in the - files available for use in the main input. i 2 /SHOW S  /SHOW[=option]  H This causes the preprocessor to generate information other than the H preprocessed input file. When this qualifier is used, no assembly ( code and no object file is generated.  H The output of the preproc SAVE.SET]:7%[ERIC.NEWDRV]GCC.HLP;22J essor is placed in the file specified by the H /LIST qualifier, if present. If the /LIST qualifier is not present, H then the output is placed in a file with the same name as the input H file with an extension that depends upon which option that is selected.  3 DEFINITIONS  H This option causes the preprocessor to dump a list of all of the H definitions to the output file. This is useful for debugging H purposes, since it lets you determine whether or not everything has  been defined properly. e H If the default file name is used for the output, the extension will be .DEF. A 3 RULES N H This option causes the preprocessor to output a rule suitable for H MAKE, describing the dependencies of the main source file. The H preprocessor outputs one MAKE rule containing the object file name H for that source file, a colon, and the names of all the concluded H files. If there are many included files then the rule is split into ' several lines using the '\'-newline. n H When using this option, only files included with the "#include "file"  directive are mentioned.  H If the default file name is used for the output, a null extension  will be used.  3 ALL o H This option is similar to RULES, except that it also mentions files 3 included with the "#include " directive. t H If the default file name is used for the output, a null extension  will be used.  2 /UNDEFINE e H /UNDEFINE cancels a macro definition. Thus, it is the same as the ! #undef preprocessor directive.  H If more than one /UNDEFINE is present on the GCC command line, only  the last /UNDEFINE is used.  H If both /DEFINE and /UNDEFINE are present on a command line, /DEFINE ! is evaluated before /UNDEFINE. t 2 /VERBOSE  H Controls whether the user sees the invocation command strings for the H preprocessor, compiler, and assembler. The compiler also outputs 7 some statistics on time spent in its various phases.  2 /VERSION  H Causes the preprocessor and the compiler to identify themselves by H their version numbers, and in the case of the compiler, the version ( number of the compiler that built it.  2 /WARNING  H When this qualifier is present, warnings about usage that should be H avoided are given by the compiler. For more information, see "Using H and Porting GNU CC", in the section on command line options, under "-Wall". = H Warnings are also generated by the preprocessor when this qualifier is given. efine C(x) ((x) & 0xff)  H If more than one /DEFINE is present on the GCC command line, only the  last /DEFINE is used.  H If both /DEFINE and /UNDEFINE are present on a command line, /DEFINE ! is evaluated before /UNDEFINE.  2 /G_FLOAT  H Instructs the compiler to use "G" floating point arithmetic instead H of "D". The difference is that double precis*[ERIC.NEWDRV]GCC.RNH;9+,;'./: 4O-7%0123KPWO56[>7f[>8_˔9 `?G:HJ.!".! RUNOFF source file for GCC.HLP .!A.! This is a RUNOFF input file which will produce a VMS help file.! for the VMS HELP library..!*.! Date of last revision: December 5, 1990.!.!.! Eric Youngdale.!.literal!=! Thinking about editing this file???? DON'T!!!! Edit GCC.RNH:! to make the changes you need and then use RUNOFF on your! modified help file.! .end literal .no paging .no flags all.right margin 70.left margin 1 .indent -11 GCC.skip, The GCC command invokes the GNU C compiler..skip.literal GCC file-spec .end literal.skip .indent -1 2 Parameters.skip file-spec.skipF A C source file. If no input file extension is specified, GNU C M assumes .C as the default extension unless the /PLUS qualifier is given,; in which case .CC is assumed as the default extension..skipL If an extension of .CPP is given, then the source file is assumed to beO the output of the preprocessor, and thus the preprocessor is not executed..skipJ If an extension of .S is given, then the source file is assumed to beO the assembly code output of the compiler, and only the assembler is called to generate an object file..skip .indent -1 2 Qualifiers.skipA GNU C command qualifiers modify the way the compiler handles the compilation..skip= The following is the list of available qualifiers for GNU C:.literal /CASE_HACK) /CC1_OPTIONS=(option [,option...]]) /DEBUG- /DEFINE=(identifier[=definition][,...]) /G_FLOAT+ /INCLUDE_DIRECTORY=(path [,path...]]) /LIST[=filename] /MACHINE_CODE /OBJECT[=filename] /OPTIMIZE /PLUS /PROFILE[=identifier] /SCAN=(file[,file...]) /SHOW[=option]- /UNDEFINE=(identifier[,identifier,...]) /VERBOSE /VERSION /WARNING .end literal.skip .indent -1 2 Linking.skipF When linking programs compiled with GNU C, you should include the GNU2 C library before the VAX C library. For example,.skip.literalD LINK object-file,GNU_CC:[000000]GCCLIB/LIB,SYS$LIBRARY:VAXCRTL/LIB .end literal.skipD You can also link your program with the shared VAX C library. ThisA can reduce the size of the .EXE file, as well as make it smaller! when it's running. For example,.skip.literal= $ LINK object-file, GNU_CC:[000000]GCCLIB/LIB,SYS$INPUT/OPT SYS$SHARE:VAXCRTL/SHARE .end literal.skipG (If you use the second example and type it in by hand, be sure to typeG ^Z after the last carriage return). A simpler alternative would be to place the single line:.skip.literal SYS$SHARE:VAXCRTL/SHARE .end literal.skip? into a file called VAXCRTL.OPT, and then use the link command:.skip.literal? $ LINK object-file, GNU_CC:[000000]GCCLIB/LIB,VAXCRTL.OPT/OPT .end literal.skip? If a program has been compiled with /G_FLOAT, then the linkingB instructions are slightly different. If you are linking with theC non-shared library, then the command that you should use would be:.skip.literalG LINK object-file,GNU_CC:[000000]GCCLIB/LIB,SYS$LIBRARY:VAXCRTLG/LIB - ,SYS$LIBRARY:VAXCRTL/LIB .end literal.skipI Note that both VAXCRTL and VAXCRTLG must be linked to. If you are using> the shared VAX C library, then you should use a command like:.skip.literalB $ LINK object-file, GNU_CC:[000000]GCCLIB/LIB,SYS$INPUT:/OPTIONS SYS$SHARE:VAXCRTLG/SHARE .end literal.skipI In the case of the sharable library, only one library needs to be linked to..skip .indent -1 2 /CASE_HACK .skip.literal" /[NO]CASE_HACK D=/CASE_HACK .end literal.skipG Since the VMS Linker and Librarian are not case sensitive with respectE to symbol names, a "case-hack" is appended to a symbol name when the) symbol contains upper case characters. .skipF There are cases where this is undesirable, (mainly when using certainE applications where modules have been precompiled, perhaps in anotherG lanFL SAVE.SET;'7%[ERIC.NEWDRV]GCC.RNH;9O guage) and thus we want to compile without case hacking. For these5 cases the /NOCASE_HACK switch disables case hacking..skip .indent -12 /CC1_OPTIONS.skipG This specifies additional switches to the compiler itself which cannot( be set by means of the compiler driver..skip .indent -12 /DEBUG.skipD /DEBUG includes additional information in the object file output soA that the program can be debugged with the VAX Symbolic Debugger..skipF To use the debugger it is also necessary to link the debugger to yourF program, which is done by specifying the /DEBUG qualifier to the linkF command. With the debugger it is possible to set breakpoints, examineB variables, and set variables to new values. See the VAX SymbolicG Debugger manual for more information, or type "HELP" from the debugger prompt..skip .indent -1 2 /DEFINE.skip.literal'/DEFINE=(identifier[=definition][,...]) .end literal.skipD /DEFINE defines a string or macro ('definition') to be substituted D for every occurrence of a given string ('identifier') in a program.8 It is equivalent to the #define preprocessor directive..skipG All definitions and identifiers are converted to uppercase unless they are in quotation marks..skip* The simple form of the /DEFINE qualifier:.skip.literal /DEFINE=vms .end literal.skipB results in a definition equivalent to the preprocessor directive:.skip.literal #define VMS 1 .end literal.skipB You must enclose macro definitions in quotation marks, as in this example:.skip.literal /DEFINE="C(x)=((x) & 0xff)" .end literal.skip< This definition is the same as the preprocessor definition:.skip.literal #define C(x) ((x) & 0xff) .end literal.skipB If more than one /DEFINE is present on the GCC command line, only the last /DEFINE is used..skipE If both /DEFINE and /UNDEFINE are present on a command line, /DEFINE is evaluated before /UNDEFINE..skip .indent -1 2 /G_FLOAT.skipG Instructs the compiler to use "G" floating point arithmetic instead of< "D". The difference is that double precision has a range ofB approximately +/-0.56e-308 to +/-0.9 e+308, with approximately 15 decimal digits precision..skipC "D" floating point has the same range as single precision floating7 point, with approximately 17 decimal digits precision..skip@ If you use the /G_FLOAT qualifier, the linking instructions are. different. See "Linking" for further details..skip .indent -12 /LIST.skip /LIST[=list_file_name].skipE This does not generate a listing file in the usual sense, however itH does direct the compiler to save the preprocessor output. If a file is< not specified, then this output is written into a file with; the same name as the source file and an extension of .CPP..skip .indent -12 /INCLUDE_DIRECTORY.skip.literal% /INCLUDE_DIRECTORY=(path [,path...]) .end literal.skipD The /INCLUDE_DIRECTORY qualifier provides additional directories to@ search for user-defined include files. 'path' can be either a + logical name or a directory specification..skipH There are two forms for specifying include files - #include "file-spec"I and #include . For the #include "file-spec" form, the search order is:.skip.literal. 1. The directory containing the source file.8 2. The directories in the /INCLUDE qualifier (if any).A 3. The directory (or directories) specified in the logical name GNU_CC_INCLUDE.A 4. The directory (or directories) specified in the logical name SYS$LIBRARY.8 For the #include form, the search order is:B 1. The directories specified in the /INCLUDE qualifier (if any).A 2. The directory (or directories) specified in the logical name GNU_CC_INCLUDE.A 3. The directory (or directories) specified in the logical name SYS$LIBRARY. .end literal .indent -12 /MACHINE_CODE.skipF Tells GNU C to output the machine code generated by the compiler. TheG machine code is output to a file with the same name as the input file,I with the extension .S. An object file is still generated, unless /NOOBJ is also specified..skip .indent -1 2 /OBJECT.skip.literal /OBJECT[=filename] /NOOBJECT .end literal.skipE Controls whether or not an object file is generated by the compiler..skip .indent -1 2 /OPTIMIZE.skip /[NO]OPTIMIZE.skipI Controls whether optimization is performed by the compiler. By default,9 optimization is on. /NOOPTIMIZE turns optimization off..skip .indent -12 /PLUS.skipK Instructs the compiler driver to use the GNU-C++ compiler instead of theM GNU-C compiler. Note that the default extension of source files is .CC when this qualifier is in effect..skip .indent -1 2 /PROFILE.skip /PROFILE[=identifier].skipH Instructs the compiler to generate function profiling code. You must= link your program to the profiler when you use this options.L The profile statistics are automatically printed out on the terminal duringG image exit. (i.e. no modifications to your source file are required in order to use the profiler)..skipI There are three identifiers that can be used with the /PROFILE switch.E These are ALL, FUNCTION, and BLOCK. If /PROFILE is given without an' identifier, then FUNCTION is assumed. .skip .indent -13 Block_Profiler.skipI The block profiler counts how many times control of the program passesE certain points in your program. This is useful in determining whichD portions of a program would benefit from recoding for optimization..skipK The report for the block profiler contains the function name, file name,K PC, and the source file line number as well as the count of how many times6 control has passed through the specified source line..skip .indent -13 Function_Profiler.skipL The function profiler counts how many times each function is entered, and? keeps track of how much CPU time is used within each function..skipI You should be careful about interpreting the results of profiles whereJ there are inline functions. When a function is included as inline, then E there is no call to the internal data collection routine used by theJ profiler, and thus there will be no record of this function being called.K The compiler does generate a callable version of each inline function, andL if this called version is used, then the profiler's data collection routine will be called..skip .indent -12 /SCAN.skip /SCAN=(file[,file...]).skipI This qualifier supplies a list of files that will be read as input, andH the output will be discarded before processing the regular input file.K Because the output generated from the files is discarded, the only effectH of this qualifier is to make the macros defined in the files available for use in the main input..skip .indent -12 /SHOW.skip /SHOW[=option].skipE This causes the preprocessor to generate information other than theI preprocessed input file. When this qualifier is used, no assembly code" and no object file is generated..skipM The output of the preprocessor is placed in the file specified by the /LISTI qualifier, if present. If the /LIST qualifier is not present, then theI output is placed in a file with the same name as the input file with an< extension that depends upon which option that is selected..skip .indent -1 3 DEFINITIONS.skip N This option causes the preprocessor to SAVE.SET;'7%[ERIC.NEWDRV]GCC.RNH;9Oq  dump a list of all of the definitionsN to the output file. This is useful for debugging purposes, since it lets you? determine whether or not everything has been defined properly..skipM If the default file name is used for the output, the extension will be .DEF..skip .indent -13 RULES.skipI This option causes the preprocessor to output a rule suitable for MAKE,O describing the dependencies of the main source file. The preprocessor outputsM one MAKE rule containing the object file name for that source file, a colon,M and the names of all the concluded files. If there are many included files A then the rule is split into several lines using the '\'-newline..skipH When using this option, only files included with the "#include "file" directive are mentioned..skipJ If the default file name is used for the output, a null extension will be used..skip .indent -13 ALL.skipN This option is similar to RULES, except that it also mentions files included( with the "#include " directive..skipJ If the default file name is used for the output, a null extension will be used..skip .indent -1 2 /UNDEFINE.skipC /UNDEFINE cancels a macro definition. Thus, it is the same as the #undef preprocessor directive..skipD If more than one /UNDEFINE is present on the GCC command line, only the last /UNDEFINE is used..skipE If both /DEFINE and /UNDEFINE are present on a command line, /DEFINE is evaluated before /UNDEFINE..skip .indent -1 2 /VERBOSE.skipF Controls whether the user sees the invocation command strings for theB preprocessor, compiler, and assembler. The compiler also outputs5 some statistics on time spent in its various phases..skip .indent -1 2 /VERSION.skipI Causes the preprocessor and the compiler to identify themselves by theirL version numbers, and in the case of the compiler, the version number of the compiler that built it..skip .indent -1 2 /WARNING.skipL When this qualifier is present, warnings about usage that should be avoidedM are given by the compiler. For more information, see "Using and Porting GNU< CC", in the section on command line options, under "-Wall"..skipN Warnings are also generated by the preprocessor when this qualifier is given.*[ERIC.NEWDRV]OBJRECDEF.H;1+,n/ ./: 4L2-7%0123KPWO56@ΧB7f?89y̔9G:HJ/* * * $OBJRECDEF7 * Generated automatically by "vms_struct Version 1.00"3 * Created from VMS definition file "objrecdef.mar" * Mon Oct 14 14:01:29 1985 * */struct OBJREC { unsigned char obj$b_rectyp; unsigned char obj$b_subtyp; unsigned char obj$b_mhd_strlv;" unsigned char obj$b_mhd_recsz[2];! unsigned char obj$t_mhd_name[1]; }; #define OBJ$C_HDR 0#define OBJ$C_HDR_MHD 0#define OBJ$C_HDR_LNM 1#define OBJ$C_HDR_SRC 2#define OBJ$C_HDR_TTL 3#define OBJ$C_HDR_CPR 4#define OBJ$C_HDR_MTC 5#define OBJ$C_HDR_GTX 6#define OBJ$C_GSD 1#define OBJ$C_GSD_PSC 0#define OBJ$C_GSD_SYM 1#define OBJ$C_GSD_EPM 2#define OBJ$C_GSD_PRO 3#define OBJ$C_GSD_SYMW 4#define OBJ$C_GSD_EPMW 5#define OBJ$C_GSD_PROW 6#define OBJ$C_GSD_IDC 7#define OBJ$C_GSD_ENV 8#define OBJ$C_GSD_LSY 9#define OBJ$C_GSD_LEPM 10#define OBJ$C_GSD_LPRO 11#define OBJ$C_GSD_SPSC 12#define OBJ$C_TIR 2#define OBJ$C_EOM 3#define OBJ$C_DBG 4#define OBJ$C_TBT 5#define OBJ$C_LNK 6#define OBJ$C_EOMW 7#define OBJ$C_MAXRECTYP 7#define OBJ$K_SUBTYP 1#define OBJ$C_SUBTYP 1#define OBJ$C_MAXRECSIZ 2048#define OBJ$C_STRLVL 0#define OBJ$C_SYMSIZ 31#define OBJ$C_STOREPLIM -1#define OBJ$C_PSCALILIM 9 #define MHD$C_MHD 0#define MHD$C_LNM 1#define MHD$C_SRC 2#define MHD$C_TTL 3#define MHD$C_CPR 4#define MHD$C_MTC 5#define MHD$C_GTX 6#define MHD$C_MAXHDRTYP 6 #define GSD$K_ENTRIES 1#define GSD$C_ENTRIES 1#define GSD$C_PSC 0#define GSD$C_SYM 1#define GSD$C_EPM 2#define GSD$C_PRO 3#define GSD$C_SYMW 4#define GSD$C_EPMW 5#define GSD$C_PROW 6#define GSD$C_IDC 7#define GSD$C_ENV 8#define GSD$C_LSY 9#define GSD$C_LEPM 10#define GSD$C_LPRO 11#define GSD$C_SPSC 12#define GSD$C_SYMV 13#define GSD$C_EPMV 14#define GSD$C_PROV 15#define GSD$C_MAXRECTYP 15 #define GSY$M_WEAK 1#define GSY$M_DEF 2#define GSY$M_UNI 4#define GSY$M_REL 8 #define GPS$M_PIC 1#define GPS$M_LIB 2#define GPS$M_OVR 4#define GPS$M_REL 8#define GPS$M_GBL 16#define GPS$M_SHR 32#define GPS$M_EXE 64#define GPS$M_RD 128#define GPS$M_WRT 256#define GPS$M_VEC 512#define GPS$K_NAME 9#define GPS$C_NAME 9 #define TIR$C_STA_GBL 0#define TIR$C_STA_SB 1#define TIR$C_STA_SW 2#define TIR$C_STA_LW 3#define TIR$C_STA_PB 4#define TIR$C_STA_PW 5#define TIR$C_STA_PL 6#define TIR$C_STA_UB 7#define TIR$C_STA_UW 8#define TIR$C_STA_BFI 9#define TIR$C_STA_WFI 10#define TIR$C_STA_LFI 11#define TIR$C_STA_EPM 12#define TIR$C_STA_CKARG 13#define TIR$C_STA_WPB 14#define TIR$C_STA_WPW 15#define TIR$C_STA_WPL 16#define TIR$C_STA_LSY 17#define TIR$C_STA_LIT 18#define TIR$C_STA_LEPM 19#define TIR$C_MAXSTACOD 19#define TIR$C_MINSTOCOD 20#define TIR$C_STO_SB 20#define TIR$C_STO_SW 21#define TIR$C_STO_L 22#define TIR$C_STO_BD 23#define TIR$C_STO_WD 24#define TIR$C_STO_LD 25#define TIR$C_STO_LI 26#define TIR$C_STO_PIDR 27#define TIR$C_STO_PICR 28#define TIR$C_STO_RSB 29#define TIR$C_STO_RSW 30#define TIR$C_STO_RL 31#define TIR$C_STO_VPS 32#define TIR$C_STO_USB 33#define TIR$C_STO_USW 34#define TIR$C_STO_RUB 35#define TIR$C_STO_RUW 36#define TIR$C_STO_B 37#define TIR$C_STO_W 38#define TIR$C_STO_RB 39#define TIR$C_STO_RW 40#define TIR$C_STO_RIVB 41#define TIR$C_STO_PIRR 42#define TIR$C_MAXSTOCOD 42#define TIR$C_MINOPRCOD 50#define TIR$C_OPR_NOP 50#define TIR$C_OPR_ADD 51#define TIR$C_OPR_SUB 52#define TIR$C_OPR_MUL 53#define TIR$C_OPR_DIV 54#define TIR$C_OPR_AND 55#define TIR$C_OPR_IOR 56#define TIR$C_OPR_EOR 57#define TIR$C_OPR_NEG 58#define TIR$C_OPR_COM 59#define TIR$C_OPR_INSV 60#define TIR$C_OPR_ASH 61#define TIR$C_OPR_USH 62#define TIR$C_OPR_ROT 63#define TIR$C_OPR_SEL 64#define TIR$C_OPR_REDEF 65#define TIR$C_OPR_DFLIT 66#define TIR$C_MAXOPRCOD 66#define TIR$C_MINCTLCOD 80#define TIR$C_CTL_SETRB 80#define TIR$C_CTL_AUGRB 81#define TIR$C_CTL_DFLOC 82#define TIR$C_CTL_STLOC 83#define TIR$C_CTL_STKDL 84#define TIR$C_MAXCTLCOD 84 /*> * Debugger symbol definitions: These are done by hand, as no% * machine-readable version seems * to be available. */)#define DST$C_C 7 /* Language == "C" */#define DST$C_VERSION 153,#define DST$C_SOURCE 155 /* Source file */#define DST$C_PROLOG 1622#define DST$C_BLKBEG 176 /* Beginning of block */,#define DST$C_BLKEND 177 /* End of block */#define DST$C_ENTRY 181#define DST$C_PS i>N SAVE.SETn/ 7%[ERIC.NEWDRV]OBJRECDEF.H;1L9  ECT 184.#define DST$C_LINE_NUM 185 /* Line Number */#define DST$C_LBLORLIT 186#define DST$C_LABEL 1873#define DST$C_MODBEG 188 /* Beginning of module */-#define DST$C_MODEND 189 /* End of module */4#define DST$C_RTNBEG 190 /* Beginning of routine */.#define DST$C_RTNEND 191 /* End of routine */)#define DST$C_DELTA_PC_W 1 /* Incr PC */-#define DST$C_INCR_LINUM 2 /* Incr Line # *//#define DST$C_INCR_LINUM_W 3 /* Incr Line # */#define DST$C_SET_LINUM_INCR 4 #define DST$C_SET_LINUM_INCR_W 5 #define DST$C_RESET_LINUM_INCR 6#define DST$C_BEG_STMT_MODE 7#define DST$C_END_STMT_MODE 8.#define DST$C_SET_LINE_NUM 9 /* Set Line # */#define DST$C_SET_PC 10#define DST$C_SET_PC_W 11#define DST$C_SET_PC_L 12#define DST$C_SET_STMTNUM 13*#define DST$C_TERM 14 /* End of lines */,#define DST$C_TERM_W 15 /* End of lines */)#define DST$C_SET_ABS_PC 16 /* Set PC */*#define DST$C_DELTA_PC_L 17 /* Incr PC */0#define DST$C_INCR_LINUM_L 18 /* Incr Line # */.#define DST$C_SET_LINUM_B 19 /* Set Line # */.#define DST$C_SET_LINUM_L 20 /* Set Line # */,#define DST$C_TERM_L 21 /* End of lines */&/* these are used with DST$C_SOURCE */.#define DST$C_SRC_FORMFEED 16 /* ^L counts */0#define DST$C_SRC_DECLFILE 1 /* Declare file */+#define DST$C_SRC_SETFILE 2 /* Set file */.#define DST$C_SRC_SETREC_L 3 /* Set record */0#define DST$C_SRC_DEFLINES_W 10 /* # of line */K/* the following are the codes for the various data types. Anything not on- * the list is included under 'advanced_type' */#define DBG$C_UCHAR 0x02#define DBG$C_USINT 0x03#define DBG$C_ULINT 0x04#define DBG$C_SCHAR 0x06#define DBG$C_SSINT 0x07#define DBG$C_SLINT 0x08#define DBG$C_REAL4 0x0a#define DBG$C_REAL8 0x0b #define DBG$C_FUNCTION_ADDR 0x17 #define DBG$C_ADVANCED_TYPE 0xa3K/* These are the codes that are used to generate the definitions of struct * union and enum records */#define DBG$C_ENUM_ITEM 0xa4#define DBG$C_ENUM_START 0xa5#define DBG$C_ENUM_END 0xa6 #define DBG$C_STRUCT_START 0xab#define DBG$C_STRUCT_ITEM 0xff#define DBG$C_STRUCT_END 0xacL/* These are the codes that are used in the suffix records to determine the * actual data type */#define DBG$C_BASIC 0x01#define DBG$C_BASIC_ARRAY 0x02#define DBG$C_STRUCT 0x03#define DBG$C_POINTER 0x04#define DBG$C_VOID 0x05!#define DBG$C_COMPLEX_ARRAY 0x07J/* These codes are used in the generation of the symbol definition records */%#define DBG$C_FUNCTION_PARAMETER 0xc9#define DBG$C_LOCAL_SYM 0xd9*[ERIC.NEWDRV]PRF.MAR;6+,5&./: 49-7%0123KPWO56,=7<>8@tӭ˔9 `?G:HJ .title prf  .ident /v1.0/ .sbttl image section $code9 .psect $code,con,rel,novec,rd,nowrt,exe,pic,lcl,shr,longmcount::5 pushl (SP) ; the PC of the routine we just came from/ pushl R0 ; and the addr of the count location  calls s^#2,_mcount rsb .end*[ERIC.NEWDRV]PROFILE.C;83+,`>. /: 4Q -7%0123KPWO!56:U?7BV?8(y̔9G:HJ /* PROFILE *C * A function and block profiler for GNU "CC" running under the VMS0 * operating system. When a program is compiledD * requesting profiling, there are externals in the object file thatD * will be satisfied by this module. When initialization is called,D * an exit handler is set up to dump the info to the screen at image * exit. * 5 * Copyright (C) 1991 Free Software Foundation, Inc.L This file is part of PROFILE, the GNU block and function profiler for GCC.?PROFILE is free software; you can redistribute it and/or modifyDit under the terms of the GNU General Public License as published byCthe Free Software Foundation; either version 1, or (at your option)any later version.:PROFILE is distributed in the hope that it will be useful,>but WITHOUT ANY WARRANTY; without even the implied warranty of=MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the,GNU General Public License for more details.AYou should have received a copy of the GNU General Public License;along with PROFILE; see the file COPYING. If not, write toIthe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *//* Written by Eric Youngdale */4/* Edit history: V1.0 2/8/91 ERY Initial Release */#include #include #include 5/* we need this to parse the debugger symbol table */#include "objrecdef.h"H/* this macro reverses the elements in a linked list, assuming that eachF struct has an element named next that points to the next element */ #define REVERSE(TYPE,HEAD) \ { \) struct TYPE * tpnt1, *tpnt2, *tpnt0; \ tpnt0 = HEAD; \# tpnt2 = (struct TYPE *) NULL; \ while(tpnt0){ \ tpnt1 = tpnt0->next; \ tpnt0->next = tpnt2; \ tpnt2 = tpnt0; \ tpnt0 = tpnt1; \ }; \ HEAD = tpnt2; \ } \struct function_list{ struct function_list* next; unsigned int count; int cpu_time; char* function_name;}; struct block{ int init; char* name; int * count_table; unsigned int counts; int sun_compatible; int * address_table; }; /* used for block profiler */ struct block_list{ struct block_list* next; struct block * block;};struct traceback{ struct traceback* next; unsigned int line_number; unsigned int PC;};struct source_files{ struct source_files * next; unsigned short int file_number; char* file_name;};struct source_list{ struct source_list * next; unsigned short int file_number; unsigned int line_number; unsigned int n_rec;};struct module_list{ struct module_list* next;# struct traceback* traceback_table; struct source_files * files; struct source_list * records;};)static struct function_list * functs = 0;%static struct block_list * chains =0;-static struct module_list * module_chain = 0;Qstatic int dstflag = 0; /*flag to see if we have read the debugger symbol table*/static struct ihd{ short int space1; short int space2; short int symblk; short int space3; int rest[126];}buffer; struct rlist{ struct rlist* next; char* rname; unsigned int * start_addr; unsigned int * end_addr;}; static struct rlist* rchain = 0;,static struct function_list* last_enter = 0;static int last_time;)/* type cast this for the exit handler */void __bb_dump_profile();L/* use this to declare exit handler. Statistics are automatically dumped */#static unsigned int exit_condition;static struct exh{ lon Cܧ SAVE.SET`>7%[ERIC.NEWDRV]PROFILE.C;83Q 8g int forward; void (*function); long int arg_cnt; unsigned int * condition;7} exh_block = { 0,__bb_dump_profile,0,&exit_condition};8static int get_delta_pc(unsigned char * pnt,int * ipnt){ int rval =0; if(pnt[0] > 0x7f)- return 0x100 - *((unsigned char *)&pnt[0]); if(pnt[0] == DST$C_DELTA_PC_W){ rval = *((short *)&pnt[1]); *ipnt += 2; }; if(pnt[0] == DST$C_DELTA_PC_L){ rval = *((long *)&pnt[1]); *ipnt += 4; }; return rval;}M/* this function reads the debugger symbol table to find out the names of all> of the functions, and the PC range that each one covers. */static readdst(){ int imafile; struct ihd buffer;5 int dstloc; /* location of debugger symbol table */+ int dstlen; /* number of blocks in dst */ unsigned char dbuffer[256]; char imagename[80]; short int imagelen; int ipnt; int abs_pc = 0; int line_number = 0; int line_increment = 1; int stat; int prcnum=0; int file_number; int rec_no; int n_lines; struct traceback* tpnt; struct source_files * spnt; struct source_list * lpnt;" struct module_list* curr_module; short int i; struct rlist* rpnt; unsigned char blen, blen1; struct jpilist{ short int buflen; short int item_code; char * buff_addr; short int * ret_len_addr; int next;@ } getimaname = {sizeof(imagename),(short int) JPI$_IMAGNAME, imagename,&imagelen,(int) 0};@ /* first we ask VMS the name of the image we are running now */3 stat = sys$getjpiw(0,&prcnum,0,&getimaname,0,0,0); if(!stat) lib$signal(stat); imagename[imagelen+1]='\0';G imafile = open(&imagename, O_RDONLY, 0666 ); /* now open that file*/; i = read(imafile,&buffer,512); /* read the header block */ i = buffer.symblk/4 -2; D dstloc = buffer.rest[i]; /* find the block where the dst starts*/! dstlen = buffer.rest[i+2] * 512;8 lseek(imafile, (dstloc -1)* 512, 0); /* and go there */D /* get blocks in debugger symbol table, one by one, and interpret them if needed */ while(1==1){A i = read(imafile,&blen,1); /* get length of debugger record */ dstlen--; if(blen == 0) break; blen1 = blen; do{H i = read(imafile,&dbuffer[blen-blen1],blen1); /* and read record */D blen1 -= i; /* find out how many characters are left to read */ }while(blen1 != 0);> dstlen -= blen; /* keep track of how many bytes are left */ switch(dbuffer[0]){ case DST$C_MODBEG:& curr_module = (struct module_list*)' malloc(sizeof(struct module_list));$ curr_module->next = module_chain; module_chain = curr_module;; curr_module->traceback_table = (struct traceback*) NULL;4 curr_module->files = (struct source_files*) NULL;5 curr_module->records = (struct source_list*) NULL; break; case DST$C_MODEND:" /* re-order the linked lists */3 REVERSE(traceback,curr_module->traceback_table);, REVERSE(source_files,curr_module->files);- REVERSE(source_list,curr_module->records); break; case DST$C_RTNBEG: dbuffer[dbuffer[6]+7] = 0;7 rpnt = (struct rlist*) malloc(sizeof(struct rlist));7 rpnt->start_addr = *((unsigned int **)&dbuffer[2]); rpnt->next = rchain;7 rpnt->rname = (char*) malloc(strlen(&dbuffer[7])+1);# strcpy(rpnt->rname,&dbuffer[7]);/ rchain = rpnt; /* put this at top of list */ break; case DST$C_RTNEND:$ rpnt->end_addr = (unsigned int *)? ((char*) rpnt->start_addr + *((unsigned int *)&dbuffer[2])); break; case DST$C_SOURCE: ipnt = 1; do{ switch(dbuffer[ipnt]){+ case DST$C_SRC_FORMFEED: /* ^L counts */ ipnt += 1; break;. case DST$C_SRC_DECLFILE: /* Declare file */" spnt = (struct source_files*) ) malloc(sizeof(struct source_files));% spnt-> next = curr_module->files; curr_module->files = spnt; spnt->file_number = 0 *((unsigned short int *)&dbuffer[ipnt+3]);7 spnt->file_name = (char*) malloc(dbuffer[ipnt+20]);/ strncpy(spnt->file_name,&dbuffer[ipnt+21],  dbuffer[ipnt+20]); ipnt += 2 + dbuffer[ipnt+1]; break;) case DST$C_SRC_SETFILE: /* Set file */ file_number = 0 *((unsigned short int *)&dbuffer[ipnt+1]); ipnt += 3; break;, case DST$C_SRC_SETREC_L: /* Set record */) rec_no = *((int *)&dbuffer[ipnt+1]); ipnt += 5; break;- case DST$C_SRC_DEFLINES_W: /* # of line */! lpnt = (struct source_list*) ( malloc(sizeof(struct source_list));' lpnt-> next = curr_module->records; curr_module->records = lpnt; lpnt->n_rec = 0 *((unsigned short int *)&dbuffer[ipnt+1]);$ lpnt->file_number = file_number; lpnt->line_number = rec_no; ipnt += 3; break; default:) printf(" Source file description\n");4 for(i=ipnt;i 0x7f){3 abs_pc += get_delta_pc(&dbuffer[ipnt],&ipnt);# line_number += line_increment; ipnt += 1; break; }; if(dbuffer[ipnt] != 0){5 printf(" Line number type %d\n",dbuffer[ipnt]); ipnt += 255; } else { ipnt += 1; }; break; }; }while(ipnt < blen);B tpnt = (struct traceback*) malloc(sizeof(struct traceback));1 tpnt-> next = curr_module->traceback_table;* curr_module->traceback_table = tpnt;& tpnt->line_number = line_number; tpnt->PC = abs_pc; break;//* the rest are assumed to be of no interest */ default: break; }; }; close(imafile);1 dstflag = 1; /* mark this as having been read */I/* now declare the exit handler, which will write the report to stdout */ stat = sys$dclexh(&exh_block); if(!stat) lib$signal(stat);}F/* this function is called each time we enter a new function. We mustO increment the count, increment the CPU time of the last function entered, andP reset the clock so we know how much CPU time was used by this function call */E/* ipnt is the address of the longword that contains a pointer to theNfunction_list structure created for this function. Once we have allocated theMstructure, we do not need to search the list. addr is the PC of the functionOthat called the profiler - we use this to determine which routine we are in. */@void _mcount(struct function_list ** ipnt, unsigned int * addr){ struct function_list* pnt;  struct rlist* rpnt; int new_time;= new_time = clock(); /* do now, so we collect all the info */ B? s 7%[ERIC.NEWDRV]XSF:O70[ p1t5@ o_$l?Ph!!fUr7N  //-Sb6+EuY+blZ)?H&e2\;et j 7^C]|r61 &j5gPc+T6Ml=.)T}U/eV`lA{E|YN4 0I_qOoRbb6YfRp/$$KIz@\dAd"X=[ e7:mkQo7yԅ\Cu< rc#H ]^wr?S ^S$@]?ws::צz+?;!~;1 x%O+C5rI;|7dv79T2Rc2RBz}4TZW [|Tl exNldq] + }`OZ+ 7A0lMc3dfg|| NKe.#])FP@[q7( T 'g`K8&o(DX()(.A) #^*^rs^ HNl[sϣqa x;#o ZdsL:6>vF &S>#XF%B\Pt;ppAI^\{L g+b#+w0]n~ s;^=SS bF _{Pc enYfY)K ,J7 }+{94/}V/? -_Ax1 >ru7,z6[%W&,!bp{"\pRY+&(t=~Xo.u![5yL*Ey}8|]tQz,*Qv= qLEY t:K[?1#*` Tp!jVj3*sXMw)F}_ch{WS\)yt2 .j2&B)*xyh^ tB`%rY_yM:xA?O%V<{# }"PoEZ=/3\a d,(L}W~ V$;S >J =}k'^(Z:=h]M\0!)XHw:*^ZXB,eU t=$P{p!JlQ`~7`4c^t%:|l:|s@779E 7!9 L~$sV7XOr ]1;G1]C Fn/KYBw ~+.sf?$#sBZnD=+-yU+JVz80cg< /otZQ>B wKu6hfC4bOg9X7W@ 3FiGOi>wxOklPf_?cE85A(e:BKdmXd9 q x9!S%.{$AQ@1>*q0M}ROVu>#]{o`[D-`l!T0&?:G*N zBtA9A f RFP9g:N.5&^,./h/w^Z3qD C(DuB o&>&h*u!vu%_/$6SD)iIlBNKI&02#>||Rkixne;I[K2.ukIemigI~ lPC$<'.,: 2R3cjY*L0@;;jQ$8V~HJ>O9`^36pOr(p[,8s d-FO5+}yXMO#*$^Cy `g>;}t)17bn(UGDEPl%l%v5MpB|QX!6/!3&#=[a /cP+RBE.ELs$.Q(f r* +U6Zs)&T^Qvr!p+?;v;! \W ,&0}zrqXq0EGj,W'A rrC$\_M18;[P/V$J&j\EE y aiD|Cjjx D%ABL;:+2!LzXxOq4oI~RJN9{fGQo:0hm(kbZRDaaWb>?\fjn~b^2_(z76cUmC]eUVXix75=g|Ks\tnh\=~E^o}SRmKon3R~{2^X4BHGI0*qMzFr=$hXvEXo/&f)GgF_rAZY%> _.7"-JX[d_`OJ:n/s<\Qn>M^Em{=dgl?k3I;z'?t&kF\jC| Lt|#9~mPx%-8huUtOd8#uaem#|#\\?}K~ ,`<$\[UFWZ^VFDJs)ejY(fwWIM/:$&(:0c,~D8_0<NxEM{2iLU-peH;xD" S/?!/,)M~ 8}^( E|AW\$94J h]@Aa{< MG;D^'~mi# /LPmSrD3!kGNf21G(n.3#IVhc X7MDX4'x7ec?~<=}q _/'t"` -^eN%*(**4f]{ u 9e*r_w1cryC$wh >..;ekBX_p]Z.03B H"0VbYvpe% *"9dX:6#)5JK.z(>/3@_#D3da;7 W~Y;!)9 t[pZ#BM}/i?1.IV@ukpxp?7^ Eh#kZX33\ JC XZ:e m X"\g])JrYP6DmCGk )9%An ^[RLUXX}9$HF[k@Gw+ssV}U :t[nEit :c7> L rG C\xqwb_">7S.!y t?7QLyL<_a 7(h?tz`oCI [Ri$b5cSi:I%wvmj>8u=Wpz6D[*O ŧ|elj;`E`?i.]2G .I nbF CV9_s0bs(Mv3}K|s N[4e"=L|L7q(Lp m-1e`l#X#g&}[J| SN8@I n])n.Q|R.g}J7,U^iN#5 6lJGe. 0+r>33qO6Cc gEhmpe2G@`,4j m9 |~%.=Ct?HY+M"dAakT) a@,I(s2I5~1C 17 NH^JOOtH]>>mh'+j`|jfBwir0tYWy0~ERSJQ23AMTh%MaYi69'vSub$Tj2.^!mGt+p3($ fFce5.X4lW'@+`+r#KX?0FUlU.|aB!$4/I\(bSaj U"dw7 LP/E$}1Cc#4VH]Q-i,>.K?;4d % =gkQFQYHO2 /db_19sF~jO GElw}g7 l7e,+xIJ@ DQg G1 &BH].:e!2, ^ma=@=i_fz{7l-ϺGzTJb?XokPNFUuNAa09:`#ed ,|8)XP!,W")phyt=Nc `>FtT?]_+avHvqdNYo \jq:E5& ys|(6i{-cG$NjCj L IS")*_+C7_bw&Fq? nnMUf( KM \"JRG 2! Tr]FR I/Dml)Sz ;U[v/ Hx9sza*;BhsXjx$Jf6X({) >29;PSc#wKTxs|gWq#vjk}c~]Ikp,! 3Gs%hF7nA07/U kKbG1@p$.('SO_}1}*J;+ 36vA>=&H|$I%+4Hln>iKuCz5eYX"1[\"g RV&_3^8p!R~@cm;~fT 0#We48ZlP"^3Zk3GJ+R9|g2|\2 }+}$/X9WgQ"hk98@-Pk)o^:qG:8BS6L z*p}bynu+ `J}- ZTD=Uqc~+>Wr eb*hbivCu(3Ng9o(r4^L "g%xM7Kz,552Ivr##0:; }nE,_c1{~ KNIoi82}wN/:L2{ :#zu|@O22:5OA`$Z5"28 !_ 1tF @ujO+cc-QJ"6Gih95 *77'|f(|?w& lquF<W9}~ MS|),4n^wyH @m-X;SwJ(TJ}'u`.W9Cl?v|xW#Us GwGp~O:xlEuT)EF~*F$BIc!Zf >I,UmQ;A2sR+ -Ir=v51Vc0{XtKr_>+ y>r'3r(<c fisk[NkLI*29<]9-x$H`HE_HvB|MQ}egNV2o^ Un ?v& U,yp' ]9}?hL^9!i%!X t[-HY"N .|VdT?q-\6L@_OD$c W!e"l)kOI %Wo-f1Di.FPiwMzR8yIZpy"'+Px;PO/e xZ^m2:l(/UC#hpc/&Q7gkx26t4,:PW|p:\kSF>"pq KLVd FAdnDOC*pZ>sR*4G=}7(13AoR^Y! MY "Z{{T\+vU,cew9N4?g%bf6{dPF, IfKq Ed_c>FBYqr:aC\c(bZIWN$k"ZOr5yb # %~}eQkil z aWby[ i5S#W:Z*n(4)Z+@LEM0RIF&ta!^" *iO}*] "mp)B*F b4L<]:X:grjyNO&>W;lN0jqI#,H L.e 6'!p,BY :0L}6G;;V}prw~\1xx 4f VbW,(`tgd*m}~%j%i" h S &=V=oxS v3=l :6\Pim}+j Tk - xOU>~2S!+ u~~'z4#`)_8j *6f@2o[n6}L>vPcQB/u~27mat? hsjc\=drR>v=g\\vPACvo5upvF od25'>UmUk6A&!XHBb'+%r''hGt[aJ>7IN wpH"1u#Q1Do n=9 Yq$CcDO*(Q/@9M49:6 F{xm4/!>c3 YGQ%*MGysoXvK)^$(jeBOC8\^\`a,6RI~:Ax H]Fa\@=q:FDn15d7l+abb\LF Ks,%cNya],LZ)]6..X)4- (g3=*SGRhd5PK] o*z[N!"5j~yaI-+o`r1n}A?080zp+Bt{.j!c1#>9L7Txj5:0(&<7m+!DA8n=e B ;y I)qbI+.JG2"%AZy2}!E_Lz +ekR+}Whb0(6wsze4gM*5)y p8H+)VBJk{ 7n1]P WOAVN0%w/1[7Qp'f3Z'NI5h6P?lhsFDqX+.zC= o' |sMBKqnb>c7NW$ 3$ptMI>< 8-2-dD'QwP_swPe 8| ILz$ * L5jXB5u>{H+(aQ~j$nQqr\MV"BOYz9 q6*-=B"2sgBxO6" i1oC%!XjaeH*}--BK{`  3&o<" 9%'`WT\^.)r<{gE'orU%]CiIr+%]iLOOl/n/Y{p;@ EhN(/5o=yn%5fDN>c9o'1G+AD?=;t.37yikmv5'ZTM|qz'zDKVJ+2csXbi YN"|1{g-I;{erF/FlJcO2W n Q Q$}TKk[#w99Q,G%71azz909UA:@W yREX/n%m zr$OUPw^=[7;DiC8XGL 3p}xd\ %L:WFvLP0IPb  s!qPE4rfiG^WX`;AEn{qp`Tlt%I_DATbTP`LS8',CpPK $?XSkx;(7mD`3<1y{4MWuBS,v{S( z|kagHPUPO4ENnOS_6.UfP%y< B@%c{!Er>+/Xv-4~u`7$[]9abV E,(GKSaZTt!RVU^oz JP|* OE_tmztjh&u*T: ge!N9-$INPUT",Temp,sizeof(Temp))){% Input_Files[i++] = savestr(Temp); checkswitches(LOCAL);};' /* find the name of the source file */) cp = (char*) strchr(Input_Files QZ SAVE.SET`>7%[ERIC.NEWDRV]PROFILE.C;83Q  if( ! *ipnt ){> if(!dstflag) readdst(); /* read the debugger symbol table */ pnt = (struct function_list*) ( malloc(sizeof(struct function_list)); pnt->next = functs; pnt->count = 0; pnt->cpu_time = 0;< pnt->function_name = "\0"; /* in case we do not find it */ rpnt = rchain; while(rpnt){: if(addr >= rpnt->start_addr && addr < rpnt->end_addr){$ pnt->function_name = rpnt->rname; break;}; rpnt=rpnt->next; }; functs = pnt;8 *ipnt = pnt; /* save this for later quick reference */ };0 ((*ipnt)->count)++; /* increment the counter */= if(last_enter) last_enter->cpu_time += new_time - last_time; last_time = new_time; last_enter = *ipnt; return;}*void _bb_init_func(struct block * block){ struct block_list* pnt; H if(!dstflag) readdst(); /* read the debugger symbol table if not done*/ pnt = (struct block_list*) $ malloc(sizeof(struct block_list)); pnt->next = chains; chains = pnt; pnt->block = block; block->init = 1; return;}+static struct module_list * current_module;'static void getmod(struct block * blk){ struct module_list * mpnt; struct traceback * tpnt; int armed; int i; int * PC; PC = blk->address_table; for(i=0;i < blk->counts ; i++){/ for(mpnt=module_chain;mpnt;mpnt = mpnt->next){ armed = 0;: for(tpnt=mpnt->traceback_table;tpnt;tpnt = tpnt->next){ if(tpnt->PC < *PC) armed = 1;5 if(tpnt->PC == *PC || (tpnt->PC > *PC && armed)) { current_module = mpnt; return; }; }; };- PC++; /* go to next element and try again */ }; current_module = 0;}*static unsigned int lnum(unsigned int PC){ struct traceback * tpnt; struct traceback closest; if(!current_module) return 0; closest.PC = 0xFFFFFFFF;B for(tpnt=current_module->traceback_table;tpnt;tpnt = tpnt->next){/ if(tpnt->PC == PC) return tpnt->line_number;/ if(tpnt->PC > PC && tpnt->PC < closest.PC) { closest.PC = tpnt->PC; * closest.line_number = tpnt->line_number; }; };' if(closest.PC == 0xFFFFFFFF) return 0;? return closest.line_number; /* best line number for this PC */}.static unsigned int lookup(int * line_number){ struct source_list * lpnt; struct traceback * tpnt; if(!current_module) return 0;< for(lpnt=current_module->records;lpnt;lpnt = lpnt->next){' if(*line_number <= lpnt->n_rec) { 8 *line_number += lpnt->line_number -1; /* add offset */ return lpnt->file_number; }; *line_number -= lpnt->n_rec; }; return 0;}static unsigned int dump(){ struct module_list * mpnt; struct traceback * tpnt; struct source_files * spnt; struct source_list * lpnt;/ for(mpnt=module_chain;mpnt;mpnt = mpnt->next){0 for(spnt=mpnt->files;spnt;spnt = spnt->next){8 printf("%d %s\n",spnt->file_number,spnt->file_name); };2 for(lpnt=mpnt->records;lpnt;lpnt = lpnt->next){I printf("%d %d %d\n",lpnt->file_number,lpnt->line_number,lpnt->n_rec); }; };}static unsigned int fdump(){ struct source_files * spnt; if(!current_module) return 0;' if(!current_module->files) return 0;: for(spnt=current_module->files;spnt;spnt = spnt->next){8 printf("%d %s\n",spnt->file_number,spnt->file_name); }; printf("\n");}L/* this routine dumps the block profile to the screen. It resets all of theD counts and CPU times, so that if the user wants to see this stuffJ incrementally s/he can call this before and after the critical piece of code */void __bb_dump_profile(){ unsigned int new_time; struct function_list* pnt;  struct block_list * bpnt;  int *ipnt, *jpnt; int raw_line_number, fnumb; int i;5/* first fix up the time spent in the last routine */ new_time = clock();= if(last_enter) last_enter->cpu_time += new_time - last_time; last_time = new_time; pnt = functs;2/* now print the function profile to the screen */ if(pnt){" printf(" Function profile:\n");4 printf(" # entries CPU sec Function Name\n");4 printf(" _________ _______ ________ ____\n"); }; while(pnt){( printf("%10d %9.2f %s\n",pnt->count,+ pnt->cpu_time/100.0,pnt->function_name); pnt->cpu_time= 0; pnt->count = 0; pnt = pnt->next; };//* now print the block profile to the screen */ bpnt = chains; while(bpnt){0 getmod(bpnt->block); /* find current module */4 printf("\n Block profile for file %s, %d lines\n",* bpnt->block->name,bpnt->block->counts);" ipnt = bpnt->block->count_table;$ jpnt = bpnt->block->address_table;1 printf(" Source files for this module are:\n"); fdump();2 printf(" F# line# rline# PC Count\n");3 printf(" ___ ______ ______ ________ ______\n");3 for(i=0;iblock->counts;i++,ipnt++,jpnt++){! raw_line_number = lnum(*jpnt);$ fnumb = lookup(&raw_line_number);* printf(" %3d %6d %6d (%8x):%d\n",fnumb,- raw_line_number,lnum(*jpnt),*jpnt,*ipnt); };  bpnt = bpnt->next; };}  8# SAVE.SET`>7%[ERIC.NEWDRV]PROFILE.C;83Q { if( ! *ipnt ){> if(!dstflag) readdst(); /* read the debugger symbol table */ pnt = (struct function_list*) ( malloc(sizeof(struct function_list)); pnt->next = functs; pnt->count = 0; pnt->cpu_time = 0;< pnt->function_name = "\0"; /* in case we do not find it */ rpnt = rchain; while(rpnt){: if(addr >= rpnt->start_addr && addr < rpnt->end_addr){$ pnt->function_name = rpnt->rname; break;}; rpnt=rpnt->next; }; functs = pnt;8 *ipnt = pnt; /* save this for later quick reference */ };0 ((*ipnt)->count)++; /* increment the counter */= if(last_enter) last_enter->cpu_time += new_time - last_time; last_time = new_time; last_enter = *ipnt; return;}*void _bb_init_func(struct block * block){ struct block_list* pnt; H if(!dstflag) readdst(); /* read the debugger symbol table if not done*/ pnt = (struct block_list*) $ malloc(sizeof(struct block_list)); pnt->next = chains; chains = pnt; pnt->block = block; block->init = 1; return;}+static struct module_list * current_module;'static void getmod(struct block * blk){ struct module_list * mpnt; struct traceback * tpnt; int armed; int i; int * PC; PC = blk->address_table; for(i=0;i < blk->counts ; i++){/ for(mpnt=module_chain;mpnt;mpnt = mpnt->next){ armed = 0;: for(tpnt=mpnt->traceback_table;tpnt;tpnt = tpnt->next){ if(tpnt->PC < *PC) armed = 1;5 if(tpnt->PC == *PC || (tpnt->PC > *PC && armed)) { current_module = mpnt; return; }; }; };- PC++; /* go to next element and try again */ }; current_module = 0;}*static unsigned int lnum(unsigned int PC){ struct traceback * tpnt; struct traceback closest; if(!current_module) return 0; closest.PC = 0xFFFFFFFF;B for(tpnt=current_module->traceback_table;tpnt;tpnt = tpnt->next){/ if(tpnt->PC == PC) return tpnt->line_number;/ if(tpnt->PC > PC && tpnt->PC < closest.PC) { closest.PC = tpnt->PC; * closest.line_number = tpnt->line_number; }; };' if(closest.PC == 0xFFFFFFFF) return 0;? return closest.line_number; /* best line number for this PC */}.static unsigned int lookup(int * line_number){ struct source_list * lpnt; struct traceback * tpnt; if(!current_module) return 0;< for(lpnt=current_module->records;lpnt;lpnt = lpnt->next){' if(*line_number <= lpnt->n_rec) { 8 *line_number += lpnt->line_number -1; /* add offset */ return lpnt->file_number; }; *line_number -= lpnt->n_rec; }; return 0;}static unsigned int dump(){ struct module_list * mpnt; struct traceback * tpnt; struct source_files * spnt; struct source_list * lpnt;/ for(mpnt=module_chain;mpnt;mpnt = mpnt->next){0 for(spnt=mpnt->files;spnt;spnt = spnt->next){8 printf("%d %s\n",spnt->file_number,spnt->file_name); };2 for(lpnt=mpnt->records;lpnt;lpnt = lpnt->next){I printf("%d %d %d\n",lpnt->file_number,lpnt->line_number,lpnt->n_rec); }; };}static unsigned int fdump(){ struct source_files * spnt; if(!current_module) return 0;' if(!current_module->files) return 0;: for(spnt=current_module->files;spnt;spnt = spnt->next){8 printf("%d %s\n",spnt->file_number,spnt->file_name); }; printf("\n");}L/* this routine dumps the block profile to the screen. It resets all of theD counts and CPU times, so that if the user wants to see this stuffJ incrementally s/he can call this before and after the critical piece of code */void __bb_dump_profile(){ unsigned int new_time; struct function_list* pnt;  struct block_list * bpnt;  int *ipnt, *jpnt; int raw_line_number, fnumb; int i;5/* first fix up the time spent in the last routine */ new_time = clock();= if(last_enter) last_enter->cpu_time += new_time - last_time; last_time = new_time; pnt = functs;2/* now print the function profile to the screen */ if(pnt){" printf(" Function profile:\n");4 printf(" # entries CPU sec Function Name\n");4 printf(" _________ _______ ________ ____\n"); }; while(pnt){( printf("%10d %9.2f %s\n",pnt->count,+ pnt->cpu_time/100.0,pnt->function_name); pnt->cpu_time= 0; pnt->count = 0; pnt = pnt->next; };//* now print the block profile to the screen */ bpnt = chains; while(bpnt){0 getmod(bpnt->block); /* find current module */4 printf("\n Block profile for file %s, %d lines\n",* bpnt->block->name,bpnt->block->counts);" ipnt = bpnt->block->count_table;$ jpnt = bpnt->block->address_table;1 printf(" Source files for this module are:\n"); fdump();2 printf(" F# line# rline# PC Count\n");3 printf(" ___ ______ ______ ________ ______\n");3 for(i=0;iblock->counts;i++,ipnt++,jpnt++){! raw_line_number = lnum(*jpnt);$ fnumb = lookup(&raw_line_number);* printf(" %3d %6d %6d (%8x):%d\n",fnumb,- raw_line_number,lnum(*jpnt),*jpnt,*ipnt); };  bpnt = bpnt->next; };}