456 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			456 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <ctype.h>
 | |
| #include <stdarg.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #ifndef FOXPRO
 | |
| #include <xvt.h>
 | |
| #endif
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
| #include <direct.h>
 | |
| #include <io.h>
 | |
| #define F_OK 0
 | |
| #else
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #include <unistd.h>
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @func Permette di rimuovere un file (chiama unlink)
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione
 | |
| //
 | |
| // @flag 0 | Se l'operazione ha successo
 | |
| // @flag -1 | Se l'operazione non e' riuscita. Viene inoltre settata la variabile
 | |
| //            <p errno> con la causa dell'insuccesso
 | |
| int remove(
 | |
|   const char* path)  // @parm Nome del file da eliminare (non valgono i caratteri jolly)
 | |
| { return unlink(path); }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #define __UTILITY_CPP
 | |
| #include <utility.h>
 | |
| 
 | |
| // @func Permette di copiare un file
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione:
 | |
| //
 | |
| // @flag TRUE | Se l'operazione e' stata effettuata con successo
 | |
| // @flag FALSE | Se l'operazione non e' stata effettuata con successo
 | |
| bool fcopy(
 | |
|   const char* orig,  // @parm Nome del file di origine
 | |
|   const char* dest,  // @parm Nome del file di destinazione
 | |
|   bool append)       // @parm Controllo per aggiungere il contenuto del
 | |
|   //       file <p dest> in coda al file <p orig> (default FALSE)
 | |
| 
 | |
|   // @comm Nel caso vengano ravvisati degli errori durante l'operazione vengono
 | |
|   //       creati dei box di comunicazione che indicano la causa del problema
 | |
| { 
 | |
|   const char* wflag;
 | |
| #if XVT_OS == XVT_OS_WIN
 | |
|   const char* const rflag = "rb";
 | |
|   if (append)                    
 | |
|     wflag = "ab";
 | |
|   else
 | |
|     wflag = "wb";
 | |
| #else
 | |
|   const char* const rflag = "r";
 | |
|   if (append)
 | |
|     wflag = "a";
 | |
|   else
 | |
|     wflag = "w";
 | |
| #endif
 | |
| 
 | |
|   FILE* i = fopen(orig, rflag);
 | |
|   if (!i) return error_box("Impossibile leggere il file %s", orig);
 | |
| 
 | |
|   FILE* o = fopen(dest, wflag);
 | |
|   CHECKS(o, "Impossibile scrivere il file ", dest);
 | |
| 
 | |
|   const word size = 16*1024;
 | |
|   TString buffer(size);
 | |
|   
 | |
|   bool ok = TRUE;          
 | |
|   while (ok)
 | |
|   {
 | |
|     const word letti = fread((char*)(const char*)buffer, 1, size, i);
 | |
|     ok = fwrite((char*)(const char*)buffer, 1, letti, o) == letti;
 | |
|     if (letti < size) break;
 | |
|   }    
 | |
|   
 | |
|   if (!ok) error_box("Errore di scrittura: probabile disco pieno!");
 | |
| 
 | |
|   fclose(o);
 | |
|   fclose(i);
 | |
| 
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // @func Controlla l'esistenza di un file
 | |
| //
 | |
| // @rdesc Ritrona i seguenti valori:
 | |
| //
 | |
| // @flag TRUE | Se il file esiste
 | |
| // @flag FALSE | Se il file non esiste
 | |
| bool fexist(
 | |
|   const char* file)  // @parm Nome del file di cui contrallarne l'esistenza
 | |
| {
 | |
|   return access(file, F_OK) == 0;
 | |
| }
 | |
| 
 | |
| // @func Permette di creare una directory
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione
 | |
| //
 | |
| // @flag TRUE | Se l'operazione e' avvenuta con successo
 | |
| // @flag FALSE | Se l'operazione non e' riuscita
 | |
| bool make_dir(
 | |
|   const char* dir) // @parm Nome della directory da creare
 | |
| {
 | |
|   int res =
 | |
| #if XVT_OS==XVT_OS_WIN
 | |
|     mkdir(dir);
 | |
| #else
 | |
|   mkdir(dir, 0777);
 | |
| #endif       
 | |
|   return res == 0;
 | |
| }
 | |
| 
 | |
| #ifndef FOXPRO
 | |
| 
 | |
| // @func Setta la token string modificando la lista dei file formata con caratteri jolly
 | |
| //                       in lista con caratteri estesi
 | |
| //
 | |
| // @rdesc Ritorna il numero di file che soddisfano la condizione passata (numero di elementi
 | |
| //                              della token string)
 | |
| int list_files(
 | |
|   TToken_string& filelist) // @parm Stringa contenente la condizione di estrazione 
 | |
|   //                            della lista dei file
 | |
|   
 | |
|   // @comm Per comodita' la lista desiderata vine anch'essa messa in <p filelist> in quanto e'
 | |
|   //                     gia' costruita                                                                                                                  
 | |
| {           
 | |
|   TFilename dir(filelist.get(0));
 | |
|   for (int i = dir.len()-1; i >= 0; i--)
 | |
|     if (dir[i] == '/' || dir[i] == '\\') break;
 | |
|   
 | |
|   const TString16 mask(dir.mid(i+1));
 | |
|   dir.cut(i > 0 ? i : 0);   
 | |
|   
 | |
|   xvt_fsys_save_dir();        
 | |
|   DIRECTORY directory; xvt_fsys_convert_str_to_dir((char*)(const char*)dir, &directory);
 | |
|   BOOLEAN ok = xvt_fsys_set_dir(&directory);
 | |
|   if (!ok) fatal_box ("Impossibile entrare in %s", (const char*)dir);
 | |
|   
 | |
|   SLIST files = xvt_fsys_list_files("", (char*)(const char*)mask, FALSE);
 | |
|   
 | |
|   const int count = xvt_slist_count(files);
 | |
|   filelist.spaces(count*12);
 | |
|   filelist.cut(0);
 | |
|   
 | |
|   for (SLIST_ELT e = xvt_slist_get_first(files); e; e = xvt_slist_get_next(files, e))
 | |
|   { 
 | |
|     char* f = xvt_slist_get(files, e, NULL);
 | |
|     if (dir.not_empty()) 
 | |
|     {
 | |
|       filelist.add(dir); 
 | |
|       filelist << '/' << f;
 | |
|     }
 | |
|     else 
 | |
|       filelist.add(f);  
 | |
|   }
 | |
|   
 | |
|   xvt_slist_destroy(files);
 | |
|   xvt_fsys_restore_dir();
 | |
|   
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| // Certified 99%
 | |
| // @func Permette di ritornare una stringa formata da parametri
 | |
| //
 | |
| // @rdesc Ritorna la stringa desiderata
 | |
| char* format(
 | |
|   const char* fmt, // @parm Formato che deve essere dato alla stringa
 | |
|   ...)                     // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
 | |
| 
 | |
|   // @comm Il funzionamento e' come la <f sprintf> del C, solo che non e' necessario passare la
 | |
|   //                     stringa di destinazione alla funzione
 | |
| {
 | |
|   va_list pars;
 | |
| 
 | |
|   va_start(pars, fmt);
 | |
|   const int tot = vsprintf(__tmp_string, fmt, pars);
 | |
|   va_end(pars);
 | |
| 
 | |
|   CHECK(tot >= 0 && tot < sizeof(__tmp_string)-1, "Ue'! Ma quanto scrivi?");
 | |
|   return(__tmp_string);
 | |
| }
 | |
| 
 | |
| 
 | |
| // @func Converte la coppia nome-parametro in una stringa che identifica il programma
 | |
| //
 | |
| // @rdesc Ritorna la stringa identificante il programma
 | |
| const char* cmd2name(
 | |
|   const char* argv0,  // @parm Nome del programma
 | |
|   const char* argv1)  // @parm Nome del parametro (default "")
 | |
| {
 | |
|   TFilename app(argv0);
 | |
|   app = app.name(); 
 | |
|   if (argv1 && *argv1) app << ' ' << argv1;
 | |
|   else app << " -0";
 | |
|   app.lower();
 | |
| 
 | |
|   const int par = app.find(" -");
 | |
|   const int num = par > 0 ? atoi(app.mid(par+2))+1 : 1; 
 | |
| 
 | |
|   const char c = (num > 9) ? ('a'+num-10) : ('0'+num);
 | |
|   app.cut(3);
 | |
|   app << c << "00";
 | |
| 
 | |
|   return strcpy(__tmp_string, app);
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Conversione in cifre romane
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| HIDDEN const char * cifre_romane = "IVXLCDM@";
 | |
| HIDDEN const int valori_cifre [] = { 1, 5, 10, 50, 100, 500, 1000, -1 };
 | |
| 
 | |
| HIDDEN int ctoi(char c)
 | |
| {
 | |
|   if (c == '\0') return 0;
 | |
| 
 | |
|   c = toupper(c);
 | |
|   for (int i = 0; cifre_romane[i]; i++)
 | |
|     if (cifre_romane[i] == c) return valori_cifre[i];
 | |
| 
 | |
|   return -1;
 | |
| }
 | |
| // @func Converte una cifra romana in intero normale
 | |
| //
 | |
| // @rdesc Ritorna l'equivalente in numeri della cifra romane
 | |
| int rtoi(
 | |
|   const char * val) // @parm Stringa contenente la cifra scritta in numeri romani
 | |
| {
 | |
|   if (val == NULL) return 0;
 | |
| 
 | |
|   int tot = 0;
 | |
|   int value = ctoi (val[0]);
 | |
|   for (int i = 1; value > 0; i++)
 | |
|   {
 | |
|     const int next_val = ctoi(val[i]);
 | |
|     if (value < next_val) tot -= value;
 | |
|     else                  tot += value;
 | |
|     value = next_val;
 | |
|   }
 | |
| 
 | |
|   return (value == 0) ? tot : -1;
 | |
| }
 | |
| 
 | |
| // @func Converte un numero intero nell'equivalente cifra romana
 | |
| //
 | |
| // @rdesc Ritorna una stringa contenente la cifra romana
 | |
| const char* itor(
 | |
|   int num) // @parm Intero da convertire in cifra romana
 | |
| {
 | |
|   HIDDEN char roman_string[16];
 | |
|   int cifra = 0;
 | |
| 
 | |
|   for (int pos = 7; pos--;)
 | |
|   {
 | |
|     int val = valori_cifre[pos];
 | |
|     int quanti = num / val;
 | |
|     if (quanti < 4)
 | |
|     {
 | |
|       if ((pos & 1) && quanti == 1 && (num/valori_cifre[pos-1]) == 9)
 | |
|       {
 | |
|         roman_string[cifra++] = cifre_romane[pos-1];
 | |
|         roman_string[cifra++] = cifre_romane[pos+1];
 | |
|         val = valori_cifre[pos-1];
 | |
|         quanti = 9;
 | |
|       }
 | |
|       else for (int i = 0; i < quanti; i++)
 | |
|         roman_string[cifra++] = cifre_romane[pos];
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       roman_string[cifra++] = cifre_romane[pos];
 | |
|       roman_string[cifra++] = cifre_romane[pos+1];
 | |
|     }
 | |
| 
 | |
|     num -= quanti * val;
 | |
|   }
 | |
| 
 | |
|   roman_string[cifra] = '\0';
 | |
|   return roman_string;
 | |
| }
 | |
| 
 | |
| // @func Permette di codificare i caratteri di escape
 | |
| //
 | |
| // @rdesc Ritorna il carattere codificato
 | |
| const char *esc(
 | |
|   const char* s) // @parm Carattere da codificare
 | |
| 
 | |
|   // @comm Viene utilizzata soprattuto in UNIX.
 | |
| {
 | |
|   const char    *s1 = s;
 | |
|   char  *s2 = __tmp_string;
 | |
|   int           base;
 | |
| 
 | |
|   while (*s1)
 | |
|   {
 | |
|     if (*s1 == '\\')
 | |
|     {
 | |
|       s1++;
 | |
|       switch (tolower(*s1))
 | |
|       {
 | |
|       case 'b' : *s2++ = '\b'; break;
 | |
|                case 'e' : *s2++ = '\033'; break;
 | |
|                case 'f' : *s2++ = '\f'; break;
 | |
|                case 'n' : *s2++ = '\n'; break;
 | |
|                case 'r' : *s2++ = '\r'; break;
 | |
|                case 't' : *s2++ = '\t'; break;
 | |
|                  default  :
 | |
|                {
 | |
|                  if (isdigit(*s1))
 | |
|                  {
 | |
|                    if (*s1 == '0')
 | |
|                    {
 | |
|                      s1++;
 | |
|                      if (tolower(*s1) == 'x') 
 | |
|                      {
 | |
|                        s1++;
 | |
|                        base = 16;
 | |
|                      }
 | |
|                      else base = 8;
 | |
|                    }
 | |
|                    else base = 10;
 | |
|                    *s2 = 0;
 | |
|                    char c = tolower(*s1);
 | |
|                    while (isdigit(c) || (base == 16 && c >= 'a' && c <= 'f'))
 | |
|                    {
 | |
|                      *s2 *= base;
 | |
|                      if (isdigit(*s1)) *s2 += (*s1 - 48);
 | |
|                      else *s2 += (*s1 - 'a' + 10) & 0x0F;
 | |
|                      s1++;
 | |
|                      c = tolower(*s1);
 | |
|                    }
 | |
|                    s2++; s1--;
 | |
|                  }
 | |
|                  else *s2++ = *s1;
 | |
|                }
 | |
|                }
 | |
|     }
 | |
|     else
 | |
|       if (*s1 == '^')
 | |
|       {
 | |
|         s1++;
 | |
|         *s2++ = (tolower(*s1) - 'a' + 1);
 | |
|       }
 | |
|       else *s2++ = *s1 ;
 | |
|     s1++;
 | |
|   }
 | |
|   *s2 = '\0';
 | |
|   return(__tmp_string);
 | |
| }
 | |
| 
 | |
| HIDDEN const char * const key = "QSECOFR-";
 | |
| 
 | |
| // @func Permette di criptare una parola
 | |
| //
 | |
| // @rdesc Ritorna la stringa criptata
 | |
| const char * encode(
 | |
|   const char * data) // @parm Stringa da criptare
 | |
| 
 | |
|   // @xref <f decode>
 | |
| {
 | |
|   for (int i = 0; data[i]; i++)
 | |
|     __tmp_string[i] = data[i] + (i < 8 ? key[i] : data[i - 8]);
 | |
|   __tmp_string[i] = '\0';
 | |
|   return __tmp_string; 
 | |
| }
 | |
| 
 | |
| // @func Permette di decodificare una stringa criptata
 | |
| //
 | |
| // @rdesc Ritorna la stringa in chiaro
 | |
| const char * decode(
 | |
|   const char * data) // @parm Stringa criptata da tradurre
 | |
| 
 | |
|   // @xref <f encode>
 | |
| {
 | |
|   for (int i = 0; data[i]; i++)
 | |
|     __tmp_string[i] = data[i] - (i < 8 ? key[i] : __tmp_string[i - 8]);
 | |
|   __tmp_string[i] = '\0';
 | |
|   return __tmp_string; 
 | |
| }
 | |
| 
 | |
| #if XVT_OS != XVT_OS_WIN
 | |
| 
 | |
| // @func Permette di confrontare due stringhe ignorando la differenza
 | |
| //       tra lettere maiuscole o minuscole
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione:
 | |
| //
 | |
| // @flag 0 | Se le stringhe sono uguali
 | |
| // @flag >0 | Se le stringhe sono differenti. Il numero indica la lettera diversa
 | |
| int stricmp(
 | |
|   const char* s1,  // @parm Prima stringa da confrontare
 | |
|   const char* s2)  // @parm Seconda stringa da confrontare
 | |
| {
 | |
|   for(int d = 0 ; (d = toupper(*s1)-toupper(*s2)) == 0; s1++, s2++)
 | |
|     if (*s1 == '\0' && *s2 == '\0') 
 | |
|       return 0;
 | |
|   return d;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifdef __WATCOMC__
 | |
| // @func Costruisce il percorso per un file temporaneo
 | |
| //
 | |
| // @rdesc Ritorna il nome assoluto del file temporaneo
 | |
| char * tempnam(
 | |
|   const char * dir ,   // @parm Nome della directory nel quale inserire il file temporaneo
 | |
|   const char * prefix) // @parm Evenutale prefisso da dare al file temporaneo
 | |
| 
 | |
|   // @comm Il nome della directory viene letto dalla variabile d'ambiente chiamata
 | |
|   //       TMP, solo nel caso questa non esista viene utilizzato il nome passato
 | |
|   //       in <p dir>.
 | |
|   //                     <nl>E' definita solo nel caso si utilizzi il WATCOM C/C++.
 | |
| 
 | |
| {
 | |
|   TFilename tmpdir(getenv("TMP"));
 | |
|   static word counter = 1;
 | |
| 
 | |
|   if (tmpdir.empty() || !fexist(tmpdir))
 | |
|   {
 | |
|     tmpdir = dir;
 | |
|     if (tmpdir.empty() || !fexist(tmpdir))
 | |
|       tmpdir = "";
 | |
|   }
 | |
|   if (is_not_slash(tmpdir.right(1)[0]))
 | |
|     tmpdir << '/';
 | |
|   tmpdir << prefix ;
 | |
|   const int lastpos = tmpdir.len() ;
 | |
|   tmpdir << format("%ud", counter);
 | |
| 
 | |
|   while (!fexist(tmpdir))
 | |
|   {
 | |
|     counter++;
 | |
|     if (counter == 0) counter = 1;
 | |
|     tmpdir.cut(lastpos);
 | |
|     tmpdir << format("%ud", counter);
 | |
|   }
 | |
|   return strdup(tmpdir);
 | |
| }
 | |
| #endif
 | |
| 
 |