Mercurial > hg > xemacs-beta
annotate lib-src/ellcc.c @ 5781:0853e1ec8529
Use alloca_{rawbytes,ibytes} in #'copy-file, #'insert-file-contents-internal
src/ChangeLog addition:
2014-01-20 Aidan Kehoe <kehoea@parhasard.net>
* fileio.c (Fcopy_file, Finsert_file_contents_internal):
Use alloca_{rawbytes,ibytes} here instead of the implicit alloca
on the stack; doesn't change where the buffers are allocated for
these two functions, but does mean that decisions about alloca
vs. malloc based on buffer size are made in the same place
(ultimately, the ALLOCA() macro).
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Mon, 20 Jan 2014 17:53:07 +0000 |
parents | 308d34e9f07d |
children |
rev | line source |
---|---|
428 | 1 /* ellcc.c - front-end for compiling Emacs modules |
2 Copyright (C) 1998, 1999 J. Kean Johnston. | |
996 | 3 Copyright (C) 2002 Jerry James. |
428 | 4 |
5 This file is part of XEmacs. | |
6 | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3983
diff
changeset
|
7 XEmacs is free software: you can redistribute it and/or modify it |
428 | 8 under the terms of the GNU General Public License as published by the |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3983
diff
changeset
|
9 Free Software Foundation, either version 3 of the License, or (at your |
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3983
diff
changeset
|
10 option) any later version. |
428 | 11 |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
3983
diff
changeset
|
18 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. |
428 | 19 Author: J. Kean Johnston (jkj@sco.com). |
20 Please mail bugs and suggestions to the XEmacs maintainer. | |
21 */ | |
22 | |
23 /* | |
24 Here's the scoop. We would really like this to be a shell script, but | |
25 the various Windows platforms don't have reliable scripting that suits | |
26 our needs. We don't want to rely on perl or some other such language | |
27 so we have to roll our own executable to act as a front-end for the | |
28 compiler. | |
29 | |
30 This program is used to invoke the compiler, the linker and to generate | |
31 the module specific documentation and initialization code. We assume we | |
32 are in 'compile' mode unless we encounter an argument which tells us | |
33 that we're not. We take all arguments and pass them on directly to the | |
34 compiler, except for a few which are specific to this program: | |
35 | |
36 --mode=VALUE This sets the program mode. VALUE can be one of | |
37 compile, link, init or verbose. | |
38 --mod-name=NAME Sets the module name to the string NAME. | |
39 --mod-title=TITLE Sets the module title to the string TITLE. | |
40 --mod-version=VER Sets the module version to the string VER. | |
41 | |
42 The idea is that Makefiles will use ellcc as the compiler for making | |
43 dynamic Emacs modules, and life should be as simple as: | |
44 | |
45 make CC=ellcc LD='ellcc --mode=link' | |
46 | |
47 The only additional requirement is an entry in the Makefile to produce | |
48 the module initialization file, which will usually be something along | |
49 the lines of: | |
50 | |
51 modinit.c: $(SRCS) | |
52 ellcc --mode=init --mod-name=\"$(MODNAME)\" \ | |
53 --mod-title=\"$(MODTITLE)\" --mod-version=\"$(MODVERSION)\" \ | |
54 -o $@ $(SRCS) | |
55 | |
56 See the samples for more details. | |
57 */ | |
58 | |
438 | 59 #include <config.h> |
428 | 60 #include <stdio.h> |
61 #include <stdlib.h> | |
442 | 62 #include <stddef.h> |
996 | 63 #include <stdarg.h> |
428 | 64 #include <string.h> |
65 #include <ctype.h> | |
66 #include <errno.h> | |
67 #include <sys/types.h> | |
68 | |
69 #ifdef HAVE_UNISTD_H | |
70 # include <unistd.h> | |
71 #endif /* HAVE_UNISTD_H */ | |
72 | |
73 #define EMODULES_GATHER_VERSION | |
996 | 74 #define EXEC_GROW_SIZE 4 |
438 | 75 |
76 #include <emodules.h> | |
77 #include <ellcc.h> /* Generated files must be included using <...> */ | |
1743 | 78 #include "compiler.h" |
1506 | 79 |
428 | 80 #ifndef HAVE_SHLIB |
81 int | |
82 main (int argc, char *argv[]) | |
83 { | |
84 fprintf (stderr, "Dynamic modules not supported on this platform\n"); | |
85 return EXIT_FAILURE; | |
86 } | |
87 #else | |
88 | |
89 /* | |
90 * Try to figure out the commands we need to use to create shared objects, | |
91 * and how to compile for PIC mode. | |
92 */ | |
93 | |
996 | 94 static char *progname; |
95 static char *mod_name = NULL; | |
96 static char *mod_version = NULL; | |
97 static char *mod_title = NULL; | |
98 static char *mod_output = NULL; | |
99 static int exec_argc = 1; | |
100 static int exec_length = 0; | |
101 static int *exec_args; | |
102 static int real_argc = 0; | |
103 static char **prog_argv; | |
104 | |
105 /* | |
106 * We allow the user to override things in the environment | |
107 */ | |
108 static char *ellcc, *ellld, *ellcflags, *ellldflags, *ellpicflags, | |
109 *elldllflags; | |
110 | |
111 #define OVERENV(STR,EVAR,DFLT) \ | |
112 do { \ | |
113 STR = getenv (EVAR); \ | |
114 if ((STR) == NULL) { \ | |
115 STR = DFLT; \ | |
116 } \ | |
117 } while(0) | |
118 | |
428 | 119 /* |
120 * xnew, xrnew -- allocate, reallocate storage | |
121 * | |
122 * SYNOPSIS: Type *xnew (int n, Type); | |
123 * Type *xrnew (OldPointer, int n, Type); | |
124 */ | |
125 #ifdef chkmalloc | |
126 # include "chkmalloc.h" | |
127 # define xnew(n,Type) ((Type *) trace_malloc (__FILE__, __LINE__, \ | |
128 (n) * sizeof (Type))) | |
129 # define xrnew(op,n,Type) ((Type *) trace_realloc (__FILE__, __LINE__, \ | |
130 (op), (n) * sizeof (Type))) | |
131 #else | |
132 # define xnew(n,Type) ((Type *) xmalloc ((n) * sizeof (Type))) | |
133 # define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type))) | |
134 #endif | |
996 | 135 |
136 /* | |
137 * Ellcc modes of operation | |
138 */ | |
139 | |
140 enum mode { ELLCC_COMPILE_MODE, ELLCC_LINK_MODE, ELLCC_INIT_MODE }; | |
428 | 141 |
996 | 142 #ifdef DEBUG |
1506 | 143 static const char *ellcc_mode_name (enum mode ellcc_mode) ATTRIBUTE_CONST; |
428 | 144 |
996 | 145 static const char * |
146 ellcc_mode_name (enum mode ellcc_mode) | |
147 { | |
148 switch (ellcc_mode) | |
149 { | |
150 case ELLCC_COMPILE_MODE: | |
151 return "compile"; | |
152 case ELLCC_LINK_MODE: | |
153 return "link"; | |
154 case ELLCC_INIT_MODE: | |
155 return "init"; | |
156 } | |
157 return ""; | |
158 } | |
159 #endif | |
428 | 160 |
161 /* | |
996 | 162 * Function Prototypes |
428 | 163 */ |
996 | 164 |
1506 | 165 static void *xmalloc (size_t size) ATTRIBUTE_MALLOC; |
166 static void *xrealloc (void *ptr, size_t size) ATTRIBUTE_MALLOC; | |
167 static char *xstrdup (char *) ATTRIBUTE_MALLOC; | |
1743 | 168 static DECLARE_DOESNT_RETURN (fatal (char *, ...)) PRINTF_ARGS (1, 2); |
996 | 169 static char ** add_string (char **, char *); |
170 static char ** add_to_argv (char **, const char *); | |
171 static char ** do_compile_mode (void); | |
172 static char ** do_link_mode (void); | |
173 static char ** do_init_mode (void); | |
174 | |
175 #define SSTR(S) ((S) != NULL ? (S) : "") | |
428 | 176 |
177 int | |
178 main (int argc, char *argv[]) | |
179 { | |
180 char *tmp; | |
996 | 181 char ** exec_argv; |
182 int i, done_mode = 0, verbose = 0; | |
183 enum mode ellcc_mode; | |
428 | 184 |
996 | 185 if (argc < 2) |
186 { | |
187 /* FIXME: Print usage output instead */ | |
188 fatal ("too few arguments"); | |
189 } | |
190 | |
428 | 191 prog_argv = argv; |
192 | |
442 | 193 #if defined(WIN32_NATIVE) |
428 | 194 tmp = strrchr (argv[0], '\\'); |
996 | 195 if (tmp != NULL) |
196 { | |
197 tmp++; | |
198 } | |
428 | 199 #elif !defined (VMS) |
200 tmp = strrchr (argv[0], '/'); | |
996 | 201 if (tmp != NULL) |
202 { | |
203 tmp++; | |
204 } | |
428 | 205 #else |
206 tmp = argv[0]; | |
207 #endif | |
208 | |
996 | 209 progname = (tmp == NULL) ? argv[0] : tmp; |
428 | 210 |
211 tmp = &progname[strlen(progname)-2]; | |
212 if (strcmp (tmp, "cc") == 0) | |
996 | 213 { |
214 ellcc_mode = ELLCC_COMPILE_MODE; | |
215 } | |
428 | 216 else if (strcmp (tmp, "ld") == 0) |
996 | 217 { |
218 ellcc_mode = ELLCC_LINK_MODE; | |
219 } | |
428 | 220 else if (strcmp (tmp, "it") == 0) |
996 | 221 { |
222 ellcc_mode = ELLCC_INIT_MODE; | |
223 } | |
224 else | |
225 { | |
226 ellcc_mode = ELLCC_COMPILE_MODE; | |
227 } | |
428 | 228 |
229 exec_args = xnew(argc, int); | |
230 exec_args[0] = 0; | |
996 | 231 for (i = 1; i < argc; i++) |
232 { | |
233 exec_args[i] = -1; | |
234 } | |
428 | 235 |
236 for (i = 1; i < argc; i++) | |
237 { | |
996 | 238 if (strncmp (argv[i], "--mode=", (size_t)7) == 0) |
428 | 239 { |
996 | 240 char *modeopt = &argv[i][7]; |
428 | 241 |
996 | 242 if (done_mode && strcmp (modeopt, "verbose") != 0) |
243 { | |
244 fatal ("more than one mode specified"); | |
245 } | |
428 | 246 if (strcmp (modeopt, "link") == 0) |
247 { | |
248 done_mode++; | |
249 ellcc_mode = ELLCC_LINK_MODE; | |
250 } | |
251 else if (strcmp (modeopt, "compile") == 0) | |
252 { | |
253 done_mode++; | |
254 ellcc_mode = ELLCC_COMPILE_MODE; | |
255 } | |
256 else if (strcmp (modeopt, "init") == 0) | |
257 { | |
258 done_mode++; | |
259 ellcc_mode = ELLCC_INIT_MODE; | |
260 } | |
261 else if (strcmp (modeopt, "verbose") == 0) | |
996 | 262 { |
263 verbose++; | |
264 } | |
265 else | |
266 { | |
267 fatal ("Mode must be link, compile, init, or verbose"); | |
268 } | |
428 | 269 } |
270 else if (strcmp (argv[i], "--mod-location") == 0) | |
271 { | |
272 printf ("%s\n", ELLCC_MODDIR); | |
996 | 273 exit (EXIT_SUCCESS); |
428 | 274 } |
275 else if (strcmp (argv[i], "--mod-site-location") == 0) | |
276 { | |
277 printf ("%s\n", ELLCC_SITEMODS); | |
996 | 278 exit (EXIT_SUCCESS); |
428 | 279 } |
280 else if (strcmp (argv[i], "--mod-archdir") == 0) | |
281 { | |
282 printf ("%s\n", ELLCC_ARCHDIR); | |
996 | 283 exit (EXIT_SUCCESS); |
428 | 284 } |
285 else if (strcmp (argv[i], "--mod-config") == 0) | |
286 { | |
287 printf ("%s\n", ELLCC_CONFIG); | |
996 | 288 exit (EXIT_SUCCESS); |
428 | 289 } |
996 | 290 else if (strncmp (argv[i], "--mod-name=", (size_t)11) == 0) |
291 { | |
292 mod_name = &argv[i][11]; | |
293 } | |
294 else if (strncmp (argv[i], "--mod-title=", (size_t)12) == 0) | |
295 { | |
296 mod_title = &argv[i][12]; | |
297 } | |
298 else if (strncmp (argv[i], "--mod-version=", (size_t)14) == 0) | |
299 { | |
300 mod_version = &argv[i][14]; | |
301 } | |
302 else if (strncmp (argv[i], "--mod-output=", (size_t)13) == 0) | |
303 { | |
304 mod_output = &argv[i][13]; | |
305 } | |
428 | 306 else |
307 { | |
308 exec_args[exec_argc] = i; | |
309 exec_argc++; | |
310 } | |
311 } | |
312 | |
996 | 313 if (ellcc_mode == ELLCC_LINK_MODE && mod_output == NULL) |
314 { | |
315 fatal ("must specify --mod-output when linking"); | |
316 } | |
317 if (ellcc_mode == ELLCC_INIT_MODE && mod_output == NULL) | |
318 { | |
319 fatal ("must specify --mod-output when creating init file"); | |
320 } | |
321 if (ellcc_mode == ELLCC_INIT_MODE && mod_name == NULL) | |
322 { | |
323 fatal ("must specify --mod-name when creating init file"); | |
324 } | |
428 | 325 |
326 /* | |
327 * We now have the list of arguments to pass to the compiler or | |
996 | 328 * linker (or to process for doc files). We can do the real work now. |
428 | 329 */ |
330 if (verbose) | |
996 | 331 { |
332 printf ("ellcc driver version %s for EMODULES version %s (%ld)\n", | |
333 ELLCC_EMACS_VER, EMODULES_VERSION, EMODULES_REVISION); | |
334 } | |
335 | |
428 | 336 #ifdef DEBUG |
337 if (verbose >= 2) | |
338 { | |
996 | 339 printf (" mode = %d (%s)\n", (int)ellcc_mode, |
340 ellcc_mode_name (ellcc_mode)); | |
428 | 341 printf (" module_name = \"%s\"\n", SSTR(mod_name)); |
342 printf (" module_title = \"%s\"\n", SSTR(mod_title)); | |
343 printf (" module_version = \"%s\"\n", SSTR(mod_version)); | |
344 | |
345 printf (" CC = %s\n", ELLCC_CC); | |
346 printf (" CFLAGS = %s\n", ELLCC_CFLAGS); | |
347 printf (" CC PIC flags = %s\n", ELLCC_DLL_CFLAGS); | |
348 printf (" LD = %s\n", ELLCC_DLL_LD); | |
349 printf (" LDFLAGS = %s\n", ELLCC_DLL_LDFLAGS); | |
350 printf (" architecture = %s\n", ELLCC_CONFIG); | |
351 printf (" Include directory = %s/include\n", ELLCC_ARCHDIR); | |
352 printf ("\n"); | |
353 } | |
354 #endif | |
355 | |
356 if (exec_argc < 2) | |
996 | 357 { |
358 /* FIXME: Print usage output instead */ | |
359 fatal ("too few arguments"); | |
360 } | |
428 | 361 |
362 /* | |
996 | 363 * Get the overrides from the environment |
428 | 364 */ |
365 OVERENV(ellcc, "ELLCC", ELLCC_CC); | |
366 OVERENV(ellld, "ELLLD", ELLCC_DLL_LD); | |
367 OVERENV(ellcflags, "ELLCFLAGS", ELLCC_CFLAGS); | |
368 OVERENV(ellldflags, "ELLLDFLAGS", ELLCC_LDFLAGS); | |
369 OVERENV(elldllflags, "ELLDLLFLAGS", ELLCC_DLL_LDFLAGS); | |
370 OVERENV(ellpicflags, "ELLPICFLAGS", ELLCC_DLL_CFLAGS); | |
371 | |
996 | 372 switch (ellcc_mode) |
373 { | |
374 case ELLCC_COMPILE_MODE: | |
375 exec_argv = do_compile_mode (); | |
376 break; | |
377 case ELLCC_LINK_MODE: | |
378 exec_argv = do_link_mode (); | |
379 break; | |
380 default: | |
381 exec_argv = do_init_mode (); | |
382 break; | |
383 } | |
428 | 384 |
385 /* | |
386 * The arguments to pass on to the desired program have now been set | |
387 * up and we can run the program. | |
388 */ | |
389 if (verbose) | |
390 { | |
391 for (i = 0; i < real_argc; i++) | |
996 | 392 { |
393 printf ("%s ", exec_argv[i]); | |
394 } | |
428 | 395 printf ("\n"); |
996 | 396 (void)fflush (stdout); |
428 | 397 } |
996 | 398 |
399 /* Terminate argument list. */ | |
400 exec_argv = add_string (exec_argv, NULL); | |
428 | 401 |
402 i = execvp (exec_argv[0], exec_argv); | |
403 if (verbose) | |
996 | 404 { |
405 printf ("%s exited with status %d\n", exec_argv[0], i); | |
406 } | |
407 exit (i); | |
428 | 408 } |
409 | |
410 /* Like malloc but get fatal error if memory is exhausted. */ | |
411 static void * | |
412 xmalloc (size_t size) | |
413 { | |
414 void *result = malloc (size); | |
415 if (result == NULL) | |
996 | 416 { |
417 fatal ("virtual memory exhausted"); | |
418 } | |
419 return result; | |
420 } | |
421 | |
422 /* Like realloc but get fatal error if memory is exhausted. */ | |
423 static void * | |
424 xrealloc (void *ptr, size_t size) | |
425 { | |
426 void *result = realloc (ptr, size); | |
427 if (result == NULL) | |
428 { | |
429 fatal ("virtual memory exhausted"); | |
430 } | |
431 return result; | |
432 } | |
433 | |
434 /* Like strdup but get fatal error if memory is exhausted. */ | |
435 static char * | |
436 xstrdup (char *s) | |
437 { | |
438 char *result = strdup (s); | |
439 if (result == NULL) | |
440 { | |
441 fatal ("virtual memory exhausted"); | |
442 } | |
428 | 443 return result; |
444 } | |
445 | |
446 /* Print error message and exit. */ | |
1743 | 447 static DOESNT_RETURN |
996 | 448 fatal (char *format, ...) |
428 | 449 { |
996 | 450 va_list ap; |
451 | |
452 va_start (ap, format); | |
453 (void)fprintf (stderr, "%s: ", progname); | |
454 (void)vfprintf (stderr, format, ap); | |
455 (void)fprintf (stderr, "\n"); | |
456 va_end (ap); | |
428 | 457 exit (EXIT_FAILURE); |
458 } | |
459 | |
996 | 460 static char ** |
461 add_string (char **exec_argv, char *str) | |
462 { | |
463 if (real_argc >= exec_length) | |
464 { | |
465 exec_length = real_argc + EXEC_GROW_SIZE; | |
466 exec_argv = xrnew (exec_argv, exec_length, char *); | |
467 } | |
468 exec_argv[real_argc++] = str; | |
469 return exec_argv; | |
470 } | |
471 | |
428 | 472 /* |
473 * Add a string to the argument vector list that will be passed on down | |
474 * to the compiler or linker. We need to split individual words into | |
996 | 475 * arguments, taking quoting into account. |
428 | 476 */ |
996 | 477 static char ** |
478 add_to_argv (char **exec_argv, const char *str) | |
428 | 479 { |
996 | 480 /* Don't add nonexistent strings */ |
481 if (str == NULL) | |
428 | 482 { |
996 | 483 return exec_argv; |
484 } | |
428 | 485 |
996 | 486 /* Skip leading whitespace */ |
487 while (isspace (*str)) | |
488 { | |
489 str++; | |
490 } | |
428 | 491 |
996 | 492 /* Don't add nonexistent strings */ |
493 if (*str == '\0') | |
494 { | |
495 return exec_argv; | |
428 | 496 } |
497 | |
996 | 498 while (*str != '\0') |
428 | 499 { |
996 | 500 const char *s; |
501 char *arg; | |
502 int l; | |
503 | |
504 s = str; /* Mark the start of THIS argument */ | |
505 | |
506 /* Find contiguous nonwhitespace characters */ | |
507 while (*str != '\0' && !isspace(*str)) | |
508 { | |
509 if (*str == '\\') /* Escaped character */ | |
510 { | |
511 str++; | |
512 if (*str != '\0') | |
513 { | |
514 str++; | |
515 } | |
516 } | |
517 else if (*str == '\'') | |
518 { | |
519 str++; | |
520 while (*str != '\0' && *str != '\'') | |
521 { | |
522 if (str[0] == '\\' && str[1] != '\0') | |
523 { | |
524 str += 2; | |
525 } | |
526 else | |
527 { | |
528 str++; | |
529 } | |
530 } | |
531 if (*str == '\'') | |
532 { | |
533 str++; | |
534 } | |
535 } | |
536 else if (*str == '\"') | |
537 { | |
538 str++; | |
539 while (*str != '\0' && *str != '\"') | |
540 { | |
541 if (str[0] == '\\' && str[1] != '\0') | |
542 { | |
543 str += 2; | |
544 } | |
545 else | |
546 { | |
547 str++; | |
548 } | |
549 } | |
550 if (*str == '\"') | |
551 { | |
552 str++; | |
553 } | |
554 } | |
555 else | |
556 { | |
557 str++; /* Normal character. Advance the pointer. */ | |
558 } | |
559 } | |
560 | |
561 /* Reached the end of the argument. Add it. */ | |
562 l = str-s; | |
563 arg = xnew(l+1, char); | |
564 strncpy(arg, s, (size_t)l); | |
565 arg[l] = '\0'; | |
566 exec_argv = add_string (exec_argv, arg); | |
567 | |
568 /* Skip trailing whitespace */ | |
569 while (isspace (*str)) | |
570 { | |
571 str++; | |
572 } | |
428 | 573 } |
996 | 574 |
575 return exec_argv; | |
428 | 576 } |
577 | |
578 /* | |
579 * For compile mode, things are pretty straight forward. All we need to do | |
580 * is build up the argument vector and exec() it. We must just make sure | |
581 * that we get all of the required arguments in place. | |
582 */ | |
996 | 583 static char ** |
428 | 584 do_compile_mode (void) |
585 { | |
586 int i; | |
996 | 587 char **exec_argv = xnew (exec_argc + 20, char *); |
428 | 588 |
996 | 589 exec_argv = add_to_argv (exec_argv, ellcc); |
1269 | 590 exec_argv = add_to_argv (exec_argv, ELLCC_CF_ALL); |
996 | 591 exec_argv = add_to_argv (exec_argv, ellcflags); |
592 exec_argv = add_to_argv (exec_argv, ellpicflags); | |
593 exec_argv = add_to_argv (exec_argv, "-DPIC"); | |
594 exec_argv = add_to_argv (exec_argv, "-DEMACS_MODULE"); | |
428 | 595 #ifdef XEMACS |
996 | 596 /* Cover both cases */ |
597 exec_argv = add_to_argv (exec_argv, "-DXEMACS_MODULE"); | |
598 exec_argv = add_to_argv (exec_argv, "-Dxemacs"); | |
428 | 599 #endif |
996 | 600 exec_argv = add_to_argv (exec_argv, "-Demacs"); |
428 | 601 for (i = 1; i < exec_argc; i++) |
996 | 602 { |
603 exec_argv = add_string (exec_argv, xstrdup (prog_argv[exec_args[i]])); | |
604 } | |
605 return exec_argv; | |
428 | 606 } |
607 | |
608 /* | |
609 * For link mode, things are a little bit more complicated. We need to | |
610 * insert the linker commands first, replace any occurrence of ELLSONAME | |
611 * with the desired output file name, insert the output arguments, then | |
612 * all of the provided arguments, then the final post arguments. Once | |
613 * all of this has been done, the argument vector is ready to run. | |
614 */ | |
996 | 615 static char ** |
428 | 616 do_link_mode (void) |
617 { | |
618 int i,x; | |
996 | 619 char *t, *ts; |
620 char **exec_argv = xnew(exec_argc + 10, char *); | |
428 | 621 |
996 | 622 exec_argv = add_to_argv (exec_argv, ellld); |
623 exec_argv = add_to_argv (exec_argv, ellldflags); | |
624 exec_argv = add_to_argv (exec_argv, elldllflags); | |
625 exec_argv = add_to_argv (exec_argv, ELLCC_DLL_LDO); | |
626 exec_argv = add_to_argv (exec_argv, mod_output); | |
428 | 627 for (i = 1; i < exec_argc; i++) |
996 | 628 { |
629 exec_argv = add_string (exec_argv, xstrdup (prog_argv[exec_args[i]])); | |
630 } | |
631 exec_argv = add_to_argv (exec_argv, ELLCC_DLL_POST); | |
428 | 632 |
633 /* | |
634 * Now go through each argument and replace ELLSONAME with mod_output. | |
635 */ | |
636 for (i = 0; i < real_argc; i++) | |
637 { | |
638 x = 0; | |
996 | 639 ts = xnew (2 * strlen (exec_argv[i]), char); |
428 | 640 ts[0] = '\0'; |
641 | |
642 t = exec_argv[i]; | |
996 | 643 while (*t != '\0') |
428 | 644 { |
645 if (*t == 'E') | |
646 { | |
996 | 647 if (strncmp (t, "ELLSONAME", (size_t)9) == 0) |
428 | 648 { |
649 strcat (ts, mod_output); | |
996 | 650 x += strlen (mod_output); |
428 | 651 t += 8; |
652 } | |
653 else | |
654 { | |
655 ts[x] = *t; | |
656 x++; | |
657 ts[x] = '\0'; | |
658 } | |
659 } | |
660 else | |
661 { | |
662 ts[x] = *t; | |
663 x++; | |
664 ts[x] = '\0'; | |
665 } | |
666 t++; | |
667 } | |
668 free (exec_argv[i]); | |
996 | 669 exec_argv[i] = ts; |
428 | 670 } |
996 | 671 return exec_argv; |
428 | 672 } |
673 | |
674 /* | |
675 * In init mode, things are a bit easier. We assume that the only things | |
676 * passed on the command line are the names of source files which the | |
677 * make-doc program will be processing. We prepare the output file with | |
678 * the header information first, as make-doc will append to the file by | |
679 * special dispensation. | |
680 */ | |
996 | 681 static char ** |
428 | 682 do_init_mode (void) |
683 { | |
684 int i; | |
996 | 685 char *ts, *mdocprog; |
686 char **exec_argv = xnew(exec_argc + 8, char *); | |
428 | 687 FILE *mout = fopen (mod_output, "w"); |
688 | |
996 | 689 if (mout == NULL) |
690 { | |
691 fatal ("Failed to open output file %s", mod_output); | |
692 } | |
428 | 693 fprintf (mout, "/* DO NOT EDIT - AUTOMATICALLY GENERATED */\n\n"); |
694 fprintf (mout, "#include <emodules.h>\n\n"); | |
1706 | 695 fprintf (mout, "#ifdef __cplusplus\n"); |
696 fprintf (mout, "extern \"C\" {\n"); | |
697 fprintf (mout, "#endif\n"); | |
698 fprintf (mout, "extern const long emodule_compiler;\n"); | |
699 fprintf (mout, "extern const char *emodule_name, *emodule_version, *emodule_title;\n"); | |
700 fprintf (mout, "extern void docs_of_%s (void);\n", SSTR(mod_name)); | |
701 fprintf (mout, "#ifdef __cplusplus\n"); | |
702 fprintf (mout, "}\n"); | |
703 fprintf (mout, "#endif\n\n"); | |
428 | 704 fprintf (mout, "const long emodule_compiler = %ld;\n", EMODULES_REVISION); |
705 fprintf (mout, "const char *emodule_name = \"%s\";\n", SSTR(mod_name)); | |
706 fprintf (mout, "const char *emodule_version = \"%s\";\n", SSTR(mod_version)); | |
1706 | 707 fprintf (mout, "const char *emodule_title = \"%s\";\n\n", SSTR(mod_title)); |
708 fprintf (mout, "void docs_of_%s ()\n", SSTR(mod_name)); | |
996 | 709 if (fclose (mout) != 0) |
710 { | |
711 fatal ("Failed to close output file %s", mod_output); | |
712 } | |
428 | 713 |
996 | 714 mdocprog = getenv ("ELLMAKEDOC"); |
715 if (mdocprog == NULL) | |
716 { | |
717 mdocprog = xnew (14 + strlen (ELLCC_ARCHDIR), char); | |
718 sprintf (mdocprog, "%s/make-docfile", ELLCC_ARCHDIR); | |
3983 | 719 exec_argv = add_to_argv (exec_argv, mdocprog); |
720 free (mdocprog); | |
996 | 721 } |
3983 | 722 else |
723 { | |
724 exec_argv = add_to_argv (exec_argv, mdocprog); | |
725 } | |
996 | 726 ts = xnew (4 + strlen (mod_output), char); |
428 | 727 sprintf (ts, "-E %s", mod_output); |
996 | 728 exec_argv = add_to_argv (exec_argv, ts); |
729 free (ts); | |
428 | 730 for (i = 1; i < exec_argc; i++) |
996 | 731 { |
732 exec_argv = add_string (exec_argv, xstrdup (prog_argv[exec_args[i]])); | |
733 } | |
734 return exec_argv; | |
428 | 735 } |
736 | |
737 #endif /* HAVE_SHLIB */ |