Diff for /parser3/src/main/pa_common.C between versions 1.337 and 1.342

version 1.337, 2025/07/02 23:42:10 version 1.342, 2026/04/24 20:14:33
Line 8 Line 8
 #include "pa_common.h"  #include "pa_common.h"
 #include "pa_exception.h"  #include "pa_exception.h"
 #include "pa_hash.h"  #include "pa_hash.h"
   #include "pa_inline_hash.h"
 #include "pa_globals.h"  #include "pa_globals.h"
 #include "pa_charsets.h"  #include "pa_charsets.h"
 #include "pa_http.h"  #include "pa_http.h"
Line 22 Line 23
 #include <direct.h>  #include <direct.h>
 #endif  #endif
   
 #ifdef _MSC_VER  volatile const char * IDENT_PA_COMMON_C="$Id$" IDENT_PA_COMMON_H IDENT_PA_HASH_H IDENT_PA_INLINE_HASH_H IDENT_PA_ARRAY_H IDENT_PA_STACK_H;
 #define pa_mkdir(path, mode) _mkdir(path)  
 #else  
 #define pa_mkdir(path, mode) mkdir(path, mode)  
 #endif  
   
 volatile const char * IDENT_PA_COMMON_C="$Id$" IDENT_PA_COMMON_H IDENT_PA_HASH_H IDENT_PA_ARRAY_H IDENT_PA_STACK_H;   
   
 // some maybe-undefined constants  // some maybe-undefined constants
   
Line 72  const UTF16* pa_utf16_encode(const char* Line 67  const UTF16* pa_utf16_encode(const char*
   
 #ifdef _MSC_VER  #ifdef _MSC_VER
   
   #define PA_UTF16_ENC(value) (const wchar_t *)pa_utf16_encode(value, pa_thread_request().charsets.source())
   
 int pa_stat(const char *pathname, struct stat *buffer){  int pa_stat(const char *pathname, struct stat *buffer){
         const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source());          return _wstat64(PA_UTF16_ENC(pathname), buffer);
         return _wstat64((const wchar_t *)utf16name, buffer);  
 }  }
   
 int pa_open(const char *pathname, int flags, int mode){  int pa_open(const char *pathname, int flags, int mode){
         const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source());          return _wopen(PA_UTF16_ENC(pathname), flags, mode);
         return _wopen((const wchar_t *)utf16name, flags, mode);  
 }  }
   
 FILE *pa_fopen(const char *pathname, const char *mode){  FILE *pa_fopen(const char *pathname, const char *mode){
         const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source());          return _wfopen(PA_UTF16_ENC(pathname), PA_UTF16_ENC(mode));
         const UTF16* utf16mode=pa_utf16_encode(mode, pa_thread_request().charsets.source());  }
         return _wfopen((const wchar_t *)utf16name, (const wchar_t *)utf16mode);  
   int pa_mkdir(const char *pathname, int){
           return _wmkdir(PA_UTF16_ENC(pathname));
   }
   
   int pa_rmdir(const char *pathname){
           return _wrmdir(PA_UTF16_ENC(pathname));
   }
   
   int pa_rename(const char *oldpath, const char *newpath){
           return _wrename(PA_UTF16_ENC(oldpath), PA_UTF16_ENC(newpath));
 }  }
   
 int pa_unlink(const char *pathname){  int pa_unlink(const char *pathname){
         const UTF16* utf16name=pa_utf16_encode(pathname, pa_thread_request().charsets.source());          return _wunlink(PA_UTF16_ENC(pathname));
         return _wunlink((const wchar_t *)utf16name);  
 }  }
   
 #else  #else
   
   #define pa_mkdir mkdir
   #define pa_rmdir rmdir
   #define pa_rename rename
 #define pa_unlink unlink  #define pa_unlink unlink
   
 #endif  #endif
Line 296  void create_dir_for_file(const String& f Line 303  void create_dir_for_file(const String& f
         const char *str=file_spec.taint_cstr(String::L_FILE_SPEC);          const char *str=file_spec.taint_cstr(String::L_FILE_SPEC);
         if(str[0]){          if(str[0]){
                 const char *pos=str+1;                  const char *pos=str+1;
                 while((pos=strchr(pos,'/')) && pos[1]) { // to avoid trailing /, see #1166                  while((pos=strpbrk(pos, "/\\")) && pos[1]) { // to avoid trailing /, see #1166
                         pa_mkdir(pa_strdup(str,pos-str), 0775);                          pa_mkdir(pa_strdup(str,pos-str), 0775);
                         pos++;                          pos++;
                 }                  }
Line 450  static void rmdir(const String& file_spe Line 457  static void rmdir(const String& file_spe
 #ifdef _MSC_VER  #ifdef _MSC_VER
                 if(!entry_ifdir(dir_spec, true))                  if(!entry_ifdir(dir_spec, true))
                         break;                          break;
                 DWORD attrs=GetFileAttributes(dir_spec);                  DWORD attrs=GetFileAttributesW(PA_UTF16_ENC(dir_spec));
                 if(                  if(
                         (attrs==INVALID_FILE_ATTRIBUTES)                          (attrs==INVALID_FILE_ATTRIBUTES)
                         || !(attrs & FILE_ATTRIBUTE_DIRECTORY)                          || !(attrs & FILE_ATTRIBUTE_DIRECTORY)
Line 458  static void rmdir(const String& file_spe Line 465  static void rmdir(const String& file_spe
                 )                  )
                         break;                          break;
 #endif  #endif
                 if( rmdir(dir_spec) )                  if(pa_rmdir(dir_spec))
                         break;                          break;
         };          };
 }  }
Line 485  void file_move(const String& old_spec, c Line 492  void file_move(const String& old_spec, c
                   
         create_dir_for_file(new_spec);           create_dir_for_file(new_spec); 
   
         if(rename(old_spec_cstr, new_spec_cstr)!=0)          if(pa_rename(old_spec_cstr, new_spec_cstr)!=0)
                 throw Exception(errno==EACCES ? "file.access" : errno==ENOENT ? "file.missing" : 0,                  throw Exception(errno==EACCES ? "file.access" : errno==ENOENT ? "file.missing" : 0,
                         &old_spec, "rename failed: %s (%d), actual filename '%s' to '%s'", strerror(errno), errno, old_spec_cstr, new_spec_cstr);                          &old_spec, "rename failed: %s (%d), actual filename '%s' to '%s'", strerror(errno), errno, old_spec_cstr, new_spec_cstr);
   
Line 691  const char *pa_filename(const char *path Line 698  const char *pa_filename(const char *path
         return path;          return path;
 }  }
   
 // format: %[flags][width][.precision]type      http://msdn.microsoft.com/ru-ru/library/56e442dc(en-us,VS.80).aspx  
 //              flags: '-', '+', ' ', '#', '0'          http://msdn.microsoft.com/ru-ru/library/8aky45ct(en-us,VS.80).aspx  
 //              width, precision: non negative decimal number  
 enum FormatType {  
         FormatInvalid,  
         FormatInt,  
         FormatUInt,  
         FormatDouble  
 };  
 FormatType format_type(const char* fmt){  
         enum FormatState {  
                 Percent,   
                 Flags,   
                 Width,  
                 Precision,  
                 Done  
         } state=Percent;  
   
         FormatType result=FormatInvalid;  
   
         const char* pos=fmt;  
         while(char c=*(pos++)){  
                 switch(state){  
                         case Percent:  
                                 if(c=='%'){  
                                         state=Flags;  
                                 } else {  
                                         return FormatInvalid; // 1st char must be '%' only  
                                 }  
                                 break;  
                         case Flags:  
                                 if(strchr("-+ #0", c)!=0){  
                                         break;  
                                 }  
                                 // go to the next step  
                         case Width:  
                                 if(c=='.'){  
                                         state=Precision;  
                                         break;  
                                 }  
                                 // go to the next step  
                         case Precision:  
                                 if(c>='0' && c<='9'){  
                                         if(state == Flags) state=Width; // no more flags  
                                         break;  
                                 } else if(c=='d' || c=='i'){  
                                         result=FormatInt;  
                                 } else if(strchr("feEgG", c)!=0){  
                                         result=FormatDouble;  
                                 } else if(strchr("uoxX", c)!=0){  
                                         result=FormatUInt;  
                                 } else {  
                                         return FormatInvalid; // invalid char  
                                 }  
                                 state=Done;  
                                 break;  
                         case Done:  
                                 return FormatInvalid; // no chars allowed after 'type'  
                 }  
         }  
         return result;  
 }  
   
   
 const char* format_double(double value, const char* fmt) {  
         char local_buf[MAX_NUMBER];  
         int size=-1;  
   
         if(fmt && strlen(fmt)){  
                 switch(format_type(fmt)){  
                         case FormatDouble:  
                                 size=snprintf(local_buf, sizeof(local_buf), fmt, value);  
                                 break;  
                         case FormatUInt:  
                                 if(value >= 0){ // on Apple M1 (uint)<negative value> is 0  
                                         size=snprintf(local_buf, sizeof(local_buf), fmt, clip2uint(value));  
                                         break;  
                                 }  
                         case FormatInt:  
                                 size=snprintf(local_buf, sizeof(local_buf), fmt, clip2int(value));  
                                 break;  
                         case FormatInvalid:  
                                 throw Exception(PARSER_RUNTIME, 0, "Incorrect format string '%s' was specified.", fmt);  
                 }  
         } else  
                 return pa_itoa(clip2int(value));  
   
         if(size < 0 || size >= MAX_NUMBER-1){ // on win32 we manually reduce max size while printing  
                 throw Exception(PARSER_RUNTIME, 0, "Error occurred white executing snprintf with format string '%s'.", fmt);  
         }  
   
         return pa_strdup(local_buf, (size_t)size);  
 }  
   
 size_t stdout_write(const void *buf, size_t size) {  size_t stdout_write(const void *buf, size_t size) {
 #ifdef WIN32  #ifdef WIN32
         size_t to_write = size;          size_t to_write = size;
Line 806  size_t stdout_write(const void *buf, siz Line 719  size_t stdout_write(const void *buf, siz
 }  }
   
 enum EscapeState {  enum EscapeState {
         EscapeRest,           EscapeRest,
         EscapeFirst,           EscapeFirst,
         EscapeSecond,          EscapeSecond,
         EscapeUnicode          EscapeUnicode
 };  };

Removed from v.1.337  
changed lines
  Added in v.1.342


E-mail: