afterbase.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001 Sasha Vasko <sasha at aftercode.net>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /*#include <X11/Xlib.h>*/
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         {       /* Save our program name - for error messages */
00090                 register int i = 1 ;                   /* we don't use standard strrchr since there
00091                                                                                                 * seems to be some wierdness in
00092                                                                                                 * CYGWIN implementation of it. */
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 /* from libAfterBase/output.c : */
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 /* from libAfterBase/fs.c : */
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;                                 /* the HOME environment variable */
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         /* home dir ? */
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         /* Get the file size. */
00252         if (stat(realfilename, &st)) return NULL;
00253         /* Open the file. */
00254         fp = fopen(realfilename, "rb");
00255         if ( fp != NULL ) 
00256         {
00257                 long len ; 
00258                 /* Read in the file. */
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  * Find the specified icon file somewhere along the given path.
00284  *
00285  * There is a possible race condition here:  We check the file and later
00286  * do something with it.  By then, the file might not be accessible.
00287  * Oh well.
00288  *
00289  ****************************************************************************/
00290 /* supposedly pathlist should not include any environment variables
00291    including things like ~/
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 /*      return put_file_home(file); */
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                 /* found $ sign - trying to replace var */
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 /* from mystring.c : */
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                 /* in some BSD implementations, tolower(c) is not defined
00521                  * unless isupper(c) is true */
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 /* from parse,c : */
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                                 {  /* we do have alpha channel !!! */
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                                 /* processing rest of the channels : */
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                         /* does not really matter here what screen to use : */
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 /* XXX Not sure if Scr.asv->colormap is always defined here.  If not,
00651 ** change back to DefaultColormap(dpy,DefaultScreen(dpy)). */
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 /* Math expression parsing algorithm. */
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 /*      const char* startptr = str; */
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 /*      show_debug(__FILE__,"parse_math",__LINE__,"Parsed math [%s] with reference [%.2f] into number [%.2f].", startptr, size, total); */
00732         return total;
00733 }
00734 
00735 /*******************************************************************/
00736 /* from ashash,c : */
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         /* first check if we already have this item */
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         /* now actually add this item */
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         /* first check if we already have this item */
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         /* we better disable errors as some of this data will belong to memory audit : */
00980         while( deallocated_used > 0 )
00981                 free( deallocated_mem[--deallocated_used] );
00982 }
00983 
00984 /************************************************************************/
00985 /************************************************************************/
00986 /*      Some usefull implementations                                    */
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 /* case sensitive strings hash */
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 /* variation for case-unsensitive strings */
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,    /* RETURN */
01127                                           unsigned int *height)    /* RETURN */
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 /* from sleep.c                        */
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  * Sleep for n microseconds
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 /* win32 : */
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);                 /* in system ticks */
01196         if (_as_ticker_tick_time == 0)
01197         {
01198                 register clock_t delta = _as_ticker_last_tick;
01199                 /* calibrating clock - how many ms per cpu tick ? */
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;                       /* in ms */
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  * Non-NULL select and dcomp pointers are *NOT* tested, but should be OK.
01239  * They are not used by afterstep however, so this implementation should
01240  * be good enough.
01241  *
01242  * c.ridd@isode.com
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;                                                  /* Pointer to static struct inside readdir() */
01251         int           n = 0;                                       /* Count of nl used so far */
01252         char         *filename;                                    /* For building filename to pass to stat */
01253         char         *p;                                                   /* Place where filename starts */
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;                                                                    /* Just in case... */
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                         /* Fill in the fields using stat() */
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         /* Return the count of the entries */
01295         return n;
01296 }
01297 
01298 #endif /* #ifndef _WIN32 */
01299 
01300 /***************************************/
01301 /* from xml.c                          */
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     /* Destroy any old data associated with this name. */
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 /*      LOCAL_DEBUG_OUT("elem = %p", elem); */
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         /* Splice the element out of the list, if it's in one. */
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                 /* Spin past any leading whitespace. */
01445                 for (bname = eparm ; isspace((int)*bname) ; bname++);
01446 
01447                 /* Check for a parm.  First is the parm name. */
01448                 for (ename = bname ; xml_tagchar((int)*ename) ; ename++);
01449 
01450                 /* No name equals no parm equals broken tag. */
01451                 if (!*ename) { eparm = NULL; break; }
01452 
01453                 /* No "=" equals broken tag.  We do not support HTML-style parms */
01454                 /* with no value.                                                */
01455                 for (bval = ename ; isspace((int)*bval) ; bval++);
01456                 if (*bval != '=') { eparm = NULL; break; }
01457 
01458                 while (isspace((int)*++bval));
01459 
01460                 /* If the next character is a quote, spin until we see another one. */
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                 /* Add the parm to our list. */
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 /*      LOCAL_DEBUG_OUT("elem = %p", elem); */
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         /* Find a tag of the form <tag opts>, </tag>, or <tag opts/>. */
01539         while (*ptr) {
01540                 const char* oab = ptr;
01541 
01542                 /* Look for an open oab bracket. */
01543                 for (oab = ptr ; *oab && *oab != '<' ; oab++);
01544 
01545                 /* If there are no oab brackets left, we're done. */
01546                 if (*oab != '<') return oab - str;
01547 
01548                 /* Does this look like a close tag? */
01549                 if (oab[1] == '/') 
01550                 {
01551                         const char* etag;
01552                         /* Find the end of the tag. */
01553                         for (etag = oab + 2 ; xml_tagchar((int)*etag) ; etag++);
01554 
01555                         while (isspace((int)*etag)) ++etag;
01556                         /* If this is an end tag, and the tag matches the tag we're parsing, */
01557                         /* we're done.  If not, continue on blindly. */
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                         /* This tag isn't interesting after all. */
01573                         ptr = oab + 1;
01574                 }
01575 
01576                 /* Does this look like a start tag? */
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                         /* Find the end of the tag. */
01585                         for (etag = btag ; xml_tagchar((int)*etag) ; etag++);
01586 
01587                         /* If we reached the end of the document, continue on. */
01588                         if (!*etag) { ptr = oab + 1; continue; }
01589 
01590                         /* Find the beginning of the parameters, if they exist. */
01591                         for (bparm = etag ; isspace((int)*bparm) ; bparm++);
01592 
01593                         /* From here on, we're looking for a sequence of parms, which have
01594                          * the form [a-z0-9-]+=("[^"]"|'[^']'|[^ \t\n]), followed by either
01595                          * a ">" or a "/>". */
01596                         for (eparm = bparm ; *eparm ; ) {
01597                                 const char* tmp;
01598 
01599                                 /* Spin past any leading whitespace. */
01600                                 for ( ; isspace((int)*eparm) ; eparm++);
01601 
01602                                 /* Are we at the end of the tag? */
01603                                 if (*eparm == '>' || (*eparm == '/' && eparm[1] == '>')) break;
01604 
01605                                 /* Check for a parm.  First is the parm name. */
01606                                 for (tmp = eparm ; xml_tagchar((int)*tmp) ; tmp++);
01607 
01608                                 /* No name equals no parm equals broken tag. */
01609                                 if (!*tmp) { eparm = NULL; break; }
01610 
01611                                 /* No "=" equals broken tag.  We do not support HTML-style parms
01612                                    with no value. */
01613                                 for ( ; isspace((int)*tmp) ; tmp++);
01614                                 if (*tmp != '=') { eparm = NULL; break; }
01615 
01616                                 do { ++tmp; } while (isspace((int)*tmp));
01617 
01618                                 /* If the next character is a quote, spin until we see another one. */
01619                                 if (*tmp == '"' || *tmp == '\'') {
01620                                         char quote = *tmp;
01621                                         for (tmp++ ; *tmp && *tmp != quote ; tmp++);
01622                                 }
01623 
01624                                 /* Now look for a space or the end of the tag. */
01625                                 for ( ; *tmp && !isspace((int)*tmp) && *tmp != '>' && !(*tmp == '/' && tmp[1] == '>') ; tmp++);
01626 
01627                                 /* If we reach the end of the string, there cannot be a '>'. */
01628                                 if (!*tmp) { eparm = NULL; break; }
01629 
01630                                 /* End of the parm.  */
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                         /* If eparm is NULL, the parm string is invalid, and we should
01640                          * abort processing. */
01641                         if (!eparm) { ptr = oab + 1; continue; }
01642 
01643                         /* Save CDATA, if there is any. */
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                         /* We found a tag!  Advance the pointer. */
01651                         for (ptr = eparm ; isspace((int)*ptr) ; ptr++);
01652                         empty = (*ptr == '/');
01653                         ptr += empty + 1;
01654 
01655                         /* Add the tag to our children and parse it. */
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         {       /* skip spaces if we are not in string */
01828                 while( i < len && isspace( (int)tmp[i] )) ++i;
01829                 if( i >= len ) 
01830                         return i;
01831         }
01832         if( xb->state == ASXML_Start ) 
01833         {     /* we are looking for the opening '<' */
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         {     /* we are looking for the beginning of tag name  or closing tag's slash */
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         {     /* we are looking for the tag name */
01875                 int start = i ;
01876                 /* need to store attribute name in form : ' attr_name' */
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         {   /* we are looking for the atteribute or closing '/>' or '>' */
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                 /* need to store attribute name in form : ' attr_name' */
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                                 /* should fall down to case below */
01950                         }else
01951                                 xb->state = ASXML_BadAttrName ;
01952                 }
01953                 return i;                                
01954         }       
01955 
01956         if( xb->state == ASXML_AttrEq )                   /* looking for '=' */
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 )/*looking for attribute value:*/
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 )  /* looking for attribute value : */
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 )  /* looking for attribute value : */
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 /* reverse transformation - put xml tags into a buffer */
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) /* not a bug - negative tags_count means unlimited !*/
02040         {
02041                 if (tags->tag_id == XML_CDATA_ID || !strcmp(tags->tag, cdata_str)) 
02042                 {
02043                         /* TODO : add handling for cdata with quotes, amps and gt, lt */
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                 /* TODO */
02119         }
02120         return state_xml;
02121 }

Generated on Tue Jul 5 14:13:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1