dslinux/user/pixil/libs/xml Makefile encoder.c parser.c
amadeus
dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:25:33 CEST 2006
Update of /cvsroot/dslinux/dslinux/user/pixil/libs/xml
In directory antilope:/tmp/cvs-serv11916/libs/xml
Added Files:
Makefile encoder.c parser.c
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it
--- NEW FILE: parser.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
/* TODO: Turn the tag structures into a binary tree for faster searching */
/* Add a stream mode so we can read from STDIN */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef __USE_ISOC99
#define __USE_ISOC99
#endif
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <xml/xml.h>
inline static char
file_getChar(xml_file * file, char *ch)
{
return (((ulong) ch < ((ulong) file->start + file->length)) ? *ch : 0);
}
static void
local_freeTag(xml_token * tag)
{
xml_prop *ptr = tag->props;
while (ptr) {
xml_prop *temp = ptr->next;
free(ptr);
ptr = temp;
}
if (tag->tagstr)
free(tag->tagstr);
free(tag);
}
static xml_prop *
local_newProp(xml_prop ** head)
{
if (!*head) {
*head = (xml_prop *) calloc(sizeof(xml_prop), 1);
return (*head);
} else {
xml_prop *ptr = *head;
while (ptr->next)
ptr = ptr->next;
ptr->next = (xml_prop *) calloc(sizeof(xml_prop), 1);
return (ptr->next);
}
}
static int
local_getTag(xml_file * file, void **pos, char **token, int *size)
{
int ret;
char ch;
char *start = (char *) *pos;
char *end;
/* Strip any whitespace */
while (1) {
ch = file_getChar(file, start);
if (!ch)
return (PARSE_EOF);
if (!isblank(ch) && ch != '\n' && ch != '\r')
break;
if (ch == '\n')
file->lineno++;
start++;
}
/* If this is the beginning of a tag, then search for the end */
if (file_getChar(file, start) == '<') {
start++;
end = start;
if (!(ch = file_getChar(file, end)))
return (PARSE_EOF);
if (ch == '!') {
ret = PARSE_COMMENT;
end++;
} else if (ch == '/') {
ret = PARSE_CLOSE;
end++;
} else
ret = PARSE_TAG;
while ((ch = file_getChar(file, end))) {
if (ch != '>') {
end++;
continue;
}
*size = (int) (end - start);
*end = 0;
*token = start;
*((unsigned char **) pos) = end + 1;
return (ret);
}
fprintf(stderr, "Parse error: Unterminated tag at line %d\n",
file->lineno);
/* The tag was never closed Thats an error */
return (PARSE_ERROR);
}
end = start;
while ((ch = file_getChar(file, end))) {
if (ch == '<' || ch == '>') {
if (ch == '<')
ret = PARSE_TEXT;
else
ret = PARSE_ERROR;
*size = (end - start);
*token = start;
*((unsigned char **) pos) = end;
return (ret);
}
end++;
}
return (PARSE_EOF);
}
static xml_token *
local_tokenize(char *tag)
{
char endchar;
xml_token *local;
char *start, *end;
if (!tag) {
DPRINT("INTERNAL: No string was presented to local_tokenize\n");
return (0);
}
/* Now, create a new tag structure */
if (!(local = (xml_token *) calloc(sizeof(xml_token), 1))) {
DPRINT("INTERNAL: Error on malloc in local_tokenize\n");
return (0);
}
local->tagstr = (char *) malloc(strlen(tag) + 1);
if (!local->tagstr) {
free(local);
return (0);
}
strcpy(local->tagstr, tag);
/* Now we can start parsing out the keywords. Since */
/* the string was copied, it is easy for us to mangle it */
/* First step, look for the inital tag */
start = tag;
for (end = tag; *end && !isblank(*end); end++);
/* If this is just the tag, then return */
if (!*end) {
local->tag = start;
return (local);
}
*end = 0; /* terminate the keyword */
local->tag = start;
start = end + 1;
/* Now, go through and parse all of the keywords */
while (*start) {
xml_prop *local_prop;
/* Strip any inital whitespace */
for (; isblank(*start) || *start == '\n'; start++);
if (!*start)
return (local); /* Nothing else left */
/* Now we have a keyword, make a new structure */
if (!(local_prop = local_newProp(&local->props))) {
DPRINT("INTERNAL: Error on malloc in local_newProp()\n");
return (local);
}
/* Now find the end of the keyword (it will be either */
/* an = or a whitespace */
for (end = start; (*end) && (*end != '=') && (!isblank(*end)); end++);
endchar = *end;
*end = 0;
local_prop->keyword = start;
xml_lowerCase(local_prop->keyword, -1);
if (!endchar)
return (local);
if (endchar == '=') {
start = end + 1;
/* Once again, skip any whitespace */
for (; isblank(*start); start++);
if (!*start) {
fprintf(stderr, "Parse warning: Keyword %s has no value\n",
local_prop->keyword);
return (local); /* Nothing else left */
}
/* If the first char is a '"' then go until the last '"' otherwise,
go until the last space / end-of-line */
if (*start == '\"') {
for (end = start + 1; *end && *end != '\"'; end++);
if (!*end) {
fprintf(stderr,
"Parse error: Unterminated quote near %s.\n",
start);
local_freeTag(local);
return (0); /* Return with an error! */
} else {
start++;
*end = 0;
local_prop->value = start;
}
} else {
for (end = start; *end && !isblank(*end); end++);
if (!*end) {
local_prop->value = start;
return (local); /* Done! */
} else
*end = 0;
local_prop->value = start;
}
} else
fprintf(stderr, "Parse warning: keyword %s has no value\n",
local_prop->keyword);
/* End the keyword / value, and start over again */
*end = 0;
start = end + 1;
}
return (local);
}
xml_tag *
local_findTag(xml_tag * list, char *tag)
{
xml_tag *local = list;
if (!list)
return (0);
while (strlen(local->tag)) {
if (strcmp(local->tag, tag) == 0)
return (local);
local++;
}
return (0);
}
/* xml_recursiveParse()
Description: This is the main parsing engine
engine - the XML engine (mainly the tags)
file - the current file we are parsing
pos - the current position in the file
cur - The tag that prompted this search
parent - The parent of the tag
parent_data - Data from the parent
*/
static int
xml_recursiveParse(xml_parser * engine, xml_file * file,
void **pos, xml_token * current,
xml_tag * parent, void *parent_data)
{
int ret;
xml_token *next;
xml_tag *tag;
void *data = 0;
tag = local_findTag(parent, current->tag);
if (!tag) {
fprintf(stderr,
"Parse error: Tag <%s> unknown for <%s> on line %d\n",
current->tag, parent->tag, file->lineno);
return (-1);
}
/* Run the init function (if it exists) */
if (tag->init)
data = tag->init(current, parent_data);
else
data = parent_data;
/* Now, we want to parse the rest of the block */
while (1) {
int dsize = 0;
char *token;
switch (local_getTag(file, pos, &token, &dsize)) {
case PARSE_EOF:
return (0);
case PARSE_ERROR:
return (-1); /* Bail on errors */
case PARSE_COMMENT:
break; /* Skip comments */
case PARSE_TEXT: /* This is data, if the tag wants it */
if (tag->data)
tag->data(current, data, token, dsize);
break;
case PARSE_TAG:
/* A new tag was found, go ahead and parse it */
next = local_tokenize(token);
if (!next)
return (-1); /* DOH! */
/* And recursively parse this sucker */
ret =
xml_recursiveParse(engine, file, pos, next, tag->subtags,
data);
/* Free the tag now that we are done with it */
local_freeTag(next);
if (ret == -1)
return (-1); /* On error, return the same */
break;
case PARSE_CLOSE:
/* A close tag, is it for the correct token? */
if (strcmp(current->tag, &token[1]) == 0) {
if (tag->end)
tag->end(current, data);
return (0); /* Success */
} else
return (-1); /* Error - Bad close */
}
}
}
static int
xml_parseToplevel(xml_parser * engine, xml_file * file, void *udata)
{
int ret;
void *pos = file->start; /* Start at the beginning */
char *token = 0;
xml_token *local;
while (1) {
int dsize = 0;
/* Get the next token */
switch (local_getTag(file, &pos, &token, &dsize)) {
case PARSE_EOF:
return (0); /* EOF, get outta here */
case PARSE_CLOSE:
fprintf(stderr, "Error - Unexpected '>' at line %d\n",
file->lineno);
return (-1);
case PARSE_ERROR:
fprintf(stderr, "Error - Parse error at line %d\n", file->lineno);
return (-1);
case PARSE_COMMENT:
break; /* Skip over comments */
case PARSE_TAG:
/* Parse the token */
local = local_tokenize(token);
if (!local) {
fprintf(stderr, "Error - Token error at line %d\n",
file->lineno);
return (-1);
}
ret =
xml_recursiveParse(engine, file, &pos, local, engine->tags,
udata);
/* Free the current token */
local_freeTag(local);
/* If the recursive parse failed, then bail */
if (ret == -1) {
printf("Error - Parse error at line %d\n", file->lineno);
return (-1);
}
break;
}
}
return (0);
}
int
xml_parseFile(xml_parser * engine, char *filename, void *userdata)
{
int fd, ret;
struct stat s;
xml_file file;
/* Stat the file to make sure it exists */
if (stat(filename, &s) == -1)
return (-1);
/* Open the file and map it */
fd = open(filename, O_RDONLY, 0);
if (!fd)
return (-1);
file.start =
mmap(0, s.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (!file.start) {
close(fd);
return (-1);
}
file.length = s.st_size;
file.lineno = 1;
/* Start the parser */
ret = xml_parseToplevel(engine, &file, userdata);
/* Clean up after ourselves */
munmap(file.start, file.length);
close(fd);
return (ret);
}
/* These are a few often used utilities that are useful to define here */
/* Convert the specified string to lower case */
void
xml_lowerCase(char *string, int count)
{
int size, i;
if (count == -1)
size = strlen(string);
else
size = count;
for (i = 0; i < size; i++)
string[i] = tolower(string[i]);
}
/* Converted the specified color triplet */
/* (#RRGGBB) to the individual colors */
int
xml_parseColor(char *string, unsigned long *val, int size)
{
char *ptr;
/* We should only accept the standard color form */
if (string[0] != '#') {
*val = 0;
return (-1);
}
ptr = &string[1];
/* We only accept the 6 digit form */
if (size != 7) {
*val = 0;
return (-1);
}
/* Now, this is pretty easy, just convert the color to a long */
*val = strtoul(ptr, NULL, 16);
return (0);
}
--- NEW FILE: encoder.c ---
/*
* Copyright (c) 2003 Century Software, Inc. All Rights Reserved.
*
* This file is part of the PIXIL Operating Environment
*
* The use, copying and distribution of this file is governed by one
* of two licenses, the PIXIL Commercial License, or the GNU General
* Public License, version 2.
*
* Licensees holding a valid PIXIL Commercial License may use this file
* in accordance with the PIXIL Commercial License Agreement provided
* with the Software. Others are governed under the terms of the GNU
* General Public License version 2.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free
* Software Foundation and appearing in the file LICENSE.GPL included
* in the packaging of this file.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* RESTRICTED RIGHTS LEGEND
*
* Use, duplication, or disclosure by the government is subject to
* restriction as set forth in paragraph (b)(3)(b) of the Rights in
* Technical Data and Computer Software clause in DAR 7-104.9(a).
*
* See http://www.pixil.org/gpl/ for GPL licensing
* information.
*
* See http://www.pixil.org/license.html or
* email cetsales at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xml/xml.h>
void
indentLine(FILE * stream, int count)
{
int i;
for (i = 0; i < count; i++)
fprintf(stream, "\t");
}
int
recursiveEncode(FILE * stream, xml_encoder * engine,
xml_encode * encode, void *in, int indent)
{
/* Write the header */
if (!encode->header) {
indentLine(stream, indent);
fprintf(stream, "<%s>\n", encode->tag);
} else
encode->header(stream, encode, in, indent);
/* Write the data */
if (encode->data)
encode->data(stream, in);
/* Write any subtags */
if (encode->subtags) {
xml_encode *list = encode->subtags;
while (strlen(list->tag)) {
void *out = engine->find(list->match, in);
while (out) {
recursiveEncode(stream, engine, list, out, indent + 1);
out = engine->next(list->match, out);
}
list++;
}
}
/* Write the footer */
if (!encode->footer) {
indentLine(stream, indent);
fprintf(stream, "</%s>\n", encode->tag);
} else
encode->footer(stream, encode, in, indent);
return (0);
}
int
xml_encodeFile(xml_encoder * engine, xml_encode * list,
char *filename, void *data)
{
FILE *stream;
xml_encode *encode = list;
if (!filename)
stream = stdout;
else
stream = fopen(filename, "w");
if (!stream)
return (-1);
if (engine->header)
engine->header(stream);
while (strlen(encode->tag)) {
void *in = engine->find(encode->match, data);
if (in)
recursiveEncode(stream, engine, encode, in, 0);
encode++;
}
if (engine->footer)
engine->footer(stream);
if (filename)
fclose(stream);
return (0);
}
--- NEW FILE: Makefile ---
#libs/xml/Makefile
LIB_STATIC=platform-objs/libxml.a
LIB_SHARED=platform-objs/libxml.so
NATIVE_LIB_STATIC=native-objs/libxml.a
PREBUILD_EXTRAS = $(CURDIR)/native-objs $(CURDIR)/platform-objs
SRC=${shell ls *.c}
OBJS := $(SRC:%.c=platform-objs/%.o)
NATIVE_OBJS := $(SRC:%.c=native-objs/%.o)
INCLUDES=-I./include
include $(BASE_DIR)/Rules.make
$(CURDIR)/platform-objs $(CURDIR)/native-objs:
@ mkdir -p $@
clean:
rm -rf $(CURDIR)/platform-objs $(CURDIR)/native-objs
More information about the dslinux-commit
mailing list