Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c693aa638 | ||
|
|
517a9d9605 | ||
|
|
9a084fe0bd | ||
|
|
91e3daf3dc | ||
|
|
9abc0f159c | ||
|
|
eb62727ff9 | ||
|
|
549a6cbab7 | ||
|
|
af79834d89 | ||
|
|
501d6c87c2 | ||
|
|
cbd16b6ab1 | ||
|
|
0f69fd7a8e |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,6 +2,7 @@ Makefile
|
|||||||
Makefile.in
|
Makefile.in
|
||||||
aclocal.m4
|
aclocal.m4
|
||||||
autom4te.cache/
|
autom4te.cache/
|
||||||
|
compile
|
||||||
config.h
|
config.h
|
||||||
config.h.in
|
config.h.in
|
||||||
config.h.in~
|
config.h.in~
|
||||||
@@ -22,3 +23,4 @@ stamp-h1
|
|||||||
ylwrap
|
ylwrap
|
||||||
*.o
|
*.o
|
||||||
*.core
|
*.core
|
||||||
|
*.tar.gz
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
sermon 1.0
|
sermon 1.2
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This utility converts text markup into various presentable forms.
|
This utility converts text markup into various presentable forms.
|
||||||
@@ -46,4 +46,4 @@ The markup syntax is very simple:
|
|||||||
> This paragraph will be
|
> This paragraph will be
|
||||||
> a block quote.
|
> a block quote.
|
||||||
|
|
||||||
- Text enclosed between `[* starred braces *]` will be ignored as a comment.
|
- Text enclosed between `[* starred braces *]` will be ignored as a comment.
|
||||||
|
|||||||
10
configure.ac
10
configure.ac
@@ -2,13 +2,13 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([sermon], [1.0], [david.a.baer@gmail.com])
|
AC_INIT([sermon], [1.2], [david.a.baer@gmail.com])
|
||||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
|
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
|
||||||
AC_CONFIG_SRCDIR([config.h.in])
|
AC_CONFIG_SRCDIR([config.h.in])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
# Checks for programs.
|
# Checks for programs.
|
||||||
AC_PROG_CC
|
AC_PROG_CC_C99
|
||||||
AC_PROG_LEX
|
AC_PROG_LEX
|
||||||
AC_PROG_YACC
|
AC_PROG_YACC
|
||||||
|
|
||||||
@@ -24,16 +24,20 @@ AC_CHECK_HEADERS([inttypes.h libintl.h limits.h malloc.h stddef.h stdint.h stdli
|
|||||||
AC_C_INLINE
|
AC_C_INLINE
|
||||||
AC_TYPE_INT16_T
|
AC_TYPE_INT16_T
|
||||||
AC_TYPE_INT32_T
|
AC_TYPE_INT32_T
|
||||||
|
AC_TYPE_INT64_T
|
||||||
AC_TYPE_INT8_T
|
AC_TYPE_INT8_T
|
||||||
|
AC_TYPE_PID_T
|
||||||
AC_TYPE_SIZE_T
|
AC_TYPE_SIZE_T
|
||||||
AC_TYPE_UINT16_T
|
AC_TYPE_UINT16_T
|
||||||
AC_TYPE_UINT32_T
|
AC_TYPE_UINT32_T
|
||||||
|
AC_TYPE_UINT64_T
|
||||||
AC_TYPE_UINT8_T
|
AC_TYPE_UINT8_T
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
|
AC_FUNC_FORK
|
||||||
AC_FUNC_MALLOC
|
AC_FUNC_MALLOC
|
||||||
AC_FUNC_REALLOC
|
AC_FUNC_REALLOC
|
||||||
AC_CHECK_FUNCS([memset pledge realpath strdup strndup])
|
AC_CHECK_FUNCS([localtime_r pledge memset realpath strcasecmp strdup strndup strrchr])
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
data/Makefile
|
data/Makefile
|
||||||
|
|||||||
48
sermon.1
Normal file
48
sermon.1
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
.Dd $Mdocdate: July 7 2016$
|
||||||
|
.Dt SERMON 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm sermon
|
||||||
|
.Nd converts sermon text markup to a variety of formats
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm sermon
|
||||||
|
.Op Fl hv
|
||||||
|
.Op Fl a Ar author
|
||||||
|
.Op Fl s Ar stylename
|
||||||
|
.Op Fl o Ar output
|
||||||
|
.Ar
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm
|
||||||
|
utility converts sermon markup text into a variety of useful formats,
|
||||||
|
including
|
||||||
|
.Em HTML Ns
|
||||||
|
,
|
||||||
|
.Em ODT Ns
|
||||||
|
, and
|
||||||
|
.Em XSL-FO No Ns .
|
||||||
|
.\" .Sh CONTEXT
|
||||||
|
.\" For section 9 functions only.
|
||||||
|
.\" .Sh IMPLEMENTATION NOTES
|
||||||
|
.\" Not used in OpenBSD.
|
||||||
|
.\" .Sh RETURN VALUES
|
||||||
|
.\" For sections 2, 3, and 9 function return values only.
|
||||||
|
.\" .Sh ENVIRONMENT
|
||||||
|
.\" For sections 1, 6, 7, and 8 only.
|
||||||
|
.\" .Sh FILES
|
||||||
|
.\" .Sh EXIT STATUS
|
||||||
|
.\" For sections 1, 6, and 8 only.
|
||||||
|
.\" .Sh EXAMPLES
|
||||||
|
.\" .Sh DIAGNOSTICS
|
||||||
|
.\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only.
|
||||||
|
.\" .Sh ERRORS
|
||||||
|
.\" For sections 2, 3, 4, and 9 errno settings only.
|
||||||
|
.\" .Sh SEE ALSO
|
||||||
|
.\" .Xr foobar 1
|
||||||
|
.\" .Sh STANDARDS
|
||||||
|
.\" .Sh HISTORY
|
||||||
|
.\" .Sh AUTHORS
|
||||||
|
.\" .Sh CAVEATS
|
||||||
|
.\" .Sh BUGS
|
||||||
|
.\" .Sh SECURITY CONSIDERATIONS
|
||||||
|
.\" Not used in OpenBSD.
|
||||||
54
src/format.c
54
src/format.c
@@ -44,6 +44,7 @@ typedef enum {
|
|||||||
TOK_UNICODE,
|
TOK_UNICODE,
|
||||||
TOK_STAR,
|
TOK_STAR,
|
||||||
TOK_REF,
|
TOK_REF,
|
||||||
|
TOK_URL,
|
||||||
/*
|
/*
|
||||||
TOK_DASH,
|
TOK_DASH,
|
||||||
TOK_OPEN_DOUBLE_QUOTE,
|
TOK_OPEN_DOUBLE_QUOTE,
|
||||||
@@ -68,22 +69,37 @@ freeTokenizer(utf8iterator* iter) {
|
|||||||
utf8FreeIterator(iter);
|
utf8FreeIterator(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
int
|
||||||
greekChar(uint32_t ch) {
|
greekChar(uint32_t ch) {
|
||||||
return (((0x370 <= ch) && (ch <= 0x3ff)) ||
|
return (((0x370 <= ch) && (ch <= 0x3ff)) ||
|
||||||
((0x1f00 <= ch) && (ch <= 0x1fff)));
|
((0x1f00 <= ch) && (ch <= 0x1fff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
int
|
||||||
extendedPunctuation(uint32_t ch) {
|
extendedPunctuation(uint32_t ch) {
|
||||||
return ((0x2000 <= ch) && (ch <= 0x206f));
|
return ((0x2000 <= ch) && (ch <= 0x206f));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int
|
int
|
||||||
latinChar(uint32_t ch) {
|
latinChar(uint32_t ch) {
|
||||||
return (ch <= 0xff) || extendedPunctuation(ch);
|
return (ch <= 0xff) || extendedPunctuation(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
httpAt(Tokenizer tokenizer) {
|
||||||
|
return ((tolower(tokenizer->txt[tokenizer->byteIndex]) == 'h') &&
|
||||||
|
(tolower(tokenizer->txt[tokenizer->byteIndex + 1]) == 't') &&
|
||||||
|
(tolower(tokenizer->txt[tokenizer->byteIndex + 2]) == 't') &&
|
||||||
|
(tolower(tokenizer->txt[tokenizer->byteIndex + 3]) == 'p') &&
|
||||||
|
((tokenizer->txt[tokenizer->byteIndex + 4] == ':') &&
|
||||||
|
(tokenizer->txt[tokenizer->byteIndex + 5] == '/') &&
|
||||||
|
(tokenizer->txt[tokenizer->byteIndex + 6] == '/')) ||
|
||||||
|
((tolower(tokenizer->txt[tokenizer->byteIndex + 4]) == 's') &&
|
||||||
|
(tokenizer->txt[tokenizer->byteIndex + 5] == ':') &&
|
||||||
|
(tokenizer->txt[tokenizer->byteIndex + 6] == '/') &&
|
||||||
|
(tokenizer->txt[tokenizer->byteIndex + 7] == '/')));
|
||||||
|
}
|
||||||
|
|
||||||
static Token
|
static Token
|
||||||
nextToken(Tokenizer tokenizer) {
|
nextToken(Tokenizer tokenizer) {
|
||||||
int startIndex = tokenizer->byteIndex;
|
int startIndex = tokenizer->byteIndex;
|
||||||
@@ -125,12 +141,30 @@ nextToken(Tokenizer tokenizer) {
|
|||||||
result.toktype = TOK_REF;
|
result.toktype = TOK_REF;
|
||||||
result.toktext = strndup(tokenizer->txt + idStart, idEnd - idStart);
|
result.toktext = strndup(tokenizer->txt + idStart, idEnd - idStart);
|
||||||
return result;
|
return result;
|
||||||
|
} else if (httpAt(tokenizer)) {
|
||||||
|
int endIndex = 0;
|
||||||
|
while ((ch != 0) && (ch != ' ') && (ch != '\r') && (ch != '\n')) {
|
||||||
|
utf8Advance(tokenizer);
|
||||||
|
ch = utf8CharAt(tokenizer);
|
||||||
|
}
|
||||||
|
if (tokenizer->txt[tokenizer->byteIndex - 1] == '.') {
|
||||||
|
/* heuristic: url doesn't end in . */
|
||||||
|
endIndex = --tokenizer->byteIndex;
|
||||||
|
} else {
|
||||||
|
endIndex = tokenizer->byteIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.toktype = TOK_URL;
|
||||||
|
result.toktext = strndup(tokenizer->txt + startIndex, endIndex - startIndex);
|
||||||
|
return result;
|
||||||
} else if (latinChar(ch)) {
|
} else if (latinChar(ch)) {
|
||||||
while ((ch != 0) && latinChar(ch) && (ch != '*')) {
|
while ((ch != 0) && latinChar(ch) && (ch != '*')) {
|
||||||
utf8Advance(tokenizer);
|
utf8Advance(tokenizer);
|
||||||
ch = utf8CharAt(tokenizer);
|
ch = utf8CharAt(tokenizer);
|
||||||
if (ch == '^') {
|
if (ch == '^') {
|
||||||
if (tokenizer->txt[tokenizer->byteIndex + 1] == '{') break;
|
if (tokenizer->txt[tokenizer->byteIndex + 1] == '{') break;
|
||||||
|
} else if (httpAt(tokenizer)) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.toktype = TOK_TEXT;
|
result.toktype = TOK_TEXT;
|
||||||
@@ -181,6 +215,8 @@ int formatText(const char* txt, FormatElement** dst, CitationRecordQueue* citati
|
|||||||
t = FORMAT_GREEK;
|
t = FORMAT_GREEK;
|
||||||
} else if (tok.toktype == TOK_UNICODE) {
|
} else if (tok.toktype == TOK_UNICODE) {
|
||||||
t = FORMAT_UNICODE;
|
t = FORMAT_UNICODE;
|
||||||
|
} else if (tok.toktype == TOK_URL) {
|
||||||
|
t = FORMAT_URL;
|
||||||
} else if (tok.toktype == TOK_REF) {
|
} else if (tok.toktype == TOK_REF) {
|
||||||
t = FORMAT_CITATION;
|
t = FORMAT_CITATION;
|
||||||
if (citationQPtr && !lookupCitation(*citationQPtr, tok.toktext)) {
|
if (citationQPtr && !lookupCitation(*citationQPtr, tok.toktext)) {
|
||||||
@@ -223,15 +259,3 @@ void freeFormatElementArray(FormatElement* a, int length) {
|
|||||||
free(a);
|
free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FORMATTER_TEST
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
const char* str = "My name in Chinese is \xe7\x86\x8a\xe5\xa4\xa7\xe8\xa1\x9b, or *xiong da wei*. My favorite Greek passage is \xe1\xbc\x90\xce\xbd \xe1\xbc\x80\xcf\x81\xcf\x87\xe1\xbf\x87 \xe1\xbc\xa6\xce\xbd \xe1\xbd\x81 \xce\xbb\xe1\xbd\xb9\xce\xb3\xce\xbf\xcf\x82.^{cite}";
|
|
||||||
|
|
||||||
int
|
|
||||||
main() {
|
|
||||||
FormatElement* lst;
|
|
||||||
int l = formatText(str, &lst, NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ typedef enum {
|
|||||||
FORMAT_STRONG,
|
FORMAT_STRONG,
|
||||||
FORMAT_CITATION,
|
FORMAT_CITATION,
|
||||||
FORMAT_GREEK,
|
FORMAT_GREEK,
|
||||||
FORMAT_UNICODE
|
FORMAT_UNICODE,
|
||||||
|
FORMAT_URL
|
||||||
} FormatElementType;
|
} FormatElementType;
|
||||||
|
|
||||||
typedef struct FormatElement FormatElement;
|
typedef struct FormatElement FormatElement;
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ uint32_t utf8CharAt(const utf8iterator* iter) {
|
|||||||
((uint32_t)(iter->txt[byteIndex] & 0x03) << 24);
|
((uint32_t)(iter->txt[byteIndex] & 0x03) << 24);
|
||||||
|
|
||||||
} else if (((iter->txt[byteIndex] & 0xf7) == 0xfc) &&
|
} else if (((iter->txt[byteIndex] & 0xf7) == 0xfc) &&
|
||||||
((iter->txt[byteIndex + 1]) & 0xc0 == 0x80) &&
|
((iter->txt[byteIndex + 1] & 0xc0) == 0x80) &&
|
||||||
((iter->txt[byteIndex + 2] & 0xc0) == 0x80) &&
|
((iter->txt[byteIndex + 2] & 0xc0) == 0x80) &&
|
||||||
((iter->txt[byteIndex + 3] & 0xc0) == 0x80) &&
|
((iter->txt[byteIndex + 3] & 0xc0) == 0x80) &&
|
||||||
((iter->txt[byteIndex + 4] & 0xc0) == 0x80) &&
|
((iter->txt[byteIndex + 4] & 0xc0) == 0x80) &&
|
||||||
@@ -112,7 +112,7 @@ _next_offset(const utf8iterator* iter) {
|
|||||||
((iter->txt[byteIndex + 4] & 0xc0) == 0x80)) {
|
((iter->txt[byteIndex + 4] & 0xc0) == 0x80)) {
|
||||||
return 5;
|
return 5;
|
||||||
} else if (((iter->txt[byteIndex] & 0xf7) == 0xfc) &&
|
} else if (((iter->txt[byteIndex] & 0xf7) == 0xfc) &&
|
||||||
((iter->txt[byteIndex + 1]) & 0xc0 == 0x80) &&
|
((iter->txt[byteIndex + 1] & 0xc0) == 0x80) &&
|
||||||
((iter->txt[byteIndex + 2] & 0xc0) == 0x80) &&
|
((iter->txt[byteIndex + 2] & 0xc0) == 0x80) &&
|
||||||
((iter->txt[byteIndex + 3] & 0xc0) == 0x80) &&
|
((iter->txt[byteIndex + 3] & 0xc0) == 0x80) &&
|
||||||
((iter->txt[byteIndex + 4] & 0xc0) == 0x80) &&
|
((iter->txt[byteIndex + 4] & 0xc0) == 0x80) &&
|
||||||
|
|||||||
33
src/xml.c
33
src/xml.c
@@ -1,3 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* xml.c - Create XML representation of sermon document
|
||||||
|
* Copyright © 2017 David A. Baer
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the organization nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY David A. Baer ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL David A. Baer BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#include <libxml/tree.h>
|
#include <libxml/tree.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
@@ -65,6 +93,11 @@ formatElementsToXML(
|
|||||||
xmlNodePtr unicode = xmlNewNode(sermon_ns, "unicode");
|
xmlNodePtr unicode = xmlNewNode(sermon_ns, "unicode");
|
||||||
xmlAddChild(unicode, xmlNewText(a[i].elementContent.textContent));
|
xmlAddChild(unicode, xmlNewText(a[i].elementContent.textContent));
|
||||||
xmlAddChild(parentElement, unicode);
|
xmlAddChild(parentElement, unicode);
|
||||||
|
} else if (a[i].elementType == FORMAT_URL) {
|
||||||
|
xmlNodePtr link = xmlNewNode(sermon_ns, "link");
|
||||||
|
xmlSetProp(link, "href", a[i].elementContent.textContent);
|
||||||
|
xmlAddChild(link, xmlNewText(a[i].elementContent.textContent));
|
||||||
|
xmlAddChild(parentElement, link);
|
||||||
} else if (a[i].elementType == FORMAT_CITATION) {
|
} else if (a[i].elementType == FORMAT_CITATION) {
|
||||||
xmlNodePtr cite = xmlNewNode(sermon_ns, "cite");
|
xmlNodePtr cite = xmlNewNode(sermon_ns, "cite");
|
||||||
int num = findReferenceNumber(numReferences, sermonReferencesPtr, a[i].elementContent.textContent);
|
int num = findReferenceNumber(numReferences, sermonReferencesPtr, a[i].elementContent.textContent);
|
||||||
|
|||||||
28
src/xml.h
28
src/xml.h
@@ -1,3 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* xml.h - create XML representation of sermon document
|
||||||
|
* Copyright © 2017 David A. Baer
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the organization nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY David A. Baer ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL David A. Baer BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
#ifndef _XML_H
|
#ifndef _XML_H
|
||||||
#define _XML_H
|
#define _XML_H
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user