home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / ecc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  32.0 KB  |  1,134 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /*
  30.  * Harvest C
  31.  * 
  32.  * Copyright 1991 Eric W. Sink   All rights reserved.
  33.  * 
  34.  * This is the principal file for Harvest C. It includes all output routines,
  35.  * memory management, as well as management of compiler options.
  36.  * 
  37.  * 
  38.  * 
  39.  */
  40.  
  41. #include "conditcomp.h"
  42. #include <stdio.h>
  43. #include <ctype.h>
  44. #include <string.h>
  45. #include <math.h>
  46. #include "structs.h"
  47. #include "CHarvestDoc.h"
  48. #include "CHarvestOptions.h"
  49.  
  50. extern CHarvestDoc *gProject;
  51. FILE *fopenMAC(char *name,short vRefNum,long dirID,char *mode);
  52.  
  53. #pragma segment HarvestMain
  54.  
  55. /* Modules */
  56. #include "TypeRecord.h"
  57.  
  58. int                             PartDone;
  59.  
  60. LabSYMVia_t                             CurrentSegmentLabel;
  61. LabSYMVia_t                             NextFuncSegment;
  62.  
  63. short                           CurVolrefnum;
  64. long                            CurDirID;
  65.  
  66. ParamRecVia_t                   ParamList;
  67.  
  68. int                             ExtraBlocks;    /* used primarily in
  69.                          * parsestmt.c, for keeping
  70.                          * track of scopes */
  71. char                            Errm[MAXERRORMSG];    /* used as a buffer for
  72.                              * constructing error
  73.                              * messages */
  74.  
  75. unsigned int                    CountIncludes;
  76.  
  77. LabSymListVia_t                 SwitchCases;
  78. #define MAXSWITCHES 64
  79. LabSymListVia_t                 Switches[MAXSWITCHES];
  80. int                             CountSwitch;
  81.  
  82. #ifdef OOPECC
  83. SymListVia_t                    ClassList;    /* global list of classes */
  84. SymListVia_t                    MessageList;    /* global list of messages */
  85. #endif
  86. LabSymListVia_t                 Labels;    /* list of asm labels */
  87. SymListVia_t                    StringLits;    /* String literal pool */
  88. SymListVia_t                    TagsTable;    /* Struct/union/enum tags */
  89. SymListVia_t                    LabelsTable;    /* C labels */
  90. /*
  91.  * The next variables are used while constructing struct declarations
  92.  */
  93. int                             CurFieldOffset;    /* offset of current bit
  94.                          * field */
  95. int                             NextStructOffset;    /* offset of next member */
  96. int                             CurFieldBit;
  97. int                             CurStructSize;
  98. ParseTreeVia_t                  LastSwitchExpression;    /* used by the parser to
  99.                              * remember the
  100.                              * expression in the
  101.                              * last switch(expr)
  102.                              * statement, so we can
  103.                              * typecheck the case
  104.                              * labels against that
  105.                              * expression */
  106. SymListVia_t                    StaticTable;    /* global list of static
  107.                          * variables (static within
  108.                          * functions) */
  109. SymListVia_t                    GlobalSymbolTable;    /* All external symbols
  110.                              * are defined here. */
  111. SymListVia_t                    TP_defnames;    /* All TP_defnames are
  112.                          * defined here. */
  113. LabSymListVia_t                    SegmentNames;    /* All segment names are
  114.                          * stored here. */
  115. int                             InPreprocIf;    /* a flag which indicates to
  116.                          * the parser whether or not
  117.                          * we are parsing the
  118.                          * expression following an
  119.                          * #if or #elif directive */
  120. /*
  121.  * A SRC is the logical source of the C program text being lexed/parsed.  It
  122.  * may be a region of memory or a file
  123.  */
  124.  
  125. SRCListVia_t                    SRCStack;    /* the SRC stack */
  126. SRCKind_t                       CurrentSRC;    /* the current SRC for C code */
  127.  
  128. KW_t                            KWTable[KEYWORDTABLESIZE];    /* The KWTable is a hash
  129.                                  * table for C reserved
  130.                                  * words.  Since
  131.                                  * virtually every token
  132.                                  * must be checked
  133.                                  * against the list of
  134.                                  * reserved word, it is
  135.                                  * worthwhile to make
  136.                                  * this search
  137.                                  * efficient. */
  138. TypeRecordVia_t                 ClassBeingImplemented = 0;    /* during a class
  139.                                  * @implementation, this
  140.                                  * is the type record
  141.                                  * for that class. When
  142.                                  * referencing an
  143.                                  * instance variable,
  144.                                  * self is cast to this
  145.                                  * type before
  146.                                  * synthesizing the
  147.                                  * indirect member tree
  148.                                  * node. */
  149. long                            CurrentEnumK;    /* The value of the current
  150.                          * enum constant. Used during
  151.                          * construction of an enum
  152.                          * declaration. */
  153. TypeRecordVia_t                 EnumBeingDeclared;    /* During an enum
  154.                              * declaration, this
  155.                              * points to the type
  156.                              * record of the enum
  157.                              * being declared.  Each
  158.                              * enum constant bears a
  159.                              * pointer to its own
  160.                              * type. */
  161. SYMVia_t                        FunctionBeingDefined;    /* During a function
  162.                              * definition, this
  163.                              * points to the symbol
  164.                              * being defined.  */
  165. SYMVia_t                        InliningFunction;    /* While inlining a
  166.                              * function, this points
  167.                              * to the function begin
  168.                              * inlined */
  169.  
  170. struct uniqstring P__H         *HalUniqs = NULL;    /* a table of unique
  171.                              * identifiers, used for
  172.                              * calculating Halstead
  173.                              * metrics */
  174. /*
  175.  * All of the following variables are used in calculating various metrics
  176.  */
  177. unsigned int                    T_PreprocSubsts = 0;
  178. unsigned int                    T_PreprocBefore = 0;
  179. unsigned int                    T_PreprocAfter = 0;
  180. unsigned int                    T_CommentBytes = 0;
  181. unsigned int                    T_StmtCount = 0;
  182. unsigned int                    T_CountIdentifiers = 0;
  183. unsigned int                    T_TotalIdentifierLength = 0;
  184. unsigned int                    T_CountCasts = 0;
  185. unsigned int                    T_CountPreprocCondits = 0;
  186. unsigned int                    T_CountComments = 0;
  187. int                             FunctionReturnCount = 0;
  188. int                             FunctionComplexity = 0;
  189. int                             HalTotalOperands = 0;
  190. int                             HalTotalOperators = 0;
  191. int                             HalUniqOperators = 0;
  192. int                             HalUniqOperands = 0;
  193. int                             PreprocSymbolCount = 0;
  194. int                             DuplicateStringLits = 0;
  195. int                             TotalLines = 0;
  196. int                             CountFunctions = 0;
  197.  
  198. int                             SumGlobals;
  199. int                             SumGlobalSpace;
  200. LocAMVia_t                      StructDoubleReturnLoc;    /* During code
  201.                              * generation, this
  202.                              * points to the place
  203.                              * to return a struct.
  204.                              * doubles are now
  205.                              * returned in d0-d1 */
  206. /* These keep track of the efficiency of the keyword hash table. */
  207. int                             HashCollisions;
  208. int                             HashCount;
  209.  
  210. int                             OddGlobal;    /* true if an odd number of
  211.                          * bytes have been generated
  212.                          * for global data.
  213.                          * depending on the next
  214.                          * global variable, an
  215.                          * alignment directive may be
  216.                          * needed */
  217. int                             DiscardedFunctionCall;    /* a flag indicating to
  218.                              * the code generator
  219.                              * that the result of
  220.                              * the function call
  221.                              * being generated is
  222.                              * not needed. for
  223.                              * example, extern int
  224.                              * x(void); x(); */
  225.  
  226. StringPoolVia_t                 ParserStrings;
  227.  
  228. char                            LastPreproc[64];    /* records the name of
  229.                              * the last preproc
  230.                              * directive used */
  231.  
  232. int                             TokenOnDeck;    /* flag indicating if a
  233.                          * single token has been read
  234.                          * and then putback. Such a
  235.                          * token is on deck and is
  236.                          * easily available to the
  237.                          * parser in NextIs() */
  238. char                            NextToken[MAXIDLENGTH];    /* tokens on deck are
  239.                              * stored here */
  240. Codigo_t                        NextTokenKind;    /* tokens on deck are stored
  241.                          * here */
  242.  
  243. char                           *LastToken;    /* A very important variable.
  244.                          * This contains the string
  245.                          * of the last token read. */
  246. int                             SizeOfFloat;    /* size of float type in
  247.                          * bytes */
  248. int                             SizeOfDouble;
  249. int                             SizeOfLongDouble;
  250. Codigo_t                        LastTokenKind;    /* code for the last token
  251.                          * read */
  252. long double                     LastFloatingConstant;    /* value of the last
  253.                              * floating point
  254.                              * constant read -
  255.                              * probably only valid
  256.                              * if the last token
  257.                              * really was a floating
  258.                              * point constant */
  259. long                            LastIntegerConstant;
  260. char                            ThisToken[MAXIDLENGTH];    /* tokens are
  261.                              * constructed here
  262.                              * during lexing */
  263. char                            LastChar;    /* The last character read
  264.                          * which contributed to a
  265.                          * token.  TODO - is this
  266.                          * correct or is this the
  267.                          * last character returned
  268.                          * from RawCharacter() ? */
  269.  
  270. GenericFileVia_t                outfile;    /* output file for assembler
  271.                          * source, etc */
  272. GenericFileVia_t                errfile;    /* error file */
  273.  
  274. int                             NumErrors;    /* Cumulative count of
  275.                          * errors. */
  276. int                             AttemptWarnings;    /* Cumulative count of
  277.                              * warnings. */
  278. int                             NumWarnings;    /* Cumulative count of
  279.                          * warnings. */
  280.  
  281.  
  282. /*
  283.  * The Preprocessor uses the variable PPStatus to signal to the parser that
  284.  * tokens are to be ignored, due to the a conditional compilation directive.
  285.  * However, since these directives may be nested, there is a stack to keep
  286.  * old values of PPStatus.  This stack is implemented as an array of int and
  287.  * PPSP is the stack pointer.
  288.  */
  289. int                             PreprocStack[MAXNESTIFDEF];
  290. int                             PPSP;
  291. int                             PPStatus;
  292. /*
  293.  * The following are used for macro definition by the preprocessor.
  294.  * MacroValue is used to temporarily store the value of the macro being
  295.  * defined. The 'value' of a a macro, as I define it, is the string used in
  296.  * expanding it.  In other words, it is the part just to the right of the id
  297.  * and arguments : #define macro(a,b,c) VALUE
  298.  */
  299. EString_t                       MacroValue;
  300.  
  301. BlockStackVia_t                 CurrentBlock;    /* used in keeping track of
  302.                          * scopes. This points to the
  303.                          * top of the scope stack.
  304.                          * When looking up the
  305.                          * meaning of some identifer,
  306.                          * during parsing, the search
  307.                          * starts in the symbol
  308.                          * tables of the top scope,
  309.                          * and proceeds downward
  310.                          * until it is found or the
  311.                          * end of the stack is
  312.                          * reached. */
  313. LabSYMVia_t                     FunctionLastLabel;    /* during code
  314.                              * generation, this is
  315.                              * the number of the
  316.                              * label which will
  317.                              * occur at the end of
  318.                              * the function. a
  319.                              * return statement is
  320.                              * compiled with a jump
  321.                              * to this label */
  322. FloatLitVia_t                   FloatList;    /* floating point literal
  323.                          * pool */
  324. int                             NextFloatLitLabel;    /* number of the next
  325.                              * label for floating
  326.                              * point literals */
  327. int                             NextLitLabel;    /* number of the next label
  328.                          * for string literals */
  329. int                             NextEccLabel;    /* number of the next general
  330.                          * Ecc generated label */
  331. /*
  332.  * used by the register allocator, these next three variables keep track of
  333.  * which register is the next candidate for allocation. Register allocation
  334.  * is done on the fly
  335.  */
  336. int                             NextTempFloatReg;
  337. int                             NextTempDataReg;
  338. int                             NextTempAddrReg;
  339. /*
  340.  * these arrays are part of the register allocator, and contain data
  341.  * structures representing the machine registers.
  342.  */
  343. RegisterRecord_t                TempFloats[8];
  344. RegisterRecord_t                TempDatas[8];
  345. RegisterRecord_t                TempAddrs[8];
  346. /*
  347.  * used by the register allocator and code generator, this is a list of spill
  348.  * slots
  349.  */
  350. SpillSlotVia_t                  SpillList;
  351. LabSYMVia_t                     BreakLabel;    /* The current break label.
  352.                          * A break statement is
  353.                          * simply compiled as a jump
  354.                          * to this label.  This label
  355.                          * is set in the routine that
  356.                          * generates code for a loop
  357.                          * of some kind */
  358. LabSYMVia_t                     ContinueLabel;    /* similar to BreakLabel */
  359. InstListVia_t                   GlobalCodes;    /* very important - this is
  360.                          * the list of 68k
  361.                          * instruction records into
  362.                          * which code is generated.
  363.                          * Harvest C currently uses
  364.                          * no intermediate
  365.                          * representation for
  366.                          * generated code. The parser
  367.                          * creates a tree
  368.                          * representation of C
  369.                          * declarations and
  370.                          * expressions.  The code
  371.                          * generator converts this
  372.                          * tree into data structures
  373.                          * representing 68000 machine
  374.                          * instructions and assembler
  375.                          * directives, storing them
  376.                          * in this list.  This list
  377.                          * is then either dumped as
  378.                          * assembly source or as an
  379.                          * MPW linker file. */
  380. InstVia_t                       LinkInst;    /* The pointer to the
  381.                          * instruction record for the
  382.                          * link instruction for the
  383.                          * function being compiled.
  384.                          * The constant contained
  385.                          * herein may be modified
  386.                          * during compilation to
  387.                          * allocate more space on the
  388.                          * stack */
  389. EString_t                       InitDataAcc;    /* used for accumulating data
  390.                          * for an initializer */
  391. int                             InitDataAccIndex;    /* index used for
  392.                              * accumulating
  393.                              * initializer data */
  394. int                             InitDataAccSize;
  395.  
  396.  
  397. EString_t
  398. MakeEString(char *s)
  399. {
  400. #ifdef OLDMEM
  401.     static char                    *holdit;
  402.     holdit = s;
  403.     return &holdit;
  404. #else
  405.     return s;
  406. #endif
  407. }
  408.  
  409. MemReq_t
  410. Ealloc(unsigned long size)
  411. {
  412. #ifdef OLDMEM
  413.     MemReq_t                        tmp;
  414.     tmp = (MemReq_t) NewHandle(size);
  415.     return tmp;
  416. #else
  417.     return (MemReq_t) icemalloc(size);
  418. #endif
  419. }
  420.  
  421. void
  422. Efree(MemReq_t mem)
  423. {
  424.     if (!mem)
  425.         return;
  426. #ifdef OLDMEM
  427.     DisposHandle(mem);
  428. #else
  429.     icefree(mem);
  430. #endif
  431. }
  432.  
  433. EString_t
  434. AllocString(EString_t tmpstring)
  435. {
  436.     /*
  437.      * Moves the string argument into dynamically allocated memory, and
  438.      * returns a pointer to that string.  Basically, returns a copy of its
  439.      * arg.
  440.      */
  441.     EString_t                       copy;
  442.     copy = NULL;
  443.     if (tmpstring) {
  444.     /*
  445.      * Danger! Should we hlock tmpstring ?  If so, how do we know that it
  446.      * is a Memory Manager allocated handle ??
  447.      */
  448.     copy = Ealloc(1 + strlen(Via(tmpstring)));
  449. #ifdef OLDMEM
  450.     HLock((Handle) copy);
  451. #endif
  452.     strcpy(Via(copy), Via(tmpstring));
  453. #ifdef OLDMEM
  454.     HUnlock((Handle) copy);
  455. #endif
  456.     }
  457.     return copy;
  458. }
  459.  
  460. static SysEnvRec                theWorld;
  461.  
  462. GenericFileVia_t
  463. OpenGenericFile(char *name, short volrefnum, long dirID, char *mode, int iswind)
  464. /* name must be a C string not a Pascal string */
  465. {
  466.     GenericFileVia_t                result = NULL;
  467.     extern GenericFileVia_t         RawGenericFile(void);
  468.     char                            pname[64];
  469.     int                             bad;
  470.     short                           refnum;
  471.     strcpy(pname, name);
  472.     c2pstr(pname);
  473.     if (iswind) {
  474.     result = RawGenericFile();
  475.     } else {
  476.     if (!strcmp(mode, "w")) {
  477.         bad = HDelete(volrefnum, dirID, pname);
  478.         bad = HCreate(volrefnum, dirID, pname, 'Jn15', '????');
  479.         UserFileError(bad);
  480.         bad = HOpen(volrefnum, dirID, pname, 2, &refnum);
  481.         UserFileError(bad);
  482.     } else {
  483.         bad = HOpen(volrefnum, dirID, pname, 1, &refnum);
  484.         if (!bad) {
  485.         result = RawGenericFile();
  486.         strcpy(Via(result)->name, name);
  487.         c2pstr(Via(result)->name);
  488.         Via(result)->volrefnum = volrefnum;
  489.         Via(result)->endfound = 0;
  490.         Via(result)->dirID = dirID;
  491.         Via(result)->refnum = refnum;
  492.         Via(result)->buffersize = 10000;
  493.         Via(result)->buffer = Ealloc(Via(result)->buffersize);
  494.         Via(result)->bufferindex = 0;
  495.         Via(result)->errval = 0;
  496.         FillGFileBuffer(result);
  497.         if (!strcmp(mode, "w"))
  498.             Via(result)->perm = 2;
  499.         else
  500.             Via(result)->perm = 1;
  501.         } else
  502.         return NULL;
  503.     }
  504.     }
  505.     return result;
  506. }
  507.  
  508. int
  509. OpenInput(char *filename, int volrefnum, long dirID)
  510. {
  511.     FILE *                thefile;
  512.     thefile = fopenMAC(filename, volrefnum, dirID, "r");
  513.     if (thefile) {
  514.     strcpy(CurrentSRC.fname, filename);
  515.     CurrentSRC.where.io = thefile;
  516.     CurrentSRC.isIO = 1;
  517.     CurrentSRC.LineCount = 1;
  518.     CurrentSRC.memindex = 0;
  519.     CurrentSRC.PreprocLineDirty = 0;
  520.     CurrentSRC.alreadyincluded = NULL;
  521.     CurrentSRC.eol = 0;
  522.     CurrentSRC.NeedtoKill = NULL;
  523.     CurrentSRC.NumExtras = 0;
  524.     return 1;
  525.     } else {
  526.     FatalError2("File not found: ", filename);
  527.     return 0;
  528.     }
  529. }
  530.  
  531. int
  532. OpenError(char *filename, int volrefnum, long dirID)
  533. {
  534.     char                            tmpname[128];
  535.     int                             fndx;
  536.     fndx = 0;
  537.     strcpy(tmpname, filename);
  538.     while ((tmpname[fndx] != '.') && (tmpname[fndx])) {
  539.     fndx++;
  540.     }
  541.     tmpname[fndx] = 0;
  542.     strcat(tmpname, ".err");
  543.     errfile = OpenGenericFile(tmpname, volrefnum, dirID, "w", 1);
  544.     if (!errfile) {
  545.     FatalError("Couldn't open error file");
  546.     return 0;
  547.     }
  548.     return 1;
  549. }
  550.  
  551. int
  552. OpenOutput(char *filename, int volrefnum, long dirID)
  553. {
  554.     outfile = NULL;
  555.     return 1;
  556. }
  557.  
  558. void
  559. PushEnumTable(SymListVia_t syms)
  560. {
  561.     ScopesVia_t                     tempblock;
  562.     tempblock = Ealloc(sizeof(Scopes_t));
  563.     Via(tempblock)->Tags = NULL;
  564.     Via(tempblock)->Symbols = NULL;
  565.     Via(tempblock)->Labels = NULL;
  566.     Via(tempblock)->Enums = syms;
  567.     PushBlock(tempblock);
  568.     ExtraBlocks++;
  569. }
  570.  
  571. void
  572. PushSpaces(SymListVia_t syms, SymListVia_t tags, SymListVia_t labs)
  573. {
  574.     /* A short hand for building a block and then pushing it */
  575.     ScopesVia_t                     tempblock;
  576.     tempblock = Ealloc(sizeof(Scopes_t));
  577.     Via(tempblock)->Tags = tags;
  578.     Via(tempblock)->Symbols = syms;
  579.     Via(tempblock)->Labels = labs;
  580.     Via(tempblock)->Enums = NULL;
  581.     PushBlock(tempblock);
  582. }
  583.  
  584. GenericFileVia_t
  585. RawGenericFile(void)
  586. {
  587.     GenericFileVia_t                result;
  588.     result = Ealloc(sizeof(GenericFile_t));
  589.     Via(result)->theWind = NULL;
  590.     Via(result)->nonmac = NULL;
  591.     Via(result)->refnum = 0;
  592.     Via(result)->Fullness = 0;
  593.     Via(result)->buffersize = 0;
  594.     Via(result)->bufferindex = 0;
  595.     Via(result)->endfound = 0;
  596.     Via(result)->volrefnum = 0;
  597.     Via(result)->dirID = 0;
  598.     Via(result)->fpos = 0;
  599.     Via(result)->perm = 0;
  600.     Via(result)->buffer = NULL;
  601.     return result;
  602. }
  603.  
  604. void
  605. PutFileOnHold(FILE * f)
  606. {
  607. #ifdef Undefined
  608.     long                            fpos;
  609.     int                             bad;
  610.     if (f) {
  611.     if (Via(f)->refnum) {
  612.         bad = GetFPos(Via(f)->refnum, &fpos);
  613.         UserFileError(bad);
  614.         Via(f)->fpos = fpos;
  615.         bad = FSClose(Via(f)->refnum);
  616.         UserFileError(bad);
  617.     }
  618.     }
  619. #endif
  620. }
  621.  
  622. void
  623. TakeFileOffHold(FILE * f)
  624. {
  625. #ifdef Undefined
  626.     int                             bad;
  627.     short                           refnum;
  628.     if (f) {
  629.     if (Via(f)->refnum) {
  630.         bad = HOpen(Via(f)->volrefnum, Via(f)->dirID, Via(f)->name, Via(f)->perm, &refnum);
  631.         UserFileError(bad);
  632.         Via(f)->refnum = refnum;
  633.         bad = SetFPos(refnum, 1, Via(f)->fpos);
  634.         UserFileError(bad);
  635.     }
  636.     }
  637. #endif
  638. }
  639.  
  640. void
  641. CloseGenericFile(GenericFileVia_t f)
  642. {
  643.     OSErr                           bad;
  644.     if (f) {
  645.     if (Via(f)->theWind) {
  646.         /* Doesn't really close the window */
  647.     } else {
  648.         if (Via(f)->refnum) {
  649.         bad = FSClose(Via(f)->refnum);
  650.         UserFileError(bad);
  651.         }
  652.     }
  653.     if (Via(f)->buffer)
  654.         Efree(Via(f)->buffer);
  655.     Efree(f);
  656.     }
  657. }
  658.  
  659. long
  660. FillGFileBuffer(GenericFileVia_t thef)
  661. /* For input files, this fills the buffer by reading the file */
  662. {
  663.     long                            count;
  664. #ifdef OLDMEM
  665.     HLock((Handle) Via(thef)->buffer);
  666. #endif
  667.     count = Via(thef)->buffersize;
  668.     Via(thef)->errval = FSRead(Via(thef)->refnum, &count, (char *) Via(Via(thef)->buffer));
  669.     if (Via(thef)->errval == -39) {
  670.     FSClose(Via(thef)->refnum);
  671.     Via(thef)->refnum = 0;
  672.     Via(thef)->errval = 0;
  673.     }
  674.     Via(thef)->Fullness = count;
  675.     Via(thef)->bufferindex = 0;
  676. #ifdef OLDMEM
  677.     HUnlock((Handle) Via(thef)->buffer);
  678. #endif    
  679.     return count;
  680. }
  681.  
  682. int
  683. GetCGenericFile(GenericFileVia_t f)
  684. {
  685.     int                             c;
  686.     if (Via(f)->endfound)
  687.     return EOF;
  688.     if (Via(f)->bufferindex >= Via(f)->Fullness)
  689.     FillGFileBuffer(f);
  690.     if (!Via(f)->Fullness)
  691.     Via(f)->errval = -1;
  692.     c = Via(Via(f)->buffer)[Via(f)->bufferindex++];
  693.     if (Via(f)->errval) {
  694.     c = ' ';
  695.     Via(f)->endfound = 1;
  696.     }
  697.     return c;
  698. }
  699.  
  700. void
  701. GenericGetLine(GenericFileVia_t thef, char *buf)
  702. {
  703.     short                           c;
  704.     int                             done = 0;
  705.     do {
  706.     c = GetCGenericFile(thef);
  707.     switch (c) {
  708.     case EOF:
  709.     case '\n':
  710.         *buf = 0;
  711.         done = 1;
  712.         break;
  713.     default:
  714.         *buf = c;
  715.         buf++;
  716.     }
  717.     } while (!done);
  718. }
  719.  
  720. void
  721. EachFileInit(void)
  722. {
  723.     InitTypes();
  724.     InitPPTable();
  725.     DiscardedFunctionCall = 0;
  726.     ParserStrings = RawStringPool(1000);
  727.     InitLocAM();
  728.     GlobalCodes = RawInstructionList();
  729.     CurrentBlock = NULL;
  730.     TP_defnames = RawTable(113);
  731.     SegmentNames = RawLabTable();
  732.     CurrentSegmentLabel = NextFuncSegment = LabTableAdd(SegmentNames, "Main");
  733.     gAllDone = 0;
  734.     gAbortCompile = 0;
  735.     PPSP = 0;
  736.     PPStatus = 0;
  737.     NumErrors = 0;
  738.     NumWarnings = 0;
  739.     AttemptWarnings = 0;
  740.     InitDataAccIndex = 0;
  741.     InitDataAccSize = 0;
  742.     TokenOnDeck = 0;
  743.     SumGlobals = 0;
  744.     SumGlobalSpace = 0;
  745.     CountFunctions = 0;
  746.     CountSwitch = 0;
  747.     CountIncludes = 0;
  748.  
  749.     ExtraBlocks = 0;
  750.     HalUniqs = NULL;
  751.  
  752.     T_CountPreprocCondits = 0;
  753.     T_PreprocSubsts = 0;
  754.     T_PreprocBefore = 0;
  755.     T_PreprocAfter = 0;
  756.     T_CommentBytes = 0;
  757.     T_StmtCount = 0;
  758.     T_CountIdentifiers = 0;
  759.     T_TotalIdentifierLength = 0;
  760.     T_CountCasts = 0;
  761.     T_CountComments = 0;
  762.  
  763.     HalTotalOperands = 0;
  764.     HalTotalOperators = 0;
  765.     HalUniqOperands = 0;
  766.     HalUniqOperators = 0;
  767.     PreprocSymbolCount = 0;
  768.     InitDataAcc = (EString_t) Ealloc(MAXINITDATA);
  769.  
  770.     OddGlobal = 0;
  771.     DuplicateStringLits = 0;
  772.     SRCStack = NULL;
  773.     FloatList = NULL;
  774.     LinkInst = NULL;
  775.     LastSwitchExpression = NULL;
  776.     NextLitLabel = 1;
  777.     NextEccLabel = 1;
  778.     FunctionLastLabel = NULL;
  779.     ParamList = NULL;
  780.     SpillList = NULL;
  781.     outfile = NULL;
  782.     HashCollisions = 0;
  783.     TotalLines = 0;
  784.     InPreprocIf = 0;
  785.     EnumBeingDeclared = 0;
  786.     FunctionBeingDefined = NULL;
  787.     FunctionReturnCount = 0;
  788.     NextTempFloatReg = 0;
  789.     NextTempDataReg = 0;
  790.     NextTempAddrReg = 0;
  791.     HashCount = 0;
  792.     AddDefine("MC68000", MakeEString("1"));
  793.     AddDefine("mc68000", MakeEString("1"));
  794.     AddDefine("m68k", MakeEString("1"));
  795.     AddDefine("macintosh", MakeEString("1"));
  796.     AddDefine("applec", MakeEString("1"));    /* pretend like we're MPW */
  797.     AddDefine("__HARVESTC__", MakeEString("1"));    /* pretend like we're MPW */
  798.     AddDefine("__STDC__", MakeEString("0"));    /* because MPW does it this
  799.                          * way */
  800.     if (gProject) {
  801.         if (gProject->itsOptions->useMC68881)
  802.             AddDefine("mc68881", MakeEString("1"));
  803.     }
  804.     Labels = RawLabTable();
  805.     SetupLibLabels();
  806.     StaticTable = RawTable(23);
  807.     StringLits = RawTable(101);
  808.     TagsTable = RawTable(113);
  809.     LabelsTable = RawTable(23);
  810.     GlobalSymbolTable = RawTable(809);
  811.     PushSpaces(GlobalSymbolTable, TagsTable, LabelsTable);
  812. }
  813.  
  814. InFileVia_t
  815. Init(int argc, char **argv)
  816. {
  817.     InFileVia_t                     resultlist;
  818.     char                            volname[64];
  819.  
  820.     EachFileInit();
  821.  
  822.     /* Floating point sizes */
  823.     SizeOfDouble = 8;
  824.     SizeOfFloat = 4;
  825.     SizeOfLongDouble = 10;
  826.  
  827.     MacroValue = Ealloc(MAXMACROLENGTH);    /* used for macro expansion */
  828.  
  829.     BuildKWHash();        /* builds a hash table for key words */
  830. }
  831.  
  832. void                            FreeSymbolList(SymListVia_t, int);
  833.  
  834. void
  835. FreeLab(LabSYMVia_t cur)
  836. {
  837.     if (cur) {
  838.     FreeLab(Via(cur)->left);
  839.     FreeLab(Via(cur)->right);
  840.     Efree(cur);
  841.     }
  842. }
  843.  
  844. void
  845. FreeLabSymbolList(LabSymListVia_t table)
  846. {
  847.     if (table) {
  848.     FreeLab(Via(table)->_head);
  849.     Efree(table);
  850.     }
  851. }
  852.  
  853. #undef FREEMEM
  854.  
  855. void
  856. RememberSwitch(LabSymListVia_t tab)
  857. {
  858.     Switches[CountSwitch++] = tab;
  859. }
  860.  
  861. void
  862. FreeSwitches(void)
  863. {
  864.     while (CountSwitch > 0) {
  865.     FreeLabSymbolList(Switches[--CountSwitch]);
  866.     }
  867. }
  868.  
  869. void
  870. FreeParamList(ParamRecVia_t head)
  871. {
  872.     if (head) {
  873.     FreeParamList(Via(head)->next);
  874.     Efree(head);
  875.     }
  876. }
  877.  
  878. void
  879. KillCodesList(InstListVia_t Codes)
  880. {
  881.     InstVia_t                       cur;
  882.     InstVia_t                       next;
  883.     if (Codes) {
  884.     cur = Via(Codes)->head;
  885.     while (cur) {
  886.         next = Via(cur)->next;
  887.         /* All Loc records are separately freed */
  888.         Efree(cur);
  889.         cur = next;
  890.     }
  891.     Via(Codes)->head = Via(Codes)->tail = NULL;
  892.     Via(Codes)->count = 0;
  893.     Via(Codes)->PendingLabel = NULL;
  894.     /*
  895.      * We don't free the list itself because we usually use this merely
  896.      * to "empty" the code list
  897.      */
  898.     }
  899. }
  900.  
  901. void
  902. OneFileCleanUp(void)
  903. {
  904.     long                            x;
  905.     long                            y;
  906.     /*
  907.      * Here will go all memory deallocation which needs to be done between
  908.      * files.
  909.      */
  910.     CloseGenericFile(errfile);
  911.     CloseGenericFile(outfile);
  912.     while (CurrentBlock)
  913.     PopBlock();
  914.     FreeSymbolList(GlobalSymbolTable, 1);
  915.     FreeSymbolList(TP_defnames, 1);
  916.     FreeParamList(ParamList);
  917.     FreeSymbolList(StringLits, 1);
  918.     FreeSymbolList(StaticTable, 1);
  919.     FreeSymbolList(TagsTable, 1);
  920.     FreeSymbolList(LabelsTable, 1);
  921.     FreeLabSymbolList(SegmentNames);
  922.     FreeLabSymbolList(Labels);
  923.     FreeSwitches();
  924.     FreeTypeRecords();
  925.     Efree(InitDataAcc);
  926.     KillFloatList(FloatList);
  927.     KillCodesList(GlobalCodes);
  928.     KillAllLocations();
  929.     KillSpillList();
  930.     KillStringPool(ParserStrings);
  931.     SpillList = NULL;
  932.     Efree(GlobalCodes);
  933.     FreePPSymbolList(Defines);
  934.     y = MaxMem(&x);
  935. }
  936.  
  937. int
  938. UserFileError(int err)
  939. {
  940.     char                            mesg[80];
  941.     if (err) {
  942.     sprintf(mesg, "Error # %d\n", err);
  943.     c2pstr(mesg);
  944.     SysBeep(1);
  945.     } else {
  946.     return 0;
  947.     }
  948. }
  949.  
  950. void
  951. CleanUp(void)
  952. {
  953.     FreeTypeRecords();
  954.     Efree(MacroValue);
  955.     FreePPSymbolList(Defines);
  956. }
  957.  
  958. #ifdef OLDCODE
  959. void
  960. OneFileReport(void)
  961. {
  962.     /* This routine reports a number of software metrics */
  963.     char                            msg[256];
  964.     if (Opts.metrics) {
  965.     T_CountCasts += CurrentSRC.CountCasts;
  966.     T_TotalIdentifierLength += CurrentSRC.TotalIdentifierLength;
  967.     T_CountIdentifiers += CurrentSRC.CountIdentifiers;
  968.     T_PreprocSubsts += CurrentSRC.PreprocSubsts;
  969.     T_PreprocBefore += CurrentSRC.PreprocBefore;
  970.     T_PreprocAfter += CurrentSRC.PreprocAfter;
  971.     T_CountPreprocCondits += CurrentSRC.CountPreprocCondits;
  972.     T_StmtCount += CurrentSRC.StmtCount;
  973.     T_CountComments += CurrentSRC.CountComments;
  974.     T_CommentBytes += CurrentSRC.CommentBytes;
  975.     sprintf(msg, "\nNumber of lines = %d\n", CurrentSRC.LineCount - 1);
  976.     UserMesg(msg);
  977.     sprintf(msg, "Number of chars = %d\n", CurrentSRC.CharCount - 1);
  978.     UserMesg(msg);
  979.     sprintf(msg, "Count casts = %d\n", CurrentSRC.CountCasts);
  980.     UserMesg(msg);
  981.     if (CurrentSRC.CountIdentifiers) {
  982.         sprintf(msg, "Avg id length = %g\n", (double) CurrentSRC.TotalIdentifierLength / CurrentSRC.CountIdentifiers);
  983.         UserMesg(msg);
  984.     }
  985.     sprintf(msg, "Preproc Substitutions = %d\n", CurrentSRC.PreprocSubsts);
  986.     UserMesg(msg);
  987.     if (CurrentSRC.PreprocSubsts && CurrentSRC.PreprocBefore) {
  988.         sprintf(msg, "Preproc Expansion factor = %g\n", (double) CurrentSRC.PreprocAfter / CurrentSRC.PreprocBefore);
  989.         UserMesg(msg);
  990.     }
  991.     sprintf(msg, "Preproc conditional compilations = %d\n", CurrentSRC.CountPreprocCondits);
  992.     UserMesg(msg);
  993.     sprintf(msg, "Count statements = %d\n", CurrentSRC.StmtCount);
  994.     UserMesg(msg);
  995.     sprintf(msg, "Count Comments = %d\n", CurrentSRC.CountComments);
  996.     UserMesg(msg);
  997.     sprintf(msg, "Bytes of comments = %d\n", CurrentSRC.CommentBytes);
  998.     UserMesg(msg);
  999.     }
  1000. }
  1001.  
  1002. void
  1003. Report(void)
  1004. {
  1005.     /* This routine reports a number of software metrics */
  1006.     char                            msg[256];
  1007.     UserMesg("\n----- Summary -----\n");
  1008.     sprintf(msg, "Time of compilation = %d seconds\n", (EndingTime - StartingTime) / 60);
  1009.     UserMesg(msg);
  1010.     if (Opts.metrics) {
  1011.     sprintf(msg, "Count casts = %d\n", T_CountCasts);
  1012.     UserMesg(msg);
  1013.     sprintf(msg, "Avg id length = %g\n", (double) T_TotalIdentifierLength / T_CountIdentifiers);
  1014.     UserMesg(msg);
  1015.     sprintf(msg, "Preproc Substitutions = %d\n", T_PreprocSubsts);
  1016.     UserMesg(msg);
  1017.     if (T_PreprocSubsts && T_PreprocBefore) {
  1018.         sprintf(msg, "Preproc Expansion factor = %g\n", (double) T_PreprocAfter / T_PreprocBefore);
  1019.         UserMesg(msg);
  1020.     }
  1021.     sprintf(msg, "Preproc conditional compilations = %d\n", T_CountPreprocCondits);
  1022.     UserMesg(msg);
  1023.     sprintf(msg, "Count statements = %d\n", T_StmtCount);
  1024.     UserMesg(msg);
  1025.     sprintf(msg, "Count Comments = %d\n", T_CountComments);
  1026.     UserMesg(msg);
  1027.     sprintf(msg, "Bytes of comments = %d\n", T_CommentBytes);
  1028.     UserMesgCR(msg);
  1029.  
  1030.     sprintf(msg, "Count Global Syms = %d\n", (int) Via(GlobalSymbolTable)->count);
  1031.     UserMesg(msg);
  1032.     sprintf(msg, "Count string lits = %d\n", (int) Via(StringLits)->count);
  1033.     UserMesg(msg);
  1034.     sprintf(msg, "Count Dup string lits = %d\n", DuplicateStringLits);
  1035.     UserMesg(msg);
  1036.     sprintf(msg, "Num of errors = %d\n", NumErrors);
  1037.     UserMesg(msg);
  1038.     sprintf(msg, "Num of warnings = %d\n", NumWarnings);
  1039.     UserMesg(msg);
  1040.     sprintf(msg, "Attempted warnings = %d\n", AttemptWarnings);
  1041.     UserMesg(msg);
  1042.     sprintf(msg, "Total # of lines = %d\n", TotalLines);
  1043.     UserMesg(msg);
  1044.     sprintf(msg, "Number of #include directives = %d\n", CountIncludes);
  1045.     UserMesg(msg);
  1046.     sprintf(msg, "Total globals = %d\n", SumGlobals);
  1047.     UserMesg(msg);
  1048.     sprintf(msg, "Total global space = %d\n", SumGlobalSpace);
  1049.     sprintf(msg, "Number of functions = %d\n", CountFunctions);
  1050.     UserMesg(msg);
  1051.     {
  1052.         int                             ndx;
  1053.         double                          HalV, HalL;
  1054.         long                            HalN;
  1055.         ndx = 0;
  1056.         while (ndx < KEYWORDTABLESIZE) {
  1057.         if (KWTable[ndx].val) {
  1058.             if (KWTable[ndx].uses) {
  1059.             HalUniqOperators++;
  1060.             }
  1061.         }
  1062.         ndx++;
  1063.         }
  1064.         sprintf(msg, "Halstead metrics :\n");
  1065.         UserMesg(msg);
  1066.         sprintf(msg, "     Length : %d\n", HalN = HalTotalOperands + HalTotalOperators);
  1067.         UserMesg(msg);
  1068.         sprintf(msg, "     Volume : %g\n", (double) (HalV = HalN * (log2((double) (HalUniqOperands + HalUniqOperators)))));
  1069.         UserMesg(msg);
  1070.         sprintf(msg, "     Level  : %g\n", (double) (HalL = (2 / (double) HalUniqOperators) * (HalUniqOperands / (double) HalTotalOperands)));
  1071.         UserMesg(msg);
  1072.         sprintf(msg, "     Ment D : %g\n", (HalV / HalL));
  1073.         UserMesg(msg);
  1074.     }
  1075.     }
  1076. }
  1077. #endif
  1078.  
  1079. int
  1080. ReInit(char *filename, int volrefnum, long dirID)
  1081. {
  1082.     EachFileInit();
  1083.     if (!OpenInput(filename, volrefnum, dirID))
  1084.     return 0;
  1085.     if (!OpenOutput(filename, volrefnum, dirID)) {
  1086.     PopSRC();
  1087.     return 0;
  1088.     }
  1089.     if (!OpenError(filename, volrefnum, dirID)) {
  1090.     PopSRC();
  1091.     CloseGenericFile(errfile);
  1092.     return 0;
  1093.     }
  1094.     CurrentSRC.ExtraChar[0] = GetCharacter();
  1095.     CurrentSRC.NumExtras = 1;
  1096.     return 1;
  1097. }
  1098.  
  1099. #ifdef SRC_COMM
  1100. void
  1101. PreprocOnly(char *name, short volrefnum, long dirID)
  1102. {
  1103.     Codigo_t                        result;
  1104.     char                            buf[256];
  1105.     OpenInput(name, volrefnum, dirID);
  1106.     OpenOutput(name, volrefnum, dirID);
  1107.     OpenError(name, volrefnum, dirID);
  1108.     sprintf(buf, "#line %d \"%s\"\n", CurrentSRC.LineCount, CurrentSRC.fname);
  1109.     Output(buf, outfile);
  1110.     while (!gAllDone) {
  1111.     result = GetToken();
  1112.     if (!gAllDone) {
  1113.         switch (result) {
  1114.         case CHARCONSTANT:
  1115.         /* Call to DumpCharK deleted here. */
  1116.         sprintf(buf, " %d", LastIntegerConstant);
  1117.         Output(buf, outfile);
  1118.         break;
  1119.         case PASCSTRING_LITERAL:
  1120.         case STRING_LITERAL:
  1121.         DumpStringLit((LastToken), outfile);
  1122.         break;
  1123.         default:
  1124.         sprintf(buf, " %s", LastToken);
  1125.         Output(buf, outfile);
  1126.         break;
  1127.         }
  1128.     }
  1129.     }
  1130. }
  1131.  
  1132. #endif
  1133.  
  1134.