Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
gtscc.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <unistd.h>
#include <ctype.h>
#include <libelf.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>

Go to the source code of this file.

Classes

struct  EhArchive
struct  EhSource
struct  EhObject
struct  EhSym
struct  EhSymTable
struct  fixup_info
struct  flush_info
struct  SummaryInfo
struct  EhDirMapEntree
struct  EhDirMap
struct  RecompileInfo
struct  FileList

Defines

#define DEFAULT_MAX_GLOBALS   15500
#define ELFSYM_IS_DEFINED(x)   ((x).st_shndx != SHN_UNDEF)
#define ELFSYM_IS_UNDEFINED(x)   ((x).st_shndx == SHN_UNDEF)
#define HANDLES_DASHSO
#define CC_COMMAND   "gcc"
#define CCC_COMMAND   "g++"
#define AS_COMMAND   "gcc"
#define LD_COMMAND   "g++"
#define AR_COMMAND   "ar"
#define AR_OPTIONS   "cr"
#define EH_NEW(type)   (type*)malloc(sizeof(type))
#define TRUE   1
#define FALSE   0
#define EH_TAG_FILE   'F'
#define EH_TAG_GLOBAL   'G'
#define EH_TAG_ZAPPED   'Z'
#define EH_TAG_INLINE   'I'
#define EH_TAG_UNDEFINED   'U'
#define VERBOSITY_USER(x)   ((x) > 0)
#define VERBOSITY_DEBUG(x)   ((x) > 1)
#define VERBOSITY_MAJOR(x)   ((x) > 2)
#define EHSYM_ISDEFINED(x)   ((x)->object!=NULL && (x)->state==EH_SYM_DEFINED)
#define EHSYM_ISZAPPED(x)   ((x)->object!=NULL && (x)->state==EH_SYM_ZAPPED)
#define EHSYM_ISUNDEFINED(x)   ((x)->object == NULL)
#define EHSYM_ISUSED(x)   ((x)->nusers != 0)
#define EHSYM_ISINLINE(x)   ((x)->state == EH_SYM_INLINE)
#define EH_OBJECT_CANBUILD(x)   ((x)->source != NULL && (x)->name != eh_unnamed_object)
#define USE_HASHING

Typedefs

typedef struct EhObject EhObject
typedef struct EhSym EhSym
typedef int(* eh_dump_mappee_t )(EhSym *sym, void *arg)
typedef struct EhDirMapEntree EhDirMapEntree
typedef struct EhDirMap EhDirMap
typedef struct FileList FileList

Enumerations

enum  EhSymState { EH_SYM_UNDEFINED, EH_SYM_DEFINED, EH_SYM_ZAPPED, EH_SYM_INLINE }

Functions

static char * make_relative_pathname (char *buf, char *filename, char *rootdir)
static EhArchiveEhArchiveNew (char *name, char *rootdir)
static EhSourceEhSourceNew (char *name, char **cc_args, char *directory)
static EhObjectEhObjectNewArchiveObject (EhArchive *archive, char *name)
static EhObjectEhObjectNew (char *name, char *rootdir)
static EhObjectEhObjectNewFromSource (EhSource *source)
static char * EhObjectGetFilename (EhObject *object, char *buf)
static EhSymEhSymNewDefined (char *name, EhObject *object)
static EhSymEhSymNewInline (char *name)
static EhSymEhSymNewUndefined (char *name)
static EhSymEhSymNewZapped (char *name, EhObject *object)
static EhSymEhSymNewRandomZap (char *name)
EhSymTableEhSymTableNew (unsigned p_size)
EhSymEhSymTableInsert (EhSymTable *table, EhSym *sym)
EhSymEhSymTableFind (EhSymTable *table, char *name)
static int EhSymTableMap (EhSymTable *table, eh_dump_mappee_t func, void *arg)
static int fixup_mappee (EhSym *sym, void *arg)
static EhObjectEhSymTableObjectFixup (EhSymTable *table, EhObject *o_old, EhObject *o_new)
static char * safe_fgets (char *buf, unsigned size, FILE *fp)
static int EhSymTableSetSymbolState (EhSymTable *table, char *name, EhSymState new_state)
static int EhSymTableFpLoad (EhSymTable *table, FILE *fp)
static int flush_mappee (EhSym *sym, void *arg)
static int flush_compare (const void *ap, const void *bp)
static void EhSourceFpWrite (EhSource *source, FILE *fp)
static int EhSymTableFpDump (EhSymTable *table, FILE *fp)
int eh_process_object (Elf *elf, EhObject *object, EhSymTable *table)
int eh_process_file (char *filename, EhSymTable *table, char *rootdir)
static int eh_dump_unused (EhSym *sym, void *arg)
static void print_dump (EhSymTable *table)
static int eh_summary_mappee (EhSym *sym, void *arg)
static void get_summary (EhSymTable *table, SummaryInfo *info)
static void print_summary (EhSymTable *table)
static EhDirMapEhDirMapNew (void)
static void EhDirMapAddDirectory (EhDirMap *map, char *dirname)
static char * EhDirMapGetLibName (EhDirMap *map, char *name, char *libbuf)
static char * test_for_global (char *buf)
static char * test_for_file (char *foo, char *buf)
static int EhSourceZapFp (EhSource *source, EhSymTable *table, FILE *fpi, FILE *fpo, unsigned verbosity, unsigned cplusplus)
static void print_command (char *command, char **args, unsigned verbosity)
static int do_command (char *label, char **args, unsigned verbosity)
static char * suffix_name (char *s)
static char * base_name (char *s)
static char * file_base_name (char *s)
static int EhSourceCompile (EhSource *source, EhSymTable *table, unsigned verbosity, unsigned do_compile, unsigned do_zap, unsigned do_assem)
static char * EhSourceGetTarget (EhSource *source)
static int EhArchiveUpdate (EhArchive *archive, char *target, char *rootdir, unsigned verbosity)
static int EhObjectRebuild (EhObject *object, EhSymTable *table, unsigned verbosity, char *rootdir)
static int object_nusers_mappee (EhSym *sym, void *arg)
static int recompile_init_mappee (EhSym *sym, void *arg)
static unsigned match_prefs (char *candidate, char **prefs)
static int recompile_compare (const void *ap, const void *bp)
static int do_recompilation (EhSymTable *table, char *gts_file, unsigned max_globals, char **prefs, char **unprefs, char *rootdir, unsigned verbosity)
static FileListfileListFind (FileList *list, char *name)
static FileListfileListAppend (FileList **list_a, char *name)
static unsigned katoi (char *buf)
static void usage (void)
int main (int argc, char **argv)

Variables

static char eh_unnamed_object [] = "<name not known>"
int djw_debug
char * djw_test_name
static char base_name_buf [MAXPATHLEN]
static char target_buf [MAXPATHLEN]
static char ** recompile_compare_prefs
static char ** recompile_compare_unprefs
static FileListo_list

Class Documentation

struct EhArchive

Definition at line 130 of file gtscc.c.

Class Members
char * name
struct EhSource

Definition at line 134 of file gtscc.c.

Class Members
char * as_savefile
char ** cc_args
time_t compile_time
char * directory
char * name
char * target_object
struct EhObject

Definition at line 143 of file gtscc.c.

Collaboration diagram for EhObject:
Class Members
unsigned _needs_unzap
struct EhObject * _recompile
EhArchive * archive
char * name
unsigned nusers
char * pathname
EhSource * source
struct EhSym

Definition at line 160 of file gtscc.c.

Collaboration diagram for EhSym:
Class Members
struct EhSym * _next
char * name
unsigned ngusers
unsigned nlusers
EhObject * object
EhSymState state
struct EhSymTable

Definition at line 187 of file gtscc.c.

Collaboration diagram for EhSymTable:
Class Members
EhSym ** heads
unsigned nentries
unsigned size
struct fixup_info

Definition at line 504 of file gtscc.c.

Collaboration diagram for fixup_info:
Class Members
EhObject * o_new
EhObject * o_old
struct flush_info

Definition at line 766 of file gtscc.c.

Collaboration diagram for flush_info:
Class Members
unsigned index
EhSym ** vector
struct SummaryInfo

Definition at line 1288 of file gtscc.c.

Class Members
unsigned ndeadcode
unsigned ndefined
unsigned ninlined
unsigned nundefined
unsigned nunlinked
unsigned nused
unsigned nzapped
unsigned nzapped_nowused
struct EhDirMapEntree

Definition at line 1371 of file gtscc.c.

Collaboration diagram for EhDirMapEntree:
Class Members
struct EhDirMapEntree * _next
char * dirname
struct EhDirMap

Definition at line 1376 of file gtscc.c.

Collaboration diagram for EhDirMap:
Class Members
EhDirMapEntree * head
struct RecompileInfo

Definition at line 2070 of file gtscc.c.

Collaboration diagram for RecompileInfo:
Class Members
unsigned recompile_count
EhObject * recompile_list
unsigned recompile_wish_count
unsigned unzap_count
unsigned zap_count
struct FileList

Definition at line 2325 of file gtscc.c.

Collaboration diagram for FileList:
Class Members
char * name
struct FileList * next

Define Documentation

#define AR_COMMAND   "ar"

Definition at line 109 of file gtscc.c.

#define AR_OPTIONS   "cr"

Definition at line 110 of file gtscc.c.

#define AS_COMMAND   "gcc"

Definition at line 107 of file gtscc.c.

#define CC_COMMAND   "gcc"

Definition at line 105 of file gtscc.c.

#define CCC_COMMAND   "g++"

Definition at line 106 of file gtscc.c.

Definition at line 91 of file gtscc.c.

#define EH_NEW (   type)    (type*)malloc(sizeof(type))

Definition at line 113 of file gtscc.c.

#define EH_OBJECT_CANBUILD (   x)    ((x)->source != NULL && (x)->name != eh_unnamed_object)

Definition at line 182 of file gtscc.c.

#define EH_TAG_FILE   'F'

Definition at line 118 of file gtscc.c.

Definition at line 119 of file gtscc.c.

Definition at line 121 of file gtscc.c.

Definition at line 122 of file gtscc.c.

#define EH_TAG_ZAPPED   'Z'

Definition at line 120 of file gtscc.c.

#define EHSYM_ISDEFINED (   x)    ((x)->object!=NULL && (x)->state==EH_SYM_DEFINED)

Definition at line 176 of file gtscc.c.

#define EHSYM_ISINLINE (   x)    ((x)->state == EH_SYM_INLINE)

Definition at line 180 of file gtscc.c.

#define EHSYM_ISUNDEFINED (   x)    ((x)->object == NULL)

Definition at line 178 of file gtscc.c.

#define EHSYM_ISUSED (   x)    ((x)->nusers != 0)

Definition at line 179 of file gtscc.c.

#define EHSYM_ISZAPPED (   x)    ((x)->object!=NULL && (x)->state==EH_SYM_ZAPPED)

Definition at line 177 of file gtscc.c.

#define ELFSYM_IS_DEFINED (   x)    ((x).st_shndx != SHN_UNDEF)

Definition at line 93 of file gtscc.c.

#define ELFSYM_IS_UNDEFINED (   x)    ((x).st_shndx == SHN_UNDEF)

Definition at line 94 of file gtscc.c.

#define FALSE   0

Definition at line 116 of file gtscc.c.

Definition at line 104 of file gtscc.c.

#define LD_COMMAND   "g++"

Definition at line 108 of file gtscc.c.

#define TRUE   1

Definition at line 115 of file gtscc.c.

Definition at line 185 of file gtscc.c.

#define VERBOSITY_DEBUG (   x)    ((x) > 1)

Definition at line 125 of file gtscc.c.

#define VERBOSITY_MAJOR (   x)    ((x) > 2)

Definition at line 126 of file gtscc.c.

#define VERBOSITY_USER (   x)    ((x) > 0)

Definition at line 124 of file gtscc.c.


Typedef Documentation

typedef int(* eh_dump_mappee_t)(EhSym *sym, void *arg)

Definition at line 480 of file gtscc.c.

typedef struct EhDirMap EhDirMap
typedef struct EhObject EhObject
typedef struct EhSym EhSym
typedef struct FileList FileList

Enumeration Type Documentation

enum EhSymState
Enumerator:
EH_SYM_UNDEFINED 
EH_SYM_DEFINED 
EH_SYM_ZAPPED 
EH_SYM_INLINE 

Definition at line 153 of file gtscc.c.

             {
       EH_SYM_UNDEFINED,
       EH_SYM_DEFINED,
       EH_SYM_ZAPPED,
       EH_SYM_INLINE /* are treated special - they belong to no file */
} EhSymState;

Function Documentation

static char* base_name ( char *  s) [static]

Definition at line 1619 of file gtscc.c.

{
       char* p;

       if ((p = strrchr(s, '.')) != NULL) {
              memcpy(base_name_buf, s, p - s);
              base_name_buf[p - s] = '\0';
              s = base_name_buf;
       }
       return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_command ( char *  label,
char **  args,
unsigned  verbosity 
) [static]

Definition at line 1573 of file gtscc.c.

{
       int status;
       pid_t child_pid;
       char* file = args[0];

       print_command(label, args, verbosity);

       if ((child_pid = fork()) == -1) {
              fprintf(stderr, "could not fork: ");
              perror(NULL);
              return -1;
       }

       if (child_pid == 0) { /* i am the child */
              if (execvp(file, args) == -1) {
                     fprintf(stderr, "could not exec %s: ", file);
                     perror(NULL);
                     exit(3);
              }
              /*NOTREACHED*/
       }

       if (waitpid(child_pid, &status, 0) == -1) {
              fprintf(stderr, "wait on %s failed: ", file);
              perror(NULL);
              return -1;
       }

       return WEXITSTATUS(status);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_recompilation ( EhSymTable table,
char *  gts_file,
unsigned  max_globals,
char **  prefs,
char **  unprefs,
char *  rootdir,
unsigned  verbosity 
) [static]

Definition at line 2194 of file gtscc.c.

{
       SummaryInfo s_info;
       RecompileInfo info;
       unsigned    size;
       unsigned n;
       EhObject* object;
       EhObject** recompiles;
       unsigned delta;
       int rv;
       unsigned nzaps;
       EhObject dummy; /* just marks the end of the recomp list */
       time_t  eta;

       get_summary(table, &s_info);

       if ((s_info.nused + s_info.ndefined) <= max_globals) {
              if (VERBOSITY_USER(verbosity))
                     fprintf(stderr,
                     "number of globals <= requested max, skipping recompilation\n");
              return 0;
       }

       /* Init recompilation. */
       info.recompile_list = &dummy; /* cannot use NULL, because syms test that */
       info.recompile_count = 0;
       info.recompile_wish_count = 0;
       info.unzap_count = 0;
       info.zap_count = 0;
       EhSymTableMap(table, recompile_init_mappee, (void*)&info);
       size = info.recompile_count;

       recompiles = (EhObject**)malloc(sizeof(EhObject*) * size);

       /* install */
       n = 0;
       for (object = info.recompile_list;
               object != &dummy;
               object = object->_recompile) {
              recompiles[n++] = object;
       }

       /* sort */
       recompile_compare_prefs = prefs;
       recompile_compare_unprefs = unprefs;
       qsort(recompiles, size, sizeof(EhObject*), recompile_compare);

       /*
        *    sorted !
        *    less recompile the first n, n = ndefined - max
        */
       delta = (s_info.nused + s_info.ndefined) - max_globals;

       if (delta > info.zap_count) {
              fprintf(stderr,
                            "WARNING: there too many globals (%d/%d fixables).\n"
                            "         I don't think I can fix this, but I'll try.\n"
                            "         You might get lucky.\n",
                            info.zap_count,
                            delta);
       }

       if (VERBOSITY_USER(verbosity))
              fprintf(stderr, "scheduling recompilation targets:\n");

       eta = 0;
       for (n = 0; n < size; n++) {
              char* cname = "unknown";
              object = recompiles[n];
              if (object->source != NULL) {
                     cname = object->source->name;
                     eta += object->source->compile_time;
              }
              
              if (VERBOSITY_DEBUG(verbosity))
                     fprintf(stderr, "object %s from source %s\n", object->name, cname);
       }

#if 0
       if (VERBOSITY_USER(verbosity))
#endif
              fprintf(stderr, "gts-ing %d symbols, eta = %d minutes\n", delta,
                            eta/(60*1000));

       if (gts_file != NULL) {
              FILE* zap_fp;
              if ((zap_fp = fopen(gts_file, "w")) == NULL) {
                     perror(0);
                     fprintf(stderr,
                                   "WARNING: could not open the gtscc db file %s.\n"
                                   "         I will continue with the recompilation, but\n"
                                   "         if you recompile any of the files I touched\n"
                                   "         I'll have to recompile them after you!\n",
                                   gts_file);
              } else {
              
                     EhSymTableFpDump(table, zap_fp);
                     
                     fclose(zap_fp);
              }
       }

       for (n = 0, nzaps = 0; n < size && nzaps < delta; n++) {

              object = recompiles[n];
              rv = EhObjectRebuild(object, table, verbosity, rootdir);

              if (rv == -1)
                     return -1;

              nzaps += rv;

              object->_recompile = NULL; /* clean up now */
       }

       if (nzaps < delta) {
              fprintf(stderr,
                            "WARNING: I wanted to gts %d symbols, but only managed\n"
                            "         to get %d of them.\n"
                            "         Your link may fail with GOT errors.\n",
                            delta,
                            nzaps);
       }
       
       free(recompiles);

       return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eh_dump_unused ( EhSym sym,
void arg 
) [static]

Definition at line 1251 of file gtscc.c.

{
       char buf[MAXPATHLEN];

       printf(/*"0x%x "*/ "%s %d %d ", /*sym,*/
                 sym->name, sym->ngusers, sym->nlusers);

       if (EHSYM_ISINLINE(sym))
              printf("%c ", EH_TAG_INLINE);
       else if (EHSYM_ISZAPPED(sym))
              printf("%c ", EH_TAG_ZAPPED);
       else if (EHSYM_ISDEFINED(sym))
              printf("%c ", EH_TAG_GLOBAL);
       else
              printf("%c ", EH_TAG_UNDEFINED);

       if (sym->object != NULL) {
              printf("%s ", EhObjectGetFilename(sym->object, buf));
              if (sym->object->source != NULL) {
                     printf("%s recompilable\n", sym->object->source->name);
              } else {
                     printf("nosource notrecompilable\n");
              }
       } else {
              printf("noobject nosource notrecompilable\n");
       }
       
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int eh_process_file ( char *  filename,
EhSymTable table,
char *  rootdir 
)

Definition at line 1162 of file gtscc.c.

{
       Elf* elf;
       Elf* arf;
       int  fd;
       Elf_Cmd cmd;
       Elf_Kind e_kind;
       EhObject* object;
       EhArchive* archive;
       Elf_Arhdr* arhdr;
       char* name;
       int   rv = 0;

       if ((fd = open(filename, O_RDONLY)) == -1) {
              fprintf(stderr, "error opening %s\n", filename);
              return -1;
       }

       elf_version(EV_CURRENT);
       if ((arf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
              return -1;
       }

       e_kind = elf_kind(arf);
       if (e_kind == ELF_K_ELF) {
              object = EhObjectNew(filename, rootdir);
              rv = eh_process_object(arf, object, table);
              
       } else if (e_kind == ELF_K_AR) {

              archive = EhArchiveNew(filename, rootdir);
              cmd = ELF_C_READ;

#if 0
              arsyms = elf_getarsym(arf, &narsyms);

              for (i = 0; i < narsyms && arsyms[i].as_name != NULL; i++) {
                     printf("%s - %d\n", arsyms[i].as_name, arsyms[i].as_off);
              }

              arhdr = elf_getarhdr(arf);
              for (i = 0; arhdr[i].ar_rawname != NULL; i++) {

                     if (arhdr[i].ar_name != NULL)
                            printf("%s\n", arhdr[i].ar_name);
                     else
                            printf("[%s]\n", arhdr[i].ar_rawname);
              }
#endif

              rv = 0;

              while ((elf = elf_begin(fd, cmd, arf)) != 0) {

                     e_kind = elf_kind(elf);

                     if (e_kind != ELF_K_ELF)
                            continue;

                     arhdr = elf_getarhdr(elf);

                     if (arhdr != NULL) {
                            if (arhdr->ar_name != NULL)
                                   name = arhdr->ar_name;
                            else
                                   name = arhdr->ar_rawname;
                     } else {
                            name = eh_unnamed_object;
                     }

                     object = EhObjectNewArchiveObject(archive, name);
                     rv = eh_process_object(elf, object, table);

                     if (rv == -1)
                            break;

                     cmd = elf_next(elf);
                     elf_end(elf);
              }
       }

       elf_end(arf);

       close(fd);

       return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int eh_process_object ( Elf *  elf,
EhObject object,
EhSymTable table 
)

Definition at line 926 of file gtscc.c.

{
       Elf32_Shdr *   shdr;
       Elf32_Ehdr *   ehdr;
       Elf_Scn * scn;
       Elf_Data *     shstr_data;
       Elf_Data*      sym_data = NULL;
       Elf_Data*      str_data = NULL;
       Elf_Data*      rel_data[4];
       int            nrel_data = 0;
       Elf32_Rel*     rel_entries;
       Elf_Data*      rela_data[10];
       int            nrela_data = 0;
       Elf32_Rela*    rela_entries;
       unsigned int   cnt;
       Elf32_Sym* elf_sym;
       int i;
       int j;
       int k;
       char*  name;
       EhSym* sym;
       char buf[MAXPATHLEN];

       /* Obtain the .shstrtab data buffer */
       if (((ehdr = elf32_getehdr(elf)) == NULL) ||
              ((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) ||
              ((shstr_data = elf_getdata(scn, NULL)) == NULL)) {
              fprintf(stderr, "problems on %s\n", EhObjectGetFilename(object, buf));
              return -1;
       }

       /* get the string table */
       for (cnt = 1, scn = NULL; (scn = elf_nextscn(elf, scn)); cnt++) {
              if ((shdr = elf32_getshdr(scn)) == NULL) {
                     fprintf(stderr, "problems on %s, section %d\n",
                                   EhObjectGetFilename(object, buf), cnt);
                     return -1;
              }

#if 0
              fprintf(stderr, "%s: section %d type %d name %s\n",
                            EhObjectGetFilename(object, buf),
                            cnt,
                            shdr->sh_type,
                            (char*)shstr_data->d_buf + shdr->sh_name);
#endif

              /*
               *    Get the string table.
               */
              if (shdr->sh_type == SHT_STRTAB &&
#ifdef sun
                     strcmp((char*)shstr_data->d_buf + shdr->sh_name, ".strtab") == 0 &&
#endif
                     cnt != ehdr->e_shstrndx) {
                     if (str_data != NULL) {
                            fprintf(stderr, "multiple string tables for %s - bailing\n",
                                          EhObjectGetFilename(object, buf));
                            return -1;
                     }
                     str_data = elf_getdata(scn, NULL);
              } else if (shdr->sh_type == SHT_SYMTAB) { /* look into sym table */
                     if (sym_data != NULL) {
                            fprintf(stderr, "multiple symbol tables for %s - bailing\n",
                                          EhObjectGetFilename(object, buf));
                            return -1;
                     }
                     sym_data = elf_getdata(scn, NULL);
              } else if (shdr->sh_type == SHT_REL) { /* look into rel table */
                     if (nrel_data >= 4) {
                            fprintf(stderr, "too many relocation tables for %s bailing\n",
                                          EhObjectGetFilename(object, buf));
                            return -1;
                     }
                     rel_data[nrel_data++] = elf_getdata(scn, NULL);
              } else if (shdr->sh_type == SHT_RELA) { /* look into rela table */
                     if (nrela_data >= 10) {
                            fprintf(stderr, "too many RELA tables for %s bailing\n",
                                          EhObjectGetFilename(object, buf));
                            return -1;
                     }
                     rela_data[nrela_data++] = elf_getdata(scn, NULL);
              }
       }

       if (sym_data == NULL) {
              fprintf(stderr, "could not load sym table for %s\n",
                            EhObjectGetFilename(object, buf));
              return -1;
       }

       if (str_data == NULL) {
              fprintf(stderr, "could not load string table for %s\n",
                            EhObjectGetFilename(object, buf));
              return -1;
       }

       elf_sym = (Elf32_Sym*)sym_data->d_buf;

       for (i = 0; i < (sym_data->d_size/sizeof(Elf32_Sym)); i++) {

              /*
               *    We are only interested in globals.
               */
              if (ELF32_ST_BIND(elf_sym[i].st_info) != STB_GLOBAL)
                     continue;
              
              name = (char *)str_data->d_buf + elf_sym[i].st_name;
              
              if (djw_test_name != NULL
                     && strcmp(djw_test_name, name) == 0) {
                     printf("found %s\n", name);
              }
              
              sym = EhSymTableFind(table, name);
              
              /*
               *    Treat inlines as non-globals
               */
              if (sym != NULL && sym->state == EH_SYM_INLINE)
                     continue;
              
#if 0
              printf("name = %s value = %d type = %d, info = %d,"
                        " other = %d, size = %d\n",
                        name,
                        elf_sym[i].st_value,
                        ELF32_ST_TYPE(elf_sym[i].st_info),
                        elf_sym[i].st_info,
                        elf_sym[i].st_other,
                        elf_sym[i].st_size);
#endif
              
              /* defined */
              if (ELFSYM_IS_DEFINED(elf_sym[i])) {
                     
                     if (sym != NULL) {
                            
                            if (sym->object == NULL) { /* object undefined */
                                   sym->object = object;
                            } else if (sym->object->name==eh_unnamed_object) {
                                   
                                   if (object->source != NULL
                                          &&
                                          object->source != sym->object->source) {
                                          
                                          fprintf(stderr,
                                                        "warning: symbol %s defined in more than one source file\n"
                                                        "last time: %s\n"
                                                        "this time: %s (ignored)\n",
                                                        sym->name,
                                                        object->source->name,
                                                        sym->object->source->name);
                                   } else {
                                          object->source = sym->object->source;
                                          /*
                                           *    Do a global: sym->object = object;
                                           */
                                          EhSymTableObjectFixup(table,
                                                                               sym->object, /*old*/
                                                                               object); /*new*/
                                          
                                   }
                                   
                            } else if (sym->object != object) {
                                   fprintf(stderr,
                                                 "warning: symbol %s define in multiple object files\n"
                                                 "last time: %s\n"
                                                 "this time: %s (ignored)\n",
                                                 sym->name,
                                                 object->name,
                                                 sym->object->name);
                            }
                            
                            sym->state = EH_SYM_DEFINED;

                     } else {
                            sym = EhSymNewDefined(name, object);
                            EhSymTableInsert(table, sym);
                     }                           

               for (k = 0; k < nrel_data; k++) {
                            int nentries = rel_data[k]->d_size/sizeof(Elf32_Rel);

                            rel_entries = (Elf32_Rel*)rel_data[k]->d_buf;
                            
                            for (j = 0; j < nentries; j++) {
                                   if (ELF32_R_SYM(rel_entries[j].r_info) == i) {
                                          /* locally referenced */
                                          sym->nlusers++;
                                   }
                            }
                     }
               for (k = 0; k < nrela_data; k++) {
                            int nentries = rela_data[k]->d_size/sizeof(Elf32_Rela);

                            rela_entries = (Elf32_Rela*)rela_data[k]->d_buf;
                            
                            for (j = 0; j < nentries; j++) {
                                   if (ELF32_R_SYM(rela_entries[j].r_info) == i) {
                                          /* locally referenced */
                                          sym->nlusers++;
                                   }
                            }
                     }
              }  
              
              /* Undefined. */
              else if (ELFSYM_IS_UNDEFINED(elf_sym[i])) {
                     
                     if (sym == NULL) {
                            sym = EhSymNewUndefined(name);
                            EhSymTableInsert(table, sym);
                     }
                     sym->ngusers++;
              } else {
                     
#if 1
                     printf("what is this: "
                               "name = %s value = %d type = %d, "
                               "info = %d, other = %d, size = %d\n",
                               name,
                               elf_sym[i].st_value,
                               ELF32_ST_TYPE(elf_sym[i].st_info),
                               elf_sym[i].st_info,
                               elf_sym[i].st_other,
                               elf_sym[i].st_size);
#endif
                     ;
              }/* type ==... */
       } /* for each symbol */

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int eh_summary_mappee ( EhSym sym,
void arg 
) [static]

Definition at line 1300 of file gtscc.c.

                                         {
       SummaryInfo* info = (SummaryInfo*)arg;

       if (EHSYM_ISDEFINED(sym)) {
              if (sym->ngusers != 0)
                     info->nused++;
              else if (sym->object != NULL && sym->object->nusers == 0)
                     info->nunlinked++;
              else if (sym->nlusers != 0)
                     info->ndefined++;
              else
                     info->ndeadcode++;
                     
       } else if (EHSYM_ISZAPPED(sym)) { /* one of ours */
              if (sym->ngusers != 0)
                     info->nzapped_nowused++;
              else
                     info->nzapped++;
       } else if (EHSYM_ISINLINE(sym)) { /* one of ours */
              info->ninlined++;
       } else {
              info->nundefined++;
       }

       return 0;
}

Here is the caller graph for this function:

static EhArchive* EhArchiveNew ( char *  name,
char *  rootdir 
) [static]

Definition at line 243 of file gtscc.c.

{
       EhArchive* archive = EH_NEW(EhArchive);
       char pathbuf[MAXPATHLEN];

       make_relative_pathname(pathbuf, name, rootdir);

       archive->name = strdup(pathbuf);

       return archive;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhArchiveUpdate ( EhArchive archive,
char *  target,
char *  rootdir,
unsigned  verbosity 
) [static]

Definition at line 1916 of file gtscc.c.

{
       char* args[8];
       unsigned nargs;
       int status;
       char pathname[MAXPATHLEN];

       pathname[0] = '\0';
       if (rootdir != NULL) {
              strcat(pathname, rootdir);
              strcat(pathname, "/");
       }
       strcat(pathname, archive->name);

#if 0
       nargs = 0;
       args[nargs++] = AR_COMMAND;
       args[nargs++] = "dc";
       args[nargs++] = pathname;
       args[nargs++] = target;
       args[nargs++] = NULL;
       
       if ((status = do_command("delete from archive", args, verbosity)) != 0) {
              fprintf(stderr, "archive: %s delete %s failed (status = %d)\n",
                            pathname,
                            target);
              return -1;
       }
#endif

       nargs = 0;
       args[nargs++] = AR_COMMAND;
       args[nargs++] = AR_OPTIONS;
       args[nargs++] = pathname;
       args[nargs++] = target;
       args[nargs++] = NULL;
       
       if ((status = do_command("archive", args, verbosity)) != 0) {
              fprintf(stderr, "archive: %s <- %s failed (status = %d)\n",
                            pathname,
                            target);
              return -1;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void EhDirMapAddDirectory ( EhDirMap map,
char *  dirname 
) [static]

Definition at line 1389 of file gtscc.c.

{
       EhDirMapEntree* entree = EH_NEW(EhDirMapEntree);
       EhDirMapEntree* foo;

       entree->dirname = strdup(dirname);
       entree->_next = NULL;

       if (map->head == NULL) {
              map->head = entree;
       } else {
              for (foo = map->head; foo->_next != NULL; foo = foo->_next)
                     ;

              foo->_next = entree;
       }
}

Here is the caller graph for this function:

static char* EhDirMapGetLibName ( EhDirMap map,
char *  name,
char *  libbuf 
) [static]

Definition at line 1408 of file gtscc.c.

{
       EhDirMapEntree* foo;
       struct stat     buf;

       for (foo = map->head; foo != NULL; foo = foo->_next) {
              sprintf(libbuf, "%s/lib%s.a", foo->dirname, name);

              if (stat(libbuf, &buf) != -1)
                     return libbuf;
       }

       return NULL;
}

Here is the caller graph for this function:

static EhDirMap* EhDirMapNew ( void  ) [static]

Definition at line 1381 of file gtscc.c.

{
       EhDirMap* dm = EH_NEW(EhDirMap);
       dm->head = NULL;
       return dm;
}

Here is the caller graph for this function:

static char* EhObjectGetFilename ( EhObject object,
char *  buf 
) [static]

Definition at line 356 of file gtscc.c.

{
       if (object->archive) {
              strcpy(buf, object->archive->name);
              strcat(buf, ":");
              strcat(buf, object->name);
              return buf;
       } else {
              return object->name;
       }
}

Here is the caller graph for this function:

static EhObject* EhObjectNew ( char *  name,
char *  rootdir 
) [static]

Definition at line 334 of file gtscc.c.

{
       EhObject* object = EhObjectNewArchiveObject(NULL, name);
       char pathname[MAXPATHLEN];

       make_relative_pathname(pathname, name, rootdir);
       object->pathname = strdup(pathname);

       return object;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhObject* EhObjectNewArchiveObject ( EhArchive archive,
char *  name 
) [static]

Definition at line 315 of file gtscc.c.

{
       EhObject* object = EH_NEW(EhObject);

       if (name == eh_unnamed_object)
              object->name = name;
       else
              object->name = strdup(name);
       object->archive = archive;
       object->source = NULL;
       object->_recompile = NULL;
       object->_needs_unzap = 0;
       object->pathname = NULL;
       object->nusers = 0;

       return object;
}

Here is the caller graph for this function:

static EhObject* EhObjectNewFromSource ( EhSource source) [static]

Definition at line 346 of file gtscc.c.

{
       EhObject* object = EhObjectNewArchiveObject(NULL, eh_unnamed_object);

       object->source = source;

       return object;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhObjectRebuild ( EhObject object,
EhSymTable table,
unsigned  verbosity,
char *  rootdir 
) [static]

Definition at line 1965 of file gtscc.c.

{
       EhSource* source = object->source;
       char  cwd[MAXPATHLEN];
       char  fullpath[MAXPATHLEN];
       int   rv = 0;
       int   do_chdir = 0;

       if (!source) {
              fprintf(stderr,
                            "wanted to recompile %s, but I don't how\n",
                            object->name);
              return -1;
       }
       
#if 0
       if (VERBOSITY_USER(verbosity))
#endif
              fprintf(stderr, "recompiling %s\n", source->name);
       
       /*
        *    Check to see if we need to chdir
        */
       if (source->directory != NULL) {
              if (getcwd(cwd, sizeof(cwd)) == NULL) {
                     fprintf(stderr, "cannot get pwd: cannot compile\n");
                     return -1;
              }
              
              make_relative_pathname(fullpath, cwd, rootdir);
              
              if (strcmp(fullpath, source->directory) != 0) {
                     fullpath[0] = '\0';
                     if (rootdir != NULL) {
                            strcat(fullpath, rootdir);
                            strcat(fullpath, "/");
                     }
                     strcat(fullpath, source->directory);

                     if (chdir(fullpath) == -1) {
                            fprintf(stderr, "cannot chdir - can't compile\n");
                            return -1;
                     }
                     do_chdir++;
              }
       }

       rv = EhSourceCompile(source,
                                           table,
                                           verbosity,
                                           TRUE,  /* compile  */
                                           2,     /* do zap   */
                                           TRUE); /* do assem */

       if (do_chdir) {
              if (chdir(cwd) == -1) {
                     fprintf(stderr, "cannot chdir - this will be very confused\n");
                     return -1;
              }
       }

       if (rv == -1) {
              fprintf(stderr, "recompiling %s failed\n",  source->name);
              return -1;
       }
       
       /* do archive */
       fullpath[0] = '\0';
       if (rootdir != NULL) {
              strcat(fullpath, rootdir);
              strcat(fullpath, "/");
       }

       if (source->directory != NULL)
              strcat(fullpath, source->directory);

       strcat(fullpath, "/");
       strcat(fullpath, EhSourceGetTarget(source));
       
       if (object->archive != NULL) {
              if (EhArchiveUpdate(object->archive, fullpath, rootdir,
                                                 verbosity) == -1)
                     return -1;
       }

       /* do install */
#if 0
       if (rv != -1) {
       }
#endif

       return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhSourceCompile ( EhSource source,
EhSymTable table,
unsigned  verbosity,
unsigned  do_compile,
unsigned  do_zap,
unsigned  do_assem 
) [static]

Definition at line 1644 of file gtscc.c.

{
       char* filename = source->name;
       char** opts = source->cc_args;
       char asname[MAXPATHLEN];
       char o_asname[MAXPATHLEN];
       char* cc_opts[256];
       unsigned i = 0;
       unsigned j = 0;
       FILE* in_fp;
       FILE* out_fp;
       int   status;
       int nzap = 0;
       char* save_prefix = NULL;
       unsigned do_dash_s = (do_zap != 0 || save_prefix != NULL);
       char* cc_command;
       char* use_savefile = NULL;
       struct timeval start_time;
       struct timeval end_time;
#ifdef DEBUG_djw
       char savebuf[1024];
#endif
       unsigned is_cplusplus = 0;

#ifdef LINUX
       gettimeofday(&start_time,NULL);
#else
       gettimeofday(&start_time);
#endif

       /* munge file */
#ifdef HANDLES_DASHSO
       if (source->target_object != NULL)
              strcpy(asname, base_name(source->target_object));
       else
#endif
              strcpy(asname, file_base_name(filename));
       strcat(asname, ".s");

       strcpy(o_asname, asname);
       strcat(o_asname, ".gts_tmp");

       if (strcmp(suffix_name(filename), ".cpp") == 0) {
              cc_command = CCC_COMMAND;
              is_cplusplus = 1;
       } else if (strcmp(suffix_name(filename), ".s") == 0) {
              do_compile = FALSE;
              cc_command = CC_COMMAND;
       } else {
              cc_command = CC_COMMAND;
       }

       if (do_compile) {

              j = 0;
              cc_opts[j++] = cc_command;
              cc_opts[j++] = "-c";

              if (do_dash_s) {
                     cc_opts[j++] = "-S";
#ifdef HANDLES_DASHSO
                     if (source->target_object != NULL) {
                            cc_opts[j++] = "-o";
                            cc_opts[j++] = asname;
                     }
#endif
              } else if (source->target_object != NULL) {
                     cc_opts[j++] = "-o";
                     cc_opts[j++] = source->target_object;
              }
              
              i = 0;
              while (opts[i] != NULL)
                     cc_opts[j++] = opts[i++];
              
              cc_opts[j++] = filename;
              cc_opts[j] = NULL;
              
              if ((status = do_command("compile", cc_opts, verbosity)) != 0) {
                     fprintf(stderr, "compile failed (returned %d)\n", status);
                     return -1;
              }

              if (!do_dash_s)
                     return 0;
       }

       /*
        *    Now we have a foo.s file, what do we do with it?
        */
       if (do_zap > 1) {

              if (use_savefile == NULL)
                     use_savefile = asname;

              if ((in_fp = fopen(use_savefile, "r")) == NULL) {
                     fprintf(stderr, "could not open %s for reading\n", asname);
                     return -1;
              }
       
              if ((out_fp = fopen(o_asname, "w")) == NULL) {
                     fprintf(stderr, "could not open %s for writing\n", o_asname);
                     return -1;
              }
       
              j = 0;
              cc_opts[j++] = "gts";
              cc_opts[j++] = asname;
              cc_opts[j++] = o_asname;
              cc_opts[j++] = NULL;
              print_command("gts", cc_opts, verbosity);

              nzap = EhSourceZapFp(source, table, in_fp, out_fp, verbosity, is_cplusplus);

              fclose(in_fp);
              fclose(out_fp);

              j = 0;
              cc_opts[j++] = "rename";
              cc_opts[j++] = o_asname;
              cc_opts[j++] = asname;
              cc_opts[j++] = NULL;
              print_command("rename", cc_opts, verbosity);

#ifdef DEBUG_djw
              strcpy(savebuf, "gts_pre_");
              strcat(savebuf, asname);
              rename(asname, savebuf);
#endif

              if (rename(o_asname, asname) == -1) {
                     fprintf(stderr, "could not rename %s\n", o_asname);
                     return -1;
              }

       } else if (do_zap > 0) { /* audit only */

              if ((in_fp = fopen(asname, "r")) == NULL) {
                     fprintf(stderr, "could not open %s for reading\n", asname);
                     return -1;
              }
       
              j = 0;
              cc_opts[j++] = "audit";
              cc_opts[j++] = asname;
              cc_opts[j++] = NULL;
              print_command("audit", cc_opts, verbosity);

              nzap = EhSourceZapFp(source, table, in_fp, NULL, verbosity, is_cplusplus);

              fclose(in_fp);
       }

       if (do_assem) {
              i = 0;
              j = 0;
              cc_opts[j++] = AS_COMMAND;
              cc_opts[j++] = "-c";

              if (source->target_object != NULL) {
                     cc_opts[j++] = "-o";
                     cc_opts[j++] = source->target_object;
              }

              while (opts[i] != NULL)
                     cc_opts[j++] = opts[i++];

              cc_opts[j++] = asname;
              cc_opts[j] = NULL;

              if ((status = do_command("assemble", cc_opts, verbosity)) != 0) {

                     unlink(asname);

                     fprintf(stderr,
                            "gtscc of %s failed (exit status = %d), reverting to %s:\n",
                                   filename,
                                   status,
                                   cc_command);
                     
                     i = 0;
                     j = 0;
                     cc_opts[j++] = cc_command;
                     cc_opts[j++] = "-c";

                     if (source->target_object != NULL) {
                            cc_opts[j++] = "-o";
                            cc_opts[j++] = source->target_object;
                     }

                     for (; opts[i]; i++, j++)
                            cc_opts[j] = opts[i];
                     
                     cc_opts[j++] = filename;
                     cc_opts[j] = NULL;
                     
                     if ((status = do_command("fix-compile", cc_opts, verbosity)) != 0)
                            return -1;

                     return 0;
              }
       }

       if (save_prefix != NULL && save_prefix[0] != '\0') {

              sprintf(o_asname, save_prefix, file_base_name(filename));

              j = 0;
              cc_opts[j++] = "rename";
              cc_opts[j++] = asname;
              cc_opts[j++] = o_asname;
              cc_opts[j++] = NULL;
              print_command("savefile", cc_opts, verbosity);

              if (rename(asname, o_asname) == -1) {
                     fprintf(stderr, "could not rename %s to %s - sorry\n",
                                   asname, o_asname);
                     return -1;
              }

              if (source->as_savefile != NULL)
                     free(source->as_savefile);
              source->as_savefile = strdup(o_asname);
       } else {

              j = 0;
              cc_opts[j++] = "unlink";
              cc_opts[j++] = asname;
              cc_opts[j++] = NULL;
              print_command("unlink", cc_opts, verbosity);

#ifdef DEBUG_djw
              strcpy(savebuf, "gts_post_");
              strcat(savebuf, asname);
              rename(asname, savebuf);
#else
              unlink(asname);
#endif
       }

#ifdef LINUX
       gettimeofday(&end_time,NULL);
#else
       gettimeofday(&end_time);
#endif

       source->compile_time = ((end_time.tv_sec - start_time.tv_sec) * 1000) +
                           ((end_time.tv_usec - start_time.tv_usec) / 1000);

       return nzap;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void EhSourceFpWrite ( EhSource source,
FILE fp 
) [static]

Definition at line 832 of file gtscc.c.

{
       unsigned n = 0;

       fputs(source->name, fp);
       fputc(' ', fp);
       fputc(EH_TAG_FILE, fp);

       fputc(' ', fp);
       if (source->directory != NULL)
              fprintf(fp, "%s", source->directory);
       else
              fputc('.', fp);
       
       fputc(' ', fp);
       if (source->as_savefile != NULL)
              fprintf(fp, "%s", source->as_savefile);
       else
              fputc('.', fp);
       
       fputc(' ', fp);
       fprintf(fp, "%d", source->compile_time);

       if (source->target_object != NULL) {
              fputs(" -o ", fp);
              fputs(source->target_object, fp);
       }
       
       if (source->cc_args != NULL) {
              for (n = 0; source->cc_args[n] != NULL; n++) {
                     fputc(' ', fp);
                     fputs(source->cc_args[n], fp);
              }
       }

       if (n < 1)
              fprintf(stderr, "WARNING: %s has no args\n", source->name);

       fputc('\n', fp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* EhSourceGetTarget ( EhSource source) [static]

Definition at line 1904 of file gtscc.c.

{
       if (source->target_object != NULL)
              return source->target_object;

       strcpy(target_buf, base_name(source->name));
       strcat(target_buf, ".o");

       return target_buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhSource* EhSourceNew ( char *  name,
char **  cc_args,
char *  directory 
) [static]

Definition at line 279 of file gtscc.c.

{
       EhSource* source = EH_NEW(EhSource);
       unsigned n;
       unsigned m;

       source->name = strdup(name);
       source->directory = (directory != NULL)? strdup(directory): NULL;
       source->as_savefile = NULL;
       source->compile_time = 0;
       source->target_object = NULL;
       source->cc_args = NULL;

       if (cc_args != NULL) {

              for (n = 0; cc_args[n] != NULL; n++)
                     ;

              source->cc_args = (char**)malloc(sizeof(char*) * (n+1));

              for (m = 0, n = 0; cc_args[n] != NULL;) {
                     if (strcmp(cc_args[n], "-o") == 0 && cc_args[n+1] != NULL) {
                            source->target_object = strdup(cc_args[n+1]);
                            n += 2;
                     } else {
                            source->cc_args[m++] =  strdup(cc_args[n++]);
                     }
              }

              source->cc_args[m] = NULL;
       }

       return source;
}

Here is the caller graph for this function:

static int EhSourceZapFp ( EhSource source,
EhSymTable table,
FILE fpi,
FILE fpo,
unsigned  verbosity,
unsigned  cplusplus 
) [static]

Definition at line 1462 of file gtscc.c.

{
       char*     buf = NULL;
       char*     p;
       int       nzap = 0;
       char*     name;
       EhSym*    sym;
       int       i_zapped;
       EhObject* object = EhObjectNewFromSource(source);
       char*     filename = source->name;
       char*     tmp_name;
       char      foo[256];
       unsigned  line_n = 0;

       if (VERBOSITY_DEBUG(verbosity))
              fputs("gts: ", stderr);

       while ((buf = safe_fgets(buf, 4192, fpi)) != NULL) {

              i_zapped = 0;
              for (p = buf; *p != '\0' && *p != '\n'; p++)
                     ;
              *p = '\0';

              if ((tmp_name = test_for_file(foo, buf)) != NULL) {
                     if (strcmp(tmp_name, filename) != 0) /* not the same file */
                            filename = "non local file";
                     else
                            filename = source->name;
              }

              else if ((name = test_for_global(buf)) != NULL) {

                     sym = EhSymTableFind(table, name);

                     /* an inline, we have to treat specially */
                     if ((filename != source->name && cplusplus != 0) /* inline now */
                            ||
                            (sym != NULL && sym->state == EH_SYM_INLINE)) {/* was inline */

                            if (!sym) { 

                                   sym = EhSymNewInline(name);
                                   
                                   EhSymTableInsert(table, sym);
                            }
                            sym->state = EH_SYM_INLINE; /* just make sure */

                            if (fpo != NULL) /* always zap inlines we see */
                                   fputs(" # gts", fpo);

                     } else { /* a real global */

                            if (fpo != NULL && sym != NULL && EHSYM_ISZAPPED(sym)) {
                                   if (VERBOSITY_DEBUG(verbosity)) {
                                          fprintf(stderr, "%s ", &buf[8]);
                                   }
                                   nzap++;

                                   if (fpo != NULL)
                                          fputs(" # gts", fpo);
                            }

                            if (sym != NULL) {
                                   if (sym->object == NULL) {
                                          sym->object = object;
                                   } else if (sym->object != object) {
                                          sym->object->source = source;
                                          EhSymTableObjectFixup(table, object, sym->object);
                                          object = sym->object;
                                   }
                            } else { /* install a new one */
                                   
                                   sym = EhSymNewDefined(name, object);
                                   
                                   EhSymTableInsert(table, sym);
                            }

                     }
              }

              if (fpo != NULL) {
                     fputs(buf, fpo);
                     fputc('\n', fpo);
              }
              line_n++;
       }
       
       if (VERBOSITY_DEBUG(verbosity))
              fputc('\n', stderr);

       return nzap;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhSym* EhSymNewDefined ( char *  name,
EhObject object 
) [static]

Definition at line 369 of file gtscc.c.

{
       EhSym* sym = EH_NEW(EhSym);

       sym->name = strdup(name);
       sym->object = object;
       sym->state = EH_SYM_DEFINED;
       sym->ngusers = 0;
       sym->nlusers = 0;

       return sym;
}

Here is the caller graph for this function:

static EhSym* EhSymNewInline ( char *  name) [static]

Definition at line 383 of file gtscc.c.

{
       EhSym* sym = EhSymNewDefined(name, NULL);
       sym->state = EH_SYM_INLINE;

       return sym;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhSym* EhSymNewRandomZap ( char *  name) [static]

Definition at line 410 of file gtscc.c.

{
       EhSym* sym = EhSymNewZapped(name, NULL);

       return sym;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhSym* EhSymNewUndefined ( char *  name) [static]

Definition at line 392 of file gtscc.c.

{
       EhSym* sym = EhSymNewDefined(name, NULL);
       sym->state = EH_SYM_UNDEFINED;

       return sym;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhSym* EhSymNewZapped ( char *  name,
EhObject object 
) [static]

Definition at line 401 of file gtscc.c.

{
       EhSym* sym = EhSymNewDefined(name, object);
       sym->state = EH_SYM_ZAPPED;

       return sym;
}

Here is the call graph for this function:

Here is the caller graph for this function:

EhSym* EhSymTableFind ( EhSymTable table,
char *  name 
)

Definition at line 458 of file gtscc.c.

{
       EhSym* sym;
       EhSym* head;

#ifdef USE_HASHING
       unsigned long hash = elf_hash(name);
       unsigned long mask = table->size - 1;
       unsigned index = (hash & mask);
       head = table->heads[index];
#else
       head = table->head;
#endif

       for (sym = head; sym != NULL; sym = sym->_next) {
              if (strcmp(name, sym->name) == 0)
                     break;
       }

       return sym;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhSymTableFpDump ( EhSymTable table,
FILE fp 
) [static]

Definition at line 874 of file gtscc.c.

{
       flush_info info;
       unsigned n;
       EhObject* object = NULL;
       EhSym**   syms;
       EhSym*    sym;
       unsigned size;

       info.index = 0;
       info.vector = NULL;
       EhSymTableMap(table, flush_mappee, (void*)&info);
       size = info.index;

       syms = (EhSym**)malloc(sizeof(EhSym*) * size);
       info.index = 0;
       info.vector = syms;
       EhSymTableMap(table, flush_mappee, (void*)&info);

       /* sort */
       qsort(syms, size, sizeof(EhSym*), flush_compare);

       /* dump */
       for (n = 0; n < size; n++) {
              sym = syms[n];

              if (sym->object != object) {
                     object = sym->object;

                     if (object->source != NULL) {
                            EhSourceFpWrite(object->source, fp);
                     }
              }

              if (sym->state == EH_SYM_INLINE) {
                     fprintf(fp, "%s %c\n", sym->name, EH_TAG_INLINE);
              } else if (object->source != NULL && sym->state == EH_SYM_ZAPPED) {
                     fprintf(fp, "%s %c\n", sym->name, EH_TAG_ZAPPED);
              } else if (object->source != NULL && sym->state == EH_SYM_DEFINED) {
                     fprintf(fp, "%s %c\n", sym->name, EH_TAG_GLOBAL);
              }
       }

       free(syms);

       return n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhSymTableFpLoad ( EhSymTable table,
FILE fp 
) [static]

Definition at line 602 of file gtscc.c.

{
       char* buf = NULL; /* I hope this is big enough */
       char* p;
       char* name;
       char* state;
       EhSym* sym;
       EhSource* source = NULL;
       EhObject* object = NULL;
       char* cc_args[512];
       unsigned n;
       unsigned line_n = 0;
       char* ctime = NULL;
       char* directory;
       char* savefile;

       while ((buf = safe_fgets(buf, 1024, fp)) != NULL) {

              if ((p = strchr(buf, '\n')) == NULL) {
                     fprintf(stderr, "line to long: %d\n", line_n);
                     return -1;
              }
              *p = '\0';

              line_n++;

              if (buf[0] == '!') /* comment */
                     continue;

              for (p = buf; isspace(*p); p++)
                     ;

              name = p;
              for (; !isspace(*p); p++)
                     ;
              *p++ = '\0';

              if (name[0] == '\0')
                     continue;
              
              for (; isspace(*p); p++)
                     ;

              state = p;
              for (; !isspace(*p) && *p != '\0'; p++)
                     ;
              *p++ = '\0';

              if (state[0] == EH_TAG_GLOBAL
                     ||
                     state[0] == EH_TAG_ZAPPED
                     ||
                     state[0] == EH_TAG_INLINE) {
                     sym = EhSymTableFind(table, name);
                     if (sym == NULL) { /* install a new one */
                            
                            if (source == NULL && state[0] != EH_TAG_INLINE) {
                                   fprintf(stderr,
                                                 "[%d] found new style symbol (%s) but no source\n",
                                                 line_n, name);
                            }

                            if (state[0] == EH_TAG_GLOBAL)
                                   sym = EhSymNewDefined(name, object);
                            else if (state[0] == EH_TAG_INLINE)
                                   sym = EhSymNewInline(name);
                            else
                                   sym = EhSymNewZapped(name, object);
                            
                            EhSymTableInsert(table, sym);
                     } else {
                            if (state[0] == EH_TAG_GLOBAL) {
                                   if (sym->state != EH_SYM_DEFINED) {
                                          fprintf(stderr,
                                                        "out of sync defined symbol: %s, fixing\n",
                                                        sym->name);
                                          sym->state = EH_SYM_DEFINED;
                                   }
                            } else if (state[0] == EH_TAG_INLINE) {
                                   if (sym->state != EH_SYM_INLINE) {
                                          fprintf(stderr,
                                                        "out of sync inlined symbol: %s, fixing\n",
                                                        sym->name);
                                          sym->state = EH_SYM_INLINE;
                                   }
                            } else {
                                   if (sym->state != EH_SYM_ZAPPED) {
                                          fprintf(stderr,
                                                        "out of sync zapped symbol: %s, fixing\n",
                                                        sym->name);
                                          sym->state = EH_SYM_ZAPPED;
                                   }
                            }

#if 0
                            /* these are probably "special" symbols like .div */
                            if (sym->object != object) {
                                   fprintf(stderr,
                                                 "out of sync object for symbol: %s, ignoring\n",
                                                 sym->name);
                            }
#endif
                     }

                     continue; /* no more fields we care about */
              } else if (state[0] == EH_TAG_FILE) {

                     directory = p;
                     for (; !isspace(*p) && *p != '\0'; p++)
                            ;
                     *p++ = '\0';

                     savefile = p;
                     for (; !isspace(*p) && *p != '\0'; p++)
                            ;
                     *p++ = '\0';

                     ctime = p;
                     for (; !isspace(*p) && *p != '\0'; p++)
                            ;
                     *p++ = '\0';

                     for (n = 0; *p != '\0';) {

                            for (; isspace(*p); p++)
                                   ;
                     
                            cc_args[n++] = p++;
                            
                            for (; !isspace(*p) && *p != '\0'; p++)
                                   ;
                            
                            if (*p == '\0')
                                   break;

                            *p++ = '\0';
                     }
                     cc_args[n] = NULL;

                     if (strcmp(directory, ".") == 0)
                            directory = NULL;
                     source = EhSourceNew(name, cc_args, directory);
                     if (ctime != NULL)
                            source->compile_time = (time_t)atoi(ctime);
                     object = EhObjectNewFromSource(source);

              } else { /* old style symbol list */
                     sym = EhSymTableFind(table, name);
                     if (sym != NULL) {
                            if (sym->state != EH_SYM_ZAPPED) {
                                   fprintf(stderr,
                                                 "out of sync random zapped symbol: %s, fixing\n",
                                                 sym->name);
                                   sym->state = EH_SYM_ZAPPED;
                            }
                     } else {
                            sym = EhSymNewRandomZap(name);
                     }
              }
       }

       return line_n;
}

Here is the call graph for this function:

Here is the caller graph for this function:

EhSym* EhSymTableInsert ( EhSymTable table,
EhSym sym 
)

Definition at line 439 of file gtscc.c.

{
#ifdef USE_HASHING
       unsigned long hash = elf_hash(sym->name);
       unsigned long mask = table->size - 1;
       unsigned index = (hash & mask);

       sym->_next = table->heads[index];
       table->heads[index] = sym;
#else
       sym->_next = table->head;
       table->head = sym;
#endif
       table->nentries++;

       return sym;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhSymTableMap ( EhSymTable table,
eh_dump_mappee_t  func,
void arg 
) [static]

Definition at line 483 of file gtscc.c.

{
       EhSym* sym;
       EhSym* head;

#ifdef USE_HASHING
       unsigned n;
       for (n = 0; n < table->size; n++) {
              head = table->heads[n];
#else
              head = table->head; {
#endif
              for (sym = head; sym != NULL; sym = sym->_next) {
                     if ((func)(sym, arg) == -1)
                            return -1;
              }
       }

       return 0;
}

Here is the caller graph for this function:

EhSymTable* EhSymTableNew ( unsigned  p_size)

Definition at line 418 of file gtscc.c.

{
       EhSymTable* table = EH_NEW(EhSymTable);

#ifdef USE_HASHING
       unsigned size;
       for (size = 0x1; size < (16*1024); size <<= 1) {
              if (size >= p_size)
                     break;
       }
       table->size = size;
       table->heads = (EhSym**)calloc(size, sizeof(EhSym*));
#else
       table->head = NULL;
#endif
       table->nentries = 0;

       return table;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static EhObject* EhSymTableObjectFixup ( EhSymTable table,
EhObject o_old,
EhObject o_new 
) [static]

Definition at line 521 of file gtscc.c.

{
       fixup_info info;

       /*
        *    Now visit every sym that pointed to tmp, and point it
        *    at object.
        */
       info.o_old = o_old;
       info.o_new = o_new;
       EhSymTableMap(table, fixup_mappee, &info);
       
       return o_new;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int EhSymTableSetSymbolState ( EhSymTable table,
char *  name,
EhSymState  new_state 
) [static]

Definition at line 566 of file gtscc.c.

{
       EhSym* sym = EhSymTableFind(table, name);

       if (sym == NULL) {
              sym = EhSymNewDefined(name, NULL);

              EhSymTableInsert(table, sym);
       }

       /* new_state must be EH_SYM_DEFINED || EH_SYM_ZAPPED */
       if (sym->state == EH_SYM_DEFINED || sym->state == EH_SYM_ZAPPED) {
              sym->state = new_state;
       } else if (sym->state == EH_SYM_INLINE) {
              char* state_name;
              if (new_state == EH_SYM_DEFINED)
                     state_name = "global";
              else
                     state_name = "static";
              fprintf(stderr,
                            "WARNING: Symbol %s is an inline.\n"
                            "         Forcing the symbol %s will be ignored.\n",
                            name,
                            state_name);
       } else { /* EH_SYM_UNDEFINED */
              /*
               *    This call is being made after objects have started being
               *    read. This is too late. I'm not sure I care though.
               */
              return -1;
       }

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* file_base_name ( char *  s) [static]

Definition at line 1632 of file gtscc.c.

{
       char* p;

       s = base_name(s);

       if ((p = strrchr(s, '/')) != NULL)
              s = &p[1];
       
       return s;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static FileList* fileListAppend ( FileList **  list_a,
char *  name 
) [static]

Definition at line 2344 of file gtscc.c.

{
       FileList* list = *list_a;
       FileList* foo;
       FileList* last;

       for (foo = list, last = NULL; foo != NULL; last = foo, foo = foo->next)
              ;

       if (last == NULL) {
              foo = EH_NEW(FileList);
              foo->next = NULL;
              foo->name = strdup(name);
              *list_a = foo;
       } else {
              foo = EH_NEW(FileList);
              foo->next = NULL;
              foo->name = strdup(name);
              last->next = foo;
       }

       return *list_a;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static FileList* fileListFind ( FileList list,
char *  name 
) [static]

Definition at line 2332 of file gtscc.c.

{
       FileList* foo;

       for (foo = list; foo != NULL; foo = foo->next) {
              if (strcmp(name, foo->name) == 0)
                     return foo;
       }
       return NULL;
}

Here is the caller graph for this function:

static int fixup_mappee ( EhSym sym,
void arg 
) [static]

Definition at line 510 of file gtscc.c.

{
       fixup_info* info = (fixup_info*)arg;

       if (sym->object == info->o_old)
              sym->object = info->o_new;

       return 0;
}

Here is the caller graph for this function:

static int flush_compare ( const void ap,
const void bp 
) [static]

Definition at line 790 of file gtscc.c.

{
       EhSym** ax = (EhSym**)ap;
       EhSym** bx = (EhSym**)bp;
       EhSym* a = *ax;
       EhSym* b = *bx;
       EhObject* oa = a->object;
       EhObject* ob = b->object;
       int foo;

       if (oa == NULL && ob != NULL)
              return -1;
       if (oa != NULL && ob == NULL)
              return 1;
       if (oa == NULL && ob == NULL) {
              foo = strcmp(a->name, b->name);
              if (foo < 0)
                     return -1;
              else if (foo > 0)
                     return 1;
              return 0;
       }

       if (oa->source == NULL && ob->source != NULL)
              return -1;
       if (oa->source != NULL && ob->source == NULL)
              return 1;
       if (oa->source == ob->source)
              return 0;
       if (oa->source < ob->source)
              return -1;
       if (oa->source > ob->source)
              return 1;
       foo = strcmp(a->name, b->name);
       if (foo < 0)
              return -1;
       else if (foo > 0)
              return 1;
       return 0;
}

Here is the caller graph for this function:

static int flush_mappee ( EhSym sym,
void arg 
) [static]

Definition at line 772 of file gtscc.c.

{
       flush_info* info = (flush_info*)arg;

       if (sym->state == EH_SYM_INLINE
              ||
              (sym->object != NULL && sym->state == EH_SYM_DEFINED)
              ||
              (sym->object != NULL && sym->state == EH_SYM_ZAPPED)) {
              if (info->vector != NULL)
                     info->vector[info->index] = sym;
              info->index++;
       }

       return 0;
}

Here is the caller graph for this function:

static void get_summary ( EhSymTable table,
SummaryInfo info 
) [static]

Definition at line 1328 of file gtscc.c.

{
       info->ndefined = 0;
       info->nused = 0;
       info->nundefined = 0;
       info->nzapped = 0;
       info->nzapped_nowused = 0;
       info->ninlined = 0;
       info->nunlinked = 0;
       info->ndeadcode = 0;
       
       EhSymTableMap(table, eh_summary_mappee, info);
} 

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned katoi ( char *  buf) [static]

Definition at line 2419 of file gtscc.c.

{
       unsigned base = 1;
       char* s;
       
       for (s = buf; isdigit(*s); s++)
              ;

       if (*s == 'k' || *s == 'K')
              base = 1024;

       *s = '\0';

       return base * atoi(buf);
}

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 2471 of file gtscc.c.

{
       EhSymTable* table = EhSymTableNew(1000);
       EhSym* sym;
       FILE* zap_fp;
       unsigned n = 0;
       unsigned verbosity = 0;
       char* arg_buf[256];
       unsigned nargs = 0;
       EhDirMap*   dmap = EhDirMapNew();
       unsigned do_dump = 0;
       unsigned do_summary = 0;
       unsigned do_link = 1;
       unsigned in_link = 1;
       unsigned do_audit = 1;
       unsigned do_zap = 1;
       unsigned do_assem = 1;
       unsigned do_recompile = 1;
       unsigned do_collect = 1;
       char* name;
       char* saveprefix = NULL;
       char* rootdir = NULL;
       int rv;
       EhSource* source = NULL;
       char* gts_file = NULL;
       char* path_prefs[32];
       unsigned npath_prefs = 0;
       char* path_un_prefs[32];
       unsigned npath_un_prefs = 0;
       char* suffix;
       unsigned max_globals = DEFAULT_MAX_GLOBALS;
       FileList* list;

       if (elf_version(EV_CURRENT) == EV_NONE) {
              fprintf(stderr, "something losing about your elf lib - sorry!\n");
              return 3;
              /* library out of date */
              /* recover from error */
       }

       arg_buf[nargs] = NULL;

       for (n = 1; n < argc; n++) {

              if (strcmp(argv[n], "-help") == 0) {
                     usage();
                     return 0;
              } else if (strcmp(argv[n], "-gtssummary") == 0) {
                     do_summary = 1;
              } else if (strcmp(argv[n], "-gtsdump") == 0) {
                     do_dump = 1;
              } else if (strcmp(argv[n], "-gtsnorecompile") == 0) {
                     do_recompile = 0;
              } else if (strcmp(argv[n], "-gtsnolink") == 0) {
                     do_link = 0;
              } else if (strcmp(argv[n], "-gtsverbose") == 0) {
                     verbosity++;
              } else if (strcmp(argv[n], "-gtsnoupdate") == 0) {
                     do_collect = 0;
              } else if (strcmp(argv[n], "-gtsnoaudit") == 0) {
                     do_audit = 0;
              } else if (strcmp(argv[n], "-gtsnozap") == 0) {
                     do_zap = 0;
              } else if (strcmp(argv[n], "-gtsrootdir") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsrootdir requires an argument\n");
                            usage();
                            return 2;
                     }
                     rootdir = argv[n+1];
                     n++;
              } else if (strcmp(argv[n], "-gtsdebugsym") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsdebugsym requires an argument\n");
                            usage();
                            return 2;
                     }
                     djw_test_name = argv[n+1];
                     n++;
              } else if (strcmp(argv[n], "-gtsmaxglobals") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsmaxglobals requires an argument\n");
                            usage();
                            return 2;
                     }
                     max_globals = katoi(argv[n+1]);
                     n++;

              } else if (strcmp(argv[n], "-gtspref") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtspref requires an argument\n");
                            usage();
                            return 2;
                     }
                     path_prefs[npath_prefs++] = argv[n+1];
                     path_prefs[npath_prefs] = NULL;
                     n++;

              } else if (strcmp(argv[n], "-gtsunpref") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsunpref requires an argument\n");
                            usage();
                            return 2;
                     }
                     path_un_prefs[npath_un_prefs++] = argv[n+1];
                     path_un_prefs[npath_un_prefs] = NULL;
                     n++;

              } else if (strcmp(argv[n], "-gtssaveprefix") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtssaveprefix requires an argument\n");
                            usage();
                            return 2;
                     }
                     saveprefix = argv[n+1];
                     n++;

              } else if (strcmp(argv[n], "-gtsfile") == 0) {

                     struct stat sbuf;

                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsfile requires an argument\n");
                            usage();
                            return 2;
                     }

                     gts_file = argv[n+1];
                            
                     if (stat(gts_file, &sbuf) == -1) {
                            fprintf(stderr,
                                          "warning: %s does not exist, will be created\n",
                                          gts_file);
                     } else {
                            
                            if ((zap_fp = fopen(gts_file, "r")) == NULL) {
                                   fprintf(stderr,      "you lose cannot open %s\n", gts_file);
                                   usage();
                                   return 2;
                            }

                            if (EhSymTableFpLoad(table, zap_fp) == -1) {
                                   fprintf(stderr,
                                                 "error: failed reading symbols from gtsfile %s\n",
                                                 argv[n+1]);
                                   usage();
                                   return 2;
                            }
                            
                            fclose(zap_fp);
                     }

                     n++;

              } else if (strcmp(argv[n], "-gtszapsymbol") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtszapsymbol requires an argument\n");
                            usage();
                            return 2;
                     }

                     EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_ZAPPED);
                     n++;

              } else if (strcmp(argv[n], "-gtsnozapsymbol") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsnozapsymbol requires an argument\n");
                            usage();
                            return 2;
                     }

                     EhSymTableSetSymbolState(table, argv[n+1], EH_SYM_DEFINED);
                     n++;

              } else if (strcmp(argv[n], "-gtsname") == 0) {
                     if (argc < n+2) {
                            fprintf(stderr,      "-gtsname requires an argument\n");
                            usage();
                            return 2;
                     }

                     sym = EhSymTableFind(table, argv[n+1]);
                     if (!sym)
                            sym = EhSymNewRandomZap(argv[n+1]);
                     n++;
                     do_audit = 1;

              } else if (strcmp(argv[n], "-c") == 0) { /* do not link */
                     in_link = 0;
                     do_link = 0;
              } else if (strcmp(argv[n], "-S") == 0) { /* do not assem */
                     do_assem = 0;
              } else if (strcmp(argv[n], "-o") == 0) { /* parse through */
                     arg_buf[nargs++] = argv[n++];
                     arg_buf[nargs++] = argv[n];
                     arg_buf[nargs] = NULL;
              } else if (strcmp((suffix = suffix_name(argv[n])), ".cpp") == 0
                               ||
                               strcmp(suffix, ".c") == 0
                               ||
                               strcmp(suffix, ".s") == 0) {
                     char pathname[MAXPATHLEN];

                     make_relative_pathname(pathname, ".", rootdir);

                     source = EhSourceNew(argv[n], arg_buf, pathname);

                     rv = EhSourceCompile(source,
                                                         table,
                                                         verbosity,
                                                         TRUE, /* compile, .s files ignore anyway */
                                                         (do_audit + do_zap),
                                                         do_assem);
                     if (rv == -1)
                            return 1;

#if 0
                     EhSourceAdjustPathname(source, rootdir);
#endif

              } else if (strcmp(suffix, ".o") == 0 || strcmp(suffix, ".a") == 0) {

                     if (fileListFind(o_list, argv[n]) == NULL) {
                            fileListAppend(&o_list, argv[n]);
                     } else {
                            fprintf(stderr,
                                          "%s repeated on command line - ignored\n",
                                          argv[n]);
                     }
                     arg_buf[nargs++] = argv[n];
                     arg_buf[nargs] = NULL;

              } else if (strncmp(argv[n], "-L", 2) == 0) {
                     EhDirMapAddDirectory(dmap, &argv[n][2]);
              } else if (strncmp(argv[n], "-l", 2) == 0) {
                     char pathbuf[MAXPATHLEN];
                     name = EhDirMapGetLibName(dmap, &argv[n][2], pathbuf);
                     if (name != NULL) {
                            if (fileListFind(o_list, name) == NULL) {
                                   fileListAppend(&o_list, name);
                            } else {
                                   fprintf(stderr,
                                                 "%s repeated on command line - ignored\n",
                                                 name);
                            }
                     } else {
                            fprintf(stderr, 
                                          "unable to resolve library reference %s - ignoring\n",
                                          argv[n]);
                     }
                     arg_buf[nargs++] = argv[n];
                     arg_buf[nargs] = NULL;
              } else {
                     arg_buf[nargs++] = argv[n];
                     arg_buf[nargs] = NULL;
              }
       }

       /*
        *    Analyse objects.
        */
       if (o_list != NULL) {
              for (list = o_list; list != NULL; list = list->next) {

                     if (eh_process_file(list->name, table, rootdir)) {
                            fprintf(stderr, "oops we died around %s\n", list->name);
                            return 1;
                     }
              }
              
              /* look for unused objects */
              EhSymTableMap(table, object_nusers_mappee, 0);
       }

       if (do_summary) {
              print_summary(table);
       }

       if (do_dump) {
              print_dump(table);
       }

       if (!in_link && gts_file != NULL) {
              FILE* zap_fp;
              if ((zap_fp = fopen(gts_file, "w")) == NULL) {
                     perror(0);
                     usage();
                     return 2;
              }

              EhSymTableFpDump(table, zap_fp);
              fclose(zap_fp);
              return 0;
       }

       /*
        *    Now the fun really starts.
        */
       if (do_recompile) {
              char** pp = NULL;
              char** up = NULL;
              
              if (npath_prefs > 0)
                     pp = path_prefs;
              
              if (npath_un_prefs > 0)
                     up = path_un_prefs;

              if (!do_collect)
                     gts_file = NULL;
              
              rv = do_recompilation(table, gts_file, max_globals, pp, up, rootdir,
                                                   verbosity);
              if (rv == -1)
                     return 1;
       }

       /*
        *    Finally.
        */
       if (do_link) {

              int status;

              arg_buf[nargs+1] = NULL;
              for (n = nargs; n > 0; n--)
                     arg_buf[n] = arg_buf[n-1];
              arg_buf[0] = LD_COMMAND;
              
              status = do_command("link", arg_buf, verbosity);

              if (status == -1)
                     return 3;
              else
                     return status;
       }
       
       return 0;
}

Here is the call graph for this function:

static char* make_relative_pathname ( char *  buf,
char *  filename,
char *  rootdir 
) [static]

Definition at line 198 of file gtscc.c.

{
       char  buf1[MAXPATHLEN];
       char  buf2[MAXPATHLEN];
       char* p;
       char* q;

       if (rootdir == NULL) {
              strcpy(buf, filename);
              return filename;
       }

       if (filename[0] != '/') {
              if (getcwd(buf2, sizeof(buf2)) == NULL) {
                     fprintf(stderr, "cannot get pwd\n");
                     return NULL;
              }

              strcat(buf2, "/");
              strcat(buf2, filename);

              filename = buf2;
       }

       if (realpath(filename, buf1) == NULL) {
              fprintf(stderr, "realpath(%s,..) failed\n", filename);
              return NULL;
       }
       
       if (realpath(rootdir, buf2) == NULL) {
              fprintf(stderr, "realpath(%s,..) failed\n", rootdir);
              return NULL;
       }

       strcat(buf2, "/");

       for (p = buf1, q = buf2; *p == *q; p++, q++)
              ;

       strcpy(buf, p);

       return buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static unsigned match_prefs ( char *  candidate,
char **  prefs 
) [static]

Definition at line 2120 of file gtscc.c.

{
       unsigned n;

       for (n = 0; prefs[n] != NULL; n++) {
              char*    pref = prefs[n];
              unsigned len = strlen(pref);
              if (strncmp(pref, candidate, len) == 0)
                     return n; /* cool */
       }
       return (unsigned)-1; /* big! */
}

Here is the caller graph for this function:

static int object_nusers_mappee ( EhSym sym,
void arg 
) [static]

Definition at line 2063 of file gtscc.c.

{
       if (sym->object != NULL)
              sym->object->nusers += sym->ngusers;
       return 0;
}

Here is the caller graph for this function:

static void print_command ( char *  command,
char **  args,
unsigned  verbosity 
) [static]

Definition at line 1558 of file gtscc.c.

{
       int i;
       FILE* fp = stderr;
       if (!VERBOSITY_USER(verbosity))
              return;

       fprintf(fp, "%s: ", command);
       for (i = 0; args[i]; i++) {
              fprintf(fp, "%s ", args[i]);
       }
       fprintf(fp, "\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_dump ( EhSymTable table) [static]

Definition at line 1282 of file gtscc.c.

{
       printf("everything\n");
       EhSymTableMap(table, eh_dump_unused, NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_summary ( EhSymTable table) [static]

Definition at line 1343 of file gtscc.c.

{
       SummaryInfo info;

       get_summary(table, &info);
       
       printf("summary:\n"
                 "defined and used:             %d\n"
                 "defined but unused globally:  %d\n"
                 "total globals in target:      %d\n"
                 "--------------------------------\n"
                 "global to statics *:          %d\n"
                 "global to statics (now used): %d\n"
                 "inlined to statics *:         %d\n"
                 "defined in unlinked objects:  %d\n"
                 "defined but unused (deadcode):%d\n"
                 "undefined but used:           %d\n",
                 info.nused,
                 info.ndefined,
                 (info.nused + info.ndefined),
                 info.nzapped,
                 info.nzapped_nowused,
                 info.ninlined,
                 info.nunlinked,                    
                 info.ndeadcode,                    
                 info.nundefined);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int recompile_compare ( const void ap,
const void bp 
) [static]

Definition at line 2134 of file gtscc.c.

{
       EhObject** ax = (EhObject**)ap;
       EhObject** bx = (EhObject**)bp;
       EhObject*  obj_a = *ax;
       EhObject*  obj_b = *bx;
       EhSource*  src_a = obj_a->source;
       EhSource*  src_b = obj_b->source;
       unsigned   matcha;
       unsigned   matchb;
       int        foo;

       if (obj_a->_needs_unzap == 0 && obj_b->_needs_unzap != 0)
              return -1;
       if (obj_a->_needs_unzap != 0 && obj_b->_needs_unzap == 0)
              return 1;

       if (src_a == NULL && src_b != NULL)
              return 1;
       if (src_a != NULL && src_b == NULL)
              return -1;
       if (src_a == src_b)
              return 0;

       if (recompile_compare_unprefs != NULL
              && src_a->directory != NULL && src_b->directory != NULL) {

              matcha = match_prefs(src_a->directory, recompile_compare_unprefs);
              matchb = match_prefs(src_b->directory, recompile_compare_unprefs);

              if (matcha > matchb) /* greater is good */
                     return -1;
              if (matcha < matchb)
                     return 1;
       }

       if (recompile_compare_prefs != NULL
              && src_a->directory != NULL && src_b->directory != NULL) {

              matcha = match_prefs(src_a->directory, recompile_compare_prefs);
              matchb = match_prefs(src_b->directory, recompile_compare_prefs);

              if (matcha > matchb) /* greater is bad */
                     return 1;
              if (matcha < matchb)
                     return -1;
       }

       /* else same directory probably */
       foo = strcmp(src_a->name, src_b->name);

       if (foo < 0)
              return -1;
       if (foo > 0)
              return 1;

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int recompile_init_mappee ( EhSym sym,
void arg 
) [static]

Definition at line 2079 of file gtscc.c.

{
       RecompileInfo* info = (RecompileInfo*)arg;

       if (EHSYM_ISZAPPED(sym) && sym->ngusers != 0) {
              if (EH_OBJECT_CANBUILD(sym->object)) {
                     sym->state = EH_SYM_DEFINED;
                     if (sym->object->_recompile == NULL) {
                            sym->object->_recompile = info->recompile_list;
                            info->recompile_list = sym->object;
                            info->recompile_count++;
                     }
                     info->unzap_count++;
                     sym->object->_needs_unzap++;
              }
              info->recompile_wish_count++;
       }
       else if (EHSYM_ISDEFINED(sym) /* it's defined */
                      && sym->ngusers == 0 /* there are no global users */
                      && sym->nlusers != 0 /* BUT, ther are local users */
                      && sym->object->nusers != 0) { /* object is linked */

              if (EH_OBJECT_CANBUILD(sym->object)) {
                     sym->state = EH_SYM_ZAPPED;
                     if (sym->object->_recompile == NULL) {
                            sym->object->_recompile = info->recompile_list;
                            info->recompile_list = sym->object;
                            info->recompile_count++;
                     }
                     info->zap_count++;
              }
              info->recompile_wish_count++;
       }

       return 0;
}

Here is the caller graph for this function:

static char* safe_fgets ( char *  buf,
unsigned  size,
FILE fp 
) [static]

Definition at line 539 of file gtscc.c.

{
       unsigned nread = 0;

       if (buf == NULL)
              buf = (char*)malloc(size);

       for (;;) {

              if (fgets(&buf[nread], size - nread, fp) == NULL) {
                     free(buf);
                     return NULL;
              }

              if (strchr(buf, '\n') != NULL)
                     return buf;

              /*
               *    fgets returns n-1 characters and \0
               */
              nread += (size - nread) - 1;
              size += 1024;
              buf = (char*)realloc(buf, size);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* suffix_name ( char *  s) [static]

Definition at line 1606 of file gtscc.c.

{
       char* p;

       if ((p = strrchr(s, '.')) != NULL)
              return p;
       else
              return "";
}

Here is the caller graph for this function:

static char* test_for_file ( char *  foo,
char *  buf 
) [static]

Definition at line 1437 of file gtscc.c.

{
#ifdef IRIX
       char* p;
       char* q;
       if (strncmp(buf, "\t.file\t", 6) == 0) {
              for (p = &buf[6]; *p != '"' && *p != '\0'; p++)
                     ;
              if (*p == '\0')
                     return NULL;
              p++; /* quote */
              q = strchr(p, '"');
              if (q == NULL)
                     return NULL;
              memcpy(foo, p, q - p);
              foo[q - p] = '\0';
              return foo;
       }
#else
       printf("test_for_file() not implemented\n");
#endif
       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* test_for_global ( char *  buf) [static]

Definition at line 1424 of file gtscc.c.

{
#ifdef IRIX
       if (strncmp(buf, "\t.globl\t", 8) == 0)
              return &buf[8];
#else
       if (strncmp(buf, "\t.global ", 9) == 0)
              return &buf[9];
#endif
       return NULL;
}

Here is the caller graph for this function:

static void usage ( void  ) [static]

Definition at line 2436 of file gtscc.c.

{
       fprintf(stderr,
                     "Usage:\n"
                     "as a compiler:\n"
                     "gtscc [gtscc_options] [compiler_options] -c file.c file.cpp ...\n"
                     "gtscc_options:\n"
                     "-gtsfile <db.gts>       the gts database file (use this)\n"
                     "-gtszapsymbol <name>    convert symbol <name>\n"
                     "-gtsnozapsymbol <name>  don't convert symbol <name>\n"
                     "-gtsrootdir <directory> the root for the tree (use this)\n"
                     "-gtsverbose             be more verbose (3 levels)\n"
                     "-gtsnozap               don't convert globals to statics\n"
                     "-gtsnoupdate            don't update the database file\n"
                     "as a linker:\n"
                     "gtscc [gtscc_options] [linker_options] file.o ... libxx.a ...\n"
                     "gtscc_options:\n"
                     "-gtsfile <db.gts>       the gts database file (use this)\n"
                     "-gtszapsymbol <name>    convert symbol <name>\n"
                     "-gtsnozapsymbol <name>  don't convert symbol <name>\n"
                     "-gtsrootdir <directory> the root for the tree (use this)\n"
                     "-gtspref <directory>    please recompile these paths first\n"
                     "-gtsunpref <directory>  please try to avoid recompiling these\n"
                     "-gtsverbose             be more verbose (3 levels)\n"
                     "-gtssummary             print a summary of global usage\n"
                     "-gtsdump                print a detailed listing of all symbols\n"
                     "-gtsmaxglobals <number>[k] maximum globals allowed in target\n"
                     "-gtsnorecompile         don't do the normal recompilation\n"
                     "-gtsnolink              don't call linker after recompilation\n"
                     "-gtsnoupdate            don't update the database file\n"
                     "-help                   print this\n"
       );
}

Here is the call graph for this function:


Variable Documentation

char base_name_buf[MAXPATHLEN] [static]

Definition at line 1616 of file gtscc.c.

Definition at line 922 of file gtscc.c.

Definition at line 923 of file gtscc.c.

char eh_unnamed_object[] = "<name not known>" [static]

Definition at line 128 of file gtscc.c.

FileList* o_list [static]

Definition at line 2371 of file gtscc.c.

char** recompile_compare_prefs [static]

Definition at line 2116 of file gtscc.c.

char** recompile_compare_unprefs [static]

Definition at line 2117 of file gtscc.c.

char target_buf[MAXPATHLEN] [static]

Definition at line 1901 of file gtscc.c.