aboutsummaryrefslogtreecommitdiff
path: root/project/dclib/dclib-file.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--project/dclib/dclib-file.c725
1 files changed, 585 insertions, 140 deletions
diff --git a/project/dclib/dclib-file.c b/project/dclib/dclib-file.c
index 333ec3a..1356d32 100644
--- a/project/dclib/dclib-file.c
+++ b/project/dclib/dclib-file.c
@@ -246,7 +246,7 @@ FileAttrib_t * SetFileAttrib
ZeroFileAttrib(dest);
if (S_ISREG(src_stat->st_mode))
{
- #if HAVE_STATTIME_NSEC
+ #if HAVE_STATTIME_NSEC
dest->atime = src_stat->st_atim;
dest->mtime = src_stat->st_mtim;
dest->ctime = src_stat->st_ctim;
@@ -2690,6 +2690,47 @@ uint PrintLineBuffer
/////////////// file helpers ///////////////
///////////////////////////////////////////////////////////////////////////////
+const char inode_type_char[INTY__N+1] = "?-+SLFBCDR";
+
+//-----------------------------------------------------------------------------
+
+inode_type_t GetInodeType ( int ret_status, mode_t md )
+{
+ return ret_status ? INTY_NOTFOUND
+ : S_ISREG(md) ? INTY_REG
+ : S_ISDIR(md) ? INTY_DIR
+ : S_ISCHR(md) ? INTY_CHAR
+ : S_ISBLK(md) ? INTY_BLOCK
+ : S_ISFIFO(md) ? INTY_FIFO
+ : S_ISLNK(md) ? INTY_LINK
+ : S_ISSOCK(md) ? INTY_SOCK
+ : INTY_AVAIL;
+}
+
+//-----------------------------------------------------------------------------
+
+inode_type_t GetInodeTypeByPath ( ccp path, mode_t *mode )
+{
+ struct stat st;
+ const int ret_status = stat(path,&st);
+ if (mode)
+ *mode = ret_status ? 0 : st.st_mode;
+ return GetInodeType(ret_status,st.st_mode);
+}
+
+//-----------------------------------------------------------------------------
+
+inode_type_t GetInodeTypeByFD ( int fd, mode_t *mode )
+{
+ struct stat st;
+ const int ret_status = fstat(fd,&st);
+ if (mode)
+ *mode = ret_status ? 0 : st.st_mode;
+ return GetInodeType(ret_status,st.st_mode);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
int IsDirectory
(
// analyse filename (last char == '/') and stat(fname)
@@ -2990,7 +3031,7 @@ enumError RemoveSource
(
ccp fname, // file to remove
ccp dest_fname, // NULL or dest file name
- // If real pathes are same: don't remove
+ // If real paths are same: don't remove
bool print_log, // true: print a log message
bool testmode // true: don't remove, log only
)
@@ -3218,14 +3259,15 @@ char * NormalizeFileName
uint buf_size, // size of buf
ccp source, // NULL or source
bool allow_slash, // true: allow '/' in source
- bool is_utf8 // true: enter UTF-8 mode
+ bool is_utf8, // true: enter UTF-8 mode
+ trailing_slash slash_mode // manipulate trailing slash
)
{
DASSERT(buf);
DASSERT(buf_size>1);
char *dest = buf, *end = buf + buf_size - 1;
- TRACE("NormalizeFileName(%s,%d)\n",source,allow_slash);
+ TRACE("NormalizeFileName(%s,%d,%d,%d)\n",source,allow_slash,is_utf8,slash_mode);
if (source)
{
@@ -3271,19 +3313,22 @@ char * NormalizeFileName
|| ch == 0xd6 // Ö
|| ch == 0xdc // Ü
)
- || strchr("_+-=%'\"$%&,.!()[]{}<>",ch)
- || ch == '/' && allow_slash )
+ || strchr("_+-=%'\"$%&#,.!()[]{}<>",ch)
+ )
{
*dest++ = ch;
skip_space = false;
}
#ifdef __CYGWIN__
- else if ( ch == '\\' && allow_slash )
+ else if ( ( ch == '/' || ch == '\\' ) && allow_slash )
+ #else
+ else if ( ch == '/' && allow_slash )
+ #endif
{
- *dest++ = '/';
+ if ( dest == buf || dest[-1] != '/' )
+ *dest++ = '/';
skip_space = false;
}
- #endif
else if (!skip_space)
{
*dest++ = ' ';
@@ -3295,6 +3340,35 @@ char * NormalizeFileName
if ( dest > buf && dest[-1] == ' ' )
dest--;
+ switch (slash_mode)
+ {
+ case TRSL_NONE: // do nothing special
+ break;
+
+ case TRSL_AUTO: // add trailing slash if it is a directory, remove otherwise
+ *dest = 0;
+ if (IsDirectory(buf,false))
+ goto add_slash;
+ // fall through
+
+ case TRSL_REMOVE: // remove trailing slash always
+ if ( dest > buf && dest[-1] == '/' )
+ dest--;
+ break;
+
+ case TRSL_ADD_AUTO: // add trailing slash if it is a directory
+ *dest = 0;
+ if (!IsDirectory(buf,false))
+ break;
+ // fall through
+
+ case TRSL_ADD_ALWAYS: // add trailing slash always
+ add_slash:
+ if ( dest > buf && dest < end && dest[-1] != '/' )
+ *dest++ = '/';
+ break;
+ }
+
DASSERT( dest <= end );
*dest = 0;
return dest;
@@ -3303,19 +3377,16 @@ char * NormalizeFileName
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-#ifdef __CYGWIN__
-
- uint IsWindowsDriveSpec
- (
+uint IsWindowsDriveSpec
+(
// returns the length of the found windows drive specification (0|2|3)
- ccp src // valid string
- )
- {
- DASSERT(src);
-
- if ( ( *src >= 'a' && *src <= 'z' || *src >= 'A' && *src <= 'Z' )
- && src[1] == ':' )
+ ccp src // NULL or valid string
+)
+{
+ if ( src
+ && src[1] == ':'
+ && ( *src >= 'a' && *src <= 'z' || *src >= 'A' && *src <= 'Z' ) )
{
if (!src[2])
return 2;
@@ -3324,41 +3395,40 @@ char * NormalizeFileName
return 3;
}
return 0;
- }
-
-#endif // __CYGWIN__
+}
///////////////////////////////////////////////////////////////////////////////
-#ifdef __CYGWIN__
-
- uint NormalizeFilenameCygwin
- (
+uint NormalizeFilenameCygwin
+(
// returns a pointer to the NULL terminator within 'buf'
char * buf, // valid destination buffer
uint buf_size, // size of buf
ccp src // NULL or source
- )
- {
+)
+{
static char prefix[] = "/cygdrive/";
if ( buf_size < sizeof(prefix) + 5 || !src )
{
- *buf = 0;
+ if ( buf && buf_size )
+ *buf = 0;
return 0;
}
char * end = buf + buf_size - 1;
char * dest = buf;
- if ( ( *src >= 'a' && *src <= 'z' || *src >= 'A' && *src <= 'Z' )
+ if ( ( *src >= 'a' && *src <= 'z' || *src >= 'A' && *src <= 'Z' )
&& src[1] == ':'
&& ( src[2] == 0 || src[2] == '/' || src[2] == '\\' ))
{
memcpy(buf,prefix,sizeof(prefix));
dest = buf + sizeof(prefix)-1;
*dest++ = tolower((int)*src); // cygwin needs the '(int)'
+ #ifdef __CYGWIN__
+ // this can only be checked with real Cygwin.
*dest = 0;
if (IsDirectory(buf,false))
{
@@ -3369,8 +3439,15 @@ char * NormalizeFileName
}
else
dest = buf;
+ #else //
+ *dest++ = '/';
+ src += 2;
+ if (*src)
+ src++;
+ #endif
+
}
- ASSERT( dest < buf + buf_size );
+ DASSERT( dest < buf + buf_size );
while ( dest < end && *src )
if ( *src == '\\' )
@@ -3384,29 +3461,367 @@ char * NormalizeFileName
*dest = 0;
ASSERT( dest < buf + buf_size );
return dest - buf;
- }
-
-#endif // __CYGWIN__
+}
///////////////////////////////////////////////////////////////////////////////
-#ifdef __CYGWIN__
+exmem_t GetNormalizeFilenameCygwin
+(
+ // returns an object. Call FreeExMem(RESULT) to possible alloced memory.
+
+ ccp source, // NULL or source
+ bool try_circ // use circ-buffer, if result is small enough
+)
+{
+ char buf[PATH_MAX];
+ const uint len = NormalizeFilenameCygwin(buf,sizeof(buf),source);
+ return AllocExMemS(buf,len,try_circ,source,-1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
- char * AllocNormalizedFilenameCygwin
- (
+char * AllocNormalizedFilenameCygwin
+(
// returns an alloced buffer with the normalized filename
- ccp source // NULL or string
- )
- {
+ ccp source, // NULL or source
+ bool try_circ // use circ-buffer, if result is small enough
+)
+{
char buf[PATH_MAX];
const uint len = NormalizeFilenameCygwin(buf,sizeof(buf),source);
- char * result = MEMDUP(buf,len); // MEMDUP allocs +1 byte and set it to NULL
- DASSERT(buf[len]==0);
- return result;
- }
+ return AllocCircBuf(buf,len,try_circ);
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// search file & config ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+void ResetSearchFile ( search_file_list_t *sfl )
+{
+ if (sfl)
+ {
+ if (sfl->list)
+ {
+ uint i;
+ search_file_t *sf = sfl->list;
+ for ( i = 0; i < sfl->used; i++, sf++ )
+ if (sf->alloced)
+ FreeString(sf->fname);
+ FREE(sfl->list);
+ }
+
+ ResetEML(&sfl->symbols);
+ InitializeSearchFile(sfl);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+search_file_t * AppendSearchFile
+(
+ search_file_list_t *sfl, // valid search list, new files will be appended
+ ccp fname, // path+fname to add
+ CopyMode_t copy_mode, // copy mode for 'fname'
+ ccp append_if_dir // append this if 'fname' is a directory
+)
+{
+ search_file_t *res = 0;
+ if ( fname && *fname )
+ {
+ #if 0
+ ccp rpath = realpath(fname,0);
+ if (rpath)
+ {
+ if ( copy_mode == CPM_MOVE )
+ FreeString(fname);
+ fname = rpath;
+ copy_mode = CPM_MOVE;
+ }
+ #endif
+
+ uint i;
+ search_file_t *sf = sfl->list;
+ for ( i = 0; i < sfl->used; i++, sf++ )
+ {
+ if (!strcmp(sf->fname,fname))
+ {
+ res = sf;
+ goto end;
+ }
+ }
+ DASSERT( i == sfl->used );
+
+
+ //-- check for directory
+
+ const inode_type_t itype = GetInodeTypeByPath(fname,0);
+ if ( itype == INTY_DIR && append_if_dir )
+ {
+ char buf[PATH_MAX];
+ ccp fname2 = PathCatPP(buf,sizeof(buf),fname,append_if_dir);
+ res = AppendSearchFile(sfl,fname2,CPM_COPY,0);
+ }
+ else
+ {
+ if ( sfl->used == sfl->size )
+ {
+ sfl->size += sfl->size/8 + 20;
+ sfl->list = REALLOC(sfl->list,sfl->size*sizeof(*sfl->list));
+ }
+
+ res = sfl->list + sfl->used++;
+ memset(res,0,sizeof(*res));
+ res->itype = itype;
+ res->fname = CopyData(fname,strlen(fname)+1,copy_mode,&res->alloced);
+ fname = 0;
+ }
+ }
+
+ end:
+ if ( fname && copy_mode == CPM_MOVE )
+ FreeString(fname);
+ return res;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void DumpSearchFile ( FILE *f, int indent,
+ const search_file_list_t *sfl, bool show_symbols, ccp info )
+{
+ if ( f && sfl && ( sfl->used || show_symbols && sfl->symbols.used ))
+ {
+ indent = NormalizeIndent(indent);
+ fprintf(f,"%*s%s%s" "SearchList %p, N=%u/%u\n",
+ indent,"", info ? info : "", info ? " : " : "",
+ sfl, sfl->used, sfl->size );
+
+ char buf[20];
+ const int fw_idx = indent
+ + snprintf(buf,sizeof(buf),"%d",sfl->used)
+ + ( show_symbols ? 3 : 1 );
+
+ uint idx = 0;
+ search_file_t *ptr, *end = sfl->list + sfl->used;
+ for ( ptr = sfl->list; ptr < end; ptr++, idx++ )
+ fprintf(f,"%*d [%c,%c:%02x] %s\n",
+ fw_idx, idx,
+ ptr->alloced ? 'A' : '-',
+ inode_type_char[ptr->itype], ptr->hint, ptr->fname );
+
+ if (show_symbols)
+ DumpEML(f,indent+2,&sfl->symbols,"Symbols");
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+uint SearchConfig1
+(
+ search_file_list_t *sfl,
+ // valid search list, new file will be appended
+ ccp config_fname, // default filename (without path) of config file
+
+ ccp option, // NULL or filename by option => CONF_HINT_OPT
+ ccp home_path, // NULL or home path for config file => CONF_HINT_HOME
+ ccp etc_path, // NULL or etc path for config file => CONF_HINT_ETC
+ ccp share_path, // NULL or share path for config file => CONF_HINT_MISC
+
+ int stop_mode // >0: stop if found, >1: stop on option
+
+ // hints (by source, values=prio): 8:option, 4:home, 2:etc, 1:prog-path
+)
+{
+ DASSERT(sfl);
+ char buf[PATH_MAX];
+
+ uint count = 0;
+ search_file_t *sf;
+ if ( option && *option )
+ {
+ sf = AppendSearchFile(sfl,option,CPM_COPY,config_fname);
+ if (sf)
+ {
+ sf->hint |= CONF_HINT_OPT;
+ if ( sf->itype == INTY_REG && ++count && stop_mode > 0 )
+ return 1;
+ if ( stop_mode > 1 )
+ return 0;
+ }
+ }
+
+ if (home_path)
+ {
+ ccp home = getenv("HOME");
+ if (home)
+ home_path = PathCatPP(buf,sizeof(buf),home,home_path);
+ sf = AppendSearchFile(sfl,home_path,CPM_COPY,config_fname);
+ if (sf)
+ {
+ sf->hint |= CONF_HINT_HOME;
+ if ( sf->itype == INTY_REG && ++count && stop_mode > 0 )
+ return 1;
+ }
+ }
+
+ if (etc_path)
+ {
+ sf = AppendSearchFile(sfl,etc_path,CPM_COPY,config_fname);
+ if (sf)
+ {
+ sf->hint |= CONF_HINT_ETC;
+ if ( sf->itype == INTY_REG && ++count && stop_mode > 0 )
+ return 1;
+ }
+ }
+
+ if (share_path)
+ {
+ sf = AppendSearchFile(sfl,share_path,CPM_COPY,config_fname);
+ if (sf)
+ {
+ sf->hint |= CONF_HINT_MISC;
+ if ( sf->itype == INTY_REG && ++count && stop_mode > 0 )
+ return 1;
+ }
+ }
+
+ ccp progpath = ProgramDirectory();
+ if (progpath)
+ {
+ sf = AppendSearchFile(sfl,progpath,CPM_COPY,config_fname);
+ if (sf)
+ {
+ sf->hint |= CONF_HINT_INST;
+ if ( sf->itype == INTY_REG && ++count && stop_mode > 0 )
+ return 1;
+ }
+ }
+
+ return count;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int add_search
+(
+ // returns 0 if !stop_if_found, 2 if added+found, 1 if added, 0 else
+
+ search_file_list_t *sfl, // valid data
+ ccp config_fname, // default filename (without path) of config file
+ ccp *list, // NULL or list of filenames
+ int n_list, // num of 'list' elements, -1:null terminated list
+ ccp prefix, // prefix for relative filenames
+ uint hint, // attributes
+ int stop_if_found // >0: stop if file found
+)
+{
+ DASSERT(sfl);
+ if (!list)
+ return 0;
+
+ if ( n_list < 0 )
+ {
+ ccp *ptr;
+ for ( ptr = list; *ptr; ptr++ )
+ ;
+ n_list = ptr - list;
+ }
+ if (!n_list)
+ return 0;
+
+ int ret_val = 0;
+ char buf[PATH_MAX];
+ for ( ; n_list > 0; n_list--, list++ )
+ {
+ if (!*list)
+ continue;
+
+ ccp path = **list == '/' || !prefix || !*prefix
+ ? *list
+ : PathCatPP(buf,sizeof(buf),prefix,*list);
+ exmem_t res = ResolveSymbolsEML(&sfl->symbols,path);
+ search_file_t *sf = AppendSearchFile( sfl, res.data.ptr,
+ res.is_alloced ? CPM_MOVE : CPM_COPY, config_fname );
+ if (sf)
+ {
+ sf->hint |= hint;
+ if ( sf->itype == INTY_REG && stop_if_found > 0 )
+ return 2;
+ ret_val = 1;
+ }
+ }
+
+ return stop_if_found > 0 ? ret_val : 0;
+}
+
+//-----------------------------------------------------------------------------
+
+bool SearchConfig
+(
+ // for all paths:
+ // /... is an absolute path
+ // $(home)/... path relative to getenv("HOME")
+ // $(xdg_home)/... path relative to first path of getenv("XDG_CONFIG_HOME")
+ // $(xdg_etc)/... path relative to first path of getenv("XDG_CONFIG_DIRS")
+ // $(etc)/... path relative to /etc directory
+ // $(install)/... path relative to installation directory = ProgramDirectory()
+ // $(NAME)/... path relative to symbol in sfl->symbols
+ // xx relative paths otherwise
+
+ search_file_list_t *sfl,
+ // valid search list, new paths will be appended
+ // sfl->symbols: home, etc and install are added (not replaced)
+ // It is used to resolve all $(NAME) references.
+
+ ccp config_fname, // default filename (without path) of config file
+
+ ccp *option, // NULL or filenames by option => CONF_HINT_OPT
+ int n_option, // num of 'option' elements, -1:null terminated list
+ ccp *xdg_home, // NULL or $(xdg_home) based paths => CONF_HINT_HOME
+ int n_xdg_home, // num of 'home' elements, -1:null terminated list
+ ccp *home, // NULL or $(home) based paths => CONF_HINT_HOME
+ int n_home, // num of 'home' elements, -1:null terminated list
+ ccp *etc, // NULL or $(etc) based paths => CONF_HINT_ETC
+ int n_etc, // num of 'etc' elements, -1:null terminated list
+ ccp *install, // NULL or $(install) based paths => CONF_HINT_INST
+ int n_install, // num of 'install' elements, -1:null terminated list
+ ccp *misc, // NULL or absolute paths => CONF_HINT_MISC
+ int n_misc, // num of 'misc' elements, -1:null terminated list
+
+ int stop_mode // >0: stop if found, >1: stop on option
+)
+{
+ // ==> see: https://wiki.archlinux.org/index.php/XDG_Base_Directory
-#endif // __CYGWIN__
+ DASSERT(sfl);
+ AddStandardSymbolsEML(&sfl->symbols,false);
+
+ int stat = add_search(sfl,config_fname,option,n_option,0,CONF_HINT_OPT,stop_mode);
+ if ( stat > 1 )
+ return true;
+ if ( stop_mode > 1 && stat )
+ return false;
+
+ if (add_search(sfl,config_fname,xdg_home,n_xdg_home,"$(xdg_home)",CONF_HINT_HOME,stop_mode)>1)
+ return true;
+
+ if (add_search(sfl,config_fname,home,n_home,"$(home)",CONF_HINT_HOME,stop_mode)>1)
+ return true;
+
+ if (add_search(sfl,config_fname,etc,n_etc,"$(xdg_etc)",CONF_HINT_ETC,stop_mode)>1)
+ return true;
+
+ if (add_search(sfl,config_fname,etc,n_etc,"$(etc)",CONF_HINT_ETC,stop_mode)>1)
+ return true;
+
+ if (add_search(sfl,config_fname,install,n_install,"$(install)",CONF_HINT_INST,stop_mode)>1)
+ return true;
+
+ return add_search(sfl,config_fname,misc,n_misc,0,CONF_HINT_MISC,stop_mode)>1;
+}
//
///////////////////////////////////////////////////////////////////////////////
@@ -4902,68 +5317,50 @@ void SaveCurrentStateByTable
break;
case SRT_FLOAT:
- switch(srt->size)
+ if ( srt->size == sizeof(float) )
{
- case sizeof(float):
- {
- const u8 *d = data + srt->offset;
- for ( i = 0; i < n_elem; i++, d += elem_off )
- fprintf(f, "%s%.8g", i ? "," : "", *(float*)d );
- }
- break;
-
- case sizeof(double):
- {
- const u8 *d = data + srt->offset;
- for ( i = 0; i < n_elem; i++, d += elem_off )
- fprintf(f, "%s%.16g", i ? "," : "", *(double*)d );
- }
- break;
-
- case sizeof(long double):
- {
- const u8 *d = data + srt->offset;
- for ( i = 0; i < n_elem; i++, d += elem_off )
- fprintf(f, "%s%.20Lg", i ? "," : "", *(long double*)d );
- }
- break;
-
- default:
- fputs("0.0",f);
+ const u8 *d = data + srt->offset;
+ for ( i = 0; i < n_elem; i++, d += elem_off )
+ fprintf(f, "%s%.8g", i ? "," : "", *(float*)d );
+ }
+ else if ( srt->size == sizeof(double) )
+ {
+ const u8 *d = data + srt->offset;
+ for ( i = 0; i < n_elem; i++, d += elem_off )
+ fprintf(f, "%s%.16g", i ? "," : "", *(double*)d );
+ }
+ else if ( srt->size == sizeof(long double) )
+ {
+ const u8 *d = data + srt->offset;
+ for ( i = 0; i < n_elem; i++, d += elem_off )
+ fprintf(f, "%s%.20Lg", i ? "," : "", *(long double*)d );
}
+ else
+ fputs("0.0",f);
fputc('\n',f);
break;
case SRT_XFLOAT:
- switch(srt->size)
+ if ( srt->size == sizeof(float) )
{
- case sizeof(float):
- {
- const u8 *d = data + srt->offset;
- for ( i = 0; i < n_elem; i++, d += elem_off )
- fprintf(f, "%s%a", i ? "," : "", *(float*)d );
- }
- break;
-
- case sizeof(double):
- {
- const u8 *d = data + srt->offset;
- for ( i = 0; i < n_elem; i++, d += elem_off )
- fprintf(f, "%s%a", i ? "," : "", *(double*)d );
- }
- break;
-
- case sizeof(long double):
- {
- const u8 *d = data + srt->offset;
- for ( i = 0; i < n_elem; i++, d += elem_off )
- fprintf(f, "%s%La", i ? "," : "", *(long double*)d );
- }
- break;
-
- default:
- fputs("0.0",f);
+ const u8 *d = data + srt->offset;
+ for ( i = 0; i < n_elem; i++, d += elem_off )
+ fprintf(f, "%s%a", i ? "," : "", *(float*)d );
+ }
+ else if ( srt->size == sizeof(double) )
+ {
+ const u8 *d = data + srt->offset;
+ for ( i = 0; i < n_elem; i++, d += elem_off )
+ fprintf(f, "%s%a", i ? "," : "", *(double*)d );
+ }
+ else if ( srt->size == sizeof(long double) )
+ {
+ const u8 *d = data + srt->offset;
+ for ( i = 0; i < n_elem; i++, d += elem_off )
+ fprintf(f, "%s%La", i ? "," : "", *(long double*)d );
}
+ else
+ fputs("0.0",f);
fputc('\n',f);
break;
@@ -5204,12 +5601,12 @@ void RestoreStateByTable
uint i = 0;
while (*src)
{
- switch(srt->size)
- {
- case sizeof(float): *(float*)val = strtof(src,&src); break;
- case sizeof(double): *(double*)val = strtod(src,&src); break;
- case sizeof(long double): *(long double*)val = strtold(src,&src); break;
- }
+ if ( srt->size == sizeof(float) )
+ *(float*)val = strtof(src,&src);
+ else if ( srt->size == sizeof(double) )
+ *(double*)val = strtod(src,&src);
+ else if ( srt->size == sizeof(long double) )
+ *(long double*)val = strtold(src,&src);
if ( ++i == n_elem )
break;
val += elem_off;
@@ -5703,6 +6100,7 @@ ccp GetNamePSFF ( PrintScriptFF fform )
{
case PSFF_UNKNOWN: return "TEXT";
case PSFF_ASSIGN: return "ASSIGN";
+ case PSFF_CONFIG: return "CONFIG";
case PSFF_JSON: return "JSON";
case PSFF_BASH: return "BASH";
case PSFF_SH: return "SH";
@@ -5723,6 +6121,11 @@ void PrintScriptHeader ( PrintScript_t *ps )
ps->add_index = false;
ps->sep[0] = ps->sep[1] = 0;
+ if ( !ps->var_name || !*ps->var_name )
+ ps->var_name = "res";
+ if ( !ps->var_prefix )
+ ps->var_prefix = "";
+
if ( ps->f )
{
switch (ps->fform)
@@ -5740,19 +6143,19 @@ void PrintScriptHeader ( PrintScript_t *ps )
case PSFF_PHP:
if (ps->create_array)
- fprintf(ps->f,"$%s = array();\n\n",ps->varname);
+ fprintf(ps->f,"$%s = array();\n\n",ps->var_name);
ps->boc = "#";
break;
case PSFF_MAKEDOC:
if (ps->create_array)
- fprintf(ps->f,"%s = @LIST\n\n",ps->varname);
+ fprintf(ps->f,"%s = @LIST\n\n",ps->var_name);
ps->boc = "#!";
break;
case PSFF_C:
if (ps->create_array)
- fprintf(ps->f,"%s = @LIST\n\n",ps->varname);
+ fprintf(ps->f,"%s = @LIST\n\n",ps->var_name);
ps->boc = "//";
break;
@@ -5781,7 +6184,7 @@ void PrintScriptFooter ( PrintScript_t *ps )
case PSFF_SH:
if (ps->create_array)
- fprintf(ps->f,"%s_N=%u\n\n",ps->varname,ps->index);
+ fprintf(ps->f,"%sN=%u\n\n",ps->var_prefix,ps->index);
break;
case PSFF_PHP:
@@ -5817,9 +6220,9 @@ int PutScriptVars
if ( ps->add_index )
snprintf( ps->prefix, sizeof(ps->prefix),
- "%s_%u", ps->varname, ps->index );
+ "%s%u", ps->var_prefix, ps->index );
else
- StringCopyS( ps->prefix, sizeof(ps->prefix), ps->varname );
+ StringCopyS( ps->prefix, sizeof(ps->prefix), ps->var_prefix );
switch (ps->fform)
{
@@ -5891,65 +6294,107 @@ int PutScriptVars
varname = MemUpperS(varbuf,sizeof(varbuf),MemByS(varname,varlen));
varname = varbuf;
}
-
- ccp param = ptr++;
- while ( (uchar)*ptr >= ' ' )
+
+ ccp quote, param;
+ uint plen, free_param = 0;
+ if ( *++ptr == '"' )
+ {
ptr++;
+ param = ptr;
+ if (ps->auto_quote)
+ {
+ quote = EmptyString;
+ while ( *ptr && *ptr != '"' )
+ {
+ if ( *ptr == '\\' && ptr[1] )
+ ptr++;
+ ptr++;
+ }
+ param = EscapeString(param,ptr-param,EmptyString,EmptyString,CHMD__MODERN,
+ ps->fform == PSFF_BASH ? '$' : '"', true, &plen );
+ free_param++;
+ }
+ else
+ {
+ quote = "\"";
+ while ( *ptr && !( ptr[0] == '"' && ptr[1] == '\n' ))
+ ptr++;
+ plen = ptr - param;
+ }
+ if ( *ptr == '"' )
+ ptr++;
+ }
+ else
+ {
+ param = ptr;
+ quote = EmptyString;
+ while ( *ptr && *ptr != '\n' )
+ ptr++;
+ plen = ptr - param;
+ }
switch (ps->fform)
{
case PSFF_ASSIGN:
- fprintf(f, "%.*s = %.*s\n",
- varlen, varname,
- (int)( ptr - param - 1 ), param+1 );
+ fprintf(f, "%.*s = %s%.*s%s\n",
+ varlen, varname, quote, plen, param, quote );
+ break;
+
+ case PSFF_CONFIG:
+ if ( ps->eq_tabstop > 0 )
+ {
+ int tabs = ps->eq_tabstop - varlen/8;
+ if ( tabs < 0 )
+ tabs = 0;
+ fprintf(f, "%.*s%.*s= %.*s\n",
+ varlen, varname, tabs, Tabs20, plen, param );
+ }
+ else
+ fprintf(f, "%.*s = %.*s\n",
+ varlen, varname, plen, param );
break;
case PSFF_JSON:
- fprintf(f, "%s\"%.*s\":%.*s",
+ fprintf(f, "%s\"%.*s\":%s%.*s%s",
ps->count ? "," : "",
- varlen, varname,
- (int)( ptr - param - 1 ), param+1 );
+ varlen, varname, quote, plen, param, quote );
break;
case PSFF_BASH:
if (ps->create_array)
{
- fprintf(f, "%s_%.*s%s=(%.*s)\n",
+ fprintf(f, "%s%.*s%s=(%s%.*s%s)\n",
ps->prefix,
- varlen, varname,
- ps->index ? "+" : "",
- (int)( ptr - param - 1 ), param+1 );
+ varlen, varname, ps->index ? "+" : "", quote, plen, param, quote );
break;
}
// fall through
case PSFF_SH:
- fprintf(f, "%s_%.*s=%.*s\n",
- ps->prefix,
- varlen, varname,
- (int)( ptr - param - 1 ), param+1 );
+ fprintf(f, "%s%.*s=%s%.*s%s\n",
+ ps->prefix, varlen, varname, quote, plen, param, quote );
break;
case PSFF_PHP:
case PSFF_C:
- fprintf(f, "$d->%.*s = %.*s;\n",
- varlen, varname,
- (int)( ptr - param - 1 ), param+1 );
+ fprintf(f, "$d->%.*s = %s%.*s%s;\n",
+ varlen, varname, quote, plen, param, quote );
break;
case PSFF_MAKEDOC:
- fprintf(f, "d[\"%.*s\"] = %.*s\n",
- varlen, varname,
- (int)( ptr - param - 1 ), param+1 );
+ fprintf(f, "d[\"%.*s\"] = %s%.*s%s\n",
+ varlen, varname, quote, plen, param, quote );
break;
default:
- fprintf(f, "%20.*s = %.*s\n",
- varlen, varname,
- (int)( ptr - param - 1 ), param+1 );
+ fprintf(f, "%*.*s = %s%.*s%s\n",
+ ps->var_size > 0 ? ps->var_size : 20,
+ varlen, varname, quote, plen, param, quote );
break;
}
ps->count++;
+ if (free_param)
+ FreeString(param);
//-- skip to next line
next_line:
@@ -5972,12 +6417,12 @@ int PutScriptVars
case PSFF_PHP:
fprintf(f, "$%s%s = $d;\n\n",
- ps->prefix, ps->create_array ? "[]" : "" );
+ ps->var_name, ps->create_array ? "[]" : "" );
break;
case PSFF_MAKEDOC:
fprintf(f, "%s %s= move(d);\n\n",
- ps->prefix, ps->create_array ? "#" : "" );
+ ps->var_name, ps->create_array ? "#" : "" );
break;
default: