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