~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/build/jlibtool.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
#include <sys/wait.h>
 
23
#include <unistd.h>
 
24
#include <dirent.h>
 
25
#include <errno.h>
 
26
#include <assert.h>
 
27
 
 
28
#ifdef __EMX__
 
29
#  define SHELL_CMD  "sh"
 
30
#  define GEN_EXPORTS "emxexp"
 
31
#  define DEF2IMPLIB_CMD "emximp"
 
32
#  define SHARE_SW   "-Zdll -Zmtd"
 
33
#  define USE_OMF 1
 
34
#  define TRUNCATE_DLL_NAME
 
35
#  define DYNAMIC_LIB_EXT "dll"
 
36
#  define EXE_EXT ".exe"
 
37
 
 
38
#  if USE_OMF
 
39
     /* OMF is the native format under OS/2 */
 
40
#    define STATIC_LIB_EXT "lib"
 
41
#    define OBJECT_EXT     "obj"
 
42
#    define LIBRARIAN      "emxomfar"
 
43
#    define LIBRARIAN_OPTS "cr"
 
44
#  else
 
45
     /* but the alternative, a.out, can fork() which is sometimes necessary */
 
46
#    define STATIC_LIB_EXT "a"
 
47
#    define OBJECT_EXT     "o"
 
48
#    define LIBRARIAN      "ar"
 
49
#    define LIBRARIAN_OPTS "cr"
 
50
#  endif
 
51
#endif
 
52
 
 
53
#if defined(__APPLE__)
 
54
#  define SHELL_CMD  "/bin/sh"
 
55
#  define DYNAMIC_LIB_EXT "dylib"
 
56
#  define MODULE_LIB_EXT  "so"
 
57
#  define STATIC_LIB_EXT "a"
 
58
#  define OBJECT_EXT     "o"
 
59
#  define LIBRARIAN      "ar"
 
60
#  define LIBRARIAN_OPTS "cr"
 
61
/* man libtool(1) documents ranlib option of -c.  */
 
62
#  define RANLIB "ranlib"
 
63
#  define PIC_FLAG "-fPIC -fno-common"
 
64
#  define SHARED_OPTS "-dynamiclib"
 
65
#  define MODULE_OPTS "-bundle"
 
66
#  define DYNAMIC_LINK_OPTS "-flat_namespace -undefined suppress"
 
67
#  define dynamic_link_version_func darwin_dynamic_link_function
 
68
#  define DYNAMIC_INSTALL_NAME "-install_name"
 
69
#  define DYNAMIC_LINK_NO_INSTALL "-dylib_file"
 
70
#  define HAS_REALPATH
 
71
/*-install_name  /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */
 
72
#  define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
 
73
#endif
 
74
 
 
75
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
 
76
#  define SHELL_CMD  "/bin/sh"
 
77
#  define DYNAMIC_LIB_EXT "so"
 
78
#  define MODULE_LIB_EXT  "so"
 
79
#  define STATIC_LIB_EXT "a"
 
80
#  define OBJECT_EXT     "o"
 
81
#  define LIBRARIAN      "ar"
 
82
#  define LIBRARIAN_OPTS "cr"
 
83
#  define RANLIB "ranlib"
 
84
#  define PIC_FLAG "-fPIC"
 
85
#  define RPATH "-rpath"
 
86
#  define SHARED_OPTS "-shared"
 
87
#  define MODULE_OPTS "-shared"
 
88
#  define DYNAMIC_LINK_OPTS "-export-dynamic"
 
89
#  define LINKER_FLAG_PREFIX "-Wl,"
 
90
#  define ADD_MINUS_L
 
91
#  define LD_RUN_PATH "LD_RUN_PATH"
 
92
#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
 
93
#endif
 
94
 
 
95
#if defined(sun)
 
96
#  define SHELL_CMD  "/bin/sh"
 
97
#  define DYNAMIC_LIB_EXT "so"
 
98
#  define MODULE_LIB_EXT  "so"
 
99
#  define STATIC_LIB_EXT "a"
 
100
#  define OBJECT_EXT     "o"
 
101
#  define LIBRARIAN      "ar"
 
102
#  define LIBRARIAN_OPTS "cr"
 
103
#  define RANLIB "ranlib"
 
104
#  define PIC_FLAG "-KPIC"
 
105
#  define RPATH "-R"
 
106
#  define SHARED_OPTS "-G"
 
107
#  define MODULE_OPTS "-G"
 
108
#  define DYNAMIC_LINK_OPTS ""
 
109
#  define LINKER_FLAG_NO_EQUALS
 
110
#  define ADD_MINUS_L
 
111
#  define HAS_REALPATH
 
112
#  define LD_RUN_PATH "LD_RUN_PATH"
 
113
#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
 
114
#endif
 
115
 
 
116
#if defined(_OSD_POSIX)
 
117
#  define SHELL_CMD  "/usr/bin/sh"
 
118
#  define DYNAMIC_LIB_EXT "so"
 
119
#  define MODULE_LIB_EXT  "so"
 
120
#  define STATIC_LIB_EXT "a"
 
121
#  define OBJECT_EXT     "o"
 
122
#  define LIBRARIAN      "ar"
 
123
#  define LIBRARIAN_OPTS "cr"
 
124
#  define SHARED_OPTS "-G"
 
125
#  define MODULE_OPTS "-G"
 
126
#  define LINKER_FLAG_PREFIX "-Wl,"
 
127
#  define NEED_SNPRINTF
 
128
#endif
 
129
 
 
130
#if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX)
 
131
#  define SHELL_CMD  "/usr/bin/sh"
 
132
#  define DYNAMIC_LIB_EXT "so"
 
133
#  define MODULE_LIB_EXT  "so"
 
134
#  define STATIC_LIB_EXT "a"
 
135
#  define OBJECT_EXT     "o"
 
136
#  define LIBRARIAN      "ar"
 
137
#  define LIBRARIAN_OPTS "cr"
 
138
#  define RPATH "-Brpath"
 
139
#  define SHARED_OPTS "-G"
 
140
#  define MODULE_OPTS "-G"
 
141
#  define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym"
 
142
#  define LINKER_FLAG_PREFIX "-Wl,"
 
143
#  define NEED_SNPRINTF
 
144
#  define LD_RUN_PATH "LD_RUN_PATH"
 
145
#  define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
 
146
#endif
 
147
 
 
148
#ifndef SHELL_CMD
 
149
#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform.
 
150
#endif
 
151
 
 
152
#ifdef NEED_SNPRINTF
 
153
#include <stdarg.h>
 
154
#endif
 
155
 
 
156
#ifdef __EMX__
 
157
#include <process.h>
 
158
#endif
 
159
 
 
160
#ifndef PATH_MAX
 
161
#define PATH_MAX 1024
 
162
#endif
 
163
 
 
164
 
 
165
/* We want to say we are libtool 1.4 for shlibtool compatibility. */
 
166
#define VERSION "1.4"
 
167
 
 
168
enum tool_mode_t {
 
169
    mUnknown,
 
170
    mCompile,
 
171
    mLink,
 
172
    mInstall,
 
173
};
 
174
 
 
175
enum output_t {
 
176
    otGeneral,
 
177
    otObject,
 
178
    otProgram,
 
179
    otLibrary,
 
180
    otStaticLibraryOnly,
 
181
    otDynamicLibraryOnly,
 
182
    otModule,
 
183
};
 
184
 
 
185
enum pic_mode_e {
 
186
    pic_UNKNOWN,
 
187
    pic_PREFER,
 
188
    pic_AVOID,
 
189
};
 
190
 
 
191
enum lib_type {
 
192
    type_UNKNOWN,
 
193
    type_DYNAMIC_LIB,
 
194
    type_STATIC_LIB,
 
195
    type_MODULE_LIB,
 
196
    type_OBJECT,
 
197
};
 
198
 
 
199
typedef struct {
 
200
    const char **vals;
 
201
    int num; 
 
202
} count_chars;
 
203
 
 
204
typedef struct {
 
205
    const char *normal;
 
206
    const char *install;
 
207
} library_name;
 
208
 
 
209
typedef struct {
 
210
    count_chars *normal;
 
211
    count_chars *install;
 
212
    count_chars *dependencies;
 
213
} library_opts;
 
214
 
 
215
typedef struct {
 
216
    int silent;
 
217
    int shared;
 
218
    int export_all;
 
219
    int dry_run;
 
220
    enum pic_mode_e pic_mode;
 
221
    int export_dynamic;
 
222
    int no_install;
 
223
} options_t;
 
224
 
 
225
typedef struct {
 
226
    enum tool_mode_t mode;
 
227
    enum output_t output;
 
228
    options_t options;
 
229
 
 
230
    char *output_name;
 
231
    char *fake_output_name;
 
232
    char *basename;
 
233
 
 
234
    const char *install_path;
 
235
    const char *compiler;
 
236
    const char *program;
 
237
    count_chars *program_opts;
 
238
 
 
239
    count_chars *arglist;
 
240
    count_chars *tmp_dirs;
 
241
    count_chars *obj_files;
 
242
    count_chars *dep_rpaths;
 
243
    count_chars *rpaths;
 
244
 
 
245
    library_name static_name;
 
246
    library_name shared_name;
 
247
    library_name module_name;
 
248
 
 
249
    library_opts static_opts;
 
250
    library_opts shared_opts;
 
251
 
 
252
    const char *version_info;
 
253
} command_t;
 
254
 
 
255
#ifdef RPATH
 
256
void add_rpath(count_chars *cc, const char *path);
 
257
#endif
 
258
 
 
259
#if defined(NEED_SNPRINTF)
 
260
/* Write at most n characters to the buffer in str, return the
 
261
 * number of chars written or -1 if the buffer would have been
 
262
 * overflowed.
 
263
 *
 
264
 * This is portable to any POSIX-compliant system has /dev/null
 
265
 */
 
266
static FILE *f=NULL;
 
267
static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
 
268
{
 
269
       int res;
 
270
 
 
271
       if (f == NULL)
 
272
               f = fopen("/dev/null","w");
 
273
       if (f == NULL)
 
274
               return -1;
 
275
 
 
276
       setvbuf( f, str, _IOFBF, n );
 
277
 
 
278
       res = vfprintf( f, fmt, ap );
 
279
 
 
280
       if ( res > 0 && res < n ) {
 
281
               res = vsprintf( str, fmt, ap );
 
282
       }
 
283
       return res;
 
284
}
 
285
static int snprintf( char *str, size_t n, const char *fmt, ... )
 
286
{
 
287
        va_list ap;
 
288
        int res;
 
289
 
 
290
        va_start( ap, fmt );
 
291
        res = vsnprintf( str, n, fmt, ap );
 
292
        va_end( ap );
 
293
        return res;
 
294
}
 
295
#endif
 
296
 
 
297
void init_count_chars(count_chars *cc)
 
298
{
 
299
    cc->vals = (const char**)malloc(PATH_MAX);
 
300
    cc->num = 0;
 
301
}
 
302
 
 
303
void clear_count_chars(count_chars *cc)
 
304
{
 
305
    int i;
 
306
    for (i = 0; i < cc->num; i++) {
 
307
        cc->vals[i] = 0;
 
308
    }
 
309
 
 
310
    cc->num = 0;
 
311
}
 
312
 
 
313
void push_count_chars(count_chars *cc, const char *newval)
 
314
{
 
315
    cc->vals[cc->num++] = newval;
 
316
}
 
317
 
 
318
void insert_count_chars(count_chars *cc, const char *newval, int position)
 
319
{
 
320
    int i;
 
321
 
 
322
    for (i = cc->num; i > position; i--) {
 
323
        cc->vals[i] = cc->vals[i-1];
 
324
    }
 
325
 
 
326
    cc->vals[position] = newval;
 
327
    cc->num++;
 
328
}
 
329
 
 
330
void append_count_chars(count_chars *cc, count_chars *cctoadd)
 
331
{
 
332
    int i;
 
333
    for (i = 0; i < cctoadd->num; i++) {
 
334
        if (cctoadd->vals[i]) {
 
335
            push_count_chars(cc, cctoadd->vals[i]);
 
336
        }
 
337
    }
 
338
}
 
339
 
 
340
const char *flatten_count_chars(count_chars *cc)
 
341
{
 
342
    int i, size;
 
343
    char *newval;
 
344
 
 
345
    size = 0;
 
346
    for (i = 0; i < cc->num; i++) {
 
347
        if (cc->vals[i]) {
 
348
            size += strlen(cc->vals[i]) + 1;
 
349
        }
 
350
    }
 
351
 
 
352
    newval = (char*)malloc(size + 1);
 
353
    newval[0] = 0;
 
354
 
 
355
    for (i = 0; i < cc->num; i++) {
 
356
        if (cc->vals[i]) {
 
357
            strcat(newval, cc->vals[i]);
 
358
            strcat(newval, " ");
 
359
        }
 
360
    }
 
361
 
 
362
    return newval;
 
363
}
 
364
 
 
365
char *shell_esc(const char *str)
 
366
{
 
367
    int in_quote = 0;
 
368
    char *cmd;
 
369
    unsigned char *d;
 
370
    const unsigned char *s;
 
371
 
 
372
    cmd = (char *)malloc(2 * strlen(str) + 1);
 
373
    d = (unsigned char *)cmd;
 
374
    s = (const unsigned char *)str;
 
375
 
 
376
    for (; *s; ++s) {
 
377
        if (*s == '"') {
 
378
            *d++ = '\\';
 
379
            in_quote++;
 
380
        }
 
381
        else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) {
 
382
            *d++ = '\\';
 
383
        }
 
384
        *d++ = *s;
 
385
    }
 
386
 
 
387
    *d = '\0';
 
388
    return cmd;
 
389
}
 
390
 
 
391
int external_spawn(command_t *cmd, const char *file, const char **argv)
 
392
{
 
393
    if (!cmd->options.silent) {
 
394
        const char **argument = argv;
 
395
        printf("Executing: ");
 
396
        while (*argument) {
 
397
            printf("%s ", *argument);
 
398
            argument++;
 
399
        }
 
400
        puts("");
 
401
    }
 
402
 
 
403
    if (cmd->options.dry_run) {
 
404
        return 0;
 
405
    }
 
406
#ifdef __EMX__
 
407
    return spawnvp(P_WAIT, file, argv);
 
408
#else
 
409
    {
 
410
        pid_t pid;
 
411
        pid = fork();
 
412
        if (pid == 0) {
 
413
            return execvp(argv[0], (char**)argv);
 
414
        }
 
415
        else {
 
416
            int statuscode;
 
417
            waitpid(pid, &statuscode, 0);
 
418
            if (WIFEXITED(statuscode)) {
 
419
                return WEXITSTATUS(statuscode);
 
420
            }
 
421
            return 0;
 
422
        }
 
423
    }
 
424
#endif
 
425
}
 
426
 
 
427
int run_command(command_t *cmd_data, count_chars *cc)
 
428
{
 
429
    char *command;
 
430
    const char *spawn_args[4];
 
431
    count_chars tmpcc;
 
432
 
 
433
    init_count_chars(&tmpcc);
 
434
 
 
435
    if (cmd_data->program) {
 
436
        push_count_chars(&tmpcc, cmd_data->program);
 
437
    }
 
438
 
 
439
    append_count_chars(&tmpcc, cmd_data->program_opts);
 
440
 
 
441
    append_count_chars(&tmpcc, cc);
 
442
 
 
443
    command = shell_esc(flatten_count_chars(&tmpcc));
 
444
 
 
445
    spawn_args[0] = SHELL_CMD;
 
446
    spawn_args[1] = "-c";
 
447
    spawn_args[2] = command;
 
448
    spawn_args[3] = NULL;
 
449
    return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args);
 
450
}
 
451
 
 
452
/*
 
453
 * print configuration
 
454
 * shlibpath_var is used in configure.
 
455
 */
 
456
void print_config()
 
457
{
 
458
#ifdef LD_RUN_PATH
 
459
    printf("runpath_var=%s\n", LD_RUN_PATH);
 
460
#endif
 
461
#ifdef LD_LIBRARY_PATH
 
462
    printf("shlibpath_var=%s\n", LD_LIBRARY_PATH);
 
463
#endif
 
464
#ifdef SHELL_CMD
 
465
    printf("SHELL=\"%s\"\n", SHELL_CMD);
 
466
#endif
 
467
}
 
468
/*
 
469
 * Add a directory to the runtime library search path.
 
470
 */
 
471
void add_runtimedirlib(char *arg, command_t *cmd_data)
 
472
{
 
473
#ifdef RPATH
 
474
    add_rpath(cmd_data->shared_opts.dependencies, arg);
 
475
#else
 
476
#endif
 
477
}
 
478
 
 
479
int parse_long_opt(char *arg, command_t *cmd_data)
 
480
{
 
481
    char *equal_pos = strchr(arg, '=');
 
482
    char var[50];
 
483
    char value[500];
 
484
 
 
485
    if (equal_pos) {
 
486
        strncpy(var, arg, equal_pos - arg);
 
487
        var[equal_pos - arg] = 0;
 
488
        strcpy(value, equal_pos + 1);
 
489
    } else {
 
490
        strcpy(var, arg);
 
491
    }
 
492
 
 
493
    if (strcmp(var, "silent") == 0) {
 
494
        cmd_data->options.silent = 1;
 
495
    } else if (strcmp(var, "mode") == 0) {
 
496
        if (strcmp(value, "compile") == 0) {
 
497
            cmd_data->mode = mCompile;
 
498
            cmd_data->output = otObject;
 
499
        }
 
500
 
 
501
        if (strcmp(value, "link") == 0) {
 
502
            cmd_data->mode = mLink;
 
503
            cmd_data->output = otLibrary;
 
504
        }
 
505
 
 
506
        if (strcmp(value, "install") == 0) {
 
507
            cmd_data->mode = mInstall;
 
508
        }
 
509
    } else if (strcmp(var, "shared") == 0) {
 
510
        if (cmd_data->mode == mLink) {
 
511
            cmd_data->output = otDynamicLibraryOnly;
 
512
        }
 
513
        cmd_data->options.shared = 1;
 
514
    } else if (strcmp(var, "export-all") == 0) {
 
515
        cmd_data->options.export_all = 1;
 
516
    } else if (strcmp(var, "dry-run") == 0) {
 
517
        printf("Dry-run mode on!\n");
 
518
        cmd_data->options.dry_run = 1;
 
519
    } else if (strcmp(var, "version") == 0) {
 
520
        printf("Version " VERSION "\n");
 
521
    } else if (strcmp(var, "help") == 0) {
 
522
        printf("Sorry.  No help available.\n");
 
523
    } else if (strcmp(var, "config") == 0) {
 
524
        print_config();
 
525
    } else if (strcmp(var, "tag") == 0) {
 
526
        if (strcmp(value, "CC") == 0) {
 
527
            /* Do nothing. */
 
528
        }
 
529
        if (strcmp(value, "CXX") == 0) {
 
530
            /* Do nothing. */
 
531
        }
 
532
    } else {
 
533
        return 0;
 
534
    }
 
535
 
 
536
    return 1;
 
537
}
 
538
 
 
539
/* Return 1 if we eat it. */
 
540
int parse_short_opt(char *arg, command_t *cmd_data)
 
541
{
 
542
    if (strcmp(arg, "export-dynamic") == 0) {
 
543
        cmd_data->options.export_dynamic = 1;
 
544
        return 1;
 
545
    }
 
546
 
 
547
    if (strcmp(arg, "module") == 0) {
 
548
        cmd_data->output = otModule;
 
549
        return 1;
 
550
    }
 
551
 
 
552
    if (strcmp(arg, "Zexe") == 0) {
 
553
        return 1;
 
554
    }
 
555
 
 
556
    if (strcmp(arg, "avoid-version") == 0) {
 
557
        return 1;
 
558
    }
 
559
 
 
560
    if (strcmp(arg, "prefer-pic") == 0) {
 
561
        cmd_data->options.pic_mode = pic_PREFER;
 
562
        return 1;
 
563
    }
 
564
 
 
565
    if (strcmp(arg, "prefer-non-pic") == 0) {
 
566
        cmd_data->options.pic_mode = pic_AVOID;
 
567
        return 1;
 
568
    }
 
569
 
 
570
    if (strcmp(arg, "static") == 0) {
 
571
        /* Don't respect it for now. */
 
572
        return 1;
 
573
    }
 
574
 
 
575
    if (cmd_data->mode == mLink) {
 
576
        if (strcmp(arg, "no-install") == 0) {
 
577
            cmd_data->options.no_install = 1;
 
578
            return 1;
 
579
        }
 
580
        if (arg[0] == 'L' || arg[0] == 'l') {
 
581
            /* Hack... */
 
582
            arg--;
 
583
            push_count_chars(cmd_data->shared_opts.dependencies, arg);
 
584
            return 1;
 
585
        } else if (arg[0] == 'R' && arg[1]) {
 
586
            /* -Rdir Add dir to runtime library search path. */
 
587
            add_runtimedirlib(&arg[1], cmd_data);
 
588
            return 1;
 
589
        }
 
590
    }
 
591
    return 0;
 
592
}
 
593
 
 
594
char *truncate_dll_name(char *path)
 
595
{
 
596
    /* Cut DLL name down to 8 characters after removing any mod_ prefix */
 
597
    char *tmppath = strdup(path);
 
598
    char *newname = strrchr(tmppath, '/') + 1;
 
599
    char *ext = strrchr(tmppath, '.');
 
600
    int len;
 
601
 
 
602
    if (ext == NULL)
 
603
        return tmppath;
 
604
 
 
605
    len = ext - newname;
 
606
 
 
607
    if (strncmp(newname, "mod_", 4) == 0) {
 
608
        strcpy(newname, newname + 4);
 
609
        len -= 4;
 
610
    }
 
611
 
 
612
    if (len > 8) {
 
613
        strcpy(newname + 8, strchr(newname, '.'));
 
614
    }
 
615
 
 
616
    return tmppath;
 
617
}
 
618
 
 
619
long safe_strtol(const char *nptr, const char **endptr, int base)
 
620
{
 
621
    long rv;
 
622
 
 
623
    errno = 0;
 
624
 
 
625
    rv = strtol(nptr, (char**)endptr, 10);
 
626
 
 
627
    if (errno == ERANGE) {
 
628
        return 0;
 
629
    }
 
630
 
 
631
    return rv; 
 
632
}
 
633
 
 
634
/* version_info is in the form of MAJOR:MINOR:PATCH */
 
635
const char *darwin_dynamic_link_function(const char *version_info)
 
636
{
 
637
    char *newarg;
 
638
    long major, minor, patch;
 
639
 
 
640
    major = 0;
 
641
    minor = 0;
 
642
    patch = 0;
 
643
 
 
644
    if (version_info) {
 
645
        major = safe_strtol(version_info, &version_info, 10);
 
646
 
 
647
        if (version_info) {
 
648
            if (version_info[0] == ':') {
 
649
                version_info++;
 
650
            }
 
651
 
 
652
            minor = safe_strtol(version_info, &version_info, 10);
 
653
 
 
654
            if (version_info) {
 
655
                if (version_info[0] == ':') {
 
656
                    version_info++;
 
657
                }
 
658
 
 
659
                patch = safe_strtol(version_info, &version_info, 10);
 
660
 
 
661
            }
 
662
        }
 
663
    }
 
664
 
 
665
    /* Avoid -dylib_compatibility_version must be greater than zero errors. */
 
666
    if (major == 0) {
 
667
        major = 1;
 
668
    }
 
669
    newarg = (char*)malloc(100);
 
670
    snprintf(newarg, 99,
 
671
             "-compatibility_version %ld -current_version %ld.%ld",
 
672
             major, major, minor);
 
673
 
 
674
    return newarg;
 
675
}
 
676
 
 
677
/* genlib values
 
678
 * 0 - static
 
679
 * 1 - dynamic
 
680
 * 2 - module
 
681
 */
 
682
char *gen_library_name(const char *name, int genlib)
 
683
{
 
684
    char *newarg, *newext;
 
685
 
 
686
    newarg = (char *)malloc(strlen(name) + 10);
 
687
    strcpy(newarg, ".libs/");
 
688
 
 
689
    if (genlib == 2 && strncmp(name, "lib", 3) == 0) {
 
690
        name += 3;
 
691
    }
 
692
 
 
693
    strcat(newarg, name);
 
694
 
 
695
    newext = strrchr(newarg, '.') + 1;
 
696
 
 
697
    switch (genlib) {
 
698
    case 0:
 
699
        strcpy(newext, STATIC_LIB_EXT);
 
700
        break;
 
701
    case 1:
 
702
        strcpy(newext, DYNAMIC_LIB_EXT);
 
703
        break;
 
704
    case 2:
 
705
        strcpy(newext, MODULE_LIB_EXT);
 
706
        break;
 
707
    }
 
708
 
 
709
    return newarg;
 
710
}
 
711
 
 
712
/* genlib values
 
713
 * 0 - static
 
714
 * 1 - dynamic
 
715
 * 2 - module
 
716
 */
 
717
char *gen_install_name(const char *name, int genlib)
 
718
{
 
719
    struct stat sb;
 
720
    char *newname;
 
721
    int rv;
 
722
 
 
723
    newname = gen_library_name(name, genlib);
 
724
 
 
725
    /* Check if it exists. If not, return NULL.  */
 
726
    rv = stat(newname, &sb);
 
727
 
 
728
    if (rv) {
 
729
        return NULL;
 
730
    }
 
731
 
 
732
    return newname;
 
733
}
 
734
 
 
735
char *check_object_exists(command_t *cmd, const char *arg, int arglen)
 
736
{
 
737
    char *newarg, *ext;
 
738
    int pass, rv;
 
739
 
 
740
    newarg = (char *)malloc(arglen + 10);
 
741
    memcpy(newarg, arg, arglen);
 
742
    newarg[arglen] = 0;
 
743
    ext = newarg + arglen;
 
744
 
 
745
    pass = 0;
 
746
 
 
747
    do {
 
748
        struct stat sb;
 
749
 
 
750
        switch (pass) {
 
751
        case 0:
 
752
            strcpy(ext, OBJECT_EXT);
 
753
            break;
 
754
/*
 
755
        case 1:
 
756
            strcpy(ext, NO_PIC_EXT);
 
757
            break;
 
758
*/
 
759
        default:
 
760
            break;
 
761
        } 
 
762
 
 
763
        if (!cmd->options.silent) {
 
764
            printf("Checking (obj): %s\n", newarg);
 
765
        }
 
766
        rv = stat(newarg, &sb);
 
767
    }
 
768
    while (rv != 0 && ++pass < 1);
 
769
 
 
770
    if (rv == 0) {
 
771
        if (pass == 1) {
 
772
            cmd->options.pic_mode = pic_AVOID;
 
773
        }
 
774
        return newarg;
 
775
    }
 
776
 
 
777
    return NULL;
 
778
}
 
779
 
 
780
/* libdircheck values:
 
781
 * 0 - no .libs suffix
 
782
 * 1 - .libs suffix
 
783
 */
 
784
char *check_library_exists(command_t *cmd, const char *arg, int pathlen,
 
785
                           int libdircheck, enum lib_type *libtype)
 
786
{
 
787
    char *newarg, *ext;
 
788
    int pass, rv, newpathlen;
 
789
 
 
790
    newarg = (char *)malloc(strlen(arg) + 10);
 
791
    strcpy(newarg, arg);
 
792
    newarg[pathlen] = 0;
 
793
 
 
794
    newpathlen = pathlen;
 
795
    if (libdircheck) {
 
796
        strcat(newarg, ".libs/");
 
797
        newpathlen += sizeof(".libs/") - 1;
 
798
    }
 
799
 
 
800
    strcpy(newarg+newpathlen, arg+pathlen);
 
801
    ext = strrchr(newarg, '.') + 1;
 
802
 
 
803
    pass = 0;
 
804
 
 
805
    do {
 
806
        struct stat sb;
 
807
 
 
808
        switch (pass) {
 
809
        case 0:
 
810
            if (cmd->options.pic_mode != pic_AVOID || cmd->options.shared) {
 
811
                strcpy(ext, DYNAMIC_LIB_EXT);
 
812
                *libtype = type_DYNAMIC_LIB;
 
813
                break;
 
814
            }
 
815
            pass = 1;
 
816
        case 1:
 
817
            strcpy(ext, STATIC_LIB_EXT);
 
818
            *libtype = type_STATIC_LIB;
 
819
            break;
 
820
        case 2:
 
821
            strcpy(ext, MODULE_LIB_EXT);
 
822
            *libtype = type_MODULE_LIB;
 
823
            break;
 
824
        case 3:
 
825
            strcpy(ext, OBJECT_EXT);
 
826
            *libtype = type_OBJECT;
 
827
            break;
 
828
        default:
 
829
            *libtype = type_UNKNOWN;
 
830
            break;
 
831
        } 
 
832
 
 
833
        if (!cmd->options.silent) {
 
834
            printf("Checking (lib): %s\n", newarg);
 
835
        }
 
836
        rv = stat(newarg, &sb);
 
837
    }
 
838
    while (rv != 0 && ++pass < 4);
 
839
 
 
840
    if (rv == 0) {
 
841
        return newarg;
 
842
    }
 
843
 
 
844
    return NULL;
 
845
}
 
846
 
 
847
char * load_install_path(const char *arg)
 
848
{
 
849
    FILE *f;
 
850
    char *path;
 
851
 
 
852
    path = malloc(PATH_MAX);
 
853
 
 
854
    f = fopen(arg,"r");
 
855
    if (f == NULL) {
 
856
        return NULL;
 
857
    }
 
858
    fgets(path, PATH_MAX, f);
 
859
    fclose(f);
 
860
    if (path[strlen(path)-1] == '\n') {
 
861
        path[strlen(path)-1] = '\0';
 
862
    }
 
863
    /* Check that we have an absolute path.
 
864
     * Otherwise the file could be a GNU libtool file.
 
865
     */
 
866
    if (path[0] != '/') {
 
867
        return NULL;
 
868
    }
 
869
    return path;
 
870
}
 
871
 
 
872
char * load_noinstall_path(const char *arg, int pathlen)
 
873
{
 
874
    char *newarg, *expanded_path;
 
875
    int newpathlen;
 
876
 
 
877
    newarg = (char *)malloc(strlen(arg) + 10);
 
878
    strcpy(newarg, arg);
 
879
    newarg[pathlen] = 0;
 
880
 
 
881
    newpathlen = pathlen;
 
882
    strcat(newarg, ".libs");
 
883
    newpathlen += sizeof(".libs") - 1;
 
884
    newarg[newpathlen] = 0;
 
885
 
 
886
#ifdef HAS_REALPATH
 
887
    expanded_path = malloc(PATH_MAX);
 
888
    expanded_path = realpath(newarg, expanded_path);
 
889
    /* Uh, oh.  There was an error.  Fall back on our first guess. */
 
890
    if (!expanded_path) {
 
891
        expanded_path = newarg;
 
892
    }
 
893
#else
 
894
    /* We might get ../ or something goofy.  Oh, well. */
 
895
    expanded_path = newarg;
 
896
#endif
 
897
 
 
898
    return expanded_path;
 
899
}
 
900
 
 
901
/* Read the final install location and add it to runtime library search path. */
 
902
#ifdef RPATH
 
903
void add_rpath(count_chars *cc, const char *path)
 
904
{
 
905
    int size = 0;
 
906
    char *tmp;
 
907
 
 
908
#ifdef LINKER_FLAG_PREFIX
 
909
    size = strlen(LINKER_FLAG_PREFIX);
 
910
#endif
 
911
    size = size + strlen(path) + strlen(RPATH) + 2;
 
912
    tmp = malloc(size);
 
913
    if (tmp == NULL) {
 
914
        return;
 
915
    }
 
916
#ifdef LINKER_FLAG_PREFIX
 
917
    strcpy(tmp, LINKER_FLAG_PREFIX);
 
918
    strcat(tmp, RPATH);
 
919
#else
 
920
    strcpy(tmp, RPATH);
 
921
#endif
 
922
#ifndef LINKER_FLAG_NO_EQUALS
 
923
    strcat(tmp, "=");
 
924
#endif
 
925
    strcat(tmp, path);
 
926
 
 
927
    push_count_chars(cc, tmp);
 
928
}
 
929
 
 
930
void add_rpath_file(count_chars *cc, const char *arg)
 
931
{
 
932
    const char *path;
 
933
 
 
934
    path = load_install_path(arg);
 
935
    if (path) {
 
936
        add_rpath(cc, path);
 
937
    }
 
938
}
 
939
 
 
940
void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen)
 
941
{
 
942
    const char *path;
 
943
 
 
944
    path = load_noinstall_path(arg, pathlen);
 
945
    if (path) {
 
946
        add_rpath(cc, path);
 
947
    }
 
948
}
 
949
#endif
 
950
 
 
951
#ifdef DYNAMIC_LINK_NO_INSTALL
 
952
void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen,
 
953
                          int extlen)
 
954
{
 
955
    const char *install_path, *current_path, *name;
 
956
    char *exp_argument;
 
957
    int i_p_len, c_p_len, name_len, dyext_len, cur_len;
 
958
 
 
959
    install_path = load_install_path(arg);
 
960
    current_path = load_noinstall_path(arg, pathlen);
 
961
 
 
962
    if (!install_path || !current_path) {
 
963
        return;
 
964
    }
 
965
 
 
966
    push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL);
 
967
 
 
968
    i_p_len = strlen(install_path);
 
969
    c_p_len = strlen(current_path);
 
970
 
 
971
    name = arg+pathlen;
 
972
    name_len = extlen-pathlen;
 
973
    dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1;
 
974
 
 
975
    /* No, we need to replace the extension. */
 
976
    exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) +
 
977
                                  (dyext_len*2) + 2);
 
978
 
 
979
    cur_len = 0;
 
980
    strcpy(exp_argument, install_path);
 
981
    cur_len += i_p_len;
 
982
    exp_argument[cur_len++] = '/';
 
983
    strncpy(exp_argument+cur_len, name, extlen-pathlen);
 
984
    cur_len += name_len;
 
985
    strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
 
986
    cur_len += dyext_len;
 
987
    exp_argument[cur_len++] = ':';
 
988
    strcpy(exp_argument+cur_len, current_path);
 
989
    cur_len += c_p_len;
 
990
    exp_argument[cur_len++] = '/';
 
991
    strncpy(exp_argument+cur_len, name, extlen-pathlen);
 
992
    cur_len += name_len;
 
993
    strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT);
 
994
    cur_len += dyext_len;
 
995
 
 
996
    push_count_chars(cc, exp_argument);
 
997
}
 
998
#endif
 
999
 
 
1000
/* use -L -llibname to allow to use installed libraries */
 
1001
void add_minus_l(count_chars *cc, const char *arg)
 
1002
{
 
1003
    char *newarg;
 
1004
    char *name = strrchr(arg, '/');
 
1005
    char *file = strrchr(arg, '.');
 
1006
    char *lib  = strstr(name, "lib");
 
1007
 
 
1008
    if (name !=NULL && file != NULL && lib == name+1) {
 
1009
        *name = '\0';
 
1010
        *file = '\0';
 
1011
        file = name;
 
1012
        file = file+4;
 
1013
        push_count_chars(cc, "-L");
 
1014
        push_count_chars(cc, arg);
 
1015
        /* we need one argument like -lapr-1 */
 
1016
        newarg = malloc(strlen(file) + 3);
 
1017
        strcpy(newarg, "-l");
 
1018
        strcat(newarg, file);
 
1019
        push_count_chars(cc, newarg);
 
1020
    } else {
 
1021
        push_count_chars(cc, arg);
 
1022
    }
 
1023
}
 
1024
 
 
1025
void add_linker_flag_prefix(count_chars *cc, const char *arg)
 
1026
{
 
1027
#ifndef LINKER_FLAG_PREFIX
 
1028
    push_count_chars(cc, arg);
 
1029
#else
 
1030
    char *newarg;
 
1031
    newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1);
 
1032
    strcpy(newarg, LINKER_FLAG_PREFIX);
 
1033
    strcat(newarg, arg);
 
1034
    push_count_chars(cc, newarg);
 
1035
#endif
 
1036
}
 
1037
 
 
1038
int parse_input_file_name(char *arg, command_t *cmd_data)
 
1039
{
 
1040
    char *ext = strrchr(arg, '.');
 
1041
    char *name = strrchr(arg, '/');
 
1042
    int pathlen;
 
1043
    enum lib_type libtype;
 
1044
    char *newarg;
 
1045
 
 
1046
    if (!ext) {
 
1047
        return 0;
 
1048
    }
 
1049
 
 
1050
    ext++;
 
1051
 
 
1052
    if (name == NULL) {
 
1053
        name = strrchr(arg, '\\');
 
1054
 
 
1055
        if (name == NULL) {
 
1056
            name = arg;
 
1057
        } else {
 
1058
            name++;
 
1059
        }
 
1060
    } else {
 
1061
        name++;
 
1062
    }
 
1063
 
 
1064
    pathlen = name - arg;
 
1065
 
 
1066
    if (strcmp(ext, "lo") == 0) {
 
1067
        newarg = check_object_exists(cmd_data, arg, ext - arg);
 
1068
        if (!newarg) {
 
1069
            printf("Can not find suitable object file for %s\n", arg);
 
1070
            exit(1);
 
1071
        }
 
1072
        if (cmd_data->mode != mLink) {
 
1073
            push_count_chars(cmd_data->arglist, newarg);
 
1074
        }
 
1075
        else {
 
1076
            push_count_chars(cmd_data->obj_files, newarg);
 
1077
        }
 
1078
        return 1;
 
1079
    }
 
1080
 
 
1081
    if (strcmp(ext, "la") == 0) {
 
1082
        switch (cmd_data->mode) {
 
1083
        case mLink:
 
1084
            /* Try the .libs dir first! */
 
1085
            newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype);
 
1086
            if (!newarg) {
 
1087
                /* Try the normal dir next. */
 
1088
                newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype);
 
1089
                if (!newarg) {
 
1090
                    printf("Can not find suitable library for %s\n", arg);
 
1091
                    exit(1);
 
1092
                }
 
1093
            }
 
1094
 
 
1095
            /* It is not ok to just add the file: a library may added with:
 
1096
               1 - -L path library_name. (For *.so in Linux).
 
1097
               2 - library_name.
 
1098
             */
 
1099
#ifdef ADD_MINUS_L
 
1100
            if (libtype == type_DYNAMIC_LIB) {
 
1101
                 add_minus_l(cmd_data->shared_opts.dependencies, newarg);
 
1102
            } else {
 
1103
                 push_count_chars(cmd_data->shared_opts.dependencies, newarg);
 
1104
            }
 
1105
#else
 
1106
            push_count_chars(cmd_data->shared_opts.dependencies, newarg);
 
1107
#endif
 
1108
            if (libtype == type_DYNAMIC_LIB) {
 
1109
                if (cmd_data->options.no_install) {
 
1110
#ifdef RPATH
 
1111
                    add_rpath_noinstall(cmd_data->shared_opts.dependencies,
 
1112
                                        arg, pathlen);
 
1113
#endif
 
1114
#ifdef DYNAMIC_LINK_NO_INSTALL
 
1115
                    /*
 
1116
                     * This doesn't work as Darwin's linker has no way to
 
1117
                     * override at link-time the search paths for a
 
1118
                     * non-installed library.
 
1119
                     */
 
1120
                    /*
 
1121
                    add_dylink_noinstall(cmd_data->shared_opts.dependencies,
 
1122
                                         arg, pathlen, ext - arg);
 
1123
                    */
 
1124
#endif
 
1125
                }
 
1126
                else {
 
1127
#ifdef RPATH
 
1128
                    add_rpath_file(cmd_data->shared_opts.dependencies, arg);
 
1129
#endif
 
1130
                }
 
1131
            }
 
1132
            break;
 
1133
        case mInstall:
 
1134
            /* If we've already recorded a library to install, we're most
 
1135
             * likely getting the .la file that we want to install as.
 
1136
             * The problem is that we need to add it as the directory,
 
1137
             * not the .la file itself.  Otherwise, we'll do odd things.
 
1138
             */
 
1139
            if (cmd_data->output == otLibrary) {
 
1140
                arg[pathlen] = '\0';
 
1141
                push_count_chars(cmd_data->arglist, arg);
 
1142
            }
 
1143
            else {
 
1144
                cmd_data->output = otLibrary;
 
1145
                cmd_data->output_name = arg;
 
1146
                cmd_data->static_name.install = gen_install_name(arg, 0);
 
1147
                cmd_data->shared_name.install = gen_install_name(arg, 1);
 
1148
                cmd_data->module_name.install = gen_install_name(arg, 2);
 
1149
            }
 
1150
            break;
 
1151
        default:
 
1152
            break;
 
1153
        }
 
1154
        return 1;
 
1155
    }
 
1156
 
 
1157
    if (strcmp(ext, "c") == 0) {
 
1158
        /* If we don't already have an idea what our output name will be. */
 
1159
        if (cmd_data->basename == NULL) {
 
1160
            cmd_data->basename = (char *)malloc(strlen(arg) + 4);
 
1161
            strcpy(cmd_data->basename, arg);
 
1162
            strcpy(strrchr(cmd_data->basename, '.') + 1, "lo");
 
1163
 
 
1164
            cmd_data->fake_output_name = strrchr(cmd_data->basename, '/');
 
1165
            if (cmd_data->fake_output_name) {
 
1166
                cmd_data->fake_output_name++;
 
1167
            }
 
1168
            else {
 
1169
                cmd_data->fake_output_name = cmd_data->basename;
 
1170
            }
 
1171
        }
 
1172
    }
 
1173
 
 
1174
    return 0;
 
1175
}
 
1176
 
 
1177
int parse_output_file_name(char *arg, command_t *cmd_data)
 
1178
{
 
1179
    char *name = strrchr(arg, '/');
 
1180
    char *ext = strrchr(arg, '.');
 
1181
    char *newarg = NULL;
 
1182
    int pathlen;
 
1183
 
 
1184
    cmd_data->fake_output_name = arg;
 
1185
 
 
1186
    if (name) {
 
1187
        name++;
 
1188
    }
 
1189
    else {
 
1190
        name = strrchr(arg, '\\');
 
1191
 
 
1192
        if (name == NULL) {
 
1193
            name = arg;
 
1194
        }
 
1195
        else {
 
1196
            name++;
 
1197
        }
 
1198
    }
 
1199
 
 
1200
    if (!ext) {
 
1201
        cmd_data->basename = arg;
 
1202
        cmd_data->output = otProgram;
 
1203
#if defined(_OSD_POSIX)
 
1204
        cmd_data->options.pic_mode = pic_AVOID;
 
1205
#endif
 
1206
        newarg = (char *)malloc(strlen(arg) + 5);
 
1207
        strcpy(newarg, arg);
 
1208
#ifdef EXE_EXT
 
1209
        strcat(newarg, EXE_EXT);
 
1210
#endif
 
1211
        cmd_data->output_name = newarg;
 
1212
        return 1;
 
1213
    }
 
1214
 
 
1215
    ext++;
 
1216
    pathlen = name - arg;
 
1217
 
 
1218
    if (strcmp(ext, "la") == 0) {
 
1219
        assert(cmd_data->mode == mLink);
 
1220
 
 
1221
        cmd_data->basename = arg;
 
1222
        cmd_data->static_name.normal = gen_library_name(arg, 0);
 
1223
        cmd_data->shared_name.normal = gen_library_name(arg, 1);
 
1224
        cmd_data->module_name.normal = gen_library_name(arg, 2);
 
1225
        cmd_data->static_name.install = gen_install_name(arg, 0);
 
1226
        cmd_data->shared_name.install = gen_install_name(arg, 1);
 
1227
        cmd_data->module_name.install = gen_install_name(arg, 2);
 
1228
 
 
1229
#ifdef TRUNCATE_DLL_NAME
 
1230
        if (shared) {
 
1231
          arg = truncate_dll_name(arg);
 
1232
        }
 
1233
#endif
 
1234
 
 
1235
        cmd_data->output_name = arg;
 
1236
        return 1;
 
1237
    }
 
1238
 
 
1239
    if (strcmp(ext, "lo") == 0) {
 
1240
        cmd_data->basename = arg;
 
1241
        cmd_data->output = otObject;
 
1242
        newarg = (char *)malloc(strlen(arg) + 2);
 
1243
        strcpy(newarg, arg);
 
1244
        ext = strrchr(newarg, '.') + 1;
 
1245
        strcpy(ext, OBJECT_EXT);
 
1246
        cmd_data->output_name = newarg;
 
1247
        return 1;
 
1248
    }
 
1249
 
 
1250
    return 0;
 
1251
}
 
1252
 
 
1253
/* returns just a file's name without path or extension */
 
1254
char *nameof(char *fullpath)
 
1255
{
 
1256
    char buffer[1024];
 
1257
    char *ext;
 
1258
    char *name = strrchr(fullpath, '/');
 
1259
 
 
1260
    if (name == NULL) {
 
1261
        name = strrchr(fullpath, '\\');
 
1262
    }
 
1263
 
 
1264
    if (name == NULL) {
 
1265
        name = fullpath;
 
1266
    } else {
 
1267
        name++;
 
1268
    }
 
1269
 
 
1270
    strcpy(buffer, name);
 
1271
    ext = strrchr(buffer, '.');
 
1272
 
 
1273
    if (ext) {
 
1274
        *ext = 0;
 
1275
        return strdup(buffer);
 
1276
    }
 
1277
 
 
1278
    return name;
 
1279
}
 
1280
 
 
1281
void parse_args(int argc, char *argv[], command_t *cmd_data)
 
1282
{
 
1283
    int a;
 
1284
    char *arg;
 
1285
    int argused;
 
1286
 
 
1287
    for (a = 1; a < argc; a++) {
 
1288
        arg = argv[a];
 
1289
        argused = 1;
 
1290
 
 
1291
        if (arg[0] == '-') {
 
1292
            if (arg[1] == '-') {
 
1293
                argused = parse_long_opt(arg + 2, cmd_data);
 
1294
            }
 
1295
            else {
 
1296
                argused = parse_short_opt(arg + 1, cmd_data);
 
1297
            }
 
1298
 
 
1299
            /* We haven't done anything with it yet, try some of the
 
1300
             * more complicated short opts... */
 
1301
            if (argused == 0 && a + 1 < argc) {
 
1302
                if (arg[1] == 'o' && !arg[2]) {
 
1303
                    arg = argv[++a];
 
1304
                    argused = parse_output_file_name(arg, cmd_data);
 
1305
                } else if (strcmp(arg+1, "MT") == 0) {
 
1306
                    if (!cmd_data->options.silent) {
 
1307
                        printf("Adding: %s", arg);
 
1308
                    }
 
1309
                    push_count_chars(cmd_data->arglist, arg);
 
1310
                    arg = argv[++a];
 
1311
                    if (!cmd_data->options.silent) {
 
1312
                        printf(" %s\n", arg);
 
1313
                    }
 
1314
                    push_count_chars(cmd_data->arglist, arg);
 
1315
                    argused = 1;
 
1316
                } else if (strcmp(arg+1, "rpath") == 0) {
 
1317
                    /* Aha, we should try to link both! */
 
1318
                    cmd_data->install_path = argv[++a];
 
1319
                    argused = 1;
 
1320
                } else if (strcmp(arg+1, "version-info") == 0) {
 
1321
                    /* Store for later deciphering */
 
1322
                    cmd_data->version_info = argv[++a];
 
1323
                    argused = 1;
 
1324
                } else if (strcmp(arg+1, "export-symbols-regex") == 0) {
 
1325
                    /* Skip the argument. */
 
1326
                    ++a;
 
1327
                    argused = 1;
 
1328
                } else if (arg[1] == 'R' && !arg[2]) {
 
1329
                    /* -R dir Add dir to runtime library search path. */
 
1330
                    add_runtimedirlib(argv[++a], cmd_data);
 
1331
                    argused = 1;
 
1332
                }
 
1333
            }
 
1334
        } else {
 
1335
            argused = parse_input_file_name(arg, cmd_data);
 
1336
        }
 
1337
 
 
1338
        if (!argused) {
 
1339
            if (!cmd_data->options.silent) {
 
1340
                printf("Adding: %s\n", arg);
 
1341
            }
 
1342
            push_count_chars(cmd_data->arglist, arg);
 
1343
        }
 
1344
    }
 
1345
 
 
1346
}
 
1347
 
 
1348
int explode_static_lib(const char *lib, command_t *cmd_data)
 
1349
{
 
1350
    char tmpdir[1024];
 
1351
    char savewd[1024];
 
1352
    char cmd[1024];
 
1353
    const char *name;
 
1354
    DIR *dir;
 
1355
    struct dirent *entry;
 
1356
 
 
1357
    /* Bah! */
 
1358
    if (cmd_data->options.dry_run) {
 
1359
        return 0;
 
1360
    }
 
1361
 
 
1362
    strcpy(tmpdir, lib);
 
1363
    strcat(tmpdir, ".exploded");
 
1364
 
 
1365
    mkdir(tmpdir, 0);
 
1366
    push_count_chars(cmd_data->tmp_dirs, strdup(tmpdir));
 
1367
    getcwd(savewd, sizeof(savewd));
 
1368
 
 
1369
    if (chdir(tmpdir) != 0)
 
1370
        return 1;
 
1371
 
 
1372
    strcpy(cmd, LIBRARIAN " x ");
 
1373
    name = strrchr(lib, '/');
 
1374
 
 
1375
    if (name) {
 
1376
        name++;
 
1377
    } else {
 
1378
        name = lib;
 
1379
    }
 
1380
 
 
1381
    strcat(cmd, "../");
 
1382
    strcat(cmd, name);
 
1383
    system(cmd);
 
1384
    chdir(savewd);
 
1385
    dir = opendir(tmpdir);
 
1386
 
 
1387
    while ((entry = readdir(dir)) != NULL) {
 
1388
        if (entry->d_name[0] != '.') {
 
1389
            strcpy(cmd, tmpdir);
 
1390
            strcat(cmd, "/");
 
1391
            strcat(cmd, entry->d_name);
 
1392
            push_count_chars(cmd_data->arglist, strdup(cmd));
 
1393
        }
 
1394
    }
 
1395
 
 
1396
    closedir(dir);
 
1397
    return 0;
 
1398
}
 
1399
 
 
1400
#ifdef GEN_EXPORTS
 
1401
void generate_def_file(command_t *cmd_data)
 
1402
{
 
1403
    char def_file[1024];
 
1404
    char implib_file[1024];
 
1405
    char *ext;
 
1406
    FILE *hDef;
 
1407
    char *export_args[1024];
 
1408
    int num_export_args = 0;
 
1409
    char *cmd;
 
1410
    int cmd_size = 0;
 
1411
    int a;
 
1412
 
 
1413
    if (cmd_data->output_name) {
 
1414
        strcpy(def_file, cmd_data->output_name);
 
1415
        strcat(def_file, ".def");
 
1416
        hDef = fopen(def_file, "w");
 
1417
 
 
1418
        if (hDef != NULL) {
 
1419
            fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name));
 
1420
            fprintf(hDef, "DATA NONSHARED\n");
 
1421
            fprintf(hDef, "EXPORTS\n");
 
1422
            fclose(hDef);
 
1423
 
 
1424
            for (a = 0; a < cmd_data->num_obj_files; a++) {
 
1425
                cmd_size += strlen(cmd_data->obj_files[a]) + 1;
 
1426
            }
 
1427
 
 
1428
            cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3;
 
1429
            cmd = (char *)malloc(cmd_size);
 
1430
            strcpy(cmd, GEN_EXPORTS);
 
1431
 
 
1432
            for (a=0; a < cmd_data->num_obj_files; a++) {
 
1433
                strcat(cmd, " ");
 
1434
                strcat(cmd, cmd_data->obj_files[a] );
 
1435
            }
 
1436
 
 
1437
            strcat(cmd, ">>");
 
1438
            strcat(cmd, def_file);
 
1439
            puts(cmd);
 
1440
            export_args[num_export_args++] = SHELL_CMD;
 
1441
            export_args[num_export_args++] = "-c";
 
1442
            export_args[num_export_args++] = cmd;
 
1443
            export_args[num_export_args++] = NULL;
 
1444
            external_spawn(cmd_data, export_args[0], (const char**)export_args);
 
1445
            cmd_data->arglist[cmd_data->num_args++] = strdup(def_file);
 
1446
 
 
1447
            /* Now make an import library for the dll */
 
1448
            num_export_args = 0;
 
1449
            export_args[num_export_args++] = DEF2IMPLIB_CMD;
 
1450
            export_args[num_export_args++] = "-o";
 
1451
 
 
1452
            strcpy(implib_file, ".libs/");
 
1453
            strcat(implib_file, cmd_data->basename);
 
1454
            ext = strrchr(implib_file, '.');
 
1455
 
 
1456
            if (ext)
 
1457
                *ext = 0;
 
1458
 
 
1459
            strcat(implib_file, ".");
 
1460
            strcat(implib_file, STATIC_LIB_EXT);
 
1461
 
 
1462
            export_args[num_export_args++] = implib_file;
 
1463
            export_args[num_export_args++] = def_file;
 
1464
            export_args[num_export_args++] = NULL;
 
1465
            external_spawn(cmd_data, export_args[0], (const char**)export_args);
 
1466
 
 
1467
        }
 
1468
    }
 
1469
}
 
1470
#endif
 
1471
 
 
1472
const char* expand_path(const char *relpath)
 
1473
{
 
1474
    char foo[PATH_MAX], *newpath;
 
1475
 
 
1476
    getcwd(foo, PATH_MAX-1);
 
1477
    newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2);
 
1478
    strcat(newpath, foo);
 
1479
    strcat(newpath, "/");
 
1480
    strcat(newpath, relpath);
 
1481
    return newpath;
 
1482
}
 
1483
 
 
1484
void link_fixup(command_t *c)
 
1485
{
 
1486
    /* If we were passed an -rpath directive, we need to build
 
1487
     * shared objects too.  Otherwise, we should only create static
 
1488
     * libraries.
 
1489
     */
 
1490
    if (!c->install_path && (c->output == otDynamicLibraryOnly ||
 
1491
        c->output == otModule || c->output == otLibrary)) {
 
1492
        c->output = otStaticLibraryOnly;
 
1493
    }
 
1494
 
 
1495
    if (c->output == otDynamicLibraryOnly ||
 
1496
        c->output == otModule ||
 
1497
        c->output == otLibrary) {
 
1498
 
 
1499
        push_count_chars(c->shared_opts.normal, "-o");
 
1500
        if (c->output == otModule) {
 
1501
            push_count_chars(c->shared_opts.normal, c->module_name.normal);
 
1502
        }
 
1503
        else {
 
1504
            char *tmp;
 
1505
            push_count_chars(c->shared_opts.normal, c->shared_name.normal);
 
1506
#ifdef DYNAMIC_INSTALL_NAME
 
1507
            push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME);
 
1508
 
 
1509
            tmp = (char*)malloc(PATH_MAX);
 
1510
            strcat(tmp, c->install_path);
 
1511
            strcat(tmp, strrchr(c->shared_name.normal, '/'));
 
1512
            push_count_chars(c->shared_opts.normal, tmp);
 
1513
#endif
 
1514
        }
 
1515
 
 
1516
        append_count_chars(c->shared_opts.normal, c->obj_files);
 
1517
        append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies);
 
1518
 
 
1519
        if (c->options.export_all) {
 
1520
#ifdef GEN_EXPORTS
 
1521
            generate_def_file(c);
 
1522
#endif
 
1523
        }
 
1524
    }
 
1525
 
 
1526
    if (c->output == otLibrary || c->output == otStaticLibraryOnly) {
 
1527
        push_count_chars(c->static_opts.normal, "-o");
 
1528
        push_count_chars(c->static_opts.normal, c->output_name);
 
1529
    }
 
1530
 
 
1531
    if (c->output == otProgram) {
 
1532
        if (c->output_name) {
 
1533
            push_count_chars(c->arglist, "-o");
 
1534
            push_count_chars(c->arglist, c->output_name);
 
1535
            append_count_chars(c->arglist, c->obj_files);
 
1536
            append_count_chars(c->arglist, c->shared_opts.dependencies);
 
1537
#ifdef DYNAMIC_LINK_OPTS
 
1538
            if (c->options.pic_mode != pic_AVOID) {
 
1539
                push_count_chars(c->arglist, DYNAMIC_LINK_OPTS);
 
1540
            }
 
1541
#endif
 
1542
        }
 
1543
    }
 
1544
}
 
1545
 
 
1546
void post_parse_fixup(command_t *cmd_data)
 
1547
{
 
1548
    switch (cmd_data->mode)
 
1549
    {
 
1550
    case mCompile:
 
1551
#ifdef PIC_FLAG
 
1552
        if (cmd_data->options.pic_mode != pic_AVOID) {
 
1553
            push_count_chars(cmd_data->arglist, PIC_FLAG);
 
1554
        }
 
1555
#endif
 
1556
        if (cmd_data->output_name) {
 
1557
            push_count_chars(cmd_data->arglist, "-o");
 
1558
            push_count_chars(cmd_data->arglist, cmd_data->output_name);
 
1559
        }
 
1560
        break;
 
1561
    case mLink:
 
1562
        link_fixup(cmd_data);
 
1563
        break;
 
1564
    case mInstall:
 
1565
        if (cmd_data->output == otLibrary) {
 
1566
            link_fixup(cmd_data);
 
1567
        }
 
1568
    default:
 
1569
        break;
 
1570
    }
 
1571
 
 
1572
#if USE_OMF
 
1573
    if (cmd_data->output == otObject ||
 
1574
        cmd_data->output == otProgram ||
 
1575
        cmd_data->output == otLibrary ||
 
1576
        cmd_data->output == otDynamicLibraryOnly) {
 
1577
        push_count_chars(cmd_data->arglist, "-Zomf");
 
1578
    }
 
1579
#endif
 
1580
 
 
1581
    if (cmd_data->options.shared &&
 
1582
            (cmd_data->output == otObject ||
 
1583
             cmd_data->output == otLibrary ||
 
1584
             cmd_data->output == otDynamicLibraryOnly)) {
 
1585
#ifdef SHARE_SW
 
1586
        push_count_chars(cmd_data->arglist, SHARE_SW);
 
1587
#endif
 
1588
    }
 
1589
}
 
1590
 
 
1591
int run_mode(command_t *cmd_data)
 
1592
{
 
1593
    int rv;
 
1594
    count_chars *cctemp;
 
1595
 
 
1596
    cctemp = (count_chars*)malloc(sizeof(count_chars));
 
1597
    init_count_chars(cctemp);
 
1598
 
 
1599
    switch (cmd_data->mode)
 
1600
    {
 
1601
    case mCompile:
 
1602
        rv = run_command(cmd_data, cmd_data->arglist);
 
1603
        if (rv) {
 
1604
            return rv;
 
1605
        }
 
1606
        break;
 
1607
    case mInstall:
 
1608
        /* Well, we'll assume it's a file going to a directory... */
 
1609
        /* For brain-dead install-sh based scripts, we have to repeat
 
1610
         * the command N-times.  install-sh should die.
 
1611
         */
 
1612
        if (!cmd_data->output_name) {
 
1613
            rv = run_command(cmd_data, cmd_data->arglist);
 
1614
            if (rv) {
 
1615
                return rv;
 
1616
            }
 
1617
        }
 
1618
        if (cmd_data->output_name) {
 
1619
            append_count_chars(cctemp, cmd_data->arglist);
 
1620
            insert_count_chars(cctemp,
 
1621
                               cmd_data->output_name,
 
1622
                               cctemp->num - 1);
 
1623
            rv = run_command(cmd_data, cctemp);
 
1624
            if (rv) {
 
1625
                return rv;
 
1626
            }
 
1627
            clear_count_chars(cctemp);
 
1628
        }
 
1629
        if (cmd_data->static_name.install) {
 
1630
            append_count_chars(cctemp, cmd_data->arglist);
 
1631
            insert_count_chars(cctemp,
 
1632
                               cmd_data->static_name.install,
 
1633
                               cctemp->num - 1);
 
1634
            rv = run_command(cmd_data, cctemp);
 
1635
            if (rv) {
 
1636
                return rv;
 
1637
            }
 
1638
            clear_count_chars(cctemp);
 
1639
        }
 
1640
        if (cmd_data->shared_name.install) {
 
1641
            append_count_chars(cctemp, cmd_data->arglist);
 
1642
            insert_count_chars(cctemp,
 
1643
                               cmd_data->shared_name.install,
 
1644
                               cctemp->num - 1);
 
1645
            rv = run_command(cmd_data, cctemp);
 
1646
            if (rv) {
 
1647
                return rv;
 
1648
            }
 
1649
            clear_count_chars(cctemp);
 
1650
        }
 
1651
        if (cmd_data->module_name.install) {
 
1652
            append_count_chars(cctemp, cmd_data->arglist);
 
1653
            insert_count_chars(cctemp,
 
1654
                               cmd_data->module_name.install,
 
1655
                               cctemp->num - 1);
 
1656
            rv = run_command(cmd_data, cctemp);
 
1657
            if (rv) {
 
1658
                return rv;
 
1659
            }
 
1660
            clear_count_chars(cctemp);
 
1661
        }
 
1662
        break;
 
1663
    case mLink:
 
1664
        if (!cmd_data->options.dry_run) {
 
1665
            /* Check first to see if the dir already exists! */
 
1666
            mode_t old_umask;
 
1667
 
 
1668
            old_umask = umask(0);
 
1669
            umask(old_umask);
 
1670
 
 
1671
            mkdir(".libs", ~old_umask);
 
1672
        }
 
1673
 
 
1674
        if (cmd_data->output == otStaticLibraryOnly ||
 
1675
            cmd_data->output == otLibrary) {
 
1676
#ifdef RANLIB
 
1677
            const char *lib_args[3];
 
1678
#endif
 
1679
            /* Removes compiler! */
 
1680
            cmd_data->program = LIBRARIAN;
 
1681
            push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS);
 
1682
            push_count_chars(cmd_data->program_opts,
 
1683
                             cmd_data->static_name.normal);
 
1684
 
 
1685
            rv = run_command(cmd_data, cmd_data->obj_files);
 
1686
            if (rv) {
 
1687
                return rv;
 
1688
            }
 
1689
 
 
1690
#ifdef RANLIB
 
1691
            lib_args[0] = RANLIB;
 
1692
            lib_args[1] = cmd_data->static_name.normal;
 
1693
            lib_args[2] = NULL;
 
1694
            external_spawn(cmd_data, RANLIB, lib_args);
 
1695
#endif
 
1696
        }
 
1697
 
 
1698
        if (cmd_data->output == otDynamicLibraryOnly ||
 
1699
            cmd_data->output == otModule ||
 
1700
            cmd_data->output == otLibrary) {
 
1701
            cmd_data->program = NULL;
 
1702
            clear_count_chars(cmd_data->program_opts);
 
1703
 
 
1704
            append_count_chars(cmd_data->program_opts, cmd_data->arglist);
 
1705
            if (cmd_data->output != otModule) {
 
1706
#ifdef SHARED_OPTS
 
1707
                push_count_chars(cmd_data->program_opts, SHARED_OPTS);
 
1708
#endif
 
1709
#ifdef dynamic_link_version_func
 
1710
                push_count_chars(cmd_data->program_opts,
 
1711
                             dynamic_link_version_func(cmd_data->version_info));
 
1712
#endif
 
1713
            }
 
1714
            if (cmd_data->output == otModule) {
 
1715
#ifdef MODULE_OPTS
 
1716
                push_count_chars(cmd_data->program_opts, MODULE_OPTS);
 
1717
#endif
 
1718
            }
 
1719
#ifdef DYNAMIC_LINK_OPTS
 
1720
            if (cmd_data->options.pic_mode != pic_AVOID) {
 
1721
                push_count_chars(cmd_data->program_opts,
 
1722
                                 DYNAMIC_LINK_OPTS);
 
1723
            }
 
1724
#endif
 
1725
            rv = run_command(cmd_data, cmd_data->shared_opts.normal);
 
1726
            if (rv) {
 
1727
                return rv;
 
1728
            }
 
1729
        }
 
1730
        if (cmd_data->output == otProgram) {
 
1731
            rv = run_command(cmd_data, cmd_data->arglist);
 
1732
            if (rv) {
 
1733
                return rv;
 
1734
            }
 
1735
        }
 
1736
        break;
 
1737
    default:
 
1738
        break;
 
1739
    } 
 
1740
 
 
1741
    return 0;
 
1742
}
 
1743
 
 
1744
void cleanup_tmp_dir(const char *dirname)
 
1745
{
 
1746
    DIR *dir;
 
1747
    struct dirent *entry;
 
1748
    char fullname[1024];
 
1749
 
 
1750
    dir = opendir(dirname);
 
1751
 
 
1752
    if (dir == NULL)
 
1753
        return;
 
1754
 
 
1755
    while ((entry = readdir(dir)) != NULL) {
 
1756
        if (entry->d_name[0] != '.') {
 
1757
            strcpy(fullname, dirname);
 
1758
            strcat(fullname, "/");
 
1759
            strcat(fullname, entry->d_name);
 
1760
            remove(fullname);
 
1761
        }
 
1762
    }
 
1763
 
 
1764
    rmdir(dirname);
 
1765
}
 
1766
 
 
1767
void cleanup_tmp_dirs(command_t *cmd_data)
 
1768
{
 
1769
    int d;
 
1770
 
 
1771
    for (d = 0; d < cmd_data->tmp_dirs->num; d++) {
 
1772
        cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]);
 
1773
    }
 
1774
}
 
1775
 
 
1776
int ensure_fake_uptodate(command_t *cmd_data)
 
1777
{
 
1778
    /* FIXME: could do the stat/touch here, but nah... */
 
1779
    const char *touch_args[3];
 
1780
 
 
1781
    if (cmd_data->mode == mInstall) {
 
1782
        return 0;
 
1783
    }
 
1784
 
 
1785
    touch_args[0] = "touch";
 
1786
    touch_args[1] = cmd_data->fake_output_name;
 
1787
    touch_args[2] = NULL;
 
1788
    return external_spawn(cmd_data, "touch", touch_args);
 
1789
}
 
1790
 
 
1791
/* Store the install path in the *.la file */
 
1792
int add_for_runtime(command_t *cmd_data)
 
1793
{
 
1794
    if (cmd_data->mode == mInstall) {
 
1795
        return 0;
 
1796
    }
 
1797
    if (cmd_data->output == otDynamicLibraryOnly ||
 
1798
        cmd_data->output == otLibrary) {
 
1799
        FILE *f=fopen(cmd_data->fake_output_name,"w");
 
1800
        if (f == NULL) {
 
1801
            return -1;
 
1802
        }
 
1803
        fprintf(f,"%s\n", cmd_data->install_path);
 
1804
        fclose(f);
 
1805
        return(0);
 
1806
    } else {
 
1807
        return(ensure_fake_uptodate(cmd_data));
 
1808
    }
 
1809
}
 
1810
 
 
1811
int main(int argc, char *argv[])
 
1812
{
 
1813
    int rc;
 
1814
    command_t cmd_data;
 
1815
 
 
1816
    memset(&cmd_data, 0, sizeof(cmd_data));
 
1817
 
 
1818
    cmd_data.options.pic_mode = pic_UNKNOWN;
 
1819
 
 
1820
    cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars));
 
1821
    init_count_chars(cmd_data.program_opts);
 
1822
    cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars));
 
1823
    init_count_chars(cmd_data.arglist);
 
1824
    cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars));
 
1825
    init_count_chars(cmd_data.tmp_dirs);
 
1826
    cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars));
 
1827
    init_count_chars(cmd_data.obj_files);
 
1828
    cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars));
 
1829
    init_count_chars(cmd_data.dep_rpaths);
 
1830
    cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars));
 
1831
    init_count_chars(cmd_data.rpaths);
 
1832
    cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars));
 
1833
    init_count_chars(cmd_data.static_opts.normal);
 
1834
    cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars));
 
1835
    init_count_chars(cmd_data.shared_opts.normal);
 
1836
    cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars));
 
1837
    init_count_chars(cmd_data.shared_opts.dependencies);
 
1838
 
 
1839
    cmd_data.mode = mUnknown;
 
1840
    cmd_data.output = otGeneral;
 
1841
 
 
1842
    parse_args(argc, argv, &cmd_data);
 
1843
    post_parse_fixup(&cmd_data);
 
1844
 
 
1845
    if (cmd_data.mode == mUnknown) {
 
1846
        exit(0);
 
1847
    }
 
1848
 
 
1849
    rc = run_mode(&cmd_data);
 
1850
 
 
1851
    if (!rc) {
 
1852
       add_for_runtime(&cmd_data); 
 
1853
    }
 
1854
 
 
1855
    cleanup_tmp_dirs(&cmd_data);
 
1856
    return rc;
 
1857
}