home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / OUTCO386.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-06  |  18.5 KB  |  729 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1996, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and sources are distributed along with any executables derived from them.
  11.  *
  12.  * The author is not responsible for damages, either direct or consequential,
  13.  * that may arise from use of this software.
  14.  *
  15.  * v1.5 August 1996
  16.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  17.  *
  18.  * Credits to Mathew Brandt for original K&R C compiler
  19.  *
  20.  */
  21. #include        <stdio.h>
  22. #include        "expr.h"
  23. #include        "c.h"
  24. #include        "gen.h"
  25. #include        "cglbdec.h"
  26.  
  27. typedef struct muldiv {
  28.         struct muldiv * link;
  29.         long value;
  30.         double floatvalue;
  31.         int size;
  32.         int label;
  33. } MULDIV;
  34. /*      variable initialization         */
  35. extern HASHREC **globalhash;
  36. extern int phiused;
  37.  
  38. enum e_gt { nogen, bytegen, wordgen, longgen, floatgen, doublegen, longdoublegen, storagegen,srrefgen };
  39. enum e_sg { noseg, codeseg, dataseg,bssxseg,startupxseg,rundownxseg,cppxseg };
  40.  
  41. extern int    prm_asmfile;
  42. extern int prm_lines;
  43. extern FILE *tempfil;
  44.  
  45. MULDIV *muldivlink = 0;
  46. int           gentype = nogen;        /* Current DC type */
  47. int           curseg = noseg;        /* Current seg */
  48. int        outcol = 0;                /* Curront col (roughly) */
  49. int newlabel;
  50. int needpointer;
  51. static int phiput;
  52. /* Init module */
  53. void outcodeini(void)
  54. {
  55.     gentype = nogen;
  56.     curseg = noseg;
  57.     outcol = 0;
  58.     newlabel = FALSE;
  59.     phiput = FALSE;
  60. }
  61. /* List of opcodes
  62.  * This list MUST be in the same order as the op_ enums 
  63.  */
  64. char * oplst[] = { "LINE#", "LABEL","SEQ@","DB",
  65.     "ADD", "AND", "CALL", "CLD", "CMP", "CMPSB", "CMPSW", "CMPSD",
  66.     "CWD", "CBW", "CBD", "DEC",
  67.     "DIV", "IDIV", "IMUL", "INC", "JB", "JBE","JE", "JL",
  68.     "JLE", "JNC", "JA", "JNE", "JGE", "JG", "JMP", "LEA", "LODSB",
  69.     "LODSW", "LODSD",
  70.     "MOV", "MOVSB", "MOVSW", "MOVSD", "MOVSX", "MOVZX", "MUL", 
  71.     "NEG", "NOT", "OR", "POP", "PUSH", "REP", "REPNZ", "REPZ", 
  72.     "RET", "SAHF", "SAL", "SAR", "SCASB", "SCASW", "SCASD",
  73.     "SHR", "SHL", "STD", "STOSB", "STOSW", "STOSD", "SUB",
  74.     "TEST", "XCHG", "XOR", "DD", "PUSHFD", "IRETD", "PUSHAD", "POPAD",
  75.     "FADD", "FIADD", "FCHS", "FCOM", "FCOMP", "FCOMPP",
  76.     "FDIV", "FIDIV", "FICOM", "FICOMP", "FILD", "FIST", "FISTP",
  77.     "FLD", "FLDZ", "FMUL", "FIMUL", "FPREM", "FSCALE", "FST", "FSTP",
  78.     "FSTCW", "FSTSW", "FSUB", "FISUB", "FTST", "FXCH", "FWAIT"
  79.     };
  80. /*
  81.  * Register a fixup 
  82.  */
  83. /* Put an opcode
  84.  */
  85. void putop(int op)
  86. {       
  87.     if (op > op_fwait)
  88.     diag("illegal opcode.");
  89.     else
  90.       fprintf(tempfil,"\t%s",oplst[op]);
  91. }
  92.  
  93. void putconst(ENODE *offset)
  94. /*
  95.  *      put a constant to the tempfil file.
  96.  */
  97. {       switch( offset->nodetype )
  98.                 {
  99.                                 case en_autoreg:
  100.                 case en_autocon:
  101.                 case en_icon:
  102.                                 case en_acon:
  103.                         fprintf(tempfil,"0%lXH",offset->v.i);
  104.                         break;
  105.                                 case en_rcon:
  106.                                                 fprintf(tempfil,"%f",offset->v.f);
  107.                                                 break;
  108.                                 case en_nalabcon:
  109.                         fprintf(tempfil,"L_%d",offset->v.i);
  110.                         break;
  111.                 case en_labcon:
  112.                         fprintf(tempfil,"CS:L_%d",offset->v.i);
  113.                         break;
  114.                                 case en_napccon:
  115.                 case en_nacon:
  116.                         fprintf(tempfil,"%s",offset->v.p[0]);
  117.                         break;
  118.                 case en_add:
  119.                         putconst(offset->v.p[0]);
  120.                         fprintf(tempfil,"+");
  121.                         putconst(offset->v.p[1]);
  122.                         break;
  123.                 case en_sub:
  124.                         putconst(offset->v.p[0]);
  125.                         fprintf(tempfil,"-");
  126.                         putconst(offset->v.p[1]);
  127.                         break;
  128.                 case en_uminus:
  129.                         fprintf(tempfil,"-");
  130.                         putconst(offset->v.p[0]);
  131.                         break;
  132.                 default:
  133.                         diag("illegal constant node.");
  134.                         break;
  135.                 }
  136. }
  137. void putlen(int l)
  138. /*
  139.  *      append the length field to an instruction.
  140.  */
  141.     if (l!= 10 && l != 8 && l != 6 && l != 4 && l != 1 && l != 2 && l != 0)
  142.      diag("illegal length field.");
  143. }
  144. void putsizedreg(char *string, int reg, int size)
  145. {
  146.     static char *byteregs[] = { "AL","CL","DL","BL","*A","*C","*D","*B" };
  147.     static char *wordregs[] = { "AX", "CX", "DX","BX","SP","BP","SI","DI"  };
  148.     static char *longregs[] = { "EAX", "ECX", "EDX","EBX","ESP","EBP","ESI","EDI" };
  149.   if (size == 4)
  150.         fprintf(tempfil,string,longregs[reg]);
  151.     else if (size == 1)
  152.         fprintf(tempfil,string,byteregs[reg]);
  153.         else
  154.             fprintf(tempfil,string,wordregs[reg]);
  155. }
  156. void pointersize(int size)
  157. {
  158. //    if (needpointer)
  159.         switch (size) {        
  160.             case 10:
  161.                 fprintf(tempfil,"TWORD PTR ");
  162.                 break;
  163.             case 8:
  164.                 fprintf(tempfil,"QWORD PTR ");
  165.                 break;
  166.             case 6:
  167.             case 4:
  168.                 fprintf(tempfil,"DWORD PTR ");
  169.                 break;
  170.             case 2:
  171.                 fprintf(tempfil,"WORD PTR ");
  172.                 break;
  173.             case 1:
  174.                 fprintf(tempfil,"BYTE PTR ");
  175.                 break;
  176.             default:
  177.                 diag("Bad pointer");
  178.         }    
  179. }
  180. void putamode(AMODE *ap,int size)
  181. /*
  182.  *      tempfil a general addressing mode.
  183.  */
  184. {       switch( ap->mode )
  185.                 {
  186.                                 case am_cs:
  187.                                                 fprintf(tempfil,"CS");
  188.                                                 break;
  189.                 case am_immed:
  190.                                                 if (size && (ap->offset->nodetype == en_labcon 
  191.                                                         || ap->offset->nodetype == en_nacon
  192.                                                         || ap->offset->nodetype == en_napccon
  193.                                                         || ap->offset->nodetype == en_nalabcon))
  194.                                                     fprintf(tempfil,"OFFSET ");
  195.                         putconst(ap->offset);
  196.                                                 break;
  197.                 case am_direct:
  198.                                                 pointersize(size);
  199.                                                 fputc('[',tempfil);
  200.                         putconst(ap->offset);
  201.                                                 fputc(']',tempfil);
  202.                         break;
  203.                 case am_dreg:
  204.                                                 putsizedreg("%s",ap->preg,size);
  205.                                                 break;
  206.                                 case am_freg:
  207.                                                 fprintf(tempfil,"ST(%d)",ap->preg);
  208.                                                 break;
  209.                                 case am_indisp:
  210.                                                 pointersize(size);
  211.                                                 putsizedreg("[%s",ap->preg,4);
  212.                                                 if (ap->offset) {
  213.                                                     fputc('+',tempfil);
  214.                                                     putconst(ap->offset);
  215.                                                 }
  216.                                                 fputc(']',tempfil);
  217.                                                 break;
  218.                                 case am_indispscale:
  219.                                                     pointersize(size);
  220.                                                 putsizedreg("[%s+",ap->preg,4);
  221.                                                 putsizedreg("%s",ap->sreg,4);
  222.                                                 if (ap->scale != 1)
  223.                                                     fprintf(tempfil,"*0%XH",ap->scale);
  224.                                                 if (ap->offset) {
  225.                                                     fputc('+',tempfil);
  226.                                                     putconst(ap->offset);
  227.                                                 }
  228.                                                 fputc(']',tempfil);
  229.                                                 break;
  230.                 default:
  231.                         diag("illegal address mode.");
  232.                         break;
  233.                 }
  234. }
  235.  
  236. void put_code(int op,int len,int len2,AMODE *aps,AMODE *apd)
  237. /*
  238.  *      tempfil a generic instruction.
  239.  */
  240. {       
  241.         if (!prm_asmfile)    
  242.             return;
  243.         if (op == op_line) {
  244.             if (!prm_lines)
  245.                 return;
  246.             fprintf(tempfil,";\n; Line %d:\t%s\n;\n",len,(char *)aps);
  247.             return;
  248.         }
  249.         needpointer = (len != len2) || ((!aps || aps->mode !=am_dreg) && (!apd || apd->mode !=am_dreg));
  250.         putop(op);
  251.         putlen(len);
  252.         if( aps != 0 )
  253.                 {
  254.                 fprintf(tempfil,"\t");
  255.         putamode(aps,len);
  256.                 if( apd != 0 )
  257.                         {
  258.                         fprintf(tempfil,",");
  259.                         putamode(apd,len2);
  260.                         }
  261.                 }
  262.   fprintf(tempfil,"\n");
  263. }
  264.  
  265. void gen_strlab(char *s)
  266. /*
  267.  *      generate a named label.
  268.  */
  269. {
  270.         if (prm_asmfile)
  271.             if (curseg == dataseg || curseg == bssxseg) {
  272.                 newlabel = TRUE;
  273.                  fprintf(tempfil,"\n%s",s);
  274.                 outcol = strlen(s)+1;
  275.             }
  276.             else
  277.         fprintf(tempfil,"%s:\n",s);
  278. }
  279.  
  280. void put_label(int lab)
  281. /*
  282.  *      tempfil a compiler generated label.
  283.  */
  284. {
  285.        if (prm_asmfile)
  286.                     fprintf(tempfil,"L_%d:\n",lab);
  287. }
  288.  
  289. void genfloat(float val)
  290. /*
  291.  * Output a float value
  292.  */
  293. {         if (prm_asmfile)
  294.         if( gentype == floatgen && outcol < 60) {
  295.                 fprintf(tempfil,",%f",val);
  296.                 outcol += 8;
  297.                 }
  298.         else    {
  299.                                 if (!newlabel)
  300.                                     nl();
  301.                                 else newlabel = FALSE;
  302.                 fprintf(tempfil,"\tDD\t%f",val);
  303.                 gentype = floatgen;
  304.                 outcol = 19;
  305.                 }
  306. }
  307.  
  308. void gendouble(double val)
  309. /*
  310.  * Output a double value
  311.  */
  312. {         if (prm_asmfile)
  313.         if( gentype == doublegen && outcol < 60) {
  314.                 fprintf(tempfil,",%f",val);
  315.                 outcol += 8;
  316.                 }
  317.         else    {
  318.                                 if (!newlabel)
  319.                                     nl();
  320.                                 else newlabel = FALSE;
  321.                 fprintf(tempfil,"\tDQ\t%f",val);
  322.                 gentype = doublegen;
  323.                 outcol = 19;
  324.                 }
  325. }
  326. void genlongdouble(double val)
  327. /*
  328.  * Output a double value
  329.  */
  330. {         if (prm_asmfile)
  331.         if( gentype == longdoublegen && outcol < 60) {
  332.                 fprintf(tempfil,",%f",val);
  333.                 outcol += 8;
  334.                 }
  335.         else    {
  336.                                 if (!newlabel)
  337.                                     nl();
  338.                                 else newlabel = FALSE;
  339.                 fprintf(tempfil,"\tDT\t%f",val);
  340.                 gentype = longdoublegen;
  341.                 outcol = 19;
  342.                 }
  343. }
  344.  
  345. void genbyte(long val)
  346. /*
  347.  * Output a byte value
  348.  */
  349. {         if (prm_asmfile)
  350.         if( gentype == bytegen && outcol < 60) {
  351.                 fprintf(tempfil,",0%XH",val & 0x00ff);
  352.                 outcol += 4;
  353.                 }
  354.         else    {
  355.                                 if (!newlabel)
  356.                                     nl();
  357.                                 else newlabel = FALSE;
  358.                 fprintf(tempfil,"\tDB\t0%XH",val & 0x00ff);
  359.                 gentype = bytegen;
  360.                 outcol = 19;
  361.                 }
  362. }
  363.  
  364. void genword(long val)
  365. /*
  366.  * Output a word value
  367.  */
  368. {     if (prm_asmfile)
  369.         if( gentype == wordgen && outcol < 58) {
  370.                 fprintf(tempfil,",0%XH",val & 0x0ffff);
  371.                 outcol += 6;
  372.                 }
  373.         else    {
  374.                                 if (!newlabel)
  375.                                     nl();
  376.                                 else newlabel = FALSE;
  377.                 fprintf(tempfil,"\tDW\t0%XH",val & 0x0ffff);
  378.                 gentype = wordgen;
  379.                 outcol = 21;
  380.                 }
  381. }
  382.  
  383. void genlong(long val)
  384. /*
  385.  * Output a long value
  386.  */
  387. {     if (prm_asmfile)
  388.         if( gentype == longgen && outcol < 56) {
  389.                 fprintf(tempfil,",0%lXH",val);
  390.                 outcol += 10;
  391.                 }
  392.         else    {
  393.                                 if (!newlabel)
  394.                                     nl();
  395.                                 else newlabel = FALSE;
  396.                 fprintf(tempfil,"\tDD\t0%lXH",val);
  397.                 gentype = longgen;
  398.                 outcol = 25;
  399.                 }
  400. }
  401.  
  402. void gensrref(char *name, int val)
  403. {
  404.             if (prm_asmfile)
  405.         if( gentype == srrefgen && outcol < 56) {
  406.                 fprintf(tempfil,",%s,%d",name,val);
  407.                 outcol += strlen(name)+1;
  408.                 }
  409.         else    {
  410.                 nl();
  411.                 fprintf(tempfil,"\tDD\t%s,%d",name,val);
  412.                 gentype = srrefgen;
  413.                 outcol = 25;
  414.                 }
  415. }
  416. void genref(SYM *sp,int offset)
  417. /*
  418.  * Output a reference to the data area (also gens fixups )
  419.  */
  420. {       char    sign;
  421.             char buf[40];
  422.         if( offset < 0) {
  423.                 sign = '-';
  424.                 offset = -offset;
  425.                 }
  426.         else
  427.                 sign = '+';
  428.             if (sp->storage_class == sc_static)
  429.                 sprintf(buf,"L_%d%c%d",sp->value.i,sign,offset);
  430.             else
  431.                 sprintf(buf,"%s%c%d",sp->name,sign,offset);
  432.             if (prm_asmfile) {
  433.         if( gentype == longgen && outcol < 55 - strlen(sp->name)) {
  434.                 fprintf(tempfil,",%s",buf);
  435.                 outcol += (11 + strlen(sp->name));
  436.                 }
  437.         else    {
  438.                                 if (!newlabel)
  439.                                     nl();
  440.                                 else newlabel = FALSE;
  441.                 fprintf(tempfil,"\tDD\t%s",buf);
  442.                 outcol = 26 + strlen(sp->name);
  443.                 gentype = longgen;
  444.                 }
  445.             }
  446. }
  447. void genpcref(SYM *sp,int offset)
  448. /*
  449.  * Output a reference to the code area (also gens fixups )
  450.  */
  451. {
  452.     genref(sp,offset);
  453. }
  454. void genstorage(int nbytes)
  455. /*
  456.  * Output bytes of storage
  457.  */
  458. {            if (prm_asmfile) {
  459.                                 if (!newlabel)
  460.                                     nl();
  461.                                 else newlabel = FALSE;
  462.         fprintf(tempfil,"\tDB\t0%XH DUP (?)",nbytes);
  463.                 outcol = 28;
  464.                 gentype = storagegen;
  465.             }
  466. }
  467.  
  468. void gen_labref(int n)
  469. /*
  470.  * Generate a reference to a label
  471.  */
  472. {            if (prm_asmfile)
  473.         if( gentype == longgen && outcol < 58) {
  474.                 fprintf(tempfil,",L_%d",n);
  475.                 outcol += 6;
  476.                 }
  477.         else    {
  478.                                 if (!newlabel)
  479.                                     nl();
  480.                                 else newlabel = FALSE;
  481.                 fprintf(tempfil,"\tDD\tL_%d",n);
  482.                 outcol = 22;
  483.                 gentype = longgen;
  484.                 }
  485. }
  486.  
  487. int     stringlit(char *s)
  488. /*
  489.  *      make s a string literal and return it's label number.
  490.  */
  491. {       struct slit     *lp;
  492.         ++global_flag;          /* always allocate from global space. */
  493.         lp = xalloc(sizeof(struct slit));
  494.         lp->label = nextlabel++;
  495.         lp->str = litlate(s);
  496.         lp->next = strtab;
  497.         strtab = lp;
  498.         --global_flag;
  499.         return lp->label;
  500. }
  501.  
  502. void dumplits(void)
  503. /*
  504.  *      dump the string literal pool.
  505.  */
  506. {       char            *cp;
  507.         while( strtab != 0) {
  508.                 cseg();
  509.                 nl();
  510.                 put_label(strtab->label);
  511.                 cp = strtab->str;
  512.                 while(*cp)
  513.                         genbyte(*cp++);
  514.                 genbyte(0);
  515.                 strtab = strtab->next;
  516.                 }
  517.         nl();
  518. }
  519.  
  520. void nl(void)
  521. /*
  522.  * New line
  523.  */
  524. {    if (prm_asmfile) {
  525.        if(outcol > 0) {
  526.                 fputc('\n',tempfil);
  527.                 outcol = 0;
  528.                 gentype = nogen;
  529.                 }
  530.              if (phiused && !phiput)
  531.                                 fputc(0x1f,outputFile);
  532.          }
  533. }
  534. /*
  535.  * Exit if from a special segment
  536.  */
  537. void exitseg(void)
  538. {
  539.     if (curseg == startupxseg) {
  540.         curseg = noseg;
  541.         fprintf(tempfil,"cstartup\tENDS\n");
  542.     }
  543.     else if (curseg == rundownxseg) {
  544.         curseg = noseg;
  545.         fprintf(tempfil,"crundown\tENDS\n");
  546.     }
  547.     else if (curseg == cppxseg) {
  548.         curseg = noseg;
  549.         fprintf(tempfil,"cppinit\tENDS\n");
  550.     }
  551. }
  552. /*
  553.  * Switch to cseg 
  554.  */
  555. void cseg(void)
  556. {            if (prm_asmfile)
  557.            if( curseg != codeseg) {
  558.                 nl();
  559.                                 exitseg();
  560.                 fprintf(tempfil,"\t.CODE\n");
  561.                 curseg = codeseg;
  562.                 }
  563. }
  564. /*
  565.  * Switch to deseg
  566.  */
  567. void dseg(void)
  568. {     if (prm_asmfile)  
  569.                 if( curseg != dataseg) {
  570.                 nl();
  571.                                 exitseg();
  572.                 fprintf(tempfil,"\t.DATA\n");
  573.                 curseg = dataseg;
  574.                 }
  575. }
  576. /*
  577.  * Switch to bssseg
  578.  */
  579. void bssseg(void)
  580. {     if (prm_asmfile)  
  581.                 if( curseg != bssxseg) {
  582.                 nl();
  583.                                 exitseg();
  584.                 fprintf(tempfil,"\t.DATA?\n");
  585.                 curseg = bssxseg;
  586.                 }
  587. }
  588. /*
  589.  * Switch to startupseg
  590.  */
  591. void startupseg(void)
  592. {     if (prm_asmfile)  
  593.                 if( curseg != startupxseg) {
  594.                 nl();
  595.                                 exitseg();    
  596.                 fprintf(tempfil,"cstartup\tSEGMENT USE32 PUBLIC DWORD \042INITDATA\042\n");
  597.                 curseg = startupxseg;
  598.                 }
  599. }
  600. /*
  601.  * Switch to rundownseg
  602.  */
  603. void rundownseg(void)
  604. {     if (prm_asmfile)  
  605.                 if( curseg != rundownxseg) {
  606.                 nl();
  607.                                 exitseg();
  608.                 fprintf(tempfil,"crundown\tSEGMENT USE32 PUBLIC DWORD \042EXITDATA\042\n");
  609.                 curseg = rundownxseg;
  610.                 }
  611. }
  612. void cppseg(void)
  613. {     if (prm_asmfile)  
  614.                 if( curseg != cppxseg) {
  615.                 nl();
  616.                                 exitseg();
  617.                 fprintf(tempfil,"cppinit\tSEGMENT USE32 PUBLIC DWORD \042CPPDATA\042\n");
  618.                 curseg = cppxseg;
  619.                 }
  620. }
  621. void gen_virtual(char *name)
  622. {
  623.     if (prm_asmfile) {
  624.         nl();
  625.         fprintf(tempfil,"@%s\tSEGMENT VIRTUAL",name);
  626.     }
  627. }
  628. void gen_endvirtual(char *name)
  629. {
  630.     if (prm_asmfile) {
  631.         nl();
  632.         fprintf(tempfil,"@%s\tENDS",name);
  633.     }
  634. }
  635. /*
  636.  * Align
  637.  */
  638. void align(int size)
  639. {
  640.             if (prm_asmfile) {
  641.                 nl();
  642.                 fprintf(tempfil,"\tALIGN\t%d\n",4);
  643.             }
  644. }
  645. /* muldiv val init
  646.  */
  647. void init_muldivval(void)
  648. {
  649.     muldivlink = 0;
  650. }
  651. /*
  652.  * queue muldiv val
  653.  */
  654. void queue_muldivval(int label, long number)
  655. {
  656.     MULDIV *p = xalloc(sizeof(MULDIV));
  657.     p->link = muldivlink;
  658.     p->value = number;
  659.     p->label = label;
  660.     p->size = 0;
  661.     muldivlink = p;
  662. }
  663. void queue_floatval(int label, double number, int size)
  664. {
  665.     MULDIV *p = xalloc(sizeof(MULDIV));
  666.     p->link = muldivlink;
  667.     p->floatvalue = number;
  668.     p->label = label;
  669.     p->size = size;
  670.     muldivlink = p;
  671. }
  672. void dump_muldivval(void)
  673. {
  674.     int tag = FALSE;
  675.     if (prm_asmfile) {
  676.         fprintf(tempfil,"\n");
  677.         if (muldivlink) {
  678.             tag = TRUE;
  679.             align(4);
  680.         }
  681.         while (muldivlink) {
  682.             put_label(muldivlink->label);
  683.             if (muldivlink->size == 0)
  684.                 fprintf(tempfil,"\tDD\t0%xH\n",muldivlink->value);
  685.             else if (muldivlink->size == 6)
  686.                 fprintf(tempfil,"\tDD\t%f\n",muldivlink->floatvalue);
  687.             else
  688.                 fprintf(tempfil,"\tDQ\t%f\n",muldivlink->floatvalue);
  689.             muldivlink = muldivlink->link;
  690.         }
  691.         if (tag)
  692.             fprintf(tempfil,"\n");
  693.     }
  694. }
  695.             
  696. void putexterns(void)
  697. /*
  698.  * Output the fixup tables and the global/external list
  699.  */
  700. {       SYM     *sp;
  701.             int i;
  702.             if (prm_asmfile){
  703.                 nl();
  704.                 exitseg();
  705.                 fprintf(outputFile,"\t.386\n\t.MODEL SMALL\n\n");
  706.                 for (i=0; i < HASHTABLESIZE; i++) {
  707.                     if ((sp=(SYM *) globalhash[i]) != 0) {
  708.                         while (sp) {
  709.                     if( sp->storage_class == sc_external && sp->extflag)
  710.                 fprintf(outputFile,"\tEXTRN\t%s\n",sp->name);
  711.                     else if( sp->storage_class == sc_externalfunc && sp->extflag)
  712.                 fprintf(outputFile,"\tEXTRN\t%s:PROC\n",sp->name);
  713.                     else if( sp->storage_class == sc_global )
  714.                 fprintf(outputFile,"\tPUBLIC\t%s\n",sp->name);
  715.                      sp = sp->next;
  716.                         }
  717.                     }
  718.                 }
  719.                 rewind(tempfil);
  720.                 while (!feof(tempfil)) {
  721.                     char buf[256];
  722.                     buf[0] = 0;
  723.                     fgets(buf,256,tempfil);
  724.                     fputs(buf,outputFile);
  725.                 }
  726.                 fprintf(outputFile,"\tEND\n");
  727.             }
  728. }