New Language: Ada
[gcc.git] / gcc / ada / gnatbl.c
1 /****************************************************************************
2 * *
3 * GNAT COMPILER TOOLS *
4 * *
5 * G N A T B L *
6 * *
7 * C Implementation File *
8 * *
9 * $Revision: 1.65 $
10 * *
11 * Copyright (C) 1992-2001 Free Software Foundation, Inc. *
12 * *
13 * GNAT is free software; you can redistribute it and/or modify it under *
14 * terms of the GNU General Public License as published by the Free Soft- *
15 * ware Foundation; either version 2, or (at your option) any later ver- *
16 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
17 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
19 * for more details. You should have received a copy of the GNU General *
20 * Public License distributed with GNAT; see file COPYING. If not, write *
21 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
22 * MA 02111-1307, USA. *
23 * *
24 * GNAT was originally developed by the GNAT team at New York University. *
25 * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
26 * *
27 ****************************************************************************/
28
29 #include "config.h"
30 #include "system.h"
31
32 #if defined (__EMX__) || defined (MSDOS)
33 #include <process.h>
34 #endif
35 #include "adaint.h"
36
37 #ifdef VMS
38 #ifdef exit
39 #undef exit
40 #endif
41 #define exit __posix_exit
42 #endif
43
44 /* These can be set by command line arguments */
45 char *binder_path = 0;
46 char *linker_path = 0;
47 char *exec_file_name = 0;
48 char *ali_file_name = 0;
49 #define BIND_ARG_MAX 512
50 char *bind_args[BIND_ARG_MAX];
51 int bind_arg_index = -1;
52 #ifdef MSDOS
53 char *coff2exe_path = 0;
54 char *coff2exe_args[] = {(char *) 0, (char *) 0};
55 char *del_command = 0;
56 #endif
57 int verbose = 0;
58 int o_present = 0;
59 int g_present = 0;
60
61 int link_arg_max = -1;
62 char **link_args = (char **) 0;
63 int link_arg_index = -1;
64
65 char *gcc_B_arg = 0;
66
67 #ifndef DIR_SEPARATOR
68 #if defined (__EMX__)
69 #define DIR_SEPARATOR '\\'
70 #else
71 #define DIR_SEPARATOR '/'
72 #endif
73 #endif
74
75 static int linkonly = 0;
76
77 static void addarg PARAMS ((char *));
78 static void process_args PARAMS ((int *, char *[]));
79 \f
80 static void
81 addarg (str)
82 char *str;
83 {
84 int i;
85
86 if (++link_arg_index >= link_arg_max)
87 {
88 char **new_link_args
89 = (char **) xcalloc (link_arg_max + 1000, sizeof (char *));
90
91 for (i = 0; i <= link_arg_max; i++)
92 new_link_args [i] = link_args [i];
93
94 if (link_args)
95 free (link_args);
96
97 link_arg_max += 1000;
98 link_args = new_link_args;
99 }
100
101 link_args [link_arg_index] = str;
102 }
103
104 static void
105 process_args (p_argc, argv)
106 int *p_argc;
107 char *argv[];
108 {
109 int i, j;
110
111 for (i = 1; i < *p_argc; i++)
112 {
113 /* -I is passed on to gnatbind */
114 if (! strncmp( argv[i], "-I", 2))
115 {
116 bind_arg_index += 1;
117 if (bind_arg_index >= BIND_ARG_MAX)
118 {
119 fprintf (stderr, "Too many arguments to gnatbind\n");
120 exit (-1);
121 }
122
123 bind_args[bind_arg_index] = argv[i];
124 }
125
126 /* -B is passed on to gcc */
127 if (! strncmp (argv [i], "-B", 2))
128 gcc_B_arg = argv[i];
129
130 /* -v turns on verbose option here and is passed on to gcc */
131
132 if (! strcmp (argv [i], "-v"))
133 verbose = 1;
134
135 if (! strcmp (argv [i], "-o"))
136 {
137 o_present = 1;
138 exec_file_name = argv [i + 1];
139 }
140
141 if (! strcmp (argv [i], "-g"))
142 g_present = 1;
143
144 if (! strcmp (argv [i], "-gnatbind"))
145 {
146 /* Explicit naming of binder. Grab the value then remove the
147 two arguments from the argument list. */
148 if ( i + 1 >= *p_argc )
149 {
150 fprintf (stderr, "Missing argument for -gnatbind\n");
151 exit (1);
152 }
153
154 binder_path = __gnat_locate_exec (argv [i + 1], (char *) ".");
155 if (!binder_path)
156 {
157 fprintf (stderr, "Could not locate binder: %s\n", argv [i + 1]);
158 exit (1);
159 }
160
161 for (j = i + 2; j < *p_argc; j++)
162 argv [j - 2] = argv [j];
163
164 (*p_argc) -= 2;
165 i--;
166 }
167
168 else if (! strcmp (argv [i], "-linkonly"))
169 {
170 /* Don't call the binder. Set the flag and then remove the
171 argument from the argument list. */
172 linkonly = 1;
173 for (j = i + 1; j < *p_argc; j++)
174 argv [j - 1] = argv [j];
175
176 (*p_argc) -= 1;
177 i--;
178 }
179
180 else if (! strcmp (argv [i], "-gnatlink"))
181 {
182 /* Explicit naming of binder. Grab the value then remove the
183 two arguments from the argument list. */
184 if (i + 1 >= *p_argc)
185 {
186 fprintf (stderr, "Missing argument for -gnatlink\n");
187 exit (1);
188 }
189
190 linker_path = __gnat_locate_exec (argv [i + 1], (char *) ".");
191 if (!linker_path)
192 {
193 fprintf (stderr, "Could not locate linker: %s\n", argv [i + 1]);
194 exit (1);
195 }
196
197 for (j = i + 2; j < *p_argc; j++)
198 argv [j - 2] = argv [j];
199 (*p_argc) -= 2;
200 i--;
201 }
202 }
203 }
204 extern int main PARAMS ((int, char **));
205
206 int
207 main (argc, argv)
208 int argc;
209 char **argv;
210 {
211 int i, j;
212 int done_an_ali = 0;
213 int retcode;
214 #ifdef VMS
215 /* Warning: getenv only retrieves the first directory in VAXC$PATH */
216 char *pathval =
217 strdup (__gnat_to_canonical_dir_spec (getenv ("VAXC$PATH"), 0));
218 #else
219 char *pathval = getenv ("PATH");
220 #endif
221 char *spawn_args [5];
222 int spawn_index = 0;
223
224 #if defined (__EMX__) || defined(MSDOS)
225 char *tmppathval = malloc (strlen (pathval) + 3);
226 strcpy (tmppathval, ".;");
227 pathval = strcat (tmppathval, pathval);
228 #endif
229
230 process_args (&argc , argv);
231
232 if (argc == 1)
233 {
234 fprintf
235 (stdout,
236 "Usage: %s 'name'.ali\n", argv[0]);
237 fprintf
238 (stdout,
239 " [-o exec_name] -- by default it is 'name'\n");
240 fprintf
241 (stdout,
242 " [-v] -- verbose mode\n");
243 fprintf
244 (stdout,
245 " [-linkonly] -- doesn't call binder\n");
246 fprintf
247 (stdout,
248 " [-gnatbind name] -- full name for gnatbind\n");
249 fprintf
250 (stdout,
251 " [-gnatlink name] -- full name for linker (gcc)\n");
252 fprintf
253 (stdout,
254 " [list of objects] -- non Ada binaries\n");
255 fprintf
256 (stdout,
257 " [linker options] -- other options for linker\n");
258 exit (1);
259 }
260
261 if (!binder_path && !linkonly)
262 binder_path = __gnat_locate_exec ((char *) "gnatbind", pathval);
263
264 if (!binder_path && !linkonly)
265 {
266 fprintf (stderr, "Couldn't locate gnatbind\n");
267 exit (1);
268 }
269
270 if (!linker_path)
271 linker_path = __gnat_locate_exec ((char *) "gnatlink", pathval);
272 if (!linker_path)
273 {
274 fprintf (stderr, "Couldn't locate gnatlink\n");
275 exit (1);
276 }
277
278 #ifdef MSDOS
279 coff2exe_path = __gnat_locate_regular_file ("coff2exe.bat", pathval);
280 if (!coff2exe_path)
281 {
282 fprintf (stderr, "Couldn't locate %s\n", "coff2exe.bat");
283 exit (1);
284 }
285 else
286 coff2exe_args[0] = coff2exe_path;
287 #endif
288
289 addarg (linker_path);
290
291 for (i = 1; i < argc; i++)
292 {
293 int arg_len = strlen (argv [i]);
294
295 if (arg_len > 4 && ! strcmp (&argv [i][arg_len - 4], ".ali"))
296 {
297 if (done_an_ali)
298 {
299 fprintf (stderr,
300 "Sorry - cannot handle more than one ALI file\n");
301 exit (1);
302 }
303
304 done_an_ali = 1;
305
306 if (__gnat_is_regular_file (argv [i]))
307 {
308 ali_file_name = argv[i];
309 if (!linkonly)
310 {
311 /* Run gnatbind */
312 spawn_index = 0;
313 spawn_args [spawn_index++] = binder_path;
314 spawn_args [spawn_index++] = ali_file_name;
315 for (j = 0 ; j <= bind_arg_index ; j++ )
316 spawn_args [spawn_index++] = bind_args [j];
317 spawn_args [spawn_index] = 0;
318
319 if (verbose)
320 {
321 int i;
322 for (i = 0; i < 2; i++)
323 printf ("%s ", spawn_args [i]);
324
325 putchar ('\n');
326 }
327
328 retcode = __gnat_portable_spawn (spawn_args);
329 if (retcode != 0)
330 exit (retcode);
331 }
332 }
333 else
334 addarg (argv [i]);
335 }
336 #ifdef MSDOS
337 else if (!strcmp (argv [i], "-o"))
338 {
339 addarg (argv [i]);
340 if (i < argc)
341 i++;
342
343 {
344 char *ptr = strstr (argv[i], ".exe");
345
346 arg_len = strlen (argv [i]);
347 coff2exe_args[1] = malloc (arg_len + 1);
348 strcpy (coff2exe_args[1], argv[i]);
349 if (ptr != NULL && strlen (ptr) == 4)
350 coff2exe_args[1][arg_len-4] = 0;
351
352 addarg (coff2exe_args[1]);
353 }
354 }
355 #endif
356 else
357 addarg (argv [i]);
358 }
359
360 if (! done_an_ali)
361 {
362 fprintf (stderr, "No \".ali\" file specified\n");
363 exit (1);
364 }
365
366 addarg (ali_file_name);
367 addarg (NULL);
368
369 if (verbose)
370 {
371 int i;
372
373 for (i = 0; i < link_arg_index; i++)
374 printf ("%s ", link_args [i]);
375
376 putchar ('\n');
377 }
378
379 retcode = __gnat_portable_spawn (link_args);
380 if (retcode != 0)
381 exit (retcode);
382
383 #ifdef MSDOS
384 retcode = __gnat_portable_spawn (coff2exe_args);
385 if (retcode != 0)
386 exit (retcode);
387
388 if (!g_present)
389 {
390 del_command = malloc (strlen (coff2exe_args[1]) + 5);
391 sprintf (del_command, "del %s", coff2exe_args[1]);
392 retcode = system (del_command);
393 }
394 #endif
395
396 exit(0);
397 }