Beef up unit tests for SI95 code
[ric-plt/lib/rmr.git] / src / rmr / common / src / symtab.c
index e96af03..9fb01bd 100644 (file)
@@ -1,8 +1,8 @@
 // : vi ts=4 sw=4 noet :
 /*
 ==================================================================================
 // : vi ts=4 sw=4 noet :
 /*
 ==================================================================================
-       Copyright (c) 2019 Nokia
-       Copyright (c) 2018-2019 AT&T Intellectual Property.
+       Copyright (c) 2019-2020 Nokia
+       Copyright (c) 2018-2020 AT&T Intellectual Property.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
@@ -33,6 +33,10 @@ Abstract:    Symbol table -- slightly streamlined from it's original 2000 version
                                  incorporated into the RIC msg routing library and will be
                                  available to user applications.
 
                                  incorporated into the RIC msg routing library and will be
                                  available to user applications.
 
+                       There is NO logging from this module!  The caller is asusmed to
+                       report any failures as it might handle them making any error messages
+                       generated here misleading if not incorrect.
+
 Date:          11 Feb 2000
 Author:                E. Scott Daniels
 
 Date:          11 Feb 2000
 Author:                E. Scott Daniels
 
@@ -42,12 +46,14 @@ Mod:                2016 23 Feb - converted Symtab refs so that caller need only a
 ------------------------------------------------------------------------------
 */
 
 ------------------------------------------------------------------------------
 */
 
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 #include <memory.h>
 #include <netdb.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 #include <memory.h>
 #include <netdb.h>
+#include <pthread.h>
 
 #include "rmr_symtab.h"
 
 
 #include "rmr_symtab.h"
 
@@ -79,8 +85,6 @@ static int sym_hash( const char *n, long size )
 {
        const char *p;
        long t = 0;
 {
        const char *p;
        long t = 0;
-       unsigned long tt = 0;
-       unsigned long x = 79;
 
        for( p = n; *p; p++ )      /* a bit of magic */
                t = (t * 79 ) + *p;
 
        for( p = n; *p; p++ )      /* a bit of magic */
                t = (t * 79 ) + *p;
@@ -91,7 +95,10 @@ static int sym_hash( const char *n, long size )
        return (int ) (t % size);
 }
 
        return (int ) (t % size);
 }
 
-/* delete element pointed to by eptr at hash loc hv */
+/*
+       Delete element pointed to by eptr which is assumed to be
+       a member of the list at symtab[i].
+*/
 static void del_ele( Sym_tab *table, int hv, Sym_ele *eptr )
 {
        Sym_ele **sym_tab;
 static void del_ele( Sym_tab *table, int hv, Sym_ele *eptr )
 {
        Sym_ele **sym_tab;
@@ -119,6 +126,39 @@ static void del_ele( Sym_tab *table, int hv, Sym_ele *eptr )
        }
 }
 
        }
 }
 
+/*
+       Delete the head element from table[i]. This isn't really
+       needed, but keeps code analysers from claiming that memory
+       is being used after it is freed.
+*/
+static void del_head_ele( Sym_tab *table, int hv ) {
+       Sym_ele **sym_tab;
+       Sym_ele *eptr;          // first in list
+
+
+       if( hv < 0 || hv >= table->size ) {
+               return;
+       }
+
+       sym_tab = table->symlist;
+       if( (eptr = sym_tab[hv]) != NULL )                                      // not an empty element; yank it off
+       {
+               if( (sym_tab[hv] = eptr->next) != NULL ) {              // bump list to next if not the only thing here
+                       sym_tab[hv]->prev = NULL;                                       // new head
+               }
+               eptr->next = NULL;                                                              // take no chances
+
+               if( eptr->class && eptr->name ) {                               // class 0 entries are numeric, so name is NOT a pointer
+                       free( (void *) eptr->name );
+               }
+
+               free( eptr );
+
+               table->deaths++;
+               table->inhabitants--;
+       }
+}
+
 /*
        Determine if these are the same.
 */
 /*
        Determine if these are the same.
 */
@@ -138,8 +178,8 @@ static inline int same( unsigned int c1, unsigned int c2, const char *s1, const
        much the same.
 */
 static int putin( Sym_tab *table, const char *name, unsigned int class, void *val ) {
        much the same.
 */
 static int putin( Sym_tab *table, const char *name, unsigned int class, void *val ) {
-       Sym_ele *eptr;                  /* pointer into hash table */
-       Sym_ele **sym_tab;      /* pointer into hash table */
+       Sym_ele *eptr;                  /* pointer into hash table */
+       Sym_ele **sym_tab;              /* pointer into hash table */
        int hv;                 /* hash value */
        int rc = 0;             /* assume it existed */
        uint64_t nkey = 0;              // numeric key if class == 0
        int hv;                 /* hash value */
        int rc = 0;             /* assume it existed */
        uint64_t nkey = 0;              // numeric key if class == 0
@@ -155,13 +195,13 @@ static int putin( Sym_tab *table, const char *name, unsigned int class, void *va
                for( eptr=sym_tab[hv]; eptr && eptr->nkey != nkey; eptr=eptr->next );
        }
 
                for( eptr=sym_tab[hv]; eptr && eptr->nkey != nkey; eptr=eptr->next );
        }
 
-       if( ! eptr ) {                  // not found above, so add
+       if( ! eptr ) {                  // not found above, so add
                rc++;
                table->inhabitants++;
 
                eptr = (Sym_ele *) malloc( sizeof( Sym_ele) );
                if( ! eptr ) {
                rc++;
                table->inhabitants++;
 
                eptr = (Sym_ele *) malloc( sizeof( Sym_ele) );
                if( ! eptr ) {
-                       fprintf( stderr, "[FAIL] symtab/putin: out of memory\n" );
+                       errno = ENOMEM;
                        return -1;
                }
 
                        return -1;
                }
 
@@ -200,9 +240,11 @@ extern void rmr_sym_clear( void *vtable )
        table = (Sym_tab *) vtable;
        sym_tab = table->symlist;
 
        table = (Sym_tab *) vtable;
        sym_tab = table->symlist;
 
-       for( i = 0; i < table->size; i++ )
-               while( sym_tab[i] )
-                       del_ele( table, i, sym_tab[i] );
+       for( i = 0; i < table->size; i++ ) {
+               while( sym_tab[i] ) {
+                       del_head_ele( table, i );                       // delete the head element (and keep bloody sonar from claiming use after free)
+               }
+       }
 }
 
 /*
 }
 
 /*
@@ -231,15 +273,14 @@ extern void rmr_sym_dump( void *vtable )
        table = (Sym_tab *) vtable;
        sym_tab = table->symlist;
 
        table = (Sym_tab *) vtable;
        sym_tab = table->symlist;
 
-       for( i = 0; i < table->size; i++ )
-       {
-               if( sym_tab[i] )
-               for( eptr = sym_tab[i]; eptr; eptr = eptr->next )
-               {
-                       if( eptr->val && eptr->class ) {
-                               fprintf( stderr, "key=%s val@=%p\n", eptr->name, eptr->val );
-                       } else {
-                               fprintf( stderr, "nkey=%lu val@=%p\n", (unsigned long) eptr->nkey, eptr->val );
+       for( i = 0; i < table->size; i++ ) {
+               if( sym_tab[i] ) {
+                       for( eptr = sym_tab[i]; eptr; eptr = eptr->next ) {
+                               if( eptr->val && eptr->class ) {
+                                       fprintf( stderr, "symtab dump: key=%s val@=%p\n", eptr->name, eptr->val );
+                               } else {
+                                       fprintf( stderr, "symtab dump: nkey=%lu val@=%p\n", (unsigned long) eptr->nkey, eptr->val );
+                               }
                        }
                }
        }
                        }
                }
        }
@@ -251,7 +292,6 @@ extern void rmr_sym_dump( void *vtable )
 */
 extern void *rmr_sym_alloc( int size )
 {
 */
 extern void *rmr_sym_alloc( int size )
 {
-       int i;
        Sym_tab *table;
 
        if( size < 11 )     /* provide a bit of sanity */
        Sym_tab *table;
 
        if( size < 11 )     /* provide a bit of sanity */
@@ -259,7 +299,7 @@ extern void *rmr_sym_alloc( int size )
 
        if( (table = (Sym_tab *) malloc( sizeof( Sym_tab ))) == NULL )
        {
 
        if( (table = (Sym_tab *) malloc( sizeof( Sym_tab ))) == NULL )
        {
-               fprintf( stderr, "rmr_sym_alloc: unable to get memory for symtable (%d elements)", size );
+               errno = ENOMEM;
                return NULL;
        }
 
                return NULL;
        }
 
@@ -272,7 +312,7 @@ extern void *rmr_sym_alloc( int size )
        }
        else
        {
        }
        else
        {
-               fprintf( stderr, "sym_alloc: unable to get memory for %d elements", size );
+               errno = ENOMEM;
                return NULL;
        }
 
                return NULL;
        }
 
@@ -308,7 +348,7 @@ extern void rmr_sym_del( void *vtable, const char *name, unsigned int class )
 /*
        Delete element by numberic key.
 */
 /*
        Delete element by numberic key.
 */
-extern void *rmr_sym_ndel(  void *vtable, uint64_t key ) {
+extern void rmr_sym_ndel(  void *vtable, uint64_t key ) {
        rmr_sym_del( vtable, (const char *) &key, 0 );
 }
 
        rmr_sym_del( vtable, (const char *) &key, 0 );
 }
 
@@ -321,7 +361,10 @@ extern void *rmr_sym_get( void *vtable, const char *name, unsigned int class )
        int hv;                 // hash value of key
        uint64_t nkey;                  // numeric key if class 0
 
        int hv;                 // hash value of key
        uint64_t nkey;                  // numeric key if class 0
 
-       table = (Sym_tab *) vtable;
+       if( (table = (Sym_tab *) vtable) == NULL ) {
+               return NULL;
+       }
+
        sym_tab = table->symlist;
 
        if( class ) {
        sym_tab = table->symlist;
 
        if( class ) {
@@ -407,9 +450,9 @@ extern void rmr_sym_stats( void *vtable, int level )
                                ch_count++;
                                if( level > 3 ) {
                                        if( eptr->class  ) {                                    // a string key
                                ch_count++;
                                if( level > 3 ) {
                                        if( eptr->class  ) {                                    // a string key
-                                               fprintf( stderr, "sym: (%d) key=%s val@=%p ref=%ld mod=%lu\n", i, eptr->name, eptr->val, eptr->rcount, eptr->mcount );
+                                               fprintf( stderr, " symtab stats: sym: (%d) key=%s val@=%p ref=%ld mod=%lu\n", i, eptr->name, eptr->val, eptr->rcount, eptr->mcount );
                                        } else {
                                        } else {
-                                               fprintf( stderr, "sym: (%d) key=%lu val@=%p ref=%ld mod=%lu\n", i, (unsigned long) eptr->nkey, eptr->val, eptr->rcount, eptr->mcount );
+                                               fprintf( stderr, "symtab stats: sym: (%d) key=%lu val@=%p ref=%ld mod=%lu\n", i, (unsigned long) eptr->nkey, eptr->val, eptr->rcount, eptr->mcount );
                                        }
                                }
                        }
                                        }
                                }
                        }
@@ -426,12 +469,12 @@ extern void rmr_sym_stats( void *vtable, int level )
                        twoper++;
 
                if( level > 2 )
                        twoper++;
 
                if( level > 2 )
-                       fprintf( stderr, "sym: (%d) chained=%ld\n", i, ch_count );
+                       fprintf( stderr, "symtab stats: sym: (%d) chained=%ld\n", i, ch_count );
        }
 
        if( level > 1 )
        {
        }
 
        if( level > 1 )
        {
-               fprintf( stderr, "sym: longest chain: idx=%d has %ld elsements):\n", maxi, max_chain );
+               fprintf( stderr, "symtab stats: sym: longest chain: idx=%d has %ld elsements):\n", maxi, max_chain );
                for( eptr = sym_tab[maxi]; eptr; eptr = eptr->next ) {
                        if( eptr->class ) {
                                fprintf( stderr, "\t%s\n", eptr->name );
                for( eptr = sym_tab[maxi]; eptr; eptr = eptr->next ) {
                        if( eptr->class ) {
                                fprintf( stderr, "\t%s\n", eptr->name );
@@ -441,7 +484,7 @@ extern void rmr_sym_stats( void *vtable, int level )
                }
        }
 
                }
        }
 
-       fprintf( stderr, "sym:%ld(size)  %ld(inhab) %ld(occupied) %ld(dead) %ld(maxch) %d(>2per)\n",
+       fprintf( stderr, "symtab stats: sym:%ld(size)  %ld(inhab) %ld(occupied) %ld(dead) %ld(maxch) %d(>2per)\n",
                        table->size, table->inhabitants, table->size - empty, table->deaths, max_chain, twoper );
 }
 
                        table->size, table->inhabitants, table->size - empty, table->deaths, max_chain, twoper );
 }
 
@@ -456,17 +499,22 @@ extern void rmr_sym_foreach_class( void *vst, unsigned int class, void (* user_f
        Sym_ele **list;
        Sym_ele *se;
        Sym_ele *next;          /* allows user to delete the node(s) we return */
        Sym_ele **list;
        Sym_ele *se;
        Sym_ele *next;          /* allows user to delete the node(s) we return */
-       int     i;
+       int             i;
 
 
-       st = (Sym_tab *) vst;
+       if( (st = (Sym_tab *) vst) == NULL ) {
+               return;
+       }
 
 
-       if( st && (list = st->symlist) != NULL && user_fun != NULL )
-               for( i = 0; i < st->size; i++ )
-                       for( se = list[i]; se; se = next )              /* using next allows user to delet via this */
-                       {
-                               next = se->next;
+       if( (list = st->symlist) != NULL && user_fun != NULL ) {
+               for( i = 0; i < st->size; i++ ) {
+                       se = list[i];
+                       while( se ) {
+                               next = se->next;                        // allow callback to delete from the list w/o borking us
                                if( class == se->class ) {
                                        user_fun( st, se, se->name, se->val, user_data );
                                }
                                if( class == se->class ) {
                                        user_fun( st, se, se->name, se->val, user_data );
                                }
+                               se = next;
                        }
                        }
+               }
+       }
 }
 }