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