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