/* Copyright (C) 1990, Digital Equipment Corporation. */ /* All rights reserved. */ /* See the file COPYRIGHT for a full description. */ /* Last modified on Thu Jul 19 07:54:34 1990 by muller */ /* Modified On Fri Jun 29 17:22:38 1990 by piet@cs.ruu.nl */ #include extern char *tempnam (); #define TRUE 1 #define FALSE 0 #define NEW(type) ((type *) malloc (sizeof (type))) #define loop while (1) #define streq(a,b) (!strcmp((a),(b))) extern char *malloc (); extern char *strtok (); extern char *strrchr (); void read_symbols (); void generate_output (); main (argc, argv) int argc; char **argv; { int preserve = 0; int localverbose = 0; int do_it = 1; char *output = "a.out"; char *options[100]; int nb_options = 0; char *files [1000]; int nb_files = 0; int size, i, more; char command [20000]; char *obj = tempnam (".", "m3ld"); char *code = tempnam (".", "m3ld"); char *syms = tempnam (".", "m3ld"); /* skip the program description */ argc--; argv++; while (argc > 0) { if (argv[0][0] == '-') { switch (argv[0][1]) { case 'o': { if (argc < 2) { fprintf (stderr, "Must specify the output file name after -o"); exit (1); } output = argv[1]; argv++; argc--; break; } case 'c': { break; } case 'p': { preserve = 1; break; } case 'v': { localverbose = 1; break; } case 'l': { files[nb_files++] = argv[0]; break; } case 'L': { if ((LD_WANTS_SPACE_AFTER_L) && (argv[0][2] != '\0')) { files[nb_files++] = "-L"; files[nb_files++] = argv[0] + 2; } else { files[nb_files++] = argv[0]; } break; } default: { options [nb_options++] = argv[0]; break; }}} else { files[nb_files++] = argv[0]; } argv++; argc--; } sprintf (command, "LD -r -o %s.o ", obj); size = strlen (command); for (i = 0; i < nb_files; i++) { more = strlen (files[i]); bcopy (files[i], command + size, more); size += more; command[size++] = ' '; } command [size] = '\0'; if (localverbose) { fprintf (stdout, "%s\n", command); } if ((do_it == 1) && (system (command) != 0)) { exit (1); } sprintf (command, "NM %s.o > %s", obj, syms); if (localverbose) { fprintf (stdout, "%s\n", command); } if ((do_it == 1) && (system (command) != 0)) { exit(1); } read_symbols (syms); generate_output (code); sprintf (command, "PASS1 -o %s ", output); size = strlen (command); for (i = 0; i < nb_options; i++) { more = strlen (options[i]); bcopy (options[i], command + size, more); size += more; command[size++] = ' '; } sprintf (command+size, " %s.c %s.o", code, obj); size = strlen (command); if (preserve) { sprintf (command+size, "; /bin/rm -f %s.o %s.o %s; mv %s.c m3ld_init.c", code, obj, syms, code); } else { sprintf (command+size, "; /bin/rm -f %s.o %s.o %s.c %s", code, obj, code, syms); } if (localverbose) { fprintf (stdout, "%s\n", command); } if ((do_it == 1) && (system (command) != 0)) { exit (1); } } typedef struct name_struct { char *name; struct name_struct *next; } PROC_STRUCT, *PROC; PROC interface_links = NULL; PROC implementation_links = NULL; PROC interface_maps = NULL; PROC implementation_maps = NULL; PROC inits = NULL; char *duplicate (string) char *string; { int n = strlen (string) + 1; char *c = malloc (n); bcopy (string, c, n); return (c); } /* duplicate */ void add_name (proc, list) char *proc; PROC *list; { PROC entry; entry = NEW (PROC_STRUCT); entry->name = duplicate (proc); entry->next = *list; *list = entry; } /* add_name */ void read_symbols (syms) char *syms; { int i; #if defined (IBMRT) || defined (IBMR2) || defined (AIX386) int c; #else char c; #endif char buff[400]; char *start, *bup; FILE *f; if ((f = fopen (syms, "r")) == 0) { perror ("opening program symbols file"); exit (1); } loop { /* read a line of the 'nm' output */ i = 0; while (((c = getc(f)) != '\n') && (c != EOF)) { buff [i++] = c; } if (c == EOF) break; buff [i] = '\0'; /* scan back in the line over the name */ #if defined (AIX386) start = buff; for (i= 0; (buff[i] != '\0') && (buff[i] != ' ') && (buff[i] != '|'); i++); buff[i] = '\0'; #else for (start = buff + i - 1; *start != ' '; start--); #endif /* skip the leading underscores */ #if defined (VAX) || defined (SPARC) || defined (HP300) start += 2; #endif #if defined (DS3100) start += 1; #endif #if defined (IBMRT) start += 2; if (*start == '.') { continue; } /* ignore _.text symbols */ #endif #if defined (IBMR2) /* All text segment entry points are defined both as public and private; select the public ones only */ if ((*(start-1) != 'T') || (*(start+1) != '.')) { continue; } start += 2; #endif bup = buff + i - 7; if (streq (bup, "__MLink")) { add_name (start, &implementation_links); } else if (streq (bup, "__ILink")) { add_name (start, &interface_links); bup[0] = '\0'; add_name (start, &inits); } else if (streq (bup+1, "__MMap")) { add_name (start, &implementation_maps); } else if (streq (bup+1, "__IMap")) { add_name (start, &interface_maps); }; }; /* end loop */ fclose (f); } /* read_symbols */ void generate_output (code) char *code; { PROC l; FILE* f; char fname [2000]; sprintf (fname, "%s.c", code); if ((f = fopen (fname, "w")) == 0) { perror ("openning code file"); exit (1); } fprintf (f, "extern void init_runtime ();\n"); fprintf (f, "extern char * Thread__init;\n"); fprintf (f, "extern char * Main__init;\n"); /* declare the init its descriptor records */ fprintf (f, "\n"); for (l = inits; l != NULL; l = l->next) { fprintf (f, "extern char * %s__init;\n", l->name); } /* declare the external map procs */ fprintf (f, "\n"); for (l = interface_maps; l != NULL; l = l->next) { fprintf (f, "extern void %s ();\n", l->name); } for (l = implementation_maps; l != NULL; l = l->next) { fprintf (f, "extern void %s ();\n", l->name); } /* The GlobalMapProc routine is ...*/ fprintf (f, "_M3Runtime__GlobalMapProc (p)"); fprintf (f, " void (*p)(); {\n"); for (l = interface_maps; l != NULL; l = l->next) { fprintf (f, " %s (p);\n", l->name); } for (l = implementation_maps; l != NULL; l = l->next) { fprintf (f, " %s (p);\n", l->name); } fprintf (f, " }\n\n"); /* The main program is ...*/ fprintf (f, "user_main (argc, argv)\n"); fprintf (f, "int argc; char **argv;\n{ int phase;\n"); /* ... a basic initialization ... */ fprintf (f, " init_runtime (argc, argv);\n\n"); /* ... call the link procedures ... */ fprintf (f, " for (phase = 0; phase <= 2; phase ++) {\n"); for (l = interface_links; l != NULL; l = l->next) { fprintf (f, " %s (phase);\n", l->name); } for (l = implementation_links; l != NULL; l = l->next) { fprintf (f, " %s (phase);\n", l->name); } /* ... get a chance to do the runtime's stuff... */ fprintf (f, "\n finish_type_registration (phase); };\n\n"); /* ... initialize the Thread mechanism ... */ fprintf (f, " _M3Runtime__InitModule (& Thread__init);\n"); /* ... initialiaize the other interfaces ... */ for (l = inits; l != NULL; l = l->next) { if (!streq (l->name, "Main") && !streq (l->name, "Thread")) { fprintf (f, " _M3Runtime__InitModule (& %s__init);\n", l->name); }} /* ... and run the main program. */ fprintf (f, " _M3Runtime__InitModule (& Main__init);\n}\n"); fclose (f); }