c2dec6b29e1b51a3b16bb04f8c31e541979d7993
[polyglot.git] / util.c
1 \r
2 // util.c\r
3 \r
4 // includes\r
5 \r
6 #ifdef _WIN32\r
7 #include <windows.h>\r
8 #include <direct.h>\r
9 #else\r
10 #include <unistd.h>\r
11 #endif\r
12 \r
13 #include <ctype.h>\r
14 #include <errno.h>\r
15 #include <math.h>\r
16 #include <stdarg.h>\r
17 #include <stdio.h>\r
18 #include <stdlib.h>\r
19 #include <string.h>\r
20 #include <time.h>\r
21 #ifndef _MSC_VER\r
22 #include <sys/time.h>\r
23 #endif\r
24 \r
25 #include "main.h"\r
26 #include "util.h"\r
27 #include "gui.h"\r
28 \r
29 // macros\r
30 \r
31 #define StringSize 4096\r
32 \r
33 // variables\r
34 \r
35 static bool Error;\r
36 \r
37 FILE * LogFile=NULL;\r
38 \r
39 // functions\r
40 \r
41 // util_init()\r
42 \r
43 void util_init() {\r
44 \r
45    Error = FALSE;\r
46 \r
47    // init log file\r
48 \r
49    LogFile = NULL;\r
50 \r
51    // switch file buffering off\r
52 \r
53    setbuf(stdin,NULL);\r
54    setbuf(stdout,NULL);\r
55 }\r
56 \r
57 // my_random_init()\r
58 \r
59 void my_random_init() {\r
60    srand(time(NULL));\r
61 }\r
62 \r
63 // my_random_int()\r
64 \r
65 int my_random_int(int n) {\r
66 \r
67    int r;\r
68 \r
69    ASSERT(n>0);\r
70 \r
71    r = ((int)floor(my_random_double()*((double)n)));\r
72    ASSERT(r>=0&&r<n);\r
73 \r
74    return r;\r
75 }\r
76 \r
77 // my_random_double()\r
78 \r
79 double my_random_double() {\r
80 \r
81    double r;\r
82 \r
83    r = ((double)rand()) / (((double)RAND_MAX) + 1.0);\r
84    ASSERT(r>=0.0&&r<1.0);\r
85 \r
86    return r;\r
87 }\r
88 \r
89 // my_atoll()\r
90 \r
91 sint64 my_atoll(const char string[]) {\r
92 \r
93    sint64 n;\r
94 \r
95    sscanf(string,S64_FORMAT,&n);\r
96 \r
97    return n;\r
98 }\r
99 \r
100 // my_round()\r
101 \r
102 int my_round(double x) {\r
103 \r
104     return ((int)floor(x+0.5));\r
105 }\r
106 \r
107 // my_malloc()\r
108 \r
109 void * my_malloc(size_t size) {\r
110 \r
111    void * address;\r
112 \r
113    ASSERT(size>0);\r
114 \r
115    address = malloc(size);\r
116    if (address == NULL) my_fatal("my_malloc(): malloc(): %s\n",strerror(errno));\r
117 \r
118    return address;\r
119 }\r
120 \r
121 // my_realloc()\r
122 \r
123 void * my_realloc(void * address, size_t size) {\r
124 \r
125    ASSERT(address!=NULL);\r
126    ASSERT(size>0);\r
127 \r
128    address = realloc(address,size);\r
129    if (address == NULL) my_fatal("my_realloc(): realloc(): %s\n",strerror(errno));\r
130 \r
131    return address;\r
132 }\r
133 \r
134 // my_free()\r
135 \r
136 void my_free(void * address) {\r
137 \r
138    ASSERT(address!=NULL);\r
139 \r
140    free(address);\r
141 }\r
142 \r
143 // my_log_open()\r
144 \r
145 void my_log_open(const char file_name[]) {\r
146 \r
147    ASSERT(file_name!=NULL);\r
148 \r
149    LogFile = fopen(file_name,"a");\r
150 #ifndef _WIN32\r
151 //line buffering doesn't work too well in MSVC and/or windows \r
152    if (LogFile != NULL) setvbuf(LogFile,NULL,_IOLBF,0); // line buffering\r
153 #endif\r
154    if(LogFile!=NULL){\r
155        my_log("POLYGLOT *** LOGFILE OPENED ***\n");\r
156    }\r
157 \r
158 }\r
159 \r
160 // my_log_close()\r
161 \r
162 void my_log_close() {\r
163 \r
164    if (LogFile != NULL) fclose(LogFile);\r
165    LogFile=NULL;\r
166 }\r
167 \r
168 // my_log()\r
169 \r
170 void my_log(const char format[], ...) {\r
171     \r
172     char string[FormatBufferSize];\r
173     \r
174     ASSERT(format!=NULL);\r
175 \r
176 //  format\r
177 \r
178     CONSTRUCT_ARG_STRING(format,string);\r
179     \r
180 \r
181     if (LogFile != NULL) {\r
182         fprintf(LogFile,"%.3f %s",now_real(),string);\r
183 #ifdef _WIN32\r
184         fflush(LogFile);\r
185 #endif\r
186     }\r
187 }\r
188 \r
189 // my_fatal()\r
190 \r
191 void my_fatal(const char format[], ...) {\r
192 \r
193     char string[FormatBufferSize];\r
194 \r
195     ASSERT(format!=NULL);\r
196 \r
197 // format\r
198 \r
199     CONSTRUCT_ARG_STRING(format,string);\r
200     \r
201     my_log("POLYGLOT %s",string);\r
202     // This should be gui_send but this does not work.\r
203     // Why?\r
204 \r
205     printf("tellusererror POLYGLOT: %s",string);\r
206 \r
207     if (Error) { // recursive error\r
208         my_log("POLYGLOT *** RECURSIVE ERROR ***\n");\r
209         exit(EXIT_FAILURE);\r
210             // abort();\r
211     } else {\r
212       Error = TRUE;\r
213       quit();\r
214     }\r
215 }\r
216 \r
217 // my_file_read_line()\r
218 \r
219 bool my_file_read_line(FILE * file, char string[], int size) {\r
220 \r
221    int src, dst;\r
222    int c;\r
223 \r
224    ASSERT(file!=NULL);\r
225    ASSERT(string!=NULL);\r
226    ASSERT(size>0);\r
227 \r
228    if (fgets(string,size,file) == NULL) {\r
229       if (feof(file)) {\r
230          return FALSE;\r
231       } else { // error\r
232          my_fatal("my_file_read_line(): fgets(): %s\n",strerror(errno));\r
233       }\r
234    }\r
235 \r
236    // remove CRs and LFs\r
237 \r
238    src = 0;\r
239    dst = 0;\r
240    \r
241    while ((c=string[src++]) != '\0') {\r
242       if (c != '\r' && c != '\n') string[dst++] = c;\r
243    }\r
244 \r
245    string[dst] = '\0';\r
246 \r
247    return TRUE;\r
248 }\r
249 \r
250 // my_file_join()\r
251 \r
252 void my_path_join(char *join_path, const char *path, const char *file){\r
253     char separator;\r
254 #ifdef _WIN32\r
255     separator='\\';\r
256 #else\r
257     separator='/';\r
258 #endif\r
259     snprintf(join_path,StringSize,"%s%c%s",path,separator,file);\r
260     join_path[StringSize-1]='\0';\r
261 }\r
262 \r
263 // my_mkdir()\r
264 \r
265 int my_mkdir(const char *path){\r
266     int ret;\r
267 #ifdef _WIN32\r
268     ret=_mkdir(path);\r
269 #else\r
270     ret=mkdir(path,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);\r
271 #endif\r
272     return ret;\r
273 }\r
274 \r
275 \r
276 // my_string_empty()\r
277 \r
278 bool my_string_empty(const char string[]) {\r
279 \r
280    return string == NULL || string[0] == '\0';\r
281 }\r
282 \r
283 // my_string_whitespace()\r
284 \r
285 bool my_string_whitespace(const char string[]){\r
286     int pos=0;\r
287     while(string[pos]!='\0'){\r
288         if(string[pos]!=' ' && string[pos]!='\t'){\r
289             return FALSE;\r
290         }\r
291         pos++;\r
292     }\r
293     return TRUE;\r
294 }\r
295 \r
296 // my_string_equal()\r
297 \r
298 bool my_string_equal(const char string_1[], const char string_2[]) {\r
299 \r
300    ASSERT(string_1!=NULL);\r
301    ASSERT(string_2!=NULL);\r
302 \r
303    return strcmp(string_1,string_2) == 0;\r
304 }\r
305 \r
306 // my_string_case_equal()\r
307 \r
308 bool my_string_case_equal(const char string_1[], const char string_2[]) {\r
309 \r
310    int c1, c2;\r
311 \r
312    ASSERT(string_1!=NULL);\r
313    ASSERT(string_2!=NULL);\r
314 \r
315    while (TRUE) {\r
316 \r
317       c1 = *string_1++;\r
318       c2 = *string_2++;\r
319 \r
320       if (tolower(c1) != tolower(c2)) return FALSE;\r
321       if (c1 == '\0') return TRUE;\r
322    }\r
323 \r
324    return FALSE;\r
325 }\r
326 \r
327 // my_strtolower()\r
328 \r
329 void my_string_tolower(char *dst, const char *src){\r
330   int c;\r
331   ASSERT(src!=NULL);\r
332   ASSERT(dst!=NULL);\r
333   while((c=*(src++))){\r
334     *dst=tolower(c);\r
335     dst++;\r
336   }\r
337   *(dst++)='\0';\r
338 }\r
339 \r
340 // my_string_case_contains()\r
341 \r
342 const char* my_string_case_contains(const char string_1[], const char string_2[]){\r
343    \r
344    char tmp1[StringSize];\r
345    char tmp2[StringSize];\r
346    char *where;\r
347 \r
348 \r
349    ASSERT(string_1!=NULL);\r
350    ASSERT(string_2!=NULL);\r
351 \r
352    my_string_tolower(tmp1,string_1);\r
353    my_string_tolower(tmp2,string_2);\r
354 \r
355    where=strstr(tmp1,tmp2);\r
356    if(where){\r
357       return string_1+(where-tmp1);\r
358    }\r
359    return NULL;\r
360 \r
361   \r
362 }\r
363 \r
364 \r
365 // my_strdup()\r
366 \r
367 char * my_strdup(const char string[]) {\r
368 \r
369    char * address;\r
370 \r
371    ASSERT(string!=NULL);\r
372 \r
373    // strdup() is not ANSI C\r
374 \r
375    address = (char *) my_malloc(strlen(string)+1);\r
376    strcpy(address,string);\r
377 \r
378    return address;\r
379 }\r
380 \r
381 // my_string_clear()\r
382 \r
383 void my_string_clear(const char * * variable) {\r
384 \r
385    ASSERT(variable!=NULL);\r
386 \r
387    if (*variable != NULL) {\r
388       my_free((void*)(*variable));\r
389       *variable = NULL;\r
390    }\r
391 }\r
392 \r
393 // my_string_set()\r
394 \r
395 void my_string_set(const char * * variable, const char string[]) {\r
396 \r
397    ASSERT(variable!=NULL);\r
398    ASSERT(string!=NULL);\r
399 \r
400    if (*variable != NULL) my_free((void*)(*variable));\r
401    *variable = my_strdup(string);\r
402 }\r
403 \r
404 // now_real()\r
405 \r
406 double now_real() {\r
407 #ifndef _WIN32\r
408    struct timeval tv[1];\r
409    struct timezone tz[1];\r
410 \r
411    tz->tz_minuteswest = 0;\r
412    tz->tz_dsttime = 0; // DST_NONE not declared in linux\r
413 \r
414    if (gettimeofday(tv,tz) == -1) {\r
415       my_fatal("now_real(): gettimeofday(): %s\n",strerror(errno));\r
416    }\r
417 \r
418    return tv->tv_sec + tv->tv_usec * 1E-6;\r
419 #else\r
420    struct _timeb timeptr;\r
421    _ftime(&timeptr);\r
422    return(timeptr.time+((double)timeptr.millitm)/1000.0);\r
423 //   return (double) GetTickCount() / 1000.0;  // we can do better here:-)\r
424 #endif\r
425 }\r
426 \r
427 \r
428 // my_timer_reset()\r
429 \r
430 void my_timer_reset(my_timer_t * timer) {\r
431 \r
432    ASSERT(timer!=NULL);\r
433 \r
434    timer->start_real = 0.0;\r
435    timer->elapsed_real = 0.0;\r
436    timer->running = FALSE;\r
437 }\r
438 \r
439 // my_timer_start()\r
440 \r
441 void my_timer_start(my_timer_t * timer) {\r
442 // timer->start_real = 0.0;\r
443    timer->elapsed_real = 0.0;\r
444 // timer->running = FALSE;\r
445    ASSERT(timer!=NULL);\r
446 \r
447    timer->running = TRUE;\r
448    timer->start_real = now_real();\r
449 }\r
450 \r
451 // my_timer_stop()\r
452 \r
453 void my_timer_stop(my_timer_t * timer) {\r
454 \r
455    ASSERT(timer!=NULL);\r
456 \r
457    ASSERT(timer->running);\r
458 \r
459    timer->elapsed_real += now_real() - timer->start_real;\r
460    timer->start_real = 0.0;\r
461    timer->running = FALSE;\r
462 }\r
463 \r
464 // my_timer_elapsed_real()\r
465 \r
466 double my_timer_elapsed_real(const my_timer_t * timer) {\r
467 \r
468    double elapsed;\r
469 \r
470    ASSERT(timer!=NULL);\r
471 \r
472    elapsed = timer->elapsed_real;\r
473    if (timer->running) elapsed += now_real() - timer->start_real;\r
474 \r
475    if (elapsed < 0.0) elapsed = 0.0;\r
476 \r
477    return elapsed;\r
478 }\r
479 \r
480 \r
481 void my_dequote(char *out, const char *in, const char *special){\r
482   const char *p; \r
483   char *q;\r
484   char c;\r
485   p=in;\r
486   q=out;\r
487   while((c=*(p++))){\r
488     if(c=='\\' && strchr(special,*p)){\r
489       *(q++)=*(p++);\r
490     }else{\r
491       *(q++)=c;\r
492     }\r
493   }\r
494   *q='\0';\r
495 }\r
496 \r
497 void my_quote(char *out, const char *in, const char *special){\r
498   const char *p;\r
499   char *q;\r
500   char c;\r
501   p=in;\r
502   q=out;\r
503   while(q-out< StringSize-2 && (c=*(p++))){\r
504     if(c=='\\'){\r
505       if(*p!=0 && strchr(special,*p)){\r
506         *(q++)='\\';\r
507       }\r
508     }else if(strchr(special,c)){\r
509       *(q++)='\\';\r
510     }\r
511     *(q++)=c;\r
512   }\r
513   *q='\0';\r
514 }\r
515 \r
516 \r
517 void my_sleep(int msec){\r
518 #ifndef _WIN32\r
519   struct timespec tm;\r
520   tm.tv_sec=msec/1000;\r
521   tm.tv_nsec=1000000*(msec%1000);\r
522   nanosleep(&tm,NULL);\r
523 #else\r
524   Sleep(msec);\r
525 #endif\r
526 }\r