Ensure packet is parented correctly
[freeradius.git] / scripts / jlibtool.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *       http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #if !defined(__MINGW32__)
25 #  include <sys/wait.h>
26 #endif
27
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <errno.h>
31 #include <assert.h>
32
33 #ifdef __EMX__
34 #  define SHELL_CMD                     "sh"
35 #  define GEN_EXPORTS                   "emxexp"
36 #  define DEF2IMPLIB_CMD                "emximp"
37 #  define SHARE_SW                      "-Zdll -Zmtd"
38 #  define USE_OMF 1
39 #  define TRUNCATE_DLL_NAME
40 #  define DYNAMIC_LIB_EXT               "dll"
41 #  define EXE_EX                        ".exe"
42 /* OMF is the native format under OS/2 */
43 #  if USE_OMF
44
45 #    define STATIC_LIB_EXT              "lib"
46 #    define OBJECT_EXT                  "obj"
47 #    define LIBRARIAN                   "emxomfar"
48 #    define LIBRARIAN_OPTS              "cr"
49 #  else
50 /* but the alternative, a.out, can fork() which is sometimes necessary */
51 #    define STATIC_LIB_EXT              "a"
52 #    define OBJECT_EXT                  "o"
53 #    define LIBRARIAN                   "ar"
54 #    define LIBRARIAN_OPTS              "cr"
55 #  endif
56 #endif
57
58 #if defined(__APPLE__)
59 #  define SHELL_CMD                     "/bin/sh"
60 #  define DYNAMIC_LIB_EXT               "dylib"
61 #  define MODULE_LIB_EXT                "bundle"
62 #  define STATIC_LIB_EXT                "a"
63 #  define OBJECT_EXT                    "o"
64 #  define LIBRARIAN                     "ar"
65 #  define LIBRARIAN_OPTS                "cr"
66 /* man libtool(1) documents ranlib option of -c.  */
67 #  define RANLIB                        "ranlib"
68 #  define PIC_FLAG                      "-fPIC -fno-common"
69 #  define SHARED_OPTS                   "-dynamiclib"
70 #  define MODULE_OPTS                   "-bundle -dynamic"
71 #  define DYNAMIC_LINK_OPTS             "-flat_namespace"
72 #  define DYNAMIC_LINK_UNDEFINED        "-undefined suppress"
73 #  define dynamic_link_version_func     darwin_dynamic_link_function
74 #  define DYNAMIC_INSTALL_NAME          "-install_name"
75 #  define DYNAMIC_LINK_NO_INSTALL       "-dylib_file"
76 #  define HAS_REALPATH
77 /*-install_name  /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
78 #  define LD_LIBRARY_PATH               "DYLD_LIBRARY_PATH"
79 #  define LD_LIBRARY_PATH_LOCAL         "DYLD_FALLBACK_LIBRARY_PATH"
80 #endif
81
82 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
83 #  define SHELL_CMD                     "/bin/sh"
84 #  define DYNAMIC_LIB_EXT               "so"
85 #  define MODULE_LIB_EXT                "so"
86 #  define STATIC_LIB_EXT                "a"
87 #  define OBJECT_EXT                    "o"
88 #  define LIBRARIAN                     "ar"
89 #  define LIBRARIAN_OPTS                "cr"
90 #  define RANLIB                        "ranlib"
91 #  define PIC_FLAG                      "-fPIC"
92 #  define RPATH                         "-rpath"
93 #  define SHARED_OPTS                   "-shared"
94 #  define MODULE_OPTS                   "-shared"
95 #  define LINKER_FLAG_PREFIX            "-Wl,"
96 #  define DYNAMIC_LINK_OPTS             LINKER_FLAG_PREFIX "-export-dynamic"
97 #  define ADD_MINUS_L
98 #  define LD_RUN_PATH                   "LD_RUN_PATH"
99 #  define LD_LIBRARY_PATH               "LD_LIBRARY_PATH"
100 #  define LD_LIBRARY_PATH_LOCAL         LD_LIBRARY_PATH
101 #endif
102
103 #if defined(__sun)
104 #  define SHELL_CMD                     "/bin/sh"
105 #  define DYNAMIC_LIB_EXT               "so"
106 #  define MODULE_LIB_EXT                "so"
107 #  define STATIC_LIB_EXT                "a"
108 #  define OBJECT_EXT                    "o"
109 #  define LIBRARIAN                     "ar"
110 #  define LIBRARIAN_OPTS                "cr"
111 #  define RANLIB                        "ranlib"
112 #  define PIC_FLAG                      "-fPIC"
113 #  define RPATH                         "-R"
114 #  define SHARED_OPTS                   "-G"
115 #  define MODULE_OPTS                   "-G"
116 #  define DYNAMIC_LINK_OPTS             ""
117 #  define LINKER_FLAG_NO_EQUALS
118 #  define ADD_MINUS_L
119 #  define HAS_REALPATH
120 #  define LD_RUN_PATH                   "LD_RUN_PATH"
121 #  define LD_LIBRARY_PATH               "LD_LIBRARY_PATH"
122 #  define LD_LIBRARY_PATH_LOCAL         LD_LIBRARY_PATH
123 #endif
124
125 #if defined(_OSD_POSIX)
126 #  define SHELL_CMD                     "/usr/bin/sh"
127 #  define DYNAMIC_LIB_EXT               "so"
128 #  define MODULE_LIB_EXT                "so"
129 #  define STATIC_LIB_EXT                "a"
130 #  define OBJECT_EXT                    "o"
131 #  define LIBRARIAN                     "ar"
132 #  define LIBRARIAN_OPTS                "cr"
133 #  define SHARED_OPTS                   "-G"
134 #  define MODULE_OPTS                   "-G"
135 #  define LINKER_FLAG_PREFIX            "-Wl,"
136 #  define NEED_SNPRINTF
137 #endif
138
139 #if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
140 #  define SHELL_CMD                     "/usr/bin/sh"
141 #  define DYNAMIC_LIB_EXT               "so"
142 #  define MODULE_LIB_EXT                "so"
143 #  define STATIC_LIB_EXT                "a"
144 #  define OBJECT_EXT                    "o"
145 #  define LIBRARIAN                     "ar"
146 #  define LIBRARIAN_OPTS                "cr"
147 #  define RPATH                         "-Brpath"
148 #  define SHARED_OPTS                   "-G"
149 #  define MODULE_OPTS                   "-G"
150 #  define LINKER_FLAG_PREFIX            "-Wl,"
151 #  define DYNAMIC_LINK_OPTS             LINKER_FLAG_PREFIX "-Blargedynsym"
152
153 #  define NEED_SNPRINTF
154 #  define LD_RUN_PATH                   "LD_RUN_PATH"
155 #  define LD_LIBRARY_PATH               "LD_LIBRARY_PATH"
156 #  define LD_LIBRARY_PATH_LOCAL         LD_LIBRARY_PATH
157 #endif
158
159 #if defined(__MINGW32__)
160 #  define SHELL_CMD                     "sh"
161 #  define DYNAMIC_LIB_EXT               "dll"
162 #  define MODULE_LIB_EXT                "dll"
163 #  define STATIC_LIB_EXT                "a"
164 #  define OBJECT_EXT                    "o"
165 #  define LIBRARIAN                     "ar"
166 #  define LIBRARIAN_OPTS                "cr"
167 #  define RANLIB                        "ranlib"
168 #  define LINKER_FLAG_PREFIX            "-Wl,"
169 #  define SHARED_OPTS                   "-shared"
170 #  define MODULE_OPTS                   "-shared"
171 #  define MKDIR_NO_UMASK
172 #  define EXE_EXT                       ".exe"
173 #endif
174
175 #ifndef CC
176 #define CC                              "gcc"
177 #endif
178
179 #ifndef CXX
180 #define CXX                             "g++"
181 #endif
182
183 #ifndef LINK_C
184 #define LINK_C                          "gcc"
185 #endif
186
187 #ifndef LINK_CXX
188 #define LINK_CXX                        "g++"
189 #endif
190
191 #ifndef LIBDIR
192 #define LIBDIR                          "/usr/local/lib"
193 #endif
194
195 #define OBJDIR                          ".libs"
196
197 #ifndef SHELL_CMD
198 #error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
199 #endif
200
201 #ifdef NEED_SNPRINTF
202 #include <stdarg.h>
203 #endif
204
205 #ifdef __EMX__
206 #include <process.h>
207 #endif
208
209 #ifndef PATH_MAX
210 #define PATH_MAX 1024
211 #endif
212
213
214 /* We want to say we are libtool 1.4 for shlibtool compatibility. */
215 #define VERSION "1.4"
216
217 #define DEBUG(fmt, ...) if(cmd->options.debug) printf(fmt, ## __VA_ARGS__)
218 #define NOTICE(fmt, ...) if(!cmd->options.silent) printf(fmt, ## __VA_ARGS__)
219 #define ERROR(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
220
221 enum tool_mode {
222         MODE_UNKNOWN,
223         MODE_COMPILE,
224         MODE_LINK,
225         MODE_EXECUTE,
226         MODE_INSTALL,
227 };
228
229 enum output_type {
230         OUT_GENERAL,
231         OUT_OBJECT,
232         OUT_PROGRAM,
233         OUT_LIB,
234         OUT_STATIC_LIB_ONLY,
235         OUT_DYNAMIC_LIB_ONLY,
236         OUT_MODULE,
237 };
238
239 enum pic_mode {
240         PIC_UNKNOWN,
241         PIC_PREFER,
242         PIC_AVOID,
243 };
244
245 enum shared_mode {
246         SHARE_UNSET,
247         SHARE_STATIC,
248         SHARE_SHARED,
249 };
250
251 enum lib_type {
252         TYPE_UKNOWN,
253         TYPE_STATIC_LIB,
254         TYPE_DYNAMIC_LIB,
255         TYPE_MODULE_LIB,
256         TYPE_OBJECT,
257 };
258
259 typedef struct {
260         char const **vals;
261         int num;
262 } count_chars;
263
264 typedef struct {
265         char const *normal;
266         char const *install;
267 } library_name;
268
269 typedef struct {
270         count_chars *normal;
271         count_chars *install;
272         count_chars *dependencies;
273 } library_opts;
274
275 typedef struct {
276         int silent;
277         int debug;
278         enum shared_mode shared;
279         int export_all;
280         int dry_run;
281         enum pic_mode pic_mode;
282         int export_dynamic;
283         int no_install;
284 } options_t;
285
286 typedef struct {
287         enum tool_mode mode;
288         enum output_type output;
289         options_t options;
290
291         char const *output_name;
292         char const *fake_output_name;
293         char const *basename;
294
295         char const *install_path;
296         char const *compiler;
297         char const *program;
298         count_chars *program_opts;
299
300         count_chars *arglist;
301         count_chars *tmp_dirs;
302         count_chars *obj_files;
303         count_chars *dep_rpaths;
304         count_chars *rpaths;
305
306         library_name static_name;
307         library_name shared_name;
308         library_name module_name;
309
310         library_opts static_opts;
311         library_opts shared_opts;
312
313         char const *version_info;
314         char const *undefined_flag;
315 } command_t;
316
317 #ifdef RPATH
318 static void add_rpath(count_chars *cc, char const *path);
319 #endif
320
321 static void usage(int code)
322 {
323         printf("Usage: jlibtool [OPTIONS...] COMMANDS...\n");
324         printf("jlibtool is a replacement for GNU libtool with similar functionality.\n\n");
325
326         printf("  --config       show all configuration variables\n");
327         printf("  --debug         enable verbose shell tracing\n");
328         printf("  --dry-run     display commands without modifying any files\n");
329         printf("  --help           display this help message and exit\n");
330         printf("  --mode=MODE      use operational mode MODE (you *must* set mode)\n");
331
332         printf("  --silent       don't print informational messages\n");
333         printf("  --tag=TAG     Ignored for libtool compatibility\n");
334         printf("  --version     print version information\n");
335
336
337         printf("  --shared       Build shared libraries when using --mode=link\n");
338         printf("  --export-all     Try to export 'def' file on some platforms\n");
339
340         printf("\nMODE must be one of the following:\n\n");
341         printf("  compile         compile a source file into a jlibtool object\n");
342         printf("  execute         automatically set library path, then run a program\n");
343         printf("  install         install libraries or executables\n");
344         printf("  link       create a library or an executable\n");
345
346         printf("\nMODE-ARGS can be the following:\n\n");
347         printf("  -export-dynamic  accepted and ignored\n");
348         printf("  -module         create a module when linking\n");
349         printf("  -shared         create a shared library when linking\n");
350         printf("  -prefer-pic      prefer position-independent-code when compiling\n");
351         printf("  -prefer-non-pic  prefer non position-independent-code when compiling\n");
352         printf("  -static         create a static library when linking\n");
353         printf("  -no-install      link libraries locally\n");
354         printf("  -rpath arg       Set install path for shared libraries\n");
355         printf("  -l arg           pass '-l arg' to the link stage\n");
356         printf("  -L arg           pass '-L arg' to the link stage\n");
357         printf("  -R dir           add 'dir' to runtime library search path.\n");
358         printf("  -Zexe     accepted and ignored\n");
359         printf("  -avoid-version   accepted and ignored\n");
360
361         exit(code);
362 }
363
364 #if defined(NEED_SNPRINTF)
365 /* Write at most n characters to the buffer in str, return the
366  * number of chars written or -1 if the buffer would have been
367  * overflowed.
368  *
369  * This is portable to any POSIX-compliant system has /dev/null
370  */
371 static FILE *f = NULL;
372 static int vsnprintf(char *str, size_t n, char const *fmt, va_list ap)
373 {
374         int res;
375
376         if (!f) {
377                 f = fopen("/dev/null","w");
378         }
379
380         if (!f) {
381                 return -1;
382         }
383
384         setvbuf(f, str, _IOFBF, n);
385
386         res = vfprintf(f, fmt, ap);
387
388         if ((res > 0) && (res < n)) {
389                 res = vsprintf( str, fmt, ap );
390         }
391         return res;
392 }
393
394 static int snprintf(char *str, size_t n, char const *fmt, ...)
395 {
396         va_list ap;
397         int res;
398
399         va_start(ap, fmt);
400         res = vsnprintf(str, n, fmt, ap);
401         va_end(ap);
402         return res;
403 }
404 #endif
405
406 static void *lt_malloc(size_t size)
407 {
408         void *out;
409
410         out = malloc(size);
411         if (!out) {
412                 ERROR("Failed allocating %zu bytes, OOM", size);
413                 exit(1);
414         }
415
416         return out;
417 }
418
419 static void lt_const_free(const void *ptr)
420 {
421         void *tmp;
422
423         memcpy(&tmp, &ptr, sizeof(tmp));
424         free(tmp);
425 }
426
427 static void init_count_chars(count_chars *cc)
428 {
429         cc->vals = (char const**) lt_malloc(PATH_MAX*sizeof(char*));
430         cc->num = 0;
431 }
432
433 static count_chars *alloc_countchars(void)
434 {
435         count_chars *out;
436         out = lt_malloc(sizeof(count_chars));
437         if (!out) {
438                 exit(1);
439         }
440         init_count_chars(out);
441
442         return out;
443 }
444
445 static void clear_count_chars(count_chars *cc)
446 {
447         int i;
448         for (i = 0; i < cc->num; i++) {
449                 cc->vals[i] = NULL;
450         }
451
452         cc->num = 0;
453 }
454
455 static void push_count_chars(count_chars *cc, char const *newval)
456 {
457         cc->vals[cc->num++] = newval;
458 }
459
460 static char const *pop_count_chars(count_chars *cc)
461 {
462         if (!cc->num) {
463                 return NULL;
464         }
465         return cc->vals[--cc->num];
466 }
467
468 static void insert_count_chars(count_chars *cc, char const *newval, int position)
469 {
470         int i;
471
472         for (i = cc->num; i > position; i--) {
473                 cc->vals[i] = cc->vals[i-1];
474         }
475
476         cc->vals[position] = newval;
477         cc->num++;
478 }
479
480 static void append_count_chars(count_chars *cc, count_chars *cctoadd)
481 {
482         int i;
483         for (i = 0; i < cctoadd->num; i++) {
484                 if (cctoadd->vals[i]) {
485                         push_count_chars(cc, cctoadd->vals[i]);
486                 }
487         }
488 }
489
490 static char const *flatten_count_chars(count_chars *cc, char delim)
491 {
492         int i, size;
493         char *newval;
494
495         size = 0;
496         for (i = 0; i < cc->num; i++) {
497                 if (cc->vals[i]) {
498                         size += strlen(cc->vals[i]) + 1;
499                         if (delim) {
500                                 size++;
501                         }
502                 }
503         }
504
505         newval = (char*)lt_malloc(size + 1);
506         newval[0] = '\0';
507
508         for (i = 0; i < cc->num; i++) {
509                 if (cc->vals[i]) {
510                         strcat(newval, cc->vals[i]);
511                         if (delim) {
512                                 size_t len = strlen(newval);
513                                 newval[len] = delim;
514                                 newval[len + 1] = '\0';
515                         }
516                 }
517         }
518
519         return newval;
520 }
521
522 static char *shell_esc(char const *str)
523 {
524         int in_quote = 0;
525         char *cmd;
526         uint8_t *d;
527         uint8_t const *s;
528
529         cmd = (char *)lt_malloc(2 * strlen(str) + 3);
530         d = (unsigned char *)cmd;
531         s = (const unsigned char *)str;
532
533 #ifdef __MINGW32__
534         *d++ = '\"';
535 #endif
536
537         for (; *s; ++s) {
538                 if (*s == '"') {
539                         *d++ = '\\';
540                         in_quote++;
541                 }
542                 else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
543                         *d++ = '\\';
544                 }
545                 *d++ = *s;
546         }
547
548 #ifdef __MINGW32__
549         *d++ = '\"';
550 #endif
551
552         *d = '\0';
553         return cmd;
554 }
555
556 static int external_spawn(command_t *cmd, char const *file, char const **argv)
557 {
558         file = file;            /* -Wunused */
559
560         if (!cmd->options.silent) {
561                 char const **argument = argv;
562                 NOTICE("Executing: ");
563                 while (*argument) {
564                         NOTICE("%s ", *argument);
565                         argument++;
566                 }
567                 puts("");
568         }
569
570         if (cmd->options.dry_run) {
571                 return 0;
572         }
573 #if defined(__EMX__) || defined(__MINGW32__)
574         return spawnvp(P_WAIT, argv[0], argv);
575 #else
576         {
577                 pid_t pid;
578                 pid = fork();
579                 if (pid == 0) {
580                         return execvp(argv[0], (char**)argv);
581                 }
582                 else {
583                         int status;
584                         waitpid(pid, &status, 0);
585
586                         /*
587                          *      Exited via exit(status)
588                          */
589                         if (WIFEXITED(status)) {
590                                 return WEXITSTATUS(status);
591                         }
592
593 #ifdef WTERMSIG
594                         if (WIFSIGNALED(status)) {
595                                 return WTERMSIG(status);
596                         }
597 #endif
598
599                         /*
600                          *      Some other failure.
601                          */
602                         return 1;
603                 }
604         }
605 #endif
606 }
607
608 static int run_command(command_t *cmd, count_chars *cc)
609 {
610         int ret;
611         char *command;
612         char *tmp;
613         char const *raw;
614         char const *spawn_args[4];
615         count_chars tmpcc;
616
617         init_count_chars(&tmpcc);
618
619         if (cmd->program) {
620                 push_count_chars(&tmpcc, cmd->program);
621         }
622
623         append_count_chars(&tmpcc, cmd->program_opts);
624
625         append_count_chars(&tmpcc, cc);
626
627         raw = flatten_count_chars(&tmpcc, ' ');
628         command = shell_esc(raw);
629
630         memcpy(&tmp, &raw, sizeof(tmp));
631         free(tmp);
632
633         spawn_args[0] = SHELL_CMD;
634         spawn_args[1] = "-c";
635         spawn_args[2] = command;
636         spawn_args[3] = NULL;
637         ret = external_spawn(cmd, spawn_args[0], spawn_args);
638
639         free(command);
640
641         return ret;
642 }
643
644 /*
645  * print configuration
646  * shlibpath_var is used in configure.
647  */
648 #define printc(_x,_y) if (!value || !strcmp(value, _x)) printf(_x "=\"%s\"\n", _y)
649
650 static void print_config(char const *value)
651 {
652 #ifdef LD_RUN_PATH
653         printc("runpath_var", LD_RUN_PATH);
654 #endif
655 #ifdef LD_LIBRARY_PATH
656         printc("shlibpath_var", LD_LIBRARY_PATH);
657 #endif
658 #ifdef LD_LIBRARY_PATH_LOCAL
659         printc("shlocallibpath_var", LD_LIBRARY_PATH_LOCAL);
660 #endif
661 #ifdef SHELL_CMD
662         printc("SHELL", SHELL_CMD);
663 #endif
664 #ifdef OBJECT_EXT
665         printc("objext", OBJECT_EXT);
666 #endif
667 #ifdef OBJDIR
668         printc("objdir", OBJDIR);
669 #endif
670 #ifdef DYNAMIC_LIB_EXT
671         /* add a '.' prefix because libtool does that. */
672         printc("shrext_cmds", "echo ." DYNAMIC_LIB_EXT);
673         /* add a '.' prefix because libtool does that. */
674         printc("shrext", "." DYNAMIC_LIB_EXT);
675 #endif
676 #ifdef EXE_EXT
677         printc("exeext", EXE_EXT);
678 #endif
679 #ifdef STATIC_LIB_EXT
680         printc("libext", STATIC_LIB_EXT);
681 #endif
682 #ifdef LIBRARIAN
683         printc("AR", LIBRARIAN);
684 #endif
685 #ifdef LIBRARIAN_OPTS
686         printc("AR_FLAGS", LIBRARIAN_OPTS);
687 #endif
688 #ifdef LINKER_FLAG_PREFIX
689         printc("wl", LINKER_FLAG_PREFIX);
690 #endif
691 #ifdef RANLIB
692         printc("ranlib", RANLIB);
693 #endif
694
695 }
696 /*
697  * Add a directory to the runtime library search path.
698  */
699 static void add_runtime_dir_lib(char const *arg, command_t *cmd)
700 {
701 #ifdef RPATH
702         add_rpath(cmd->shared_opts.dependencies, arg);
703 #else
704         (void) arg;                     /* -Wunused */
705         (void) cmd;
706 #endif
707 }
708
709 static int parse_long_opt(char const *arg, command_t *cmd)
710 {
711         char *equal_pos = strchr(arg, '=');
712         char var[50];
713         char value[500];
714
715         if (equal_pos) {
716                 strncpy(var, arg, equal_pos - arg);
717                 var[equal_pos - arg] = 0;
718                 if (strlen(equal_pos + 1) >= sizeof(var)) {
719                         return 0;
720                 }
721                 strcpy(value, equal_pos + 1);
722         } else {
723                 strncpy(var, arg, sizeof(var) - 1);
724                 var[sizeof(var) - 1] = '\0';
725
726                 value[0] = '\0';
727         }
728
729         if (strcmp(var, "silent") == 0) {
730                 cmd->options.silent = 1;
731         } else if (strcmp(var, "quiet") == 0) {
732                 cmd->options.silent = 1;
733         } else if (strcmp(var, "debug") == 0) {
734                 cmd->options.debug = 1;
735         } else if (strcmp(var, "mode") == 0) {
736                 if (cmd->mode != MODE_UNKNOWN) {
737                         ERROR("Cannot set --mode twice\n");
738                         exit(1);
739                 }
740
741                 if (strcmp(value, "compile") == 0) {
742                         cmd->mode = MODE_COMPILE;
743                         cmd->output = OUT_OBJECT;
744
745                 } else if (strcmp(value, "link") == 0) {
746                         cmd->mode = MODE_LINK;
747                         cmd->output = OUT_LIB;
748
749                 } else if (strcmp(value, "install") == 0) {
750                         cmd->mode = MODE_INSTALL;
751
752                 } else if (strcmp(value, "execute") == 0) {
753                         cmd->mode = MODE_EXECUTE;
754
755                 } else {
756                         ERROR("Unknown mode \"%s\"\n", value);
757                         exit(1);
758                 }
759
760         } else if (strcmp(var, "shared") == 0) {
761                 if ((cmd->mode == MODE_LINK) && (cmd->output == OUT_GENERAL)) {
762                         cmd->output = OUT_DYNAMIC_LIB_ONLY;
763                 }
764                 cmd->options.shared = SHARE_SHARED;
765
766         } else if (strcmp(var, "export-all") == 0) {
767                 cmd->options.export_all = 1;
768
769         } else if (strcmp(var, "dry-run") == 0) {
770                 NOTICE("Dry-run mode on!\n");
771                 cmd->options.dry_run = 1;
772
773         } else if (strcmp(var, "version") == 0) {
774                 NOTICE("Version " VERSION "\n");
775
776         } else if (strcmp(var, "help") == 0) {
777                 usage(0);
778
779         } else if (strcmp(var, "config") == 0) {
780                 print_config(value);
781
782                 exit(0);
783         } else {
784                 return 0;
785         }
786
787         return 1;
788 }
789
790 /* Return 1 if we eat it. */
791 static int parse_short_opt(char const *arg, command_t *cmd)
792 {
793         if (strcmp(arg, "export-dynamic") == 0) {
794                 cmd->options.export_dynamic = 1;
795                 return 1;
796         }
797
798         if (strcmp(arg, "module") == 0) {
799                 cmd->output = OUT_MODULE;
800                 return 1;
801         }
802
803         if (strcmp(arg, "shared") == 0) {
804                 if (cmd->mode == MODE_LINK) {
805                         cmd->output = OUT_DYNAMIC_LIB_ONLY;
806                 }
807                 cmd->options.shared = SHARE_SHARED;
808                 return 1;
809         }
810
811         if (strcmp(arg, "Zexe") == 0) {
812                 return 1;
813         }
814
815         if (strcmp(arg, "avoid-version") == 0) {
816                 return 1;
817         }
818
819         if (strcmp(arg, "prefer-pic") == 0) {
820                 cmd->options.pic_mode = PIC_PREFER;
821                 return 1;
822         }
823
824         if (strcmp(arg, "prefer-non-pic") == 0) {
825                 cmd->options.pic_mode = PIC_AVOID;
826                 return 1;
827         }
828
829         if (strcmp(arg, "static") == 0) {
830                 if ((cmd->mode == MODE_LINK) && (cmd->output == OUT_LIB)) {
831                         cmd->output = OUT_STATIC_LIB_ONLY;
832                 }
833                 cmd->options.shared = SHARE_STATIC;
834                 return 1;
835         }
836
837         if (cmd->mode == MODE_LINK) {
838                 if (strcmp(arg, "no-install") == 0) {
839                         cmd->options.no_install = 1;
840                         return 1;
841                 }
842                 if (arg[0] == 'L' || arg[0] == 'l') {
843                         /* Hack... */
844                         arg--;
845                         push_count_chars(cmd->shared_opts.dependencies, arg);
846                         return 1;
847                 } else if (arg[0] == 'R' && arg[1]) {
848                         /* -Rdir Add dir to runtime library search path. */
849                         add_runtime_dir_lib(&arg[1], cmd);
850                         return 1;
851                 }
852         }
853         return 0;
854 }
855
856 #ifdef TRUNCATE_DLL_NAME
857 static char *truncate_dll_name(char *path)
858 {
859         /* Cut DLL name down to 8 characters after removing any mod_ prefix */
860         char *tmppath = strdup(path);
861         char *newname = strrchr(tmppath, '/') + 1;
862         char *ext = strrchr(newname, '.');
863         int len;
864
865         if (ext == NULL) {
866                 return tmppath;
867         }
868
869         len = ext - newname;
870
871         if (strncmp(newname, "mod_", 4) == 0) {
872                 strcpy(newname, newname + 4);
873                 len -= 4;
874         }
875
876         if (len > 8) {
877                 strcpy(newname + 8, strchr(newname, '.'));
878         }
879
880         return tmppath;
881 }
882 #endif
883
884 static long safe_strtol(char const *nptr, char const **endptr, int base)
885 {
886         long rv;
887
888         errno = 0;
889
890         rv = strtol(nptr, (char**)endptr, 10);
891
892         if (errno == ERANGE) {
893                 return 0;
894         }
895
896         return rv;
897 }
898
899 static void safe_mkdir(command_t *cmd, char const *path)
900 {
901         int status;
902         mode_t old_umask;
903
904         old_umask = umask(0);
905         umask(old_umask);
906
907 #ifdef MKDIR_NO_UMASK
908         status = mkdir(path);
909 #else
910         status = mkdir(path, ~old_umask);
911 #endif
912         if ((status < 0) && (errno != EEXIST)) {
913                 NOTICE("Warning: mkdir of %s failed\n", path);
914         }
915 }
916
917 /** Returns a file's name without the path
918  *
919  * @param path to break apart.
920  * @return pointer in path.
921  */
922 static char const *file_name(char const *path)
923 {
924         char const *name;
925
926         name = strrchr(path, '/');
927         if (!name) {
928                 name = strrchr(path, '\\');     /* eww windows? */
929         }
930         if (!name) {
931                 name = path;
932         } else {
933                 name++;
934         }
935
936         return name;
937 }
938
939 #ifdef GEN_EXPORTS
940
941 /** Returns a file's name without path or extension
942  *
943  * @param path to check
944  * @return pointer in path.
945  */
946 static char const *file_name_stripped(char const *path)
947 {
948         char const *name;
949         char const *ext;
950
951         name = file_name(path);
952         ext = strrchr(name, '.');
953
954         if (ext) {
955                 char *trimmed;
956
957                 trimmed = lt_malloc(ext - name + 1);
958                 strncpy(trimmed, name, ext - name);
959                 trimmed[ext-name] = 0;
960
961                 return trimmed;
962         }
963
964         return name;
965 }
966 #endif
967
968 /* version_info is in the form of MAJOR:MINOR:PATCH */
969 static char const *darwin_dynamic_link_function(char const *version_info)
970 {
971         char *newarg;
972         long major, minor, patch;
973
974         major = 0;
975         minor = 0;
976         patch = 0;
977
978         if (version_info) {
979                 major = safe_strtol(version_info, &version_info, 10);
980
981                 if (version_info) {
982                         if (version_info[0] == ':') {
983                                 version_info++;
984                         }
985
986                         minor = safe_strtol(version_info, &version_info, 10);
987
988                         if (version_info) {
989                                 if (version_info[0] == ':') {
990                                         version_info++;
991                                 }
992
993                                 patch = safe_strtol(version_info, &version_info, 10);
994
995                         }
996                 }
997         }
998
999         /* Avoid -dylib_compatibility_version must be greater than zero errors. */
1000         if (major == 0) {
1001                 major = 1;
1002         }
1003         newarg = (char*)lt_malloc(100);
1004         snprintf(newarg, 99,
1005                          "-compatibility_version %ld -current_version %ld.%ld",
1006                          major, major, minor);
1007
1008         return newarg;
1009 }
1010
1011
1012 /*
1013  *      Add a '.libs/' to the buffer.  The caller ensures that
1014  *      The buffer is large enough to handle 6 extra characters.
1015  */
1016 static void add_dotlibs(char *buffer)
1017 {
1018         char *name = strrchr(buffer, '/');
1019
1020         if (!name) {
1021                 if (!buffer[0]) {
1022                         strcpy(buffer, ".libs/");
1023                         return;
1024                 }
1025                 name = buffer;
1026         } else {
1027                 name++;
1028         }
1029         memmove(name + 6, name, strlen(name));
1030         memcpy(name, ".libs/", 6);
1031 }
1032
1033 static char *gen_library_name(char const *name, enum lib_type genlib)
1034 {
1035         char *newarg, *newext;
1036
1037         newarg = (char *)calloc(strlen(name) + 11, 1);
1038
1039         if (genlib == TYPE_MODULE_LIB && strncmp(name, "lib", 3) == 0) {
1040                 name += 3;
1041         }
1042
1043         if (genlib == TYPE_MODULE_LIB) {
1044                 strcpy(newarg, file_name(name));
1045         }
1046         else {
1047                 strcpy(newarg, name);
1048         }
1049
1050         newext = strrchr(newarg, '.');
1051         if (!newext) {
1052                 ERROR("Library path does not have an extension");
1053         free(newarg);
1054
1055         return NULL;
1056         }
1057         newext++;
1058
1059         switch (genlib) {
1060         case TYPE_STATIC_LIB:
1061                 strcpy(newext, STATIC_LIB_EXT);
1062                 break;
1063         case TYPE_DYNAMIC_LIB:
1064                 strcpy(newext, DYNAMIC_LIB_EXT);
1065                 break;
1066         case TYPE_MODULE_LIB:
1067                 strcpy(newext, MODULE_LIB_EXT);
1068                 break;
1069
1070         default:
1071                 break;
1072         }
1073
1074         add_dotlibs(newarg);
1075
1076         return newarg;
1077 }
1078
1079 static char *gen_install_name(char const *name, enum lib_type genlib)
1080 {
1081         char *newname;
1082         int rv;
1083         struct stat sb;
1084
1085         newname = gen_library_name(name, genlib);
1086         if (!newname) return NULL;
1087
1088         /* Check if it exists. If not, return NULL.  */
1089         rv = stat(newname, &sb);
1090
1091         if (rv) {
1092                 free(newname);
1093                 return NULL;
1094         }
1095
1096         return newname;
1097 }
1098
1099 static char const *check_object_exists(command_t *cmd, char const *arg, int arglen)
1100 {
1101         char *newarg, *ext;
1102         struct stat sb;
1103
1104         newarg = (char *)lt_malloc(arglen + 10);
1105         memcpy(newarg, arg, arglen);
1106         newarg[arglen] = 0;
1107         ext = newarg + arglen;
1108
1109         strcpy(ext, OBJECT_EXT);
1110
1111         DEBUG("Checking (obj): %s\n", newarg);
1112         if (stat(newarg, &sb) == 0) {
1113                 return newarg;
1114         }
1115
1116         free(newarg);
1117
1118         return NULL;
1119 }
1120
1121 /* libdircheck values:
1122  * 0 - no .libs suffix
1123  * 1 - .libs suffix
1124  */
1125 static char *check_library_exists(command_t *cmd, char const *arg, int pathlen,
1126                                   int libdircheck, enum lib_type *libtype)
1127 {
1128         char *newarg, *ext;
1129         int pass, rv, newpathlen;
1130
1131         newarg = (char *)lt_malloc(strlen(arg) + 10);
1132         strcpy(newarg, arg);
1133         newarg[pathlen] = '\0';
1134
1135         newpathlen = pathlen;
1136         if (libdircheck) {
1137                 add_dotlibs(newarg);
1138                 newpathlen += sizeof(".libs/") - 1;
1139         }
1140
1141         strcpy(newarg + newpathlen, arg + pathlen);
1142         ext = strrchr(newarg, '.');
1143         if (!ext) {
1144                 ERROR("Error: Library path does not have an extension");
1145                 free(newarg);
1146
1147                 return NULL;
1148         }
1149         ext++;
1150
1151         pass = 0;
1152
1153         do {
1154                 struct stat sb;
1155
1156                 switch (pass) {
1157                 case 0:
1158                         if (cmd->options.pic_mode != PIC_AVOID &&
1159                                 cmd->options.shared != SHARE_STATIC) {
1160                                 strcpy(ext, DYNAMIC_LIB_EXT);
1161                                 *libtype = TYPE_DYNAMIC_LIB;
1162                                 break;
1163                         }
1164                         pass = 1;
1165                         /* Fall through */
1166                 case 1:
1167                         strcpy(ext, STATIC_LIB_EXT);
1168                         *libtype = TYPE_STATIC_LIB;
1169                         break;
1170                 case 2:
1171                         strcpy(ext, MODULE_LIB_EXT);
1172                         *libtype = TYPE_MODULE_LIB;
1173                         break;
1174                 case 3:
1175                         strcpy(ext, OBJECT_EXT);
1176                         *libtype = TYPE_OBJECT;
1177                         break;
1178                 default:
1179                         *libtype = TYPE_UKNOWN;
1180                         break;
1181                 }
1182
1183                 DEBUG("Checking (lib): %s\n", newarg);
1184                 rv = stat(newarg, &sb);
1185         }
1186         while (rv != 0 && ++pass < 4);
1187
1188         if (rv == 0) {
1189                 return newarg;
1190         }
1191
1192         free(newarg);
1193
1194         return NULL;
1195 }
1196
1197 static char * load_install_path(char const *arg)
1198 {
1199         FILE *f;
1200         char *path;
1201
1202         f = fopen(arg,"r");
1203         if (f == NULL) {
1204                 return NULL;
1205         }
1206
1207         path = lt_malloc(PATH_MAX);
1208
1209         fgets(path, PATH_MAX, f);
1210         fclose(f);
1211
1212         if (path[strlen(path)-1] == '\n') {
1213                 path[strlen(path)-1] = '\0';
1214         }
1215
1216         /* Check that we have an absolute path.
1217          * Otherwise the file could be a GNU libtool file.
1218          */
1219         if (path[0] != '/') {
1220                 free(path);
1221
1222                 return NULL;
1223         }
1224         return path;
1225 }
1226
1227 static char *load_noinstall_path(char const *arg, int pathlen)
1228 {
1229         char *newarg, *expanded_path;
1230         int newpathlen;
1231
1232         newarg = (char *)lt_malloc(strlen(arg) + 10);
1233         strcpy(newarg, arg);
1234         newarg[pathlen] = 0;
1235
1236         newpathlen = pathlen;
1237         strcat(newarg, ".libs");
1238         newpathlen += sizeof(".libs") - 1;
1239         newarg[newpathlen] = 0;
1240
1241 #ifdef HAS_REALPATH
1242         expanded_path = lt_malloc(PATH_MAX);
1243         expanded_path = realpath(newarg, expanded_path);
1244         /* Uh, oh.  There was an error.  Fall back on our first guess. */
1245         if (!expanded_path) {
1246                 expanded_path = newarg;
1247         }
1248 #else
1249         /* We might get ../ or something goofy.  Oh, well. */
1250         expanded_path = newarg;
1251 #endif
1252
1253         return expanded_path;
1254 }
1255
1256 static void add_dynamic_link_opts(command_t *cmd, count_chars *args)
1257 {
1258 #ifdef DYNAMIC_LINK_OPTS
1259         if (cmd->options.pic_mode != PIC_AVOID) {
1260                 DEBUG("Adding linker opt: %s\n", DYNAMIC_LINK_OPTS);
1261
1262                 push_count_chars(args, DYNAMIC_LINK_OPTS);
1263                 if (cmd->undefined_flag) {
1264                         push_count_chars(args, "-undefined");
1265 #if defined(__APPLE__)
1266                         /* -undefined dynamic_lookup is used by the bundled Python in
1267                          * 10.4, but if we don't set MACOSX_DEPLOYMENT_TARGET to 10.3+,
1268                          * we'll get a linker error if we pass this flag.
1269                          */
1270                         if (strcasecmp(cmd->undefined_flag, "dynamic_lookup") == 0) {
1271                                 insert_count_chars(cmd->program_opts, "MACOSX_DEPLOYMENT_TARGET=10.3", 0);
1272                         }
1273 #endif
1274                         push_count_chars(args, cmd->undefined_flag);
1275                 }
1276                 else {
1277 #ifdef DYNAMIC_LINK_UNDEFINED
1278                         DEBUG("Adding linker opt: %s\n", DYNAMIC_LINK_UNDEFINED);
1279
1280                         push_count_chars(args, DYNAMIC_LINK_UNDEFINED);
1281 #endif
1282                 }
1283         }
1284 #endif
1285 }
1286
1287 /* Read the final install location and add it to runtime library search path. */
1288 #ifdef RPATH
1289 static void add_rpath(count_chars *cc, char const *path)
1290 {
1291         int size = 0;
1292         char *tmp;
1293
1294 #ifdef LINKER_FLAG_PREFIX
1295         size = strlen(LINKER_FLAG_PREFIX);
1296 #endif
1297         size = size + strlen(path) + strlen(RPATH) + 2;
1298         tmp = lt_malloc(size);
1299
1300 #ifdef LINKER_FLAG_PREFIX
1301         strcpy(tmp, LINKER_FLAG_PREFIX);
1302         strcat(tmp, RPATH);
1303 #else
1304         strcpy(tmp, RPATH);
1305 #endif
1306 #ifndef LINKER_FLAG_NO_EQUALS
1307         strcat(tmp, "=");
1308 #endif
1309         strcat(tmp, path);
1310
1311         push_count_chars(cc, tmp);
1312 }
1313
1314 static void add_rpath_file(count_chars *cc, char const *arg)
1315 {
1316         char const *path;
1317
1318         path = load_install_path(arg);
1319         if (path) {
1320                 add_rpath(cc, path);
1321                 lt_const_free(path);
1322         }
1323 }
1324
1325 static void add_rpath_noinstall(count_chars *cc, char const *arg, int pathlen)
1326 {
1327         char const *path;
1328
1329         path = load_noinstall_path(arg, pathlen);
1330         if (path) {
1331                 add_rpath(cc, path);
1332                 lt_const_free(path);
1333         }
1334 }
1335 #endif
1336
1337 #ifdef DYNAMIC_LINK_NO_INSTALL
1338 static void add_dylink_noinstall(count_chars *cc, char const *arg, int pathlen,
1339                                                   int extlen)
1340 {
1341         char const *install_path, *current_path, *name;
1342         char *exp_argument;
1343         int i_p_len, c_p_len, name_len, dyext_len, cur_len;
1344
1345         install_path = load_install_path(arg);
1346         current_path = load_noinstall_path(arg, pathlen);
1347
1348         if (!install_path || !current_path) {
1349                 return;
1350         }
1351
1352         push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
1353
1354         i_p_len = strlen(install_path);
1355         c_p_len = strlen(current_path);
1356
1357         name = arg+pathlen;
1358         name_len = extlen-pathlen;
1359         dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
1360
1361         /* No, we need to replace the extension. */
1362         exp_argument = (char *)lt_malloc(i_p_len + c_p_len + (name_len*2) +
1363                                                                   (dyext_len*2) + 2);
1364
1365         cur_len = 0;
1366         strcpy(exp_argument, install_path);
1367         cur_len += i_p_len;
1368         exp_argument[cur_len++] = '/';
1369         strncpy(exp_argument+cur_len, name, extlen-pathlen);
1370         cur_len += name_len;
1371         strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
1372         cur_len += dyext_len;
1373         exp_argument[cur_len++] = ':';
1374         strcpy(exp_argument+cur_len, current_path);
1375         cur_len += c_p_len;
1376         exp_argument[cur_len++] = '/';
1377         strncpy(exp_argument+cur_len, name, extlen-pathlen);
1378         cur_len += name_len;
1379         strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
1380         cur_len += dyext_len;
1381
1382         push_count_chars(cc, exp_argument);
1383 }
1384 #endif
1385
1386 #ifdef ADD_MINUS_L
1387 /* use -L -llibname to allow to use installed libraries */
1388 static void add_minus_l(count_chars *cc, char const *arg)
1389 {
1390         char *newarg;
1391         char *name = strrchr(arg, '/');
1392         char *file = strrchr(arg, '.');
1393
1394         if ((name != NULL) && (file != NULL) &&
1395                 (strstr(name, "lib") == (name + 1))) {
1396                 *name = '\0';
1397                 *file = '\0';
1398                 file = name;
1399                 file = file+4;
1400                 push_count_chars(cc, "-L");
1401                 push_count_chars(cc, arg);
1402                 /* we need one argument like -lapr-1 */
1403                 newarg = lt_malloc(strlen(file) + 3);
1404                 strcpy(newarg, "-l");
1405                 strcat(newarg, file);
1406                 push_count_chars(cc, newarg);
1407         } else {
1408                 push_count_chars(cc, arg);
1409         }
1410 }
1411 #endif
1412
1413 #if 0
1414 static void add_linker_flag_prefix(count_chars *cc, char const *arg)
1415 {
1416 #ifndef LINKER_FLAG_PREFIX
1417         push_count_chars(cc, arg);
1418 #else
1419         char *newarg;
1420         newarg = (char*)lt_malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
1421         strcpy(newarg, LINKER_FLAG_PREFIX);
1422         strcat(newarg, arg);
1423         push_count_chars(cc, newarg);
1424 #endif
1425 }
1426 #endif
1427
1428 static int explode_static_lib(command_t *cmd, char const *lib)
1429 {
1430         count_chars tmpdir_cc, libname_cc;
1431         char const *tmpdir, *libname;
1432         char savewd[PATH_MAX];
1433         char const *name;
1434         DIR *dir;
1435         struct dirent *entry;
1436         char const *lib_args[4];
1437
1438         /* Bah! */
1439         if (cmd->options.dry_run) {
1440                 return 0;
1441         }
1442
1443         name = file_name(lib);
1444
1445         init_count_chars(&tmpdir_cc);
1446         push_count_chars(&tmpdir_cc, ".libs/");
1447         push_count_chars(&tmpdir_cc, name);
1448         push_count_chars(&tmpdir_cc, ".exploded/");
1449         tmpdir = flatten_count_chars(&tmpdir_cc, 0);
1450
1451         NOTICE("Making: %s\n", tmpdir);
1452
1453         safe_mkdir(cmd, tmpdir);
1454
1455         push_count_chars(cmd->tmp_dirs, tmpdir);
1456
1457         getcwd(savewd, sizeof(savewd));
1458
1459         if (chdir(tmpdir) != 0) {
1460                 NOTICE("Warning: could not explode %s\n", lib);
1461
1462                 return 1;
1463         }
1464
1465         if (lib[0] == '/') {
1466                 libname = lib;
1467         }
1468         else {
1469                 init_count_chars(&libname_cc);
1470                 push_count_chars(&libname_cc, "../../");
1471                 push_count_chars(&libname_cc, lib);
1472                 libname = flatten_count_chars(&libname_cc, 0);
1473         }
1474
1475         lib_args[0] = LIBRARIAN;
1476         lib_args[1] = "x";
1477         lib_args[2] = libname;
1478         lib_args[3] = NULL;
1479
1480         external_spawn(cmd, LIBRARIAN, lib_args);
1481
1482         chdir(savewd);
1483         dir = opendir(tmpdir);
1484
1485         while ((entry = readdir(dir)) != NULL) {
1486 #if defined(__APPLE__) && defined(RANLIB)
1487                 /* Apple inserts __.SYMDEF which isn't needed.
1488                  * Leopard (10.5+) can also add '__.SYMDEF SORTED' which isn't
1489                  * much fun either.  Just skip them.
1490                  */
1491                 if (strstr(entry->d_name, "__.SYMDEF") != NULL) {
1492                         continue;
1493                 }
1494 #endif
1495                 if (entry->d_name[0] != '.') {
1496                         push_count_chars(&tmpdir_cc, entry->d_name);
1497                         name = flatten_count_chars(&tmpdir_cc, 0);
1498
1499                         DEBUG("Adding object: %s\n", name);
1500                         push_count_chars(cmd->obj_files, name);
1501                         pop_count_chars(&tmpdir_cc);
1502                 }
1503         }
1504
1505         closedir(dir);
1506         return 0;
1507 }
1508
1509 static int parse_input_file_name(char const *arg, command_t *cmd)
1510 {
1511         char const *ext = strrchr(arg, '.');
1512         char const *name;
1513         int pathlen;
1514         enum lib_type libtype;
1515         char const *newarg;
1516
1517         /* Can't guess the extension */
1518         if (!ext) {
1519                 return 0;
1520         }
1521
1522         ext++;
1523         name = file_name(arg);
1524         pathlen = name - arg;
1525
1526         /*
1527          *      Were linking and have an archived object or object file
1528          *      push it onto the list of object files which'll get used
1529          *      to create the input files list for the linker.
1530          *
1531          *      We assume that these are outside of the project were building,
1532          *      as there's no reason to create .a files as part of the build
1533          *      process.
1534          */
1535         if (!strcmp(ext, STATIC_LIB_EXT) && (cmd->mode == MODE_LINK)) {
1536                 struct stat sb;
1537
1538                 if (!stat(arg, &sb)) {
1539                         DEBUG("Adding object: %s\n", arg);
1540
1541                         push_count_chars(cmd->obj_files, arg);
1542
1543                         return 1;
1544                 }
1545         }
1546
1547         /*
1548          *      More object files, if were linking they get set as input
1549          *      files.
1550          */
1551         if (!strcmp(ext, "lo") || !strcmp(ext, OBJECT_EXT)) {
1552                 newarg = check_object_exists(cmd, arg, ext - arg);
1553                 if (!newarg) {
1554                         ERROR("Can not find suitable object file for %s\n", arg);
1555                         exit(1);
1556                 }
1557
1558                 if (cmd->mode == MODE_LINK) {
1559                         DEBUG("Adding object: %s\n", newarg);
1560
1561                         push_count_chars(cmd->obj_files, newarg);
1562                 } else {
1563                         push_count_chars(cmd->arglist, newarg);
1564                 }
1565
1566                 return 1;
1567         }
1568
1569         if (!strcmp(ext, "la")) {
1570                 switch (cmd->mode) {
1571                 case MODE_LINK:
1572                         /* Try the .libs dir first! */
1573                         newarg = check_library_exists(cmd, arg, pathlen, 1, &libtype);
1574                         if (!newarg) {
1575                                 /* Try the normal dir next. */
1576                                 newarg = check_library_exists(cmd, arg, pathlen, 0, &libtype);
1577                                 if (!newarg) {
1578                                         ERROR("Can not find suitable library for %s\n", arg);
1579                                         exit(1);
1580                                 }
1581                         }
1582
1583                         /* It is not ok to just add the file: a library may added with:
1584                            1 - -L path library_name. (For *.so in Linux).
1585                            2 - library_name.
1586                          */
1587 #ifdef ADD_MINUS_L
1588                         if (libtype == TYPE_DYNAMIC_LIB) {
1589                                 add_minus_l(cmd->shared_opts.dependencies, newarg);
1590                         } else if (cmd->output == OUT_LIB &&
1591                                            libtype == TYPE_STATIC_LIB) {
1592                                 explode_static_lib(cmd, newarg);
1593                         } else {
1594                                 push_count_chars(cmd->shared_opts.dependencies, newarg);
1595                         }
1596 #else
1597                         if (cmd->output == OUT_LIB && libtype == TYPE_STATIC_LIB) {
1598                                 explode_static_lib(cmd, newarg);
1599                         }
1600                         else {
1601                                 push_count_chars(cmd->shared_opts.dependencies, newarg);
1602                         }
1603 #endif
1604                         if (libtype == TYPE_DYNAMIC_LIB) {
1605                                 if (cmd->options.no_install) {
1606 #ifdef RPATH
1607                                         add_rpath_noinstall(cmd->shared_opts.dependencies,
1608                                                                                 arg, pathlen);
1609 #endif
1610                                 }
1611                                 else {
1612 #ifdef RPATH
1613                                         add_rpath_file(cmd->shared_opts.dependencies, arg);
1614 #endif
1615                                 }
1616                         }
1617                         break;
1618                 case MODE_INSTALL:
1619                         /*
1620                          *      If we've already recorded a library to
1621                          *      install, we're most likely getting the .la
1622                          *      file that we want to install as.
1623                          *
1624                          *      The problem is that we need to add it as the
1625                          *      directory, not the .la file itself.
1626                          *      Otherwise, we'll do odd things.
1627                          */
1628                         if (cmd->output == OUT_LIB) {
1629                                 char *tmp;
1630
1631                                 tmp = strdup(arg);
1632                                 tmp[pathlen] = '\0';
1633                                 push_count_chars(cmd->arglist, tmp);
1634
1635                         } else {
1636                                 cmd->output = OUT_LIB;
1637                                 cmd->output_name = arg;
1638                                 cmd->static_name.install = gen_install_name(arg, 0);
1639                                 cmd->shared_name.install = gen_install_name(arg, 1);
1640                                 cmd->module_name.install = gen_install_name(arg, 2);
1641
1642                                 if (!cmd->static_name.install &&
1643                                         !cmd->shared_name.install &&
1644                                         !cmd->module_name.install) {
1645                                         ERROR("Files to install do not exist\n");
1646                                         exit(1);
1647                                 }
1648
1649                         }
1650                         break;
1651                 default:
1652                         break;
1653                 }
1654
1655                 return 1;
1656         }
1657
1658         if (!strcmp(ext, "c")) {
1659                 /* If we don't already have an idea what our output name will be. */
1660                 if (!cmd->basename) {
1661                         char *tmp = lt_malloc(strlen(arg) + 4);
1662                         strcpy(tmp, arg);
1663                         strcpy(strrchr(tmp, '.') + 1, "lo");
1664
1665                         cmd->basename = tmp;
1666
1667                         cmd->fake_output_name = strrchr(cmd->basename, '/');
1668                         if (cmd->fake_output_name) {
1669                                 cmd->fake_output_name++;
1670                         } else {
1671                                 cmd->fake_output_name = cmd->basename;
1672                         }
1673                 }
1674         }
1675
1676         return 0;
1677 }
1678
1679 static int parse_output_file_name(char const *arg, command_t *cmd)
1680 {
1681         char const *name;
1682         char const *ext;
1683         char *newarg = NULL;
1684         size_t pathlen;
1685
1686         cmd->fake_output_name = arg;
1687
1688         name = file_name(arg);
1689         ext = strrchr(name, '.');
1690
1691 #ifdef EXE_EXT
1692         if (!ext || strcmp(ext, EXE_EXT) == 0) {
1693 #else
1694         if (!ext) {
1695 #endif
1696                 cmd->basename = arg;
1697                 cmd->output = OUT_PROGRAM;
1698 #if defined(_OSD_POSIX)
1699                 cmd->options.pic_mode = PIC_AVOID;
1700 #endif
1701                 newarg = (char *)lt_malloc(strlen(arg) + 5);
1702                 strcpy(newarg, arg);
1703 #ifdef EXE_EXT
1704         if (!ext) {
1705           strcat(newarg, EXE_EXT);
1706         }
1707 #endif
1708                 cmd->output_name = newarg;
1709                 return 1;
1710         }
1711
1712         ext++;
1713         pathlen = name - arg;
1714
1715         if (strcmp(ext, "la") == 0) {
1716                 assert(cmd->mode == MODE_LINK);
1717
1718                 cmd->basename = arg;
1719                 cmd->static_name.normal = gen_library_name(arg, TYPE_STATIC_LIB);
1720                 cmd->shared_name.normal = gen_library_name(arg, TYPE_DYNAMIC_LIB);
1721                 cmd->module_name.normal = gen_library_name(arg, TYPE_MODULE_LIB);
1722                 cmd->static_name.install = gen_install_name(arg, TYPE_STATIC_LIB);
1723                 cmd->shared_name.install = gen_install_name(arg, TYPE_DYNAMIC_LIB);
1724                 cmd->module_name.install = gen_install_name(arg, TYPE_MODULE_LIB);
1725
1726                 if (!cmd->options.dry_run) {
1727                         char *newname;
1728                         char *newext;
1729                         newname = lt_malloc(strlen(cmd->static_name.normal) + 1);
1730
1731                         strcpy(newname, cmd->static_name.normal);
1732                         newext = strrchr(newname, '/');
1733                         if (!newext) {
1734                                 /* Check first to see if the dir already exists! */
1735                                 safe_mkdir(cmd, ".libs");
1736                         } else {
1737                                 *newext = '\0';
1738                                 safe_mkdir(cmd, newname);
1739                         }
1740                         free(newname);
1741                 }
1742
1743 #ifdef TRUNCATE_DLL_NAME
1744                 if (shared) {
1745                         arg = truncate_dll_name(arg);
1746                 }
1747 #endif
1748
1749                 cmd->output_name = arg;
1750                 return 1;
1751         }
1752
1753         if (strcmp(ext, STATIC_LIB_EXT) == 0) {
1754                 assert(cmd->mode == MODE_LINK);
1755
1756                 cmd->basename = arg;
1757                 cmd->options.shared = SHARE_STATIC;
1758                 cmd->output = OUT_STATIC_LIB_ONLY;
1759                 cmd->static_name.normal = gen_library_name(arg, TYPE_STATIC_LIB);
1760                 cmd->static_name.install = gen_install_name(arg, TYPE_STATIC_LIB);
1761
1762                 if (!cmd->options.dry_run) {
1763                         char *newname;
1764                         char *newext;
1765                         newname = lt_malloc(strlen(cmd->static_name.normal) + 1);
1766
1767                         strcpy(newname, cmd->static_name.normal);
1768                         newext = strrchr(newname, '/');
1769                         if (!newext) {
1770                                 /* Check first to see if the dir already exists! */
1771                                 safe_mkdir(cmd, ".libs");
1772                         } else {
1773                                 *newext = '\0';
1774                                 safe_mkdir(cmd, newname);
1775                         }
1776                         free(newname);
1777                 }
1778
1779                 cmd->output_name = arg;
1780                 return 1;
1781         }
1782
1783         if (strcmp(ext, DYNAMIC_LIB_EXT) == 0) {
1784                 assert(cmd->mode == MODE_LINK);
1785
1786                 cmd->basename = arg;
1787                 cmd->options.shared = SHARE_SHARED;
1788                 cmd->output = OUT_DYNAMIC_LIB_ONLY;
1789                 cmd->shared_name.normal = gen_library_name(arg, TYPE_DYNAMIC_LIB);
1790                 cmd->module_name.normal = gen_library_name(arg, TYPE_MODULE_LIB);
1791                 cmd->shared_name.install = gen_install_name(arg, TYPE_DYNAMIC_LIB);
1792                 cmd->module_name.install = gen_install_name(arg, TYPE_MODULE_LIB);
1793
1794                 if (!cmd->options.dry_run) {
1795                         char *newname;
1796                         char *newext;
1797                         newname = lt_malloc(strlen(cmd->shared_name.normal) + 1);
1798
1799                         strcpy(newname, cmd->shared_name.normal);
1800                         newext = strrchr(newname, '/');
1801                         if (!newext) {
1802                                 /* Check first to see if the dir already exists! */
1803                                 safe_mkdir(cmd, ".libs");
1804                         } else {
1805                                 *newext = '\0';
1806                                 safe_mkdir(cmd, newname);
1807                         }
1808                         free(newname);
1809                 }
1810
1811                 cmd->output_name = arg;
1812                 return 1;
1813         }
1814
1815         if (strcmp(ext, "lo") == 0) {
1816                 char *newext;
1817                 cmd->basename = arg;
1818                 cmd->output = OUT_OBJECT;
1819                 newarg = (char *)lt_malloc(strlen(arg) + 2);
1820                 strcpy(newarg, arg);
1821                 newext = strrchr(newarg, '.') + 1;
1822                 strcpy(newext, OBJECT_EXT);
1823                 cmd->output_name = newarg;
1824                 return 1;
1825         }
1826
1827         if (strcmp(ext, DYNAMIC_LIB_EXT) == 0) {
1828                 ERROR("Please build libraries with .la target, not ."
1829                       DYNAMIC_LIB_EXT "\n");
1830
1831                 exit(1);
1832         }
1833
1834         if (strcmp(ext, STATIC_LIB_EXT) == 0) {
1835                 ERROR("Please build libraries with .la target, not ."
1836                       STATIC_LIB_EXT "\n");
1837
1838                 exit(1);
1839         }
1840
1841         return 0;
1842 }
1843
1844 static char const *automode(char const *arg, command_t *cmd)
1845 {
1846         if (cmd->mode != MODE_UNKNOWN) return arg;
1847
1848         if (!strcmp(arg, "CC") ||
1849             !strcmp(arg, "CXX")) {
1850                 DEBUG("Now in compile mode, guessed from: %s\n", arg);
1851                 arg = CC;
1852                 cmd->mode = MODE_COMPILE;
1853
1854         } else if (!strcmp(arg, "LINK") ||
1855                    !strcmp(arg, "LINK.c") ||
1856                    !strcmp(arg, "LINK.cxx")) {
1857                 DEBUG("Now in linker mode, guessed from: %s\n", arg);
1858                 arg = LINK_C;
1859                 cmd->mode = MODE_LINK;
1860         }
1861
1862         return arg;
1863 }
1864
1865
1866 #ifdef GEN_EXPORTS
1867 static void generate_def_file(command_t *cmd)
1868 {
1869         char def_file[1024];
1870         char implib_file[1024];
1871         char *ext;
1872         FILE *hDef;
1873         char *export_args[1024];
1874         int num_export_args = 0;
1875         char *cmd;
1876         int cmd_size = 0;
1877         int a;
1878
1879         if (cmd->output_name) {
1880                 strcpy(def_file, cmd->output_name);
1881                 strcat(def_file, ".def");
1882                 hDef = fopen(def_file, "w");
1883
1884                 if (hDef != NULL) {
1885                         fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", file_name_stripped(cmd->output_name));
1886                         fprintf(hDef, "DATA NONSHARED\n");
1887                         fprintf(hDef, "EXPORTS\n");
1888                         fclose(hDef);
1889
1890                         for (a = 0; a < cmd->num_obj_files; a++) {
1891                                 cmd_size += strlen(cmd->obj_files[a]) + 1;
1892                         }
1893
1894                         cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
1895                         cmd = (char *)lt_malloc(cmd_size);
1896                         strcpy(cmd, GEN_EXPORTS);
1897
1898                         for (a=0; a < cmd->num_obj_files; a++) {
1899                                 strcat(cmd, " ");
1900                                 strcat(cmd, cmd->obj_files[a] );
1901                         }
1902
1903                         strcat(cmd, ">>");
1904                         strcat(cmd, def_file);
1905                         puts(cmd);
1906                         export_args[num_export_args++] = SHELL_CMD;
1907                         export_args[num_export_args++] = "-c";
1908                         export_args[num_export_args++] = cmd;
1909                         export_args[num_export_args++] = NULL;
1910                         external_spawn(cmd, export_args[0], (char const**)export_args);
1911                         cmd->arglist[cmd->num_args++] = strdup(def_file);
1912
1913                         /* Now make an import library for the dll */
1914                         num_export_args = 0;
1915                         export_args[num_export_args++] = DEF2IMPLIB_CMD;
1916                         export_args[num_export_args++] = "-o";
1917
1918                         strcpy(implib_file, ".libs/");
1919                         strcat(implib_file, cmd->basename);
1920                         ext = strrchr(implib_file, '.');
1921
1922                         if (ext) {
1923                                 *ext = '\0';
1924                         }
1925
1926                         strcat(implib_file, ".");
1927                         strcat(implib_file, STATIC_LIB_EXT);
1928
1929                         export_args[num_export_args++] = implib_file;
1930                         export_args[num_export_args++] = def_file;
1931                         export_args[num_export_args++] = NULL;
1932                         external_spawn(cmd, export_args[0], (char const**)export_args);
1933
1934                 }
1935         }
1936 }
1937 #endif
1938
1939 #if 0
1940 static char const* expand_path(char const *relpath)
1941 {
1942         char foo[PATH_MAX], *newpath;
1943
1944         getcwd(foo, PATH_MAX-1);
1945         newpath = (char*)lt_malloc(strlen(foo)+strlen(relpath)+2);
1946         strcpy(newpath, foo);
1947         strcat(newpath, "/");
1948         strcat(newpath, relpath);
1949         return newpath;
1950 }
1951 #endif
1952
1953 static void link_fixup(command_t *cmd)
1954 {
1955         /* If we were passed an -rpath directive, we need to build
1956          * shared objects too.  Otherwise, we should only create static
1957          * libraries.
1958          */
1959         if (!cmd->install_path && (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
1960                 cmd->output == OUT_MODULE || cmd->output == OUT_LIB)) {
1961                 if (cmd->options.shared == SHARE_SHARED) {
1962                         cmd->install_path = LIBDIR;
1963                 }
1964         }
1965
1966         if (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
1967                 cmd->output == OUT_MODULE ||
1968                 cmd->output == OUT_LIB) {
1969
1970                 push_count_chars(cmd->shared_opts.normal, "-o");
1971                 if (cmd->output == OUT_MODULE) {
1972                         push_count_chars(cmd->shared_opts.normal, cmd->module_name.normal);
1973                 } else {
1974                         push_count_chars(cmd->shared_opts.normal, cmd->shared_name.normal);
1975 #ifdef DYNAMIC_INSTALL_NAME
1976                         push_count_chars(cmd->shared_opts.normal, DYNAMIC_INSTALL_NAME);
1977
1978                         if (!cmd->install_path) {
1979                                 ERROR("Installation mode requires -rpath\n");
1980                                 exit(1);
1981                         }
1982
1983                         {
1984                                 char *tmp = lt_malloc(PATH_MAX);
1985                                 strcpy(tmp, cmd->install_path);
1986
1987                                 if (cmd->shared_name.install) {
1988                                         strcat(tmp, strrchr(cmd->shared_name.install, '/'));
1989                                 } else {
1990                                         strcat(tmp, strrchr(cmd->shared_name.normal, '/'));
1991                                 }
1992
1993                                 push_count_chars(cmd->shared_opts.normal, tmp);
1994                         }
1995 #endif
1996                 }
1997
1998                 append_count_chars(cmd->shared_opts.normal, cmd->obj_files);
1999                 append_count_chars(cmd->shared_opts.normal, cmd->shared_opts.dependencies);
2000
2001                 if (cmd->options.export_all) {
2002 #ifdef GEN_EXPORTS
2003                         generate_def_file(cmd);
2004 #endif
2005                 }
2006         }
2007
2008         if (cmd->output == OUT_LIB || cmd->output == OUT_STATIC_LIB_ONLY) {
2009                 push_count_chars(cmd->static_opts.normal, "-o");
2010                 push_count_chars(cmd->static_opts.normal, cmd->output_name);
2011         }
2012
2013         if (cmd->output == OUT_PROGRAM) {
2014                 if (cmd->output_name) {
2015                         push_count_chars(cmd->arglist, "-o");
2016                         push_count_chars(cmd->arglist, cmd->output_name);
2017                         append_count_chars(cmd->arglist, cmd->obj_files);
2018                         append_count_chars(cmd->arglist, cmd->shared_opts.dependencies);
2019                         add_dynamic_link_opts(cmd, cmd->arglist);
2020                 }
2021         }
2022 }
2023
2024 static void post_parse_fixup(command_t *cmd)
2025 {
2026         switch (cmd->mode) {
2027         case MODE_COMPILE:
2028 #ifdef PIC_FLAG
2029                 if (cmd->options.pic_mode != PIC_AVOID) {
2030                         push_count_chars(cmd->arglist, PIC_FLAG);
2031                 }
2032 #endif
2033                 if (cmd->output_name) {
2034                         push_count_chars(cmd->arglist, "-o");
2035                         push_count_chars(cmd->arglist, cmd->output_name);
2036                 }
2037                 break;
2038         case MODE_LINK:
2039                 link_fixup(cmd);
2040                 break;
2041         case MODE_INSTALL:
2042                 if (cmd->output == OUT_LIB) {
2043                         link_fixup(cmd);
2044                 }
2045         default:
2046                 break;
2047         }
2048
2049 #ifdef USE_OMF
2050         if (cmd->output == OUT_OBJECT ||
2051                 cmd->output == OUT_PROGRAM ||
2052                 cmd->output == OUT_LIB ||
2053                 cmd->output == OUT_DYNAMIC_LIB_ONLY) {
2054                 push_count_chars(cmd->arglist, "-Zomf");
2055         }
2056 #endif
2057
2058         if (cmd->options.shared &&
2059                         (cmd->output == OUT_OBJECT ||
2060                          cmd->output == OUT_LIB ||
2061                          cmd->output == OUT_DYNAMIC_LIB_ONLY)) {
2062 #ifdef SHARE_SW
2063                 push_count_chars(cmd->arglist, SHARE_SW);
2064 #endif
2065         }
2066 }
2067
2068 static int run_mode(command_t *cmd)
2069 {
2070         int rv = 0;
2071         count_chars *cctemp;
2072
2073         cctemp = (count_chars*)lt_malloc(sizeof(count_chars));
2074         init_count_chars(cctemp);
2075
2076         switch (cmd->mode) {
2077         case MODE_COMPILE:
2078                 rv = run_command(cmd, cmd->arglist);
2079                 if (rv) goto finish;
2080                 break;
2081         case MODE_INSTALL:
2082                 /* Well, we'll assume it's a file going to a directory... */
2083                 /* For brain-dead install-sh based scripts, we have to repeat
2084                  * the command N-times.  install-sh should die.
2085                  */
2086                 if (!cmd->output_name) {
2087                         rv = run_command(cmd, cmd->arglist);
2088                         if (rv) goto finish;
2089                 }
2090                 if (cmd->output_name) {
2091                         append_count_chars(cctemp, cmd->arglist);
2092                         insert_count_chars(cctemp,
2093                                                            cmd->output_name,
2094                                                            cctemp->num - 1);
2095                         rv = run_command(cmd, cctemp);
2096                         if (rv) goto finish;
2097                         clear_count_chars(cctemp);
2098                 }
2099                 if (cmd->static_name.install) {
2100                         append_count_chars(cctemp, cmd->arglist);
2101                         insert_count_chars(cctemp,
2102                                                            cmd->static_name.install,
2103                                                            cctemp->num - 1);
2104                         rv = run_command(cmd, cctemp);
2105                         if (rv) goto finish;
2106 #if defined(__APPLE__) && defined(RANLIB)
2107                         /* From the Apple libtool(1) manpage on Tiger/10.4:
2108                          * ----
2109                          * With  the way libraries used to be created, errors were possible
2110                          * if the library was modified with ar(1) and  the  table  of
2111                          * contents  was  not updated  by  rerunning ranlib(1).  Thus the
2112                          * link editor, ld, warns when the modification date of a library
2113                          * is more  recent  than  the  creation date  of its table of
2114                          * contents.  Unfortunately, this means that you get the warning
2115                          * even if you only copy the library.
2116                          * ----
2117                          *
2118                          * This means that when we install the static archive, we need to
2119                          * rerun ranlib afterwards.
2120                          */
2121                         char const *lib_args[3], *static_lib_name;
2122
2123                         {
2124                                 char *tmp;
2125                                 size_t len1, len2;
2126
2127                                 len1 = strlen(cmd->arglist->vals[cmd->arglist->num - 1]);
2128
2129                                 static_lib_name = file_name(cmd->static_name.install);
2130                                 len2 = strlen(static_lib_name);
2131
2132                                 tmp = lt_malloc(len1 + len2 + 2);
2133
2134                                 snprintf(tmp, len1 + len2 + 2, "%s/%s",
2135                                                 cmd->arglist->vals[cmd->arglist->num - 1],
2136                                                 static_lib_name);
2137
2138                                 lib_args[0] = RANLIB;
2139                                 lib_args[1] = tmp;
2140                                 lib_args[2] = NULL;
2141
2142                                 external_spawn(cmd, RANLIB, lib_args);
2143
2144                                 free(tmp);
2145                         }
2146 #endif
2147                         clear_count_chars(cctemp);
2148                 }
2149                 if (cmd->shared_name.install) {
2150                         append_count_chars(cctemp, cmd->arglist);
2151                         insert_count_chars(cctemp, cmd->shared_name.install,
2152                                            cctemp->num - 1);
2153                         rv = run_command(cmd, cctemp);
2154                         if (rv) goto finish;
2155                         clear_count_chars(cctemp);
2156                 }
2157                 if (cmd->module_name.install) {
2158                         append_count_chars(cctemp, cmd->arglist);
2159                         insert_count_chars(cctemp, cmd->module_name.install,
2160                                            cctemp->num - 1);
2161                         rv = run_command(cmd, cctemp);
2162                         if (rv) goto finish;
2163                         clear_count_chars(cctemp);
2164                 }
2165                 break;
2166         case MODE_LINK:
2167                 if (cmd->output == OUT_STATIC_LIB_ONLY ||
2168                         cmd->output == OUT_LIB) {
2169 #ifdef RANLIB
2170                         char const *lib_args[3];
2171 #endif
2172                         /* Removes compiler! */
2173                         cmd->program = LIBRARIAN;
2174                         push_count_chars(cmd->program_opts, LIBRARIAN_OPTS);
2175                         push_count_chars(cmd->program_opts, cmd->static_name.normal);
2176
2177                         rv = run_command(cmd, cmd->obj_files);
2178                         if (rv) goto finish;
2179
2180 #ifdef RANLIB
2181                         lib_args[0] = RANLIB;
2182                         lib_args[1] = cmd->static_name.normal;
2183                         lib_args[2] = NULL;
2184                         external_spawn(cmd, RANLIB, lib_args);
2185 #endif
2186                 }
2187
2188                 if (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
2189                         cmd->output == OUT_MODULE ||
2190                         cmd->output == OUT_LIB) {
2191                         cmd->program = NULL;
2192                         clear_count_chars(cmd->program_opts);
2193
2194                         append_count_chars(cmd->program_opts, cmd->arglist);
2195                         if (cmd->output == OUT_MODULE) {
2196 #ifdef MODULE_OPTS
2197                                 push_count_chars(cmd->program_opts, MODULE_OPTS);
2198 #endif
2199                         } else {
2200 #ifdef SHARED_OPTS
2201                                 push_count_chars(cmd->program_opts, SHARED_OPTS);
2202 #endif
2203 #ifdef dynamic_link_version_func
2204                                 push_count_chars(cmd->program_opts,
2205                                                  dynamic_link_version_func(cmd->version_info));
2206 #endif
2207                         }
2208                         add_dynamic_link_opts(cmd, cmd->program_opts);
2209
2210                         rv = run_command(cmd, cmd->shared_opts.normal);
2211                         if (rv) goto finish;
2212                 }
2213                 if (cmd->output == OUT_PROGRAM) {
2214                         rv = run_command(cmd, cmd->arglist);
2215                         if (rv) goto finish;
2216                 }
2217                 break;
2218         case MODE_EXECUTE:
2219         {
2220                 char *l, libpath[PATH_MAX];
2221
2222                 if (strlen(cmd->arglist->vals[0]) >= PATH_MAX) {
2223                         ERROR("Libpath too long no buffer space");
2224                         rv = 1;
2225
2226                         goto finish;
2227                 }
2228
2229                 strcpy(libpath, cmd->arglist->vals[0]);
2230                 add_dotlibs(libpath);
2231         l = strrchr(libpath, '/');
2232         if (!l) l = strrchr(libpath, '\\');
2233         if (l) {
2234                 *l = '\0';
2235                 l = libpath;
2236         } else {
2237                 l = ".libs/";
2238         }
2239
2240         l = "./build/lib/.libs";
2241         setenv(LD_LIBRARY_PATH_LOCAL, l, 1);
2242         rv = run_command(cmd, cmd->arglist);
2243                 if (rv) goto finish;
2244         }
2245           break;
2246
2247         default:
2248                 break;
2249         }
2250
2251         finish:
2252
2253         free(cctemp);
2254         return rv;
2255 }
2256
2257 static void cleanup_tmp_dir(char const *dirname)
2258 {
2259         DIR *dir;
2260         struct dirent *entry;
2261         char fullname[1024];
2262
2263         dir = opendir(dirname);
2264         if (!dir) {
2265                 return;
2266         }
2267
2268         if ((strlen(dirname) + 1 + sizeof(entry->d_name)) >= sizeof(fullname)) {
2269                 ERROR("Dirname too long, out of buffer space");
2270
2271                 (void) closedir(dir);
2272                 return;
2273         }
2274
2275         while ((entry = readdir(dir)) != NULL) {
2276                 if (entry->d_name[0] != '.') {
2277                         strcpy(fullname, dirname);
2278                         strcat(fullname, "/");
2279                         strcat(fullname, entry->d_name);
2280                         (void) remove(fullname);
2281                 }
2282         }
2283
2284         rmdir(dirname);
2285
2286         (void) closedir(dir);
2287 }
2288
2289 static void cleanup_tmp_dirs(command_t *cmd)
2290 {
2291         int d;
2292
2293         for (d = 0; d < cmd->tmp_dirs->num; d++) {
2294                 cleanup_tmp_dir(cmd->tmp_dirs->vals[d]);
2295         }
2296 }
2297
2298 static int ensure_fake_uptodate(command_t *cmd)
2299 {
2300         /* FIXME: could do the stat/touch here, but nah... */
2301         char const *touch_args[3];
2302
2303         if (cmd->mode == MODE_INSTALL) {
2304                 return 0;
2305         }
2306         if (!cmd->fake_output_name) {
2307                 return 0;
2308         }
2309
2310         touch_args[0] = "touch";
2311         touch_args[1] = cmd->fake_output_name;
2312         touch_args[2] = NULL;
2313         return external_spawn(cmd, "touch", touch_args);
2314 }
2315
2316 /* Store the install path in the *.la file */
2317 static int add_for_runtime(command_t *cmd)
2318 {
2319         if (cmd->mode == MODE_INSTALL) {
2320                 return 0;
2321         }
2322         if (cmd->output == OUT_DYNAMIC_LIB_ONLY ||
2323                 cmd->output == OUT_LIB) {
2324                 FILE *f=fopen(cmd->fake_output_name,"w");
2325                 if (f == NULL) {
2326                         return -1;
2327                 }
2328                 fprintf(f,"%s\n", cmd->install_path);
2329                 fclose(f);
2330                 return(0);
2331         } else {
2332                 return(ensure_fake_uptodate(cmd));
2333         }
2334 }
2335
2336 static void parse_args(int argc, char *argv[], command_t *cmd)
2337 {
2338         int a;
2339         char const *arg, *base;
2340         int arg_used;
2341
2342         /*
2343          *      We now take a major step past libtool.
2344          *
2345          *      IF there's no "--mode=...", AND we recognise
2346          *      the binary as a "special" name, THEN replace it
2347          *      with the correct one, and set the correct mode.
2348          *
2349          *      For example if were called 'CC' then we know we should
2350          *      probably be compiling stuff.
2351          */
2352         base = file_name(argv[0]);
2353         arg = automode(base, cmd);
2354         if (arg != base) {
2355                 push_count_chars(cmd->arglist, arg);
2356
2357                 assert(cmd->mode != MODE_UNKNOWN);
2358         }
2359
2360         /*
2361          *      We first pass over the command-line arguments looking for
2362          *      "--mode", etc.  If so, then use the libtool compatibility
2363          *      method for building the software.  Otherwise, auto-detect it
2364          *      via "-o" and the extensions.
2365          */
2366         base = NULL;
2367         if (cmd->mode == MODE_UNKNOWN) for (a = 1; a < argc; a++) {
2368                 arg = argv[a];
2369
2370                 if (strncmp(arg, "--mode=", 7) == 0) {
2371                         base = NULL;
2372                         break;
2373                 }
2374
2375                 /*
2376                  *      Stop if we get another magic method
2377                  */
2378                 if ((a == 1) &&
2379                     ((strncmp(arg, "LINK", 4) == 0) ||
2380                      (strcmp(arg, "CC") == 0) ||
2381                      (strcmp(arg, "CXX") == 0))) {
2382                         base = NULL;
2383                         break;
2384                 }
2385
2386                 if (strncmp(arg, "-o", 2) == 0) {
2387                         base = argv[++a];
2388                 }
2389         }
2390
2391         /*
2392          *      There were no magic args or an explicit --mode= but we did
2393          *      find an output file, so guess what mode were meant to be in
2394          *      from its extension.
2395          */
2396         if (base) {
2397                 arg = strrchr(base, '.');
2398                 if (!arg) {
2399                         cmd->mode = MODE_LINK;
2400                         push_count_chars(cmd->arglist, LINK_C);
2401                 }
2402 #ifdef EXE_EXT
2403                 else if (strcmp(arg, EXE_EXT) == 0) {
2404                         cmd->mode = MODE_LINK;
2405                         push_count_chars(cmd->arglist, LINK_C);
2406                 }
2407 #endif
2408                 else if (strcmp(arg + 1, DYNAMIC_LIB_EXT) == 0) {
2409                         cmd->mode = MODE_LINK;
2410                         push_count_chars(cmd->arglist, LINK_C);
2411                 }
2412                 else if (strcmp(arg + 1, STATIC_LIB_EXT) == 0) {
2413                         cmd->mode = MODE_LINK;
2414                         push_count_chars(cmd->arglist, LINK_C);
2415                 }
2416                 else if (strcmp(arg + 1, "la") == 0) {
2417                         cmd->mode = MODE_LINK;
2418                         push_count_chars(cmd->arglist, LINK_C);
2419                 }
2420                 else if ((strcmp(arg + 1, "lo") == 0) ||
2421                          (strcmp(arg + 1, "o") == 0)) {
2422                         cmd->mode = MODE_COMPILE;
2423                         push_count_chars(cmd->arglist, CC);
2424                 }
2425         }
2426
2427         for (a = 1; a < argc; a++) {
2428                 arg = argv[a];
2429                 arg_used = 1;
2430
2431                 if (cmd->mode == MODE_EXECUTE) {
2432                         push_count_chars(cmd->arglist, arg);
2433                         continue;
2434                 }
2435
2436                 if (arg[0] == '-') {
2437                         /*
2438                          *      Double dashed (long) single dash (short)
2439                          */
2440                         arg_used = (arg[1] == '-') ?
2441                                 parse_long_opt(arg + 2, cmd) :
2442                                 parse_short_opt(arg + 1, cmd);
2443
2444                         if (arg_used) continue;
2445
2446                         /*
2447                          *      Ignore all options after the '--execute'
2448                          */
2449                         if (cmd->mode == MODE_EXECUTE) continue;
2450
2451                         /*
2452                          *      We haven't done anything with it yet, but
2453                          *      there are still some arg/value pairs.
2454                          *
2455                          *      Try some of the more complicated short opts...
2456                          */
2457                         if (a + 1 < argc) {
2458                                 /*
2459                                  *      We found an output file!
2460                                  */
2461                                 if ((arg[1] == 'o') && (arg[2] == '\0')) {
2462                                         arg = argv[++a];
2463                                         arg_used = parse_output_file_name(arg,
2464                                                                           cmd);
2465                                 /*
2466                                  *      -MT literal dependency
2467                                  */
2468                                 } else if (!strcmp(arg + 1, "MT")) {
2469                                         DEBUG("Adding: %s\n", arg);
2470
2471                                         push_count_chars(cmd->arglist, arg);
2472                                         arg = argv[++a];
2473
2474                                         NOTICE(" %s\n", arg);
2475
2476                                         push_count_chars(cmd->arglist, arg);
2477                                         arg_used = 1;
2478                                 /*
2479                                  *      Runtime library search path
2480                                  */
2481                                 } else if (!strcmp(arg + 1, "rpath")) {
2482                                         /* Aha, we should try to link both! */
2483                                         cmd->install_path = argv[++a];
2484                                         arg_used = 1;
2485
2486                                 } else if (!strcmp(arg + 1, "release")) {
2487                                         /* Store for later deciphering */
2488                                         cmd->version_info = argv[++a];
2489                                         arg_used = 1;
2490
2491                                 } else if (!strcmp(arg + 1, "version-info")) {
2492                                         /* Store for later deciphering */
2493                                         cmd->version_info = argv[++a];
2494                                         arg_used = 1;
2495
2496                                 } else if (!strcmp(arg + 1,
2497                                                    "export-symbols-regex")) {
2498                                         /* Skip the argument. */
2499                                         ++a;
2500                                         arg_used = 1;
2501
2502                                 } else if (!strcmp(arg + 1, "undefined")) {
2503                                         cmd->undefined_flag = argv[++a];
2504                                         arg_used = 1;
2505                                 /*
2506                                  *      Add dir to runtime library search path.
2507                                  */
2508                                 } else if ((arg[1] == 'R') && !arg[2]) {
2509
2510                                         add_runtime_dir_lib(argv[++a], cmd);
2511                                         arg_used = 1;
2512                                 }
2513                         }
2514                 /*
2515                  *      Ok.. the argument doesn't begin with a dash
2516                  *      maybe it's an input file.
2517                  *
2518                  *      Check its extension to see if it's a known input
2519                  *      file and verify it exists.
2520                  */
2521                 } else {
2522                         arg_used = parse_input_file_name(arg, cmd);
2523                 }
2524
2525                 /*
2526                  *      If we still don't have a run mode, look for a magic
2527                  *      program name CC, LINK, or whatever.  Then replace that
2528                  *      with the name of the real program we want to run.
2529                  */
2530                 if (!arg_used) {
2531                         if ((cmd->arglist->num == 0) &&
2532                                 (cmd->mode == MODE_UNKNOWN)) {
2533                                 arg = automode(arg, cmd);
2534                         }
2535
2536                         DEBUG("Adding: %s\n", arg);
2537
2538                         push_count_chars(cmd->arglist, arg);
2539                 }
2540         }
2541
2542 }
2543
2544 int main(int argc, char *argv[])
2545 {
2546         int rc;
2547         command_t cmd;
2548
2549         memset(&cmd, 0, sizeof(cmd));
2550
2551         cmd.options.pic_mode = PIC_UNKNOWN;
2552         cmd.mode = MODE_UNKNOWN;
2553         cmd.output = OUT_GENERAL;
2554
2555         /*
2556          *      Initialise the various argument lists
2557          */
2558         cmd.program_opts                = alloc_countchars();
2559         cmd.arglist                     = alloc_countchars();
2560         cmd.tmp_dirs                    = alloc_countchars();
2561         cmd.obj_files                   = alloc_countchars();
2562         cmd.dep_rpaths                  = alloc_countchars();
2563         cmd.rpaths                      = alloc_countchars();
2564         cmd.static_opts.normal          = alloc_countchars();
2565         cmd.shared_opts.normal          = alloc_countchars();
2566         cmd.shared_opts.dependencies    = alloc_countchars();
2567
2568         /*
2569          *      Fill up the various argument lists
2570          */
2571         parse_args(argc, argv, &cmd);
2572         post_parse_fixup(&cmd);
2573
2574         /*
2575          *      We couldn't figure out which mode to operate in
2576          */
2577         if (cmd.mode == MODE_UNKNOWN) {
2578                 usage(1);
2579         }
2580
2581         rc = run_mode(&cmd);
2582         if (!rc) {
2583                 add_for_runtime(&cmd);
2584         }
2585
2586         cleanup_tmp_dirs(&cmd);
2587
2588         return rc;
2589 }