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