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

  1. /*
  2.  * lmem.c -- memory initialization and allocation; also parses arguments.
  3.  */
  4.  
  5. #include "link.h"
  6. #include "tproto.h"
  7. #include "globals.h"
  8.  
  9. /*
  10.  * The following code is operating-system dependent [@lmem.01].  It includes
  11.  *  files that are system dependent.
  12.  */
  13.  
  14. #if PORT
  15.    /* nothing is needed */
  16. Deliberate Syntax Error
  17. #endif                    /* PORT */
  18.  
  19. #if AMIGA || ARM || ATARI_ST || MACINTOSH || VMS
  20.    /* nothing is needed */
  21. #endif                    /* AMIGA || ARM || ATARI_ST || ... */
  22.  
  23. #if OS2
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #endif                    /* OS@ */
  27.  
  28. #if MSDOS
  29. #if MWC
  30. #include <stat.h>
  31. #endif                    /* MWC */
  32. #if LATTICE
  33. #include <types.h>
  34. #include <stat.h>
  35. #endif                    /* LATTICE */
  36. #if MICROSOFT || INTEL_386 || ZTC_386 || HIGHC_386
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #endif                    /* MICROSOFT || INTEL_386 || ...  */
  40. #if TURBO
  41. #include <sys/stat.h>
  42. #endif                    /* TURBO */
  43. #endif                    /* MSDOS */
  44.  
  45. #if MVS || VM
  46. #if SASC
  47. #include <fcntl.h>
  48. #endif                    /* SASC */
  49. #endif                    /* MVS || VM */
  50.  
  51. #if UNIX
  52. #ifndef ATT3B
  53. #ifdef CRAY
  54. #define word word_fubar
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57. #undef word
  58. #else                    /* CRAY */
  59. #include <sys/types.h>
  60. #include <sys/stat.h>
  61. #endif                    /* CRAY */
  62. #endif                    /* ATT3B */
  63. #endif                    /* UNIX */
  64.  
  65. /*
  66.  * End of operating-system specific code.
  67.  */
  68.  
  69. /*
  70.  * Prototypes.
  71.  */
  72.  
  73. hidden struct    lfile *alclfile    Params((char *name));
  74. hidden int    canread        Params((char *file));
  75. hidden int    trypath        Params((char *name,char *file));
  76.  
  77. #ifdef DeBugLinker
  78. hidden    novalue    dumpfiles    Params((noargs));
  79. #endif                    /* DeBugLinker */
  80.  
  81. #ifdef MultipleRuns
  82. hidden novalue    freelfile    Params((struct lfile *p));
  83. #endif                    /* MultipleRuns */
  84.  
  85. /*
  86.  * Memory initialization
  87.  */
  88.  
  89. struct gentry **lghash;        /* hash area for global table */
  90. struct ientry **lihash;        /* hash area for identifier table */
  91. struct fentry **lfhash;        /* hash area for field table */
  92.  
  93. struct lentry *lltable;        /* local table */
  94. struct gentry *lgtable;        /* global table */
  95. struct centry *lctable;        /* constant table */
  96. struct ientry *litable;        /* identifier table */
  97. struct fentry *lftable;        /* field table headers */
  98. struct rentry *lrtable;        /* field table record lists */
  99. struct ipc_fname *fnmtbl;    /* table associating ipc with file name */
  100. struct ipc_line *lntable;    /* table associating ipc with line number */
  101.  
  102. char *lsspace;            /* string space */
  103. word *labels;            /* label table */
  104. char *codeb;            /* generated code space */
  105.  
  106. struct gentry *lgfree;        /* free pointer for global table */
  107. struct ientry *lifree;        /* free pointer for identifier table */
  108. struct fentry *lffree;        /* free pointer for field table headers */
  109. struct rentry *lrfree;        /* free pointer for field table record lists */
  110. struct ipc_fname *fnmfree;    /* free pointer for ipc/file name table */
  111. struct ipc_line *lnfree;    /* free pointer for ipc/line number table */
  112. char *lsfree;            /* free pointer for string space */
  113. char *codep;            /* free pointer for code space */
  114.  
  115. char *lsend;            /* pointer to end of string space */
  116.  
  117. static char *ipath;        /* path for iconx */
  118.  
  119. #ifdef MultipleRuns
  120. extern word pc;
  121. extern int fatals;
  122. extern int nlflag;
  123. extern int lstatics;
  124. extern int nfields;
  125. #endif                    /* MultipleRuns */
  126.  
  127. /*
  128.  * linit - scan the command line arguments and initialize data structures.
  129.  */
  130. novalue linit()
  131.    {
  132.    struct gentry **gp;
  133.    struct ientry **ip;
  134.    struct fentry **fp;
  135.  
  136.    llfiles = NULL;        /* Zero queue of files to link. */
  137.  
  138. #ifdef EnvVars
  139.    ipath = getenv(IPATH);
  140. #else                    /* EnvVars */
  141.    ipath = NULL;
  142. #endif                    /* EnvVars */
  143.  
  144.    if (ipath == NULL)
  145.  
  146. /*
  147.  * The following code is operating-system dependent [@lmem.02].  Set default
  148.  * for IPATH.
  149.  */
  150.  
  151. #if PORT
  152.    /* something is needed */
  153. Deliberate Syntax Error
  154. #endif                    /* PORT */
  155.  
  156. #if AMIGA
  157.    /*
  158.     * There is no environment, so set IPATH to the null string. The
  159.     *  current directory is searched anyway and there is no symbol
  160.     *  to force current path search.
  161.     */
  162.       ipath = "";
  163. #endif                    /* AMIGA */
  164.  
  165. #if ARM
  166.       ipath = "Icon: Lib:Icon.";
  167. #endif                    /* ARM */
  168.  
  169. #if ATARI_ST || UNIX
  170.       ipath = ".";
  171. #endif                    /* ATARI_ST || UNIX */
  172.  
  173. #if MSDOS || OS2
  174.       ipath = ";";
  175. #endif                    /* MSDOS || OS2 */
  176.  
  177. #if MACINTOSH
  178. #if MPW || LSC
  179.       ipath = ":";
  180. #endif                    /* MPW || LSC */
  181. #endif                    /* MACINTOSH */
  182.  
  183. #if MVS
  184. #if SASC
  185.       ipath = "iconlib ddn:::lib";
  186. #else                    /* SASC */
  187.       ipath = "";
  188. #endif                    /* SASC */
  189. #endif                    /* MVS */
  190.  
  191. #if VM
  192.       ipath = "";
  193. #endif                                  /* VM */
  194.  
  195. #if VMS
  196.       ipath = "[]";
  197. #endif                    /* VMS */
  198.  
  199. /*
  200.  * End of operating-system specific code.
  201.  */
  202.  
  203.    /*
  204.     * Allocate the various data structures that are used by the linker.
  205.     */
  206.    lghash   = (struct gentry **) tcalloc(ghsize, sizeof(struct gentry *));
  207.    lihash   = (struct ientry **) tcalloc(ihsize, sizeof(struct ientry *));
  208.    lfhash   = (struct fentry **) tcalloc(fhsize, sizeof(struct fentry *));
  209.  
  210.    lltable  = (struct lentry *) tcalloc(lsize, sizeof(struct lentry));
  211.    lctable  = (struct centry *) tcalloc(csize, sizeof(struct centry));
  212.  
  213.    lffree = lftable  = (struct fentry *) tcalloc(fsize, sizeof(struct fentry));
  214.    lgfree = lgtable  = (struct gentry *) tcalloc(gsize, sizeof(struct gentry));
  215.    lifree = litable  = (struct ientry *) tcalloc(isize, sizeof(struct ientry ));
  216.    lnfree = lntable  = (struct ipc_line*)tcalloc(nsize,sizeof(struct ipc_line));
  217.    lrfree = lrtable  = (struct rentry *) tcalloc(rsize, sizeof(struct rentry));
  218.  
  219.    lsfree = lsspace = (char *) tcalloc(stsize, sizeof(char));
  220.    lsend = lsspace + stsize - 1;
  221.  
  222.    fnmtbl = (struct ipc_fname *) tcalloc(fnmsize, sizeof(struct ipc_fname));
  223.    fnmfree = fnmtbl;
  224.  
  225.    labels  = (word *) tcalloc(maxlabels, sizeof(word));
  226.    codep = codeb = (char *) tcalloc(maxcode, 1);
  227.  
  228.    /*
  229.     * Zero out the hash tables.
  230.     */
  231.    for (gp = lghash; gp < &lghash[ghsize]; gp++)
  232.       *gp = NULL;
  233.    for (ip = lihash; ip < &lihash[ihsize]; ip++)
  234.       *ip = NULL;
  235.    for (fp = lfhash; fp < &lfhash[fhsize]; fp++)
  236.       *fp = NULL;
  237.  
  238. #ifdef MultipleRuns
  239.  
  240.    /*
  241.     * Initializations required for repeated program runs.
  242.     */
  243.  
  244.    pc = 0;                /* In lcode.c    */
  245.    nrecords = 0;            /* In lglob.c    */
  246.  
  247. #ifdef EventMon
  248.    colmno = 0;                /* In link.c    */
  249. #endif                    /* EventMon */
  250.  
  251.    lineno = 0;                /* In link.c    */
  252.    fatals = 0;                /* In link.c    */
  253.    nlflag = 0;                /* In llex.c    */
  254.    lstatics = 0;            /* In lsym.c    */
  255.    nfields = 0;                /* In lsym.c    */
  256. #endif                    /* MultipleRuns */
  257.  
  258.    /*
  259.     * Install "main" as a global variable in order to insure that it
  260.     *  is the first global variable.  iconx/start.s depends on main
  261.     *  being global number 0.
  262.     */
  263.    putglobal(instid("main"), F_Global, 0, 0);
  264.    }
  265.  
  266. #ifdef DeBugLinker
  267. /*
  268.  * dumplfiles - print the list of files to link.  Used for debugging only.
  269.  */
  270.  
  271. novalue dumplfiles()
  272.    {
  273.    struct lfile *p,*lfls;
  274.  
  275.    fprintf(stderr,"lfiles:\n");
  276.    lfls = llfiles;
  277.    while (p = getlfile(&lfls))
  278.        fprintf(stderr,"'%s'\n",p->lf_name);
  279.    fflush(stderr);
  280.    }
  281. #endif                    /* DeBugLinker */
  282.  
  283. /*
  284.  * alsolink - create an lfile structure for the named file and add it to the
  285.  *  end of the list of files (llfiles) to generate link instructions for.
  286.  */
  287. static char *pptr;
  288. novalue alsolink(name)
  289. char *name;
  290.    {
  291.    struct lfile *nlf, *p;
  292.    char file[256], ok;
  293.  
  294.    ok = 0;
  295.    if (canread(name)) {
  296.       ok++;
  297.       strcpy(file, name);
  298.       }
  299.    else {
  300.       /*
  301.        * Can't find name in current directory so try paths in
  302.        *   IPATH if there are any. (IPATH cannot override the
  303.        *   current-directory-first strategy so there is probably
  304.        *   no reason to initialize IPATH to the various current
  305.        *   directory markers as is done above, since this will
  306.        *   only result in a duplicate failed search. Note that
  307.        *   the access test which is done above in some systems
  308.        *   will have already caused ilink to exit if name is
  309.        *   not found in the current directory anyway so ipath
  310.        *   was never able to search other paths first in any case.)
  311.        */
  312.  
  313.  
  314.       pptr = ipath;
  315.  
  316.       while (trypath(name, file)) {
  317.          if (canread(file)) {
  318.             ok++;
  319.             break;
  320.             }
  321.          }
  322.       }
  323.  
  324.    if (!ok)
  325.      quitf("cannot resolve reference to file '%s'",name);
  326.  
  327.    nlf = alclfile(file);
  328.    if (llfiles == NULL) {
  329.       llfiles = nlf;
  330.       }
  331.    else {
  332.       p = llfiles;
  333.       while (p->lf_link != NULL) {
  334.         if (strcmp(p->lf_name,file) == 0)
  335.            return;
  336.         p = p->lf_link;
  337.         }
  338.       if (strcmp(p->lf_name,file) == 0)
  339.         return;
  340.       p->lf_link = nlf;
  341.       }
  342.    }
  343.  
  344. /*
  345.  * getlfile - return a pointer (p) to the lfile structure pointed at by lptr
  346.  *  and move lptr to the lfile structure that p points at.  That is, getlfile
  347.  *  returns a pointer to the current (wrt. lptr) lfile and advances lptr.
  348.  */
  349. struct lfile *getlfile(lptr)
  350. struct lfile **lptr;
  351.    {
  352.    struct lfile *p;
  353.  
  354.    if (*lptr == NULL)
  355.       return (struct lfile *)NULL;
  356.    else {
  357.       p = *lptr;
  358.       *lptr = p->lf_link;
  359.       return p;
  360.       }
  361.    }
  362.  
  363. /*
  364.  * canread - see if file can be read and be sure that it's just an
  365.  *  ordinary file.
  366.  */
  367. static int canread(file)
  368. char *file;
  369.    {
  370.  
  371. /*
  372.  * The following code is operating-system dependent [@lmem.03]. Check to see if
  373.  *  .u1 file can be read.
  374.  */
  375.  
  376. #if PORT
  377.    /* something is needed */
  378. Deliberate Syntax Error
  379. #endif                    /* PORT */
  380.  
  381. #if AMIGA || ATARI_ST || VMS
  382.    if (access(file,4) == 0)
  383.       return 1;
  384. #endif                    /* AMIGA || ATARI_ST || VMS */
  385.  
  386. #if ARM
  387.    {
  388.    FILE *f;
  389.    if ((f = fopen(file,ReadText)) != NULL) {
  390.       fclose(f);
  391.       return 1;
  392.       }
  393.    }
  394. #endif                    /* ARM */
  395.  
  396. #if MACINTOSH
  397. #if MPW || LSC
  398.    {
  399.    FILE *f;
  400.    if ((f = fopen(file,ReadText)) != NULL) {
  401.       fclose(f);
  402.       return 1;
  403.       }
  404.    }
  405. #endif                    /* MPW || LSC */
  406. #endif                    /* MACINTOSH */
  407.  
  408. #if MSDOS || OS2 || UNIX
  409. #if INTEL_386
  410.    char lclname[MaxFileName];
  411.    if (access( makename(lclname,(char *)NULL,file,U1Suffix), 4 ) == 0 )
  412.       return 1;
  413. #else                    /* INTEL_386 */
  414.    struct stat statb;
  415.    if (access(file,4) == 0) {
  416.       stat(file,&statb);
  417.       if (statb.st_mode & S_IFREG)
  418.          return 1;
  419.       }
  420. #endif                    /* INTEL_386 */
  421. #endif                    /* MSDOS || ... */
  422.  
  423. #if MVS || VM
  424.    char lclname[MaxFileName];
  425. #if SASC
  426.    if (access(makename(lclname,(char*)NULL,file,U1Suffix),R_OK) == 0)
  427.       return 1;
  428. #else                    /* SASC */
  429.    FILE *f;                     /* can't use access because it will */
  430.                                 /* accept LRECL, etc. */
  431.  
  432.    if ((f = fopen(makename(lclname,(char *)NULL,file,U1suffix),
  433.       ReadText)) != NULL) {
  434.       fclose(f);
  435.       return 1;
  436.       }
  437. #endif                    /* SASC */
  438. #endif                    /* MVS || VM */
  439.  
  440. /*
  441.  * End of operating-system specific code.
  442.  */
  443.  
  444.    return 0;
  445.    }
  446.  
  447.  
  448. /*
  449.  * trypath - form a file name in file by concatenating name onto the
  450.  *  next path element.
  451.  */
  452. static int trypath(name,file)
  453. char *name, *file;
  454.    {
  455.    char c;
  456.  
  457.    while (*pptr == ' ')
  458.       pptr++;
  459.    if (!*pptr)
  460.       return 0;
  461.    do {
  462.       c = (*file++ = *pptr++);
  463.       }
  464.       while (c != ' ' && c);
  465.    pptr--;
  466.    file--;
  467.  
  468. /*
  469.  * The following code is operating-system dependent [@lmem.04].  Append path
  470.  *  character.
  471.  */
  472.  
  473. #if PORT
  474.    /* nothing is needed */
  475. Deliberate Syntax Error
  476. #endif                    /* PORT */
  477.  
  478. #if AMIGA
  479.    file--;
  480.    switch (*file) {
  481.  
  482.       case ':':
  483.       case '/':
  484.                  file++;
  485.                  break;       /* add nothing, delimiter already there */
  486.       default:
  487.                  *file++ = '/';
  488.       }
  489. #endif                    /* AMIGA */
  490.  
  491. #if ARM || ATARI_ST || MACINTOSH || VM || VMS
  492.    /* nothing is needed */
  493. #endif                    /* ARM || ATARI_ST || MACINTOSH ... */
  494.  
  495. #if MVS
  496.    *file++ = '(';
  497. #endif                    /* MVS */
  498.  
  499. #if UNIX || MSDOS || OS2
  500. #if HIGHC_386
  501.    *file++ = '\\';
  502. #else                    /* HIGHC_386 */
  503.    *file++ = '/';            /* should check for delimiter */
  504. #endif                    /* HIGHC_386 */
  505. #endif                    /* UNIX || MSDOS || OS2 */
  506.  
  507. /*
  508.  * End of operating-system specific code.
  509.  */
  510.  
  511.    while (*file++ = *name++);
  512.  
  513. #if MVS
  514.    file[-1] = ')';
  515. #endif                    /* MVS */
  516.    *file = 0;
  517.    return 1;
  518.    }
  519.  
  520. /*
  521.  * alclfile - allocate an lfile structure for the named file, fill
  522.  *  in the name and return a pointer to it.
  523.  */
  524. static struct lfile *alclfile(name)
  525. char *name;
  526.    {
  527.    struct lfile *p;
  528.  
  529.    p = (struct lfile *) alloc(sizeof(struct lfile));
  530.    p->lf_link = NULL;
  531.    p->lf_name = salloc(name);
  532.    return p;
  533.    }
  534.  
  535. #ifdef MultipleRuns
  536. /*
  537.  * freelfile - free memory of an lfile structure.
  538.  */
  539. static novalue freelfile(p)
  540. struct lfile *p;
  541.    {
  542.    free(p->lf_name);
  543.    free((char *) p);
  544.    }
  545. #endif                        /* MultipleRuns */
  546.  
  547. /*
  548.  * lmfree - free memory used by the linker
  549.  */
  550. novalue lmfree()
  551.    {
  552.    struct lfile *lf, *nlf;
  553.  
  554.    free((char *) lghash);   lghash = NULL;
  555.    free((char *) lihash);   lihash = NULL;
  556.    free((char *) lfhash);   lfhash = NULL;
  557.    free((char *) lltable);   lltable = NULL;
  558.    free((char *) lctable);   lctable = NULL;
  559.    free((char *) lftable);   lftable = NULL;
  560.    free((char *) lgtable);   lgtable = NULL;
  561.    free((char *) litable);   litable = NULL;
  562.    free((char *) lntable);   lntable = NULL;
  563.    free((char *) lrtable);   lrtable = NULL;
  564.    free((char *) lsspace);   lsspace = NULL;
  565.    free((char *) fnmtbl);   fnmtbl = NULL;
  566.    free((char *) labels);   labels = NULL;
  567.    free((char *) codep);   codep = NULL;
  568.  
  569. #ifdef MultipleRuns
  570.    for (lf = llfiles; lf != NULL; lf = nlf) {
  571.       nlf = lf->lf_link;
  572.       freelfile(lf);
  573.       }
  574.    llfiles = NULL;
  575.  
  576. #if MACINTOSH
  577. #if MPW
  578. /* #pragma unused(nlf,lf) */
  579. #endif                    /* MPW */
  580. #endif                    /* MACINTOSH */
  581. #endif                    /* MultipleRuns */
  582.  
  583.    }
  584.