LCOV - code coverage report
Current view: top level - src - symbol.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 179 190 94.2 %
Date: 2015-04-21 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /* This file is part of GNU cflow
       2             :    Copyright (C) 1997, 2005, 2006, 2007, 2009, 2010 Sergey Poznyakoff
       3             : 
       4             :    GNU cflow is free software; you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation; either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    GNU cflow is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public
      15             :    License along with GNU cflow; if not, write to the Free Software
      16             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      17             :    MA 02110-1301 USA */
      18             : 
      19             : #include <cflow.h>
      20             : #include <parser.h>
      21             : #include <hash.h>
      22             : 
      23             : static Hash_table *symbol_table;
      24             : 
      25             : static struct linked_list *static_symbol_list;
      26             : static struct linked_list *auto_symbol_list;
      27             : static struct linked_list *static_func_list;
      28             : 
      29             : static void
      30       10593 : append_symbol(struct linked_list **plist, Symbol *sp)
      31             : {
      32       10593 :      if (sp->entry) {
      33         112 :           linked_list_unlink(sp->entry->list, sp->entry);
      34         112 :           sp->entry = NULL;
      35             :      }
      36       10593 :      if (!data_in_list(sp, *plist)) {
      37       10593 :           linked_list_append(plist, sp);
      38       10593 :           sp->entry = (*plist)->tail;
      39             :      }
      40       10593 : }
      41             : 
      42             : struct table_entry {
      43             :      Symbol *sym;
      44             : };
      45             : 
      46             : /* Calculate the hash of a string.  */
      47             : static size_t
      48      288619 : hash_symbol_hasher(void const *data, unsigned n_buckets)
      49             : {
      50      288619 :      struct table_entry const *t = data;
      51      288619 :      if (!t->sym)
      52       19593 :           return ((size_t) data) % n_buckets;
      53      269026 :      return hash_string(t->sym->name, n_buckets);
      54             : }
      55             : 
      56             : /* Compare two strings for equality.  */
      57             : static bool
      58      429462 : hash_symbol_compare(void const *data1, void const *data2)
      59             : {
      60      429462 :      struct table_entry const *t1 = data1;
      61      429462 :      struct table_entry const *t2 = data2;
      62      429462 :      return t1->sym && t2->sym && strcmp(t1->sym->name, t2->sym->name) == 0;
      63             : }
      64             : 
      65             : Symbol *
      66      226061 : lookup(const char *name)
      67             : {
      68             :      Symbol s, *sym;
      69             :      struct table_entry t, *tp;
      70             :      
      71      226061 :      if (!symbol_table)
      72           0 :           return NULL;
      73      226061 :      s.name = (char*) name;
      74      226061 :      t.sym = &s;
      75      226061 :      tp = hash_lookup(symbol_table, &t);
      76      226061 :      if (tp) {
      77      189346 :           sym = tp->sym;
      78      378692 :           while (sym->type == SymToken && sym->flag == symbol_alias)
      79           0 :                sym = sym->alias;
      80             :      } else
      81       36715 :           sym = NULL;
      82      226061 :      return sym;
      83             : }
      84             : 
      85             : /* Install a new symbol `NAME'.  If UNIT_LOCAL is set, this symbol can
      86             :    be local to the current compilation unit. */
      87             : Symbol *
      88       18692 : install(char *name, int flags)
      89             : {
      90             :      Symbol *sym;
      91             :      struct table_entry *tp, *ret;
      92             :      
      93       18692 :      sym = xmalloc(sizeof(*sym));
      94       18692 :      memset(sym, 0, sizeof(*sym));
      95       18692 :      sym->type = SymUndefined;
      96       18692 :      sym->name = name;
      97             : 
      98       18692 :      tp = xmalloc(sizeof(*tp));
      99       18692 :      tp->sym = sym;
     100             :      
     101       18692 :      if (((flags & INSTALL_CHECK_LOCAL) &&
     102       27835 :           canonical_filename && strcmp(filename, canonical_filename)) ||
     103       17344 :          (flags & INSTALL_UNIT_LOCAL)) {
     104        1556 :           sym->flag = symbol_temp;
     105        1556 :           append_symbol(&static_symbol_list, sym);
     106             :      } else
     107       17136 :           sym->flag = symbol_none;
     108             :      
     109       37384 :      if (! ((symbol_table
     110          19 :              || (symbol_table = hash_initialize (0, 0, 
     111             :                                                  hash_symbol_hasher,
     112             :                                                  hash_symbol_compare, 0)))
     113       18692 :             && (ret = hash_insert (symbol_table, tp))))
     114           0 :           xalloc_die ();
     115             : 
     116       18692 :      if (ret != tp) {
     117        1455 :           if (flags & INSTALL_OVERWRITE) {
     118           0 :                free(sym);
     119           0 :                free(tp);
     120           0 :                return ret->sym;
     121             :           }
     122        1455 :           if (ret->sym->type != SymUndefined) 
     123        1455 :                sym->next = ret->sym;
     124        1455 :           ret->sym = sym;
     125        1455 :           free(tp);
     126             :      }
     127       18692 :      sym->owner = ret;
     128       18692 :      return sym;
     129             : }
     130             : 
     131             : void
     132       23025 : ident_change_storage(Symbol *sp, enum storage storage)
     133             : {
     134       23025 :      if (sp->storage == storage)
     135       37007 :           return;
     136        9043 :      if (sp->storage == StaticStorage)
     137             :           /* FIXME */;
     138             : 
     139        9043 :      switch (storage) {
     140             :      case StaticStorage:
     141        1581 :           append_symbol(&static_symbol_list, sp);
     142        1581 :           break;
     143             :      case AutoStorage:
     144        7456 :           append_symbol(&auto_symbol_list, sp);
     145        7456 :           break;
     146             :      default:
     147           6 :           break;
     148             :      }
     149        9043 :      sp->storage = storage;
     150             : }
     151             : 
     152             : Symbol *
     153       17947 : install_ident(char *name, enum storage storage)
     154             : {
     155             :      Symbol *sp;
     156             : 
     157       17947 :      sp = install(name, 
     158             :                   storage != AutoStorage ? 
     159             :                      INSTALL_CHECK_LOCAL : INSTALL_DEFAULT);
     160       17947 :      sp->type = SymIdentifier;
     161       17947 :      sp->arity = -1;
     162       17947 :      sp->storage = ExternStorage;
     163       17947 :      sp->decl = NULL;
     164       17947 :      sp->source = NULL;
     165       17947 :      sp->def_line = -1;
     166       17947 :      sp->ref_line = NULL;
     167       17947 :      sp->caller = sp->callee = NULL;
     168       17947 :      sp->level = -1;
     169       17947 :      ident_change_storage(sp, storage);
     170       17947 :      return sp;
     171             : }
     172             : 
     173             : /* Unlink the symbol from the table entry */
     174             : static void
     175       10481 : unlink_symbol(Symbol *sym)
     176             : {
     177       10481 :      Symbol *s, *prev = NULL;
     178       10481 :      struct table_entry *tp = sym->owner;
     179       20962 :      for (s = tp->sym; s; ) {
     180       10481 :           Symbol *next = s->next;
     181       10481 :           if (s == sym) {
     182       10481 :                if (prev)
     183           0 :                     prev->next = next;
     184             :                else
     185       10481 :                     tp->sym = next;
     186       10481 :                break;
     187             :           } else
     188           0 :                prev = s;
     189           0 :           s = next;
     190             :      }
     191             :                
     192       10481 :      sym->owner = NULL;
     193       10481 : }     
     194             : 
     195             : /* Unlink and free the first symbol from the table entry */
     196             : static void
     197        9012 : delete_symbol(Symbol *sym)
     198             : {
     199        9012 :      unlink_symbol(sym);
     200             :      /* The symbol could have been referenced even if it is static
     201             :         in -i^s mode. See tests/static.at for details. */
     202        9012 :      if (sym->ref_line == NULL && !(reverse_tree && sym->callee)) {
     203        7762 :           linked_list_destroy(&sym->ref_line);
     204        7762 :           linked_list_destroy(&sym->caller);
     205        7762 :           linked_list_destroy(&sym->callee);
     206        7762 :           free(sym);
     207             :      }
     208        9012 : }     
     209             : 
     210             : /* Delete from the symbol table all static symbols defined in the current
     211             :    source.
     212             :    If the user requested static symbols in the listing, the symbol is
     213             :    not deleted, as it may have been referenced by other symbols. Instead,
     214             :    it is unlinked from its table entry.
     215             :    NOTE: This takes advantage of the fact that install() uses LIFO strategy,
     216             :    so we don't have to check the name of the source where the symbol was
     217             :    defined. */
     218             : 
     219             : static void
     220        3009 : static_free(void *data)
     221             : {
     222        3009 :      Symbol *sym = data;
     223        3009 :      struct table_entry *t = sym->owner;
     224             : 
     225        3009 :      if (!t)
     226        3009 :           return;
     227        3009 :      if (sym->flag == symbol_temp) 
     228        1556 :           delete_symbol(sym);
     229             :      else {
     230        1453 :           unlink_symbol(sym);
     231        1453 :           if (symbol_is_function(sym))
     232         892 :                linked_list_append(&static_func_list, sym);
     233             :      }
     234             : }
     235             : 
     236             : void
     237         227 : delete_statics()
     238             : {
     239         227 :      if (static_symbol_list) {
     240         177 :           static_symbol_list->free_data = static_free;
     241         177 :           linked_list_destroy(&static_symbol_list);
     242             :      }
     243         227 : }
     244             : 
     245             : /* See NOTE above */
     246             : 
     247             : /* Delete from the symbol table all auto variables with given nesting
     248             :    level. */
     249             : int
     250       19726 : delete_level_autos(void *data, void *call_data)
     251             : {
     252       19726 :      int level = *(int*)call_data;
     253       19726 :      Symbol *s = data;
     254       19726 :      if (s->level == level) {
     255        6874 :           delete_symbol(s);
     256        6874 :           return 1;
     257             :      }
     258       12852 :      return 0;
     259             : }
     260             : 
     261             : int
     262      209961 : delete_level_statics(void *data, void *call_data)
     263             : {
     264      209961 :      int level = *(int*)call_data;
     265      209961 :      Symbol *s = data;
     266      209961 :      if (s->level == level) {
     267          16 :           unlink_symbol(s);
     268          16 :           return 1;
     269             :      }
     270      209945 :      return 0;
     271             : }
     272             : 
     273             : void
     274        8432 : delete_autos(int level)
     275             : {
     276        8432 :      linked_list_iterate(&auto_symbol_list, delete_level_autos, &level);
     277        8432 :      linked_list_iterate(&static_symbol_list, delete_level_statics, &level);
     278        8432 : }
     279             : 
     280             : struct collect_data {
     281             :      Symbol **sym;
     282             :      int (*sel)(Symbol *p);
     283             :      size_t index;
     284             : };
     285             : 
     286             : static bool
     287       58290 : collect_processor(void *data, void *proc_data)
     288             : {
     289       58290 :      struct table_entry *t = data;
     290       58290 :      struct collect_data *cd = proc_data;
     291             :      Symbol *s;
     292       86074 :      for (s = t->sym; s; s = s->next) {
     293       27784 :           if (cd->sel(s)) {
     294       17830 :                if (cd->sym)
     295        8915 :                     cd->sym[cd->index] = s;
     296       17830 :                cd->index++;
     297             :           }
     298             :      }
     299       58290 :      return true;
     300             : }
     301             : 
     302             : size_t
     303          33 : collect_symbols(Symbol ***return_sym, int (*sel)(Symbol *p),
     304             :                 size_t reserved_slots)
     305             : {
     306             :      struct collect_data cdata;
     307             : 
     308          33 :      cdata.sym = NULL;
     309          33 :      cdata.index = 0;
     310          33 :      cdata.sel = sel;
     311          33 :      hash_do_for_each (symbol_table, collect_processor, &cdata);
     312          33 :      cdata.sym = calloc(cdata.index + reserved_slots, sizeof(*cdata.sym));
     313          33 :      if (!cdata.sym)
     314           0 :           xalloc_die();
     315          33 :      cdata.index = 0;
     316          33 :      hash_do_for_each (symbol_table, collect_processor, &cdata);
     317          33 :      *return_sym = cdata.sym;
     318          33 :      return cdata.index;
     319             : }
     320             : 
     321             : size_t
     322          14 : collect_functions(Symbol ***return_sym)
     323             : {
     324             :      Symbol **symbols;
     325             :      size_t num, snum;
     326             :      struct linked_list_entry *p;
     327             : 
     328             :      /* Count static functions */
     329          14 :      snum = 0;
     330          14 :      if (static_func_list)
     331         627 :           for (p = linked_list_head(static_func_list); p; p = p->next)
     332         615 :                snum++;
     333             :      
     334             :      /* Collect global functions */
     335          14 :      num = collect_symbols(&symbols, symbol_is_function, snum);
     336             : 
     337             :      /* Collect static functions */
     338          14 :      if (snum) 
     339         627 :           for (p = linked_list_head(static_func_list); p; p = p->next)
     340         615 :                symbols[num++] = p->data;
     341          14 :      *return_sym = symbols;
     342          14 :      return num;
     343             : }
     344             : 
     345             : 
     346             : 
     347             : /* Special handling for function parameters */
     348             : 
     349             : int
     350        8430 : delete_parms_itr(void *data, void *call_data)
     351             : {
     352        8430 :      int level = *(int*)call_data;
     353        8430 :      Symbol *s = data;
     354        8430 :      struct table_entry *t = s->owner;
     355             :           
     356        8430 :      if (!t)
     357           0 :           return 1;
     358        8430 :      if (s->type == SymIdentifier && s->storage == AutoStorage
     359        8430 :          && s->flag == symbol_parm && s->level > level) {
     360         582 :           delete_symbol(s);
     361         582 :           return 1;
     362             :      }
     363        7848 :      return 0;
     364             : }
     365             : 
     366             : /* Delete all parameters with parameter nesting level greater than LEVEL */
     367             : void
     368       12093 : delete_parms(int level)
     369             : {
     370       12093 :      linked_list_iterate(&auto_symbol_list, delete_parms_itr, &level);
     371       12093 : }
     372             : 
     373             : /* Redeclare all saved parameters as automatic variables with the
     374             :    given nesting level */
     375             : void
     376        3102 : move_parms(int level)
     377             : {
     378             :      struct linked_list_entry *p;
     379             : 
     380        7202 :      for (p = linked_list_head(auto_symbol_list); p; p = p->next) {
     381        4100 :           Symbol *s = p->data;
     382             : 
     383        4100 :           if (s->type == SymIdentifier && s->storage == AutoStorage
     384        4100 :               && s->flag == symbol_parm) {
     385        4100 :                s->level = level;
     386        4100 :                s->flag = symbol_none;
     387             :           }
     388             :      }
     389        3102 : }
     390             : 

Generated by: LCOV version 1.10