diff options
Diffstat (limited to '')
| -rw-r--r-- | project/dclib/dclib-file.c | 725 |
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: |
