Mercurial > hg > xemacs-beta
annotate lib-src/ellcc.c @ 5819:ba0ff364bd94
Repair invalid GNU-style key-bindings.
author | Stephen J. Turnbull <stephen@xemacs.org> |
---|---|
date | Sat, 18 Oct 2014 23:21:30 +0900 |
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 */ |