#include #include #include "link.h" #define ALLOC_SYM 10000 // Nombre de symbole allou‚ par chunk /* Liste des symboles Pour chaque symbole, on retient son module de provenance. */ PUBLIC SYMBOLS::SYMBOLS() { sym.cur = NULL; memset (hash,0,sizeof(hash)); allocsym(); } /* Alloue un nouveau buffer d'accumulation pour les symboles */ PROTECTED void SYMBOLS::allocsym() { LIST_SYMBOL *list = (LIST_SYMBOL*) malloc_err (sizeof(LIST_SYMBOL) +ALLOC_SYM*sizeof(SYMBOL),1); list->next = sym.cur; sym.cur = list; sym.nb = 0; sym.ptacc = list->alloc; sym.lastacc = list->alloc+ALLOC_SYM; } /* Ajoute un symbole ou localise. Ce symbole est soit publique ou un external (requis). Retourne le symbole localis‚ ou ajout‚ */ PUBLIC SYMBOL *SYMBOLS::add ( const char *name, MODULE *module, // Module qui d‚clare ce symbole ou NULL. SYM_STATUS status, int &module_requis, // Contiendra != 0 si on ‚tablis que le module // en traitement est requis par un autre // module vue pr‚c‚demment. // Assume qu'il y a deja une valeure dedans int is_common) { // Recherche le nom unsigned hashval = 0; const char *pt = name; while (*pt != '\0'){ hashval = (hashval << 1) + *pt++; } hashval %= 2048; SYMBOL **ffind = hash + hashval; SYMBOL *find = *ffind; while (find != NULL){ if (strcmp(find->name,name)==0) break; find = find->next; } if (find == NULL){ // Ajoute a la liste if (sym.ptacc == sym.lastacc) allocsym(); find = sym.ptacc++; sym.nb++; find->name = alloctxt_add (name); find->module = NULL; find->next = *ffind; *ffind = find; find->force = 0; find->is_common = 0; find->is_dup = 0; if (status == SYM_REQUIS){ find->requis = 1; find->defini = 0; find->vue_avant = 0; }else if (status == SYM_PASUTIL){ find->requis = 0; find->defini = 0; find->vue_avant = 0; }else{ find->requis = 0; find->defini = 1; find->vue_avant = 1; find->is_common = is_common; find->module = module; } }else{ // Deja la if (status == SYM_DEFINI){ if (find->defini){ // Le symbole est d‚j… d‚finie // On ne l'insere pas dans le hashing et on note // qu'il est en double. Si jamais un module doit // ˆtre charg‚ et possŠde un symbole "duplicate" // on pourra signale le probleme. if (sym.ptacc == sym.lastacc) allocsym(); find = sym.ptacc++; sym.nb++; find->name = alloctxt_add (name); find->next = NULL; find->force = 0; find->is_common = 0; find->is_dup = 1; find->requis = 0; find->vue_avant = 0; } find->module = module; find->defini = 1; find->is_common = is_common; if (find->requis) module_requis = 1; }else if (status == SYM_REQUIS){ find->requis = 1; } } return find; } /* Trouve les symboles qui doivent ˆtre "demander" au linker. On fait ca pour eviter un link multi-passe. Retourne le nombre de symbole plac‚ dans tb. */ PUBLIC int SYMBOLS::findforce ( char **tb, // tb peut ˆtre NULL // Ca permet de les compter int maxtb) { int ret = 0; LIST_SYMBOL *list = sym.cur; int nbsym = sym.nb; while (list != NULL){ SYMBOL *ptsym = list->alloc; for (int i=0; iforce){ if (tb != NULL) tb[ret++] = strdup_err (ptsym->name,1); if (ret >= maxtb) { fprintf(stderr, "Too many symbols: %d\n", ret); return ret; } } } nbsym = ALLOC_SYM; list = list->next; } return ret; } /* Pr‚sente toute la liste de symbole en m‚moire */ PUBLIC void SYMBOLS::dump (FILE *fout) { LIST_SYMBOL *list = sym.cur; int nbsym = sym.nb; while (list != NULL){ SYMBOL *ptsym = list->alloc; for (int i=0; iname,ptsym->requis ,ptsym->defini,ptsym->vue_avant ,ptsym->is_common,ptsym->force); } nbsym = ALLOC_SYM; list = list->next; } }