00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef _WIN32
00019 #include "win32/config.h"
00020 #else
00021 #include "config.h"
00022 #endif
00023
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <ctype.h>
00027 #include <limits.h>
00028 #ifdef HAVE_UNISTD_H
00029 #include <unistd.h>
00030 #endif
00031 #ifdef HAVE_STDLIB_H
00032 #include <stdlib.h>
00033 #endif
00034 #ifdef HAVE_STDDEF_H
00035 #include <stddef.h>
00036 #endif
00037 #ifdef HAVE_STDARG_H
00038 #include <stdarg.h>
00039 #endif
00040 #include <sys/stat.h>
00041 #ifdef __APPLE_API_PRIVATE
00042 #undef __APPLE_API_PRIVATE
00043 #endif
00044 #if HAVE_DIRENT_H
00045 # include <dirent.h>
00046 # define NAMLEN(dirent) strlen((dirent)->d_name)
00047 #else
00048 # if HAVE_SYS_DIRENT_H
00049 # include <sys/dirent.h>
00050 # define NAMLEN(dirent) strlen((dirent)->d_name)
00051 # else
00052 # define dirent direct
00053 # define NAMLEN(dirent) (dirent)->d_namlen
00054 # if HAVE_SYS_NDIR_H
00055 # include <sys/ndir.h>
00056 # endif
00057 # if HAVE_SYS_DIR_H
00058 # include <sys/dir.h>
00059 # endif
00060 # if HAVE_NDIR_H
00061 # include <ndir.h>
00062 # endif
00063 # endif
00064 #endif
00065
00066 #ifdef _WIN32
00067 #include "win32/afterbase.h"
00068 #include <io.h>
00069 #include <windows.h>
00070 #define access _access
00071 #else
00072 #include "afterbase.h"
00073 #endif
00074 #include "asimage.h"
00075
00076 #ifdef X_DISPLAY_MISSING
00077 #include "colornames.h"
00078 #endif
00079
00080
00081
00082 char *asim_ApplicationName = NULL ;
00083
00084 void
00085 asim_set_application_name (char *argv0)
00086 {
00087 char *temp = &(argv0[0]);
00088 do
00089 {
00090 register int i = 1 ;
00091
00092
00093 asim_ApplicationName = temp ;
00094 while( temp[i] && temp[i] != '/' ) ++i ;
00095 temp = temp[i] ? &(temp[i+1]): NULL ;
00096 }while( temp != NULL );
00097 }
00098
00099 const char *
00100 asim_get_application_name()
00101 {
00102 return asim_ApplicationName;
00103 }
00104
00105 static unsigned int asim_as_output_threshold = OUTPUT_DEFAULT_THRESHOLD ;
00106
00107 unsigned int
00108 asim_get_output_threshold()
00109 {
00110 return asim_as_output_threshold ;
00111 }
00112
00113 unsigned int
00114 asim_set_output_threshold( unsigned int threshold )
00115 {
00116 unsigned int old = asim_as_output_threshold;
00117 asim_as_output_threshold = threshold ;
00118 return old;
00119 }
00120
00121
00122
00123 Bool asim_show_error( const char *error_format, ...)
00124 {
00125 if( OUTPUT_LEVEL_ERROR <= get_output_threshold())
00126 {
00127 va_list ap;
00128 fprintf (stderr, "%s ERROR: ", get_application_name() );
00129 va_start (ap, error_format);
00130 vfprintf (stderr, error_format, ap);
00131 va_end (ap);
00132 fprintf (stderr, "\n" );
00133 return True;
00134 }
00135 return False;
00136 }
00137
00138 Bool asim_show_warning( const char *warning_format, ...)
00139 {
00140 if( OUTPUT_LEVEL_WARNING <= get_output_threshold())
00141 {
00142 va_list ap;
00143 fprintf (stderr, "%s warning: ", get_application_name() );
00144 va_start (ap, warning_format);
00145 vfprintf (stderr, warning_format, ap);
00146 va_end (ap);
00147 fprintf (stderr, "\n" );
00148 return True;
00149 }
00150 return False;
00151 }
00152
00153 Bool asim_show_progress( const char *msg_format, ...)
00154 {
00155 if( OUTPUT_LEVEL_PROGRESS <= get_output_threshold())
00156 {
00157 va_list ap;
00158 fprintf (stderr, "%s : ", get_application_name() );
00159 va_start (ap, msg_format);
00160 vfprintf (stderr, msg_format, ap);
00161 va_end (ap);
00162 fprintf (stderr, "\n" );
00163 return True;
00164 }
00165 return False;
00166 }
00167
00168
00169 Bool asim_show_debug( const char *file, const char *func, int line, const char *msg_format, ...)
00170 {
00171 if( OUTPUT_LEVEL_DEBUG <= get_output_threshold())
00172 {
00173 va_list ap;
00174 fprintf (stderr, "%s debug msg: %s:%s():%d: ", get_application_name(), file, func, line );
00175 va_start (ap, msg_format);
00176 vfprintf (stderr, msg_format, ap);
00177 va_end (ap);
00178 fprintf (stderr, "\n" );
00179 return True;
00180 }
00181 return False;
00182 }
00183
00184
00185 void asim_nonGNUC_debugout( const char *format, ...)
00186 {
00187 va_list ap;
00188 fprintf (stderr, "%s: ", get_application_name() );
00189 va_start (ap, format);
00190 vfprintf (stderr, format, ap);
00191 va_end (ap);
00192 fprintf (stderr, "\n" );
00193 }
00194
00195 void asim_nonGNUC_debugout_stub( const char *format, ...)
00196 {}
00197
00198
00199
00200 int asim_check_file_mode (const char *file, int mode)
00201 {
00202 struct stat st;
00203
00204 if ((stat (file, &st) == -1) || (st.st_mode & S_IFMT) != mode)
00205 return (-1);
00206 else
00207 return (0);
00208 }
00209
00210 char *
00211 asim_put_file_home (const char *path_with_home)
00212 {
00213 static char *home = NULL;
00214 static char default_home[3] = "./";
00215 static int home_len = 0;
00216 char *str = NULL, *ptr;
00217 register int i;
00218 if (path_with_home == NULL)
00219 return NULL;
00220
00221 if ( strncmp( path_with_home, "$HOME/", 6 ) == 0 )
00222 path_with_home += 5 ;
00223 else if (path_with_home[0] == '~' && path_with_home[1] == '/')
00224 path_with_home += 1 ;
00225 else
00226 return mystrdup(path_with_home);
00227
00228 if (home == NULL)
00229 {
00230 if ((home = getenv ("HOME")) == NULL)
00231 home = &(default_home[0]);
00232 home_len = strlen (home);
00233 }
00234
00235 for (i = 0; path_with_home[i]; i++);
00236 str = safemalloc (home_len + i + 1);
00237 for (ptr = str + home_len; i >= 0; i--)
00238 ptr[i] = path_with_home[i];
00239 for (i = 0; i < home_len; i++)
00240 str[i] = home[i];
00241 return str;
00242 }
00243
00244 char*
00245 asim_load_binary_file(const char* realfilename, long *file_size_return)
00246 {
00247 struct stat st;
00248 FILE* fp;
00249 char* data = NULL ;
00250
00251
00252 if (stat(realfilename, &st)) return NULL;
00253
00254 fp = fopen(realfilename, "rb");
00255 if ( fp != NULL )
00256 {
00257 long len ;
00258
00259 data = safecalloc(1, st.st_size + 1);
00260 len = fread(data, 1, st.st_size, fp);
00261 if( file_size_return )
00262 *file_size_return = len ;
00263 fclose(fp);
00264 }
00265 return data;
00266 }
00267
00268 char*
00269 asim_load_file(const char* realfilename)
00270 {
00271 long len;
00272 char* str = load_binary_file( realfilename, &len );
00273
00274 if (str != NULL && len >= 0)
00275 str[len] = '\0';
00276
00277 return str;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 void
00294 unix_path2dos_path( char *path )
00295 {
00296 int i = strlen(path) ;
00297 while( --i >= 0 )
00298 if( path[i] == '/' && ( i == 0 || path[i-1] != '/' ) )
00299 path[i] = '\\' ;
00300 }
00301
00302
00303 char *
00304 asim_find_file (const char *file, const char *pathlist, int type)
00305 {
00306 char *path;
00307 register int len;
00308 int max_path = 0;
00309 register char *ptr;
00310 register int i;
00311 Bool local = False ;
00312
00313 if (file == NULL)
00314 return NULL;
00315 #ifdef _WIN32
00316 #define PATH_SEPARATOR_CHAR ';'
00317 #define PATH_CHAR '\\'
00318 #else
00319 #define PATH_SEPARATOR_CHAR ':'
00320 #define PATH_CHAR '/'
00321 #endif
00322
00323 if (*file == PATH_CHAR || *file == '~' || ((pathlist == NULL) || (*pathlist == '\0')))
00324 local = True ;
00325 else if( file[0] == '.' && (file[1] == PATH_CHAR || (file[1] == '.' && file[2] == PATH_CHAR)))
00326 local = True ;
00327 else if( strncmp( file, "$HOME", 5) == 0 )
00328 local = True ;
00329 if( local )
00330 {
00331 path = put_file_home (file);
00332 if ( access (path, type) == 0 )
00333 {
00334 return path;
00335 }
00336 free (path);
00337 return NULL;
00338 }
00339
00340 for (i = 0; file[i]; i++);
00341 len = i ;
00342 for (ptr = (char *)pathlist; *ptr; ptr += i)
00343 {
00344 if (*ptr == PATH_SEPARATOR_CHAR )
00345 ptr++;
00346 for (i = 0; ptr[i] && ptr[i] != PATH_SEPARATOR_CHAR; i++);
00347 if (i > max_path)
00348 max_path = i;
00349 }
00350
00351 path = safecalloc (1, max_path + 1 + len + 1);
00352 strcpy( path+max_path+1, file );
00353 path[max_path] = PATH_CHAR ;
00354
00355 ptr = (char*)&(pathlist[0]) ;
00356 while( ptr[0] != '\0' )
00357 {
00358 int skip ;
00359 for( i = 0 ; ptr[i] == PATH_SEPARATOR_CHAR; ++i );
00360 ptr += i ;
00361 for( i = 0 ; ptr[i] != PATH_SEPARATOR_CHAR && ptr[i] != '\0'; ++i );
00362 skip = i ;
00363 if( i > 0 && ptr[i-1] == PATH_CHAR )
00364 i-- ;
00365 if( i > 0 )
00366 {
00367 register char *try_path = path+max_path-i;
00368 strncpy( try_path, ptr, i );
00369 if (access(try_path, type) == 0)
00370 {
00371 char* res = mystrdup(try_path);
00372 free( path );
00373 return res;
00374 }
00375 }
00376 ptr += skip ;
00377 }
00378 free (path);
00379 return NULL;
00380 }
00381
00382 static char *
00383 find_envvar (char *var_start, int *end_pos)
00384 {
00385 char backup, *name_start = var_start;
00386 register int i;
00387 char *var = NULL;
00388
00389 if (var_start[0] == '{')
00390 {
00391 name_start++;
00392 for (i = 1; var_start[i] && var_start[i] != '}'; i++);
00393 } else
00394 for (i = 0; isalnum ((int)var_start[i]) || var_start[i] == '_'; i++);
00395
00396 backup = var_start[i];
00397 var_start[i] = '\0';
00398 var = getenv (name_start);
00399 var_start[i] = backup;
00400
00401 *end_pos = i;
00402 if (backup == '}')
00403 (*end_pos)++;
00404 return var;
00405 }
00406
00407 static char *
00408 do_replace_envvar (char *path)
00409 {
00410 char *data = path, *tmp;
00411 char *home = getenv ("HOME");
00412 int pos = 0, len, home_len = 0;
00413
00414 if (path == NULL)
00415 return NULL;
00416 if (*path == '\0')
00417 return path;
00418 len = strlen (path);
00419 if (home)
00420 home_len = strlen (home);
00421
00422 while (*(data + pos))
00423 {
00424 char *var;
00425 int var_len, end_pos;
00426
00427 while (*(data + pos) != '$' && *(data + pos))
00428 {
00429 if (*(data + pos) == '~' && *(data + pos + 1) == '/')
00430 {
00431 if (pos > 0)
00432 if (*(data + pos - 1) != ':')
00433 {
00434 pos += 2;
00435 continue;
00436 }
00437 if (home == NULL)
00438 *(data + (pos++)) = '.';
00439 else
00440 {
00441 len += home_len;
00442 tmp = safecalloc (1, len);
00443 strncpy (tmp, data, pos);
00444 strcpy (tmp + pos, home);
00445 strcpy (tmp + pos + home_len, data + pos + 1);
00446 if( data != path )
00447 free (data);
00448 data = tmp;
00449 pos += home_len;
00450 }
00451 }
00452 pos++;
00453 }
00454 if (*(data + pos) == '\0')
00455 break;
00456
00457 if ((var = find_envvar (data + pos + 1, &end_pos)) == NULL)
00458 {
00459 ++pos;
00460 continue;
00461 }
00462 var_len = strlen (var);
00463 len += var_len;
00464 tmp = safecalloc (1, len);
00465 strncpy (tmp, data, pos);
00466 strcpy (tmp + pos, var);
00467 strcpy (tmp + pos + var_len, data + pos + end_pos + 1);
00468 if( data != path )
00469 free (data);
00470 data = tmp;
00471 }
00472 return data;
00473 }
00474
00475 char*
00476 asim_copy_replace_envvar (char *path)
00477 {
00478 char *res = do_replace_envvar( path );
00479 return ( res == path )?mystrdup( res ):res;
00480 }
00481
00482
00483
00484
00485 char *
00486 asim_mystrndup (const char *str, size_t n)
00487 {
00488 char *c = NULL;
00489 if (str)
00490 {
00491 c = calloc (1, n + 1);
00492 strncpy (c, str, n);
00493 }
00494 return c;
00495 }
00496
00497 char *
00498 asim_mystrdup (const char *str)
00499 {
00500 char *c = NULL;
00501
00502 if (str)
00503 {
00504 c = malloc (strlen (str) + 1);
00505 strcpy (c, str);
00506 }
00507 return c;
00508 }
00509
00510 int
00511 asim_mystrcasecmp (const char *s1, const char *s2)
00512 {
00513 int c1, c2;
00514 register int i = 0 ;
00515
00516 if (s1 == NULL || s2 == NULL)
00517 return (s1 == s2) ? 0 : ((s1==NULL)?1:-1);
00518 while (s1[i])
00519 {
00520
00521
00522 c1 = s1[i];
00523 if (isupper (c1))
00524 c1 = tolower (c1);
00525 c2 = s2[i];
00526 if (isupper (c2))
00527 c2 = tolower (c2);
00528
00529 ++i ;
00530 if (c1 != c2)
00531 return (c1 - c2);
00532 }
00533 return -s2[i];
00534 }
00535
00536 int
00537 asim_mystrncasecmp (const char *s1, const char *s2, size_t n)
00538 {
00539 register int c1, c2;
00540 register int i = 0 ;
00541
00542 if (s1 == NULL || s2 == NULL)
00543 return (s1 == s2) ? 0 : ((s1==NULL)?1:-1);
00544 while( i < n )
00545 {
00546 c1 = s1[i], c2 = s2[i];
00547 ++i ;
00548 if (c1==0)
00549 return -c2;
00550 if (isupper (c1))
00551 c1 = tolower(c1);
00552 if (isupper (c2))
00553 c2 = tolower(c2);
00554 if (c1 != c2)
00555 return (c1 - c2);
00556 }
00557 return 0;
00558 }
00559
00560 #ifdef X_DISPLAY_MISSING
00561 static int compare_xcolor_entries(const void *a, const void *b)
00562 {
00563 return strcmp((const char *) a, ((const XColorEntry *) b)->name);
00564 }
00565
00566 static int FindColor(const char *name, CARD32 *colorPtr)
00567 {
00568 XColorEntry *found;
00569
00570 found = bsearch(name, xColors, numXColors, sizeof(XColorEntry),
00571 compare_xcolor_entries);
00572 if (found == NULL)
00573 return 0;
00574
00575 *colorPtr = 0xFF000000|((found->red<<16)&0x00FF0000)|((found->green<<8)&0x0000FF00)|((found->blue)&0x000000FF);
00576 return 1;
00577 }
00578 #endif
00579
00580
00581
00582 const char *asim_parse_argb_color( const char *color, CARD32 *pargb )
00583 {
00584 #define hextoi(h) (isdigit(h)?((h)-'0'):(isupper(h)?((h)-'A'+10):((h)-'a'+10)))
00585 if( color )
00586 {
00587 if( *color == '#' )
00588 {
00589 CARD32 argb = 0 ;
00590 int len = 0 ;
00591 register const char *ptr = color+1 ;
00592 while( isxdigit((int)ptr[len]) ) len++;
00593 if( len >= 3)
00594 {
00595 if( (len&0x3) == 0 && len != 12 )
00596 {
00597 len = len>>2 ;
00598 argb = (hextoi((int)ptr[0])<<28)&0xF0000000 ;
00599 if( len > 1 )
00600 argb |= (hextoi((int)ptr[1])<<24)&0x0F000000 ;
00601 else
00602 argb |= 0x0F000000;
00603 ptr += len ;
00604 }else
00605 {
00606 len = len/3 ;
00607 argb = 0xFF000000;
00608 }
00609
00610 if( len == 1 )
00611 {
00612 argb |= 0x000F0F0F;
00613 argb |= (hextoi((int)ptr[0])<<20)&0x00F00000 ;
00614 argb |= (hextoi((int)ptr[1])<<12)&0x0000F000 ;
00615 argb |= (hextoi((int)ptr[2])<<4 )&0x000000F0 ;
00616 ptr += 3 ;
00617 }else
00618 {
00619 argb |= (hextoi((int)ptr[0])<<20)&0x00F00000 ;
00620 argb |= (hextoi((int)ptr[1])<<16)&0x000F0000 ;
00621 ptr += len ;
00622 argb |= (hextoi((int)ptr[0])<<12)&0x0000F000 ;
00623 argb |= (hextoi((int)ptr[1])<<8) &0x00000F00 ;
00624 ptr += len ;
00625 argb |= (hextoi((int)ptr[0])<<4 )&0x000000F0 ;
00626 argb |= (hextoi((int)ptr[1])) &0x0000000F ;
00627 ptr += len ;
00628 }
00629 *pargb = argb ;
00630 return ptr;
00631 }
00632 }else if( *color )
00633 {
00634
00635 Display *dpy = get_default_asvisual()->dpy;
00636 #ifdef X_DISPLAY_MISSING
00637 register const char *ptr = &(color[0]);
00638 if(!FindColor(color, pargb))
00639 return color;
00640 while( !isspace((int)*ptr) && *ptr != '\0' ) ptr++;
00641 return ptr;
00642 #else
00643 if( dpy == NULL )
00644 return color ;
00645 else
00646 {
00647 register const char *ptr = &(color[0]);
00648 #ifndef X_DISPLAY_MISSING
00649 XColor xcol, xcol_scr ;
00650
00651
00652 if( XLookupColor( dpy, DefaultColormap(dpy,DefaultScreen(dpy)), color, &xcol, &xcol_scr) )
00653 *pargb = 0xFF000000|((xcol.red<<8)&0x00FF0000)|(xcol.green&0x0000FF00)|((xcol.blue>>8)&0x000000FF);
00654 #endif
00655 while( !isspace((int)*ptr) && *ptr != '\0' ) ptr++;
00656 return ptr;
00657 }
00658 #endif
00659 }
00660 }
00661 return color;
00662 }
00663
00664
00665 static int asim_asxml_var_nget(char* name, int n);
00666
00667
00668
00669 double asim_parse_math(const char* str, char** endptr, double size) {
00670 double total = 0;
00671 char op = '+';
00672 char minus = 0;
00673 char logical_not = 0;
00674
00675 if( str == NULL )
00676 return 0 ;
00677
00678 while (isspace((int)*str)) str++;
00679 if( *str == '!' )
00680 {
00681 logical_not = 1;
00682 ++str ;
00683 }else if( *str == '-' )
00684 {
00685 minus = 1 ;
00686 ++str ;
00687 }
00688
00689 while (*str)
00690 {
00691 while (isspace((int)*str)) str++;
00692 if (!op)
00693 {
00694 if (*str == '+' || *str == '-' || *str == '*' || *str == '/') op = *str++;
00695 else if (*str == '-') { minus = 1; str++; }
00696 else if (*str == '!') { logical_not = 1; str++; }
00697 else if (*str == ')') { str++; break; }
00698 else break;
00699 } else
00700 {
00701 char* ptr;
00702 double num;
00703
00704 if (*str == '(')
00705 num = asim_parse_math(str + 1, &ptr, size);
00706 else if (*str == '$')
00707 {
00708 for (ptr = (char*)str + 1 ; *ptr && !isspace(*ptr) && *ptr != '+' && *ptr != '-' && *ptr != '*' && *ptr != '!' && *ptr != '/' && *ptr != ')' ; ptr++);
00709 num = asim_asxml_var_nget((char*)str + 1, ptr - (str + 1));
00710 }else
00711 num = strtod(str, &ptr);
00712
00713 if (str != ptr)
00714 {
00715 if (*ptr == '%') num *= size / 100.0, ptr++;
00716 if (minus) num = -num;
00717 if (logical_not) num = !num;
00718
00719 if (op == '+') total += num;
00720 else if (op == '-') total -= num;
00721 else if (op == '*') total *= num;
00722 else if (op == '/' && num) total /= num;
00723 } else
00724 break;
00725 str = ptr;
00726 op = '\0';
00727 minus = logical_not = 0;
00728 }
00729 }
00730 if (endptr) *endptr = (char*)str;
00731
00732 return total;
00733 }
00734
00735
00736
00737 ASHashKey asim_default_hash_func (ASHashableValue value, ASHashKey hash_size)
00738 {
00739 return (ASHashKey)(value % hash_size);
00740 }
00741
00742 long
00743 asim_default_compare_func (ASHashableValue value1, ASHashableValue value2)
00744 {
00745 return ((long)value1 - (long)value2);
00746 }
00747
00748 long
00749 asim_desc_long_compare_func (ASHashableValue value1, ASHashableValue value2)
00750 {
00751 return ((long)value2 - (long)value1);
00752 }
00753
00754 void
00755 asim_init_ashash (ASHashTable * hash, Bool freeresources)
00756 {
00757 LOCAL_DEBUG_CALLER_OUT( " has = %p, free ? %d", hash, freeresources );
00758 if (hash)
00759 {
00760 if (freeresources)
00761 if (hash->buckets)
00762 free (hash->buckets);
00763 memset (hash, 0x00, sizeof (ASHashTable));
00764 }
00765 }
00766
00767 ASHashTable *
00768 asim_create_ashash (ASHashKey size,
00769 ASHashKey (*hash_func) (ASHashableValue, ASHashKey),
00770 long (*compare_func) (ASHashableValue, ASHashableValue),
00771 void (*item_destroy_func) (ASHashableValue, void *))
00772 {
00773 ASHashTable *hash;
00774
00775 if (size <= 0)
00776 size = 63;
00777
00778 hash = safecalloc (1, sizeof (ASHashTable));
00779 init_ashash (hash, False);
00780
00781 hash->buckets = safecalloc (size, sizeof (ASHashBucket));
00782
00783 hash->size = size;
00784
00785 if (hash_func)
00786 hash->hash_func = hash_func;
00787 else
00788 hash->hash_func = asim_default_hash_func;
00789
00790 if (compare_func)
00791 hash->compare_func = compare_func;
00792 else
00793 hash->compare_func = asim_default_compare_func;
00794
00795 hash->item_destroy_func = item_destroy_func;
00796
00797 return hash;
00798 }
00799
00800 static void
00801 destroy_ashash_bucket (ASHashBucket * bucket, void (*item_destroy_func) (ASHashableValue, void *))
00802 {
00803 register ASHashItem *item, *next;
00804
00805 for (item = *bucket; item != NULL; item = next)
00806 {
00807 next = item->next;
00808 if (item_destroy_func)
00809 item_destroy_func (item->value, item->data);
00810 free (item);
00811 }
00812 *bucket = NULL;
00813 }
00814
00815 void
00816 asim_destroy_ashash (ASHashTable ** hash)
00817 {
00818 LOCAL_DEBUG_CALLER_OUT( " hash = %p, *hash = %p", hash, *hash );
00819 if (*hash)
00820 {
00821 register int i;
00822
00823 for (i = (*hash)->size - 1; i >= 0; i--)
00824 if ((*hash)->buckets[i])
00825 destroy_ashash_bucket (&((*hash)->buckets[i]), (*hash)->item_destroy_func);
00826
00827 asim_init_ashash (*hash, True);
00828 free (*hash);
00829 *hash = NULL;
00830 }
00831 }
00832
00833 static ASHashResult
00834 add_item_to_bucket (ASHashBucket * bucket, ASHashItem * item, long (*compare_func) (ASHashableValue, ASHashableValue))
00835 {
00836 ASHashItem **tmp;
00837
00838
00839 for (tmp = bucket; *tmp != NULL; tmp = &((*tmp)->next))
00840 {
00841 register long res = compare_func ((*tmp)->value, item->value);
00842
00843 if (res == 0)
00844 return ((*tmp)->data == item->data) ? ASH_ItemExistsSame : ASH_ItemExistsDiffer;
00845 else if (res > 0)
00846 break;
00847 }
00848
00849 item->next = (*tmp);
00850 *tmp = item;
00851 return ASH_Success;
00852 }
00853
00854 #define DEALLOC_CACHE_SIZE 1024
00855 static ASHashItem* deallocated_mem[DEALLOC_CACHE_SIZE+10] ;
00856 static unsigned int deallocated_used = 0 ;
00857
00858 ASHashResult
00859 asim_add_hash_item (ASHashTable * hash, ASHashableValue value, void *data)
00860 {
00861 ASHashKey key;
00862 ASHashItem *item;
00863 ASHashResult res;
00864
00865 if (hash == NULL)
00866 return ASH_BadParameter;
00867
00868 key = hash->hash_func (value, hash->size);
00869 if (key >= hash->size)
00870 return ASH_BadParameter;
00871
00872 if( deallocated_used > 0 )
00873 item = deallocated_mem[--deallocated_used];
00874 else
00875 item = safecalloc (1, sizeof (ASHashItem));
00876
00877 item->next = NULL;
00878 item->value = value;
00879 item->data = data;
00880
00881 res = add_item_to_bucket (&(hash->buckets[key]), item, hash->compare_func);
00882 if (res == ASH_Success)
00883 {
00884 hash->most_recent = item ;
00885 hash->items_num++;
00886 if (hash->buckets[key]->next == NULL)
00887 hash->buckets_used++;
00888 } else
00889 free (item);
00890 return res;
00891 }
00892
00893 static ASHashItem **
00894 find_item_in_bucket (ASHashBucket * bucket,
00895 ASHashableValue value, long (*compare_func) (ASHashableValue, ASHashableValue))
00896 {
00897 register ASHashItem **tmp;
00898 register long res;
00899
00900
00901 for (tmp = bucket; *tmp != NULL; tmp = &((*tmp)->next))
00902 {
00903 res = compare_func ((*tmp)->value, value);
00904 if (res == 0)
00905 return tmp;
00906 else if (res > 0)
00907 break;
00908 }
00909 return NULL;
00910 }
00911
00912 ASHashResult
00913 asim_get_hash_item (ASHashTable * hash, ASHashableValue value, void **trg)
00914 {
00915 ASHashKey key;
00916 ASHashItem **pitem = NULL;
00917
00918 if (hash)
00919 {
00920 key = hash->hash_func (value, hash->size);
00921 if (key < hash->size)
00922 pitem = find_item_in_bucket (&(hash->buckets[key]), value, hash->compare_func);
00923 }
00924 if (pitem)
00925 if (*pitem)
00926 {
00927 if (trg)
00928 *trg = (*pitem)->data;
00929 return ASH_Success;
00930 }
00931 return ASH_ItemNotExists;
00932 }
00933
00934 ASHashResult
00935 asim_remove_hash_item (ASHashTable * hash, ASHashableValue value, void **trg, Bool destroy)
00936 {
00937 ASHashKey key = 0;
00938 ASHashItem **pitem = NULL;
00939
00940 if (hash)
00941 {
00942 key = hash->hash_func (value, hash->size);
00943 if (key < hash->size)
00944 pitem = find_item_in_bucket (&(hash->buckets[key]), value, hash->compare_func);
00945 }
00946 if (pitem)
00947 if (*pitem)
00948 {
00949 ASHashItem *next;
00950
00951 if( hash->most_recent == *pitem )
00952 hash->most_recent = NULL ;
00953
00954 if (trg)
00955 *trg = (*pitem)->data;
00956
00957 next = (*pitem)->next;
00958 if (hash->item_destroy_func && destroy)
00959 hash->item_destroy_func ((*pitem)->value, (trg) ? NULL : (*pitem)->data);
00960
00961 if( deallocated_used < DEALLOC_CACHE_SIZE )
00962 {
00963 deallocated_mem[deallocated_used++] = *pitem ;
00964 }else
00965 free( *pitem );
00966
00967 *pitem = next;
00968 if (hash->buckets[key] == NULL)
00969 hash->buckets_used--;
00970 hash->items_num--;
00971
00972 return ASH_Success;
00973 }
00974 return ASH_ItemNotExists;
00975 }
00976
00977 void asim_flush_ashash_memory_pool()
00978 {
00979
00980 while( deallocated_used > 0 )
00981 free( deallocated_mem[--deallocated_used] );
00982 }
00983
00984
00985
00986
00987
00988 ASHashKey asim_pointer_hash_value (ASHashableValue value, ASHashKey hash_size)
00989 {
00990 union
00991 {
00992 void *ptr;
00993 ASHashKey key[2];
00994 } mix;
00995 register ASHashKey key;
00996
00997 mix.ptr = (void*)value;
00998 key = mix.key[0]^mix.key[1] ;
00999 if( hash_size == 256 )
01000 return (key>>4)&0x0FF;
01001 return (key>>4) % hash_size;
01002 }
01003
01004
01005 ASHashKey
01006 asim_string_hash_value (ASHashableValue value, ASHashKey hash_size)
01007 {
01008 ASHashKey hash_key = 0;
01009 register int i = 0;
01010 char *string = (char*)value;
01011 register char c;
01012
01013 do
01014 {
01015 c = string[i];
01016 if (c == '\0')
01017 break;
01018 hash_key += (((ASHashKey) c) << i);
01019 ++i ;
01020 }while( i < ((sizeof (ASHashKey) - sizeof (char)) << 3) );
01021 return hash_key % hash_size;
01022 }
01023
01024 long
01025 asim_string_compare (ASHashableValue value1, ASHashableValue value2)
01026 {
01027 register char *str1 = (char*)value1;
01028 register char *str2 = (char*)value2;
01029 register int i = 0 ;
01030
01031 if (str1 == str2)
01032 return 0;
01033 if (str1 == NULL)
01034 return -1;
01035 if (str2 == NULL)
01036 return 1;
01037 do
01038 {
01039 if (str1[i] != str2[i])
01040 return (long)(str1[i]) - (long)(str2[i]);
01041
01042 }while( str1[i++] );
01043 return 0;
01044 }
01045
01046 void
01047 asim_string_destroy_without_data (ASHashableValue value, void *data)
01048 {
01049 if ((char*)value != NULL)
01050 free ((char*)value);
01051 }
01052
01053
01054 ASHashKey
01055 asim_casestring_hash_value (ASHashableValue value, ASHashKey hash_size)
01056 {
01057 ASHashKey hash_key = 0;
01058 register int i = 0;
01059 char *string = (char*)value;
01060 register int c;
01061
01062 do
01063 {
01064 c = string[i];
01065 if (c == '\0')
01066 break;
01067 if (isupper (c))
01068 c = tolower (c);
01069 hash_key += (((ASHashKey) c) << i);
01070 ++i;
01071 }while(i < ((sizeof (ASHashKey) - sizeof (char)) << 3));
01072
01073 return hash_key % hash_size;
01074 }
01075
01076 long
01077 asim_casestring_compare (ASHashableValue value1, ASHashableValue value2)
01078 {
01079 register char *str1 = (char*)value1;
01080 register char *str2 = (char*)value2;
01081 register int i = 0;
01082
01083 if (str1 == str2)
01084 return 0;
01085 if (str1 == NULL)
01086 return -1;
01087 if (str2 == NULL)
01088 return 1;
01089 do
01090 {
01091 int u1, u2;
01092
01093 u1 = str1[i];
01094 u2 = str2[i];
01095 if (islower (u1))
01096 u1 = toupper (u1);
01097 if (islower (u2))
01098 u2 = toupper (u2);
01099 if (u1 != u2)
01100 return (long)u1 - (long)u2;
01101 }while( str1[i++] );
01102 return 0;
01103 }
01104
01105 int
01106 asim_get_drawable_size (Drawable d, unsigned int *ret_w, unsigned int *ret_h)
01107 {
01108 Display *dpy = get_default_asvisual()->dpy;
01109 *ret_w = 0;
01110 *ret_h = 0;
01111 #ifndef X_DISPLAY_MISSING
01112 if( dpy && d )
01113 {
01114 Window root;
01115 unsigned int ujunk;
01116 int junk;
01117 if (XGetGeometry (dpy, d, &root, &junk, &junk, ret_w, ret_h, &ujunk, &ujunk) != 0)
01118 return 1;
01119 }
01120 #endif
01121 return 0;
01122 }
01123
01124 #ifdef X_DISPLAY_MISSING
01125 int XParseGeometry ( char *string,int *x,int *y,
01126 unsigned int *width,
01127 unsigned int *height)
01128 {
01129 show_error( "Parsing of geometry is not supported without either Xlib opr libAfterBase" );
01130 return 0;
01131 }
01132 void XDestroyImage( void* d){}
01133 int XGetWindowAttributes( void*d, Window w, unsigned long m, void* s){ return 0;}
01134 void *XGetImage( void* dpy,Drawable d,int x,int y,unsigned int width,unsigned int height, unsigned long m,int t)
01135 {return NULL ;}
01136 unsigned long XGetPixel(void* d, int x, int y){return 0;}
01137 int XQueryColors(void* a,Colormap c,void* x,int m){return 0;}
01138 #endif
01139
01140
01141
01142
01143
01144 #if TIME_WITH_SYS_TIME
01145 # include <sys/time.h>
01146 # include <time.h>
01147 #else
01148 # if HAVE_SYS_TIME_H
01149 # include <sys/time.h>
01150 # else
01151 # include <time.h>
01152 # endif
01153 #endif
01154 #ifndef _WIN32
01155 # include <sys/times.h>
01156 #endif
01157 static clock_t _as_ticker_last_tick = 0;
01158 static clock_t _as_ticker_tick_size = 1;
01159 static clock_t _as_ticker_tick_time = 0;
01160
01161
01162
01163
01164 void
01165 sleep_a_little (int n)
01166 {
01167 #ifndef _WIN32
01168 struct timeval value;
01169
01170 if (n <= 0)
01171 return;
01172
01173 value.tv_usec = n % 1000000;
01174 value.tv_sec = n / 1000000;
01175
01176 #ifndef PORTABLE_SELECT
01177 #ifdef __hpux
01178 #define PORTABLE_SELECT(w,i,o,e,t) select((w),(int *)(i),(int *)(o),(e),(t))
01179 #else
01180 #define PORTABLE_SELECT(w,i,o,e,t) select((w),(i),(o),(e),(t))
01181 #endif
01182 #endif
01183 PORTABLE_SELECT (1, 0, 0, 0, &value);
01184 #else
01185 Sleep(n);
01186 #endif
01187 }
01188
01189 void
01190 asim_start_ticker (unsigned int size)
01191 {
01192 #ifndef _WIN32
01193 struct tms t;
01194
01195 _as_ticker_last_tick = times (&t);
01196 if (_as_ticker_tick_time == 0)
01197 {
01198 register clock_t delta = _as_ticker_last_tick;
01199
01200 sleep_a_little (100);
01201 _as_ticker_last_tick = times (&t);
01202 delta = _as_ticker_last_tick - delta ;
01203 if( delta <= 0 )
01204 _as_ticker_tick_time = 100;
01205 else
01206 _as_ticker_tick_time = 101 / delta;
01207 }
01208 #else
01209 _as_ticker_tick_time = 1000;
01210 _as_ticker_last_tick = time(NULL) ;
01211 #endif
01212 _as_ticker_tick_size = size;
01213
01214 }
01215
01216 void
01217 asim_wait_tick ()
01218 {
01219 #ifndef _WIN32
01220 struct tms t;
01221 register clock_t curr = (times (&t) - _as_ticker_last_tick) * _as_ticker_tick_time;
01222 #else
01223 register int curr = (time(NULL) - _as_ticker_last_tick) * _as_ticker_tick_time;
01224 #endif
01225
01226 if (curr < _as_ticker_tick_size)
01227 sleep_a_little (_as_ticker_tick_size - curr);
01228
01229 #ifndef _WIN32
01230 _as_ticker_last_tick = times (&t);
01231 #else
01232 _as_ticker_last_tick = time(NULL) ;
01233 #endif
01234 }
01235
01236 #ifndef _WIN32
01237
01238
01239
01240
01241
01242
01243
01244 int
01245 asim_my_scandir_ext ( const char *dirname, int (*filter_func) (const char *),
01246 Bool (*handle_direntry_func)( const char *fname, const char *fullname, struct stat *stat_info, void *aux_data),
01247 void *aux_data)
01248 {
01249 DIR *d;
01250 struct dirent *e;
01251 int n = 0;
01252 char *filename;
01253 char *p;
01254 struct stat stat_info;
01255
01256 d = opendir (dirname);
01257
01258 if (d == NULL)
01259 return -1;
01260
01261 filename = (char *)safecalloc (1, strlen (dirname) + PATH_MAX + 2);
01262 if (filename == NULL)
01263 {
01264 closedir (d);
01265 return -1;
01266 }
01267 strcpy (filename, dirname);
01268 p = filename + strlen (filename);
01269 if( *p != '/' )
01270 {
01271 *p++ = '/';
01272 *p = 0;
01273 }
01274
01275 while ((e = readdir (d)) != NULL)
01276 {
01277 if ((filter_func == NULL) || filter_func (&(e->d_name[0])))
01278 {
01279 int i = 0;
01280
01281 do{ p[i] = e->d_name[i]; ++i ; }while( e->d_name[i] && i < PATH_MAX );
01282 p[i] ='\0' ;
01283 if (stat (filename, &stat_info) != -1)
01284 {
01285 if( handle_direntry_func( e->d_name, filename, &stat_info, aux_data) )
01286 n++;
01287 }
01288 }
01289 }
01290 free (filename);
01291
01292 if (closedir (d) == -1)
01293 return -1;
01294
01295 return n;
01296 }
01297
01298 #endif
01299
01300
01301
01302
01303 static char* cdata_str = XML_CDATA_STR;
01304 static char* container_str = XML_CONTAINER_STR;
01305 static ASHashTable *asxml_var = NULL;
01306
01307 void
01308 asim_asxml_var_init(void)
01309 {
01310 if ( asxml_var == NULL )
01311 {
01312 Display *dpy = get_default_asvisual()->dpy;
01313
01314 asxml_var = create_ashash(0, string_hash_value, string_compare, string_destroy_without_data);
01315 if (!asxml_var) return;
01316 #ifndef X_DISPLAY_MISSING
01317 if ( dpy != NULL )
01318 {
01319 asxml_var_insert("xroot.width", XDisplayWidth (dpy, DefaultScreen(dpy)));
01320 asxml_var_insert("xroot.height", XDisplayHeight(dpy, DefaultScreen(dpy)));
01321 }
01322 #endif
01323 }
01324 }
01325
01326 void
01327 asim_asxml_var_insert(const char* name, int value)
01328 {
01329 ASHashData hdata;
01330
01331 if (!asxml_var) asxml_var_init();
01332 if (!asxml_var) return;
01333
01334
01335 remove_hash_item(asxml_var, AS_HASHABLE(name), NULL, True);
01336
01337 show_progress("Defining var [%s] == %d.", name, value);
01338
01339 hdata.i = value;
01340 add_hash_item(asxml_var, AS_HASHABLE(mystrdup(name)), hdata.vptr);
01341 }
01342
01343 int
01344 asim_asxml_var_get(const char* name)
01345 {
01346 ASHashData hdata = {0};
01347
01348 if (!asxml_var) asxml_var_init();
01349 if (!asxml_var) return 0;
01350 if( get_hash_item(asxml_var, AS_HASHABLE(name), &hdata.vptr) != ASH_Success )
01351 {
01352 show_debug(__FILE__, "asxml_var_get", __LINE__, "Use of undefined variable [%s].", name);
01353 return 0;
01354 }
01355 return hdata.i;
01356 }
01357
01358 static int
01359 asim_asxml_var_nget(char* name, int n) {
01360 int value;
01361 char oldc = name[n];
01362 name[n] = '\0';
01363 value = asxml_var_get(name);
01364 name[n] = oldc;
01365 return value;
01366 }
01367
01368 void
01369 asim_asxml_var_cleanup(void)
01370 {
01371 if ( asxml_var != NULL )
01372 destroy_ashash( &asxml_var );
01373
01374 }
01375
01376 static char* lcstring(char* str)
01377 {
01378 char* ptr = str;
01379 for ( ; *ptr ; ptr++) if (isupper((int)*ptr)) *ptr = tolower((int)*ptr);
01380 return str;
01381 }
01382
01383
01384 static xml_elem_t* xml_elem_new(void) {
01385 xml_elem_t* elem = NEW(xml_elem_t);
01386 elem->next = elem->child = NULL;
01387 elem->parm = elem->tag = NULL;
01388 elem->tag_id = XML_UNKNOWN_ID ;
01389
01390 return elem;
01391 }
01392
01393 static int
01394 xml_name2id( const char *name, ASHashTable *vocabulary )
01395 {
01396 ASHashData hdata;
01397 hdata.i = 0 ;
01398 get_hash_item(vocabulary, AS_HASHABLE(name), &hdata.vptr);
01399 return hdata.i;
01400 }
01401
01402 static xml_elem_t* xml_elem_remove(xml_elem_t** list, xml_elem_t* elem) {
01403
01404 if (list) {
01405 if (*list == elem) {
01406 *list = elem->next;
01407 } else {
01408 xml_elem_t* ptr;
01409 for (ptr = *list ; ptr->next ; ptr = ptr->next) {
01410 if (ptr->next == elem) {
01411 ptr->next = elem->next;
01412 break;
01413 }
01414 }
01415 }
01416 }
01417 elem->next = NULL;
01418 return elem;
01419 }
01420
01421 static void xml_insert(xml_elem_t* parent, xml_elem_t* child) {
01422 child->next = NULL;
01423 if (!parent->child) {
01424 parent->child = child;
01425 return;
01426 }
01427 for (parent = parent->child ; parent->next ; parent = parent->next);
01428 parent->next = child;
01429 }
01430
01431 xml_elem_t* asim_xml_parse_parm(const char* parm, ASHashTable *vocabulary) {
01432 xml_elem_t* list = NULL;
01433 const char* eparm;
01434
01435 if (!parm) return NULL;
01436
01437 for (eparm = parm ; *eparm ; ) {
01438 xml_elem_t* p;
01439 const char* bname;
01440 const char* ename;
01441 const char* bval;
01442 const char* eval;
01443
01444
01445 for (bname = eparm ; isspace((int)*bname) ; bname++);
01446
01447
01448 for (ename = bname ; xml_tagchar((int)*ename) ; ename++);
01449
01450
01451 if (!*ename) { eparm = NULL; break; }
01452
01453
01454
01455 for (bval = ename ; isspace((int)*bval) ; bval++);
01456 if (*bval != '=') { eparm = NULL; break; }
01457
01458 while (isspace((int)*++bval));
01459
01460
01461 if (*bval == '"' || *bval == '\'') {
01462 char quote = *bval;
01463 bval++;
01464 for (eval = bval ; *eval && *eval != quote ; eval++);
01465 } else {
01466 for (eval = bval ; *eval && !isspace((int)*eval) ; eval++);
01467 }
01468
01469 for (eparm = eval ; *eparm && !isspace((int)*eparm) ; eparm++);
01470
01471
01472 p = xml_elem_new();
01473 if (!list) list = p;
01474 else { p->next = list; list = p; }
01475 p->tag = lcstring(mystrndup(bname, ename - bname));
01476 if( vocabulary )
01477 p->tag_id = xml_name2id( p->tag, vocabulary );
01478 p->parm = mystrndup(bval, eval - bval);
01479 }
01480
01481 if (!eparm) {
01482 while (list) {
01483 xml_elem_t* p = list->next;
01484 free(list->tag);
01485 free(list->parm);
01486 free(list);
01487 list = p;
01488 }
01489 }
01490
01491 return list;
01492 }
01493
01494
01495 void asim_xml_elem_delete(xml_elem_t** list, xml_elem_t* elem) {
01496
01497
01498 if (list) xml_elem_remove(list, elem);
01499 while (elem) {
01500 xml_elem_t* ptr = elem;
01501 elem = elem->next;
01502 if (ptr->child) xml_elem_delete(NULL, ptr->child);
01503 if (ptr->tag && ptr->tag != cdata_str && ptr->tag != container_str) free(ptr->tag);
01504 if (ptr->parm) free(ptr->parm);
01505 free(ptr);
01506 }
01507 }
01508
01509 static xml_elem_t *
01510 create_CDATA_tag()
01511 {
01512 xml_elem_t *cdata = xml_elem_new();
01513 cdata->tag = strdup(XML_CDATA_STR) ;
01514 cdata->tag_id = XML_CDATA_ID ;
01515 return cdata;
01516 }
01517
01518 static xml_elem_t *
01519 create_CONTAINER_tag()
01520 {
01521 xml_elem_t *container = xml_elem_new();
01522 container->tag = strdup(XML_CONTAINER_STR) ;
01523 container->tag_id = XML_CONTAINER_ID ;
01524 return container;
01525 }
01526
01527
01528
01529 xml_elem_t* asim_xml_parse_doc(const char* str, ASHashTable *vocabulary) {
01530 xml_elem_t* elem = create_CONTAINER_tag();
01531 xml_parse(str, elem, vocabulary);
01532 return elem;
01533 }
01534
01535 int asim_xml_parse(const char* str, xml_elem_t* current, ASHashTable *vocabulary) {
01536 const char* ptr = str;
01537
01538
01539 while (*ptr) {
01540 const char* oab = ptr;
01541
01542
01543 for (oab = ptr ; *oab && *oab != '<' ; oab++);
01544
01545
01546 if (*oab != '<') return oab - str;
01547
01548
01549 if (oab[1] == '/')
01550 {
01551 const char* etag;
01552
01553 for (etag = oab + 2 ; xml_tagchar((int)*etag) ; etag++);
01554
01555 while (isspace((int)*etag)) ++etag;
01556
01557
01558 if (*etag == '>')
01559 {
01560 if (!mystrncasecmp(oab + 2, current->tag, etag - (oab + 2)))
01561 {
01562 if (oab - ptr)
01563 {
01564 xml_elem_t* child = create_CDATA_tag();
01565 child->parm = mystrndup(ptr, oab - ptr);
01566 xml_insert(current, child);
01567 }
01568 return (etag + 1) - str;
01569 }
01570 }
01571
01572
01573 ptr = oab + 1;
01574 }
01575
01576
01577 if (oab[1] != '/') {
01578 int empty = 0;
01579 const char* btag = oab + 1;
01580 const char* etag;
01581 const char* bparm;
01582 const char* eparm;
01583
01584
01585 for (etag = btag ; xml_tagchar((int)*etag) ; etag++);
01586
01587
01588 if (!*etag) { ptr = oab + 1; continue; }
01589
01590
01591 for (bparm = etag ; isspace((int)*bparm) ; bparm++);
01592
01593
01594
01595
01596 for (eparm = bparm ; *eparm ; ) {
01597 const char* tmp;
01598
01599
01600 for ( ; isspace((int)*eparm) ; eparm++);
01601
01602
01603 if (*eparm == '>' || (*eparm == '/' && eparm[1] == '>')) break;
01604
01605
01606 for (tmp = eparm ; xml_tagchar((int)*tmp) ; tmp++);
01607
01608
01609 if (!*tmp) { eparm = NULL; break; }
01610
01611
01612
01613 for ( ; isspace((int)*tmp) ; tmp++);
01614 if (*tmp != '=') { eparm = NULL; break; }
01615
01616 do { ++tmp; } while (isspace((int)*tmp));
01617
01618
01619 if (*tmp == '"' || *tmp == '\'') {
01620 char quote = *tmp;
01621 for (tmp++ ; *tmp && *tmp != quote ; tmp++);
01622 }
01623
01624
01625 for ( ; *tmp && !isspace((int)*tmp) && *tmp != '>' && !(*tmp == '/' && tmp[1] == '>') ; tmp++);
01626
01627
01628 if (!*tmp) { eparm = NULL; break; }
01629
01630
01631 eparm = tmp;
01632
01633 if (!isspace((int)*tmp)) break;
01634 for ( ; isspace((int)*tmp) ; tmp++);
01635 if( *tmp == '>' || (*tmp == '/' && tmp[1] == '>') )
01636 break;
01637 }
01638
01639
01640
01641 if (!eparm) { ptr = oab + 1; continue; }
01642
01643
01644 if (oab - ptr) {
01645 xml_elem_t* child = create_CDATA_tag();
01646 child->parm = mystrndup(ptr, oab - ptr);
01647 xml_insert(current, child);
01648 }
01649
01650
01651 for (ptr = eparm ; isspace((int)*ptr) ; ptr++);
01652 empty = (*ptr == '/');
01653 ptr += empty + 1;
01654
01655
01656 {
01657 xml_elem_t* child = xml_elem_new();
01658 child->tag = lcstring(mystrndup(btag, etag - btag));
01659 if( vocabulary )
01660 child->tag_id = xml_name2id( child->tag, vocabulary );
01661 if (eparm - bparm) child->parm = mystrndup(bparm, eparm - bparm);
01662 xml_insert(current, child);
01663 if (!empty) ptr += xml_parse(ptr, child, vocabulary);
01664 }
01665 }
01666 }
01667 return ptr - str;
01668 }
01669
01670
01671 char *asim_interpret_ctrl_codes( char *text )
01672 {
01673 register char *ptr = text ;
01674 int len, curr = 0 ;
01675 if( ptr == NULL ) return NULL ;
01676
01677 len = strlen(ptr);
01678 while( ptr[curr] != '\0' )
01679 {
01680 if( ptr[curr] == '\\' && ptr[curr+1] != '\0' )
01681 {
01682 char subst = '\0' ;
01683 switch( ptr[curr+1] )
01684 {
01685 case '\\': subst = '\\' ; break ;
01686 case 'a' : subst = '\a' ; break ;
01687 case 'b' : subst = '\b' ; break ;
01688 case 'f' : subst = '\f' ; break ;
01689 case 'n' : subst = '\n' ; break ;
01690 case 'r' : subst = '\r' ; break ;
01691 case 't' : subst = '\t' ; break ;
01692 case 'v' : subst = '\v' ; break ;
01693 }
01694 if( subst )
01695 {
01696 register int i = curr ;
01697 ptr[i] = subst ;
01698 while( ++i < len )
01699 ptr[i] = ptr[i+1] ;
01700 --len ;
01701 }
01702 }
01703 ++curr ;
01704 }
01705 return text;
01706 }
01707
01708 void asim_reset_xml_buffer( ASXmlBuffer *xb )
01709 {
01710 if( xb )
01711 {
01712 xb->current = xb->used = 0 ;
01713 xb->state = ASXML_Start ;
01714 xb->level = 0 ;
01715 xb->verbatim = False ;
01716 xb->quoted = False ;
01717 xb->tag_type = ASXML_OpeningTag ;
01718 xb->tags_count = 0 ;
01719 }
01720 }
01721
01722 void
01723 asim_free_xml_buffer_resources (ASXmlBuffer *xb)
01724 {
01725 if (xb && xb->buffer)
01726 {
01727 free (xb->buffer);
01728 xb->allocated = xb->current = xb->used = 0 ;
01729 xb->buffer = NULL;
01730 }
01731 }
01732
01733 static inline void
01734 realloc_xml_buffer( ASXmlBuffer *xb, int len )
01735 {
01736 if( xb->used + len > xb->allocated )
01737 {
01738 xb->allocated = xb->used + (((len>>11)+1)<<11) ;
01739 xb->buffer = realloc( xb->buffer, xb->allocated );
01740 }
01741 }
01742
01743 void
01744 asim_add_xml_buffer_chars( ASXmlBuffer *xb, char *tmp, int len )
01745 {
01746 realloc_xml_buffer (xb, len);
01747 memcpy( &(xb->buffer[xb->used]), tmp, len );
01748 xb->used += len ;
01749 }
01750
01751 static void
01752 add_xml_buffer_spaces( ASXmlBuffer *xb, int len )
01753 {
01754 if (len > 0)
01755 {
01756 realloc_xml_buffer (xb, len);
01757 memset( &(xb->buffer[xb->used]), ' ', len );
01758 xb->used += len ;
01759 }
01760 }
01761
01762 static void
01763 add_xml_buffer_open_tag( ASXmlBuffer *xb, xml_elem_t *tag )
01764 {
01765 int tag_len = strlen (tag->tag);
01766 int parm_len = 0;
01767 xml_elem_t* parm = NULL ;
01768
01769 if (tag->parm)
01770 {
01771 xml_elem_t *t = parm = xml_parse_parm(tag->parm, NULL);
01772 while (t)
01773 {
01774 parm_len += 1 + strlen(t->tag) + 1 + 1 + strlen(t->parm) + 1;
01775 t = t->next;
01776 }
01777 }
01778 realloc_xml_buffer (xb, 1+tag_len+1+parm_len+2);
01779 xb->buffer[(xb->used)++] = '<';
01780 memcpy (&(xb->buffer[xb->used]), tag->tag, tag_len);
01781 xb->used += tag_len ;
01782
01783 while (parm)
01784 {
01785 xml_elem_t* p = parm->next;
01786 int len;
01787 xb->buffer[(xb->used)++] = ' ';
01788 for (len = 0 ; parm->tag[len] ; ++len)
01789 xb->buffer[xb->used+len] = parm->tag[len];
01790 xb->used += len ;
01791 xb->buffer[(xb->used)++] = '=';
01792 xb->buffer[(xb->used)++] = '\"';
01793 for (len = 0 ; parm->parm[len] ; ++len)
01794 xb->buffer[xb->used+len] = parm->parm[len];
01795 xb->used += len ;
01796 xb->buffer[(xb->used)++] = '\"';
01797 free(parm->tag);
01798 free(parm->parm);
01799 free(parm);
01800 parm = p;
01801 }
01802
01803 if (tag->child == NULL)
01804 xb->buffer[(xb->used)++] = '/';
01805 xb->buffer[(xb->used)++] = '>';
01806 }
01807
01808 static void
01809 add_xml_buffer_close_tag( ASXmlBuffer *xb, xml_elem_t *tag )
01810 {
01811 int tag_len = strlen (tag->tag);
01812 realloc_xml_buffer (xb, tag_len+3);
01813 xb->buffer[(xb->used)++] = '<';
01814 xb->buffer[(xb->used)++] = '/';
01815 memcpy (&(xb->buffer[xb->used]), tag->tag, tag_len);
01816 xb->used += tag_len ;
01817 xb->buffer[(xb->used)++] = '>';
01818 }
01819
01820 int
01821 asim_spool_xml_tag( ASXmlBuffer *xb, char *tmp, int len )
01822 {
01823 register int i = 0 ;
01824
01825 if( !xb->verbatim && !xb->quoted &&
01826 (xb->state != ASXML_Start || xb->level == 0 ))
01827 {
01828 while( i < len && isspace( (int)tmp[i] )) ++i;
01829 if( i >= len )
01830 return i;
01831 }
01832 if( xb->state == ASXML_Start )
01833 {
01834 if( tmp[i] != '<' )
01835 {
01836 if( xb->level == 0 )
01837 xb->state = ASXML_BadStart ;
01838 else
01839 {
01840 int start = i ;
01841 while( i < len && tmp[i] != '<' ) ++i ;
01842 add_xml_buffer_chars( xb, &tmp[start], i - start );
01843 return i;
01844 }
01845 }else
01846 {
01847 xb->state = ASXML_TagOpen;
01848 xb->tag_type = ASXML_OpeningTag ;
01849 add_xml_buffer_chars( xb, "<", 1 );
01850 if( ++i >= len )
01851 return i;
01852 }
01853 }
01854
01855 if( xb->state == ASXML_TagOpen )
01856 {
01857 if( tmp[i] == '/' )
01858 {
01859 xb->state = ASXML_TagName;
01860 xb->verbatim = True ;
01861 xb->tag_type = ASXML_ClosingTag ;
01862 add_xml_buffer_chars( xb, "/", 1 );
01863 if( ++i >= len )
01864 return i;
01865 }else if( isalnum((int)tmp[i]) )
01866 {
01867 xb->state = ASXML_TagName;
01868 xb->verbatim = True ;
01869 }else
01870 xb->state = ASXML_BadTagName ;
01871 }
01872
01873 if( xb->state == ASXML_TagName )
01874 {
01875 int start = i ;
01876
01877 while( i < len && isalnum((int)tmp[i]) ) ++i ;
01878 if( i > start )
01879 add_xml_buffer_chars( xb, &tmp[start], i - start );
01880 if( i < len )
01881 {
01882 if( isspace( (int)tmp[i] ) || tmp[i] == '>' )
01883 {
01884 xb->state = ASXML_TagAttrOrClose;
01885 xb->verbatim = False ;
01886 }else
01887 xb->state = ASXML_BadTagName ;
01888 }
01889 return i;
01890 }
01891
01892 if( xb->state == ASXML_TagAttrOrClose )
01893 {
01894 Bool has_slash = (xb->tag_type != ASXML_OpeningTag);
01895
01896 if( !has_slash && tmp[i] == '/' )
01897 {
01898 xb->tag_type = ASXML_SimpleTag ;
01899 add_xml_buffer_chars( xb, "/", 1 );
01900 ++i ;
01901 has_slash = True ;
01902 }
01903 if( i < len )
01904 {
01905 if( has_slash && tmp[i] != '>')
01906 xb->state = ASXML_UnexpectedSlash ;
01907 else if( tmp[i] == '>' )
01908 {
01909 ++(xb->tags_count);
01910 xb->state = ASXML_Start;
01911 add_xml_buffer_chars( xb, ">", 1 );
01912 ++i ;
01913 if( xb->tag_type == ASXML_OpeningTag )
01914 ++(xb->level);
01915 else if( xb->tag_type == ASXML_ClosingTag )
01916 {
01917 if( xb->level <= 0 )
01918 {
01919 xb->state = ASXML_UnmatchedClose;
01920 return i;
01921 }else
01922 --(xb->level);
01923 }
01924 }else if( !isalnum( (int)tmp[i] ) )
01925 xb->state = ASXML_BadAttrName ;
01926 else
01927 {
01928 xb->state = ASXML_AttrName;
01929 xb->verbatim = True ;
01930 add_xml_buffer_chars( xb, " ", 1);
01931 }
01932 }
01933 return i;
01934 }
01935
01936 if( xb->state == ASXML_AttrName )
01937 {
01938 int start = i ;
01939
01940 while( i < len && isalnum((int)tmp[i]) ) ++i ;
01941 if( i > start )
01942 add_xml_buffer_chars( xb, &tmp[start], i - start );
01943 if( i < len )
01944 {
01945 if( isspace( (int)tmp[i] ) || tmp[i] == '=' )
01946 {
01947 xb->state = ASXML_AttrEq;
01948 xb->verbatim = False ;
01949
01950 }else
01951 xb->state = ASXML_BadAttrName ;
01952 }
01953 return i;
01954 }
01955
01956 if( xb->state == ASXML_AttrEq )
01957 {
01958 if( tmp[i] == '=' )
01959 {
01960 xb->state = ASXML_AttrValueStart;
01961 add_xml_buffer_chars( xb, "=", 1 );
01962 ++i ;
01963 }else
01964 xb->state = ASXML_MissingAttrEq ;
01965 return i;
01966 }
01967
01968 if( xb->state == ASXML_AttrValueStart )
01969 {
01970 xb->state = ASXML_AttrValue ;
01971 if( tmp[i] == '"' )
01972 {
01973 xb->quoted = True ;
01974 add_xml_buffer_chars( xb, "\"", 1 );
01975 ++i ;
01976 }else
01977 xb->verbatim = True ;
01978 return i;
01979 }
01980
01981 if( xb->state == ASXML_AttrValue )
01982 {
01983 if( !xb->quoted && isspace((int)tmp[i]) )
01984 {
01985 add_xml_buffer_chars( xb, " ", 1 );
01986 ++i ;
01987 xb->verbatim = False ;
01988 xb->state = ASXML_TagAttrOrClose ;
01989 }else if( xb->quoted && tmp[i] == '"' )
01990 {
01991 add_xml_buffer_chars( xb, "\"", 1 );
01992 ++i ;
01993 xb->quoted = False ;
01994 xb->state = ASXML_TagAttrOrClose ;
01995 }else if( tmp[i] == '/' && !xb->quoted)
01996 {
01997 xb->state = ASXML_AttrSlash ;
01998 add_xml_buffer_chars( xb, "/", 1 );
01999 ++i ;
02000 }else if( tmp[i] == '>' )
02001 {
02002 xb->quoted = False ;
02003 xb->verbatim = False ;
02004 xb->state = ASXML_TagAttrOrClose ;
02005 }else
02006 {
02007 add_xml_buffer_chars( xb, &tmp[i], 1 );
02008 ++i ;
02009 }
02010 return i;
02011 }
02012 if( xb->state == ASXML_AttrSlash )
02013 {
02014 if( tmp[i] == '>' )
02015 {
02016 xb->tag_type = ASXML_SimpleTag ;
02017 add_xml_buffer_chars( xb, ">", 1 );
02018 ++i ;
02019 ++(xb->tags_count);
02020 xb->state = ASXML_Start;
02021 xb->quoted = False ;
02022 xb->verbatim = False ;
02023 }else
02024 {
02025 xb->state = ASXML_AttrValue ;
02026 }
02027 return i;
02028 }
02029
02030 return (i==0)?1:i;
02031 }
02032
02033
02034 Bool
02035 asim_xml_tags2xml_buffer( xml_elem_t *tags, ASXmlBuffer *xb, int tags_count, int depth)
02036 {
02037 Bool new_line = False;
02038
02039 while (tags && tags_count != 0)
02040 {
02041 if (tags->tag_id == XML_CDATA_ID || !strcmp(tags->tag, cdata_str))
02042 {
02043
02044 add_xml_buffer_chars( xb, tags->parm, strlen(tags->parm));
02045 }else
02046 {
02047 if (depth >= 0 && (tags->child != NULL || tags->next != NULL))
02048 {
02049 add_xml_buffer_chars( xb, "\n", 1);
02050 add_xml_buffer_spaces( xb, depth*2);
02051 new_line = True ;
02052 }
02053 add_xml_buffer_open_tag( xb, tags);
02054
02055 if (tags->child)
02056 {
02057 if( xml_tags2xml_buffer( tags->child, xb, -1, (depth < 0)?-1:depth+1 ))
02058 {
02059 if (depth >= 0)
02060 {
02061 add_xml_buffer_chars( xb, "\n", 1);
02062 add_xml_buffer_spaces( xb, depth*2);
02063 }
02064 }
02065 add_xml_buffer_close_tag( xb, tags);
02066 }
02067 }
02068 tags = tags->next;
02069 --tags_count;
02070 }
02071 return new_line;
02072 }
02073
02074 void asim_xml_print(xml_elem_t* root)
02075 {
02076 ASXmlBuffer xb;
02077 memset( &xb, 0x00, sizeof(xb));
02078 xml_tags2xml_buffer( root, &xb, -1, 0);
02079 add_xml_buffer_chars( &xb, "\0", 1 );
02080 printf ("%s", xb.buffer);
02081 free_xml_buffer_resources (&xb);
02082 }
02083
02084
02085 xml_elem_t *
02086 asim_format_xml_buffer_state (ASXmlBuffer *xb)
02087 {
02088 xml_elem_t *state_xml = NULL;
02089 if (xb->state < 0)
02090 {
02091 state_xml = xml_elem_new();
02092 state_xml->tag = strdup("error");
02093 state_xml->parm = safemalloc (64);
02094 sprintf(state_xml->parm, "code=%d level=%d tag_count=%d", xb->state, xb->level ,xb->tags_count );
02095 state_xml->child = create_CDATA_tag();
02096 switch( xb->state )
02097 {
02098 case ASXML_BadStart : state_xml->child->parm = strdup("Text encountered before opening tag bracket - not XML format"); break;
02099 case ASXML_BadTagName : state_xml->child->parm = strdup("Invalid characters in tag name" );break;
02100 case ASXML_UnexpectedSlash : state_xml->child->parm = strdup("Unexpected '/' encountered");break;
02101 case ASXML_UnmatchedClose : state_xml->child->parm = strdup("Closing tag encountered without opening tag" );break;
02102 case ASXML_BadAttrName : state_xml->child->parm = strdup("Invalid characters in attribute name" );break;
02103 case ASXML_MissingAttrEq : state_xml->child->parm = strdup("Attribute name not followed by '=' character" );break;
02104 default:
02105 state_xml->child->parm = strdup("Premature end of the input");break;
02106 }
02107 }else if (xb->state == ASXML_Start)
02108 {
02109 if (xb->tags_count > 0)
02110 {
02111 state_xml = xml_elem_new();
02112 state_xml->tag = strdup("success");
02113 state_xml->parm = safemalloc(64);
02114 sprintf(state_xml->parm, "tag_count=%d level=%d", xb->tags_count, xb->level );
02115 }
02116 }else
02117 {
02118
02119 }
02120 return state_xml;
02121 }