scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

main.c (2862B)


      1 #include <errno.h>
      2 #include <stdarg.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include <scc/mach.h>
      8 
      9 #include "ld.h"
     10 
     11 #define MAX_LIB_PATHS 12
     12 
     13 int sflag;        /* discard all the symbols */
     14 int xflag;        /* discard local symbols */
     15 int Xflag;        /* discard locals starting with 'L' */
     16 int rflag;        /* preserve relocation bits */
     17 int dflag;        /* define common even with rflag */
     18 int gflag;        /* preserve debug symbols */
     19 int nmagic;       /* nmagic output */
     20 
     21 char *filename, *membname;
     22 
     23 Segment text = {.type = 'T'};
     24 Segment rodata = {.type = 'R'};
     25 Segment data = {.type = 'D'};
     26 Segment bss = {.type = 'B'};
     27 Segment debug = {.type = 'N'};
     28 
     29 char *libpaths[MAX_LIB_PATHS];
     30 
     31 char *output = "a.out", *entry = "start";
     32 static int status;
     33 
     34 void
     35 error(char *fmt, ...)
     36 {
     37 	va_list va;
     38 
     39 	va_start(va, fmt);
     40 	fprintf(stderr, "ld: %s: ", filename);
     41 	if (membname)
     42 		fprintf(stderr, "%s: ", membname);
     43 	vfprintf(stderr, fmt, va);
     44 	putc('\n', stderr);
     45 	va_end(va);
     46 
     47 	status = EXIT_FAILURE;
     48 }
     49 
     50 static void
     51 cleanup(void)
     52 {
     53 	if (status != EXIT_FAILURE)
     54 		remove(output);
     55 }
     56 
     57 /*
     58  * pass1: Get the list of object files that are going to be linked.
     59  * pass2: Calculate the size of every segment.
     60  * pass3: Rebase all symbols in sections
     61  * pass4: Create the temporary files per section
     62  * pass5: Create the temporary files per segment
     63  */
     64 static void
     65 ld(int argc, char*argv[])
     66 {
     67 	pass1(argc, argv);
     68 	pass2(argc, argv);
     69 /*
     70 	pass3(argc, argv);
     71 	pass4(argc, argv);
     72 	pass5(argc, argv);
     73 */
     74 	debugsym();
     75 	debugsec();
     76 }
     77 
     78 static void
     79 usage(void)
     80 {
     81 	fputs("usage: ld [options] file ...\n", stderr);
     82 	exit(EXIT_FAILURE);
     83 }
     84 
     85 static void
     86 Lpath(char *path)
     87 {
     88 	char **bp, **end;
     89 
     90 	end = &libpaths[MAX_LIB_PATHS];
     91 	for (bp = libpaths; bp < end && *bp; ++bp)
     92 		;
     93 	if (bp == end) {
     94 		fputs("ld: too many -L options\n", stderr);
     95 		exit(1);
     96 	}
     97 	*bp = path;
     98 }
     99 
    100 char *
    101 nextarg(char **argp, char ***argv)
    102 {
    103 	char *ap = *argp, **av = *argv;
    104 
    105 	if (ap[1]) {
    106 		*argp += strlen(ap);
    107 		return ap+1;
    108 	}
    109 
    110 	if (av[1]) {
    111 		*argv = ++av;
    112 		return *av;
    113 	}
    114 
    115 	usage();
    116 }
    117 
    118 int
    119 main(int argc, char *argv[])
    120 {
    121 	int files = 0;
    122 	char *ap, **av;
    123 
    124 	for (av = argv+1; *av; ++av) {
    125 		if (av[0][0] != '-') {
    126 			files = 1;
    127 			continue;
    128 		}
    129 		for (ap = &av[0][1]; *ap; ++ap) {
    130 			switch (*ap) {
    131 			case 's':
    132 				sflag = 1;
    133 				break;
    134 			case 'x':
    135 				xflag = 1;
    136 				break;
    137 			case 'X':
    138 				Xflag = 1;
    139 				break;
    140 			case 'i':
    141 			case 'r':
    142 				rflag = 1;
    143 				break;
    144 			case 'd':
    145 				dflag = 1;
    146 				break;
    147 			case 'n':
    148 				nmagic = 1;
    149 				break;
    150 			case 'l':
    151 			case 'u':
    152 				nextarg(&ap, &av);
    153 				break;
    154 			case 'L':
    155 				Lpath(nextarg(&ap, &av));
    156 				break;
    157 			case 'o':
    158 				output = nextarg(&ap, &av);
    159 				break;
    160 			case 'e':
    161 				entry = nextarg(&ap, &av);
    162 				break;
    163 			default:
    164 				usage();
    165 			}
    166 		}
    167 	}
    168 
    169 	if (!files)
    170 		usage();
    171 
    172 	atexit(cleanup);
    173 	ld(argc, argv);
    174 
    175 	return status;
    176 }