diff --git a/qse/cmd/xli/xli.c b/qse/cmd/xli/xli.c index 37381ff8..37f55ae4 100644 --- a/qse/cmd/xli/xli.c +++ b/qse/cmd/xli/xli.c @@ -128,9 +128,11 @@ static void print_usage (QSE_FILE* out, int argc, qse_char_t* argv[]) qse_fprintf (out, QSE_T("options as follows:\n")); qse_fprintf (out, QSE_T(" -h/--help show this message\n")); qse_fprintf (out, QSE_T(" --version show version\n")); - qse_fprintf (out, QSE_T(" -f file specify an input file\n")); + qse_fprintf (out, QSE_T(" -i file specify an input file\n")); qse_fprintf (out, QSE_T(" -o file specify an output file\n")); qse_fprintf (out, QSE_T(" -n allow a key name\n")); + qse_fprintf (out, QSE_T(" -f keep file inclusion info\n")); + qse_fprintf (out, QSE_T(" -t keep comment text\n")); qse_fprintf (out, QSE_T(" -m number specify the maximum amount of memory to use in bytes\n")); #if defined(QSE_BUILD_DEBUG) qse_fprintf (out, QSE_T(" -X number fail the number'th memory allocation\n")); @@ -157,9 +159,9 @@ static int handle_args (int argc, qse_char_t* argv[]) static qse_opt_t opt = { #if defined(QSE_BUILD_DEBUG) - QSE_T("hf:o:nm:X:"), + QSE_T("hi:o:nftm:X:"), #else - QSE_T("hf:o:nm:"), + QSE_T("hi:o:nftm:"), #endif lng }; @@ -193,7 +195,7 @@ static int handle_args (int argc, qse_char_t* argv[]) print_usage (QSE_STDOUT, argc, argv); goto done; - case QSE_T('f'): + case QSE_T('i'): g_input_file = opt.arg; break; @@ -205,6 +207,14 @@ static int handle_args (int argc, qse_char_t* argv[]) g_trait |= QSE_XLI_KEYNAME; break; + case QSE_T('f'): + g_trait |= QSE_XLI_KEEPFILE; + break; + + case QSE_T('t'): + g_trait |= QSE_XLI_KEEPTEXT; + break; + case QSE_T('m'): g_memlimit = qse_strtoulong (opt.arg); break; diff --git a/qse/include/qse/xli/xli.h b/qse/include/qse/xli/xli.h index cc42b98c..7e2452e3 100644 --- a/qse/include/qse/xli/xli.h +++ b/qse/include/qse/xli/xli.h @@ -73,9 +73,11 @@ typedef enum qse_xli_opt_t qse_xli_opt_t; enum qse_xli_trait_t { - QSE_XLI_KEYNODUP = (1 << 0), - QSE_XLI_KEYNAME = (1 << 1), - QSE_XLI_NOTEXT = (1 << 10) + QSE_XLI_KEYNODUP = (1 << 1), + QSE_XLI_KEYNAME = (1 << 2), + + QSE_XLI_KEEPTEXT = (1 << 3), /**< keep comment text */ + QSE_XLI_KEEPFILE = (1 << 4), /**< keep inclusion file info */ }; typedef enum qse_xli_trait_t qse_xli_trait_t; @@ -88,6 +90,7 @@ typedef struct qse_xli_atom_t qse_xli_atom_t; typedef struct qse_xli_pair_t qse_xli_pair_t; typedef struct qse_xli_text_t qse_xli_text_t; typedef struct qse_xli_file_t qse_xli_file_t; +typedef struct qse_xli_eof_t qse_xli_eof_t; enum qse_xli_val_type_t { @@ -102,6 +105,7 @@ enum qse_xli_atom_type_t QSE_XLI_PAIR, QSE_XLI_TEXT, QSE_XLI_FILE, + QSE_XLI_EOF }; typedef enum qse_xli_atom_type_t qse_xli_atom_type_t; @@ -163,6 +167,12 @@ struct qse_xli_file_t const qse_char_t* path; }; +struct qse_xli_eof_t +{ + QSE_XLI_ATOM_HDR; +}; + + /** * The qse_xli_ecb_close_t type defines the callback function * called when an xli object is cloxli. @@ -487,6 +497,26 @@ QSE_EXPORT qse_xli_pair_t* qse_xli_insertpairwithstr ( const qse_cstr_t* value ); +QSE_EXPORT qse_xli_text_t* qse_xli_inserttext ( + qse_xli_t* xli, + qse_xli_list_t* parent, + qse_xli_atom_t* peer, + const qse_char_t* str +); + +QSE_EXPORT qse_xli_file_t* qse_xli_insertfile ( + qse_xli_t* xli, + qse_xli_list_t* parent, + qse_xli_atom_t* peer, + const qse_char_t* path +); + +QSE_EXPORT qse_xli_eof_t* qse_xli_inserteof ( + qse_xli_t* xli, + qse_xli_list_t* parent, + qse_xli_atom_t* peer +); + QSE_EXPORT qse_xli_list_t* qse_xli_getroot ( qse_xli_t* xli ); diff --git a/qse/lib/xli/read.c b/qse/lib/xli/read.c index 17b609a0..8715052f 100644 --- a/qse/lib/xli/read.c +++ b/qse/lib/xli/read.c @@ -174,15 +174,13 @@ static int skip_comment (qse_xli_t* xli, qse_xli_tok_t* tok) { GET_CHAR_TO (xli, c); if (c == QSE_T('\n') || c == QSE_CHAR_EOF) break; -#if 0 - ADD_TOKEN_CHAR (xli, tok, c); -#endif + + if (xli->opt.trait & QSE_XLI_KEEPTEXT) ADD_TOKEN_CHAR (xli, tok, c); } while (1); -#if 0 - if (qse_xli_inserttext (xli, list, QSE_NULL, QSE_STR_PTR(tok->name)) <= -1) return -1; -#endif + if ((xli->opt.trait & QSE_XLI_KEEPTEXT) && + qse_xli_inserttext (xli, xli->parlink->list, QSE_NULL, QSE_STR_PTR(tok->name)) == QSE_NULL) return -1; GET_CHAR (xli); /* eat the new line letter */ return 1; /* comment by # */ @@ -271,13 +269,14 @@ static int get_symbols (qse_xli_t* xli, qse_cint_t c, qse_xli_tok_t* tok) return 0; } -static int end_include (qse_xli_t* xli) +static int end_include (qse_xli_t* xli, int noeof) { int x; qse_xli_io_arg_t* cur; if (xli->sio.inp == &xli->sio.arg) return 0; /* no include */ + /* if it is an included file, close it and * retry to read a character from an outer file */ @@ -298,6 +297,9 @@ static int end_include (qse_xli_t* xli) QSE_MMGR_FREE (xli->mmgr, cur); /* xli->parse.depth.incl--; */ + if ((xli->opt.trait & QSE_XLI_KEEPFILE) && !noeof && + qse_xli_inserteof (xli, xli->parlink->list, QSE_NULL) == QSE_NULL) return -1; + if (x != 0) { /* the failure mentioned above is returned here */ @@ -349,12 +351,19 @@ static int begin_include (qse_xli_t* xli) * from this file. */ if (get_char (xli) <= -1 || get_token (xli) <= -1) { - end_include (xli); + end_include (xli, 1); /* i don't jump to oops since i've called * end_include() where xli->sio.inp/arg is freed. */ return -1; } + if ((xli->opt.trait & QSE_XLI_KEEPFILE) && + qse_xli_insertfile (xli, xli->parlink->list, QSE_NULL, arg->name) == QSE_NULL) + { + end_include (xli, 1); + return -1; + } + return 0; oops: @@ -389,7 +398,7 @@ retry: if (c == QSE_CHAR_EOF) { - n = end_include (xli); + n = end_include (xli, 0); if (n <= -1) return -1; if (n >= 1) { @@ -526,18 +535,21 @@ static int get_token (qse_xli_t* xli) return get_token_into (xli, &xli->tok); } -static int read_pair (qse_xli_t* xli, qse_xli_list_t* list) +static int read_pair (qse_xli_t* xli) { qse_char_t* key = QSE_NULL; qse_char_t* name = QSE_NULL; qse_xli_pair_t* pair; + qse_xli_list_t* parlist; + + parlist = xli->parlink->list; if (xli->opt.trait & QSE_XLI_KEYNODUP) { qse_xli_atom_t* atom; /* find any key conflicts in the current scope */ - atom = list->tail; + atom = parlist->tail; while (atom) { if (atom->type == QSE_XLI_PAIR && @@ -567,7 +579,7 @@ static int read_pair (qse_xli_t* xli, qse_xli_list_t* list) { qse_xli_atom_t* atom; - atom = list->tail; + atom = parlist->tail; while (atom) { if (atom->type == QSE_XLI_PAIR && @@ -630,7 +642,7 @@ static int read_pair (qse_xli_t* xli, qse_xli_list_t* list) } pair = qse_xli_insertpairwithstr ( - xli, list, QSE_NULL, key, name, QSE_STR_CSTR(xli->tmp[0])); + xli, parlist, QSE_NULL, key, name, QSE_STR_CSTR(xli->tmp[0])); if (pair == QSE_NULL) goto oops; /* semicolon is mandatory for a string */ @@ -653,7 +665,7 @@ static int read_pair (qse_xli_t* xli, qse_xli_list_t* list) if (get_token (xli) <= -1) goto oops; /* insert a pair with an empty list */ - pair = qse_xli_insertpairwithemptylist (xli, list, QSE_NULL, key, name); + pair = qse_xli_insertpairwithemptylist (xli, parlist, QSE_NULL, key, name); if (pair == QSE_NULL) goto oops; if (read_list (xli, (qse_xli_list_t*)pair->val) <= -1) goto oops; @@ -676,7 +688,7 @@ static int read_pair (qse_xli_t* xli, qse_xli_list_t* list) else if (MATCH (xli, TOK_SEMICOLON)) { /* no value has been specified for the pair */ - pair = qse_xli_insertpair (xli, list, QSE_NULL, key, name, &xli->xnil); + pair = qse_xli_insertpair (xli, parlist, QSE_NULL, key, name, &xli->xnil); if (pair == QSE_NULL) goto oops; /* skip the semicolon */ @@ -698,8 +710,17 @@ oops: return -1; } -static int read_list (qse_xli_t* xli, qse_xli_list_t* list) +static int read_list (qse_xli_t* xli, qse_xli_list_t* parlist) { + qse_xli_list_link_t* link = QSE_NULL; + + link = (qse_xli_list_link_t*) qse_xli_callocmem (xli, QSE_SIZEOF(*link)); + if (link == QSE_NULL) goto oops; + + link->list = parlist; + link->next = xli->parlink; + xli->parlink = link; + while (1) { if (MATCH (xli, TOK_XINCLUDE)) @@ -716,7 +737,7 @@ static int read_list (qse_xli_t* xli, qse_xli_list_t* list) } else if (MATCH (xli, TOK_IDENT)) { - if (read_pair (xli, list) <= -1) goto oops; + if (read_pair (xli) <= -1) goto oops; } else if (MATCH (xli, TOK_TEXT)) { @@ -728,9 +749,19 @@ static int read_list (qse_xli_t* xli, qse_xli_list_t* list) } } + QSE_ASSERT (link == xli->parlink); + xli->parlink = link->next; + qse_xli_freemem (xli, link); + return 0; oops: + if (link) + { + QSE_ASSERT (link == xli->parlink); + xli->parlink = link->next; + qse_xli_freemem (xli, link); + } return -1; } @@ -774,6 +805,8 @@ int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io) if (get_char (xli) <= -1 || get_token (xli) <= -1) goto oops; if (read_list (xli, &xli->root) <= -1) goto oops; + QSE_ASSERT (xli->parlink == QSE_NULL); + if (!MATCH (xli, TOK_EOF)) { qse_xli_seterror (xli, QSE_XLI_ESYNTAX, QSE_NULL, &xli->tok.loc); diff --git a/qse/lib/xli/write.c b/qse/lib/xli/write.c index 08f0ba66..c1ab51ea 100644 --- a/qse/lib/xli/write.c +++ b/qse/lib/xli/write.c @@ -84,10 +84,13 @@ static int write_list (qse_xli_t* xli, qse_xli_list_t* list, int depth) case QSE_XLI_FILE: /* TODO filename escaping.... */ - qse_printf (QSE_T("@include \"%s\";\n"),(( qse_xli_file_t*)curatom)->path); + qse_printf (QSE_T("@include \"%s\";\n"),((qse_xli_file_t*)curatom)->path); /* TODO: open a new stream */ break; + + case QSE_XLI_EOF: + break; } } diff --git a/qse/lib/xli/xli.c b/qse/lib/xli/xli.c index 8f605bd6..b03bbbdc 100644 --- a/qse/lib/xli/xli.c +++ b/qse/lib/xli/xli.c @@ -300,11 +300,48 @@ qse_xli_text_t* qse_xli_inserttext ( text->type = QSE_XLI_TEXT; text->ptr = (const qse_char_t*)(text + 1); + qse_strcpy ((qse_char_t*)(text + 1), str); + insert_atom (xli, parent, peer, (qse_xli_atom_t*)text); return text; } +qse_xli_file_t* qse_xli_insertfile ( + qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer, const qse_char_t* path) +{ + qse_xli_file_t* file; + qse_size_t plen; + + plen = qse_strlen (path); + + file = qse_xli_callocmem (xli, QSE_SIZEOF(*file) + ((plen + 1) * QSE_SIZEOF(*path))); + if (file == QSE_NULL) return QSE_NULL; + + file->type = QSE_XLI_FILE; + file->path = (const qse_char_t*)(file + 1); + + qse_strcpy ((qse_char_t*)(file + 1), path); + + insert_atom (xli, parent, peer, (qse_xli_atom_t*)file); + + return file; +} + +qse_xli_eof_t* qse_xli_inserteof ( + qse_xli_t* xli, qse_xli_list_t* parent, qse_xli_atom_t* peer) +{ + qse_xli_eof_t* eof; + + eof = qse_xli_callocmem (xli, QSE_SIZEOF(*eof)); + if (eof == QSE_NULL) return QSE_NULL; + + eof->type = QSE_XLI_EOF; + insert_atom (xli, parent, peer, (qse_xli_atom_t*)eof); + + return eof; +} + /* ------------------------------------------------------ */ static void free_list (qse_xli_t* xli, qse_xli_list_t* list); diff --git a/qse/lib/xli/xli.h b/qse/lib/xli/xli.h index 865fefde..062bb30a 100644 --- a/qse/lib/xli/xli.h +++ b/qse/lib/xli/xli.h @@ -34,6 +34,14 @@ struct qse_xli_tok_t qse_xli_loc_t loc; }; +typedef struct qse_xli_list_link_t qse_xli_list_link_t; + +struct qse_xli_list_link_t +{ + qse_xli_list_link_t* next; + qse_xli_list_t* list; +}; + struct qse_xli_t { qse_mmgr_t* mmgr; @@ -50,8 +58,9 @@ struct qse_xli_t qse_xli_ecb_t* ecb; - qse_xli_list_t root; qse_xli_nil_t xnil; + qse_xli_list_t root; + qse_xli_list_link_t* parlink; qse_str_t* tmp[1]; qse_xli_tok_t tok;