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