home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / icon / dos / src / icont / link.c < prev    next >
C/C++ Source or Header  |  1992-02-10  |  10KB  |  390 lines

  1. /*
  2.  * link.c -- linker main program that controls the linking process.
  3.  */
  4.  
  5. #include "link.h"
  6. #include "tproto.h"
  7. #include "globals.h"
  8. #include "../h/header.h"
  9.  
  10. #ifdef Header
  11. #include "hdr.h"
  12.  
  13. #ifndef MaxHeader
  14. #define MaxHeader MaxHdr
  15. #endif                    /* MaxHeader */
  16.  
  17. #endif                    /* Header */
  18.  
  19. /*
  20.  * Prototype.
  21.  */
  22.  
  23. hidden    novalue    setexe    Params((char *fname));
  24.  
  25.  
  26. /*
  27.  * The following code is operating-system dependent [@link.01].  Include
  28.  *  system-dependent files and declarations.
  29.  */
  30.  
  31. #if PORT
  32.    /* nothing to do */
  33. Deliberate Syntax Error
  34. #endif                    /* PORT */
  35.  
  36. #if AMIGA || ATARI_ST || MACINTOSH || VM || VMS
  37.    /* nothing to do */
  38. #endif                    /* AMIGA || ATARI_ST || ... */
  39.  
  40. #if ARM
  41. #include "kernel.h"
  42. #include "swis.h"
  43. #endif                    /* ARM */
  44.  
  45.  
  46. #if MSDOS
  47. #if MICROSOFT || TURBO
  48. #include <fcntl.h>
  49. #endif                    /* MICROSOFT || TURBO */
  50. #endif                    /* MSDOS */
  51.  
  52. #if MVS
  53. char *routname;                /* real output file name */
  54. #endif                    /* MVS */
  55.  
  56. #if OS2
  57. #if MICROSOFT
  58. #include <fcntl.h>
  59. #endif                    /* MICROSOFT */
  60. #endif                    /* OS2 */
  61.  
  62. #if UNIX
  63. #ifdef CRAY
  64. #define word word_fubar
  65. #include <sys/types.h>
  66. #include <sys/stat.h>
  67. #undef word
  68. #else                    /* CRAY */
  69. #include <sys/types.h>
  70. #include <sys/stat.h>
  71. #endif                    /* CRAY */
  72. #endif                    /* UNIX */
  73.  
  74. /*
  75.  * End of operating-system specific code.
  76.  */
  77.  
  78. FILE *infile;                /* input file (.u1 or .u2) */
  79. FILE *outfile;                /* interpreter code output file */
  80.  
  81. #ifdef DeBugLinker
  82. FILE *dbgfile;                /* debug file */
  83. static char dbgname[MaxFileName];    /* debug file name */
  84. #endif                    /* DeBugLinker */
  85.  
  86. char inname[MaxFileName];        /* input file name */
  87. static char icnname[MaxFileName];    /* icon source file name */
  88.  
  89. struct lfile *llfiles = NULL;        /* List of files to link */
  90.  
  91. #ifdef EventMon
  92. int colmno = 0;                /* current source program colm number */
  93. #endif                    /* EventMon */
  94.  
  95. int lineno = 0;                /* current source program line number */
  96. int fatals = 0;                /* number of errors encountered */
  97.  
  98. /*
  99.  *  ilink - link a number of files, returning error count
  100.  */
  101. int ilink(ifiles,outname)
  102. char **ifiles;
  103. char *outname;
  104.    {
  105.  
  106.  
  107.    int i;
  108.    struct lfile *lf,*lfls;
  109.    char *filename;            /* name of current input file */
  110.  
  111.    linit();                /* initialize memory structures */
  112.    while (*ifiles)
  113.       alsolink(*ifiles++);        /* make initial list of files */
  114.  
  115.    /*
  116.     * Phase I: load global information contained in .u2 files into
  117.     *  data structures.
  118.     *
  119.     * The list of files to link is maintained as a queue with llfiles
  120.     *  as the base.  lf moves along the list.  Each file is processed
  121.     *  in turn by forming .u2 and .icn names from each file name, each
  122.     *  of which ends in .u1.  The .u2 file is opened and globals is called
  123.     *  to process it.  When the end of the list is reached, lf becomes
  124.     *  NULL and the loop is terminated, completing phase I.  Note that
  125.     *  link instructions in the .u2 file cause files to be added to list
  126.     *  of files to link.
  127.     */
  128.    for (lf = llfiles; lf != NULL; lf = lf->lf_link) {
  129.       filename = lf->lf_name;
  130.       makename(inname, SourceDir, filename, U2Suffix);
  131.       makename(icnname, TargetDir, filename, SourceSuffix);
  132.  
  133. #if MVS || VM
  134. /*
  135.  * Even though the ucode data is all reasonable text characters, use
  136.  *  of text I/O may cause problems if a line is larger than LRECL.
  137.  *  This is likely to be true with any compiler, though the precise
  138.  *  disaster which results may vary.
  139.  */
  140.       infile = fopen(inname, ReadBinary);
  141. #else
  142.       infile = fopen(inname, ReadText);
  143. #endif                    /* MVS || VM */
  144.  
  145.       if (infile == NULL)
  146.          quitf("cannot open %s",inname);
  147.       readglob();
  148.       fclose(infile);
  149.       }
  150.  
  151.    /* Phase II: resolve undeclared variables and generate code. */
  152.  
  153.    /*
  154.     * Open the output file.
  155.     */
  156.  
  157. #if MVS
  158.    routname = outname;
  159.    outfile = tmpfile();         /* write icode to temporary file to
  160.                                    avoid fseek-PDS limitations */
  161. #else                    /* MVS */
  162.    outfile = fopen(outname, WriteBinary);
  163. #endif                    /* MVS */
  164.  
  165. /*
  166.  * The following code is operating-system dependent [@link.02].  Set
  167.  *  untranslated mode if necessary.
  168.  */
  169.  
  170. #if PORT
  171.    /* probably nothing */
  172. Deliberate Syntax Error
  173. #endif                    /* PORT */
  174.  
  175. #if AMIGA || ARM || ATARI_ST || MACINTOSH || MVS || UNIX || VM || VMS
  176.    /* nothing to do */
  177. #endif                    /* AMIGA || ARM || ATARI_ST || ... */
  178.  
  179. #if MSDOS
  180.  
  181. #if LATTICE
  182.    fmode(outfile,1);            /* set for untranslated mode */
  183. #endif                    /* LATTICE */
  184. #if MICROSOFT || TURBO
  185.    setmode(fileno(outfile),O_BINARY);    /* set for untranslated mode */
  186. #endif                    /* MICROSOFT || TURBO */
  187. #endif                    /* MSDOS */
  188.  
  189. #if OS2
  190. #if MICROSOFT
  191.    setmode(fileno(outfile),O_BINARY);
  192. #endif                    /* MICROSOFT */
  193. #endif                    /* OS2 */
  194.  
  195. /*
  196.  * End of operating-system specific code.
  197.  */
  198.  
  199.    if (outfile == NULL) 
  200.       quitf("cannot create %s",outname);
  201.  
  202. #ifdef Header
  203.    /*
  204.     * Open Header, which contains the start-up program and copy it to the
  205.     *  output file.  Then, write out null bytes to past the end of the
  206.     *  start-up program.
  207.     */
  208.    {
  209.    int hsize;
  210.    char hname[MaxFileName];
  211.    char hdrdat[MaxHeader+1];
  212.  
  213. #if (MACINTOSH && MPW)
  214.    {
  215.    int i;
  216.    fwrite(iconxhdr, sizeof(char), sizeof iconxhdr, outfile);
  217.    for (i = MaxHeader - sizeof iconxhdr;i;--i) fputc(0,outfile);
  218.    }
  219. #else                /* (MACINTOSH && MPW) */
  220.    fwrite(iconxhdr, sizeof(char), MaxHeader, outfile);
  221. #endif                /* (MACINTOSH && MPW) */
  222.  
  223.    }
  224. #endif                    /* Header */
  225.  
  226.    for (i = sizeof(struct header); i--;)
  227.       putc(0, outfile);
  228.    fflush(outfile);
  229.    if (ferror(outfile) != 0)
  230.       quit("unable to write to icode file");
  231.  
  232. #ifdef DeBugLinker
  233.    /*
  234.     * Open the .ux file if debugging is on.
  235.     */
  236.    if (Dflag) {
  237.       makename(dbgname, TargetDir, llfiles->lf_name, ".ux");
  238.       dbgfile = fopen(dbgname, WriteText);
  239.       if (dbgfile == NULL)
  240.          quitf("cannot create %s", dbgname);
  241.       }
  242. #endif                    /* DeBugLinker */
  243.  
  244.    /*
  245.     * Loop through input files and generate code for each.
  246.     */
  247.    lfls = llfiles;
  248.    while (lf = getlfile(&lfls)) {
  249.       filename = lf->lf_name;
  250.       makename(inname, SourceDir, filename, U1Suffix);
  251.       makename(icnname, TargetDir, filename, SourceSuffix);
  252.  
  253. #if MVS || VM
  254.       infile = fopen(inname, ReadBinary);
  255.       if (infile != NULL)         /* discard the extra blank we had */
  256.          (void) getc(infile);     /* to write to make it non-empty  */
  257. #else                                   /* MVS || VM */
  258.       infile = fopen(inname, ReadText);
  259. #endif                                  /* MVS || VM */
  260.  
  261.       if (infile == NULL)
  262.          quitf("cannot open %s", inname);
  263.       gencode();
  264.  
  265.  
  266.       fclose(infile);
  267.       }
  268.  
  269.  
  270.    gentables();        /* Generate record, field, global, global names,
  271.                static, and identifier tables. */
  272.    fclose(outfile);
  273.    lmfree();
  274.    if (fatals > 0)
  275.       return fatals;
  276.    setexe(outname);
  277.    return 0;
  278.    }
  279.  
  280. /*
  281.  * lwarn - issue a linker warning message.
  282.  */
  283. novalue lwarn(s1, s2, s3)
  284. char *s1, *s2, *s3;
  285.    {
  286.    fprintf(stderr, "%s: ", icnname);
  287.    if (lineno)
  288.       fprintf(stderr, "Line %d # :", lineno);
  289.    fprintf(stderr, "\"%s\": %s%s\n", s1, s2, s3);
  290.    fflush(stderr);
  291.    }
  292.  
  293. /*
  294.  * lfatal - issue a fatal linker error message.
  295.  */
  296.  
  297. novalue lfatal(s1, s2)
  298. char *s1, *s2;
  299.    {
  300.  
  301.    fprintf(stderr, "%s: ", icnname);
  302.    if (lineno)
  303.       fprintf(stderr, "Line %d # : ", lineno);
  304.    fprintf(stderr, "\"%s\": %s\n", s1, s2);
  305.    fatals++;
  306.    }
  307.  
  308. /*
  309.  * setexe - mark the output file as executable
  310.  */
  311.  
  312. static novalue setexe(fname)
  313. char *fname;
  314.    {
  315.  
  316. /*
  317.  * The following code is operating-system dependent [@link.03].  It changes the
  318.  *  mode of executable file so that it can be executed directly.
  319.  */
  320.  
  321. #if PORT
  322.    /* something is needed */
  323. Deliberate Syntax Error
  324. #endif                    /* PORT */
  325.  
  326. #if AMIGA
  327.    /* not necessary */
  328. #endif                    /* AMIGA */
  329.  
  330. #if ARM
  331.    {
  332.       _kernel_swi_regs regs;
  333.  
  334.       regs.r[0] = 31;
  335.       regs.r[1] = (int)"Icon";
  336.       if (_kernel_swi(OS_FSControl,®s,®s) == NULL)
  337.       {
  338.          regs.r[0] = 18;
  339.          regs.r[1] = (int)fname;
  340.          _kernel_swi(OS_File,®s,®s);
  341.       }
  342.    }
  343. #endif                    /* ARM */
  344.  
  345. #if ATARI_ST || MSDOS || MVS || OS2 || VM || VMS 
  346.    /* can't be made executable */
  347.    /* note: VMS files can't be made executable, but see "iexe.com" under VMS. */
  348. #endif                    /* ATARI_ST || MSDOS || VMS */
  349.  
  350. #if MACINTOSH
  351. #if MPW
  352.    /* Nothing to do here -- file is set to type TEXT
  353.       (so it can be executed as a script) in tmain.c.
  354.    */
  355. /* #pragma unused(fname) */
  356. #endif                    /* MPW */
  357. #endif                    /* MACINTOSH */
  358.  
  359. #if MSDOS
  360. #if LATTICE || MICROSOFT || TURBO
  361.    chmod(fname,0755);    /* probably could be smarter... */
  362. #endif                    /* LATTICE || MICROSOFT || TURBO */
  363. #if MWC
  364.    /* can't handle */
  365. #endif                    /* MWC */
  366. #endif                    /* MSDOS */
  367.  
  368. #if UNIX
  369.       {
  370.       struct stat stbuf;
  371.       int u, r, m;
  372.       /*
  373.        * Set each of the three execute bits (owner,group,other) if allowed by
  374.        *  the current umask and if the corresponding read bit is set; do not
  375.        *  clear any bits already set.
  376.        */
  377.       umask(u = umask(0));        /* get and restore umask */
  378.       if (stat(fname,&stbuf) == 0)  {    /* must first read existing mode */
  379.          r = (stbuf.st_mode & 0444) >> 2;    /* get & position read bits */
  380.          m = stbuf.st_mode | (r & ~u);        /* set execute bits */
  381.          chmod(fname,m);         /* change file mode */
  382.          }
  383.       }
  384. #endif                    /* UNIX */
  385.  
  386. /*
  387.  * End of operating-system specific code.
  388.  */
  389.    }
  390.