~ubuntu-branches/ubuntu/oneiric/enigmail/oneiric-updates

« back to all changes in this revision

Viewing changes to config/gtscc.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2010-04-10 01:42:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100410014224-fbq9ui5x3b0h2t36
Tags: 2:1.0.1-0ubuntu1
* First releaase of enigmail 1.0.1 for tbird/icedove 3
  (LP: #527138)
* redo packaging from scratch 
  + add debian/make-orig target that uses xulrunner provided
    buildsystem + enigmail tarball to produce a proper orig.tar.gz
  + use debhelper 7 with mozilla-devscripts
  + use debian source format 3.0 (quilt)
  + patch enigmail to use frozen API only
    - add debian/patches/frozen_api.diff
  + patch build system to not link against -lxul - which isnt
    available for sdks produced by all-static apps like tbird
    - add debian/patches/build_system_dont_link_libxul.diff
  + add minimal build-depends to control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Mozilla Public License Version
 
6
 * 1.1 (the "License"); you may not use this file except in compliance with
 
7
 * the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/MPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1998
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 
26
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
/* */
 
38
/*
 
39
 *--------------------------------------------------------------------------
 
40
 *
 
41
 *    
 
42
 *
 
43
 *--------------------------------------------------------------------------
 
44
 *
 
45
 *    gtscc - Global To Static C/C++ compiler driver.
 
46
 *
 
47
 *    Syntax:
 
48
 *
 
49
 *    gtscc [options] -c file.cpp ...
 
50
 *    gtscc [options] file.o ... libxx.a ...
 
51
 *
 
52
 *    gtscc is a compiler and linker driver/wrapper for Irix only.
 
53
 *    gtscc takes all compiler options and passes them onto the Irix
 
54
 *    cc/CC compiler/linker.
 
55
 *    Typically, gtscc is used in two phases. Phase one is during compilation.
 
56
 *    gtscc, the compiler, converts all inline globals to statics, and records
 
57
 *    the existence of other globals and how to compile the file in the gtscc
 
58
 *    database file.
 
59
 *    During linking, globals dependencies are analyzed, and a list of
 
60
 *    "convertable" globals is determined. Globals that are not referenced
 
61
 *    globally, but are referenced locally are considered convertable.
 
62
 *    The linker then recompiles the files that those symbols are in, and
 
63
 *    converts them to statics. It also calls the archiver to install
 
64
 *    the converted objects into libraries.
 
65
 *    Finally the linker is called.
 
66
 *
 
67
 *    Created: David Williams, djw@netscape.com, 13-Feb-1997
 
68
 *
 
69
 *--------------------------------------------------------------------------
 
70
 */
 
71
#include <stdio.h>
 
72
#include <stdlib.h>
 
73
#include <string.h>
 
74
#include <sys/types.h>
 
75
#include <sys/wait.h>
 
76
#include <sys/param.h>
 
77
#include <sys/types.h>
 
78
#include <unistd.h>
 
79
#include <ctype.h>
 
80
 
 
81
#if defined(LINUX) && defined(__GLIBC__)
 
82
#include <libelf/libelf.h>
 
83
#else
 
84
#include <libelf.h>
 
85
#endif
 
86
 
 
87
#include <sys/stat.h>
 
88
#include <fcntl.h>
 
89
#include <sys/time.h>
 
90
 
 
91
#define DEFAULT_MAX_GLOBALS 15500
 
92
 
 
93
#define ELFSYM_IS_DEFINED(x)   ((x).st_shndx != SHN_UNDEF)
 
94
#define ELFSYM_IS_UNDEFINED(x) ((x).st_shndx == SHN_UNDEF)
 
95
 
 
96
#ifdef IRIX
 
97
#define CC_COMMAND  "cc"
 
98
#define CCC_COMMAND "CC"
 
99
#define AS_COMMAND  "cc"
 
100
#define LD_COMMAND  "CC"
 
101
#define AR_COMMAND  "ar"
 
102
#define AR_OPTIONS  "cr"
 
103
#else
 
104
#define HANDLES_DASHSO
 
105
#define CC_COMMAND  "gcc"
 
106
#define CCC_COMMAND "g++"
 
107
#define AS_COMMAND  "gcc"
 
108
#define LD_COMMAND  "g++"
 
109
#define AR_COMMAND  "ar"
 
110
#define AR_OPTIONS  "cr"
 
111
#endif
 
112
 
 
113
#define EH_NEW(type) (type*)malloc(sizeof(type))
 
114
 
 
115
#define TRUE 1
 
116
#define FALSE 0
 
117
 
 
118
#define EH_TAG_FILE   'F'
 
119
#define EH_TAG_GLOBAL 'G'
 
120
#define EH_TAG_ZAPPED 'Z'
 
121
#define EH_TAG_INLINE 'I'
 
122
#define EH_TAG_UNDEFINED 'U'
 
123
 
 
124
#define VERBOSITY_USER(x)  ((x) > 0)
 
125
#define VERBOSITY_DEBUG(x) ((x) > 1)
 
126
#define VERBOSITY_MAJOR(x) ((x) > 2)
 
127
 
 
128
static char eh_unnamed_object[] = "<name not known>";
 
129
 
 
130
typedef struct {
 
131
        char*    name;       /* archive */
 
132
} EhArchive;
 
133
 
 
134
typedef struct {
 
135
        char*      name;     /* name of C/C++ file, relative to rootdir */
 
136
        char*      directory;/* must compile in this directory */
 
137
        char**     cc_args;  /* cc -I ..... */
 
138
        char*      as_savefile;
 
139
        time_t     compile_time;
 
140
        char*      target_object;
 
141
} EhSource;
 
142
 
 
143
typedef struct EhObject {
 
144
        struct EhObject* _recompile; /* used for recompilation link list */
 
145
        unsigned   _needs_unzap;
 
146
        char*      name;     /* name of .o */
 
147
        EhArchive* archive;  /* it is stored in */
 
148
        EhSource*  source;
 
149
        char*      pathname;
 
150
        unsigned   nusers;
 
151
} EhObject;
 
152
 
 
153
typedef enum {
 
154
        EH_SYM_UNDEFINED,
 
155
        EH_SYM_DEFINED,
 
156
        EH_SYM_ZAPPED,
 
157
        EH_SYM_INLINE /* are treated special - they belong to no file */
 
158
} EhSymState;
 
159
 
 
160
typedef struct EhSym {
 
161
        struct EhSym* _next; /* used for link list */
 
162
        char*      name;     /* name of symbol */
 
163
        EhObject*  object;   /* if symbol is undefined == NULL */
 
164
        unsigned   ngusers;   /* number of global users */
 
165
        unsigned   nlusers;   /* number of local file users */
 
166
 
 
167
#if 0
 
168
        unsigned   section;  /* section in elf file */
 
169
        unsigned   index;    /* index into symbol table */
 
170
        unsigned char info;
 
171
        unsigned   dirty;
 
172
#endif
 
173
        EhSymState state;
 
174
} EhSym;
 
175
 
 
176
#define EHSYM_ISDEFINED(x)   ((x)->object!=NULL && (x)->state==EH_SYM_DEFINED)
 
177
#define EHSYM_ISZAPPED(x)    ((x)->object!=NULL && (x)->state==EH_SYM_ZAPPED)
 
178
#define EHSYM_ISUNDEFINED(x) ((x)->object == NULL)
 
179
#define EHSYM_ISUSED(x)      ((x)->nusers != 0)
 
180
#define EHSYM_ISINLINE(x)    ((x)->state == EH_SYM_INLINE)
 
181
 
 
182
#define EH_OBJECT_CANBUILD(x) \
 
183
((x)->source != NULL && (x)->name != eh_unnamed_object)
 
184
 
 
185
#define USE_HASHING
 
186
 
 
187
typedef struct {
 
188
#ifdef USE_HASHING
 
189
        EhSym** heads;
 
190
        unsigned size;
 
191
#else
 
192
        EhSym* head;
 
193
#endif
 
194
        unsigned nentries;
 
195
} EhSymTable;
 
196
 
 
197
static char*
 
198
make_relative_pathname(char* buf, char* filename, char* rootdir)
 
199
{
 
200
        char  buf1[MAXPATHLEN];
 
201
        char  buf2[MAXPATHLEN];
 
202
        char* p;
 
203
        char* q;
 
204
 
 
205
        if (rootdir == NULL) {
 
206
                strcpy(buf, filename);
 
207
                return filename;
 
208
        }
 
209
 
 
210
        if (filename[0] != '/') {
 
211
                if (getcwd(buf2, sizeof(buf2)) == NULL) {
 
212
                        fprintf(stderr, "cannot get pwd\n");
 
213
                        return NULL;
 
214
                }
 
215
 
 
216
                strcat(buf2, "/");
 
217
                strcat(buf2, filename);
 
218
 
 
219
                filename = buf2;
 
220
        }
 
221
 
 
222
        if (realpath(filename, buf1) == NULL) {
 
223
                fprintf(stderr, "realpath(%s,..) failed\n", filename);
 
224
                return NULL;
 
225
        }
 
226
        
 
227
        if (realpath(rootdir, buf2) == NULL) {
 
228
                fprintf(stderr, "realpath(%s,..) failed\n", rootdir);
 
229
                return NULL;
 
230
        }
 
231
 
 
232
        strcat(buf2, "/");
 
233
 
 
234
        for (p = buf1, q = buf2; *p == *q; p++, q++)
 
235
                ;
 
236
 
 
237
        strcpy(buf, p);
 
238
 
 
239
        return buf;
 
240
}
 
241
 
 
242
static EhArchive*
 
243
EhArchiveNew(char* name, char* rootdir)
 
244
{
 
245
        EhArchive* archive = EH_NEW(EhArchive);
 
246
        char pathbuf[MAXPATHLEN];
 
247
 
 
248
        make_relative_pathname(pathbuf, name, rootdir);
 
249
 
 
250
        archive->name = strdup(pathbuf);
 
251
 
 
252
        return archive;
 
253
}
 
254
 
 
255
#if 0
 
256
/*
 
257
 *    This is evil, we should never free anything, because it messes up
 
258
 *    interning.
 
259
 */
 
260
static void
 
261
EhSourceDelete(EhSource* source)
 
262
{
 
263
        unsigned n;
 
264
        if (source->name != NULL)
 
265
                free(source->name);
 
266
        if (source->directory != NULL)
 
267
                free(source->directory);
 
268
        if (source->cc_args != NULL) {
 
269
                for (n = 0; source->cc_args[n] != NULL; n++)
 
270
                        free(source->cc_args[n]);
 
271
                free(source->cc_args);
 
272
        }
 
273
        if (source->as_savefile != NULL)
 
274
                free(source->as_savefile);
 
275
}
 
276
#endif
 
277
 
 
278
static EhSource*
 
279
EhSourceNew(char* name, char** cc_args, char* directory)
 
280
{
 
281
        EhSource* source = EH_NEW(EhSource);
 
282
        unsigned n;
 
283
        unsigned m;
 
284
 
 
285
        source->name = strdup(name);
 
286
        source->directory = (directory != NULL)? strdup(directory): NULL;
 
287
        source->as_savefile = NULL;
 
288
        source->compile_time = 0;
 
289
        source->target_object = NULL;
 
290
        source->cc_args = NULL;
 
291
 
 
292
        if (cc_args != NULL) {
 
293
 
 
294
                for (n = 0; cc_args[n] != NULL; n++)
 
295
                        ;
 
296
 
 
297
                source->cc_args = (char**)malloc(sizeof(char*) * (n+1));
 
298
 
 
299
                for (m = 0, n = 0; cc_args[n] != NULL;) {
 
300
                        if (strcmp(cc_args[n], "-o") == 0 && cc_args[n+1] != NULL) {
 
301
                                source->target_object = strdup(cc_args[n+1]);
 
302
                                n += 2;
 
303
                        } else {
 
304
                                source->cc_args[m++] =  strdup(cc_args[n++]);
 
305
                        }
 
306
                }
 
307
 
 
308
                source->cc_args[m] = NULL;
 
309
        }
 
310
 
 
311
        return source;
 
312
}
 
313
 
 
314
static EhObject*
 
315
EhObjectNewArchiveObject(EhArchive* archive, char* name)
 
316
{
 
317
        EhObject* object = EH_NEW(EhObject);
 
318
 
 
319
        if (name == eh_unnamed_object)
 
320
                object->name = name;
 
321
        else
 
322
                object->name = strdup(name);
 
323
        object->archive = archive;
 
324
        object->source = NULL;
 
325
        object->_recompile = NULL;
 
326
        object->_needs_unzap = 0;
 
327
        object->pathname = NULL;
 
328
        object->nusers = 0;
 
329
 
 
330
        return object;
 
331
}
 
332
 
 
333
static EhObject*
 
334
EhObjectNew(char* name, char* rootdir)
 
335
{
 
336
        EhObject* object = EhObjectNewArchiveObject(NULL, name);
 
337
        char pathname[MAXPATHLEN];
 
338
 
 
339
        make_relative_pathname(pathname, name, rootdir);
 
340
        object->pathname = strdup(pathname);
 
341
 
 
342
        return object;
 
343
}
 
344
 
 
345
static EhObject*
 
346
EhObjectNewFromSource(EhSource* source)
 
347
{
 
348
        EhObject* object = EhObjectNewArchiveObject(NULL, eh_unnamed_object);
 
349
 
 
350
        object->source = source;
 
351
 
 
352
        return object;
 
353
}
 
354
 
 
355
static char*
 
356
EhObjectGetFilename(EhObject* object, char* buf)
 
357
{
 
358
        if (object->archive) {
 
359
                strcpy(buf, object->archive->name);
 
360
                strcat(buf, ":");
 
361
                strcat(buf, object->name);
 
362
                return buf;
 
363
        } else {
 
364
                return object->name;
 
365
        }
 
366
}
 
367
 
 
368
static EhSym*
 
369
EhSymNewDefined(char* name, EhObject* object)
 
370
{
 
371
        EhSym* sym = EH_NEW(EhSym);
 
372
 
 
373
        sym->name = strdup(name);
 
374
        sym->object = object;
 
375
        sym->state = EH_SYM_DEFINED;
 
376
        sym->ngusers = 0;
 
377
        sym->nlusers = 0;
 
378
 
 
379
        return sym;
 
380
}
 
381
 
 
382
static EhSym*
 
383
EhSymNewInline(char* name)
 
384
{
 
385
        EhSym* sym = EhSymNewDefined(name, NULL);
 
386
        sym->state = EH_SYM_INLINE;
 
387
 
 
388
        return sym;
 
389
}
 
390
 
 
391
static EhSym*
 
392
EhSymNewUndefined(char* name)
 
393
{
 
394
        EhSym* sym = EhSymNewDefined(name, NULL);
 
395
        sym->state = EH_SYM_UNDEFINED;
 
396
 
 
397
        return sym;
 
398
}
 
399
 
 
400
static EhSym*
 
401
EhSymNewZapped(char* name, EhObject* object)
 
402
{
 
403
        EhSym* sym = EhSymNewDefined(name, object);
 
404
        sym->state = EH_SYM_ZAPPED;
 
405
 
 
406
        return sym;
 
407
}
 
408
 
 
409
static EhSym*
 
410
EhSymNewRandomZap(char* name)
 
411
{
 
412
        EhSym* sym = EhSymNewZapped(name, NULL);
 
413
 
 
414
        return sym;
 
415
}
 
416
 
 
417
EhSymTable*
 
418
EhSymTableNew(unsigned p_size)
 
419
{
 
420
        EhSymTable* table = EH_NEW(EhSymTable);
 
421
 
 
422
#ifdef USE_HASHING
 
423
        unsigned size;
 
424
        for (size = 0x1; size < (16*1024); size <<= 1) {
 
425
                if (size >= p_size)
 
426
                        break;
 
427
        }
 
428
        table->size = size;
 
429
        table->heads = (EhSym**)calloc(size, sizeof(EhSym*));
 
430
#else
 
431
        table->head = NULL;
 
432
#endif
 
433
        table->nentries = 0;
 
434
 
 
435
        return table;
 
436
}
 
437
 
 
438
EhSym*
 
439
EhSymTableInsert(EhSymTable* table, EhSym* sym)
 
440
{
 
441
#ifdef USE_HASHING
 
442
        unsigned long hash = elf_hash(sym->name);
 
443
        unsigned long mask = table->size - 1;
 
444
        unsigned index = (hash & mask);
 
445
 
 
446
        sym->_next = table->heads[index];
 
447
        table->heads[index] = sym;
 
448
#else
 
449
        sym->_next = table->head;
 
450
        table->head = sym;
 
451
#endif
 
452
        table->nentries++;
 
453
 
 
454
        return sym;
 
455
}
 
456
 
 
457
EhSym*
 
458
EhSymTableFind(EhSymTable* table, char* name)
 
459
{
 
460
        EhSym* sym;
 
461
        EhSym* head;
 
462
 
 
463
#ifdef USE_HASHING
 
464
        unsigned long hash = elf_hash(name);
 
465
        unsigned long mask = table->size - 1;
 
466
        unsigned index = (hash & mask);
 
467
        head = table->heads[index];
 
468
#else
 
469
        head = table->head;
 
470
#endif
 
471
 
 
472
        for (sym = head; sym != NULL; sym = sym->_next) {
 
473
                if (strcmp(name, sym->name) == 0)
 
474
                        break;
 
475
        }
 
476
 
 
477
        return sym;
 
478
}
 
479
 
 
480
typedef int (*eh_dump_mappee_t)(EhSym* sym, void* arg);
 
481
 
 
482
static int
 
483
EhSymTableMap(EhSymTable* table, eh_dump_mappee_t func, void* arg)
 
484
{
 
485
        EhSym* sym;
 
486
        EhSym* head;
 
487
 
 
488
#ifdef USE_HASHING
 
489
        unsigned n;
 
490
        for (n = 0; n < table->size; n++) {
 
491
                head = table->heads[n];
 
492
#else
 
493
                head = table->head; {
 
494
#endif
 
495
                for (sym = head; sym != NULL; sym = sym->_next) {
 
496
                        if ((func)(sym, arg) == -1)
 
497
                                return -1;
 
498
                }
 
499
        }
 
500
 
 
501
        return 0;
 
502
}
 
503
 
 
504
typedef struct {
 
505
        EhObject* o_old;
 
506
        EhObject* o_new;
 
507
} fixup_info;
 
508
 
 
509
static int
 
510
fixup_mappee(EhSym* sym, void* arg)
 
511
{
 
512
        fixup_info* info = (fixup_info*)arg;
 
513
 
 
514
        if (sym->object == info->o_old)
 
515
                sym->object = info->o_new;
 
516
 
 
517
        return 0;
 
518
}
 
519
 
 
520
static EhObject*
 
521
EhSymTableObjectFixup(EhSymTable* table, EhObject* o_old, EhObject* o_new)
 
522
{
 
523
        fixup_info info;
 
524
 
 
525
        /*
 
526
         *    Now visit every sym that pointed to tmp, and point it
 
527
         *    at object.
 
528
         */
 
529
        info.o_old = o_old;
 
530
        info.o_new = o_new;
 
531
        EhSymTableMap(table, fixup_mappee, &info);
 
532
        
 
533
        return o_new;
 
534
}
 
535
 
 
536
 
 
537
 
 
538
static char*
 
539
safe_fgets(char* buf, unsigned size, FILE* fp)
 
540
{
 
541
        unsigned nread = 0;
 
542
 
 
543
        if (buf == NULL)
 
544
                buf = (char*)malloc(size);
 
545
 
 
546
        for (;;) {
 
547
 
 
548
                if (fgets(&buf[nread], size - nread, fp) == NULL) {
 
549
                        free(buf);
 
550
                        return NULL;
 
551
                }
 
552
 
 
553
                if (strchr(buf, '\n') != NULL)
 
554
                        return buf;
 
555
 
 
556
                /*
 
557
                 *    fgets returns n-1 characters and \0
 
558
                 */
 
559
                nread += (size - nread) - 1;
 
560
                size += 1024;
 
561
                buf = (char*)realloc(buf, size);
 
562
        }
 
563
}
 
564
 
 
565
static int
 
566
EhSymTableSetSymbolState(EhSymTable* table, char* name, EhSymState new_state)
 
567
{
 
568
        EhSym* sym = EhSymTableFind(table, name);
 
569
 
 
570
        if (sym == NULL) {
 
571
                sym = EhSymNewDefined(name, NULL);
 
572
 
 
573
                EhSymTableInsert(table, sym);
 
574
        }
 
575
 
 
576
        /* new_state must be EH_SYM_DEFINED || EH_SYM_ZAPPED */
 
577
        if (sym->state == EH_SYM_DEFINED || sym->state == EH_SYM_ZAPPED) {
 
578
                sym->state = new_state;
 
579
        } else if (sym->state == EH_SYM_INLINE) {
 
580
                char* state_name;
 
581
                if (new_state == EH_SYM_DEFINED)
 
582
                        state_name = "global";
 
583
                else
 
584
                        state_name = "static";
 
585
                fprintf(stderr,
 
586
                                "WARNING: Symbol %s is an inline.\n"
 
587
                                "         Forcing the symbol %s will be ignored.\n",
 
588
                                name,
 
589
                                state_name);
 
590
        } else { /* EH_SYM_UNDEFINED */
 
591
                /*
 
592
                 *    This call is being made after objects have started being
 
593
                 *    read. This is too late. I'm not sure I care though.
 
594
                 */
 
595
                return -1;
 
596
        }
 
597
 
 
598
        return 0;
 
599
}
 
600
 
 
601
static int
 
602
EhSymTableFpLoad(EhSymTable* table, FILE* fp)
 
603
{
 
604
        char* buf = NULL; /* I hope this is big enough */
 
605
        char* p;
 
606
        char* name;
 
607
        char* state;
 
608
        EhSym* sym;
 
609
        EhSource* source = NULL;
 
610
        EhObject* object = NULL;
 
611
        char* cc_args[512];
 
612
        unsigned n;
 
613
        unsigned line_n = 0;
 
614
        char* ctime = NULL;
 
615
        char* directory;
 
616
        char* savefile;
 
617
 
 
618
        while ((buf = safe_fgets(buf, 1024, fp)) != NULL) {
 
619
 
 
620
                if ((p = strchr(buf, '\n')) == NULL) {
 
621
                        fprintf(stderr, "line to long: %d\n", line_n);
 
622
                        return -1;
 
623
                }
 
624
                *p = '\0';
 
625
 
 
626
                line_n++;
 
627
 
 
628
                if (buf[0] == '!') /* comment */
 
629
                        continue;
 
630
 
 
631
                for (p = buf; isspace(*p); p++)
 
632
                        ;
 
633
 
 
634
                name = p;
 
635
                for (; !isspace(*p); p++)
 
636
                        ;
 
637
                *p++ = '\0';
 
638
 
 
639
                if (name[0] == '\0')
 
640
                        continue;
 
641
                
 
642
                for (; isspace(*p); p++)
 
643
                        ;
 
644
 
 
645
                state = p;
 
646
                for (; !isspace(*p) && *p != '\0'; p++)
 
647
                        ;
 
648
                *p++ = '\0';
 
649
 
 
650
                if (state[0] == EH_TAG_GLOBAL
 
651
                        ||
 
652
                        state[0] == EH_TAG_ZAPPED
 
653
                        ||
 
654
                        state[0] == EH_TAG_INLINE) {
 
655
                        sym = EhSymTableFind(table, name);
 
656
                        if (sym == NULL) { /* install a new one */
 
657
                                
 
658
                                if (source == NULL && state[0] != EH_TAG_INLINE) {
 
659
                                        fprintf(stderr,
 
660
                                                        "[%d] found new style symbol (%s) but no source\n",
 
661
                                                        line_n, name);
 
662
                                }
 
663
 
 
664
                                if (state[0] == EH_TAG_GLOBAL)
 
665
                                        sym = EhSymNewDefined(name, object);
 
666
                                else if (state[0] == EH_TAG_INLINE)
 
667
                                        sym = EhSymNewInline(name);
 
668
                                else
 
669
                                        sym = EhSymNewZapped(name, object);
 
670
                                
 
671
                                EhSymTableInsert(table, sym);
 
672
                        } else {
 
673
                                if (state[0] == EH_TAG_GLOBAL) {
 
674
                                        if (sym->state != EH_SYM_DEFINED) {
 
675
                                                fprintf(stderr,
 
676
                                                                "out of sync defined symbol: %s, fixing\n",
 
677
                                                                sym->name);
 
678
                                                sym->state = EH_SYM_DEFINED;
 
679
                                        }
 
680
                                } else if (state[0] == EH_TAG_INLINE) {
 
681
                                        if (sym->state != EH_SYM_INLINE) {
 
682
                                                fprintf(stderr,
 
683
                                                                "out of sync inlined symbol: %s, fixing\n",
 
684
                                                                sym->name);
 
685
                                                sym->state = EH_SYM_INLINE;
 
686
                                        }
 
687
                                } else {
 
688
                                        if (sym->state != EH_SYM_ZAPPED) {
 
689
                                                fprintf(stderr,
 
690
                                                                "out of sync zapped symbol: %s, fixing\n",
 
691
                                                                sym->name);
 
692
                                                sym->state = EH_SYM_ZAPPED;
 
693
                                        }
 
694
                                }
 
695
 
 
696
#if 0
 
697
                                /* these are probably "special" symbols like .div */
 
698
                                if (sym->object != object) {
 
699
                                        fprintf(stderr,
 
700
                                                        "out of sync object for symbol: %s, ignoring\n",
 
701
                                                        sym->name);
 
702
                                }
 
703
#endif
 
704
                        }
 
705
 
 
706
                        continue; /* no more fields we care about */
 
707
                } else if (state[0] == EH_TAG_FILE) {
 
708
 
 
709
                        directory = p;
 
710
                        for (; !isspace(*p) && *p != '\0'; p++)
 
711
                                ;
 
712
                        *p++ = '\0';
 
713
 
 
714
                        savefile = p;
 
715
                        for (; !isspace(*p) && *p != '\0'; p++)
 
716
                                ;
 
717
                        *p++ = '\0';
 
718
 
 
719
                        ctime = p;
 
720
                        for (; !isspace(*p) && *p != '\0'; p++)
 
721
                                ;
 
722
                        *p++ = '\0';
 
723
 
 
724
                        for (n = 0; *p != '\0';) {
 
725
 
 
726
                                for (; isspace(*p); p++)
 
727
                                        ;
 
728
                        
 
729
                                cc_args[n++] = p++;
 
730
                                
 
731
                                for (; !isspace(*p) && *p != '\0'; p++)
 
732
                                        ;
 
733
                                
 
734
                                if (*p == '\0')
 
735
                                        break;
 
736
 
 
737
                                *p++ = '\0';
 
738
                        }
 
739
                        cc_args[n] = NULL;
 
740
 
 
741
                        if (strcmp(directory, ".") == 0)
 
742
                                directory = NULL;
 
743
                        source = EhSourceNew(name, cc_args, directory);
 
744
                        if (ctime != NULL)
 
745
                                source->compile_time = (time_t)atoi(ctime);
 
746
                        object = EhObjectNewFromSource(source);
 
747
 
 
748
                } else { /* old style symbol list */
 
749
                        sym = EhSymTableFind(table, name);
 
750
                        if (sym != NULL) {
 
751
                                if (sym->state != EH_SYM_ZAPPED) {
 
752
                                        fprintf(stderr,
 
753
                                                        "out of sync random zapped symbol: %s, fixing\n",
 
754
                                                        sym->name);
 
755
                                        sym->state = EH_SYM_ZAPPED;
 
756
                                }
 
757
                        } else {
 
758
                                sym = EhSymNewRandomZap(name);
 
759
                        }
 
760
                }
 
761
        }
 
762
 
 
763
        return line_n;
 
764
}
 
765
 
 
766
typedef struct {
 
767
        EhSym**  vector;
 
768
        unsigned index;
 
769
} flush_info;
 
770
 
 
771
static int
 
772
flush_mappee(EhSym* sym, void* arg)
 
773
{
 
774
        flush_info* info = (flush_info*)arg;
 
775
 
 
776
        if (sym->state == EH_SYM_INLINE
 
777
                ||
 
778
                (sym->object != NULL && sym->state == EH_SYM_DEFINED)
 
779
                ||
 
780
                (sym->object != NULL && sym->state == EH_SYM_ZAPPED)) {
 
781
                if (info->vector != NULL)
 
782
                        info->vector[info->index] = sym;
 
783
                info->index++;
 
784
        }
 
785
 
 
786
        return 0;
 
787
}
 
788
 
 
789
static  int
 
790
flush_compare(const void* ap, const void* bp)
 
791
{
 
792
        EhSym** ax = (EhSym**)ap;
 
793
        EhSym** bx = (EhSym**)bp;
 
794
        EhSym* a = *ax;
 
795
        EhSym* b = *bx;
 
796
        EhObject* oa = a->object;
 
797
        EhObject* ob = b->object;
 
798
        int foo;
 
799
 
 
800
        if (oa == NULL && ob != NULL)
 
801
                return -1;
 
802
        if (oa != NULL && ob == NULL)
 
803
                return 1;
 
804
        if (oa == NULL && ob == NULL) {
 
805
                foo = strcmp(a->name, b->name);
 
806
                if (foo < 0)
 
807
                        return -1;
 
808
                else if (foo > 0)
 
809
                        return 1;
 
810
                return 0;
 
811
        }
 
812
 
 
813
        if (oa->source == NULL && ob->source != NULL)
 
814
                return -1;
 
815
        if (oa->source != NULL && ob->source == NULL)
 
816
                return 1;
 
817
        if (oa->source == ob->source)
 
818
                return 0;
 
819
        if (oa->source < ob->source)
 
820
                return -1;
 
821
        if (oa->source > ob->source)
 
822
                return 1;
 
823
        foo = strcmp(a->name, b->name);
 
824
        if (foo < 0)
 
825
                return -1;
 
826
        else if (foo > 0)
 
827
                return 1;
 
828
        return 0;
 
829
}
 
830
 
 
831
static void
 
832
EhSourceFpWrite(EhSource* source, FILE* fp)
 
833
{
 
834
        unsigned n = 0;
 
835
 
 
836
        fputs(source->name, fp);
 
837
        fputc(' ', fp);
 
838
        fputc(EH_TAG_FILE, fp);
 
839
 
 
840
        fputc(' ', fp);
 
841
        if (source->directory != NULL)
 
842
                fprintf(fp, "%s", source->directory);
 
843
        else
 
844
                fputc('.', fp);
 
845
        
 
846
        fputc(' ', fp);
 
847
        if (source->as_savefile != NULL)
 
848
                fprintf(fp, "%s", source->as_savefile);
 
849
        else
 
850
                fputc('.', fp);
 
851
        
 
852
        fputc(' ', fp);
 
853
        fprintf(fp, "%d", source->compile_time);
 
854
 
 
855
        if (source->target_object != NULL) {
 
856
                fputs(" -o ", fp);
 
857
                fputs(source->target_object, fp);
 
858
        }
 
859
        
 
860
        if (source->cc_args != NULL) {
 
861
                for (n = 0; source->cc_args[n] != NULL; n++) {
 
862
                        fputc(' ', fp);
 
863
                        fputs(source->cc_args[n], fp);
 
864
                }
 
865
        }
 
866
 
 
867
        if (n < 1)
 
868
                fprintf(stderr, "WARNING: %s has no args\n", source->name);
 
869
 
 
870
        fputc('\n', fp);
 
871
}
 
872
 
 
873
static int
 
874
EhSymTableFpDump(EhSymTable* table, FILE* fp)
 
875
{
 
876
        flush_info info;
 
877
        unsigned n;
 
878
        EhObject* object = NULL;
 
879
        EhSym**   syms;
 
880
        EhSym*    sym;
 
881
        unsigned size;
 
882
 
 
883
        info.index = 0;
 
884
        info.vector = NULL;
 
885
        EhSymTableMap(table, flush_mappee, (void*)&info);
 
886
        size = info.index;
 
887
 
 
888
        syms = (EhSym**)malloc(sizeof(EhSym*) * size);
 
889
        info.index = 0;
 
890
        info.vector = syms;
 
891
        EhSymTableMap(table, flush_mappee, (void*)&info);
 
892
 
 
893
        /* sort */
 
894
        qsort(syms, size, sizeof(EhSym*), flush_compare);
 
895
 
 
896
        /* dump */
 
897
        for (n = 0; n < size; n++) {
 
898
                sym = syms[n];
 
899
 
 
900
                if (sym->object != object) {
 
901
                        object = sym->object;
 
902
 
 
903
                        if (object->source != NULL) {
 
904
                                EhSourceFpWrite(object->source, fp);
 
905
                        }
 
906
                }
 
907
 
 
908
                if (sym->state == EH_SYM_INLINE) {
 
909
                        fprintf(fp, "%s %c\n", sym->name, EH_TAG_INLINE);
 
910
                } else if (object->source != NULL && sym->state == EH_SYM_ZAPPED) {
 
911
                        fprintf(fp, "%s %c\n", sym->name, EH_TAG_ZAPPED);
 
912
                } else if (object->source != NULL && sym->state == EH_SYM_DEFINED) {
 
913
                        fprintf(fp, "%s %c\n", sym->name, EH_TAG_GLOBAL);
 
914
                }
 
915
        }
 
916
 
 
917
        free(syms);
 
918
 
 
919
        return n;
 
920
}
 
921
 
 
922
int djw_debug;
 
923
char* djw_test_name;
 
924
 
 
925
int
 
926
eh_process_object(Elf* elf, EhObject* object, EhSymTable* table)
 
927
{
 
928
        Elf32_Shdr *   shdr;
 
929
        Elf32_Ehdr *   ehdr;
 
930
        Elf_Scn * scn;
 
931
        Elf_Data *     shstr_data;
 
932
        Elf_Data*      sym_data = NULL;
 
933
        Elf_Data*      str_data = NULL;
 
934
        Elf_Data*      rel_data[4];
 
935
        int            nrel_data = 0;
 
936
        Elf32_Rel*     rel_entries;
 
937
        Elf_Data*      rela_data[10];
 
938
        int            nrela_data = 0;
 
939
        Elf32_Rela*    rela_entries;
 
940
        unsigned int   cnt;
 
941
        Elf32_Sym* elf_sym;
 
942
        int i;
 
943
        int j;
 
944
        int k;
 
945
        char*  name;
 
946
        EhSym* sym;
 
947
        char buf[MAXPATHLEN];
 
948
 
 
949
        /* Obtain the .shstrtab data buffer */
 
950
        if (((ehdr = elf32_getehdr(elf)) == NULL) ||
 
951
                ((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) ||
 
952
                ((shstr_data = elf_getdata(scn, NULL)) == NULL)) {
 
953
                fprintf(stderr, "problems on %s\n", EhObjectGetFilename(object, buf));
 
954
                return -1;
 
955
        }
 
956
 
 
957
        /* get the string table */
 
958
        for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) {
 
959
                if ((shdr = elf32_getshdr(scn)) == NULL) {
 
960
                        fprintf(stderr, "problems on %s, section %d\n",
 
961
                                        EhObjectGetFilename(object, buf), cnt);
 
962
                        return -1;
 
963
                }
 
964
 
 
965
#if 0
 
966
                fprintf(stderr, "%s: section %d type %d name %s\n",
 
967
                                EhObjectGetFilename(object, buf),
 
968
                                cnt,
 
969
                                shdr->sh_type,
 
970
                                (char*)shstr_data->d_buf + shdr->sh_name);
 
971
#endif
 
972
 
 
973
                /*
 
974
                 *    Get the string table.
 
975
                 */
 
976
                if (shdr->sh_type == SHT_STRTAB &&
 
977
#ifdef sun
 
978
                        strcmp((char*)shstr_data->d_buf + shdr->sh_name, ".strtab") == 0 &&
 
979
#endif
 
980
                        cnt != ehdr->e_shstrndx) {
 
981
                        if (str_data != NULL) {
 
982
                                fprintf(stderr, "multiple string tables for %s - bailing\n",
 
983
                                                EhObjectGetFilename(object, buf));
 
984
                                return -1;
 
985
                        }
 
986
                        str_data = elf_getdata(scn, NULL);
 
987
                } else if (shdr->sh_type == SHT_SYMTAB) { /* look into sym table */
 
988
                        if (sym_data != NULL) {
 
989
                                fprintf(stderr, "multiple symbol tables for %s - bailing\n",
 
990
                                                EhObjectGetFilename(object, buf));
 
991
                                return -1;
 
992
                        }
 
993
                        sym_data = elf_getdata(scn, NULL);
 
994
                } else if (shdr->sh_type == SHT_REL) { /* look into rel table */
 
995
                        if (nrel_data >= 4) {
 
996
                                fprintf(stderr, "too many relocation tables for %s bailing\n",
 
997
                                                EhObjectGetFilename(object, buf));
 
998
                                return -1;
 
999
                        }
 
1000
                        rel_data[nrel_data++] = elf_getdata(scn, NULL);
 
1001
                } else if (shdr->sh_type == SHT_RELA) { /* look into rela table */
 
1002
                        if (nrela_data >= 10) {
 
1003
                                fprintf(stderr, "too many RELA tables for %s bailing\n",
 
1004
                                                EhObjectGetFilename(object, buf));
 
1005
                                return -1;
 
1006
                        }
 
1007
                        rela_data[nrela_data++] = elf_getdata(scn, NULL);
 
1008
                }
 
1009
        }
 
1010
 
 
1011
        if (sym_data == NULL) {
 
1012
                fprintf(stderr, "could not load sym table for %s\n",
 
1013
                                EhObjectGetFilename(object, buf));
 
1014
                return -1;
 
1015
        }
 
1016
 
 
1017
        if (str_data == NULL) {
 
1018
                fprintf(stderr, "could not load string table for %s\n",
 
1019
                                EhObjectGetFilename(object, buf));
 
1020
                return -1;
 
1021
        }
 
1022
 
 
1023
        elf_sym = (Elf32_Sym*)sym_data->d_buf;
 
1024
 
 
1025
        for (i = 0; i < (sym_data->d_size/sizeof(Elf32_Sym)); i++) {
 
1026
 
 
1027
                /*
 
1028
                 *    We are only interested in globals.
 
1029
                 */
 
1030
                if (ELF32_ST_BIND(elf_sym[i].st_info) != STB_GLOBAL)
 
1031
                        continue;
 
1032
                
 
1033
                name = (char *)str_data->d_buf + elf_sym[i].st_name;
 
1034
                
 
1035
                if (djw_test_name != NULL
 
1036
                        && strcmp(djw_test_name, name) == 0) {
 
1037
                        printf("found %s\n", name);
 
1038
                }
 
1039
                
 
1040
                sym = EhSymTableFind(table, name);
 
1041
                
 
1042
                /*
 
1043
                 *    Treat inlines as non-globals
 
1044
                 */
 
1045
                if (sym != NULL && sym->state == EH_SYM_INLINE)
 
1046
                        continue;
 
1047
                
 
1048
#if 0
 
1049
                printf("name = %s value = %d type = %d, info = %d,"
 
1050
                           " other = %d, size = %d\n",
 
1051
                           name,
 
1052
                           elf_sym[i].st_value,
 
1053
                           ELF32_ST_TYPE(elf_sym[i].st_info),
 
1054
                           elf_sym[i].st_info,
 
1055
                           elf_sym[i].st_other,
 
1056
                           elf_sym[i].st_size);
 
1057
#endif
 
1058
                
 
1059
                /* defined */
 
1060
                if (ELFSYM_IS_DEFINED(elf_sym[i])) {
 
1061
                        
 
1062
                        if (sym != NULL) {
 
1063
                                
 
1064
                                if (sym->object == NULL) { /* object undefined */
 
1065
                                        sym->object = object;
 
1066
                                } else if (sym->object->name==eh_unnamed_object) {
 
1067
                                        
 
1068
                                        if (object->source != NULL
 
1069
                                                &&
 
1070
                                                object->source != sym->object->source) {
 
1071
                                                
 
1072
                                                fprintf(stderr,
 
1073
                                                                "warning: symbol %s defined in more than one source file\n"
 
1074
                                                                "last time: %s\n"
 
1075
                                                                "this time: %s (ignored)\n",
 
1076
                                                                sym->name,
 
1077
                                                                object->source->name,
 
1078
                                                                sym->object->source->name);
 
1079
                                        } else {
 
1080
                                                object->source = sym->object->source;
 
1081
                                                /*
 
1082
                                                 *    Do a global: sym->object = object;
 
1083
                                                 */
 
1084
                                                EhSymTableObjectFixup(table,
 
1085
                                                                                          sym->object, /*old*/
 
1086
                                                                                          object); /*new*/
 
1087
                                                
 
1088
                                        }
 
1089
                                        
 
1090
                                } else if (sym->object != object) {
 
1091
                                        fprintf(stderr,
 
1092
                                                        "warning: symbol %s define in multiple object files\n"
 
1093
                                                        "last time: %s\n"
 
1094
                                                        "this time: %s (ignored)\n",
 
1095
                                                        sym->name,
 
1096
                                                        object->name,
 
1097
                                                        sym->object->name);
 
1098
                                }
 
1099
                                
 
1100
                                sym->state = EH_SYM_DEFINED;
 
1101
 
 
1102
                        } else {
 
1103
                                sym = EhSymNewDefined(name, object);
 
1104
                                EhSymTableInsert(table, sym);
 
1105
                        }                               
 
1106
 
 
1107
                for (k = 0; k < nrel_data; k++) {
 
1108
                                int nentries = rel_data[k]->d_size/sizeof(Elf32_Rel);
 
1109
 
 
1110
                                rel_entries = (Elf32_Rel*)rel_data[k]->d_buf;
 
1111
                                
 
1112
                                for (j = 0; j < nentries; j++) {
 
1113
                                        if (ELF32_R_SYM(rel_entries[j].r_info) == i) {
 
1114
                                                /* locally referenced */
 
1115
                                                sym->nlusers++;
 
1116
                                        }
 
1117
                                }
 
1118
                        }
 
1119
                for (k = 0; k < nrela_data; k++) {
 
1120
                                int nentries = rela_data[k]->d_size/sizeof(Elf32_Rela);
 
1121
 
 
1122
                                rela_entries = (Elf32_Rela*)rela_data[k]->d_buf;
 
1123
                                
 
1124
                                for (j = 0; j < nentries; j++) {
 
1125
                                        if (ELF32_R_SYM(rela_entries[j].r_info) == i) {
 
1126
                                                /* locally referenced */
 
1127
                                                sym->nlusers++;
 
1128
                                        }
 
1129
                                }
 
1130
                        }
 
1131
                }  
 
1132
                
 
1133
                /* Undefined. */
 
1134
                else if (ELFSYM_IS_UNDEFINED(elf_sym[i])) {
 
1135
                        
 
1136
                        if (sym == NULL) {
 
1137
                                sym = EhSymNewUndefined(name);
 
1138
                                EhSymTableInsert(table, sym);
 
1139
                        }
 
1140
                        sym->ngusers++;
 
1141
                } else {
 
1142
                        
 
1143
#if 1
 
1144
                        printf("what is this: "
 
1145
                                   "name = %s value = %d type = %d, "
 
1146
                                   "info = %d, other = %d, size = %d\n",
 
1147
                                   name,
 
1148
                                   elf_sym[i].st_value,
 
1149
                                   ELF32_ST_TYPE(elf_sym[i].st_info),
 
1150
                                   elf_sym[i].st_info,
 
1151
                                   elf_sym[i].st_other,
 
1152
                                   elf_sym[i].st_size);
 
1153
#endif
 
1154
                        ;
 
1155
                }/* type ==... */
 
1156
        } /* for each symbol */
 
1157
 
 
1158
        return 0;
 
1159
}
 
1160
 
 
1161
int
 
1162
eh_process_file(char* filename, EhSymTable* table, char* rootdir)
 
1163
{
 
1164
        Elf* elf;
 
1165
        Elf* arf;
 
1166
        int  fd;
 
1167
        Elf_Cmd cmd;
 
1168
        Elf_Kind e_kind;
 
1169
        EhObject* object;
 
1170
        EhArchive* archive;
 
1171
        Elf_Arhdr* arhdr;
 
1172
        char* name;
 
1173
        int   rv = 0;
 
1174
 
 
1175
        if ((fd = open(filename, O_RDONLY)) == -1) {
 
1176
                fprintf(stderr, "error opening %s\n", filename);
 
1177
                return -1;
 
1178
        }
 
1179
 
 
1180
        elf_version(EV_CURRENT);
 
1181
        if ((arf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
 
1182
                return -1;
 
1183
        }
 
1184
 
 
1185
        e_kind = elf_kind(arf);
 
1186
        if (e_kind == ELF_K_ELF) {
 
1187
                object = EhObjectNew(filename, rootdir);
 
1188
                rv = eh_process_object(arf, object, table);
 
1189
                
 
1190
        } else if (e_kind == ELF_K_AR) {
 
1191
 
 
1192
                archive = EhArchiveNew(filename, rootdir);
 
1193
                cmd = ELF_C_READ;
 
1194
 
 
1195
#if 0
 
1196
                arsyms = elf_getarsym(arf, &narsyms);
 
1197
 
 
1198
                for (i = 0; i < narsyms && arsyms[i].as_name != NULL; i++) {
 
1199
                        printf("%s - %d\n", arsyms[i].as_name, arsyms[i].as_off);
 
1200
                }
 
1201
 
 
1202
                arhdr = elf_getarhdr(arf);
 
1203
                for (i = 0; arhdr[i].ar_rawname != NULL; i++) {
 
1204
 
 
1205
                        if (arhdr[i].ar_name != NULL)
 
1206
                                printf("%s\n", arhdr[i].ar_name);
 
1207
                        else
 
1208
                                printf("[%s]\n", arhdr[i].ar_rawname);
 
1209
                }
 
1210
#endif
 
1211
 
 
1212
                rv = 0;
 
1213
 
 
1214
                while ((elf = elf_begin(fd, cmd, arf)) != 0) {
 
1215
 
 
1216
                        e_kind = elf_kind(elf);
 
1217
 
 
1218
                        if (e_kind != ELF_K_ELF)
 
1219
                                continue;
 
1220
 
 
1221
                        arhdr = elf_getarhdr(elf);
 
1222
 
 
1223
                        if (arhdr != NULL) {
 
1224
                                if (arhdr->ar_name != NULL)
 
1225
                                        name = arhdr->ar_name;
 
1226
                                else
 
1227
                                        name = arhdr->ar_rawname;
 
1228
                        } else {
 
1229
                                name = eh_unnamed_object;
 
1230
                        }
 
1231
 
 
1232
                        object = EhObjectNewArchiveObject(archive, name);
 
1233
                        rv = eh_process_object(elf, object, table);
 
1234
 
 
1235
                        if (rv == -1)
 
1236
                                break;
 
1237
 
 
1238
                        cmd = elf_next(elf);
 
1239
                        elf_end(elf);
 
1240
                }
 
1241
        }
 
1242
 
 
1243
        elf_end(arf);
 
1244
 
 
1245
        close(fd);
 
1246
 
 
1247
        return rv;
 
1248
}
 
1249
 
 
1250
static int
 
1251
eh_dump_unused(EhSym* sym, void* arg)
 
1252
{
 
1253
        char buf[MAXPATHLEN];
 
1254
 
 
1255
        printf(/*"0x%x "*/ "%s %d %d ", /*sym,*/
 
1256
                   sym->name, sym->ngusers, sym->nlusers);
 
1257
 
 
1258
        if (EHSYM_ISINLINE(sym))
 
1259
                printf("%c ", EH_TAG_INLINE);
 
1260
        else if (EHSYM_ISZAPPED(sym))
 
1261
                printf("%c ", EH_TAG_ZAPPED);
 
1262
        else if (EHSYM_ISDEFINED(sym))
 
1263
                printf("%c ", EH_TAG_GLOBAL);
 
1264
        else
 
1265
                printf("%c ", EH_TAG_UNDEFINED);
 
1266
 
 
1267
        if (sym->object != NULL) {
 
1268
                printf("%s ", EhObjectGetFilename(sym->object, buf));
 
1269
                if (sym->object->source != NULL) {
 
1270
                        printf("%s recompilable\n", sym->object->source->name);
 
1271
                } else {
 
1272
                        printf("nosource notrecompilable\n");
 
1273
                }
 
1274
        } else {
 
1275
                printf("noobject nosource notrecompilable\n");
 
1276
        }
 
1277
        
 
1278
        return 0;
 
1279
}
 
1280
 
 
1281
static void
 
1282
print_dump(EhSymTable* table)
 
1283
{
 
1284
        printf("everything\n");
 
1285
        EhSymTableMap(table, eh_dump_unused, NULL);
 
1286
}
 
1287
 
 
1288
typedef struct {
 
1289
        unsigned ndefined;
 
1290
        unsigned nused; /* globally */
 
1291
        unsigned nundefined;
 
1292
        unsigned nzapped;
 
1293
        unsigned nzapped_nowused;
 
1294
        unsigned ninlined;
 
1295
        unsigned nunlinked;
 
1296
        unsigned ndeadcode;
 
1297
} SummaryInfo;
 
1298
 
 
1299
static int
 
1300
eh_summary_mappee(EhSym* sym, void* arg) {
 
1301
        SummaryInfo* info = (SummaryInfo*)arg;
 
1302
 
 
1303
        if (EHSYM_ISDEFINED(sym)) {
 
1304
                if (sym->ngusers != 0)
 
1305
                        info->nused++;
 
1306
                else if (sym->object != NULL && sym->object->nusers == 0)
 
1307
                        info->nunlinked++;
 
1308
                else if (sym->nlusers != 0)
 
1309
                        info->ndefined++;
 
1310
                else
 
1311
                        info->ndeadcode++;
 
1312
                        
 
1313
        } else if (EHSYM_ISZAPPED(sym)) { /* one of ours */
 
1314
                if (sym->ngusers != 0)
 
1315
                        info->nzapped_nowused++;
 
1316
                else
 
1317
                        info->nzapped++;
 
1318
        } else if (EHSYM_ISINLINE(sym)) { /* one of ours */
 
1319
                info->ninlined++;
 
1320
        } else {
 
1321
                info->nundefined++;
 
1322
        }
 
1323
 
 
1324
        return 0;
 
1325
}
 
1326
 
 
1327
static void
 
1328
get_summary(EhSymTable* table, SummaryInfo* info)
 
1329
{
 
1330
        info->ndefined = 0;
 
1331
        info->nused = 0;
 
1332
        info->nundefined = 0;
 
1333
        info->nzapped = 0;
 
1334
        info->nzapped_nowused = 0;
 
1335
        info->ninlined = 0;
 
1336
        info->nunlinked = 0;
 
1337
        info->ndeadcode = 0;
 
1338
        
 
1339
        EhSymTableMap(table, eh_summary_mappee, info);
 
1340
 
1341
 
 
1342
static void
 
1343
print_summary(EhSymTable* table)
 
1344
{
 
1345
        SummaryInfo info;
 
1346
 
 
1347
        get_summary(table, &info);
 
1348
        
 
1349
        printf("summary:\n"
 
1350
                   "defined and used:             %d\n"
 
1351
                   "defined but unused globally:  %d\n"
 
1352
                   "total globals in target:      %d\n"
 
1353
                   "--------------------------------\n"
 
1354
                   "global to statics *:          %d\n"
 
1355
                   "global to statics (now used): %d\n"
 
1356
                   "inlined to statics *:         %d\n"
 
1357
                   "defined in unlinked objects:  %d\n"
 
1358
                   "defined but unused (deadcode):%d\n"
 
1359
                   "undefined but used:           %d\n",
 
1360
                   info.nused,
 
1361
                   info.ndefined,
 
1362
                   (info.nused + info.ndefined),
 
1363
                   info.nzapped,
 
1364
                   info.nzapped_nowused,
 
1365
                   info.ninlined,
 
1366
                   info.nunlinked,                         
 
1367
                   info.ndeadcode,                         
 
1368
                   info.nundefined);
 
1369
}
 
1370
 
 
1371
typedef struct EhDirMapEntree {
 
1372
        char* dirname;
 
1373
        struct EhDirMapEntree* _next;
 
1374
} EhDirMapEntree;
 
1375
 
 
1376
typedef struct EhDirMap {
 
1377
        EhDirMapEntree* head;
 
1378
} EhDirMap;
 
1379
 
 
1380
static EhDirMap*
 
1381
EhDirMapNew(void)
 
1382
{
 
1383
        EhDirMap* dm = EH_NEW(EhDirMap);
 
1384
        dm->head = NULL;
 
1385
        return dm;
 
1386
}
 
1387
 
 
1388
static void
 
1389
EhDirMapAddDirectory(EhDirMap* map, char* dirname)
 
1390
{
 
1391
        EhDirMapEntree* entree = EH_NEW(EhDirMapEntree);
 
1392
        EhDirMapEntree* foo;
 
1393
 
 
1394
        entree->dirname = strdup(dirname);
 
1395
        entree->_next = NULL;
 
1396
 
 
1397
        if (map->head == NULL) {
 
1398
                map->head = entree;
 
1399
        } else {
 
1400
                for (foo = map->head; foo->_next != NULL; foo = foo->_next)
 
1401
                        ;
 
1402
 
 
1403
                foo->_next = entree;
 
1404
        }
 
1405
}
 
1406
 
 
1407
static char*
 
1408
EhDirMapGetLibName(EhDirMap* map, char* name, char* libbuf)
 
1409
{
 
1410
        EhDirMapEntree* foo;
 
1411
        struct stat     buf;
 
1412
 
 
1413
        for (foo = map->head; foo != NULL; foo = foo->_next) {
 
1414
                sprintf(libbuf, "%s/lib%s.a", foo->dirname, name);
 
1415
 
 
1416
                if (stat(libbuf, &buf) != -1)
 
1417
                        return libbuf;
 
1418
        }
 
1419
 
 
1420
        return NULL;
 
1421
}
 
1422
 
 
1423
static char*
 
1424
test_for_global(char* buf)
 
1425
{
 
1426
#ifdef IRIX
 
1427
        if (strncmp(buf, "\t.globl\t", 8) == 0)
 
1428
                return &buf[8];
 
1429
#else
 
1430
        if (strncmp(buf, "\t.global ", 9) == 0)
 
1431
                return &buf[9];
 
1432
#endif
 
1433
        return NULL;
 
1434
}
 
1435
 
 
1436
static char*
 
1437
test_for_file(char* foo, char* buf)
 
1438
{
 
1439
#ifdef IRIX
 
1440
        char* p;
 
1441
        char* q;
 
1442
        if (strncmp(buf, "\t.file\t", 6) == 0) {
 
1443
                for (p = &buf[6]; *p != '"' && *p != '\0'; p++)
 
1444
                        ;
 
1445
                if (*p == '\0')
 
1446
                        return NULL;
 
1447
                p++; /* quote */
 
1448
                q = strchr(p, '"');
 
1449
                if (q == NULL)
 
1450
                        return NULL;
 
1451
                memcpy(foo, p, q - p);
 
1452
                foo[q - p] = '\0';
 
1453
                return foo;
 
1454
        }
 
1455
#else
 
1456
        printf("test_for_file() not implemented\n");
 
1457
#endif
 
1458
        return NULL;
 
1459
}
 
1460
 
 
1461
static int
 
1462
EhSourceZapFp(EhSource* source, EhSymTable* table, FILE* fpi, FILE* fpo,
 
1463
                          unsigned verbosity, unsigned cplusplus)
 
1464
{
 
1465
        char*     buf = NULL;
 
1466
        char*     p;
 
1467
        int       nzap = 0;
 
1468
        char*     name;
 
1469
        EhSym*    sym;
 
1470
        int       i_zapped;
 
1471
        EhObject* object = EhObjectNewFromSource(source);
 
1472
        char*     filename = source->name;
 
1473
        char*     tmp_name;
 
1474
        char      foo[256];
 
1475
        unsigned  line_n = 0;
 
1476
 
 
1477
        if (VERBOSITY_DEBUG(verbosity))
 
1478
                fputs("gts: ", stderr);
 
1479
 
 
1480
        while ((buf = safe_fgets(buf, 4192, fpi)) != NULL) {
 
1481
 
 
1482
                i_zapped = 0;
 
1483
                for (p = buf; *p != '\0' && *p != '\n'; p++)
 
1484
                        ;
 
1485
                *p = '\0';
 
1486
 
 
1487
                if ((tmp_name = test_for_file(foo, buf)) != NULL) {
 
1488
                        if (strcmp(tmp_name, filename) != 0) /* not the same file */
 
1489
                                filename = "non local file";
 
1490
                        else
 
1491
                                filename = source->name;
 
1492
                }
 
1493
 
 
1494
                else if ((name = test_for_global(buf)) != NULL) {
 
1495
 
 
1496
                        sym = EhSymTableFind(table, name);
 
1497
 
 
1498
                        /* an inline, we have to treat specially */
 
1499
                        if ((filename != source->name && cplusplus != 0) /* inline now */
 
1500
                                ||
 
1501
                                (sym != NULL && sym->state == EH_SYM_INLINE)) {/* was inline */
 
1502
 
 
1503
                                if (!sym) { 
 
1504
 
 
1505
                                        sym = EhSymNewInline(name);
 
1506
                                        
 
1507
                                        EhSymTableInsert(table, sym);
 
1508
                                }
 
1509
                                sym->state = EH_SYM_INLINE; /* just make sure */
 
1510
 
 
1511
                                if (fpo != NULL) /* always zap inlines we see */
 
1512
                                        fputs(" # gts", fpo);
 
1513
 
 
1514
                        } else { /* a real global */
 
1515
 
 
1516
                                if (fpo != NULL && sym != NULL && EHSYM_ISZAPPED(sym)) {
 
1517
                                        if (VERBOSITY_DEBUG(verbosity)) {
 
1518
                                                fprintf(stderr, "%s ", &buf[8]);
 
1519
                                        }
 
1520
                                        nzap++;
 
1521
 
 
1522
                                        if (fpo != NULL)
 
1523
                                                fputs(" # gts", fpo);
 
1524
                                }
 
1525
 
 
1526
                                if (sym != NULL) {
 
1527
                                        if (sym->object == NULL) {
 
1528
                                                sym->object = object;
 
1529
                                        } else if (sym->object != object) {
 
1530
                                                sym->object->source = source;
 
1531
                                                EhSymTableObjectFixup(table, object, sym->object);
 
1532
                                                object = sym->object;
 
1533
                                        }
 
1534
                                } else { /* install a new one */
 
1535
                                        
 
1536
                                        sym = EhSymNewDefined(name, object);
 
1537
                                        
 
1538
                                        EhSymTableInsert(table, sym);
 
1539
                                }
 
1540
 
 
1541
                        }
 
1542
                }
 
1543
 
 
1544
                if (fpo != NULL) {
 
1545
                        fputs(buf, fpo);
 
1546
                        fputc('\n', fpo);
 
1547
                }
 
1548
                line_n++;
 
1549
        }
 
1550
        
 
1551
        if (VERBOSITY_DEBUG(verbosity))
 
1552
                fputc('\n', stderr);
 
1553
 
 
1554
        return nzap;
 
1555
}
 
1556
 
 
1557
static void
 
1558
print_command(char* command, char** args, unsigned verbosity)
 
1559
{
 
1560
        int i;
 
1561
        FILE* fp = stderr;
 
1562
        if (!VERBOSITY_USER(verbosity))
 
1563
                return;
 
1564
 
 
1565
        fprintf(fp, "%s: ", command);
 
1566
        for (i = 0; args[i]; i++) {
 
1567
                fprintf(fp, "%s ", args[i]);
 
1568
        }
 
1569
        fprintf(fp, "\n");
 
1570
}
 
1571
 
 
1572
static int
 
1573
do_command(char* label, char** args, unsigned verbosity)
 
1574
{
 
1575
        int status;
 
1576
        pid_t child_pid;
 
1577
        char* file = args[0];
 
1578
 
 
1579
        print_command(label, args, verbosity);
 
1580
 
 
1581
        if ((child_pid = fork()) == -1) {
 
1582
                fprintf(stderr, "could not fork: ");
 
1583
                perror(NULL);
 
1584
                return -1;
 
1585
        }
 
1586
 
 
1587
        if (child_pid == 0) { /* i am the child */
 
1588
                if (execvp(file, args) == -1) {
 
1589
                        fprintf(stderr, "could not exec %s: ", file);
 
1590
                        perror(NULL);
 
1591
                        exit(3);
 
1592
                }
 
1593
                /*NOTREACHED*/
 
1594
        }
 
1595
 
 
1596
        if (waitpid(child_pid, &status, 0) == -1) {
 
1597
                fprintf(stderr, "wait on %s failed: ", file);
 
1598
                perror(NULL);
 
1599
                return -1;
 
1600
        }
 
1601
 
 
1602
        return WEXITSTATUS(status);
 
1603
}
 
1604
 
 
1605
static char*
 
1606
suffix_name(char* s)
 
1607
{
 
1608
        char* p;
 
1609
 
 
1610
        if ((p = strrchr(s, '.')) != NULL)
 
1611
                return p;
 
1612
        else
 
1613
                return "";
 
1614
}
 
1615
 
 
1616
static char base_name_buf[MAXPATHLEN];
 
1617
 
 
1618
static char*
 
1619
base_name(char* s)
 
1620
{
 
1621
        char* p;
 
1622
 
 
1623
        if ((p = strrchr(s, '.')) != NULL) {
 
1624
                memcpy(base_name_buf, s, p - s);
 
1625
                base_name_buf[p - s] = '\0';
 
1626
                s = base_name_buf;
 
1627
        }
 
1628
        return s;
 
1629
}
 
1630
 
 
1631
static char*
 
1632
file_base_name(char *s)
 
1633
{
 
1634
        char* p;
 
1635
 
 
1636
        s = base_name(s);
 
1637
 
 
1638
        if ((p = strrchr(s, '/')) != NULL)
 
1639
                s = &p[1];
 
1640
        
 
1641
        return s;
 
1642
}
 
1643
static int
 
1644
EhSourceCompile(EhSource*   source,
 
1645
                                EhSymTable* table,
 
1646
                                unsigned    verbosity,
 
1647
                                unsigned    do_compile,
 
1648
                                unsigned    do_zap,
 
1649
                                unsigned    do_assem)
 
1650
{
 
1651
        char* filename = source->name;
 
1652
        char** opts = source->cc_args;
 
1653
        char asname[MAXPATHLEN];
 
1654
        char o_asname[MAXPATHLEN];
 
1655
        char* cc_opts[256];
 
1656
        unsigned i = 0;
 
1657
        unsigned j = 0;
 
1658
        FILE* in_fp;
 
1659
        FILE* out_fp;
 
1660
        int   status;
 
1661
        int nzap = 0;
 
1662
        char* save_prefix = NULL;
 
1663
        unsigned do_dash_s = (do_zap != 0 || save_prefix != NULL);
 
1664
        char* cc_command;
 
1665
        char* use_savefile = NULL;
 
1666
        struct timeval start_time;
 
1667
        struct timeval end_time;
 
1668
#ifdef DEBUG_djw
 
1669
        char savebuf[1024];
 
1670
#endif
 
1671
        unsigned is_cplusplus = 0;
 
1672
 
 
1673
#ifdef LINUX
 
1674
        gettimeofday(&start_time,NULL);
 
1675
#else
 
1676
        gettimeofday(&start_time);
 
1677
#endif
 
1678
 
 
1679
        /* munge file */
 
1680
#ifdef HANDLES_DASHSO
 
1681
        if (source->target_object != NULL)
 
1682
                strcpy(asname, base_name(source->target_object));
 
1683
        else
 
1684
#endif
 
1685
                strcpy(asname, file_base_name(filename));
 
1686
        strcat(asname, ".s");
 
1687
 
 
1688
        strcpy(o_asname, asname);
 
1689
        strcat(o_asname, ".gts_tmp");
 
1690
 
 
1691
        if (strcmp(suffix_name(filename), ".cpp") == 0) {
 
1692
                cc_command = CCC_COMMAND;
 
1693
                is_cplusplus = 1;
 
1694
        } else if (strcmp(suffix_name(filename), ".s") == 0) {
 
1695
                do_compile = FALSE;
 
1696
                cc_command = CC_COMMAND;
 
1697
        } else {
 
1698
                cc_command = CC_COMMAND;
 
1699
        }
 
1700
 
 
1701
        if (do_compile) {
 
1702
 
 
1703
                j = 0;
 
1704
                cc_opts[j++] = cc_command;
 
1705
                cc_opts[j++] = "-c";
 
1706
 
 
1707
                if (do_dash_s) {
 
1708
                        cc_opts[j++] = "-S";
 
1709
#ifdef HANDLES_DASHSO
 
1710
                        if (source->target_object != NULL) {
 
1711
                                cc_opts[j++] = "-o";
 
1712
                                cc_opts[j++] = asname;
 
1713
                        }
 
1714
#endif
 
1715
                } else if (source->target_object != NULL) {
 
1716
                        cc_opts[j++] = "-o";
 
1717
                        cc_opts[j++] = source->target_object;
 
1718
                }
 
1719
                
 
1720
                i = 0;
 
1721
                while (opts[i] != NULL)
 
1722
                        cc_opts[j++] = opts[i++];
 
1723
                
 
1724
                cc_opts[j++] = filename;
 
1725
                cc_opts[j] = NULL;
 
1726
                
 
1727
                if ((status = do_command("compile", cc_opts, verbosity)) != 0) {
 
1728
                        fprintf(stderr, "compile failed (returned %d)\n", status);
 
1729
                        return -1;
 
1730
                }
 
1731
 
 
1732
                if (!do_dash_s)
 
1733
                        return 0;
 
1734
        }
 
1735
 
 
1736
        /*
 
1737
         *    Now we have a foo.s file, what do we do with it?
 
1738
         */
 
1739
        if (do_zap > 1) {
 
1740
 
 
1741
                if (use_savefile == NULL)
 
1742
                        use_savefile = asname;
 
1743
 
 
1744
                if ((in_fp = fopen(use_savefile, "r")) == NULL) {
 
1745
                        fprintf(stderr, "could not open %s for reading\n", asname);
 
1746
                        return -1;
 
1747
                }
 
1748
        
 
1749
                if ((out_fp = fopen(o_asname, "w")) == NULL) {
 
1750
                        fprintf(stderr, "could not open %s for writing\n", o_asname);
 
1751
                        return -1;
 
1752
                }
 
1753
        
 
1754
                j = 0;
 
1755
                cc_opts[j++] = "gts";
 
1756
                cc_opts[j++] = asname;
 
1757
                cc_opts[j++] = o_asname;
 
1758
                cc_opts[j++] = NULL;
 
1759
                print_command("gts", cc_opts, verbosity);
 
1760
 
 
1761
                nzap = EhSourceZapFp(source, table, in_fp, out_fp, verbosity, is_cplusplus);
 
1762
 
 
1763
                fclose(in_fp);
 
1764
                fclose(out_fp);
 
1765
 
 
1766
                j = 0;
 
1767
                cc_opts[j++] = "rename";
 
1768
                cc_opts[j++] = o_asname;
 
1769
                cc_opts[j++] = asname;
 
1770
                cc_opts[j++] = NULL;
 
1771
                print_command("rename", cc_opts, verbosity);
 
1772
 
 
1773
#ifdef DEBUG_djw
 
1774
                strcpy(savebuf, "gts_pre_");
 
1775
                strcat(savebuf, asname);
 
1776
                rename(asname, savebuf);
 
1777
#endif
 
1778
 
 
1779
                if (rename(o_asname, asname) == -1) {
 
1780
                        fprintf(stderr, "could not rename %s\n", o_asname);
 
1781
                        return -1;
 
1782
                }
 
1783
 
 
1784
        } else if (do_zap > 0) { /* audit only */
 
1785
 
 
1786
                if ((in_fp = fopen(asname, "r")) == NULL) {
 
1787
                        fprintf(stderr, "could not open %s for reading\n", asname);
 
1788
                        return -1;
 
1789
                }
 
1790
        
 
1791
                j = 0;
 
1792
                cc_opts[j++] = "audit";
 
1793
                cc_opts[j++] = asname;
 
1794
                cc_opts[j++] = NULL;
 
1795
                print_command("audit", cc_opts, verbosity);
 
1796
 
 
1797
                nzap = EhSourceZapFp(source, table, in_fp, NULL, verbosity, is_cplusplus);
 
1798
 
 
1799
                fclose(in_fp);
 
1800
        }
 
1801
 
 
1802
        if (do_assem) {
 
1803
                i = 0;
 
1804
                j = 0;
 
1805
                cc_opts[j++] = AS_COMMAND;
 
1806
                cc_opts[j++] = "-c";
 
1807
 
 
1808
                if (source->target_object != NULL) {
 
1809
                        cc_opts[j++] = "-o";
 
1810
                        cc_opts[j++] = source->target_object;
 
1811
                }
 
1812
 
 
1813
                while (opts[i] != NULL)
 
1814
                        cc_opts[j++] = opts[i++];
 
1815
 
 
1816
                cc_opts[j++] = asname;
 
1817
                cc_opts[j] = NULL;
 
1818
 
 
1819
                if ((status = do_command("assemble", cc_opts, verbosity)) != 0) {
 
1820
 
 
1821
                        unlink(asname);
 
1822
 
 
1823
                        fprintf(stderr,
 
1824
                                "gtscc of %s failed (exit status = %d), reverting to %s:\n",
 
1825
                                        filename,
 
1826
                                        status,
 
1827
                                        cc_command);
 
1828
                        
 
1829
                        i = 0;
 
1830
                        j = 0;
 
1831
                        cc_opts[j++] = cc_command;
 
1832
                        cc_opts[j++] = "-c";
 
1833
 
 
1834
                        if (source->target_object != NULL) {
 
1835
                                cc_opts[j++] = "-o";
 
1836
                                cc_opts[j++] = source->target_object;
 
1837
                        }
 
1838
 
 
1839
                        for (; opts[i]; i++, j++)
 
1840
                                cc_opts[j] = opts[i];
 
1841
                        
 
1842
                        cc_opts[j++] = filename;
 
1843
                        cc_opts[j] = NULL;
 
1844
                        
 
1845
                        if ((status = do_command("fix-compile", cc_opts, verbosity)) != 0)
 
1846
                                return -1;
 
1847
 
 
1848
                        return 0;
 
1849
                }
 
1850
        }
 
1851
 
 
1852
        if (save_prefix != NULL && save_prefix[0] != '\0') {
 
1853
 
 
1854
                sprintf(o_asname, save_prefix, file_base_name(filename));
 
1855
 
 
1856
                j = 0;
 
1857
                cc_opts[j++] = "rename";
 
1858
                cc_opts[j++] = asname;
 
1859
                cc_opts[j++] = o_asname;
 
1860
                cc_opts[j++] = NULL;
 
1861
                print_command("savefile", cc_opts, verbosity);
 
1862
 
 
1863
                if (rename(asname, o_asname) == -1) {
 
1864
                        fprintf(stderr, "could not rename %s to %s - sorry\n",
 
1865
                                        asname, o_asname);
 
1866
                        return -1;
 
1867
                }
 
1868
 
 
1869
                if (source->as_savefile != NULL)
 
1870
                        free(source->as_savefile);
 
1871
                source->as_savefile = strdup(o_asname);
 
1872
        } else {
 
1873
 
 
1874
                j = 0;
 
1875
                cc_opts[j++] = "unlink";
 
1876
                cc_opts[j++] = asname;
 
1877
                cc_opts[j++] = NULL;
 
1878
                print_command("unlink", cc_opts, verbosity);
 
1879
 
 
1880
#ifdef DEBUG_djw
 
1881
                strcpy(savebuf, "gts_post_");
 
1882
                strcat(savebuf, asname);
 
1883
                rename(asname, savebuf);
 
1884
#else
 
1885
                unlink(asname);
 
1886
#endif
 
1887
        }
 
1888
 
 
1889
#ifdef LINUX
 
1890
        gettimeofday(&end_time,NULL);
 
1891
#else
 
1892
        gettimeofday(&end_time);
 
1893
#endif
 
1894
 
 
1895
        source->compile_time = ((end_time.tv_sec - start_time.tv_sec) * 1000) +
 
1896
                           ((end_time.tv_usec - start_time.tv_usec) / 1000);
 
1897
 
 
1898
        return nzap;
 
1899
}
 
1900
 
 
1901
static char target_buf[MAXPATHLEN]; /* this will go away with rel source */
 
1902
 
 
1903
static char*
 
1904
EhSourceGetTarget(EhSource* source)
 
1905
{
 
1906
        if (source->target_object != NULL)
 
1907
                return source->target_object;
 
1908
 
 
1909
        strcpy(target_buf, base_name(source->name));
 
1910
        strcat(target_buf, ".o");
 
1911
 
 
1912
        return target_buf;
 
1913
}
 
1914
 
 
1915
static int
 
1916
EhArchiveUpdate(EhArchive* archive, char* target, char* rootdir,
 
1917
                                unsigned verbosity)
 
1918
{
 
1919
        char* args[8];
 
1920
        unsigned nargs;
 
1921
        int status;
 
1922
        char pathname[MAXPATHLEN];
 
1923
 
 
1924
        pathname[0] = '\0';
 
1925
        if (rootdir != NULL) {
 
1926
                strcat(pathname, rootdir);
 
1927
                strcat(pathname, "/");
 
1928
        }
 
1929
        strcat(pathname, archive->name);
 
1930
 
 
1931
#if 0
 
1932
        nargs = 0;
 
1933
        args[nargs++] = AR_COMMAND;
 
1934
        args[nargs++] = "dc";
 
1935
        args[nargs++] = pathname;
 
1936
        args[nargs++] = target;
 
1937
        args[nargs++] = NULL;
 
1938
        
 
1939
        if ((status = do_command("delete from archive", args, verbosity)) != 0) {
 
1940
                fprintf(stderr, "archive: %s delete %s failed (status = %d)\n",
 
1941
                                pathname,
 
1942
                                target);
 
1943
                return -1;
 
1944
        }
 
1945
#endif
 
1946
 
 
1947
        nargs = 0;
 
1948
        args[nargs++] = AR_COMMAND;
 
1949
        args[nargs++] = AR_OPTIONS;
 
1950
        args[nargs++] = pathname;
 
1951
        args[nargs++] = target;
 
1952
        args[nargs++] = NULL;
 
1953
        
 
1954
        if ((status = do_command("archive", args, verbosity)) != 0) {
 
1955
                fprintf(stderr, "archive: %s <- %s failed (status = %d)\n",
 
1956
                                pathname,
 
1957
                                target);
 
1958
                return -1;
 
1959
        }
 
1960
 
 
1961
        return 0;
 
1962
}
 
1963
 
 
1964
static int
 
1965
EhObjectRebuild(EhObject*   object,
 
1966
                                EhSymTable* table,
 
1967
                                unsigned    verbosity,
 
1968
                                char*       rootdir)
 
1969
{
 
1970
        EhSource* source = object->source;
 
1971
        char  cwd[MAXPATHLEN];
 
1972
        char  fullpath[MAXPATHLEN];
 
1973
        int   rv = 0;
 
1974
        int   do_chdir = 0;
 
1975
 
 
1976
        if (!source) {
 
1977
                fprintf(stderr,
 
1978
                                "wanted to recompile %s, but I don't how\n",
 
1979
                                object->name);
 
1980
                return -1;
 
1981
        }
 
1982
        
 
1983
#if 0
 
1984
        if (VERBOSITY_USER(verbosity))
 
1985
#endif
 
1986
                fprintf(stderr, "recompiling %s\n", source->name);
 
1987
        
 
1988
        /*
 
1989
         *    Check to see if we need to chdir
 
1990
         */
 
1991
        if (source->directory != NULL) {
 
1992
                if (getcwd(cwd, sizeof(cwd)) == NULL) {
 
1993
                        fprintf(stderr, "cannot get pwd: cannot compile\n");
 
1994
                        return -1;
 
1995
                }
 
1996
                
 
1997
                make_relative_pathname(fullpath, cwd, rootdir);
 
1998
                
 
1999
                if (strcmp(fullpath, source->directory) != 0) {
 
2000
                        fullpath[0] = '\0';
 
2001
                        if (rootdir != NULL) {
 
2002
                                strcat(fullpath, rootdir);
 
2003
                                strcat(fullpath, "/");
 
2004
                        }
 
2005
                        strcat(fullpath, source->directory);
 
2006
 
 
2007
                        if (chdir(fullpath) == -1) {
 
2008
                                fprintf(stderr, "cannot chdir - can't compile\n");
 
2009
                                return -1;
 
2010
                        }
 
2011
                        do_chdir++;
 
2012
                }
 
2013
        }
 
2014
 
 
2015
        rv = EhSourceCompile(source,
 
2016
                                                 table,
 
2017
                                                 verbosity,
 
2018
                                                 TRUE,  /* compile  */
 
2019
                                                 2,     /* do zap   */
 
2020
                                                 TRUE); /* do assem */
 
2021
 
 
2022
        if (do_chdir) {
 
2023
                if (chdir(cwd) == -1) {
 
2024
                        fprintf(stderr, "cannot chdir - this will be very confused\n");
 
2025
                        return -1;
 
2026
                }
 
2027
        }
 
2028
 
 
2029
        if (rv == -1) {
 
2030
                fprintf(stderr, "recompiling %s failed\n",  source->name);
 
2031
                return -1;
 
2032
        }
 
2033
        
 
2034
        /* do archive */
 
2035
        fullpath[0] = '\0';
 
2036
        if (rootdir != NULL) {
 
2037
                strcat(fullpath, rootdir);
 
2038
                strcat(fullpath, "/");
 
2039
        }
 
2040
 
 
2041
        if (source->directory != NULL)
 
2042
                strcat(fullpath, source->directory);
 
2043
 
 
2044
        strcat(fullpath, "/");
 
2045
        strcat(fullpath, EhSourceGetTarget(source));
 
2046
        
 
2047
        if (object->archive != NULL) {
 
2048
                if (EhArchiveUpdate(object->archive, fullpath, rootdir,
 
2049
                                                        verbosity) == -1)
 
2050
                        return -1;
 
2051
        }
 
2052
 
 
2053
        /* do install */
 
2054
#if 0
 
2055
        if (rv != -1) {
 
2056
        }
 
2057
#endif
 
2058
 
 
2059
        return rv;
 
2060
}
 
2061
 
 
2062
static int
 
2063
object_nusers_mappee(EhSym* sym, void* arg)
 
2064
{
 
2065
        if (sym->object != NULL)
 
2066
                sym->object->nusers += sym->ngusers;
 
2067
        return 0;
 
2068
}
 
2069
 
 
2070
typedef struct {
 
2071
        EhObject* recompile_list;
 
2072
        unsigned  recompile_count;
 
2073
        unsigned  recompile_wish_count;
 
2074
        unsigned  unzap_count;
 
2075
        unsigned  zap_count;
 
2076
} RecompileInfo;
 
2077
 
 
2078
static int
 
2079
recompile_init_mappee(EhSym* sym, void* arg)
 
2080
{
 
2081
        RecompileInfo* info = (RecompileInfo*)arg;
 
2082
 
 
2083
        if (EHSYM_ISZAPPED(sym) && sym->ngusers != 0) {
 
2084
                if (EH_OBJECT_CANBUILD(sym->object)) {
 
2085
                        sym->state = EH_SYM_DEFINED;
 
2086
                        if (sym->object->_recompile == NULL) {
 
2087
                                sym->object->_recompile = info->recompile_list;
 
2088
                                info->recompile_list = sym->object;
 
2089
                                info->recompile_count++;
 
2090
                        }
 
2091
                        info->unzap_count++;
 
2092
                        sym->object->_needs_unzap++;
 
2093
                }
 
2094
                info->recompile_wish_count++;
 
2095
        }
 
2096
        else if (EHSYM_ISDEFINED(sym) /* it's defined */
 
2097
                         && sym->ngusers == 0 /* there are no global users */
 
2098
                         && sym->nlusers != 0 /* BUT, ther are local users */
 
2099
                         && sym->object->nusers != 0) { /* object is linked */
 
2100
 
 
2101
                if (EH_OBJECT_CANBUILD(sym->object)) {
 
2102
                        sym->state = EH_SYM_ZAPPED;
 
2103
                        if (sym->object->_recompile == NULL) {
 
2104
                                sym->object->_recompile = info->recompile_list;
 
2105
                                info->recompile_list = sym->object;
 
2106
                                info->recompile_count++;
 
2107
                        }
 
2108
                        info->zap_count++;
 
2109
                }
 
2110
                info->recompile_wish_count++;
 
2111
        }
 
2112
 
 
2113
        return 0;
 
2114
}
 
2115
 
 
2116
static char**    recompile_compare_prefs;
 
2117
static char**    recompile_compare_unprefs;
 
2118
 
 
2119
static unsigned
 
2120
match_prefs(char* candidate, char** prefs)
 
2121
{
 
2122
        unsigned n;
 
2123
 
 
2124
        for (n = 0; prefs[n] != NULL; n++) {
 
2125
                char*    pref = prefs[n];
 
2126
                unsigned len = strlen(pref);
 
2127
                if (strncmp(pref, candidate, len) == 0)
 
2128
                        return n; /* cool */
 
2129
        }
 
2130
        return (unsigned)-1; /* big! */
 
2131
}
 
2132
 
 
2133
static  int
 
2134
recompile_compare(const void* ap, const void* bp)
 
2135
{
 
2136
        EhObject** ax = (EhObject**)ap;
 
2137
        EhObject** bx = (EhObject**)bp;
 
2138
        EhObject*  obj_a = *ax;
 
2139
        EhObject*  obj_b = *bx;
 
2140
        EhSource*  src_a = obj_a->source;
 
2141
        EhSource*  src_b = obj_b->source;
 
2142
        unsigned   matcha;
 
2143
        unsigned   matchb;
 
2144
        int        foo;
 
2145
 
 
2146
        if (obj_a->_needs_unzap == 0 && obj_b->_needs_unzap != 0)
 
2147
                return -1;
 
2148
        if (obj_a->_needs_unzap != 0 && obj_b->_needs_unzap == 0)
 
2149
                return 1;
 
2150
 
 
2151
        if (src_a == NULL && src_b != NULL)
 
2152
                return 1;
 
2153
        if (src_a != NULL && src_b == NULL)
 
2154
                return -1;
 
2155
        if (src_a == src_b)
 
2156
                return 0;
 
2157
 
 
2158
        if (recompile_compare_unprefs != NULL
 
2159
                && src_a->directory != NULL && src_b->directory != NULL) {
 
2160
 
 
2161
                matcha = match_prefs(src_a->directory, recompile_compare_unprefs);
 
2162
                matchb = match_prefs(src_b->directory, recompile_compare_unprefs);
 
2163
 
 
2164
                if (matcha > matchb) /* greater is good */
 
2165
                        return -1;
 
2166
                if (matcha < matchb)
 
2167
                        return 1;
 
2168
        }
 
2169
 
 
2170
        if (recompile_compare_prefs != NULL
 
2171
                && src_a->directory != NULL && src_b->directory != NULL) {
 
2172
 
 
2173
                matcha = match_prefs(src_a->directory, recompile_compare_prefs);
 
2174
                matchb = match_prefs(src_b->directory, recompile_compare_prefs);
 
2175
 
 
2176
                if (matcha > matchb) /* greater is bad */
 
2177
                        return 1;
 
2178
                if (matcha < matchb)
 
2179
                        return -1;
 
2180
        }
 
2181
 
 
2182
        /* else same directory probably */
 
2183
        foo = strcmp(src_a->name, src_b->name);
 
2184
 
 
2185
        if (foo < 0)
 
2186
                return -1;
 
2187
        if (foo > 0)
 
2188
                return 1;
 
2189
 
 
2190
        return 0;
 
2191
}
 
2192
 
 
2193
static int
 
2194
do_recompilation(EhSymTable* table, char* gts_file, unsigned max_globals,
 
2195
                                 char** prefs, char** unprefs,
 
2196
                                 char* rootdir, unsigned verbosity)
 
2197
{
 
2198
        SummaryInfo s_info;
 
2199
        RecompileInfo info;
 
2200
        unsigned    size;
 
2201
        unsigned n;
 
2202
        EhObject* object;
 
2203
        EhObject** recompiles;
 
2204
        unsigned delta;
 
2205
        int rv;
 
2206
        unsigned nzaps;
 
2207
        EhObject dummy; /* just marks the end of the recomp list */
 
2208
        time_t  eta;
 
2209
 
 
2210
        get_summary(table, &s_info);
 
2211
 
 
2212
        if ((s_info.nused + s_info.ndefined) <= max_globals) {
 
2213
                if (VERBOSITY_USER(verbosity))
 
2214
                        fprintf(stderr,
 
2215
                        "number of globals <= requested max, skipping recompilation\n");
 
2216
                return 0;
 
2217
        }
 
2218
 
 
2219
        /* Init recompilation. */
 
2220
        info.recompile_list = &dummy; /* cannot use NULL, because syms test that */
 
2221
        info.recompile_count = 0;
 
2222
        info.recompile_wish_count = 0;
 
2223
        info.unzap_count = 0;
 
2224
        info.zap_count = 0;
 
2225
        EhSymTableMap(table, recompile_init_mappee, (void*)&info);
 
2226
        size = info.recompile_count;
 
2227
 
 
2228
        recompiles = (EhObject**)malloc(sizeof(EhObject*) * size);
 
2229
 
 
2230
        /* install */
 
2231
        n = 0;
 
2232
        for (object = info.recompile_list;
 
2233
                 object != &dummy;
 
2234
                 object = object->_recompile) {
 
2235
                recompiles[n++] = object;
 
2236
        }
 
2237
 
 
2238
        /* sort */
 
2239
        recompile_compare_prefs = prefs;
 
2240
        recompile_compare_unprefs = unprefs;
 
2241
        qsort(recompiles, size, sizeof(EhObject*), recompile_compare);
 
2242
 
 
2243
        /*
 
2244
         *    sorted !
 
2245
         *    less recompile the first n, n = ndefined - max
 
2246
         */
 
2247
        delta = (s_info.nused + s_info.ndefined) - max_globals;
 
2248
 
 
2249
        if (delta > info.zap_count) {
 
2250
                fprintf(stderr,
 
2251
                                "WARNING: there too many globals (%d/%d fixables).\n"
 
2252
                                "         I don't think I can fix this, but I'll try.\n"
 
2253
                                "         You might get lucky.\n",
 
2254
                                info.zap_count,
 
2255
                                delta);
 
2256
        }
 
2257
 
 
2258
        if (VERBOSITY_USER(verbosity))
 
2259
                fprintf(stderr, "scheduling recompilation targets:\n");
 
2260
 
 
2261
        eta = 0;
 
2262
        for (n = 0; n < size; n++) {
 
2263
                char* cname = "unknown";
 
2264
                object = recompiles[n];
 
2265
                if (object->source != NULL) {
 
2266
                        cname = object->source->name;
 
2267
                        eta += object->source->compile_time;
 
2268
                }
 
2269
                
 
2270
                if (VERBOSITY_DEBUG(verbosity))
 
2271
                        fprintf(stderr, "object %s from source %s\n", object->name, cname);
 
2272
        }
 
2273
 
 
2274
#if 0
 
2275
        if (VERBOSITY_USER(verbosity))
 
2276
#endif
 
2277
                fprintf(stderr, "gts-ing %d symbols, eta = %d minutes\n", delta,
 
2278
                                eta/(60*1000));
 
2279
 
 
2280
        if (gts_file != NULL) {
 
2281
                FILE* zap_fp;
 
2282
                if ((zap_fp = fopen(gts_file, "w")) == NULL) {
 
2283
                        perror(0);
 
2284
                        fprintf(stderr,
 
2285
                                        "WARNING: could not open the gtscc db file %s.\n"
 
2286
                                        "         I will continue with the recompilation, but\n"
 
2287
                                        "         if you recompile any of the files I touched\n"
 
2288
                                        "         I'll have to recompile them after you!\n",
 
2289
                                        gts_file);
 
2290
                } else {
 
2291
                
 
2292
                        EhSymTableFpDump(table, zap_fp);
 
2293
                        
 
2294
                        fclose(zap_fp);
 
2295
                }
 
2296
        }
 
2297
 
 
2298
        for (n = 0, nzaps = 0; n < size && nzaps < delta; n++) {
 
2299
 
 
2300
                object = recompiles[n];
 
2301
                rv = EhObjectRebuild(object, table, verbosity, rootdir);
 
2302
 
 
2303
                if (rv == -1)
 
2304
                        return -1;
 
2305
 
 
2306
                nzaps += rv;
 
2307
 
 
2308
                object->_recompile = NULL; /* clean up now */
 
2309
        }
 
2310
 
 
2311
        if (nzaps < delta) {
 
2312
                fprintf(stderr,
 
2313
                                "WARNING: I wanted to gts %d symbols, but only managed\n"
 
2314
                                "         to get %d of them.\n"
 
2315
                                "         Your link may fail with GOT errors.\n",
 
2316
                                delta,
 
2317
                                nzaps);
 
2318
        }
 
2319
        
 
2320
        free(recompiles);
 
2321
 
 
2322
        return n;
 
2323
}
 
2324
 
 
2325
typedef struct FileList
 
2326
{
 
2327
        char*            name;
 
2328
        struct FileList* next;
 
2329
} FileList;
 
2330
 
 
2331
static FileList*
 
2332
fileListFind(FileList* list, char* name)
 
2333
{
 
2334
        FileList* foo;
 
2335
 
 
2336
        for (foo = list; foo != NULL; foo = foo->next) {
 
2337
                if (strcmp(name, foo->name) == 0)
 
2338
                        return foo;
 
2339
        }
 
2340
        return NULL;
 
2341
}
 
2342
 
 
2343
static FileList*
 
2344
fileListAppend(FileList** list_a, char* name)
 
2345
{
 
2346
        FileList* list = *list_a;
 
2347
        FileList* foo;
 
2348
        FileList* last;
 
2349
 
 
2350
        for (foo = list, last = NULL; foo != NULL; last = foo, foo = foo->next)
 
2351
                ;
 
2352
 
 
2353
        if (last == NULL) {
 
2354
                foo = EH_NEW(FileList);
 
2355
                foo->next = NULL;
 
2356
                foo->name = strdup(name);
 
2357
                *list_a = foo;
 
2358
        } else {
 
2359
                foo = EH_NEW(FileList);
 
2360
                foo->next = NULL;
 
2361
                foo->name = strdup(name);
 
2362
                last->next = foo;
 
2363
        }
 
2364
 
 
2365
        return *list_a;
 
2366
}
 
2367
 
 
2368
#if 0
 
2369
static FileList* c_list;
 
2370
#endif
 
2371
static FileList* o_list;
 
2372
 
 
2373
#if 0
 
2374
static char*
 
2375
EhSourceAdjustPathname(EhSource* source, char* rootdir)
 
2376
{
 
2377
        char buf[MAXPATHLEN];
 
2378
        char buf2[MAXPATHLEN];
 
2379
        char* p;
 
2380
        char* q;
 
2381
        char* filename = source->name;
 
2382
 
 
2383
        if (getcwd(buf, sizeof(buf)) == NULL) {
 
2384
                fprintf(stderr, "cannot get pwd\n");
 
2385
                return NULL;
 
2386
        }
 
2387
 
 
2388
        strcat(buf, "/");
 
2389
        strcat(buf, filename);
 
2390
 
 
2391
        if (rootdir == NULL) {
 
2392
                filename = buf;
 
2393
        } else {
 
2394
                if (realpath(buf, buf2) == NULL) {
 
2395
                        fprintf(stderr, "realpath() failed: %s\n", buf2);
 
2396
                        return NULL;
 
2397
                }
 
2398
 
 
2399
                if (realpath(rootdir, buf) == NULL) {
 
2400
                        fprintf(stderr, "realpath() failed: %s\n", buf);
 
2401
                        return NULL;
 
2402
                }
 
2403
                strcat(buf, "/"); 
 
2404
                
 
2405
                for (p = buf, q = buf2; *p == *q; p++, q++)
 
2406
                        ;
 
2407
 
 
2408
                filename = q;
 
2409
        }
 
2410
 
 
2411
        free(source->name);
 
2412
        source->name = strdup(filename);
 
2413
 
 
2414
        return source->name;
 
2415
}
 
2416
#endif
 
2417
 
 
2418
static unsigned
 
2419
katoi(char *buf)
 
2420
{
 
2421
        unsigned base = 1;
 
2422
        char* s;
 
2423
        
 
2424
        for (s = buf; isdigit(*s); s++)
 
2425
                ;
 
2426
 
 
2427
        if (*s == 'k' || *s == 'K')
 
2428
                base = 1024;
 
2429
 
 
2430
        *s = '\0';
 
2431
 
 
2432
        return base * atoi(buf);
 
2433
}
 
2434
 
 
2435
static void
 
2436
usage(void)
 
2437
{
 
2438
        fprintf(stderr,
 
2439
                        "Usage:\n"
 
2440
                        "as a compiler:\n"
 
2441
                        "gtscc [gtscc_options] [compiler_options] -c file.c file.cpp ...\n"
 
2442
                        "gtscc_options:\n"
 
2443
                        "-gtsfile <db.gts>       the gts database file (use this)\n"
 
2444
                        "-gtszapsymbol <name>    convert symbol <name>\n"
 
2445
                        "-gtsnozapsymbol <name>  don't convert symbol <name>\n"
 
2446
                        "-gtsrootdir <directory> the root for the tree (use this)\n"
 
2447
                        "-gtsverbose             be more verbose (3 levels)\n"
 
2448
                        "-gtsnozap               don't convert globals to statics\n"
 
2449
                        "-gtsnoupdate            don't update the database file\n"
 
2450
                        "as a linker:\n"
 
2451
                        "gtscc [gtscc_options] [linker_options] file.o ... libxx.a ...\n"
 
2452
                        "gtscc_options:\n"
 
2453
                        "-gtsfile <db.gts>       the gts database file (use this)\n"
 
2454
                        "-gtszapsymbol <name>    convert symbol <name>\n"
 
2455
                        "-gtsnozapsymbol <name>  don't convert symbol <name>\n"
 
2456
                        "-gtsrootdir <directory> the root for the tree (use this)\n"
 
2457
                        "-gtspref <directory>    please recompile these paths first\n"
 
2458
                        "-gtsunpref <directory>  please try to avoid recompiling these\n"
 
2459
                        "-gtsverbose             be more verbose (3 levels)\n"
 
2460
                        "-gtssummary             print a summary of global usage\n"
 
2461
                        "-gtsdump                print a detailed listing of all symbols\n"
 
2462
                        "-gtsmaxglobals <number>[k] maximum globals allowed in target\n"
 
2463
                        "-gtsnorecompile         don't do the normal recompilation\n"
 
2464
                        "-gtsnolink              don't call linker after recompilation\n"
 
2465
                        "-gtsnoupdate            don't update the database file\n"
 
2466
                        "-help                   print this\n"
 
2467
        );
 
2468
}
 
2469
 
 
2470
int
 
2471
main(int argc, char** argv)
 
2472
{
 
2473
        EhSymTable* table = EhSymTableNew(1000);
 
2474
        EhSym* sym;
 
2475
        FILE* zap_fp;
 
2476
        unsigned n = 0;
 
2477
        unsigned verbosity = 0;
 
2478
        char* arg_buf[256];
 
2479
        unsigned nargs = 0;
 
2480
        EhDirMap*   dmap = EhDirMapNew();
 
2481
        unsigned do_dump = 0;
 
2482
        unsigned do_summary = 0;
 
2483
        unsigned do_link = 1;
 
2484
        unsigned in_link = 1;
 
2485
        unsigned do_audit = 1;
 
2486
        unsigned do_zap = 1;
 
2487
        unsigned do_assem = 1;
 
2488
        unsigned do_recompile = 1;
 
2489
        unsigned do_collect = 1;
 
2490
        char* name;
 
2491
        char* saveprefix = NULL;
 
2492
        char* rootdir = NULL;
 
2493
        int rv;
 
2494
        EhSource* source = NULL;
 
2495
        char* gts_file = NULL;
 
2496
        char* path_prefs[32];
 
2497
        unsigned npath_prefs = 0;
 
2498
        char* path_un_prefs[32];
 
2499
        unsigned npath_un_prefs = 0;
 
2500
        char* suffix;
 
2501
        unsigned max_globals = DEFAULT_MAX_GLOBALS;
 
2502
        FileList* list;
 
2503
 
 
2504
        if (elf_version(EV_CURRENT) == EV_NONE) {
 
2505
                fprintf(stderr, "something losing about your elf lib - sorry!\n");
 
2506
                return 3;
 
2507
                /* library out of date */
 
2508
                /* recover from error */
 
2509
        }
 
2510
 
 
2511
        arg_buf[nargs] = NULL;
 
2512
 
 
2513
        for (n = 1; n < argc; n++) {
 
2514
 
 
2515
                if (strcmp(argv[n], "-help") == 0) {
 
2516
                        usage();
 
2517
                        return 0;
 
2518
                } else if (strcmp(argv[n], "-gtssummary") == 0) {
 
2519
                        do_summary = 1;
 
2520
                } else if (strcmp(argv[n], "-gtsdump") == 0) {
 
2521
                        do_dump = 1;
 
2522
                } else if (strcmp(argv[n], "-gtsnorecompile") == 0) {
 
2523
                        do_recompile = 0;
 
2524
                } else if (strcmp(argv[n], "-gtsnolink") == 0) {
 
2525
                        do_link = 0;
 
2526
                } else if (strcmp(argv[n], "-gtsverbose") == 0) {
 
2527
                        verbosity++;
 
2528
                } else if (strcmp(argv[n], "-gtsnoupdate") == 0) {
 
2529
                        do_collect = 0;
 
2530
                } else if (strcmp(argv[n], "-gtsnoaudit") == 0) {
 
2531
                        do_audit = 0;
 
2532
                } else if (strcmp(argv[n], "-gtsnozap") == 0) {
 
2533
                        do_zap = 0;
 
2534
                } else if (strcmp(argv[n], "-gtsrootdir") == 0) {
 
2535
                        if (argc < n+2) {
 
2536
                                fprintf(stderr, "-gtsrootdir requires an argument\n");
 
2537
                                usage();
 
2538
                                return 2;
 
2539
                        }
 
2540
                        rootdir = argv[n+1];
 
2541
                        n++;
 
2542
                } else if (strcmp(argv[n], "-gtsdebugsym") == 0) {
 
2543
                        if (argc < n+2) {
 
2544
                                fprintf(stderr, "-gtsdebugsym requires an argument\n");
 
2545
                                usage();
 
2546
                                return 2;
 
2547
                        }
 
2548
                        djw_test_name = argv[n+1];
 
2549
                        n++;
 
2550
                } else if (strcmp(argv[n], "-gtsmaxglobals") == 0) {
 
2551
                        if (argc < n+2) {
 
2552
                                fprintf(stderr, "-gtsmaxglobals requires an argument\n");
 
2553
                                usage();
 
2554
                                return 2;
 
2555
                        }
 
2556
                        max_globals = katoi(argv[n+1]);
 
2557
                        n++;
 
2558
 
 
2559
                } else if (strcmp(argv[n], "-gtspref") == 0) {
 
2560
                        if (argc < n+2) {
 
2561
                                fprintf(stderr, "-gtspref requires an argument\n");
 
2562
                                usage();
 
2563
                                return 2;
 
2564
                        }
 
2565
                        path_prefs[npath_prefs++] = argv[n+1];
 
2566
                        path_prefs[npath_prefs] = NULL;
 
2567
                        n++;
 
2568
 
 
2569
                } else if (strcmp(argv[n], "-gtsunpref") == 0) {
 
2570
                        if (argc < n+2) {
 
2571
                                fprintf(stderr, "-gtsunpref requires an argument\n");
 
2572
                                usage();
 
2573
                                return 2;
 
2574
                        }
 
2575
                        path_un_prefs[npath_un_prefs++] = argv[n+1];
 
2576
                        path_un_prefs[npath_un_prefs] = NULL;
 
2577
                        n++;
 
2578
 
 
2579
                } else if (strcmp(argv[n], "-gtssaveprefix") == 0) {
 
2580
                        if (argc < n+2) {
 
2581
                                fprintf(stderr, "-gtssaveprefix requires an argument\n");
 
2582
                                usage();
 
2583
                                return 2;
 
2584
                        }
 
2585
                        saveprefix = argv[n+1];
 
2586
                        n++;
 
2587
 
 
2588
                } else if (strcmp(argv[n], "-gtsfile") == 0) {
 
2589
 
 
2590
                        struct stat sbuf;
 
2591
 
 
2592
                        if (argc < n+2) {
 
2593
                                fprintf(stderr, "-gtsfile requires an argument\n");
 
2594
                                usage();
 
2595
                                return 2;
 
2596
                        }
 
2597
 
 
2598
                        gts_file = argv[n+1];
 
2599
                                
 
2600
                        if (stat(gts_file, &sbuf) == -1) {
 
2601
                                fprintf(stderr,
 
2602
                                                "warning: %s does not exist, will be created\n",
 
2603
                                                gts_file);
 
2604
                        } else {
 
2605
                                
 
2606
                                if ((zap_fp = fopen(gts_file, "r")) == NULL) {
 
2607
                                        fprintf(stderr, "you lose cannot open %s\n", gts_file);
 
2608
                                        usage();
 
2609
                                        return 2;
 
2610
                                }
 
2611
 
 
2612
                                if (EhSymTableFpLoad(table, zap_fp) == -1) {
 
2613
                                        fprintf(stderr,
 
2614
                                                        "error: failed reading symbols from gtsfile %s\n",
 
2615
                                                        argv[n+1]);
 
2616
                                        usage();
 
2617
                                        return 2;
 
2618
                                }
 
2619
                                
 
2620
                                fclose(zap_fp);
 
2621
                        }
 
2622
 
 
2623
                        n++;
 
2624
 
 
2625
                } else if (strcmp(argv[n], "-gtszapsymbol") == 0) {
 
2626
                        if (argc < n+2) {
 
2627
                                fprintf(stderr, "-gtszapsymbol requires an argument\n");
 
2628
                                usage();
 
2629
                                return 2;
 
2630
                        }
 
2631
 
 
2632
                        EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_ZAPPED);
 
2633
                        n++;
 
2634
 
 
2635
                } else if (strcmp(argv[n], "-gtsnozapsymbol") == 0) {
 
2636
                        if (argc < n+2) {
 
2637
                                fprintf(stderr, "-gtsnozapsymbol requires an argument\n");
 
2638
                                usage();
 
2639
                                return 2;
 
2640
                        }
 
2641
 
 
2642
                        EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_DEFINED);
 
2643
                        n++;
 
2644
 
 
2645
                } else if (strcmp(argv[n], "-gtsname") == 0) {
 
2646
                        if (argc < n+2) {
 
2647
                                fprintf(stderr, "-gtsname requires an argument\n");
 
2648
                                usage();
 
2649
                                return 2;
 
2650
                        }
 
2651
 
 
2652
                        sym = EhSymTableFind(table, argv[n+1]);
 
2653
                        if (!sym)
 
2654
                                sym = EhSymNewRandomZap(argv[n+1]);
 
2655
                        n++;
 
2656
                        do_audit = 1;
 
2657
 
 
2658
                } else if (strcmp(argv[n], "-c") == 0) { /* do not link */
 
2659
                        in_link = 0;
 
2660
                        do_link = 0;
 
2661
                } else if (strcmp(argv[n], "-S") == 0) { /* do not assem */
 
2662
                        do_assem = 0;
 
2663
                } else if (strcmp(argv[n], "-o") == 0) { /* parse through */
 
2664
                        arg_buf[nargs++] = argv[n++];
 
2665
                        arg_buf[nargs++] = argv[n];
 
2666
                        arg_buf[nargs] = NULL;
 
2667
                } else if (strcmp((suffix = suffix_name(argv[n])), ".cpp") == 0
 
2668
                                   ||
 
2669
                                   strcmp(suffix, ".c") == 0
 
2670
                                   ||
 
2671
                                   strcmp(suffix, ".s") == 0) {
 
2672
                        char pathname[MAXPATHLEN];
 
2673
 
 
2674
                        make_relative_pathname(pathname, ".", rootdir);
 
2675
 
 
2676
                        source = EhSourceNew(argv[n], arg_buf, pathname);
 
2677
 
 
2678
                        rv = EhSourceCompile(source,
 
2679
                                                                 table,
 
2680
                                                                 verbosity,
 
2681
                                                                 TRUE, /* compile, .s files ignore anyway */
 
2682
                                                                 (do_audit + do_zap),
 
2683
                                                                 do_assem);
 
2684
                        if (rv == -1)
 
2685
                                return 1;
 
2686
 
 
2687
#if 0
 
2688
                        EhSourceAdjustPathname(source, rootdir);
 
2689
#endif
 
2690
 
 
2691
                } else if (strcmp(suffix, ".o") == 0 || strcmp(suffix, ".a") == 0) {
 
2692
 
 
2693
                        if (fileListFind(o_list, argv[n]) == NULL) {
 
2694
                                fileListAppend(&o_list, argv[n]);
 
2695
                        } else {
 
2696
                                fprintf(stderr,
 
2697
                                                "%s repeated on command line - ignored\n",
 
2698
                                                argv[n]);
 
2699
                        }
 
2700
                        arg_buf[nargs++] = argv[n];
 
2701
                        arg_buf[nargs] = NULL;
 
2702
 
 
2703
                } else if (strncmp(argv[n], "-L", 2) == 0) {
 
2704
                        EhDirMapAddDirectory(dmap, &argv[n][2]);
 
2705
                } else if (strncmp(argv[n], "-l", 2) == 0) {
 
2706
                        char pathbuf[MAXPATHLEN];
 
2707
                        name = EhDirMapGetLibName(dmap, &argv[n][2], pathbuf);
 
2708
                        if (name != NULL) {
 
2709
                                if (fileListFind(o_list, name) == NULL) {
 
2710
                                        fileListAppend(&o_list, name);
 
2711
                                } else {
 
2712
                                        fprintf(stderr,
 
2713
                                                        "%s repeated on command line - ignored\n",
 
2714
                                                        name);
 
2715
                                }
 
2716
                        } else {
 
2717
                                fprintf(stderr, 
 
2718
                                                "unable to resolve library reference %s - ignoring\n",
 
2719
                                                argv[n]);
 
2720
                        }
 
2721
                        arg_buf[nargs++] = argv[n];
 
2722
                        arg_buf[nargs] = NULL;
 
2723
                } else {
 
2724
                        arg_buf[nargs++] = argv[n];
 
2725
                        arg_buf[nargs] = NULL;
 
2726
                }
 
2727
        }
 
2728
 
 
2729
        /*
 
2730
         *    Analyse objects.
 
2731
         */
 
2732
        if (o_list != NULL) {
 
2733
                for (list = o_list; list != NULL; list = list->next) {
 
2734
 
 
2735
                        if (eh_process_file(list->name, table, rootdir)) {
 
2736
                                fprintf(stderr, "oops we died around %s\n", list->name);
 
2737
                                return 1;
 
2738
                        }
 
2739
                }
 
2740
                
 
2741
                /* look for unused objects */
 
2742
                EhSymTableMap(table, object_nusers_mappee, 0);
 
2743
        }
 
2744
 
 
2745
        if (do_summary) {
 
2746
                print_summary(table);
 
2747
        }
 
2748
 
 
2749
        if (do_dump) {
 
2750
                print_dump(table);
 
2751
        }
 
2752
 
 
2753
        if (!in_link && gts_file != NULL) {
 
2754
                FILE* zap_fp;
 
2755
                if ((zap_fp = fopen(gts_file, "w")) == NULL) {
 
2756
                        perror(0);
 
2757
                        usage();
 
2758
                        return 2;
 
2759
                }
 
2760
 
 
2761
                EhSymTableFpDump(table, zap_fp);
 
2762
                fclose(zap_fp);
 
2763
                return 0;
 
2764
        }
 
2765
 
 
2766
        /*
 
2767
         *    Now the fun really starts.
 
2768
         */
 
2769
        if (do_recompile) {
 
2770
                char** pp = NULL;
 
2771
                char** up = NULL;
 
2772
                
 
2773
                if (npath_prefs > 0)
 
2774
                        pp = path_prefs;
 
2775
                
 
2776
                if (npath_un_prefs > 0)
 
2777
                        up = path_un_prefs;
 
2778
 
 
2779
                if (!do_collect)
 
2780
                        gts_file = NULL;
 
2781
                
 
2782
                rv = do_recompilation(table, gts_file, max_globals, pp, up, rootdir,
 
2783
                                                          verbosity);
 
2784
                if (rv == -1)
 
2785
                        return 1;
 
2786
        }
 
2787
 
 
2788
        /*
 
2789
         *    Finally.
 
2790
         */
 
2791
        if (do_link) {
 
2792
 
 
2793
                int status;
 
2794
 
 
2795
                arg_buf[nargs+1] = NULL;
 
2796
                for (n = nargs; n > 0; n--)
 
2797
                        arg_buf[n] = arg_buf[n-1];
 
2798
                arg_buf[0] = LD_COMMAND;
 
2799
                
 
2800
                status = do_command("link", arg_buf, verbosity);
 
2801
 
 
2802
                if (status == -1)
 
2803
                        return 3;
 
2804
                else
 
2805
                        return status;
 
2806
        }
 
2807
        
 
2808
        return 0;
 
2809
}