00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 #include "config.h"
00055 #include "mxml.h"
00056 #ifdef WIN32
00057 #  include <io.h>
00058 #else
00059 #  include <unistd.h>
00060 #endif 
00061 
00062 
00063 
00064 
00065 
00066 
00067 #define ENCODE_UTF8     0               
00068 #define ENCODE_UTF16BE  1               
00069 #define ENCODE_UTF16LE  2               
00070 
00071 
00072 
00073 
00074 
00075 
00076 #define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) != '\t')
00077 
00078 
00079 
00080 
00081 
00082 
00083 typedef struct mxml_fdbuf_s             
00084 {
00085   int           fd;                     
00086   unsigned char *current,               
00087                 *end,                   
00088                 buffer[8192];           
00089 } mxml_fdbuf_t;
00090 
00091 
00092 
00093 
00094 
00095 
00096 extern void     (*mxml_error_cb)(const char *);
00097 
00098 
00099 
00100 
00101 
00102 
00103 static mxml_custom_load_cb_t    mxml_custom_load_cb = NULL;
00104 static mxml_custom_save_cb_t    mxml_custom_save_cb = NULL;
00105 
00106 
00107 
00108 
00109 
00110 
00111 static int              mxml_add_char(int ch, char **ptr, char **buffer,
00112                                       int *bufsize);
00113 static int              mxml_fd_getc(void *p, int *encoding);
00114 static int              mxml_fd_putc(int ch, void *p);
00115 static int              mxml_fd_read(mxml_fdbuf_t *buf);
00116 static int              mxml_fd_write(mxml_fdbuf_t *buf);
00117 static int              mxml_file_getc(void *p, int *encoding);
00118 static int              mxml_file_putc(int ch, void *p);
00119 static int              mxml_get_entity(mxml_node_t *parent, void *p,
00120                                         int *encoding,
00121                                         int (*getc_cb)(void *, int *));
00122 static mxml_node_t      *mxml_load_data(mxml_node_t *top, void *p,
00123                                         mxml_type_t (*cb)(mxml_node_t *),
00124                                         int (*getc_cb)(void *, int *));
00125 static int              mxml_parse_element(mxml_node_t *node, void *p,
00126                                            int *encoding,
00127                                            int (*getc_cb)(void *, int *));
00128 static int              mxml_string_getc(void *p, int *encoding);
00129 static int              mxml_string_putc(int ch, void *p);
00130 static int              mxml_write_name(const char *s, void *p,
00131                                         int (*putc_cb)(int, void *));
00132 static int              mxml_write_node(mxml_node_t *node, void *p,
00133                                         const char *(*cb)(mxml_node_t *, int),
00134                                         int col,
00135                                         int (*putc_cb)(int, void *));
00136 static int              mxml_write_string(const char *s, void *p,
00137                                           int (*putc_cb)(int, void *));
00138 static int              mxml_write_ws(mxml_node_t *node, void *p, 
00139                                       const char *(*cb)(mxml_node_t *, int), int ws,
00140                                       int col, int (*putc_cb)(int, void *));
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 mxml_node_t *                           
00159 mxmlLoadFd(mxml_node_t *top,            
00160            int         fd,              
00161            mxml_type_t (*cb)(mxml_node_t *node))
00162                                         
00163 {
00164   mxml_fdbuf_t  buf;                    
00165 
00166 
00167  
00168 
00169 
00170 
00171   buf.fd      = fd;
00172   buf.current = buf.buffer;
00173   buf.end     = buf.buffer;
00174 
00175  
00176 
00177 
00178 
00179   return (mxml_load_data(top, &buf, cb, mxml_fd_getc));
00180 }
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 mxml_node_t *                           
00199 mxmlLoadFile(mxml_node_t *top,          
00200              FILE        *fp,           
00201              mxml_type_t (*cb)(mxml_node_t *node))
00202                                         
00203 {
00204  
00205 
00206 
00207 
00208   return (mxml_load_data(top, fp, cb, mxml_file_getc));
00209 }
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 mxml_node_t *                           
00228 mxmlLoadString(mxml_node_t *top,        
00229                const char  *s,          
00230                mxml_type_t (*cb)(mxml_node_t *node))
00231                                         
00232 {
00233  
00234 
00235 
00236 
00237   return (mxml_load_data(top, &s, cb, mxml_string_getc));
00238 }
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 char *                                  
00258 mxmlSaveAllocString(mxml_node_t *node,  
00259                     const char  *(*cb)(mxml_node_t *node, int ws))
00260                                         
00261 {
00262   int   bytes;                          
00263   char  buffer[8192];                   
00264   char  *s;                             
00265 
00266 
00267  
00268 
00269 
00270 
00271   bytes = mxmlSaveString(node, buffer, sizeof(buffer), cb);
00272 
00273   if (bytes <= 0)
00274     return (NULL);
00275 
00276   if (bytes < (int)(sizeof(buffer) - 1))
00277   {
00278    
00279 
00280 
00281 
00282 
00283     return (strdup(buffer));
00284   }
00285 
00286  
00287 
00288 
00289 
00290 
00291   if ((s = malloc(bytes + 1)) == NULL)
00292     return (NULL);
00293 
00294   mxmlSaveString(node, s, bytes + 1, cb);
00295 
00296  
00297 
00298 
00299 
00300   return (s);
00301 }
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 int                                     
00315 mxmlSaveFd(mxml_node_t *node,           
00316            int         fd,              
00317            const char  *(*cb)(mxml_node_t *node, int ws))
00318                                         
00319 {
00320   int           col;                    
00321   mxml_fdbuf_t  buf;                    
00322 
00323 
00324  
00325 
00326 
00327 
00328   buf.fd      = fd;
00329   buf.current = buf.buffer;
00330   buf.end     = buf.buffer + sizeof(buf.buffer) - 4;
00331 
00332  
00333 
00334 
00335 
00336   if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc)) < 0)
00337     return (-1);
00338 
00339   if (col > 0)
00340     if (mxml_fd_putc('\n', &buf) < 0)
00341       return (-1);
00342 
00343  
00344 
00345 
00346 
00347   return (mxml_fd_write(&buf));
00348 }
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 int                                     
00362 mxmlSaveFile(mxml_node_t *node,         
00363              FILE        *fp,           
00364              const char  *(*cb)(mxml_node_t *node, int ws))
00365                                         
00366 {
00367   int   col;                            
00368 
00369 
00370  
00371 
00372 
00373 
00374   if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc)) < 0)
00375     return (-1);
00376 
00377   if (col > 0)
00378     if (putc('\n', fp) < 0)
00379       return (-1);
00380 
00381  
00382 
00383 
00384 
00385   return (0);
00386 }
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 int                                     
00404 mxmlSaveString(mxml_node_t *node,       
00405                char        *buffer,     
00406                int         bufsize,     
00407                const char  *(*cb)(mxml_node_t *node, int ws))
00408                                         
00409 {
00410   int   col;                            
00411   char  *ptr[2];                        
00412 
00413 
00414  
00415 
00416 
00417 
00418   ptr[0] = buffer;
00419   ptr[1] = buffer + bufsize;
00420 
00421   if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc)) < 0)
00422     return (-1);
00423 
00424   if (col > 0)
00425     mxml_string_putc('\n', ptr);
00426 
00427  
00428 
00429 
00430 
00431   if (ptr[0] >= ptr[1])
00432     buffer[bufsize - 1] = '\0';
00433   else
00434     ptr[0][0] = '\0';
00435 
00436  
00437 
00438 
00439 
00440   return (ptr[0] - buffer);
00441 }
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 void
00456 mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
00457                                         
00458                       mxml_custom_save_cb_t save)
00459                                         
00460 {
00461   mxml_custom_load_cb = load;
00462   mxml_custom_save_cb = save;
00463 }
00464 
00465 
00466 
00467 
00468 
00469 
00470 void
00471 mxmlSetErrorCallback(void (*cb)(const char *))
00472                                         
00473 {
00474   mxml_error_cb = cb;
00475 }
00476 
00477 
00478 
00479 
00480 
00481 
00482 static int                              
00483 mxml_add_char(int  ch,                  
00484               char **bufptr,            
00485               char **buffer,            
00486               int  *bufsize)            
00487 {
00488   char  *newbuffer;                     
00489 
00490 
00491   if (*bufptr >= (*buffer + *bufsize - 4))
00492   {
00493    
00494 
00495 
00496 
00497     if (*bufsize < 1024)
00498       (*bufsize) *= 2;
00499     else
00500       (*bufsize) += 1024;
00501 
00502     if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
00503     {
00504       free(*buffer);
00505 
00506       mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
00507 
00508       return (-1);
00509     }
00510 
00511     *bufptr = newbuffer + (*bufptr - *buffer);
00512     *buffer = newbuffer;
00513   }
00514 
00515   if (ch < 0x80)
00516   {
00517    
00518 
00519 
00520 
00521     *(*bufptr)++ = ch;
00522   }
00523   else if (ch < 0x800)
00524   {
00525    
00526 
00527 
00528 
00529     *(*bufptr)++ = 0xc0 | (ch >> 6);
00530     *(*bufptr)++ = 0x80 | (ch & 0x3f);
00531   }
00532   else if (ch < 0x10000)
00533   {
00534    
00535 
00536 
00537 
00538     *(*bufptr)++ = 0xe0 | (ch >> 12);
00539     *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
00540     *(*bufptr)++ = 0x80 | (ch & 0x3f);
00541   }
00542   else
00543   {
00544    
00545 
00546 
00547 
00548     *(*bufptr)++ = 0xf0 | (ch >> 18);
00549     *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
00550     *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
00551     *(*bufptr)++ = 0x80 | (ch & 0x3f);
00552   }
00553 
00554   return (0);
00555 }
00556 
00557 
00558 
00559 
00560 
00561 
00562 static int                              
00563 mxml_fd_getc(void *p,                   
00564              int  *encoding)            
00565 {
00566   mxml_fdbuf_t  *buf;                   
00567   int           ch,                     
00568                 temp;                   
00569 
00570 
00571  
00572 
00573 
00574 
00575   buf = (mxml_fdbuf_t *)p;
00576 
00577   if (buf->current >= buf->end)
00578     if (mxml_fd_read(buf) < 0)
00579       return (EOF);
00580 
00581   ch = *(buf->current)++;
00582 
00583   switch (*encoding)
00584   {
00585     case ENCODE_UTF8 :
00586        
00587 
00588 
00589 
00590         if (!(ch & 0x80))
00591         {
00592 #if DEBUG > 1
00593           printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
00594 #endif 
00595 
00596           if (mxml_bad_char(ch))
00597           {
00598             mxml_error("Bad control character 0x%02x not allowed by XML standard!",
00599                        ch);
00600             return (EOF);
00601           }
00602 
00603           return (ch);
00604         }
00605         else if (ch == 0xfe)
00606         {
00607          
00608 
00609 
00610 
00611           if (buf->current >= buf->end)
00612             if (mxml_fd_read(buf) < 0)
00613               return (EOF);
00614 
00615           ch = *(buf->current)++;
00616           
00617           if (ch != 0xff)
00618             return (EOF);
00619 
00620           *encoding = ENCODE_UTF16BE;
00621 
00622           return (mxml_fd_getc(p, encoding));
00623         }
00624         else if (ch == 0xff)
00625         {
00626          
00627 
00628 
00629 
00630           if (buf->current >= buf->end)
00631             if (mxml_fd_read(buf) < 0)
00632               return (EOF);
00633 
00634           ch = *(buf->current)++;
00635           
00636           if (ch != 0xfe)
00637             return (EOF);
00638 
00639           *encoding = ENCODE_UTF16LE;
00640 
00641           return (mxml_fd_getc(p, encoding));
00642         }
00643         else if ((ch & 0xe0) == 0xc0)
00644         {
00645          
00646 
00647 
00648 
00649           if (buf->current >= buf->end)
00650             if (mxml_fd_read(buf) < 0)
00651               return (EOF);
00652 
00653           temp = *(buf->current)++;
00654 
00655           if ((temp & 0xc0) != 0x80)
00656             return (EOF);
00657 
00658           ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
00659 
00660           if (ch < 0x80)
00661             return (EOF);
00662         }
00663         else if ((ch & 0xf0) == 0xe0)
00664         {
00665          
00666 
00667 
00668 
00669           if (buf->current >= buf->end)
00670             if (mxml_fd_read(buf) < 0)
00671               return (EOF);
00672 
00673           temp = *(buf->current)++;
00674 
00675           if ((temp & 0xc0) != 0x80)
00676             return (EOF);
00677 
00678           ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
00679 
00680           if (buf->current >= buf->end)
00681             if (mxml_fd_read(buf) < 0)
00682               return (EOF);
00683 
00684           temp = *(buf->current)++;
00685 
00686           if ((temp & 0xc0) != 0x80)
00687             return (EOF);
00688 
00689           ch = (ch << 6) | (temp & 0x3f);
00690 
00691           if (ch < 0x800)
00692             return (EOF);
00693         }
00694         else if ((ch & 0xf8) == 0xf0)
00695         {
00696          
00697 
00698 
00699 
00700           if (buf->current >= buf->end)
00701             if (mxml_fd_read(buf) < 0)
00702               return (EOF);
00703 
00704           temp = *(buf->current)++;
00705 
00706           if ((temp & 0xc0) != 0x80)
00707             return (EOF);
00708 
00709           ch = ((ch & 0x07) << 6) | (temp & 0x3f);
00710 
00711           if (buf->current >= buf->end)
00712             if (mxml_fd_read(buf) < 0)
00713               return (EOF);
00714 
00715           temp = *(buf->current)++;
00716 
00717           if ((temp & 0xc0) != 0x80)
00718             return (EOF);
00719 
00720           ch = (ch << 6) | (temp & 0x3f);
00721 
00722           if (buf->current >= buf->end)
00723             if (mxml_fd_read(buf) < 0)
00724               return (EOF);
00725 
00726           temp = *(buf->current)++;
00727 
00728           if ((temp & 0xc0) != 0x80)
00729             return (EOF);
00730 
00731           ch = (ch << 6) | (temp & 0x3f);
00732 
00733           if (ch < 0x10000)
00734             return (EOF);
00735         }
00736         else
00737           return (EOF);
00738         break;
00739 
00740     case ENCODE_UTF16BE :
00741        
00742 
00743 
00744 
00745         if (buf->current >= buf->end)
00746           if (mxml_fd_read(buf) < 0)
00747             return (EOF);
00748 
00749         temp = *(buf->current)++;
00750 
00751         ch = (ch << 8) | temp;
00752 
00753         if (mxml_bad_char(ch))
00754         {
00755           mxml_error("Bad control character 0x%02x not allowed by XML standard!",
00756                      ch);
00757           return (EOF);
00758         }
00759         else if (ch >= 0xd800 && ch <= 0xdbff)
00760         {
00761          
00762 
00763 
00764 
00765           int lch;
00766 
00767           if (buf->current >= buf->end)
00768             if (mxml_fd_read(buf) < 0)
00769               return (EOF);
00770 
00771           lch = *(buf->current)++;
00772 
00773           if (buf->current >= buf->end)
00774             if (mxml_fd_read(buf) < 0)
00775               return (EOF);
00776 
00777           temp = *(buf->current)++;
00778 
00779           lch = (lch << 8) | temp;
00780 
00781           if (lch < 0xdc00 || lch >= 0xdfff)
00782             return (EOF);
00783 
00784           ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
00785         }
00786         break;
00787 
00788     case ENCODE_UTF16LE :
00789        
00790 
00791 
00792 
00793         if (buf->current >= buf->end)
00794           if (mxml_fd_read(buf) < 0)
00795             return (EOF);
00796 
00797         temp = *(buf->current)++;
00798 
00799         ch |= (temp << 8);
00800 
00801         if (mxml_bad_char(ch))
00802         {
00803           mxml_error("Bad control character 0x%02x not allowed by XML standard!",
00804                      ch);
00805           return (EOF);
00806         }
00807         else if (ch >= 0xd800 && ch <= 0xdbff)
00808         {
00809          
00810 
00811 
00812 
00813           int lch;
00814 
00815           if (buf->current >= buf->end)
00816             if (mxml_fd_read(buf) < 0)
00817               return (EOF);
00818 
00819           lch = *(buf->current)++;
00820 
00821           if (buf->current >= buf->end)
00822             if (mxml_fd_read(buf) < 0)
00823               return (EOF);
00824 
00825           temp = *(buf->current)++;
00826 
00827           lch |= (temp << 8);
00828 
00829           if (lch < 0xdc00 || lch >= 0xdfff)
00830             return (EOF);
00831 
00832           ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
00833         }
00834         break;
00835   }
00836 
00837 #if DEBUG > 1
00838   printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
00839 #endif 
00840 
00841   return (ch);
00842 }
00843 
00844 
00845 
00846 
00847 
00848 
00849 static int                              
00850 mxml_fd_putc(int  ch,                   
00851              void *p)                   
00852 {
00853   mxml_fdbuf_t  *buf;                   
00854 
00855 
00856  
00857 
00858 
00859 
00860 
00861   buf = (mxml_fdbuf_t *)p;
00862 
00863   if (buf->current >= buf->end)
00864     if (mxml_fd_write(buf) < 0)
00865       return (-1);
00866 
00867   if (ch < 0x80)
00868   {
00869    
00870 
00871 
00872 
00873     *(buf->current)++ = ch;
00874   }
00875   else if (ch < 0x800)
00876   {
00877    
00878 
00879 
00880 
00881     *(buf->current)++ = 0xc0 | (ch >> 6);
00882     *(buf->current)++ = 0x80 | (ch & 0x3f);
00883   }
00884   else if (ch < 0x10000)
00885   {
00886    
00887 
00888 
00889 
00890     *(buf->current)++ = 0xe0 | (ch >> 12);
00891     *(buf->current)++ = 0x80 | ((ch >> 6) & 0x3f);
00892     *(buf->current)++ = 0x80 | (ch & 0x3f);
00893   }
00894   else
00895   {
00896    
00897 
00898 
00899 
00900     *(buf->current)++ = 0xf0 | (ch >> 18);
00901     *(buf->current)++ = 0x80 | ((ch >> 12) & 0x3f);
00902     *(buf->current)++ = 0x80 | ((ch >> 6) & 0x3f);
00903     *(buf->current)++ = 0x80 | (ch & 0x3f);
00904   }
00905 
00906  
00907 
00908 
00909 
00910   return (0);
00911 }
00912 
00913 
00914 
00915 
00916 
00917 
00918 static int                              
00919 mxml_fd_read(mxml_fdbuf_t *buf)         
00920 {
00921   int   bytes;                          
00922 
00923 
00924  
00925 
00926 
00927 
00928   if (!buf)
00929     return (-1);
00930 
00931  
00932 
00933 
00934 
00935   while ((bytes = read(buf->fd, buf->buffer, sizeof(buf->buffer))) < 0)
00936     if (errno != EAGAIN && errno != EINTR)
00937       return (-1);
00938 
00939   if (bytes == 0)
00940     return (-1);
00941 
00942  
00943 
00944 
00945 
00946   buf->current = buf->buffer;
00947   buf->end     = buf->buffer + bytes;
00948 
00949   return (0);
00950 }
00951 
00952 
00953 
00954 
00955 
00956 
00957 static int                              
00958 mxml_fd_write(mxml_fdbuf_t *buf)        
00959 {
00960   int           bytes;                  
00961   unsigned char *ptr;                   
00962 
00963 
00964  
00965 
00966 
00967 
00968   if (!buf)
00969     return (-1);
00970 
00971  
00972 
00973 
00974 
00975   if (buf->current == buf->buffer)
00976     return (0);
00977 
00978  
00979 
00980 
00981 
00982   for (ptr = buf->buffer; ptr < buf->current; ptr += bytes)
00983     if ((bytes = write(buf->fd, ptr, buf->current - ptr)) < 0)
00984       return (-1);
00985 
00986  
00987 
00988 
00989 
00990   buf->current = buf->buffer;
00991 
00992   return (0);
00993 }
00994 
00995 
00996 
00997 
00998 
00999 
01000 static int                              
01001 mxml_file_getc(void *p,                 
01002                int  *encoding)          
01003 {
01004   int   ch,                             
01005         temp;                           
01006   FILE  *fp;                            
01007 
01008 
01009  
01010 
01011 
01012 
01013   fp = (FILE *)p;
01014   ch = getc(fp);
01015 
01016   if (ch == EOF)
01017     return (EOF);
01018 
01019   switch (*encoding)
01020   {
01021     case ENCODE_UTF8 :
01022        
01023 
01024 
01025 
01026         if (!(ch & 0x80))
01027         {
01028           if (mxml_bad_char(ch))
01029           {
01030             mxml_error("Bad control character 0x%02x not allowed by XML standard!",
01031                        ch);
01032             return (EOF);
01033           }
01034 
01035 #if DEBUG > 1
01036           printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
01037 #endif 
01038 
01039           return (ch);
01040         }
01041         else if (ch == 0xfe)
01042         {
01043          
01044 
01045 
01046 
01047           ch = getc(fp);
01048           if (ch != 0xff)
01049             return (EOF);
01050 
01051           *encoding = ENCODE_UTF16BE;
01052 
01053           return (mxml_file_getc(p, encoding));
01054         }
01055         else if (ch == 0xff)
01056         {
01057          
01058 
01059 
01060 
01061           ch = getc(fp);
01062           if (ch != 0xfe)
01063             return (EOF);
01064 
01065           *encoding = ENCODE_UTF16LE;
01066 
01067           return (mxml_file_getc(p, encoding));
01068         }
01069         else if ((ch & 0xe0) == 0xc0)
01070         {
01071          
01072 
01073 
01074 
01075           if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01076             return (EOF);
01077 
01078           ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
01079 
01080           if (ch < 0x80)
01081             return (EOF);
01082         }
01083         else if ((ch & 0xf0) == 0xe0)
01084         {
01085          
01086 
01087 
01088 
01089           if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01090             return (EOF);
01091 
01092           ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
01093 
01094           if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01095             return (EOF);
01096 
01097           ch = (ch << 6) | (temp & 0x3f);
01098 
01099           if (ch < 0x800)
01100             return (EOF);
01101         }
01102         else if ((ch & 0xf8) == 0xf0)
01103         {
01104          
01105 
01106 
01107 
01108           if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01109             return (EOF);
01110 
01111           ch = ((ch & 0x07) << 6) | (temp & 0x3f);
01112 
01113           if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01114             return (EOF);
01115 
01116           ch = (ch << 6) | (temp & 0x3f);
01117 
01118           if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
01119             return (EOF);
01120 
01121           ch = (ch << 6) | (temp & 0x3f);
01122 
01123           if (ch < 0x10000)
01124             return (EOF);
01125         }
01126         else
01127           return (EOF);
01128         break;
01129 
01130     case ENCODE_UTF16BE :
01131        
01132 
01133 
01134 
01135         ch = (ch << 8) | getc(fp);
01136 
01137         if (mxml_bad_char(ch))
01138         {
01139           mxml_error("Bad control character 0x%02x not allowed by XML standard!",
01140                      ch);
01141           return (EOF);
01142         }
01143         else if (ch >= 0xd800 && ch <= 0xdbff)
01144         {
01145          
01146 
01147 
01148 
01149           int lch = (getc(fp) << 8) | getc(fp);
01150 
01151           if (lch < 0xdc00 || lch >= 0xdfff)
01152             return (EOF);
01153 
01154           ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
01155         }
01156         break;
01157 
01158     case ENCODE_UTF16LE :
01159        
01160 
01161 
01162 
01163         ch |= (getc(fp) << 8);
01164 
01165         if (mxml_bad_char(ch))
01166         {
01167           mxml_error("Bad control character 0x%02x not allowed by XML standard!",
01168                      ch);
01169           return (EOF);
01170         }
01171         else if (ch >= 0xd800 && ch <= 0xdbff)
01172         {
01173          
01174 
01175 
01176 
01177           int lch = getc(fp) | (getc(fp) << 8);
01178 
01179           if (lch < 0xdc00 || lch >= 0xdfff)
01180             return (EOF);
01181 
01182           ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
01183         }
01184         break;
01185   }
01186 
01187 #if DEBUG > 1
01188   printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
01189 #endif 
01190 
01191   return (ch);
01192 }
01193 
01194 
01195 
01196 
01197 
01198 
01199 static int                              
01200 mxml_file_putc(int  ch,                 
01201                void *p)                 
01202 {
01203   char  buffer[4],                      
01204         *bufptr;                        
01205   int   buflen;                         
01206 
01207 
01208   if (ch < 0x80)
01209     return (putc(ch, (FILE *)p) == EOF ? -1 : 0);
01210 
01211   bufptr = buffer;
01212 
01213   if (ch < 0x800)
01214   {
01215    
01216 
01217 
01218 
01219     *bufptr++ = 0xc0 | (ch >> 6);
01220     *bufptr++ = 0x80 | (ch & 0x3f);
01221   }
01222   else if (ch < 0x10000)
01223   {
01224    
01225 
01226 
01227 
01228     *bufptr++ = 0xe0 | (ch >> 12);
01229     *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);
01230     *bufptr++ = 0x80 | (ch & 0x3f);
01231   }
01232   else
01233   {
01234    
01235 
01236 
01237 
01238     *bufptr++ = 0xf0 | (ch >> 18);
01239     *bufptr++ = 0x80 | ((ch >> 12) & 0x3f);
01240     *bufptr++ = 0x80 | ((ch >> 6) & 0x3f);
01241     *bufptr++ = 0x80 | (ch & 0x3f);
01242   }
01243 
01244   buflen = bufptr - buffer;
01245 
01246   return (fwrite(buffer, 1, buflen, (FILE *)p) < buflen ? -1 : 0);
01247 }
01248 
01249 
01250 
01251 
01252 
01253 
01254 static int                              
01255 mxml_get_entity(mxml_node_t *parent,    
01256                 void        *p,         
01257                 int         *encoding,  
01258                 int         (*getc_cb)(void *, int *))
01259                                         
01260 {
01261   int   ch;                             
01262   char  entity[64],                     
01263         *entptr;                        
01264 
01265 
01266   entptr = entity;
01267 
01268   while ((ch = (*getc_cb)(p, encoding)) != EOF)
01269     if (ch > 126 || (!isalnum(ch) && ch != '#'))
01270       break;
01271     else if (entptr < (entity + sizeof(entity) - 1))
01272       *entptr++ = ch;
01273     else
01274     {
01275       mxml_error("Entity name too long under parent <%s>!",
01276                  parent ? parent->value.element.name : "null");
01277       break;
01278     }
01279 
01280   *entptr = '\0';
01281 
01282   if (ch != ';')
01283   {
01284     mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
01285                entity, parent ? parent->value.element.name : "null");
01286     return (EOF);
01287   }
01288 
01289   if (entity[0] == '#')
01290   {
01291     if (entity[1] == 'x')
01292       ch = strtol(entity + 2, NULL, 16);
01293     else
01294       ch = strtol(entity + 1, NULL, 10);
01295   }
01296   else if ((ch = mxmlEntityGetValue(entity)) < 0)
01297     mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
01298                entity, parent ? parent->value.element.name : "null");
01299 
01300   if (mxml_bad_char(ch))
01301   {
01302     mxml_error("Bad control character 0x%02x under parent <%s> not allowed by XML standard!",
01303                ch, parent ? parent->value.element.name : "null");
01304     return (EOF);
01305   }
01306 
01307   return (ch);
01308 }
01309 
01310 
01311 
01312 
01313 
01314 
01315 static mxml_node_t *                    
01316 mxml_load_data(mxml_node_t *top,        
01317                void        *p,          
01318                mxml_type_t (*cb)(mxml_node_t *),
01319                                         
01320                int         (*getc_cb)(void *, int *))
01321                                         
01322 {
01323   mxml_node_t   *node,                  
01324                 *first,                 
01325                 *parent;                
01326   int           ch,                     
01327                 whitespace;             
01328   char          *buffer,                
01329                 *bufptr;                
01330   int           bufsize;                
01331   mxml_type_t   type;                   
01332   int           encoding;               
01333   static const char * const types[] =   
01334                 {
01335                   "MXML_ELEMENT",       
01336                   "MXML_INTEGER",       
01337                   "MXML_OPAQUE",        
01338                   "MXML_REAL",          
01339                   "MXML_TEXT",          
01340                   "MXML_CUSTOM"         
01341                 };
01342 
01343 
01344  
01345 
01346 
01347 
01348   if ((buffer = malloc(64)) == NULL)
01349   {
01350     mxml_error("Unable to allocate string buffer!");
01351     return (NULL);
01352   }
01353 
01354   bufsize    = 64;
01355   bufptr     = buffer;
01356   parent     = top;
01357   first      = NULL;
01358   whitespace = 0;
01359   encoding   = ENCODE_UTF8;
01360 
01361   if (cb && parent)
01362     type = (*cb)(parent);
01363   else
01364     type = MXML_TEXT;
01365 
01366   while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01367   {
01368     if ((ch == '<' ||
01369          (isspace(ch) && type != MXML_OPAQUE && type != MXML_CUSTOM)) &&
01370         bufptr > buffer)
01371     {
01372      
01373 
01374 
01375 
01376       *bufptr = '\0';
01377 
01378       switch (type)
01379       {
01380         case MXML_INTEGER :
01381             node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
01382             break;
01383 
01384         case MXML_OPAQUE :
01385             node = mxmlNewOpaque(parent, buffer);
01386             break;
01387 
01388         case MXML_REAL :
01389             node = mxmlNewReal(parent, strtod(buffer, &bufptr));
01390             break;
01391 
01392         case MXML_TEXT :
01393             node = mxmlNewText(parent, whitespace, buffer);
01394             break;
01395 
01396         case MXML_CUSTOM :
01397             if (mxml_custom_load_cb)
01398             {
01399              
01400 
01401 
01402 
01403               node = mxmlNewCustom(parent, NULL, NULL);
01404 
01405               if ((*mxml_custom_load_cb)(node, buffer))
01406               {
01407                 mxml_error("Bad custom value '%s' in parent <%s>!",
01408                            buffer, parent ? parent->value.element.name : "null");
01409                 mxmlDelete(node);
01410                 node = NULL;
01411               }
01412               break;
01413             }
01414 
01415         default : 
01416             node = NULL;
01417             break;
01418       }   
01419 
01420       if (*bufptr)
01421       {
01422        
01423 
01424 
01425 
01426         mxml_error("Bad %s value '%s' in parent <%s>!",
01427                    type == MXML_INTEGER ? "integer" : "real", buffer,
01428                    parent ? parent->value.element.name : "null");
01429         break;
01430       }
01431 
01432       bufptr     = buffer;
01433       whitespace = isspace(ch) && type == MXML_TEXT;
01434 
01435       if (!node)
01436       {
01437        
01438 
01439 
01440 
01441         mxml_error("Unable to add value node of type %s to parent <%s>!",
01442                    types[type], parent ? parent->value.element.name : "null");
01443         goto error;
01444       }
01445 
01446       if (!first)
01447         first = node;
01448     }
01449     else if (isspace(ch) && type == MXML_TEXT)
01450       whitespace = 1;
01451 
01452    
01453 
01454 
01455 
01456 
01457     if (ch == '<' && whitespace && type == MXML_TEXT)
01458     {
01459       mxmlNewText(parent, whitespace, "");
01460       whitespace = 0;
01461     }
01462 
01463     if (ch == '<')
01464     {
01465      
01466 
01467 
01468 
01469       bufptr = buffer;
01470 
01471       while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01472         if (isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
01473           break;
01474         else if (ch == '&')
01475         {
01476           if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
01477             goto error;
01478 
01479           if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01480             goto error;
01481         }
01482         else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01483           goto error;
01484         else if (((bufptr - buffer) == 1 && buffer[0] == '?') ||
01485                  ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) ||
01486                  ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8)))
01487           break;
01488 
01489       *bufptr = '\0';
01490 
01491       if (!strcmp(buffer, "!--"))
01492       {
01493        
01494 
01495 
01496 
01497         while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01498         {
01499           if (ch == '>' && bufptr > (buffer + 4) &&
01500               bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-')
01501             break;
01502           else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01503             goto error;
01504         }
01505 
01506        
01507 
01508 
01509 
01510         if (ch != '>')
01511         {
01512          
01513 
01514 
01515 
01516           mxml_error("Early EOF in comment node!");
01517           goto error;
01518         }
01519 
01520 
01521        
01522 
01523 
01524 
01525         *bufptr = '\0';
01526 
01527         if (!mxmlNewElement(parent, buffer))
01528         {
01529          
01530 
01531 
01532 
01533           mxml_error("Unable to add comment node to parent <%s>!",
01534                      parent ? parent->value.element.name : "null");
01535           break;
01536         }
01537       }
01538       else if (!strcmp(buffer, "![CDATA["))
01539       {
01540        
01541 
01542 
01543 
01544         while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01545         {
01546           if (ch == '>' && !strncmp(bufptr - 2, "]]", 2))
01547             break;
01548           else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01549             goto error;
01550         }
01551 
01552        
01553 
01554 
01555 
01556         if (ch != '>')
01557         {
01558          
01559 
01560 
01561 
01562           mxml_error("Early EOF in CDATA node!");
01563           goto error;
01564         }
01565 
01566 
01567        
01568 
01569 
01570 
01571         *bufptr = '\0';
01572 
01573         if (!mxmlNewElement(parent, buffer))
01574         {
01575          
01576 
01577 
01578 
01579           mxml_error("Unable to add CDATA node to parent <%s>!",
01580                      parent ? parent->value.element.name : "null");
01581           goto error;
01582         }
01583       }
01584       else if (buffer[0] == '?')
01585       {
01586        
01587 
01588 
01589 
01590         while ((ch = (*getc_cb)(p, &encoding)) != EOF)
01591         {
01592           if (ch == '>' && bufptr > buffer && bufptr[-1] == '?')
01593             break;
01594           else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01595             goto error;
01596         }
01597 
01598        
01599 
01600 
01601 
01602         if (ch != '>')
01603         {
01604          
01605 
01606 
01607 
01608           mxml_error("Early EOF in processing instruction node!");
01609           goto error;
01610         }
01611 
01612 
01613        
01614 
01615 
01616 
01617         *bufptr = '\0';
01618 
01619         if (!(parent = mxmlNewElement(parent, buffer)))
01620         {
01621          
01622 
01623 
01624 
01625           mxml_error("Unable to add processing instruction node to parent <%s>!",
01626                      parent ? parent->value.element.name : "null");
01627           goto error;
01628         }
01629 
01630         if (cb)
01631           type = (*cb)(parent);
01632       }
01633       else if (buffer[0] == '!')
01634       {
01635        
01636 
01637 
01638 
01639         do
01640         {
01641           if (ch == '>')
01642             break;
01643           else
01644           {
01645             if (ch == '&')
01646               if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
01647                 goto error;
01648 
01649             if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01650               goto error;
01651           }
01652         }
01653         while ((ch = (*getc_cb)(p, &encoding)) != EOF);
01654 
01655        
01656 
01657 
01658 
01659         if (ch != '>')
01660         {
01661          
01662 
01663 
01664 
01665           mxml_error("Early EOF in declaration node!");
01666           goto error;
01667         }
01668 
01669        
01670 
01671 
01672 
01673         *bufptr = '\0';
01674 
01675         node = mxmlNewElement(parent, buffer);
01676         if (!node)
01677         {
01678          
01679 
01680 
01681 
01682           mxml_error("Unable to add declaration node to parent <%s>!",
01683                      parent ? parent->value.element.name : "null");
01684           goto error;
01685         }
01686 
01687        
01688 
01689 
01690 
01691         parent = node;
01692 
01693         if (cb)
01694           type = (*cb)(parent);
01695       }
01696       else if (buffer[0] == '/')
01697       {
01698        
01699 
01700 
01701 
01702         if (!parent || strcmp(buffer + 1, parent->value.element.name))
01703         {
01704          
01705 
01706 
01707 
01708           mxml_error("Mismatched close tag <%s> under parent <%s>!",
01709                      buffer, parent->value.element.name);
01710           goto error;
01711         }
01712 
01713        
01714 
01715 
01716 
01717         while (ch != '>' && ch != EOF)
01718           ch = (*getc_cb)(p, &encoding);
01719 
01720        
01721 
01722 
01723 
01724         parent = parent->parent;
01725 
01726         if (cb && parent)
01727           type = (*cb)(parent);
01728       }
01729       else
01730       {
01731        
01732 
01733 
01734 
01735         node = mxmlNewElement(parent, buffer);
01736 
01737         if (!node)
01738         {
01739          
01740 
01741 
01742 
01743           mxml_error("Unable to add element node to parent <%s>!",
01744                      parent ? parent->value.element.name : "null");
01745           goto error;
01746         }
01747 
01748         if (isspace(ch))
01749           ch = mxml_parse_element(node, p, &encoding, getc_cb);
01750         else if (ch == '/')
01751         {
01752           if ((ch = (*getc_cb)(p, &encoding)) != '>')
01753           {
01754             mxml_error("Expected > but got '%c' instead for element <%s/>!",
01755                        ch, buffer);
01756             goto error;
01757           }
01758 
01759           ch = '/';
01760         }
01761 
01762         if (ch == EOF)
01763           break;
01764 
01765         if (ch != '/')
01766         {
01767          
01768 
01769 
01770 
01771           parent = node;
01772 
01773           if (cb && parent)
01774             type = (*cb)(parent);
01775         }
01776       }
01777 
01778       bufptr  = buffer;
01779     }
01780     else if (ch == '&')
01781     {
01782      
01783 
01784 
01785 
01786       if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
01787         goto error;
01788 
01789       if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01790         goto error;
01791     }
01792     else if (type == MXML_OPAQUE || type == MXML_CUSTOM || !isspace(ch))
01793     {
01794      
01795 
01796 
01797 
01798       if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
01799         goto error;
01800     }
01801   }
01802 
01803  
01804 
01805 
01806 
01807   free(buffer);
01808 
01809  
01810 
01811 
01812 
01813   if (parent)
01814   {
01815     while (parent->parent != top && parent->parent)
01816       parent = parent->parent;
01817   }
01818 
01819   return (parent);
01820 
01821  
01822 
01823 
01824 
01825 error:
01826 
01827   mxmlDelete(first);
01828 
01829   free(buffer);
01830 
01831   return (NULL);
01832 }
01833 
01834 
01835 
01836 
01837 
01838 
01839 static int                              
01840 mxml_parse_element(mxml_node_t *node,   
01841                    void        *p,      
01842                    int         *encoding,
01843                                         
01844                    int         (*getc_cb)(void *, int *))
01845                                         
01846 {
01847   int   ch,                             
01848         quote;                          
01849   char  *name,                          
01850         *value,                         
01851         *ptr;                           
01852   int   namesize,                       
01853         valsize;                        
01854 
01855 
01856 
01857 
01858  
01859 
01860 
01861 
01862   if ((name = malloc(64)) == NULL)
01863   {
01864     mxml_error("Unable to allocate memory for name!");
01865     return (EOF);
01866   }
01867 
01868   namesize = 64;
01869 
01870   if ((value = malloc(64)) == NULL)
01871   {
01872     free(name);
01873     mxml_error("Unable to allocate memory for value!");
01874     return (EOF);
01875   }
01876 
01877   valsize = 64;
01878 
01879  
01880 
01881 
01882 
01883   while ((ch = (*getc_cb)(p, encoding)) != EOF)
01884   {
01885 #if DEBUG > 1
01886     fprintf(stderr, "parse_element: ch='%c'\n", ch);
01887 #endif 
01888 
01889    
01890 
01891 
01892 
01893     if (isspace(ch))
01894       continue;
01895 
01896    
01897 
01898 
01899 
01900     if (ch == '/' || ch == '?')
01901     {
01902      
01903 
01904 
01905 
01906       quote = (*getc_cb)(p, encoding);
01907 
01908       if (quote != '>')
01909       {
01910         mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
01911                    ch, node->value.element.name, quote);
01912         ch = EOF;
01913       }
01914 
01915       break;
01916     }
01917     else if (ch == '>')
01918       break;
01919 
01920    
01921 
01922 
01923 
01924     name[0] = ch;
01925     ptr     = name + 1;
01926 
01927     if (ch == '\"' || ch == '\'')
01928     {
01929      
01930 
01931 
01932 
01933       quote = ch;
01934 
01935       while ((ch = (*getc_cb)(p, encoding)) != EOF)
01936       {
01937         if (ch == '&')
01938           if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
01939             goto error;
01940 
01941         if (mxml_add_char(ch, &ptr, &name, &namesize))
01942           goto error;
01943 
01944         if (ch == quote)
01945           break;
01946       }
01947     }
01948     else
01949     {
01950      
01951 
01952 
01953 
01954       while ((ch = (*getc_cb)(p, encoding)) != EOF)
01955         if (isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?')
01956           break;
01957         else
01958         {
01959           if (ch == '&')
01960             if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
01961               goto error;
01962 
01963           if (mxml_add_char(ch, &ptr, &name, &namesize))
01964             goto error;
01965         }
01966     }
01967 
01968     *ptr = '\0';
01969 
01970     if (mxmlElementGetAttr(node, name))
01971       goto error;
01972 
01973     if (ch == '=')
01974     {
01975      
01976 
01977 
01978 
01979       if ((ch = (*getc_cb)(p, encoding)) == EOF)
01980       {
01981         mxml_error("Missing value for attribute '%s' in element %s!",
01982                    name, node->value.element.name);
01983         return (EOF);
01984       }
01985 
01986       if (ch == '\'' || ch == '\"')
01987       {
01988        
01989 
01990 
01991 
01992         quote = ch;
01993         ptr   = value;
01994 
01995         while ((ch = (*getc_cb)(p, encoding)) != EOF)
01996           if (ch == quote)
01997             break;
01998           else
01999           {
02000             if (ch == '&')
02001               if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
02002                 goto error;
02003               
02004             if (mxml_add_char(ch, &ptr, &value, &valsize))
02005               goto error;
02006           }
02007 
02008         *ptr = '\0';
02009       }
02010       else
02011       {
02012        
02013 
02014 
02015 
02016         value[0] = ch;
02017         ptr      = value + 1;
02018 
02019         while ((ch = (*getc_cb)(p, encoding)) != EOF)
02020           if (isspace(ch) || ch == '=' || ch == '/' || ch == '>')
02021             break;
02022           else
02023           {
02024             if (ch == '&')
02025               if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
02026                 goto error;
02027               
02028             if (mxml_add_char(ch, &ptr, &value, &valsize))
02029               goto error;
02030           }
02031 
02032         *ptr = '\0';
02033       }
02034 
02035      
02036 
02037 
02038 
02039       mxmlElementSetAttr(node, name, value);
02040     }
02041     else
02042     {
02043      
02044 
02045 
02046 
02047       mxmlElementSetAttr(node, name, NULL);
02048     }
02049 
02050    
02051 
02052 
02053 
02054     if (ch == '/' || ch == '?')
02055     {
02056      
02057 
02058 
02059 
02060       quote = (*getc_cb)(p, encoding);
02061 
02062       if (quote != '>')
02063       {
02064         mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
02065                    ch, node->value.element.name, quote);
02066         ch = EOF;
02067       }
02068 
02069       break;
02070     }
02071     else if (ch == '>')
02072       break;
02073   }
02074 
02075  
02076 
02077 
02078 
02079   free(name);
02080   free(value);
02081 
02082   return (ch);
02083 
02084  
02085 
02086 
02087 
02088 error:
02089 
02090   free(name);
02091   free(value);
02092 
02093   return (EOF);
02094 }
02095 
02096 
02097 
02098 
02099 
02100 
02101 static int                              
02102 mxml_string_getc(void *p,               
02103                  int  *encoding)        
02104 {
02105   int           ch;                     
02106   const char    **s;                    
02107 
02108 
02109   s = (const char **)p;
02110 
02111   if ((ch = (*s)[0] & 255) != 0 || *encoding == ENCODE_UTF16LE)
02112   {
02113    
02114 
02115 
02116 
02117     (*s)++;
02118 
02119     switch (*encoding)
02120     {
02121       case ENCODE_UTF8 :
02122           if (!(ch & 0x80))
02123           {
02124 #if DEBUG > 1
02125             printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02126 #endif 
02127 
02128             if (mxml_bad_char(ch))
02129             {
02130               mxml_error("Bad control character 0x%02x not allowed by XML standard!",
02131                          ch);
02132               return (EOF);
02133             }
02134 
02135             return (ch);
02136           }
02137           else if (ch == 0xfe)
02138           {
02139            
02140 
02141 
02142 
02143             if (((*s)[0] & 255) != 0xff)
02144               return (EOF);
02145 
02146             *encoding = ENCODE_UTF16BE;
02147             (*s)++;
02148 
02149             return (mxml_string_getc(p, encoding));
02150           }
02151           else if (ch == 0xff)
02152           {
02153            
02154 
02155 
02156 
02157             if (((*s)[0] & 255) != 0xfe)
02158               return (EOF);
02159 
02160             *encoding = ENCODE_UTF16LE;
02161             (*s)++;
02162 
02163             return (mxml_string_getc(p, encoding));
02164           }
02165           else if ((ch & 0xe0) == 0xc0)
02166           {
02167            
02168 
02169 
02170 
02171             if (((*s)[0] & 0xc0) != 0x80)
02172               return (EOF);
02173 
02174             ch = ((ch & 0x1f) << 6) | ((*s)[0] & 0x3f);
02175 
02176             (*s)++;
02177 
02178             if (ch < 0x80)
02179               return (EOF);
02180 
02181 #if DEBUG > 1
02182             printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02183 #endif 
02184 
02185             return (ch);
02186           }
02187           else if ((ch & 0xf0) == 0xe0)
02188           {
02189            
02190 
02191 
02192 
02193             if (((*s)[0] & 0xc0) != 0x80 ||
02194                 ((*s)[1] & 0xc0) != 0x80)
02195               return (EOF);
02196 
02197             ch = ((((ch & 0x0f) << 6) | ((*s)[0] & 0x3f)) << 6) | ((*s)[1] & 0x3f);
02198 
02199             (*s) += 2;
02200 
02201             if (ch < 0x800)
02202               return (EOF);
02203 
02204 #if DEBUG > 1
02205             printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02206 #endif 
02207 
02208             return (ch);
02209           }
02210           else if ((ch & 0xf8) == 0xf0)
02211           {
02212            
02213 
02214 
02215 
02216             if (((*s)[0] & 0xc0) != 0x80 ||
02217                 ((*s)[1] & 0xc0) != 0x80 ||
02218                 ((*s)[2] & 0xc0) != 0x80)
02219               return (EOF);
02220 
02221             ch = ((((((ch & 0x07) << 6) | ((*s)[0] & 0x3f)) << 6) |
02222                    ((*s)[1] & 0x3f)) << 6) | ((*s)[2] & 0x3f);
02223 
02224             (*s) += 3;
02225 
02226             if (ch < 0x10000)
02227               return (EOF);
02228 
02229 #if DEBUG > 1
02230             printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02231 #endif 
02232 
02233             return (ch);
02234           }
02235           else
02236             return (EOF);
02237 
02238       case ENCODE_UTF16BE :
02239          
02240 
02241 
02242 
02243           ch = (ch << 8) | ((*s)[0] & 255);
02244           (*s) ++;
02245 
02246           if (mxml_bad_char(ch))
02247           {
02248             mxml_error("Bad control character 0x%02x not allowed by XML standard!",
02249                        ch);
02250             return (EOF);
02251           }
02252           else if (ch >= 0xd800 && ch <= 0xdbff)
02253           {
02254            
02255 
02256 
02257 
02258             int lch;                    
02259 
02260 
02261             if (!(*s)[0])
02262               return (EOF);
02263 
02264             lch = (((*s)[0] & 255) << 8) | ((*s)[1] & 255);
02265             (*s) += 2;
02266 
02267             if (lch < 0xdc00 || lch >= 0xdfff)
02268               return (EOF);
02269 
02270             ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
02271           }
02272 
02273 #if DEBUG > 1
02274           printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02275 #endif 
02276 
02277           return (ch);
02278 
02279       case ENCODE_UTF16LE :
02280          
02281 
02282 
02283 
02284           ch = ch | (((*s)[0] & 255) << 8);
02285 
02286           if (!ch)
02287           {
02288             (*s) --;
02289             return (EOF);
02290           }
02291 
02292           (*s) ++;
02293 
02294           if (mxml_bad_char(ch))
02295           {
02296             mxml_error("Bad control character 0x%02x not allowed by XML standard!",
02297                        ch);
02298             return (EOF);
02299           }
02300           else if (ch >= 0xd800 && ch <= 0xdbff)
02301           {
02302            
02303 
02304 
02305 
02306             int lch;                    
02307 
02308 
02309             if (!(*s)[1])
02310               return (EOF);
02311 
02312             lch = (((*s)[1] & 255) << 8) | ((*s)[0] & 255);
02313             (*s) += 2;
02314 
02315             if (lch < 0xdc00 || lch >= 0xdfff)
02316               return (EOF);
02317 
02318             ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
02319           }
02320 
02321 #if DEBUG > 1
02322           printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
02323 #endif 
02324 
02325           return (ch);
02326     }
02327   }
02328 
02329   return (EOF);
02330 }
02331 
02332 
02333 
02334 
02335 
02336 
02337 static int                              
02338 mxml_string_putc(int  ch,               
02339                  void *p)               
02340 {
02341   char  **pp;                           
02342 
02343 
02344   pp = (char **)p;
02345 
02346   if (ch < 0x80)
02347   {
02348    
02349 
02350 
02351 
02352     if (pp[0] < pp[1])
02353       pp[0][0] = ch;
02354 
02355     pp[0] ++;
02356   }
02357   else if (ch < 0x800)
02358   {
02359    
02360 
02361 
02362 
02363     if ((pp[0] + 1) < pp[1])
02364     {
02365       pp[0][0] = 0xc0 | (ch >> 6);
02366       pp[0][1] = 0x80 | (ch & 0x3f);
02367     }
02368 
02369     pp[0] += 2;
02370   }
02371   else if (ch < 0x10000)
02372   {
02373    
02374 
02375 
02376 
02377     if ((pp[0] + 2) < pp[1])
02378     {
02379       pp[0][0] = 0xe0 | (ch >> 12);
02380       pp[0][1] = 0x80 | ((ch >> 6) & 0x3f);
02381       pp[0][2] = 0x80 | (ch & 0x3f);
02382     }
02383 
02384     pp[0] += 3;
02385   }
02386   else
02387   {
02388    
02389 
02390 
02391 
02392     if ((pp[0] + 2) < pp[1])
02393     {
02394       pp[0][0] = 0xf0 | (ch >> 18);
02395       pp[0][1] = 0x80 | ((ch >> 12) & 0x3f);
02396       pp[0][2] = 0x80 | ((ch >> 6) & 0x3f);
02397       pp[0][3] = 0x80 | (ch & 0x3f);
02398     }
02399 
02400     pp[0] += 4;
02401   }
02402 
02403   return (0);
02404 }
02405 
02406 
02407 
02408 
02409 
02410 
02411 static int                              
02412 mxml_write_name(const char *s,          
02413                 void       *p,          
02414                 int        (*putc_cb)(int, void *))
02415                                         
02416 {
02417   char          quote;                  
02418   const char    *name;                  
02419 
02420 
02421   if (*s == '\"' || *s == '\'')
02422   {
02423    
02424 
02425 
02426 
02427     if ((*putc_cb)(*s, p) < 0)
02428       return (-1);
02429 
02430     quote = *s++;
02431 
02432     while (*s && *s != quote)
02433     {
02434       if ((name = mxmlEntityGetName(*s)) != NULL)
02435       {
02436         if ((*putc_cb)('&', p) < 0)
02437           return (-1);
02438 
02439         while (*name)
02440         {
02441           if ((*putc_cb)(*name, p) < 0)
02442             return (-1);
02443 
02444           name ++;
02445         }
02446 
02447         if ((*putc_cb)(';', p) < 0)
02448           return (-1);
02449       }
02450       else if ((*putc_cb)(*s, p) < 0)
02451         return (-1);
02452 
02453       s ++;
02454     }
02455 
02456    
02457 
02458 
02459 
02460     if ((*putc_cb)(quote, p) < 0)
02461       return (-1);
02462   }
02463   else
02464   {
02465    
02466 
02467 
02468 
02469     while (*s)
02470     {
02471       if ((*putc_cb)(*s, p) < 0)
02472         return (-1);
02473 
02474       s ++;
02475     }
02476   }
02477 
02478   return (0);
02479 }
02480 
02481 
02482 
02483 
02484 
02485 
02486 static int                              
02487 mxml_write_node(mxml_node_t *node,      
02488                 void        *p,         
02489                 const char  *(*cb)(mxml_node_t *, int),
02490                                         
02491                 int         col,        
02492                 int         (*putc_cb)(int, void *))
02493 {
02494   int           i,                      
02495                 width;                  
02496   mxml_attr_t   *attr;                  
02497   char          s[255];                 
02498 
02499 
02500   while (node != NULL)
02501   {
02502    
02503 
02504 
02505 
02506     switch (node->type)
02507     {
02508       case MXML_ELEMENT :
02509           col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
02510 
02511           if ((*putc_cb)('<', p) < 0)
02512             return (-1);
02513           if (node->value.element.name[0] == '?' ||
02514               !strncmp(node->value.element.name, "!--", 3) ||
02515               !strncmp(node->value.element.name, "![CDATA[", 8))
02516           {
02517            
02518 
02519 
02520 
02521 
02522             const char  *ptr;           
02523 
02524 
02525             for (ptr = node->value.element.name; *ptr; ptr ++)
02526               if ((*putc_cb)(*ptr, p) < 0)
02527                 return (-1);
02528 
02529            
02530 
02531 
02532 
02533             if (!strncmp(node->value.element.name, "?xml", 4))
02534               col = MXML_WRAP;
02535           }
02536           else if (mxml_write_name(node->value.element.name, p, putc_cb) < 0)
02537             return (-1);
02538 
02539           col += strlen(node->value.element.name) + 1;
02540 
02541           for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
02542                i > 0;
02543                i --, attr ++)
02544           {
02545             width = strlen(attr->name);
02546 
02547             if (attr->value)
02548               width += strlen(attr->value) + 3;
02549 
02550             if ((col + width) > MXML_WRAP)
02551             {
02552               if ((*putc_cb)('\n', p) < 0)
02553                 return (-1);
02554 
02555               col = 0;
02556             }
02557             else
02558             {
02559               if ((*putc_cb)(' ', p) < 0)
02560                 return (-1);
02561 
02562               col ++;
02563             }
02564 
02565             if (mxml_write_name(attr->name, p, putc_cb) < 0)
02566               return (-1);
02567 
02568             if (attr->value)
02569             {
02570               if ((*putc_cb)('=', p) < 0)
02571                 return (-1);
02572               if ((*putc_cb)('\"', p) < 0)
02573                 return (-1);
02574               if (mxml_write_string(attr->value, p, putc_cb) < 0)
02575                 return (-1);
02576               if ((*putc_cb)('\"', p) < 0)
02577                 return (-1);
02578             }
02579 
02580             col += width;
02581           }
02582 
02583           if (node->child)
02584           {
02585            
02586 
02587 
02588 
02589             if ((*putc_cb)('>', p) < 0)
02590               return (-1);
02591             else
02592               col ++;
02593 
02594             col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
02595 
02596             if ((col = mxml_write_node(node->child, p, cb, col, putc_cb)) < 0)
02597               return (-1);
02598 
02599            
02600 
02601 
02602 
02603             if (node->value.element.name[0] != '!' &&
02604                 node->value.element.name[0] != '?')
02605             {
02606               col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_CLOSE, col, putc_cb);
02607 
02608               if ((*putc_cb)('<', p) < 0)
02609                 return (-1);
02610               if ((*putc_cb)('/', p) < 0)
02611                 return (-1);
02612               if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
02613                 return (-1);
02614               if ((*putc_cb)('>', p) < 0)
02615                 return (-1);
02616 
02617               col += strlen(node->value.element.name) + 3;
02618 
02619               col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_CLOSE, col, putc_cb);
02620             }
02621           }
02622           else if (node->value.element.name[0] == '!' ||
02623                    node->value.element.name[0] == '?')
02624           {
02625            
02626 
02627 
02628 
02629             if ((*putc_cb)('>', p) < 0)
02630               return (-1);
02631             else
02632               col ++;
02633 
02634             col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
02635           }
02636           else
02637           {
02638             if ((*putc_cb)(' ', p) < 0)
02639               return (-1);
02640             if ((*putc_cb)('/', p) < 0)
02641               return (-1);
02642             if ((*putc_cb)('>', p) < 0)
02643               return (-1);
02644 
02645             col += 3;
02646 
02647             col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
02648           }
02649           break;
02650 
02651       case MXML_INTEGER :
02652           if (node->prev)
02653           {
02654             if (col > MXML_WRAP)
02655             {
02656               if ((*putc_cb)('\n', p) < 0)
02657                 return (-1);
02658 
02659               col = 0;
02660             }
02661             else if ((*putc_cb)(' ', p) < 0)
02662               return (-1);
02663             else
02664               col ++;
02665           }
02666 
02667           sprintf(s, "%d", node->value.integer);
02668           if (mxml_write_string(s, p, putc_cb) < 0)
02669             return (-1);
02670 
02671           col += strlen(s);
02672           break;
02673 
02674       case MXML_OPAQUE :
02675           if (mxml_write_string(node->value.opaque, p, putc_cb) < 0)
02676             return (-1);
02677 
02678           col += strlen(node->value.opaque);
02679           break;
02680 
02681       case MXML_REAL :
02682           if (node->prev)
02683           {
02684             if (col > MXML_WRAP)
02685             {
02686               if ((*putc_cb)('\n', p) < 0)
02687                 return (-1);
02688 
02689               col = 0;
02690             }
02691             else if ((*putc_cb)(' ', p) < 0)
02692               return (-1);
02693             else
02694               col ++;
02695           }
02696 
02697           sprintf(s, "%f", node->value.real);
02698           if (mxml_write_string(s, p, putc_cb) < 0)
02699             return (-1);
02700 
02701           col += strlen(s);
02702           break;
02703 
02704       case MXML_TEXT :
02705           if (node->value.text.whitespace && col > 0)
02706           {
02707             if (col > MXML_WRAP)
02708             {
02709               if ((*putc_cb)('\n', p) < 0)
02710                 return (-1);
02711 
02712               col = 0;
02713             }
02714             else if ((*putc_cb)(' ', p) < 0)
02715               return (-1);
02716             else
02717               col ++;
02718           }
02719 
02720           if (mxml_write_string(node->value.text.string, p, putc_cb) < 0)
02721             return (-1);
02722 
02723           col += strlen(node->value.text.string);
02724           break;
02725 
02726       case MXML_CUSTOM :
02727           if (mxml_custom_save_cb)
02728           {
02729             char        *data;          
02730             const char  *newline;       
02731 
02732 
02733             if ((data = (*mxml_custom_save_cb)(node)) == NULL)
02734               return (-1);
02735 
02736             if (mxml_write_string(data, p, putc_cb) < 0)
02737               return (-1);
02738 
02739             if ((newline = strrchr(data, '\n')) == NULL)
02740               col += strlen(data);
02741             else
02742               col = strlen(newline);
02743 
02744             free(data);
02745             break;
02746           }
02747 
02748       default : 
02749           return (-1);
02750     }
02751 
02752    
02753 
02754 
02755 
02756     node = node->next;
02757   }
02758 
02759   return (col);
02760 }
02761 
02762 
02763 
02764 
02765 
02766 
02767 static int                              
02768 mxml_write_string(const char *s,        
02769                   void       *p,        
02770                   int        (*putc_cb)(int, void *))
02771                                         
02772 {
02773   const char    *name;                  
02774 
02775 
02776   while (*s)
02777   {
02778     if ((name = mxmlEntityGetName(*s)) != NULL)
02779     {
02780       if ((*putc_cb)('&', p) < 0)
02781         return (-1);
02782 
02783       while (*name)
02784       {
02785         if ((*putc_cb)(*name, p) < 0)
02786           return (-1);
02787         name ++;
02788       }
02789 
02790       if ((*putc_cb)(';', p) < 0)
02791         return (-1);
02792     }
02793     else if ((*putc_cb)(*s, p) < 0)
02794       return (-1);
02795 
02796     s ++;
02797   }
02798 
02799   return (0);
02800 }
02801 
02802 
02803 
02804 
02805 
02806 
02807 static int                              
02808 mxml_write_ws(mxml_node_t *node,        
02809               void        *p,           
02810               const char  *(*cb)(mxml_node_t *, int),
02811                                         
02812               int         ws,           
02813               int         col,          
02814               int         (*putc_cb)(int, void *))
02815                                         
02816 {
02817   const char    *s;                     
02818 
02819 
02820   if (cb && (s = (*cb)(node, ws)) != NULL)
02821   {
02822     while (*s)
02823     {
02824       if ((*putc_cb)(*s, p) < 0)
02825         return (-1);
02826       else if (*s == '\n')
02827         col = 0;
02828       else if (*s == '\t')
02829       {
02830         col += MXML_TAB;
02831         col = col - (col % MXML_TAB);
02832       }
02833       else
02834         col ++;
02835 
02836       s ++;
02837     }
02838   }
02839 
02840   return (col);
02841 }
02842 
02843 
02844 
02845 
02846