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