📄 xml.c
字号:
#include "xml.h"
#include <stdio.h>
#include <string.h>
/*
GLOBALS
*/
char line[INP_MAX_CHAR+1]; // input readed line
int line_index; // current char for readed line
// NOTE:
// 'END' keyword or directive is used while searching tags into the array.
// See 'parse' function on identifier match for an example...
// recognized tags
char *tags[] = { "database", "db-dsn", "db-host", "db-name", "db-password", "db-port",
"db-type", "db-username", "jdbc", "jdbc-driver", "jdbc-string",
"END" };
// db types
char *dbtypes[] = { "mysql", "odbc",
"END" };
// used for push-back
// if this ptr not equals NULL, the parse() function will return this value...
lisa_node *pushback_XML_node = NULL;
// this is the XML stream
FILE *xml_stream = NULL;
/*
FUNCTIONS
*/
// getXMLChar:
// Get the next char from the xml stream.
// Return 0 if EOF;
char getXMLChar( void )
{
char ch;
// get current char from the line
ch = line[ line_index ];
if ( ch == '\0' )
{
// empty the previous line...
line[0] = '\0';
// ...read a whole line...
fgets( line, INP_MAX_CHAR, xml_stream );
// ...and get first char
line_index = 0;
ch = line[ line_index ];
}
// second '\0' means EOF reached
if ( ch == '\0' )
{
return 0;
}
// increase index for next time
line_index += 1;
// return current char
return ch;
}//getXMLChar
// initXMLParser:
// Initialize the parser.
void initXMLParser( FILE *stream )
{
// empty pushback buffer...
if ( pushback_XML_node != NULL )
{
destroyNodeR( pushback_XML_node );
pushback_XML_node = NULL;
}
// set the input stream...
xml_stream = stream;
}//initXMLParser
// parseXML:
// Parse the xml stream and return a node (token).
// On error (ie: EOF), return a empty node.
//
// The SYNTAX is: (pseudo-BNF)
//
// XML control tag ::= '<?' something '?>'
// remark ::= '<!--' anychar '-->'
// lisa tag ::= '<' tags '>'
// '</' tags '>'
// value ::= { anychar }
lisa_node *parseXML( void )
{
lisa_node *node = NULL;
unsigned char ch;
// return the push-back node if exists...
if ( pushback_XML_node != NULL )
{
node = pushback_XML_node;
pushback_XML_node = NULL;
return node;
}
// create a empty node
node = createNode();
ch = getXMLChar();
// ignoring initial blanks...
while ( strchr( " \t\n\r", ch ) )
{
if ( ch == 0 )
{
// if no more chars, return a empty node...
return node;
}
// get next char
ch = getXMLChar();
}
switch ( ch )
{
case '\0':
{
// if no more chars, return a empty node...
return node;
}
// tag ::= '<' anychar... '>'
case '<':
{
int i=0;
node->element[i] = '\0';
// search for another char...
ch = getXMLChar();
// lowercasing char...
if ( ch >= 'A' && ch <= 'Z' )
ch |= 32;
switch ( ch )
{
// XML tag
case '?':
{
// read until '?>'...
ch = getXMLChar();
while ( 1 )
{
// test for '?'...
while ( ch != '?' )
{
node->element[ i++ ] = ch;
ch = getXMLChar();
}
// test for '>'...
ch = getXMLChar();
if ( ch == '>' )
{
break;
}
else
{
node->element[ i++ ] = '?';
node->element[ i++ ] = ch;
}
}
node->element[ i ] = '\0';
node->type = XML_DEFINITION_TAG;
break;
}
// remark tag
case '!':
{
// check for '--'...
ch = getXMLChar();
if ( ch != '-' ) error( "bad XML <!-- --> tag" );
ch = getXMLChar();
if ( ch != '-' ) error( "bad XML <!-- --> tag" );
// read until '-->'...
ch = getXMLChar();
while ( 1 )
{
// test for '-'...
while ( ch != '-' )
{
node->element[ i++ ] = ch;
ch = getXMLChar();
}
// test for '-'...
ch = getXMLChar();
if ( ch != '-' )
{
node->element[ i++ ] = '-';
node->element[ i++ ] = ch;
}
else
{
// test for '>'...
ch = getXMLChar();
if ( ch != '>' )
{
node->element[ i++ ] = '-';
node->element[ i++ ] = '-';
node->element[ i++ ] = ch;
}
else
{
break;
}
}
}
node->element[ i ] = '\0';
node->type = XML_REMARK_TAG;
break;
}
// end tag
case '/':
{
ch = getXMLChar();
// lowercasing char...
if ( ch >= 'A' && ch <= 'Z' )
ch |= 32;
while ( strchr( "abcdefghijklmnopqrstuvwxyz_0123456789-", ch ) )
{
node->element[i++] = ch;
ch = getXMLChar();
if ( ch >= 'A' && ch <= 'Z' )
ch |= 32;
}
node->element[i] = '\0';
node->type = XML_LISA_ENDTAG;
// check for end tag '>' char
if ( ch != '>' ) error( "bad XML lisa tag" );
// testing tags match...
for ( i=0 ; 1 ; i++ )
{
char *s = tags[ i ];
if ( strcmp( s, node->element ) == 0 )
{
// founded a valid tag!!!
node->type = XML_LISA_ENDTAG;
break;
}
if ( strcmp( s, "END" ) == 0 )
{
// no tags match...
error( "unknown XML tag" );
break;
}
}
break;
}
// lisa tag
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
{
// lowercasing char...
if ( ch >= 'A' && ch <= 'Z' )
ch |= 32;
while ( strchr( "abcdefghijklmnopqrstuvwxyz_0123456789-", ch ) )
{
node->element[i++] = ch;
ch = getXMLChar();
if ( ch >= 'A' && ch <= 'Z' )
ch |= 32;
}
node->element[i] = '\0';
node->type = XML_LISA_TAG;
// check for end tag '>' char
if ( ch != '>' ) error( "bad XML lisa tag" );
// testing tags match...
for ( i=0 ; 1 ; i++ )
{
char *s = tags[ i ];
if ( strcmp( s, node->element ) == 0 )
{
// founded a valid tag!!!
node->type = XML_LISA_TAG;
break;
}
if ( strcmp( s, "END" ) == 0 )
{
// no tags match...
error( "unknown XML tag" );
break;
}
}
break;
}
// BAD TAG DEFINITION!!!
default:
{
error( "bad XML configuration file" );
}
}
break;
}// case '>'
// value ::= { anychar }
default:
{
int i = 0;
// ignore initials blank spaces...
while ( strchr( " \t\n\r", ch ) )
ch = getXMLChar();
// get the whole value...
while ( ch != '<' )
{
node->element[i++] = ch;
ch = getXMLChar();
if ( strchr( "\t\r\n", ch ) ) ch = ' ';
}
node->element[i] = '\0';
node->type = XML_VALUE;
// trim endings blank chars...
if ( i > 0 )
{
while ( strchr( " \t\n\r", node->element[ i-1 ] ) )
{
node->element[ i-1 ] = '\0';
i -= 1;
if ( i == 0 ) break;
}
}
// making a push-back of the '<' char
pushbackXMLChar();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -