From 791565aa2bb86a2a1dd621608d8bea4f997a4815 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 11 Mar 2009 04:39:18 +0000 Subject: [PATCH] interim commit --- qse/include/qse/utl/main.h | 19 +++-- qse/include/qse/utl/sed.h | 34 ++++++++- qse/lib/cmn/chr.h | 18 ++++- qse/lib/cmn/mem.h | 18 ++++- qse/lib/cmn/syscall.h | 19 +++++ qse/lib/utl/sed.c | 153 ++++++++++++++++++++++++++++++------- qse/lib/utl/sed.h | 7 +- qse/test/utl/sed01.c | 25 ++++-- 8 files changed, 240 insertions(+), 53 deletions(-) diff --git a/qse/include/qse/utl/main.h b/qse/include/qse/utl/main.h index 18af440f..6039c427 100644 --- a/qse/include/qse/utl/main.h +++ b/qse/include/qse/utl/main.h @@ -11,15 +11,15 @@ #include #if defined(_WIN32) && !defined(__MINGW32__) - #if defined(QSE_CHAR_IS_MCHAR) - #define qse_main main +# if defined(QSE_CHAR_IS_MCHAR) +# define qse_main main typedef qse_mchar_t qse_achar_t; - #else - #define qse_main wmain +# else +# define qse_main wmain typedef qse_wchar_t qse_achar_t; - #endif +# endif #else - #define qse_main main +# define qse_main main typedef qse_mchar_t qse_achar_t; #endif @@ -27,7 +27,12 @@ extern "C" { #endif -int qse_runmain (int argc, qse_achar_t* argv[], int(*mf) (int,qse_char_t*[])); +int qse_runmain ( + int argc, + qse_achar_t* argv[], + int (*mf)(int,qse_char_t*[]) +); + /* TODO - qse_runmain with env, namely, qse_runmaine */ #ifdef __cplusplus diff --git a/qse/include/qse/utl/sed.h b/qse/include/qse/utl/sed.h index 5dbfdde5..9c969b58 100644 --- a/qse/include/qse/utl/sed.h +++ b/qse/include/qse/utl/sed.h @@ -39,15 +39,20 @@ enum qse_sed_errnum_t QSE_SED_EBSEXP /* \ is expected */ }; +enum qse_sed_option_t +{ + QSE_SED_STRIPLS = (1 << 0) /* strip leading spaces from text*/ +}; + typedef struct qse_sed_t qse_sed_t; typedef struct qse_sed_c_t qse_sed_c_t; /* command */ typedef enum qse_sed_errnum_t qse_sed_errnum_t; - struct qse_sed_t { QSE_DEFINE_COMMON_FIELDS (sed) qse_sed_errnum_t errnum; + int option; /* source code pointers */ struct @@ -119,10 +124,33 @@ void qse_sed_fini ( ); /******/ - -int qse_sed_execute ( +/****f* Text Processor/qse_sed_getoption + * NAME + * qse_sed_getoption - get option + * SYNOPSIS + */ +int qse_sed_getoption ( qse_sed_t* sed ); +/******/ + +/****f* Text Processor/qse_sed_setoption + * NAME + * qse_sed_setoption - set option + * SYNOPSIS + */ +void qse_sed_setoption ( + qse_sed_t* sed, + int option +); +/*****/ + + +int qse_sed_compile ( + qse_sed_t* sed, + const qse_char_t* sptr, + qse_size_t slen +); #ifdef __cplusplus } diff --git a/qse/lib/cmn/chr.h b/qse/lib/cmn/chr.h index 8f131dbd..4a4db959 100644 --- a/qse/lib/cmn/chr.h +++ b/qse/lib/cmn/chr.h @@ -1,7 +1,19 @@ /* - * $Id: chr.h 76 2009-02-22 14:18:06Z hyunghwan.chung $ - * - * {License} + * $Id: chr.h 97 2009-03-10 10:39:18Z hyunghwan.chung $ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ #ifndef _QSE_LIB_CMN_CHR_H_ diff --git a/qse/lib/cmn/mem.h b/qse/lib/cmn/mem.h index 121e8af9..ec917f6a 100644 --- a/qse/lib/cmn/mem.h +++ b/qse/lib/cmn/mem.h @@ -1,7 +1,19 @@ /* - * $Id: mem.h 76 2009-02-22 14:18:06Z hyunghwan.chung $ - * - * {License} + * $Id: mem.h 97 2009-03-10 10:39:18Z hyunghwan.chung $ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ #ifndef _QSE_LIB_CMN_MEM_H_ diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index 8ff2808e..6bf0d40f 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -1,3 +1,21 @@ +/* + * $Id: syscall.h 97 2009-03-10 10:39:18Z hyunghwan.chung $ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + #ifndef _QSE_LIB_CMN_SYSCALL_H_ #define _QSE_LIB_CMN_SYSCALL_H_ @@ -170,4 +188,5 @@ #else # define QSE_cHROOT(path) chroot(path) #endif + #endif diff --git a/qse/lib/utl/sed.c b/qse/lib/utl/sed.c index 492a0dc7..5f34b8ad 100644 --- a/qse/lib/utl/sed.c +++ b/qse/lib/utl/sed.c @@ -20,6 +20,14 @@ #include "../cmn/mem.h" #include +/* TODO: delete stdio.h */ +#include + +/* POSIX http://www.opengroup.org/onlinepubs/009695399/utilities/sed.html + * ALSO READ + http://www.freebsd.org/cgi/cvsweb.cgi/src/usr.bin/sed/POSIX?rev=1.4.6.1;content-type=text%2Fplain + */ + QSE_IMPLEMENT_COMMON_FUNCTIONS (sed) qse_sed_t* qse_sed_open (qse_mmgr_t* mmgr, qse_size_t xtn) @@ -83,13 +91,23 @@ void qse_sed_fini (qse_sed_t* sed) qse_str_fini (&sed->rexbuf); } +void qse_sed_setoption (qse_sed_t* sed, int option) +{ + sed->option = option; +} + +int qse_sed_getoption (qse_sed_t* sed) +{ + return sed->option; +} + /* get the current charanter of the source code */ #define CURSC(sed) \ - (((sed)->src.cur < (sed)->src.end)? *(sed)->src.cur: QSE_CHAR_EOF) + (((sed)->src.cur < (sed)->src.end)? (*(sed)->src.cur): QSE_CHAR_EOF) /* advance the current pointer of the source code */ #define ADVSCP(sed) ((sed)->src.cur++) #define NXTSC(sed) \ - (((++(sed)->src.cur) < (sed)->src.end)? *(sed)->src.cur: QSE_CHAR_EOF) + (((++(sed)->src.cur) < (sed)->src.end)? (*(sed)->src.cur): QSE_CHAR_EOF) #define ISSPACE(c) (c == QSE_T(' ') || c == QSE_T('\t')) @@ -196,6 +214,76 @@ static qse_sed_a_t* address (qse_sed_t* sed, qse_sed_a_t* a) return a; } +/* get the text following 'a' and 'i' command. + * POSIX: + * The argument text shall consist of one or more lines. Each embedded + * in the text shall be preceded by a backslash. Other backslashes + * in text shall be removed, and the following character shall be treated + * literally. */ +static qse_str_t* get_text (qse_sed_t* sed, qse_sed_c_t* cmd) +{ + qse_cint_t c; + qse_str_t* text = QSE_NULL; + + text = qse_str_open (sed->mmgr, 0, 128); + if (text == QSE_NULL) goto oops; + + do + { + c = CURSC (sed); + + if (sed->option & QSE_SED_STRIPLS) + { + /* get the first non-space character */ + while (ISSPACE(c)) c = NXTSC (sed); + } + + while (c != QSE_CHAR_EOF) + { + int nl = 0; + + if (c == QSE_T('\\')) + { + c = NXTSC (sed); + if (c == QSE_CHAR_EOF) break; + /* TODO: alternate bahavior - add \ to text. */ + + } + else if (c == QSE_T('\n')) nl = 1; + + if (qse_str_ccat (text, c) == (qse_size_t)-1) + { + sed->errnum = QSE_SED_ENOMEM; + goto oops; + } + + if (c == QSE_T('\n')) + { + ADVSCP (sed); + if (nl) break; + } + + c = NXTSC (sed); + } + } + while (c != QSE_CHAR_EOF); + + if (/*(sed->option & QSE_SED_ENSURENL) &&*/ QSE_STR_LEN(text) == 0) + { + if (qse_str_ccat (text, QSE_T('\n')) == (qse_size_t)-1) + { + sed->errnum = QSE_SED_ENOMEM; + goto oops; + } + } + + return text; + +oops: + if (text != QSE_NULL) qse_str_close (text); + return QSE_NULL; +} + static int command (qse_sed_t* sed) { qse_cint_t c; @@ -205,6 +293,7 @@ static int command (qse_sed_t* sed) switch (c) { default: +qse_printf (QSE_T("command not recognized [%c]\n"), c); sed->errnum = QSE_SED_ECMDNR; return -1; @@ -244,50 +333,49 @@ static int command (qse_sed_t* sed) case QSE_SED_CMD_A: case QSE_SED_CMD_I: + { cmd->type = c; + /* if (cmd->a2.type != QSE_SED_A_NONE) { sed->errnum = QSE_SED_EA2PHB; return -1; } + */ - /* get the first non-space character */ c = NXTSC (sed); while (ISSPACE(c)) c = NXTSC (sed); - if (c == QSE_CHAR_EOF) + if (c != QSE_T('\\')) { sed->errnum = QSE_SED_EBSEXP; - return -1; + return -1; } + + c = NXTSC (sed); + while (ISSPACE(c)) c = NXTSC (sed); - do + if (c != QSE_T('\n')) { - if (c == QSE_T('\n')) - { - ADVSCP (sed); - break; - } - - if (c == QSE_T('\\')) - { - c = NXTSC (sed); - if (c == QSE_CHAR_EOF) break; - - if (c == QSE_T('\n')) - { - /* TODO: support different line end scheme... */ - c = NXTSC (sed); - continue; - } - } - - /* TODO: add c to cmd->u.text */ - - c = NXTSC (sed); + /* TODO: change error code. garbage after + * backslash... */ + sed->errnum = QSE_SED_EBSEXP; + return -1; } - while (c != QSE_CHAR_EOF); + + ADVSCP (sed); /* skip the new line */ + + /* get_text() starts from the next line */ + cmd->u.text = get_text (sed, cmd); + if (cmd->u.text == QSE_NULL) return -1; + +{ +qse_char_t ttt[1000]; +fgets (ttt, QSE_COUNTOF(ttt), stdin); +qse_printf (QSE_T("%s%s"), ttt, QSE_STR_PTR(cmd->u.text)); +} break; + } case QSE_T('c'): break; @@ -429,6 +517,8 @@ static int compile_source ( if (sed->cmd.cur >= sed->cmd.end) { /* TODO: too many commands */ + sed->errnum = QSE_SED_ENOMEM; /* TODO change it. */ + return -1; } cmd = ++sed->cmd.cur; @@ -436,3 +526,8 @@ static int compile_source ( return 0; } + +int qse_sed_compile (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) +{ + return compile_source (sed, sptr, slen); +} diff --git a/qse/lib/utl/sed.h b/qse/lib/utl/sed.h index 4768f420..ec70cfcf 100644 --- a/qse/lib/utl/sed.h +++ b/qse/lib/utl/sed.h @@ -20,6 +20,7 @@ #define _QSE_LIB_UTL_SED_H_ #include +#include typedef qse_int_t qse_sed_line_t; @@ -50,9 +51,9 @@ struct qse_sed_c_t union { - void* rex; /* regular expression */ - qse_char_t* text; /* added text or file name */ - qse_sed_c_t* lbl; /* destination command of branch */ + qse_str_t* text; + void* rex; + qse_sed_c_t* lbl; /* branch destination */ } u; qse_char_t* rhs; /* right-hand side of sustitution */ diff --git a/qse/test/utl/sed01.c b/qse/test/utl/sed01.c index 01413941..d72bdf3e 100644 --- a/qse/test/utl/sed01.c +++ b/qse/test/utl/sed01.c @@ -22,12 +22,19 @@ #include #include +#include -int main () +int sed_main (int argc, qse_char_t* argv[]) { qse_sed_t* sed = QSE_NULL; int ret = -1; + if (argc != 2) + { + qse_fprintf (QSE_STDERR, QSE_T("usage: %s string\n"), argv[0]); + return -1; + } + sed = qse_sed_open (QSE_NULL, 0); if (sed == QSE_NULL) { @@ -35,11 +42,14 @@ int main () goto oops; } - //if (qse_sed_compile (sed, QSE_T("1,20"), 4) == -1) - //{ + qse_sed_setoption (sed, QSE_SED_STRIPLS); + + if (qse_sed_compile (sed, argv[1], qse_strlen(argv[1])) == -1) + { + qse_fprintf (QSE_STDERR, QSE_T("cannot compile - %d\n"), sed->errnum); //qse_fprintf (QSE_STDERR, QSE_T("cannot compile - %s\n"), qse_sed_geterrstr(sed)); - // goto oops; - //} + goto oops; + } //if (qse_sed_execute (sed, io) == -1) //{ @@ -51,4 +61,9 @@ oops: return ret; } +int qse_main (int argc, char* argv[]) +{ + return qse_runmain (argc, argv, sed_main); +} + /******/