Home
       symbol.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       symbol.c (3023B)
       ---
            1 #include <assert.h>
            2 #include <errno.h>
            3 #include <stdio.h>
            4 #include <stdlib.h>
            5 #include <string.h>
            6 
            7 #include <scc/mach.h>
            8 #include <scc/scc.h>
            9 
           10 #include "ld.h"
           11 
           12 #define NR_SYMBOL 128
           13 
           14 /*
           15  * struct symtab has a Symbol as first field because
           16  * the code is going to cast from the symbols to the tab.
           17  */
           18 struct symtab {
           19         Symbol sym;
           20         Obj *where;
           21         struct symtab *hash;
           22         struct symtab *next, *prev;
           23 };
           24 
           25 static struct symtab *symtab[NR_SYMBOL];
           26 static struct symtab undef = {.next = &undef, .prev = &undef};
           27 static struct symtab def = {.next = &def, .prev = &def};
           28 static struct symtab common = {.next = &common, .prev = &common};
           29 
           30 static Symbol *
           31 unlinksym(Symbol *sym)
           32 {
           33         struct symtab *sp = (struct symtab *) sym;
           34 
           35         sp->next->prev = sp->prev;
           36         sp->prev->next = sp->next;
           37 
           38         return sym;
           39 }
           40 
           41 static Symbol *
           42 linksym(struct symtab *lst, Symbol *sym)
           43 {
           44         struct symtab *sp = (struct symtab *) sym;
           45 
           46         sp->next = lst;
           47         sp->prev = lst->prev;
           48         lst->prev->next = sp;
           49         lst->prev = sp;
           50 
           51         return sym;
           52 }
           53 
           54 int
           55 hasref(char *name)
           56 {
           57         unsigned h;
           58         struct symtab *sp;
           59 
           60         h = genhash(name) % NR_SYMBOL;
           61         for (sp = symtab[h]; sp; sp = sp->hash) {
           62                 if (!strcmp(name, sp->sym.name))
           63                         return sp->sym.type == 'U';
           64         }
           65         return 0;
           66 }
           67 
           68 Symbol *
           69 lookupsym(char *name)
           70 {
           71         unsigned h;
           72         size_t len;
           73         char *s;
           74         Symbol *sym;
           75         struct symtab *sp;
           76 
           77         h = genhash(name) % NR_SYMBOL;
           78         for (sp = symtab[h]; sp; sp = sp->hash) {
           79                 if (!strcmp(name, sp->sym.name))
           80                         return &sp->sym;
           81         }
           82 
           83         len = strlen(name) + 1;
           84         s = malloc(len);
           85         sp = malloc(sizeof(*sp));
           86         if (!s  || !sp) {
           87                 error(strerror(errno));
           88                 exit(EXIT_FAILURE);
           89         }
           90 
           91         sym = &sp->sym;
           92         sym->name = memcpy(s, name, len);
           93         sym->value = 0;
           94         sym->size = 0;
           95         sym->index = 0;
           96         sym->type = 'U';
           97         sp->where = NULL;
           98         sp->hash = symtab[h];
           99         symtab[h] = sp;
          100 
          101         return linksym(&undef, sym);
          102 }
          103 
          104 
          105 int
          106 moreundef(void)
          107 {
          108         return undef.next != &undef;
          109 }
          110 
          111 void
          112 listundef(void)
          113 {
          114         struct symtab *sp;
          115 
          116         for (sp = undef.next; sp != &undef; sp = sp->next)
          117                 error("ld: symbol '%s' not defined", sp->sym.name);
          118 }
          119 
          120 Symbol *
          121 define(Symbol *osym, Obj *obj)
          122 {
          123         struct symtab *lst;
          124         Symbol *sym = lookupsym(osym->name);
          125         struct symtab *sp = (struct symtab *) sym;
          126 
          127         assert(osym->type != 'U');
          128         sp->where = obj;
          129 
          130         switch (sym->type) {
          131         case 'U':
          132                 sym->value = osym->value;
          133                 sym->size = osym->size;
          134                 lst = (osym->type == 'C') ? &common : &def;
          135                 linksym(lst, unlinksym(sym));
          136                 break;
          137         case 'C':
          138                 if (osym->type != 'C') {
          139                         sym->size = osym->size;
          140                         sym->value = osym->size;
          141                         linksym(&def, unlinksym(sym));
          142                 } else  if (sym->size < osym->size) {
          143                         sym->value = osym->value;
          144                         sym->size = osym->size;
          145                 }
          146                 break;
          147         defaul:
          148                 error("%s: symbol redefined", sym->name);
          149                 break;
          150         }
          151 
          152         return sym;
          153 }
          154 
          155 #ifndef NDEBUG
          156 void
          157 debugsym(void)
          158 {
          159         struct symtab **spp, *sp;
          160         Symbol*sym;
          161 
          162         fputs("Symbols:\n", stderr);
          163         for (spp = symtab; spp < &symtab[NR_SYMBOL]; spp++) {
          164                 for (sp = *spp; sp; sp = sp->hash) {
          165                         sym = &sp->sym;
          166                         fprintf(stderr,
          167                                 "sym: %s (%#llx)\n",
          168                                 sym->name,
          169                                 sym->value);
          170                 }
          171         }
          172 }
          173 #endif