@ -55,42 +55,26 @@ typedef struct _mxml_fdbuf_s /**** File descriptor buffer ****/
* Local functions . . .
*/
static int mxml_add_char ( int ch , char * * ptr , char * * buffer ,
int * bufsize ) ;
static int mxml_add_char ( int ch , char * * ptr , char * * buffer , int * bufsize ) ;
static int mxml_fd_getc ( void * p , int * encoding ) ;
static int mxml_fd_putc ( int ch , void * p ) ;
static int mxml_fd_read ( _mxml_fdbuf_t * buf ) ;
static int mxml_fd_write ( _mxml_fdbuf_t * buf ) ;
static int mxml_file_getc ( void * p , int * encoding ) ;
static int mxml_file_putc ( int ch , void * p ) ;
static int mxml_get_entity ( mxml_node_t * parent , void * p ,
int * encoding ,
_mxml_getc_cb_t getc_cb ) ;
static int mxml_get_entity ( mxml_node_t * parent , void * p , int * encoding , _mxml_getc_cb_t getc_cb , int * line ) ;
static inline int mxml_isspace ( int ch )
{
return ( ch = = ' ' | | ch = = ' \t ' | | ch = = ' \r ' | |
ch = = ' \n ' ) ;
return ( ch = = ' ' | | ch = = ' \t ' | | ch = = ' \r ' | | ch = = ' \n ' ) ;
}
static mxml_node_t * mxml_load_data ( mxml_node_t * top , void * p ,
mxml_load_cb_t cb ,
_mxml_getc_cb_t getc_cb ,
mxml_sax_cb_t sax_cb , void * sax_data ) ;
static int mxml_parse_element ( mxml_node_t * node , void * p ,
int * encoding ,
_mxml_getc_cb_t getc_cb ) ;
static mxml_node_t * mxml_load_data ( mxml_node_t * top , void * p , mxml_load_cb_t cb , _mxml_getc_cb_t getc_cb , mxml_sax_cb_t sax_cb , void * sax_data ) ;
static int mxml_parse_element ( mxml_node_t * node , void * p , int * encoding , _mxml_getc_cb_t getc_cb , int * line ) ;
static int mxml_string_getc ( void * p , int * encoding ) ;
static int mxml_string_putc ( int ch , void * p ) ;
static int mxml_write_name ( const char * s , void * p ,
_mxml_putc_cb_t putc_cb ) ;
static int mxml_write_node ( mxml_node_t * node , void * p ,
mxml_save_cb_t cb , int col ,
_mxml_putc_cb_t putc_cb ,
_mxml_global_t * global ) ;
static int mxml_write_string ( const char * s , void * p ,
_mxml_putc_cb_t putc_cb ) ;
static int mxml_write_ws ( mxml_node_t * node , void * p ,
mxml_save_cb_t cb , int ws ,
int col , _mxml_putc_cb_t putc_cb ) ;
static int mxml_write_name ( const char * s , void * p , _mxml_putc_cb_t putc_cb ) ;
static int mxml_write_node ( mxml_node_t * node , void * p , mxml_save_cb_t cb , int col , _mxml_putc_cb_t putc_cb , _mxml_global_t * global ) ;
static int mxml_write_string ( const char * s , void * p , _mxml_putc_cb_t putc_cb ) ;
static int mxml_write_ws ( mxml_node_t * node , void * p , mxml_save_cb_t cb , int ws , int col , _mxml_putc_cb_t putc_cb ) ;
/*
@ -1315,8 +1299,9 @@ static int /* O - Character value or EOF on error */
mxml_get_entity ( mxml_node_t * parent , /* I - Parent node */
void * p , /* I - Pointer to source */
int * encoding , /* IO - Character encoding */
int ( * getc_cb ) ( void * , int * ) )
int ( * getc_cb ) ( void * , int * ) ,
/* I - Get character function */
int * line ) /* IO - Current line number */
{
int ch ; /* Current character */
char entity [ 64 ] , /* Entity string */
@ -1326,23 +1311,27 @@ mxml_get_entity(mxml_node_t *parent, /* I - Parent node */
entptr = entity ;
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF )
{
if ( ch > 126 | | ( ! isalnum ( ch ) & & ch ! = ' # ' ) )
break ;
else if ( entptr < ( entity + sizeof ( entity ) - 1 ) )
* entptr + + = ch ;
else
{
mxml_error ( " Entity name too long under parent <%s>! " ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Entity name too long under parent <%s> on line %d. " , parent ? parent - > value . element . name : " null " , * line ) ;
break ;
}
}
* entptr = ' \0 ' ;
if ( ch ! = ' ; ' )
{
mxml_error ( " Character entity \" %s \" not terminated under parent <%s>! " ,
entity , parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Character entity '%s' not terminated under parent <%s> on line %d. " , entity , parent ? parent - > value . element . name : " null " , * line ) ;
if ( ch = = ' \n ' )
( * line ) + + ;
return ( EOF ) ;
}
@ -1354,13 +1343,11 @@ mxml_get_entity(mxml_node_t *parent, /* I - Parent node */
ch = ( int ) strtol ( entity + 1 , NULL , 10 ) ;
}
else if ( ( ch = mxmlEntityGetValue ( entity ) ) < 0 )
mxml_error ( " Entity name \" %s; \" not supported under parent <%s>! " ,
entity , parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Entity name '%s;' not supported under parent <%s> on line %d. " , entity , parent ? parent - > value . element . name : " null " , * line ) ;
if ( mxml_bad_char ( ch ) )
{
mxml_error ( " Bad control character 0x%02x under parent <%s> not allowed by XML standard! " ,
ch , parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Bad control character 0x%02x under parent <%s> on line %d not allowed by XML standard. " , ch , parent ? parent - > value . element . name : " null " , * line ) ;
return ( EOF ) ;
}
@ -1384,7 +1371,8 @@ mxml_load_data(
mxml_node_t * node , /* Current node */
* first , /* First node added */
* parent ; /* Current parent node */
int ch , /* Character from file */
int line = 1 , /* Current line number */
ch , /* Character from file */
whitespace ; /* Non-zero if whitespace seen */
char * buffer , /* String buffer */
* bufptr ; /* Pointer into buffer */
@ -1469,8 +1457,7 @@ mxml_load_data(
if ( ( * global - > custom_load_cb ) ( node , buffer ) )
{
mxml_error ( " Bad custom value '%s' in parent <%s>! " ,
buffer , parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Bad custom value '%s' in parent <%s> on line %d. " , buffer , parent ? parent - > value . element . name : " null " , line ) ;
mxmlDelete ( node ) ;
node = NULL ;
}
@ -1488,9 +1475,7 @@ mxml_load_data(
* Bad integer / real number value . . .
*/
mxml_error ( " Bad %s value '%s' in parent <%s>! " ,
type = = MXML_INTEGER ? " integer " : " real " , buffer ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Bad %s value '%s' in parent <%s> on line %d. " , type = = MXML_INTEGER ? " integer " : " real " , buffer , parent ? parent - > value . element . name : " null " , line ) ;
break ;
}
@ -1503,8 +1488,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Unable to add value node of type %s to parent <%s>! " ,
types [ type ] , parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Unable to add value node of type %s to parent <%s> on line %d. " , types [ type ] , parent ? parent - > value . element . name : " null " , line ) ;
goto error ;
}
@ -1522,6 +1506,9 @@ mxml_load_data(
else if ( mxml_isspace ( ch ) & & type = = MXML_TEXT )
whitespace = 1 ;
if ( ch = = ' \n ' )
line + + ;
/*
* Add lone whitespace node if we have an element and existing
* whitespace . . .
@ -1557,6 +1544,7 @@ mxml_load_data(
bufptr = buffer ;
while ( ( ch = ( * getc_cb ) ( p , & encoding ) ) ! = EOF )
{
if ( mxml_isspace ( ch ) | | ch = = ' > ' | | ( ch = = ' / ' & & bufptr > buffer ) )
break ;
else if ( ch = = ' < ' )
@ -1566,7 +1554,7 @@ mxml_load_data(
}
else if ( ch = = ' & ' )
{
if ( ( ch = mxml_get_entity ( parent , p , & encoding , getc_cb ) ) = = EOF )
if ( ( ch = mxml_get_entity ( parent , p , & encoding , getc_cb , & line ) ) = = EOF )
goto error ;
if ( mxml_add_char ( ch , & bufptr , & buffer , & bufsize ) )
@ -1581,6 +1569,10 @@ mxml_load_data(
( ( bufptr - buffer ) = = 8 & & ! strncmp ( buffer , " ![CDATA[ " , 8 ) ) )
break ;
if ( ch = = ' \n ' )
line + + ;
}
* bufptr = ' \0 ' ;
if ( ! strcmp ( buffer , " !-- " ) )
@ -1596,6 +1588,9 @@ mxml_load_data(
break ;
else if ( mxml_add_char ( ch , & bufptr , & buffer , & bufsize ) )
goto error ;
if ( ch = = ' \n ' )
line + + ;
}
/*
@ -1608,7 +1603,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Early EOF in comment node! " ) ;
mxml_error ( " Early EOF in comment node on line %d. " , line ) ;
goto error ;
}
@ -1625,8 +1620,7 @@ mxml_load_data(
* There can only be one root element !
*/
mxml_error ( " <%s> cannot be a second root node after <%s> " ,
buffer , first - > value . element . name ) ;
mxml_error ( " <%s> cannot be a second root node after <%s> on line %d. " , buffer , first - > value . element . name , line ) ;
goto error ;
}
@ -1636,8 +1630,7 @@ mxml_load_data(
* Just print error for now . . .
*/
mxml_error ( " Unable to add comment node to parent <%s>! " ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Unable to add comment node to parent <%s> on line %d. " , parent ? parent - > value . element . name : " null " , line ) ;
break ;
}
@ -1671,6 +1664,9 @@ mxml_load_data(
}
else if ( mxml_add_char ( ch , & bufptr , & buffer , & bufsize ) )
goto error ;
if ( ch = = ' \n ' )
line + + ;
}
/*
@ -1683,7 +1679,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Early EOF in CDATA node! " ) ;
mxml_error ( " Early EOF in CDATA node on line %d. " , line ) ;
goto error ;
}
@ -1700,8 +1696,7 @@ mxml_load_data(
* There can only be one root element !
*/
mxml_error ( " <%s> cannot be a second root node after <%s> " ,
buffer , first - > value . element . name ) ;
mxml_error ( " <%s> cannot be a second root node after <%s> on line %d. " , buffer , first - > value . element . name , line ) ;
goto error ;
}
@ -1711,8 +1706,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Unable to add CDATA node to parent <%s>! " ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Unable to add CDATA node to parent <%s> on line %d. " , parent ? parent - > value . element . name : " null " , line ) ;
goto error ;
}
@ -1739,6 +1733,9 @@ mxml_load_data(
break ;
else if ( mxml_add_char ( ch , & bufptr , & buffer , & bufsize ) )
goto error ;
if ( ch = = ' \n ' )
line + + ;
}
/*
@ -1751,7 +1748,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Early EOF in processing instruction node! " ) ;
mxml_error ( " Early EOF in processing instruction node on line %d. " , line ) ;
goto error ;
}
@ -1767,8 +1764,7 @@ mxml_load_data(
* There can only be one root element !
*/
mxml_error ( " <%s> cannot be a second root node after <%s> " ,
buffer , first - > value . element . name ) ;
mxml_error ( " <%s> cannot be a second root node after <%s> on line %d. " , buffer , first - > value . element . name , line ) ;
goto error ;
}
@ -1778,8 +1774,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Unable to add processing instruction node to parent <%s>! " ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Unable to add processing instruction node to parent <%s> on line %d. " , parent ? parent - > value . element . name : " null " , line ) ;
goto error ;
}
@ -1820,12 +1815,17 @@ mxml_load_data(
else
{
if ( ch = = ' & ' )
if ( ( ch = mxml_get_entity ( parent , p , & encoding , getc_cb ) ) = = EOF )
{
if ( ( ch = mxml_get_entity ( parent , p , & encoding , getc_cb , & line ) ) = = EOF )
goto error ;
}
if ( mxml_add_char ( ch , & bufptr , & buffer , & bufsize ) )
goto error ;
}
if ( ch = = ' \n ' )
line + + ;
}
while ( ( ch = ( * getc_cb ) ( p , & encoding ) ) ! = EOF ) ;
@ -1839,7 +1839,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Early EOF in declaration node! " ) ;
mxml_error ( " Early EOF in declaration node on line %d. " , line ) ;
goto error ;
}
@ -1855,8 +1855,7 @@ mxml_load_data(
* There can only be one root element !
*/
mxml_error ( " <%s> cannot be a second root node after <%s> " ,
buffer , first - > value . element . name ) ;
mxml_error ( " <%s> cannot be a second root node after <%s> on line %d. " , buffer , first - > value . element . name , line ) ;
goto error ;
}
@ -1866,8 +1865,7 @@ mxml_load_data(
* Print error and return . . .
*/
mxml_error ( " Unable to add declaration node to parent <%s>! " ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Unable to add declaration node to parent <%s> on line %d. " , parent ? parent - > value . element . name : " null " , line ) ;
goto error ;
}
@ -1907,8 +1905,7 @@ mxml_load_data(
* Close tag doesn ' t match tree ; print an error for now . . .
*/
mxml_error ( " Mismatched close tag <%s> under parent <%s>! " ,
buffer , parent ? parent - > value . element . name : " (null) " ) ;
mxml_error ( " Mismatched close tag <%s> under parent <%s> on line %d. " , buffer , parent ? parent - > value . element . name : " (null) " , line ) ;
goto error ;
}
@ -1949,8 +1946,7 @@ mxml_load_data(
* There can only be one root element !
*/
mxml_error ( " <%s> cannot be a second root node after <%s> " ,
buffer , first - > value . element . name ) ;
mxml_error ( " <%s> cannot be a second root node after <%s> on line %d. " , buffer , first - > value . element . name , line ) ;
goto error ;
}
@ -1960,22 +1956,20 @@ mxml_load_data(
* Just print error for now . . .
*/
mxml_error ( " Unable to add element node to parent <%s>! " ,
parent ? parent - > value . element . name : " null " ) ;
mxml_error ( " Unable to add element node to parent <%s> on line %d. " , parent ? parent - > value . element . name : " null " , line ) ;
goto error ;
}
if ( mxml_isspace ( ch ) )
{
if ( ( ch = mxml_parse_element ( node , p , & encoding , getc_cb ) ) = = EOF )
if ( ( ch = mxml_parse_element ( node , p , & encoding , getc_cb , & line ) ) = = EOF )
goto error ;
}
else if ( ch = = ' / ' )
{
if ( ( ch = ( * getc_cb ) ( p , & encoding ) ) ! = ' > ' )
{
mxml_error ( " Expected > but got '%c' instead for element <%s/>! " ,
ch , buffer ) ;
mxml_error ( " Expected > but got '%c' instead for element <%s/> on line %d. " , ch , buffer , line ) ;
mxmlDelete ( node ) ;
goto error ;
}
@ -2022,7 +2016,7 @@ mxml_load_data(
* Add character entity to current buffer . . .
*/
if ( ( ch = mxml_get_entity ( parent , p , & encoding , getc_cb ) ) = = EOF )
if ( ( ch = mxml_get_entity ( parent , p , & encoding , getc_cb , & line ) ) = = EOF )
goto error ;
if ( mxml_add_char ( ch , & bufptr , & buffer , & bufsize ) )
@ -2058,9 +2052,7 @@ mxml_load_data(
if ( node ! = parent )
{
mxml_error ( " Missing close tag </%s> under parent <%s>! " ,
node - > value . element . name ,
node - > parent ? node - > parent - > value . element . name : " (null) " ) ;
mxml_error ( " Missing close tag </%s> under parent <%s> on line %d. " , node - > value . element . name , node - > parent ? node - > parent - > value . element . name : " (null) " , line ) ;
mxmlDelete ( first ) ;
@ -2077,7 +2069,7 @@ mxml_load_data(
* Common error return . . .
*/
error :
error :
mxmlDelete ( first ) ;
@ -2096,7 +2088,8 @@ mxml_parse_element(
mxml_node_t * node , /* I - Element node */
void * p , /* I - Data to read from */
int * encoding , /* IO - Encoding */
_mxml_getc_cb_t getc_cb ) /* I - Data callback */
_mxml_getc_cb_t getc_cb , /* I - Data callback */
int * line ) /* IO - Current line number */
{
int ch , /* Current character in file */
quote ; /* Quoting character */
@ -2143,7 +2136,12 @@ mxml_parse_element(
*/
if ( mxml_isspace ( ch ) )
{
if ( ch = = ' \n ' )
( * line ) + + ;
continue ;
}
/*
* Stop at / , ? , or > . . .
@ -2159,8 +2157,7 @@ mxml_parse_element(
if ( quote ! = ' > ' )
{
mxml_error ( " Expected '>' after '%c' for element %s, but got '%c'! " ,
ch , node - > value . element . name , quote ) ;
mxml_error ( " Expected '>' after '%c' for element %s, but got '%c' on line %d. " , ch , node - > value . element . name , quote , * line ) ;
goto error ;
}
@ -2168,7 +2165,7 @@ mxml_parse_element(
}
else if ( ch = = ' < ' )
{
mxml_error ( " Bare < in element %s! " , node - > value . element . name ) ;
mxml_error ( " Bare < in element %s on line %d. " , node - > value . element . name , * lin e ) ;
goto error ;
}
else if ( ch = = ' > ' )
@ -2192,8 +2189,12 @@ mxml_parse_element(
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF )
{
if ( ch = = ' & ' )
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb ) ) = = EOF )
{
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb , line ) ) = = EOF )
goto error ;
}
else if ( ch = = ' \n ' )
( * line ) + + ;
if ( mxml_add_char ( ch , & ptr , & name , & namesize ) )
goto error ;
@ -2209,40 +2210,59 @@ mxml_parse_element(
*/
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF )
{
if ( mxml_isspace ( ch ) | | ch = = ' = ' | | ch = = ' / ' | | ch = = ' > ' | |
ch = = ' ? ' )
{
if ( ch = = ' \n ' )
( * line ) + + ;
break ;
}
else
{
if ( ch = = ' & ' )
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb ) ) = = EOF )
{
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb , line ) ) = = EOF )
goto error ;
}
if ( mxml_add_char ( ch , & ptr , & name , & namesize ) )
goto error ;
}
}
}
* ptr = ' \0 ' ;
if ( mxmlElementGetAttr ( node , name ) )
{
mxml_error ( " Duplicate attribute '%s' in element %s on line %d. " , name , node - > value . element . name , name , * line ) ;
goto error ;
}
while ( ch ! = EOF & & mxml_isspace ( ch ) )
{
ch = ( * getc_cb ) ( p , encoding ) ;
if ( ch = = ' \n ' )
( * line ) + + ;
}
if ( ch = = ' = ' )
{
/*
* Read the attribute value . . .
*/
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF & & mxml_isspace ( ch ) ) ;
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF & & mxml_isspace ( ch ) )
{
if ( ch = = ' \n ' )
( * line ) + + ;
}
if ( ch = = EOF )
{
mxml_error ( " Missing value for attribute '%s' in element %s! " ,
name , node - > value . element . name ) ;
mxml_error ( " Missing value for attribute '%s' in element %s on line %d. " , name , node - > value . element . name , * line ) ;
goto error ;
}
@ -2256,17 +2276,25 @@ mxml_parse_element(
ptr = value ;
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF )
{
if ( ch = = quote )
{
break ;
}
else
{
if ( ch = = ' & ' )
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb ) ) = = EOF )
{
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb , line ) ) = = EOF )
goto error ;
}
else if ( ch = = ' \n ' )
( * line ) + + ;
if ( mxml_add_char ( ch , & ptr , & value , & valsize ) )
goto error ;
}
}
* ptr = ' \0 ' ;
}
@ -2280,17 +2308,26 @@ mxml_parse_element(
ptr = value + 1 ;
while ( ( ch = ( * getc_cb ) ( p , encoding ) ) ! = EOF )
{
if ( mxml_isspace ( ch ) | | ch = = ' = ' | | ch = = ' / ' | | ch = = ' > ' )
{
if ( ch = = ' \n ' )
( * line ) + + ;
break ;
}
else
{
if ( ch = = ' & ' )
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb ) ) = = EOF )
{
if ( ( ch = mxml_get_entity ( node , p , encoding , getc_cb , line ) ) = = EOF )
goto error ;
}
if ( mxml_add_char ( ch , & ptr , & value , & valsize ) )
goto error ;
}
}
* ptr = ' \0 ' ;
}
@ -2303,8 +2340,7 @@ mxml_parse_element(
}
else
{
mxml_error ( " Missing value for attribute '%s' in element %s! " ,
name , node - > value . element . name ) ;
mxml_error ( " Missing value for attribute '%s' in element %s on line %d. " , name , node - > value . element . name , * line ) ;
goto error ;
}
@ -2322,8 +2358,7 @@ mxml_parse_element(
if ( quote ! = ' > ' )
{
mxml_error ( " Expected '>' after '%c' for element %s, but got '%c'! " ,
ch , node - > value . element . name , quote ) ;
mxml_error ( " Expected '>' after '%c' for element %s, but got '%c' on line %d. " , ch , node - > value . element . name , quote , * line ) ;
ch = EOF ;
}
@ -2346,7 +2381,7 @@ mxml_parse_element(
* Common error return point . . .
*/
error :
error :
free ( name ) ;
free ( value ) ;