home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / sml_nj / 93src.lha / src / runtime / linkdata.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-09  |  8.8 KB  |  324 lines

  1. /* clinkdata.c:
  2.  *
  3.  * COPYRIGHT (c) 1989 by AT&T Bell Laboratories.
  4.  *
  5.  * Group files into the text segment of a .o file.  This is done by creating an
  6.  * assembly file "runtime/allmo.s" that allocates space for the code and deals
  7.  * with the relative addressing.  This file is then assembled, and then the actual
  8.  * code is patched into allmo.o.
  9.  *
  10.  * Specifically, this file produces an ML value of the type
  11.  *
  12.  *    datatype datalist
  13.  *      = DATANIL
  14.  *      | DATACONS of (string * (unit -> unit) * datalist)
  15.  *
  16.  * where the "unit -> unit" function is an empty closure refering to the
  17.  * code from the mo file.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <sys/file.h>
  24. #include "tags.h"
  25.  
  26. #define MAGICNUM    0x18273645
  27.  
  28. /* RUNTIME is defined to be the path prefix of the runtime source directory */
  29. #ifndef RUNTIME
  30. #define RUNTIME "runtime"
  31. #endif
  32.  
  33. #ifdef RS6000
  34. #define SYMBOL        "datalist"
  35. #define TEXT(F)        fprintf(F, ".toc\n.csect [RW]\n.align 2\n")
  36. #define GLOBAL(F,S)    fprintf(F, ".globl %s\n", S)
  37. #define WORD(F,N)    fprintf(F, ".long %d\n", N)
  38. #define ADDR(F,A)    fprintf(F, ".long %s\n", A)
  39. #define ADDR1(F,A,N)    fprintf(F, ".long %s+%d\n", A,N)
  40. #define SPACE(F,N)    fprintf(F, ".space %d\n", N)
  41. #else /* !RS6000 */
  42. #ifdef MIPS
  43. #define SYMBOL        "datalist"
  44. #define TEXT(F)         fprintf(F, ".text\n.set noreorder\n")
  45. #define GLOBAL(F,S)    fprintf(F, ".globl %s\n", S)
  46. #define WORD(F,N)    fprintf(F, ".word %d\n", N)
  47. #define ADDR(F,A)    fprintf(F, ".word %s\n", A)
  48. #define ADDR1(F,A,N)    fprintf(F, ".word %s+%d\n", A,N)
  49. #define SPACE(F,N)    fprintf(F, ".space %d\n", N)
  50. #else /* !RS6000 && !MIPS */
  51. #ifdef SPARC
  52. #define SYMBOL        "_datalist"
  53. #define TEXT(F)        fprintf(F, ".seg \"text\"\n")
  54. #define GLOBAL(F,S)    fprintf(F, ".global %s\n", S)
  55. #define WORD(F,N)    fprintf(F, ".word %d\n", N)
  56. #define ADDR(F,A)    fprintf(F, ".word %s\n", A)
  57. #define ADDR1(F,A,N)    fprintf(F, ".word %s+%d\n", A,N)
  58. #define SPACE(F,N)    fprintf(F, ".skip %d\n", N)
  59. #else /* !RS6000 && !MIPS && !SPARC */
  60. #ifdef sun3
  61. #define SYMBOL        "_datalist"
  62. #define TEXT(F)        fprintf(F, ".text\n")
  63. #define GLOBAL(F,S)    fprintf(F, ".globl %s\n", S)
  64. #define WORD(F,N)    fprintf(F, ".long %d\n", N)
  65. #define ADDR(F,A)    fprintf(F, ".long %s\n", A)
  66. #define ADDR1(F,A,N)    fprintf(F, ".long %s+%d\n", A, N)
  67. #define SPACE(F,N)    fprintf(F, ".skip %d\n", N)
  68. #else /* !RS6000 && !MIPS && !SPARC && !sun3 */
  69. #if defined(HPUX) && !defined(HPPA)
  70. #define SYMBOL        "_datalist"
  71. #define TEXT(F)        fprintf(F, "text\n")
  72. #define GLOBAL(F,S)    fprintf(F, "global %s\n", S)
  73. #define WORD(F,N)    fprintf(F, "long %d\n", N)
  74. #define ADDR(F,A)    fprintf(F, "long %s\n", A)
  75. #define ADDR1(F,A,N)    fprintf(F, "long %s+%d\n", A, N)
  76. #define SPACE(F,N)    fprintf(F, "space %d\n", N)
  77. #else /* !RS6000 && !MIPS && !SPARC && !sun3 && !HPUX */
  78. #ifdef AUX
  79. #define SYMBOL        "datalist"
  80. #define TEXT(F)        fprintf(F, ".file \"allmo.s\"\n.text\n")
  81. #define GLOBAL(F,S)    fprintf(F, ".globl %s\n", S)
  82. #define WORD(F,N)    fprintf(F, ".long %d\n", N)
  83. #define ADDR(F,A)    fprintf(F, ".long %s\n", A)
  84. #define ADDR1(F,A,N)    fprintf(F, ".long %s+%d\n", A, N)
  85. #define SPACE(F,N)    fprintf(F, ".space %d\n", N)
  86. #else
  87. #ifdef HPPA
  88. #define SYMBOL        "datalist"
  89. #define TEXT(F)        fprintf(F, "\t.space $PRIVATE$,SORT=16\n\t.subspa $DATA$,QUAD=0,ALIGN=4,ACCESS=63,SORT=16\n");
  90. #define GLOBAL(F,S)    fprintf(F, "\t.export %s,DATA\n", S)
  91. #define WORD(F,N)    fprintf(F, "\t.word %d\n", N)
  92. #define ADDR(F,A)    fprintf(F, "\t.word %s\n", A)
  93. #define ADDR1(F,A,N)    fprintf(F, "\t.word %s+%d\n", A, N)
  94. #define SPACE(F,N)    fprintf(F, "\t.blockz %d\n", N)
  95. #else /* !RS6000 && !MIPS && !SPARC && !sun3 && !HPUX && !AUX && !HPPA*/
  96. #define SYMBOL        "_datalist"
  97. #define TEXT(F)        fprintf(F, ".text\n")
  98. #define GLOBAL(F,S)    fprintf(F, ".globl %s\n", S)
  99. #define WORD(F,N)    fprintf(F, ".long %d\n", N)
  100. #define ADDR(F,A)    fprintf(F, ".long %s\n", A)
  101. #define ADDR1(F,A,N)    fprintf(F, ".long %s+%d\n", A, N)
  102. #define SPACE(F,N)    fprintf(F, ".space %d\n", N)
  103. #endif /* HPPA */
  104. #endif /* AUX */
  105. #endif /* HPUX */
  106. #endif /* sun3 */
  107. #endif /* SPARC */
  108. #endif /* MIPS */
  109. #endif /* RS6000 */
  110. #ifdef HPPA
  111. #  define LABEL(F,L)    fprintf(F, "\t.export %s,DATA\n%s\n", L,L)
  112. #else
  113. #  define LABEL(F,L)    fprintf(F, "%s:\n", L)
  114. #endif
  115.  
  116. #define LONG_SZ        (sizeof(long))
  117. #define align(x)    (((x) + (LONG_SZ - 1)) & ~(LONG_SZ - 1))
  118.  
  119. void die(s, arg)
  120.     char *s;
  121.     int arg;
  122. {
  123.     char buf[64];
  124.     sprintf(buf, s, arg);
  125.     perror(buf);
  126.     exit(1);
  127. }
  128.  
  129. extern char *malloc();
  130.  
  131. /* make_sfile:
  132.  * generate the assembly skeleton file
  133.  */
  134. void make_sfile (asfile, nfiles, mofiles)
  135.     FILE    *asfile;
  136.     int        nfiles;
  137.     char    **mofiles;
  138. {
  139.     struct stat st;
  140.     int n, len, str_sz, code_sz, i;
  141.     char buf[64], buf2[64], lab_buf[8];
  142.     static int lab_cnt = 0;
  143.  
  144.     TEXT(asfile);
  145.     WORD(asfile, MAGICNUM);
  146.     GLOBAL(asfile, SYMBOL);
  147.  
  148.     for (i = 0;  i < nfiles;  i++) {
  149.     char *fname = mofiles[i];
  150.       /* compute the space required for the file */
  151.     if (stat(fname, &st) == -1)
  152.         die("stat(\"%s\")", fname);
  153.     n = st.st_size;
  154.     if (n == 0)
  155.         die("mo file is empty");
  156.     len = strlen(fname);
  157.     str_sz = align(len) + 2*LONG_SZ;  /* includes filename and code descriptors */
  158.     code_sz = align(n);
  159.  
  160.       /* extract the structure name from the file name */
  161.     {
  162.         register char *p, *begin;
  163.  
  164.       /* find the beginning of the file name. */
  165.         for (p = begin = fname;  *p;  p++) {
  166.         if (*p == '/')
  167.             begin = p+1;
  168.         }
  169.       /* find the ".mo" */
  170.         for (p = begin, len = 0;  *p && (*p != '.');  p++, len++)
  171.         continue;
  172.         strncpy (buf, begin, len);
  173.         buf[len] = '\0';
  174.     }
  175.  
  176.       /* add the datalist entry for this structure */
  177.     if (i == 0)
  178.         LABEL(asfile, SYMBOL);
  179.     WORD(asfile, MAKE_DESC(3, TAG_record));
  180.     sprintf (lab_buf, "L%d", lab_cnt++);
  181.     LABEL(asfile, lab_buf);
  182.     ADDR1(asfile, lab_buf, 24);    /* mo filename string */
  183.     ADDR1(asfile, lab_buf, 16);    /* closure address */
  184.     if (i == (nfiles-1))
  185.         WORD(asfile, 1);        /* DATANIL */
  186.     else
  187.         ADDR1(asfile, buf, code_sz+4);
  188.  
  189.       /* create the closure record */
  190.     WORD(asfile, MAKE_DESC(1, TAG_record));
  191.     ADDR1(asfile, buf, 4);        /* code string address */
  192.  
  193.       /* add a label and space for the structure to the "allmo.s" file. */
  194.     SPACE(asfile, str_sz);
  195.     LABEL(asfile, buf);
  196.     SPACE(asfile, code_sz);        /* space for code (not including tag) */
  197.     }
  198.  
  199. } /* end of make_sfile */
  200.  
  201.  
  202. /* copy:
  203.  * append the code from file to output, preceded by name.
  204.  */
  205. int copy (file, ofd)
  206.     char *file; int ofd;
  207. {
  208.     int fd;
  209.     long i, x, len, n, nbytes;
  210.     char *s;
  211.     struct stat st;
  212.     static int bufsize = 0;
  213.     static long *buf;
  214.  
  215.     if ((fd = open(file, 0)) == -1) {
  216.     char    buf[64];
  217.     sprintf(buf, "open: %s", file);
  218.     die(buf);
  219.     }
  220.     if (fstat(fd, &st) == -1)
  221.     die("stat");
  222.  
  223.     n = st.st_size;
  224.     if (n == 0)
  225.     die("mo file is empty");
  226.     len = strlen(file);
  227.     nbytes = LONG_SZ + align(n) + LONG_SZ + align(len);
  228.  
  229.     if (nbytes > bufsize) {
  230.     bufsize = nbytes + 4096;
  231.     if (buf != NULL)
  232.         free(buf);
  233.     buf = (long *)malloc(bufsize);
  234.     if (buf == NULL)
  235.         die("malloc(buf)");
  236.     }
  237.  
  238.     buf[0] = MAKE_DESC(len, TAG_string);       /* tag for file name */
  239.     strcpy((char *) &buf[1], file);
  240.     s = ((char *) &buf[1]) + len;
  241.     for (i = align(len); i > len; i--)
  242.     *s++ = 0;
  243.  
  244.     *((long *) s) = MAKE_DESC(n, TAG_string);  /* tag for code */
  245.     s += LONG_SZ;
  246.  
  247.     for (x = n;  x > 0; ) {
  248.     i = read(fd, s, x);
  249.     if (i <= 0) die("read");
  250.     s += i; x -= i;
  251.      }
  252.  
  253.     for (i = align(n); i > n; i--) *s++ = 0;
  254.  
  255.     if (close(fd) == -1) die("close");
  256.  
  257.   /* advance the file pointer past the mo_list object and closure */
  258.     if (lseek(ofd, 6*LONG_SZ, 1 /* L_INCR */) == -1) die("lseek");
  259.  
  260.     s = (char*)buf;
  261.     for (x = nbytes;  x > 0; ) {
  262.     i = write(ofd, s, x);
  263.     if (i <= 0) die ("write");
  264.     x -= i; s += i;
  265.     }
  266. }
  267.  
  268.  
  269. int main(argc, argv)
  270.     int argc;
  271.     char *argv[];
  272. {
  273.     int i, pos, sts;
  274.     FILE *asfile, *ofile; int ofd;
  275.     char *as_buf, *o_buf, *cmd_buf;
  276.  
  277.     sprintf(as_buf = malloc(sizeof(RUNTIME)+16), "%s/allmo.s", RUNTIME);
  278.     sprintf(o_buf = malloc(sizeof(RUNTIME)+16), "%s/allmo.o", RUNTIME);
  279. #ifdef AUX
  280.     sprintf(cmd_buf = malloc(2*sizeof(RUNTIME)+32), "gas %s -o %s", as_buf, o_buf);
  281. #else
  282.     sprintf(cmd_buf = malloc(2*sizeof(RUNTIME)+32), "as %s -o %s", as_buf, o_buf);
  283. #endif
  284.  
  285.     asfile = fopen(as_buf,"w");
  286.     if (asfile == NULL)
  287.     die("fopen %s", as_buf);
  288.  
  289.     make_sfile (asfile, argc-1, argv+1);
  290.  
  291.     fclose (asfile);
  292.  
  293.     fprintf (stderr, "%s> %s\n", argv[0], cmd_buf);
  294.     if ((sts = system (cmd_buf)) != 0) {
  295.     fprintf (stderr, "cannot assemble %s, status = %d\n", as_buf, sts);
  296.     exit (1);
  297.     }
  298.  
  299.     ofile = fopen(o_buf,"r");
  300.     if (!ofile)
  301.     die("fopen %s", o_buf);
  302.     for (i = 0, pos = 0;  i != MAGICNUM;  pos += LONG_SZ) {
  303.     if (fread (&i, LONG_SZ, 1, ofile) == 0)
  304.         die("can't find magic num");
  305.     }
  306.     fclose (ofile);
  307.  
  308.     ofd = open (o_buf, O_RDWR, 0);
  309.     if (ofd < 0)
  310.     die("open %s", o_buf);
  311.  
  312.   /* set the file pointer to the tag word of the first datalist item */
  313.     lseek (ofd, pos, 0 /* L_SET */);
  314.  
  315.     for (i = 1;  i < argc;  i++)
  316.     copy (argv[i], ofd);
  317.  
  318.     close (ofd);
  319.  
  320.     exit (0);
  321. }
  322.  
  323.  
  324.