diff --git a/qse/doc/page/awk.doc b/qse/doc/page/awk.doc index 19b33230..a6f1ac16 100644 --- a/qse/doc/page/awk.doc +++ b/qse/doc/page/awk.doc @@ -128,6 +128,12 @@ BEGIN { } @endcode +@subsection awk_ext_fs EXTENDED FS +@code +BEGIN { FS="?:\\\"\""; } +@endcode + + @subsection awk_ext_binnum BINARY NUMBER Use 0b to begin a binary number sequence. diff --git a/qse/lib/awk/misc.c b/qse/lib/awk/misc.c index 2376c31b..0c8a6146 100644 --- a/qse/lib/awk/misc.c +++ b/qse/lib/awk/misc.c @@ -1,5 +1,5 @@ /* - * $Id: misc.c 291 2009-09-21 13:28:18Z hyunghwan.chung $ + * $Id: misc.c 292 2009-09-23 10:19:30Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -940,10 +940,90 @@ exit_loop: qse_char_t* qse_awk_rtx_strxnfld ( qse_awk_rtx_t* rtx, qse_char_t* str, qse_size_t len, - qse_char_t fs, qse_char_t lq, qse_char_t rq, qse_char_t ec, + qse_char_t fs, qse_char_t ec, qse_char_t lq, qse_char_t rq, qse_char_t** tok, qse_size_t* tok_len) { -/* TODO: */ + qse_char_t* p = str; + qse_char_t* end = str + len; + int escaped = 0, quoted = 0; + qse_char_t* ts; /* token start */ + qse_char_t* tp; /* points to one char past the last token char */ + qse_char_t* xp; /* points to one char past the last effective char */ + + /* skip leading spaces */ + while (p < end && QSE_ISSPACE(*p)) p++; + + /* initialize token pointers */ + ts = tp = xp = p; + + while (p < end) + { + char c = *p; + + if (escaped) + { + *tp++ = c; xp = tp; p++; + escaped = 0; + } + else + { + if (c == ec) + { + escaped = 1; + p++; + } + else if (quoted) + { + if (c == rq) + { + quoted = 0; + p++; + } + else + { + *tp++ = c; xp = tp; p++; + } + } + else + { + if (c == fs) + { + *tok = ts; + *tok_len = xp - ts; + p++; + + if (QSE_ISSPACE(fs)) + { + while (p < end && *p == fs) p++; + if (p >= end) return QSE_NULL; + } + + return p; + } + + if (c == lq) + { + quoted = 1; + p++; + } + else + { + *tp++ = c; p++; + if (!QSE_ISSPACE(c)) xp = tp; + } + } + } + } + + if (escaped) + { + /* if it is still escaped, the last character must be + * the escaper itself. treat it as a normal character */ + *xp++ = ec; + } + + *tok = ts; + *tok_len = xp - ts; return QSE_NULL; } diff --git a/qse/lib/awk/rec.c b/qse/lib/awk/rec.c index 63a37aa5..43cae14d 100644 --- a/qse/lib/awk/rec.c +++ b/qse/lib/awk/rec.c @@ -1,5 +1,5 @@ /* - * $Id: rec.c 291 2009-09-21 13:28:18Z hyunghwan.chung $ + * $Id: rec.c 292 2009-09-23 10:19:30Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -98,7 +98,7 @@ int qse_awk_rtx_setrec ( static int split_record (qse_awk_rtx_t* rtx) { - qse_char_t* p, * tok; + qse_char_t* p, * px, * tok; qse_size_t len, tok_len, nflds; qse_awk_val_t* v, * fs; qse_char_t* fs_ptr, * fs_free; @@ -136,9 +136,6 @@ static int split_record (qse_awk_rtx_t* rtx) } /* scan the input record to count the fields */ - - len = QSE_STR_LEN(&rtx->inrec.line); - if (fs_len == 5 && fs_ptr[0] == QSE_T('?')) { if (qse_str_ncpy ( @@ -152,15 +149,18 @@ static int split_record (qse_awk_rtx_t* rtx) return -1; } - p = QSE_STR_PTR(&rtx->inrec.linew); + px = QSE_STR_PTR(&rtx->inrec.linew); how = 1; } else { - p = QSE_STR_PTR(&rtx->inrec.line); + px = QSE_STR_PTR(&rtx->inrec.line); how = (fs_len <= 1)? 0: 2; } + p = px; + len = QSE_STR_LEN(&rtx->inrec.line); + #if 0 nflds = 0; while (p != QSE_NULL) @@ -238,12 +238,14 @@ static int split_record (qse_awk_rtx_t* rtx) qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); return -1; } - p = QSE_STR_PTR(&rtx->inrec.linew): + px = QSE_STR_PTR(&rtx->inrec.linew): } else { - p = QSE_STR_PTR(&rtx->inrec.line); + px = QSE_STR_PTR(&rtx->inrec.line); } + + p = px; len = QSE_STR_LEN(&rtx->inrec.line); #endif @@ -338,8 +340,7 @@ static int split_record (qse_awk_rtx_t* rtx) rtx, rtx->inrec.flds[rtx->inrec.nflds].val); rtx->inrec.nflds++; - len = QSE_STR_LEN(&rtx->inrec.line) - - (p - QSE_STR_PTR(&rtx->inrec.line)); + len = QSE_STR_LEN(&rtx->inrec.line) - (p - px); } if (fs_free != QSE_NULL) QSE_AWK_FREE (rtx->awk, fs_free); diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 16090fe5..ccd3bc43 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c 291 2009-09-21 13:28:18Z hyunghwan.chung $ + * $Id: run.c 292 2009-09-23 10:19:30Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -402,7 +402,7 @@ static int set_global ( fs_len = out.u.cpldup.len; } - if (fs_len > 1) + if (fs_len > 1 && !(fs_len == 5 && fs_ptr[0] == QSE_T('?'))) { void* rex; qse_awk_errnum_t errnum;