diff options
Diffstat (limited to 'project/dclib/dclib-basics.c')
| -rw-r--r-- | project/dclib/dclib-basics.c | 934 |
1 files changed, 862 insertions, 72 deletions
diff --git a/project/dclib/dclib-basics.c b/project/dclib/dclib-basics.c index 7504951..bf0496c 100644 --- a/project/dclib/dclib-basics.c +++ b/project/dclib/dclib-basics.c @@ -34,11 +34,6 @@ #define _GNU_SOURCE 1 -#ifndef WIN_SZS_LIB - // needed for GetTermWidthFD() - #include <sys/ioctl.h> -#endif - #include <string.h> #include <unistd.h> #include <time.h> @@ -47,6 +42,7 @@ #include <errno.h> #include <sys/time.h> #include <fcntl.h> +#include <sys/ioctl.h> #include "dclib-basics.h" #include "dclib-debug.h" @@ -302,6 +298,21 @@ int GetProgramPath { char path[PATH_MAX], path2[PATH_MAX]; +#ifdef __APPLE__ + + //--- read apple path of executable + + extern int _NSGetExecutablePath( char* buf, uint32_t * bufsize ); + + uint32_t size = sizeof(path); + if (!_NSGetExecutablePath(path,&size)) + { + if ( realpath(path,path2) && *path2 ) + return StringCopyS(buf,buf_size,path2) - buf; + return StringCopyS(buf,buf_size,path) - buf; + } + +#else // !__APPLE__ //--- read files of /proc/... @@ -321,6 +332,8 @@ int GetProgramPath return StringCopyS(buf,buf_size,path) - buf; } +#endif // !__APPLE__ + //--- analyze argv0 @@ -377,9 +390,9 @@ int GetProgramPath void FreeString ( ccp str ) { - noTRACE("FreeString(%p) EmptyString=%p MinusString=%p\n", - str, EmptyString, MinusString ); - if ( str != EmptyString && str != EmptyQuote && str != MinusString ) + noTRACE("FreeString(%p) EmptyString=%p MinusString=%p, IsCircBuf=%d\n", + str, EmptyString, MinusString, IsCircBuf(str) ); + if ( str != EmptyString && str != EmptyQuote && str != MinusString && !IsCircBuf(str) ) FREE((char*)str); } @@ -506,19 +519,18 @@ char * StringCat3S ( char * buf, size_t buf_size, ccp src1, ccp src2, ccp src3 ) } /////////////////////////////////////////////////////////////////////////////// -// [[?]] -char * StringCat2A ( ccp src1, ccp src2 ) +char * StringCat2A ( ccp src1, ccp src2 ) { - mem_t mem = MemCat2A( MemByString(src1), MemByString(src2) ); + mem_t mem = MemCat2A( MemByString0(src1), MemByString0(src2) ); return (char*)mem.ptr; } //----------------------------------------------------------------------------- -char * StringCat3A ( ccp src1, ccp src2, ccp src3 ) +char * StringCat3A ( ccp src1, ccp src2, ccp src3 ) { - mem_t mem = MemCat3A( MemByString(src1), MemByString(src2), MemByString(src3) ); + mem_t mem = MemCat3A( MemByString0(src1), MemByString0(src2), MemByString0(src3) ); return (char*)mem.ptr; } @@ -1554,9 +1566,16 @@ static char *circ_ptr = circ_buf; /////////////////////////////////////////////////////////////////////////////// +bool IsCircBuf ( cvp ptr ) +{ + return ptr && (ccp)ptr >= circ_buf && (ccp)ptr < circ_buf + sizeof(circ_buf); +} + +/////////////////////////////////////////////////////////////////////////////// + char * GetCircBuf ( - // never returns NULL, but always ALIGN(4) + // Never returns NULL, but always ALIGN(4) u32 buf_size // wanted buffer size, caller must add 1 for NULL-term // if buf_size > CIRC_BUF_MAX_ALLOC: @@ -1591,7 +1610,7 @@ char * GetCircBuf char * CopyCircBuf ( - // never returns NULL, but always ALIGN(4) + // Never returns NULL, but always ALIGN(4) cvp data, // source to copy u32 data_size // see GetCircBuf() @@ -1606,8 +1625,8 @@ char * CopyCircBuf char * CopyCircBuf0 ( - // never returns NULL, but always ALIGN(4) - // an additional char is alloced and set to NULL + // Like CopyCircBuf(), but an additional char is alloced and set to NULL + // Never returns NULL, but always ALIGN(4). cvp data, // source to copy u32 data_size // see GetCircBuf() @@ -1623,6 +1642,8 @@ char * CopyCircBuf0 char * PrintCircBuf ( + // returns CopyCircBuf0() or EmptyString. + ccp format, // format string for vsnprintf() ... // arguments for 'format' ) @@ -1638,6 +1659,51 @@ char * PrintCircBuf /////////////////////////////////////////////////////////////////////////////// +char * AllocCircBuf +( + // Never returns NULL. Call FreeString(RESULT) to free possible alloced memory. + + cvp src, // NULL or source + int src_len, // len of 'src'; if -1: use strlen(source) + bool try_circ // use circ-buffer, if result is small enough +) +{ + if (!src) + return (char*)EmptyString; + + if ( src_len < 0 ) + src_len = strlen(src); + + return try_circ && src_len <= CIRC_BUF_MAX_ALLOC + ? CopyCircBuf(src,src_len) + : MEMDUP(src,src_len); +} + +/////////////////////////////////////////////////////////////////////////////// + +char * AllocCircBuf0 +( + // Never returns NULL. Call FreeString(RESULT) to free possible alloced memory. + // Like AllocCircBuf(), but an additional char is alloced and set to NULL + + cvp src, // NULL or source + int src_len, // len of 'src'; if -1: use strlen(source) + bool try_circ // use circ-buffer, if result is small enough +) +{ + if (!src) + return (char*)EmptyString; + + if ( src_len < 0 ) + src_len = strlen(src); + + return try_circ && src_len < CIRC_BUF_MAX_ALLOC + ? CopyCircBuf0(src,src_len) + : MEMDUP(src,src_len); // MEMDUP() always add 0-term +} + +/////////////////////////////////////////////////////////////////////////////// + void ReleaseCircBuf ( ccp end_buf, // pointer to end of previous alloced buffer @@ -2408,26 +2474,186 @@ mem_t MemCat3A ( const mem_t m1, const mem_t m2, const mem_t m3 ) // /////////////////////////////////////////////////////////////////////////////// -/////////////// struct mem_list_t /////////////// +/////////////// struct exmem_t /////////////// + +exmem_t EmptyExMem = {{EmptyString,0},0,false,false,false,false}; +exmem_t NullExMem = {{0,0},0,false,false,false,false}; + /////////////////////////////////////////////////////////////////////////////// -void InitializeMemList ( mem_list_t *ml ) +void FreeExMem ( const exmem_t *em ) { - DASSERT(ml); - memset(ml,0,sizeof(*ml)); + if (em) + { + if (em->is_alloced) + FreeString(em->data.ptr); + memset((exmem_t*)em,0,sizeof(*em)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void FreeExMemCM ( const exmem_t *em, CopyMode_t copy_mode ) +{ + if ( em && copy_mode == CPM_MOVE ) + { + if (em->is_alloced) + FreeString(em->data.ptr); + memset((exmem_t*)em,0,sizeof(*em)); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_t AllocExMemS +( + cvp src, // NULL or source + int src_len, // len of 'src'; if -1: use strlen(source) + bool try_circ, // use circ-buffer, if result is small enough + cvp orig, // NULL or data to compare + int orig_len // len of 'orig'; if -1: use strlen(source) +) +{ + exmem_t em = {{0}}; + if (src) + { + if ( src_len < 0 ) + src_len = strlen(src); + if (!src_len) + em.data.ptr = EmptyString; + else + { + em.data.len = src_len; + if ( orig + && src_len == ( orig_len < 0 ? strlen(orig) : orig_len ) + && !memcmp(src,orig,src_len) + ) + { + em.data.ptr = orig; + em.is_original = true; + } + else if ( try_circ && src_len <= CIRC_BUF_MAX_ALLOC ) + { + em.data.ptr = CopyCircBuf(src,src_len); + em.is_circ_buf = true; + } + else + { + em.data.ptr = MEMDUP(src,src_len); + em.is_alloced = true; + } + } + } + + return em; } /////////////////////////////////////////////////////////////////////////////// +void AssignExMem ( exmem_t *dest, const exmem_t *source, CopyMode_t copy_mode ) +{ + if ( dest && dest != source ) + { + if (dest->is_alloced) + FreeString(dest->data.ptr); + const bool dest_key_alloced = dest->is_key_alloced; + if (source) + { + switch (copy_mode) + { + case CPM_COPY: + memset(dest,0,sizeof(*dest)); + dest->data.len = source->data.len; + dest->data.ptr = MEMDUP(source->data.ptr,source->data.len); + dest->is_alloced = true; + dest->attrib = source->attrib; + break; + + case CPM_MOVE: + *dest = *source; + memset((exmem_t*)source,0,sizeof(*source)); + break; + + case CPM_LINK: + *dest = *source; + dest->is_original = false; + dest->is_alloced = false; + break; + } + } + else + memset(dest,0,sizeof(*dest)); + dest->is_key_alloced = dest_key_alloced; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_t CopyExMemS ( ccp string, int slen, CopyMode_t copy_mode ) +{ + exmem_t em = {{0}}; + + if (string) + { + em.data.len = slen < 0 ? strlen(string) : slen; + + switch (copy_mode) + { + case CPM_COPY: + em.data.ptr = MEMDUP(string,em.data.len); + em.is_alloced = true; + break; + + case CPM_MOVE: + em.is_alloced = true; + // fall through + case CPM_LINK: + em.data.ptr = string; + break; + } + } + + return em; +} + +/////////////////////////////////////////////////////////////////////////////// + +ccp PrintExMem ( const exmem_t * em ) // print to circ-buf +{ + if (!em) + return MinusString; + + char ebuf[60]; + uint len; + PrintEscapedString(ebuf,sizeof(ebuf),em->data.ptr,em->data.len,CHMD__MODERN,'"',&len); + + return PrintCircBuf( + "[%c%c%c%c:%x] %u/%u %s", + em->is_key_alloced ? 'a' : '-', // flags: same as in DumpEML() + em->is_alloced ? 'A' : '-', + em->is_circ_buf ? 'C' : '-', + em->is_original ? 'O' : '-', + em->attrib, + len, em->data.len, ebuf ); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct mem_list_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + void ResetMemList ( mem_list_t *ml ) { - DASSERT(ml); - FREE(ml->list); - FREE(ml->buf); - memset(ml,0,sizeof(*ml)); + if (ml) + { + FREE(ml->list); + FREE(ml->buf); + memset(ml,0,sizeof(*ml)); + } } /////////////////////////////////////////////////////////////////////////////// +// [[?]] void MoveMemList ( mem_list_t *dest, mem_list_t *src ) { @@ -2448,6 +2674,7 @@ void MoveMemList ( mem_list_t *dest, mem_list_t *src ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] void NeedBufMemList ( mem_list_t *ml, uint need_size, uint extra_size ) { @@ -2480,6 +2707,7 @@ void NeedBufMemList ( mem_list_t *ml, uint need_size, uint extra_size ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] void NeedElemMemList ( mem_list_t *ml, uint need_elem, uint need_size ) { @@ -2497,6 +2725,7 @@ void NeedElemMemList ( mem_list_t *ml, uint need_elem, uint need_size ) /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +// [[?]] void InsertMemListN ( @@ -2643,6 +2872,7 @@ void InsertMemListN /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +// [[?]] void CatMemListN ( @@ -2705,7 +2935,6 @@ void CatMemListN ? MALLOC(sizeof(*new_list)*need_elem) : dest->list; - //--- assign values char *bufptr = new_buf; @@ -2772,6 +3001,7 @@ void CatMemListN /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint LeftMemList ( mem_list_t *ml, int count ) { @@ -2780,6 +3010,7 @@ uint LeftMemList ( mem_list_t *ml, int count ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint RightMemList ( mem_list_t *ml, int count ) { @@ -2795,6 +3026,7 @@ uint RightMemList ( mem_list_t *ml, int count ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint MidMemList ( mem_list_t *ml, int begin, int count ) { @@ -2820,6 +3052,7 @@ uint MidMemList ( mem_list_t *ml, int begin, int count ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint ExtractMemList ( mem_list_t *ml, int begin, int end ) { @@ -2830,6 +3063,7 @@ uint ExtractMemList ( mem_list_t *ml, int begin, int end ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint ExtractEndMemList ( mem_list_t *ml, int begin, int end ) { @@ -2840,6 +3074,7 @@ uint ExtractEndMemList ( mem_list_t *ml, int begin, int end ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint RemoveMemList ( mem_list_t *ml, int begin, int end ) { @@ -2850,6 +3085,7 @@ uint RemoveMemList ( mem_list_t *ml, int begin, int end ) } /////////////////////////////////////////////////////////////////////////////// +// [[?]] uint RemoveEndMemList ( mem_list_t *ml, int begin, int end ) { @@ -4797,10 +5033,11 @@ const KeywordTab_t KeyTab_OFF_AUTO_ON[] = //----------------------------------------------------------------------------- -int ScanKeywordOffAutoOn +int ScanKeywordOffAutoOnEx ( // returns one of OFFON_* + const KeywordTab_t *keytab, // Keyword table. If NULL, then use KeyTab_OFF_AUTO_ON[] ccp arg, // argument to scan int on_empty, // return this value on empty uint max_num, // >0: additionally accept+return number <= max_num @@ -4810,8 +5047,11 @@ int ScanKeywordOffAutoOn if ( !arg || !*arg ) return on_empty; + if (!keytab) + keytab = KeyTab_OFF_AUTO_ON; + int status; - const KeywordTab_t *key = ScanKeyword(&status,arg,KeyTab_OFF_AUTO_ON); + const KeywordTab_t *key = ScanKeyword(&status,arg,keytab); if (key) return key->id; @@ -4824,7 +5064,7 @@ int ScanKeywordOffAutoOn } if (object) - PrintKeywordError(KeyTab_OFF_AUTO_ON,arg,status,0,object); + PrintKeywordError(keytab,arg,status,0,object); return OFFON_ERROR; } @@ -5465,6 +5705,27 @@ void AppendStringField ( StringField_t * sf, ccp key, bool move_key ) /////////////////////////////////////////////////////////////////////////////// +void AppendUniqueStringField ( StringField_t * sf, ccp key, bool move_key ) +{ + DASSERT(sf); + if (!key) + return; + + ccp * src = sf->field; + ccp * end = sf->field + sf->used; + while ( src < end ) + if (!strcmp(*src++,key)) + { + if (move_key) + FreeString(key); + return; + } + + AppendStringField(sf,key,move_key); +} + +/////////////////////////////////////////////////////////////////////////////// + void SortStringField ( StringField_t * sf ) { DASSERT(sf); @@ -5719,11 +5980,8 @@ void RestoreStateStringField /////////////// ParamField_t /////////////// /////////////////////////////////////////////////////////////////////////////// -void InitializeParamField ( ParamField_t * pf ) -{ - DASSERT(pf); - memset(pf,0,sizeof(*pf)); -} +#undef PARAM_FIELD_GROW +#define PARAM_FIELD_GROW(s) (s)/4+100 /////////////////////////////////////////////////////////////////////////////// @@ -5812,7 +6070,7 @@ static ParamFieldItem_t * InsertParamFieldHelper ( ParamField_t * pf, int idx ) noPRINT("+SF: %u/%u/%u\n",idx,pf->used,pf->size); if ( pf->used == pf->size ) { - pf->size += 0x100; + pf->size += PARAM_FIELD_GROW(pf->size); pf->field = REALLOC(pf->field,pf->size*sizeof(*pf->field)); } DASSERT( idx <= pf->used ); @@ -5825,13 +6083,11 @@ static ParamFieldItem_t * InsertParamFieldHelper ( ParamField_t * pf, int idx ) /////////////////////////////////////////////////////////////////////////////// ParamFieldItem_t * FindInsertParamField - ( ParamField_t * pf, ccp key, bool move_key, bool *old_found ) + ( ParamField_t * pf, ccp key, bool move_key, uint num, bool *old_found ) { if (!key) return 0; - noTRACE("InsertParamField(%s,%x)\n",key,num); - bool found; int idx = FindParamFieldHelper(pf,&found,key); ParamFieldItem_t *item; @@ -5843,9 +6099,9 @@ ParamFieldItem_t * FindInsertParamField } else { - item = InsertParamFieldHelper(pf,idx); + item = InsertParamFieldHelper(pf,idx); item->key = move_key ? key : STRDUP(key); - item->num = 0; + item->num = num; item->data = 0; } @@ -5856,9 +6112,9 @@ ParamFieldItem_t * FindInsertParamField /////////////////////////////////////////////////////////////////////////////// -ParamFieldItem_t * CountParamField ( ParamField_t * pf, ccp key, bool move_key ) +ParamFieldItem_t * IncrementParamField ( ParamField_t * pf, ccp key, bool move_key ) { - ParamFieldItem_t *item = FindInsertParamField(pf,key,move_key,0); + ParamFieldItem_t *item = FindInsertParamField(pf,key,move_key,0,0); if (item) item->num++; return item; @@ -5896,35 +6152,6 @@ bool InsertParamField /////////////////////////////////////////////////////////////////////////////// -ParamFieldItem_t * InsertParamFieldEx - ( ParamField_t * pf, ccp key, bool move_key, uint num, bool *p_found ) -{ - if (!key) - return 0; - - noTRACE("InsertParamField(%s,%x)\n",key,num); - - bool found; - int idx = FindParamFieldHelper(pf,&found,key); - if (p_found) - *p_found = found; - - if (found) - { - if (move_key) - FreeString(key); - return pf->field + idx; - } - - ParamFieldItem_t * dest = InsertParamFieldHelper(pf,idx); - dest->key = move_key ? key : STRDUP(key); - dest->num = num; - dest->data = 0; - return dest; -} - -/////////////////////////////////////////////////////////////////////////////// - bool ReplaceParamField ( ParamField_t * pf, ccp key, bool move_key, uint num, cvp data ) { @@ -5987,7 +6214,7 @@ ParamFieldItem_t * AppendParamField noPRINT(">SF: %u/%u\n",pf->used,pf->size); if ( pf->used == pf->size ) { - pf->size += 0x100; + pf->size += PARAM_FIELD_GROW(pf->size); pf->field = REALLOC(pf->field,pf->size*sizeof(*pf->field)); } TRACE("AppendParamField(%s,%d) %d/%d\n",key,move_key,pf->used,pf->size); @@ -6044,6 +6271,569 @@ uint FindParamFieldHelper ( const ParamField_t * pf, bool * p_found, ccp key ) // /////////////////////////////////////////////////////////////////////////////// +/////////////// exmem_list_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +#undef EXMEM_LIST_GROW +#define EXMEM_LIST_GROW(s) (s)/2+50 + +//----------------------------------------------------------------------------- + +void ResetEML ( exmem_list_t * eml ) +{ + if (eml) + { + if ( eml->used > 0 ) + { + DASSERT(eml->list); + exmem_key_t *ptr = eml->list, *end; + for ( end = ptr + eml->used; ptr < end; ptr++ ) + { + if (ptr->data.is_key_alloced) + FreeString(ptr->key); + if (ptr->data.is_alloced) + FreeString(ptr->data.data.ptr); + } + } + FREE(eml->list); + + int (*func_cmp)( ccp s1, ccp s2 ) = eml->func_cmp; + InitializeEML(eml); + eml->func_cmp = func_cmp; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +void MoveEML ( exmem_list_t * dest, exmem_list_t * src ) +{ + DASSERT(dest); + if ( src != dest ) + { + ResetEML(dest); + if (src) + { + *dest = *src; + InitializeEML(src); + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +uint FindHelperEML ( const exmem_list_t * eml, ccp key, bool * p_found ) +{ + DASSERT(eml); + + int (*cmp)( ccp s1, ccp s2 ) = eml->func_cmp ? eml->func_cmp : strcmp; + + if ( eml->is_unsorted ) + { + uint i; + exmem_key_t *ptr = eml->list; + for ( i = 0; i < eml->used; i++, ptr++ ) + if (!cmp(key,ptr->key)) + { + if (p_found) + *p_found = true; + return i; + } + + if (p_found) + *p_found = false; + return eml->used; + } + + int beg = 0; + if (key) + { + int end = eml->used - 1; + while ( beg <= end ) + { + const uint idx = (beg+end)/2; + const int stat = cmp(key,eml->list[idx].key); + if ( stat < 0 ) + end = idx - 1 ; + else if ( stat > 0 ) + beg = idx + 1; + else + { + noTRACE("FindHelperEML(%s) FOUND=%d/%d/%d\n", + key, idx, eml->used, eml->size ); + if (p_found) + *p_found = true; + return idx; + } + } + } + + noTRACE("FindHelperEML(%s) failed=%d/%d/%d\n", + key, beg, eml->used, eml->size ); + + if (p_found) + *p_found = false; + return beg; +} + +/////////////////////////////////////////////////////////////////////////////// + +int FindIndexEML ( const exmem_list_t * eml, ccp key, int not_found_value ) +{ + bool found; + const int idx = FindHelperEML(eml,key,&found); + return found ? idx : not_found_value; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * FindEML ( const exmem_list_t * eml, ccp key ) +{ + bool found; + const int idx = FindHelperEML(eml,key,&found); + return found ? eml->list + idx : 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * FindAttribEML ( const exmem_list_t * eml, u32 attrib ) +{ + DASSERT(eml); + noTRACE("FindAttribEML(%x)\n",attrib); + + exmem_key_t *ptr = eml->list, *end; + for ( end = ptr + eml->used; ptr < end; ptr++ ) + if ( ptr->data.attrib == attrib ) + return ptr; + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +static exmem_key_t * InsertHelperEML + ( exmem_list_t * eml, int idx, + ccp key, CopyMode_t cm_key, + const exmem_t *data, CopyMode_t cm_data ) +{ + DASSERT(eml); + DASSERT( eml->used <= eml->size ); + noPRINT("+SF: %u/%u/%u\n",idx,eml->used,eml->size); + if ( eml->used == eml->size ) + { + eml->size += EXMEM_LIST_GROW(eml->size); + eml->list = REALLOC(eml->list,eml->size*sizeof(*eml->list)); + } + + DASSERT( idx <= eml->used ); + exmem_key_t * dest = eml->list + idx; + memmove(dest+1,dest,(eml->used-idx)*sizeof(*dest)); + eml->used++; + + dest->data = CopyExMem(data,cm_data); + dest->key = cm_key == CPM_COPY ? STRDUP(key) : key; + dest->data.is_key_alloced = cm_key != CPM_LINK; + + return dest; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * FindInsertEML + ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, bool *old_found ) +{ + if (!key) + return 0; + + bool found; + int idx = FindHelperEML(eml,key,&found); + exmem_key_t *item; + if (found) + { + if ( cm_key == CPM_MOVE ) + FreeString(key); + item = eml->list + idx; + } + else + item = InsertHelperEML(eml,idx,key,cm_key,0,0); + + if (old_found) + *old_found = found; + return item; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool InsertEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, + const exmem_t *data, CopyMode_t cm_data ) +{ + DASSERT(eml); + + if (!key) + { + FreeExMemCM(data,cm_data); + return 0; + } + + bool found; + int idx = FindHelperEML(eml,key,&found); + if (found) + { + if ( cm_key == CPM_MOVE ) + FreeString(key); + FreeExMemCM(data,cm_data); + } + else + InsertHelperEML(eml,idx,key,cm_key,data,cm_data); + + return !found; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool ReplaceEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, + const exmem_t *data, CopyMode_t cm_data ) +{ + DASSERT(eml); + + if (!key) + { + FreeExMemCM(data,cm_data); + return 0; + } + + bool found; + int idx = FindHelperEML(eml,key,&found); + if (found) + { + if ( cm_key == CPM_MOVE ) + FreeString(key); + + exmem_key_t * dest = eml->list + idx; + AssignExMem(&dest->data,data,cm_data); + } + else + InsertHelperEML(eml,idx,key,cm_key,data,cm_data); + + return !found; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool OverwriteEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, + const exmem_t *data, CopyMode_t cm_data ) +{ + DASSERT(eml); + + if (!key) + { + FreeExMemCM(data,cm_data); + return 0; + } + + bool found; + int idx = FindHelperEML(eml,key,&found); + if (found) + { + if ( cm_key == CPM_MOVE ) + FreeString(key); + + exmem_key_t * dest = eml->list + idx; + AssignExMem(&dest->data,data,cm_data); + } + + return found; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * AppendEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key, + const exmem_t *data, CopyMode_t cm_data ) +{ + DASSERT(eml); + + if (!key) + { + FreeExMemCM(data,cm_data); + return 0; + } + + if ( eml->used == eml->size ) + { + eml->size += EXMEM_LIST_GROW(eml->size); + eml->list = REALLOC(eml->list,eml->size*sizeof(*eml->list)); + } + TRACE("AppendEML(%s,%d) %d/%d\n",key,cm_key,eml->used,eml->size); + + exmem_key_t * dest = eml->list + eml->used++; + dest->data = CopyExMem(data,cm_data); + dest->key = cm_key == CPM_COPY ? STRDUP(key) : key; + dest->data.is_key_alloced = cm_key != CPM_LINK; + + eml->is_unsorted = true; + return dest; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool RemoveEML ( exmem_list_t * eml, ccp key ) +{ + bool found; + uint idx = FindHelperEML(eml,key,&found); + if (found) + { + DASSERT(eml->used); + eml->used--; + DASSERT( idx <= eml->used ); + exmem_key_t * dest = eml->list + idx; + if (dest->data.is_key_alloced) + FreeString(dest->key); + FreeExMem(&dest->data); + if (eml->used) + memmove(dest,dest+1,(eml->used-idx)*sizeof(*dest)); + else + eml->is_unsorted = false; + } + return found; +} + +/////////////////////////////////////////////////////////////////////////////// + +exmem_key_t * MatchEML ( const exmem_list_t * eml, ccp key ) +{ + DASSERT(eml); + if (key) + { + exmem_key_t *ptr = eml->list, *end; + for ( end = ptr + eml->used; ptr < end; ptr++ ) + if (MatchPattern(ptr->key,key,'/')) + return ptr; + } + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void DumpEML ( FILE *f, int indent, const exmem_list_t * eml, ccp info ) +{ + if ( f && eml && eml->used ) + { + indent = NormalizeIndent(indent); + fprintf(f,"%*s%s%s" "exmem list %p, N=%u/%u%s\n", + indent,"", info ? info : "", info ? " : " : "", + eml, eml->used, eml->size, eml->is_unsorted ? ", not sorted" : "" ); + + char buf[20]; + const int fw_idx = indent + snprintf(buf,sizeof(buf),"%d",eml->used-1) + 1; + + exmem_key_t *ptr, *end = eml->list + eml->used; + int fw_key = 0; + for ( ptr = eml->list; ptr < end; ptr++ ) + { + if (ptr->key) + { + const int klen = strlen(ptr->key); + if ( fw_key < klen ) + fw_key = klen; + } + } + if ( fw_key > 30 ) + fw_key = 30; + + uint idx = 0; + for ( ptr = eml->list; ptr < end; ptr++, idx++ ) + fprintf(f,"%*d [%c%c%c%c] %-*s = [%x] %s\n", + fw_idx, idx, + ptr->data.is_key_alloced? 'a' : '-', // flags: same as in PrintExMem() + ptr->data.is_alloced ? 'A' : '-', + ptr->data.is_circ_buf ? 'C' : '-', + ptr->data.is_original ? 'O' : '-', + fw_key, ptr->key ? ptr->key : "", + ptr->data.attrib, ptr->data.data.ptr ); + } +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +exmem_t ResolveSymbolsEML ( const exmem_list_t * eml, ccp source ) +{ + exmem_t em = {{0}}; + + if (source) + { + char name[100]; + + int try; + for ( try = 0; try < 50; try++ ) + { + ccp p1 = strstr(source,"$("); + if (!p1) + continue; + ccp p2 = strchr(p1,')'); + if (!p2) + break; + + const int plen = p2 - p1 - 2; + DASSERT(plen>=0); + + StringCopySM(name,sizeof(name),p1+2,plen); + const exmem_key_t *ref = FindEML(eml,name); + mem_t replace = ref ? ref->data.data : NullMem; + + char *temp = MEMDUP3(source, p1-source, + replace.ptr, replace.len, + p2+1, strlen(p2+1) ); + if (em.is_alloced) + FreeString(source); + source = temp; + em.is_alloced = true; + } + } + + em.data.ptr = source; + em.data.len = strlen(source); + em.is_original = !em.is_alloced; + return em; +} + +/////////////////////////////////////////////////////////////////////////////// + +uint ResolveAllSymbolsEML ( exmem_list_t * eml ) +{ + ASSERT(eml); + int try, count = 0; + char name[100]; + exmem_key_t *ptr, *end = eml->list + eml->used; + + for ( try = 0; try < 20; try++ ) + { + int try_again = 0; + + for ( ptr = eml->list; ptr < end; ptr++ ) + { + for( int try2 = 0; try2 < 10; try2++ ) + { + ccp str = ptr->data.data.ptr; + if (!str) + break; + + ccp p1 = strstr(str,"$("); + if (!p1) + break; + ccp p2 = strchr(p1,')'); + if (!p2) + break; + const int plen = p2 - p1 - 2; + ASSERT(plen>=0); + + StringCopySM(name,sizeof(name),p1+2,plen); + const exmem_key_t *ref = FindEML(eml,name); + mem_t replace = ref && ref != ptr ? ref->data.data : NullMem; + + char *temp = MEMDUP3( str, p1-str, + replace.ptr, replace.len, + p2+1, strlen(p2+1) ); + if (ptr->data.is_alloced) + FreeString(str); + ASSERT(temp); + ptr->data.data.ptr = temp; + ptr->data.data.len = strlen(temp); + ptr->data.is_alloced = true; + ptr->data.is_original = ptr->data.is_circ_buf = false; + try_again++; + count++; + } + } + + if (!try_again) + break; + } + return count; +} + +/////////////////////////////////////////////////////////////////////////////// + +// add symbols 'home', 'etc', 'install' = 'prog' and 'cwd' +void AddStandardSymbolsEML ( exmem_list_t * eml, bool overwrite ) +{ + DASSERT(eml); + + char buf[PATH_MAX]; + bool (*func)(exmem_list_t*,ccp,CopyMode_t,const exmem_t*,CopyMode_t) + = overwrite ? ReplaceEML : InsertEML; + PRINT0("overwrite=%d, func=%p, ins=%p, repl=%p\n",overwrite,func,InsertEML,ReplaceEML); + + exmem_t temp = ExMemByString("/etc"); + func(eml,"etc",CPM_LINK,&temp,CPM_LINK); + + ccp home = getenv("HOME"); + temp = ExMemByString0(home); + func(eml,"home",CPM_LINK,&temp,CPM_COPY); + + // https://wiki.archlinux.org/index.php/XDG_Base_Directory + ccp xdg = getenv("XDG_CONFIG_HOME"); + if ( xdg && *xdg ) + { + temp = ExMemByString0(xdg); + ccp colon = strchr(xdg,':'); + if (colon) + { + if ( colon == xdg ) + goto xdg_home; + temp.data.len = colon - xdg; + } + func(eml,"xdg_home",CPM_LINK,&temp,CPM_COPY); + } + else if (home) + { + xdg_home:; + xdg = PathCatPP(buf,sizeof(buf),home,".config"); + temp = ExMemByString0(xdg); + func(eml,"xdg_home",CPM_LINK,&temp,CPM_COPY); + } + + xdg = getenv("XDG_CONFIG_DIRS"); + if ( xdg && *xdg ) + { + temp = ExMemByString0(xdg); + ccp colon = strchr(xdg,':'); + if (colon) + { + if ( colon == xdg ) + goto xdg_etc; + temp.data.len = colon - xdg; + } + func(eml,"xdg_etc",CPM_LINK,&temp,CPM_COPY); + } + else + { + xdg_etc:; + temp = ExMemByString("/etc/xdg"); + func(eml,"xdg_etc",CPM_LINK,&temp,CPM_LINK); + } + + ccp install = ProgramDirectory(); + temp = ExMemByString0(install); + func(eml,"install",CPM_LINK,&temp,CPM_COPY); + func(eml,"prog",CPM_LINK,&temp,CPM_COPY); + + if (getcwd(buf,sizeof(buf))) + { + temp = ExMemByString0(buf); + func(eml,"cwd",CPM_LINK,&temp,CPM_COPY); + } + + #ifdef __CYGWIN__ + ccp prog_files = getenv("PROGRAMFILES"); + if ( !prog_files || !*prog_files ) + prog_files = "C:/Program Files"; + temp = GetNormalizeFilenameCygwin(prog_files,true); + func(eml,"programfiles",CPM_LINK,&temp,CPM_COPY); + FreeExMem(&temp); + #endif +} + +// +/////////////////////////////////////////////////////////////////////////////// /////////////// Memory Maps /////////////// /////////////////////////////////////////////////////////////////////////////// |
