ranlib: fix it
[odcctools-svp.git] / as / driver.c
blob3594aa313b4e4445b9a91943b231734959471c16
1 /*
2 * The assembler driver that lives in /bin/as and runs the assembler for the
3 * "-arch <arch_flag>" (if given) in /usr/libexec/gcc/darwin/<arch_flag>/as or
4 * in /usr/local/libexec/gcc/darwin/<arch_flag>/as. Or runs the assembler for
5 * the host architecture as returned by get_arch_from_host(). The driver only
6 * checks to make sure their are not multiple arch_flags and then passes all
7 * flags to the assembler it will run.
8 */
9 #include "stdio.h"
10 #include "stdlib.h"
11 #include "string.h"
12 #include "libc.h"
13 #include <sys/file.h>
14 #include <mach/mach.h>
15 #include "stuff/arch.h"
16 #include "stuff/errors.h"
17 #include "stuff/execute.h"
18 #include "stuff/allocate.h"
19 #include <mach-o/dyld.h>
21 /* used by error calls (exported) */
22 char *progname = NULL;
24 int
25 main(
26 int argc,
27 char **argv,
28 char **envp)
30 const char *LIB =
31 ASLIBEXECDIR;
32 #if 0
33 #if defined(__OPENSTEP__) || defined(__HERA__) || \
34 defined(__GONZO_BUNSEN_BEAKER__) || defined(__KODIAK__)
35 "../libexec/";
36 #else
37 "../libexec/gcc/darwin/";
38 #endif
39 const char *LOCALLIB =
40 #if defined(__OPENSTEP__) || defined(__HERA__) || \
41 defined(__GONZO_BUNSEN_BEAKER__) || defined(__KODIAK__)
42 "../local/libexec/";
43 #else
44 "../local/libexec/gcc/darwin/";
45 #endif
46 #endif
47 const char *AS = "/as";
49 int i;
50 unsigned long count, verbose;
51 char *p, c, *arch_name, *as, *as_local;
52 char *prefix, buf[MAXPATHLEN], resolved_name[PATH_MAX];
53 uint32_t bufsize;
54 struct arch_flag arch_flag;
55 const struct arch_flag *arch_flags, *family_arch_flag;
57 progname = argv[0];
58 arch_name = NULL;
59 verbose = 0;
60 #if 0
62 * Construct the prefix to the assembler driver.
64 bufsize = MAXPATHLEN;
65 p = buf;
66 i = _NSGetExecutablePath(p, &bufsize);
67 if(i == -1){
68 p = allocate(bufsize);
69 _NSGetExecutablePath(p, &bufsize);
71 prefix = realpath(p, resolved_name);
72 p = rindex(prefix, '/');
73 if(p != NULL)
74 p[1] = '\0';
75 #else
76 prefix = "";
77 #endif
79 * Process the assembler flags exactly like the assembler would (except
80 * let the assembler complain about multiple flags, bad combinations of
81 * flags, unknown single letter flags and the like). The main thing
82 * here is to parse out the "-arch <arch_flag>" and to do so the
83 * multiple argument and multiple character flags need to be known how
84 * to be stepped over correctly.
86 for(i = 1; i < argc; i++){
88 * The assembler flags start with '-' except that "--" is recognized
89 * as assemble from stdin and that flag "--" is not allowed to be
90 * grouped with other flags (so "-a-" is not the same as "-a --").
92 if(argv[i][0] == '-' &&
93 !(argv[i][1] == '-' && argv[i][2] == '0')){
95 * the assembler allows single letter flags to be grouped
96 * together so "-abc" is the same as "-a -b -c". So that
97 * logic must be followed here.
99 for(p = &(argv[i][1]); (c = *p); p++){
101 * The assembler simply ignores the high bit of flag
102 * characters and not treat them as different characters
103 * as they are (but the argument following the flag
104 * character is not treated this way). So it's done
105 * here as well to match it.
107 c &= 0x7F;
108 switch(c){
110 * Flags that take a single argument. The argument is the
111 * rest of the current argument if there is any or the it is
112 * the next argument. Again errors like missing arguments
113 * are not handled here but left to the assembler.
115 case 'o': /* -o name */
116 case 'I': /* -I directory */
117 case 'm': /* -mc68000, -mc68010 and mc68020 */
118 case 'N': /* -NEXTSTEP-deployment-target */
119 if(p[1] == '\0')
120 i++;
121 break;
123 case 'a':
124 if(strcmp(p, "arch") == 0){
125 if(i + 1 >= argc)
126 fatal("missing argument to %s option", argv[i]);
127 if(arch_name != NULL)
128 fatal("more than one %s option (not allowed, "
129 "use cc(1) instead)", argv[i]);
130 arch_name = argv[i+1];
131 break;
133 /* fall through for non "-arch" */
134 case 'f':
135 case 'k':
136 case 'g':
137 case 'v':
138 case 'W':
139 case 'L':
140 case 'l':
141 default:
142 /* just recognize it, do nothing */
143 break;
144 case 'V':
145 verbose = 1;
146 break;
153 * Construct the name of the assembler to run from the given -arch
154 * <arch_flag> or if none then from the value returned from
155 * get_arch_from_host().
157 if(arch_name == NULL){
158 if(get_arch_from_host(&arch_flag, NULL))
159 arch_name = arch_flag.name;
160 else
161 fatal("unknown host architecture (can't determine which "
162 "assembler to run)");
164 else{
166 * Convert a possible machine specific architecture name to a
167 * family name to base the name of the assembler to run.
169 if(get_arch_from_flag(arch_name, &arch_flag) != 0){
170 family_arch_flag =
171 get_arch_family_from_cputype(arch_flag.cputype);
172 if(family_arch_flag != NULL)
173 arch_name = (char *)(family_arch_flag->name);
177 as = makestr(prefix, LIB, arch_name, AS, NULL);
180 * If this assembler exist try to run it else print an error message.
182 if(access(as, F_OK) == 0){
183 argv[0] = as;
184 if(execute(argv, verbose))
185 exit(0);
186 else
187 exit(1);
189 as_local = "";
190 #if 0
191 as_local = makestr(prefix, LOCALLIB, arch_name, AS, NULL);
192 if(access(as_local, F_OK) == 0){
193 argv[0] = as_local;
194 if(execute(argv, verbose))
195 exit(0);
196 else
197 exit(1);
199 else
200 #endif
202 printf("%s: assembler (%s or %s) for architecture %s not "
203 "installed\n", progname, as, as_local, arch_name);
204 arch_flags = get_arch_flags();
205 count = 0;
206 for(i = 0; arch_flags[i].name != NULL; i++){
207 as = makestr(prefix, LIB, arch_flags[i].name, AS, NULL);
208 if(access(as, F_OK) == 0){
209 if(count == 0)
210 printf("Installed assemblers are:\n");
211 printf("%s for architecture %s\n", as, arch_flags[i].name);
212 count++;
214 #if 0
215 else{
216 as_local = makestr(prefix, LOCALLIB, arch_flags[i].name,
217 AS, NULL);
218 if(access(as_local, F_OK) == 0){
219 if(count == 0)
220 printf("Installed assemblers are:\n");
221 printf("%s for architecture %s\n", as_local,
222 arch_flags[i].name);
223 count++;
226 #endif
228 if(count == 0)
229 printf("%s: no assemblers installed\n", progname);
230 exit(1);
232 return(0);