123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- #include "cmPrefix.h"
- #include "cmGlobal.h"
- #include "cmRpt.h"
- #include "cmErr.h"
- #include "cmCtx.h"
- #include "cmMem.h"
- #include "cmMallocDebug.h"
- #include "cmSymTbl.h"
- #include "cmLinkedHeap.h"
-
- cmSymTblH_t cmSymTblNullHandle = cmSTATIC_NULL_HANDLE;
-
- enum
- {
- kDynStFl = 0x01
- };
-
- typedef struct cmSymLabel_str
- {
- unsigned flags;
- const cmChar_t* label;
- } cmSymLabel_t;
-
-
- struct cmSym_str;
-
- typedef struct cmSymAvail_str
- {
- unsigned id;
- struct cmSym_str* linkPtr;
- } cmSymAvail_t;
-
- typedef struct cmSym_str
- {
- union
- {
- cmSymLabel_t label;
- cmSymAvail_t avail;
- } u;
- } cmSym_t;
-
- typedef struct cmSymBlock_t
- {
- cmSym_t* base; // block base - contains cmSymTbl_t.symPerBlock cmSym_t records
- unsigned cnt; // cout of symbols actually used in this block
- struct cmSymBlock_t* link; // next block
- } cmSymBlock_t;
-
- typedef struct
- {
- cmSymTblH_t parentH; // parent symbols table
- cmLHeapH_t heapH; // symbol label storage
- cmSymBlock_t* first; // pointer to head of symbol block chain
- cmSymBlock_t* last; // pointer to last symbol block in chain
- unsigned blkCnt; // count of blocks on chain
- unsigned symCnt; // total count of symbols controlled by this symbol (does not include parent symbols)
- unsigned baseSymId;
- unsigned symPerBlock;
- cmSym_t* availPtr;
- } cmSymTbl_t;
-
- cmSymTbl_t* _cmSymTblHandleToPtr( cmSymTblH_t h )
- {
- cmSymTbl_t* stp = (cmSymTbl_t*)h.h;
- assert( stp != NULL );
- return stp;
- }
-
- cmSymBlock_t* _cmSymTblAllocateBlock( cmSymTbl_t* stp )
- {
- // allocate the new block
- cmSymBlock_t* sbp = (cmSymBlock_t*)cmMemMallocZ( sizeof(cmSymBlock_t) + (stp->symPerBlock * sizeof(cmSym_t)));
-
- // initialize the new block control recd
- sbp->base = (cmSym_t*)(sbp+1);
- sbp->cnt = 0;
- sbp->link = NULL;
-
- // add the new block control recd to the end of the block chain
- if( stp->last == NULL )
- stp->first = sbp;
- else
- stp->last->link = sbp;
-
- // the new block control recd always becomes the last recd in the chain
- stp->last = sbp;
-
- ++stp->blkCnt;
-
- return sbp;
- }
-
- bool _cmSymTblIsSymbolRemoved( cmSymTbl_t* stp, unsigned symId )
- {
- const cmSym_t* sp = stp->availPtr;
- for(; sp != NULL; sp=sp->u.avail.linkPtr)
- if( sp->u.avail.id == symId )
- return true;
- return false;
- }
-
- unsigned _cmSymTblLabelToId( cmSymTbl_t* stp, const char* label )
- {
- cmSymBlock_t* sbp = stp->first;
-
- unsigned symId = stp->baseSymId;
-
- while( sbp != NULL )
- {
- cmSym_t* sp = sbp->base;
- cmSym_t* ep = sbp->base + sbp->cnt;
-
- for(; sp<ep; ++sp,++symId)
- {
- if( _cmSymTblIsSymbolRemoved(stp, symId ) == false )
- if( strcmp( sp->u.label.label, label ) == 0 )
- return symId;
- }
- sbp = sbp->link;
- }
-
- return cmInvalidId;
- }
-
- cmSym_t* _cmSymTblIdToSymPtr( cmSymTbl_t* stp, unsigned symId )
- {
- if( cmSymTblIsValid(stp->parentH) && cmSymTblIsValidId( stp->parentH, symId ) )
- return _cmSymTblIdToSymPtr( _cmSymTblHandleToPtr(stp->parentH), symId );
-
- symId -= stp->baseSymId;
-
- unsigned n = symId / stp->symPerBlock;
- unsigned i = symId % stp->symPerBlock;
-
- if( n >= stp->blkCnt )
- return NULL;
-
- cmSymBlock_t* sbp = stp->first;
-
- unsigned j;
- for(j=0; j<n; ++j)
- sbp = sbp->link;
-
- if( i >= sbp->cnt )
- return NULL;
-
- return sbp->base + i;
- }
-
- cmSymTblH_t cmSymTblCreate( cmSymTblH_t parentH, unsigned baseSymId, cmCtx_t* ctx )
- {
- cmSymTblH_t h;
- cmSymTbl_t* stp = cmMemAllocZ( cmSymTbl_t, 1 );
-
- stp->heapH = cmLHeapCreate( 2048, ctx );
- stp->symPerBlock = 3;
- stp->baseSymId = baseSymId;
- stp->parentH = parentH;
-
- _cmSymTblAllocateBlock( stp );
-
-
- h.h = stp;
- return h;
- }
-
- void cmSymTblDestroy( cmSymTblH_t* hp )
- {
- if( hp==NULL || hp->h == NULL )
- return;
-
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(*hp);
-
- assert( stp != NULL );
-
- cmSymBlock_t* sbp = stp->first;
- while( sbp != NULL )
- {
- cmSymBlock_t* t = sbp;
- sbp = sbp->link;
- cmMemFree(t);
- }
-
- cmLHeapDestroy(&stp->heapH);
-
- cmMemFree(hp->h);
-
- hp->h = NULL;
-
- }
-
- unsigned cmSymTblRegister( cmSymTblH_t h, const char* label, bool staticFl )
- {
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
- unsigned symId;
- unsigned flags = 0;
- cmSym_t* sp = NULL;
-
- // check for the label in the local symbol table
- if((symId = _cmSymTblLabelToId( stp, label )) != cmInvalidId )
- return symId;
-
- // check for the label in the parent symbol table
- if( cmSymTblIsValid(stp->parentH) )
- if((symId = _cmSymTblLabelToId( _cmSymTblHandleToPtr(stp->parentH), label)) != cmInvalidId )
- return symId;
-
- // if the label is not static then create a copy of it on the local heap
- if( !staticFl )
- {
- char* cp = (char*)cmLHeapAlloc( stp->heapH, strlen(label) + 1 );
- strcpy(cp,label);
- label = cp;
- flags |= kDynStFl;
- }
-
- // if there are no previosly removed symbols available
- if( stp->availPtr == NULL )
- {
- cmSymBlock_t*sbp = stp->last;
-
- // if the last block is full
- if( sbp->cnt == stp->symPerBlock )
- sbp = _cmSymTblAllocateBlock(stp);
-
- // the last block must now have an empty slot
- assert( sbp->cnt < stp->symPerBlock );
-
-
- unsigned idx = sbp->cnt++;
- sp = sbp->base + idx;
- //sbp->base[ idx ].u.label.label = label;
- //sbp->base[ idx ].u.label.flags = flags;
-
- // calculate the symbol id
- symId = stp->baseSymId + ((stp->blkCnt-1) * stp->symPerBlock) + sbp->cnt - 1;
- }
- else // there are previously removed symbols available
- {
- sp = stp->availPtr; // get the next avail symbol
- stp->availPtr = sp->u.avail.linkPtr; // take it off the avail list
- symId = sp->u.avail.id; // store the new symbol's id
- }
-
- // setup the symbol record
- sp->u.label.label = label;
- sp->u.label.flags = flags;
-
- // verify that the new symId does not already belong to the parent
- assert( cmSymTblIsValid(stp->parentH)==false ? 1 : cmSymTblLabel( stp->parentH, symId)==NULL );
-
- ++stp->symCnt;
-
- return symId;
-
- }
-
- unsigned cmSymTblRegisterSymbol( cmSymTblH_t h, const char* label )
- { return cmSymTblRegister( h, label, false ); }
-
- unsigned cmSymTblRegisterStaticSymbol( cmSymTblH_t h, const char* label )
- { return cmSymTblRegister( h, label, true ); }
-
- unsigned cmSymTblRegisterVFmt( cmSymTblH_t h, const cmChar_t* fmt, va_list vl )
- {
- unsigned n = vsnprintf(NULL,0,fmt,vl);
- cmChar_t b[n+1];
- vsnprintf(b,n,fmt,vl);
- return cmSymTblRegister(h,fmt,vl);
-
- }
-
- unsigned cmSymTblRegisterFmt( cmSymTblH_t h, const cmChar_t* fmt, ... )
- {
- va_list vl;
- va_start(vl,fmt);
- unsigned id = cmSymTblRegisterVFmt(h,fmt,vl);
- va_end(vl);
- return id;
- }
-
-
- bool cmSymTblRemove( cmSymTblH_t h, unsigned symId )
- {
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
-
- cmSym_t* sp;
-
- if((sp = _cmSymTblIdToSymPtr(stp,symId)) == NULL )
- return false;
-
- if( cmIsFlag(sp->u.label.flags,kDynStFl))
- cmLHeapFree(stp->heapH,(void*)sp->u.label.label);
-
- sp->u.avail.id = symId;
- sp->u.avail.linkPtr = stp->availPtr;
- stp->availPtr = sp;
-
-
- return true;
- }
-
-
- const char* cmSymTblLabel( cmSymTblH_t h, unsigned symId )
- {
-
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
-
- cmSym_t* sp;
-
- if((sp = _cmSymTblIdToSymPtr(stp,symId)) == NULL )
- return NULL;
-
- return sp->u.label.label;
- }
-
- unsigned cmSymTblId( cmSymTblH_t h, const char* label )
- {
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
- unsigned id;
- if((id=_cmSymTblLabelToId(stp,label)) == cmInvalidId )
- if( cmSymTblIsValid(stp->parentH))
- return _cmSymTblLabelToId( _cmSymTblHandleToPtr(stp->parentH), label );
- return id;
- }
-
- bool cmSymTblIsValid( cmSymTblH_t h )
- { return h.h != NULL; }
-
- bool cmSymTblIsValidId( cmSymTblH_t h, unsigned symId )
- {
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
- return stp->baseSymId <= symId && symId < (stp->baseSymId + stp->symCnt);
- }
-
- void cmSymTblReport( cmSymTblH_t h )
- {
- cmSymTbl_t* stp = _cmSymTblHandleToPtr(h);
- cmSymBlock_t* sbp = stp->first;
- unsigned i=0, j=0, symId = stp->baseSymId;
-
- printf("blks:%i syms:%i\n", stp->blkCnt, stp->symCnt );
-
- for(; sbp != NULL; sbp=sbp->link,++i)
- for(j=0; j<sbp->cnt; ++j,++symId)
- {
- bool remFl = _cmSymTblIsSymbolRemoved(stp, symId );
- printf("blk:%i sym:%i id:%i label:%s\n",i,j,symId,remFl ? "<removed>" : sbp->base[j].u.label.label);
- }
-
- }
-
- //{ { label:cmSymTblEx }
- //(
- // cmSymTblTest() gives a usage example for the symbol table component.
- //)
-
- //[
- void cmSymTblTest( cmCtx_t* ctx )
- {
- unsigned baseSymId = 100;
- unsigned i;
- unsigned n = 10;
- unsigned idArray[n];
-
- // create a symbol table
- cmSymTblH_t h = cmSymTblCreate( cmSymTblNullHandle, baseSymId, ctx );
-
- if( cmSymTblIsValid(h) == false )
- {
- cmRptPrintf(&ctx->rpt,"Symbol table creation failed.");
- return;
- }
-
- // generate and register some symbols
- for(i=0; i<n; ++i)
- {
- bool staticFl = false;
- char str[10];
- snprintf(str,9,"sym%i",i);
- idArray[i] = cmSymTblRegister( h, str, staticFl );
- }
-
- // remove the fourth symbol generated
- cmSymTblRemove( h, baseSymId+3 );
-
- // print the symbol table
- cmSymTblReport(h);
-
- // iterate through the symbol table
- for(i=0; i<n; ++i)
- {
- const cmChar_t* lbl = cmSymTblLabel(h,idArray[i]);
-
- if( lbl == NULL )
- cmRptPrintf(&ctx->rpt,"%i <removed>\n",i);
- else
- cmRptPrintf(&ctx->rpt,"%i %i==%i %s \n",i,idArray[i],cmSymTblId(h,lbl),lbl);
- }
-
- // release the symbol table
- cmSymTblDestroy(&h);
-
- return;
- }
- //]
- //}
|