fixed a few bugs in sed

This commit is contained in:
hyung-hwan 2009-05-19 06:55:01 +00:00
parent acab50e08a
commit 37bdcd4fb2
7 changed files with 2025 additions and 434 deletions

View File

@ -1,15 +1,28 @@
/** @mainpage
@section INTRODUCTION
QSE provides a script engine for various scripting languages and utility programs. It aims to produce a flexible script engine framework that can be embedded into an application. A hosting application can access various aspects of the embedded script engine and vice versa.
<< INSTALL >>
The library is licended under the Apache License, Version 2.0.
The project webpage: http://qse.googlecode.com/
For furthur information, contact: Chung, Hyung-Hwan <b a c o n e v i @ g m a i l . c o m>
@section INSTALLATION
Cross compiling for WIN32 with MINGW32
./configure --host=i586-mingw32msvc --target=i586-mingw32msvc --enable-syscall
make
<< DOCUMENTATION >>
@section DOCUMENTATION
Generate the API documents with robodoc.
robodoc --rc doc/robodoc.rc --css doc/robodoc.css --src . --doc ./doc/qse
@section MODULES
QSE includes various modules:
- AWK: awk.h
- SED: sed.h
*/

1510
qse/doc/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* $Id: str.h 138 2009-05-17 09:35:16Z hyunghwan.chung $
* $Id: str.h 140 2009-05-18 12:55:01Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
@ -22,16 +22,14 @@
#include <qse/types.h>
#include <qse/macros.h>
/****o* Common/String
* DESCRIPTION
/** @file
* <qse/cmn/str.h> defines various functions, types, macros to manipulate
* strings.
* a string.
*
* The qse_cstr_t type and the qse_xstr_t defined in ase/types.h helps you
* The qse_cstr_t type and the qse_xstr_t defined in <qse/types.h> helps you
* dealing with a string pointer and length.
*
* #include <qse/cmn/str.h>
******
* @example str.c
*/
#define QSE_STR_LEN(s) ((s)->len)
@ -43,21 +41,17 @@
typedef struct qse_str_t qse_str_t;
typedef qse_size_t (*qse_str_sizer_t) (qse_str_t* data, qse_size_t hint);
/****s* Common/qse_str_t
* NAME
* qse_str_t - define a dynamically resizable string
* SYNOPSIS
/**
* The qse_str_t type defines a dynamically resizable string.
*/
struct qse_str_t
{
QSE_DEFINE_COMMON_FIELDS (str)
qse_str_sizer_t sizer;
qse_char_t* ptr;
qse_size_t len;
qse_size_t capa;
};
/******/
/* int qse_chartonum (qse_char_t c, int base) */
#define QSE_CHARTONUM(c,base) \
@ -109,10 +103,13 @@ struct qse_str_t
if (__ston_f > 0) value *= -1; \
}
enum qse_strtrm_opt_t
/**
* The qse_strtrm_op_t defines a string trimming operation.
*/
enum qse_strtrm_op_t
{
QSE_STRTRM_LEFT = (1 << 0),
QSE_STRTRM_RIGHT = (1 << 1)
QSE_STRTRM_LEFT = (1 << 0), /**< trim leading spaces */
QSE_STRTRM_RIGHT = (1 << 1) /**< trim trailing spaces */
};
#ifdef __cplusplus
@ -246,25 +243,25 @@ int qse_strxncmp (
int qse_strcasecmp (const qse_char_t* s1, const qse_char_t* s2);
/****f* Common/qse_strxncasecmp
* NAME
* qse_strxncasecmp - compare strings ignoring case
* DESCRIPTION
* The qse_strxncasecmp() function compares characters at the same position
* in each string after converting them to the same case temporarily.
* It accepts two strings and a character class handler. A string is
* represented by its beginning pointer and length.
/**
* The qse_strxncasecmp() function compares characters at the same position
* in each string after converting them to the same case temporarily.
* It accepts two strings and a character class handler. A string is
* represented by its beginning pointer and length.
*
* For two strings to be equal, they need to have the same length and all
* characters in the first string should be equal to their counterpart in the
* second string.
*
* The following code snippet compares "foo" and "FoO" case-insenstively.
* @code
* qse_strxncasecmp (QSE_T("foo"), 3, QSE_T("FoO"), 3);
* @endcode
*
* @return
* The qse_strxncasecmp() returns 0 if two strings are equal, a positive
* number if the first string is larger, -1 if the second string is larger.
*
* For two strings to be equal, they need to have the same length and all
* characters in the first string should be equal to their counterpart in the
* second string.
* RETURN
* The qse_strxncasecmp() returns 0 if two strings are equal, a positive
* number if the first string is larger, -1 if the second string is larger.
* EXAMPLES
* The example compares "foo" and "FoO" case-insenstively.
* qse_strxncasecmp (QSE_T("foo"), 3, QSE_T("FoO"), 3);
* SYNOPSIS
*/
int qse_strxncasecmp (
const qse_char_t* s1 /* the pointer to the first string */,
@ -272,7 +269,6 @@ int qse_strxncasecmp (
const qse_char_t* s2 /* the pointer to the second string */,
qse_size_t len2 /* the length of the second string */
);
/******/
qse_char_t* qse_strdup (const qse_char_t* str, qse_mmgr_t* mmgr);
qse_char_t* qse_strxdup (
@ -303,15 +299,49 @@ qse_char_t* qse_strxnbeg (
const qse_char_t* str, qse_size_t len1,
const qse_char_t* sub, qse_size_t len2);
/* Checks if a string ends with a substring */
qse_char_t* qse_strend (const qse_char_t* str, const qse_char_t* sub);
/**
* The qse_strend() function checks if the a string ends with a substring.
* @return the pointer to a beginning of a matching end,
* QSE_NULL if no match is found.
*/
qse_char_t* qse_strend (
const qse_char_t* str, /**< a string */
const qse_char_t* sub /**< a substring */
);
/**
* The qse_strxend function checks if the a string ends with a substring.
* @return the pointer to a beginning of a matching end,
* QSE_NULL if no match is found.
*/
qse_char_t* qse_strxend (
const qse_char_t* str, qse_size_t len, const qse_char_t* sub);
const qse_char_t* str,
qse_size_t len,
const qse_char_t* sub
);
/**
* The qse_strnend() function checks if the a string ends with a substring.
* @return the pointer to a beginning of a matching end,
* QSE_NULL if no match is found.
*/
qse_char_t* qse_strnend (
const qse_char_t* str, const qse_char_t* sub, qse_size_t len);
const qse_char_t* str,
const qse_char_t* sub,
qse_size_t len
);
/**
* The qse_strxnend() function checks if the a string ends with a substring.
* @return the pointer to a beginning of a matching end,
* QSE_NULL if no match is found.
*/
qse_char_t* qse_strxnend (
const qse_char_t* str, qse_size_t len1,
const qse_char_t* sub, qse_size_t len2);
const qse_char_t* str,
qse_size_t len1,
const qse_char_t* sub,
qse_size_t len2
);
/*
* string conversion
@ -336,6 +366,191 @@ qse_long_t qse_strxtolong (const qse_char_t* str, qse_size_t len);
qse_uint_t qse_strxtouint (const qse_char_t* str, qse_size_t len);
qse_ulong_t qse_strxtoulong (const qse_char_t* str, qse_size_t len);
/****f* Common/qse_strspl
* NAME
* qse_strspl - split a string into fields
* SEE ALSO
* qse_strspltrn
* SYNOPSIS
*/
int qse_strspl (
qse_char_t* str,
const qse_char_t* delim,
qse_char_t lquote,
qse_char_t rquote,
qse_char_t escape
);
/******/
/****f* Common/qse_strspltrn
* NAME
* qse_strspltrn - split a string translating special escape sequences
* DESCRIPTION
* The argument trset is a translation character set which is composed
* of multiple character pairs. An escape character followed by the
* first character in a pair is translated into the second character
* in the pair. If trset is QSE_NULL, no translation is performed.
* EXAMPLES
* Let's translate a sequence of '\n' and '\r' to a new line and a carriage
* return respectively.
* qse_strspltrn (str, QSE_T(':'), QSE_T('['), QSE_T(']'), QSE_T('\\'), QSE_T("n\nr\r"), &nfields);
* Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second
* fields to <CR>abc<NL>def where <CR> is a carriage return and <NL> is a
* new line.
* SEE ALSO
* If you don't need any translation, you may call qse_strspl() alternatively.
* SYNOPSIS
*/
int qse_strspltrn (
qse_char_t* str,
const qse_char_t* delim,
qse_char_t lquote,
qse_char_t rquote,
qse_char_t escape,
const qse_char_t* trset
);
/******/
/**
* The qse_strtrm() function removes leading spaces and/or trailing
* spaces from a string depending on the opt parameter. You can form
* the op parameter by bitwise-OR'ing one or more of the following
* values:
*
* - QSE_STRTRM_LEFT - trim leading spaces
* - QSE_STRTRM_RIGHT - trim trailing spaces
*
* Should it remove leading spaces, it just returns the pointer to
* the first non-space character in the string. Should it remove trailing
* spaces, it inserts a QSE_T('\0') character after the last non-space
* characters. Take note of this behavior.
*
* @code
* qse_char_t a[] = QSE_T(" this is a test string ");
* qse_printf (QSE_T("[%s]\n"), qse_strtrm(a,QSE_STRTRM_LEFT|QSE_STRTRM_RIGHT));
* @endcode
*
* @return the pointer to a trimmed string.
*/
qse_char_t* qse_strtrm (
qse_char_t* str, /**< a string */
int op /**< operation code XOR'ed of qse_strtrm_op_t values */
);
/****f* Common/qse_mbstowcs
* NAME
* qse_mbstowcs - convert a multibyte string to a wide character string
* SYNOPSIS
*/
qse_size_t qse_mbstowcs (
const qse_mchar_t* mbs,
qse_wchar_t* wcs,
qse_size_t* wcslen
);
/******/
/****f* Common/qse_mbsntowcsn
* NAME
* qse_mbsntowcsn - convert a multibyte string to a wide character string
* RETURN
* The qse_mbstowcs() function returns the number of bytes handled.
* SYNOPSIS
*/
qse_size_t qse_mbsntowcsn (
const qse_mchar_t* mbs,
qse_size_t mbslen,
qse_wchar_t* wcs,
qse_size_t* wcslen
);
/******/
/****f* Common/qse_wcstombslen
* NAME
* qse_wcstombslen - get the length
* DESCRIPTION
* The qse_wcstombslen() function scans a null-terminated wide character
* string to get the total number of multibyte characters that it can be
* converted to. The resulting number of characters is stored into memory
* pointed to by mbslen.
* RETURN
* The qse_wcstombslen() function returns the number of wide characters
* handled.
* SYNOPSIS
*/
qse_size_t qse_wcstombslen (
const qse_wchar_t* wcs,
qse_size_t* mbslen
);
/******/
/****f* Common/qse_wcsntombsnlen
* NAME
* qse_wcsntombsnlen - get the length
* DESCRIPTION
* The qse_wcsntombsnlen() function scans a wide character wcs as long as
* wcslen characters to get the get the total number of multibyte characters
* that it can be converted to. The resulting number of characters is stored
* into memory pointed to by mbslen.
* RETURN
* The qse_wcsntombsnlen() function returns the number of wide characters
* handled.
* SYNOPSIS
*/
qse_size_t qse_wcsntombsnlen (
const qse_wchar_t* wcs,
qse_size_t wcslen,
qse_size_t* mbslen
);
/******/
/****f* Common/qse_wcstombs
* NAME
* qse_wcstombs - convert a wide character string to a multibyte string.
* DESCRIPTION
* The qse_wcstombs() function converts a null-terminated wide character
* string to a multibyte string and stores it into the buffer pointed to
* by mbs. The pointer to a variable holding the buffer length should be
* passed to the function as the third parameter. After conversion, it holds
* the length of the multibyte string excluding the terminating-null.
* It may not null-terminate the resulting multibyte string if the buffer
* is not large enough. You can check if the resulting mbslen is equal to
* the input mbslen to know it.
* RETURN
* The qse_wcstombs() function returns the number of wide characters handled.
* SYNOPSIS
*/
qse_size_t qse_wcstombs (
const qse_wchar_t* wcs,
qse_mchar_t* mbs,
qse_size_t* mbslen
);
/******/
/**
* The qse_wcsntombsn() function converts a wide character string to a
* multibyte string.
* @return the number of wide characters
*/
qse_size_t qse_wcsntombsn (
const qse_wchar_t* wcs, /**< a wide string */
qse_size_t wcslen, /**< wide string length */
qse_mchar_t* mbs, /**< a multibyte string buffer */
qse_size_t* mbslen /**< the buffer size */
);
/**
* The qse_wcstombs_strict() function performs the same as the qse_wcsmbs()
* function except that it returns an error if it can't fully convert the
* input string and/or the buffer is not large enough.
* @return 0 on success, -1 on failure.
*/
int qse_wcstombs_strict (
const qse_wchar_t* wcs,
qse_mchar_t* mbs,
qse_size_t mbslen
);
QSE_DEFINE_COMMON_FUNCTIONS (str)
qse_str_t* qse_str_open (
@ -545,201 +760,6 @@ qse_size_t qse_str_del (
qse_size_t size
);
/****f* Common/qse_strspl
* NAME
* qse_strspl - split a string into fields
* SEE ALSO
* qse_strspltrn
* SYNOPSIS
*/
int qse_strspl (
qse_char_t* str,
const qse_char_t* delim,
qse_char_t lquote,
qse_char_t rquote,
qse_char_t escape
);
/******/
/****f* Common/qse_strspltrn
* NAME
* qse_strspltrn - split a string translating special escape sequences
* DESCRIPTION
* The argument trset is a translation character set which is composed
* of multiple character pairs. An escape character followed by the
* first character in a pair is translated into the second character
* in the pair. If trset is QSE_NULL, no translation is performed.
* EXAMPLES
* Let's translate a sequence of '\n' and '\r' to a new line and a carriage
* return respectively.
* qse_strspltrn (str, QSE_T(':'), QSE_T('['), QSE_T(']'), QSE_T('\\'), QSE_T("n\nr\r"), &nfields);
* Given [xxx]:[\rabc\ndef]:[] as an input, the example breaks the second
* fields to <CR>abc<NL>def where <CR> is a carriage return and <NL> is a
* new line.
* SEE ALSO
* If you don't need any translation, you may call qse_strspl() alternatively.
* SYNOPSIS
*/
int qse_strspltrn (
qse_char_t* str,
const qse_char_t* delim,
qse_char_t lquote,
qse_char_t rquote,
qse_char_t escape,
const qse_char_t* trset
);
/******/
/****f* Common/qse_strtrm
* NAME
* qse_strtrm - remove leading and/or trailing spaces from a string
* DESCRIPTION
* The qse_strtrm() function removes leading spaces and/or trailing
* spaces from a string depending on the opt parameter. You can form
* the opt parameter by bitwise-OR'ing one or more of the following
* values.
* * QSE_STRTRM_LEFT - remove leading spaces
* * QSE_STRTRM_RIGHT - remove trailing spaces
* It returns the pointer to the trimmed string.
* NOTE
* Should it remove leading spaces, it just returns the pointer to
* the first non-space character in the string. Should it remove trailing
* spaces, it inserts a QSE_T('\0') character after the last non-space
* characters.
* EXAMPLES
* The example removes leading and trailing spaces from the string a.
* qse_char_t a[] = QSE_T(" this is a test string ");
* qse_printf (QSE_T("[%s]\n"), a);
* qse_printf (QSE_T("[%s]\n"), qse_strtrm (a, QSE_STRTRM_LEFT|QSE_STRTRM_RIGHT));
* SYNOPSIS
*/
qse_char_t* qse_strtrm (
qse_char_t* str,
int opt
);
/******/
/****f* Common/qse_mbstowcs
* NAME
* qse_mbstowcs - convert a multibyte string to a wide character string
* SYNOPSIS
*/
qse_size_t qse_mbstowcs (
const qse_mchar_t* mbs,
qse_wchar_t* wcs,
qse_size_t* wcslen
);
/******/
/****f* Common/qse_mbsntowcsn
* NAME
* qse_mbsntowcsn - convert a multibyte string to a wide character string
* RETURN
* The qse_mbstowcs() function returns the number of bytes handled.
* SYNOPSIS
*/
qse_size_t qse_mbsntowcsn (
const qse_mchar_t* mbs,
qse_size_t mbslen,
qse_wchar_t* wcs,
qse_size_t* wcslen
);
/******/
/****f* Common/qse_wcstombslen
* NAME
* qse_wcstombslen - get the length
* DESCRIPTION
* The qse_wcstombslen() function scans a null-terminated wide character
* string to get the total number of multibyte characters that it can be
* converted to. The resulting number of characters is stored into memory
* pointed to by mbslen.
* RETURN
* The qse_wcstombslen() function returns the number of wide characters
* handled.
* SYNOPSIS
*/
qse_size_t qse_wcstombslen (
const qse_wchar_t* wcs,
qse_size_t* mbslen
);
/******/
/****f* Common/qse_wcsntombsnlen
* NAME
* qse_wcsntombsnlen - get the length
* DESCRIPTION
* The qse_wcsntombsnlen() function scans a wide character wcs as long as
* wcslen characters to get the get the total number of multibyte characters
* that it can be converted to. The resulting number of characters is stored
* into memory pointed to by mbslen.
* RETURN
* The qse_wcsntombsnlen() function returns the number of wide characters
* handled.
* SYNOPSIS
*/
qse_size_t qse_wcsntombsnlen (
const qse_wchar_t* wcs,
qse_size_t wcslen,
qse_size_t* mbslen
);
/******/
/****f* Common/qse_wcstombs
* NAME
* qse_wcstombs - convert a wide character string to a multibyte string.
* DESCRIPTION
* The qse_wcstombs() function converts a null-terminated wide character
* string to a multibyte string and stores it into the buffer pointed to
* by mbs. The pointer to a variable holding the buffer length should be
* passed to the function as the third parameter. After conversion, it holds
* the length of the multibyte string excluding the terminating-null.
* It may not null-terminate the resulting multibyte string if the buffer
* is not large enough. You can check if the resulting mbslen is equal to
* the input mbslen to know it.
* RETURN
* The qse_wcstombs() function returns the number of wide characters handled.
* SYNOPSIS
*/
qse_size_t qse_wcstombs (
const qse_wchar_t* wcs,
qse_mchar_t* mbs,
qse_size_t* mbslen
);
/******/
/****f* Common/qse_wcsntombsn
* NAME
* qse_wcstombs - convert a wide character string to a multibyte string
* RETURN
* The qse_wcstombs() function returns the number of wide characters handled.
* SYNOPSIS
*/
qse_size_t qse_wcsntombsn (
const qse_wchar_t* wcs,
qse_size_t wcslen,
qse_mchar_t* mbs,
qse_size_t* mbslen
);
/******/
/****f* Common/qse_wcstombs_strict
* NAME
* qse_wcstombs_strict - convert a wide character string to a multibyte string.
* DESCRIPTION
* The qse_wcstombs_strict() function performs the same as the qse_wcsmbs()
* function except that it returns an error if it can't fully convert the
* input string and/or the buffer is not large enough.
* RETURN
* The qse_wcstombs_strict() function returns 0 on success and -1 on failure.
* SYNOPSIS
*/
int qse_wcstombs_strict (
const qse_wchar_t* wcs,
qse_mchar_t* mbs,
qse_size_t mbslen
);
/******/
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* $Id: macros.h 119 2009-04-02 07:09:10Z hyunghwan.chung $
* $Id: macros.h 140 2009-05-18 12:55:01Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
@ -19,6 +19,10 @@
#ifndef _QSE_MACROS_H_
#define _QSE_MACROS_H_
/** @file
* <qse/macros.h> contains various useful macro definitions.
*/
#include <qse/types.h>
#ifdef __cplusplus
@ -39,25 +43,48 @@
#define QSE_WCHAR_EOF ((qse_wcint_t)-1)
#define QSE_CHAR_EOF ((qse_cint_t)-1)
/****m* Base/QSE_SIZEOF
* NAME
* QSE_SIZEOF - get data size in bytes
* SYNOPSIS
/**
* The QSE_SIZEOF() macro gets data size in bytes. It is equivalent to the
* sizeof operator. The following code snippet should print sizeof(int)*128.
* @code
* int x[128];
* printf ("%d\n", (int)QSE_SIZEOF(x));
* @endcode
*/
#define QSE_SIZEOF(n) (sizeof(n))
/******/
/****m* Base/QSE_COUNTOF
* NAME
* QSE_COUNTOF - get the number elements in a array
* SYNOPSIS
/**
* The QSE_COUNTOF() macro gets the number elements in a array.
* The following code snippet should print 128.
* @code
* int x[128];
* printf ("%d\n", (int)QSE_COUNTOF(x));
* @endcode
*/
#define QSE_COUNTOF(n) (sizeof(n)/sizeof(n[0]))
/******/
/**
* The QSE_OFFSETOF() macro get the offset of a fields from the beginning
* of a structure.
*/
#define QSE_OFFSETOF(type,member) ((qse_size_t)&((type*)0)->member)
/**
* The QSE_TYPE_IS_SIGNED() macro determines if a type is signed.
* @code
* printf ("%d\n", QSE_TYPE_IS_SIGNED(int));
* printf ("%d\n", QSE_TYPE_IS_SIGNED(unsigned int));
* @endcode
*/
#define QSE_TYPE_IS_SIGNED(type) (((type)0) > ((type)-1))
/**
* The QSE_TYPE_IS_SIGNED() macro determines if a type is unsigned.
* @code
* printf ("%d\n", QSE_TYPE_IS_UNSIGNED(int));
* printf ("%d\n", QSE_TYPE_IS_UNSIGNED(unsigned int));
* @endcode
*/
#define QSE_TYPE_IS_UNSIGNED(type) (((type)0) < ((type)-1))
#define QSE_TYPE_SIGNED_MAX(type) \
@ -168,50 +195,35 @@
# define QSE_END_NAMESPACE2(y,x) }}
#endif
/****m* Base/QSE_DEFINE_COMMON_FIELDS
* NAME
* QSE_DEFINE_COMMON_FIELDS - define common fields
* SYNOPSIS
/**
* The QSE_DEFINE_COMMON_FIELDS() macro defines common object fields.
*/
#define QSE_DEFINE_COMMON_FIELDS(name) \
qse_mmgr_t* mmgr;
/******/
/****m* Base/QSE_DEFINE_COMMON_FUNCTIONS
* NAME
* QSE_DEFINE_COMMON_FUNCTIONS - define common functions
* SYNOPSIS
/**
* The QSE_DEFINE_COMMON_FUNcTIONS() macro defines common object functions.
*/
#define QSE_DEFINE_COMMON_FUNCTIONS(name) \
void qse_##name##_setmmgr (qse_##name##_t* name, qse_mmgr_t* mmgr); \
qse_mmgr_t* qse_##name##_getmmgr (qse_##name##_t* name); \
void* qse_##name##_getxtn (qse_##name##_t* name);
/******/
/****m* Base/QSE_MMGR
* NAME
* QSE_MMGR - get the memory manager field
* SYNOPSIS
/**
* The QSE_MMGR() macro gets the memory manager field from an object.
*/
#define QSE_MMGR(obj) (obj->mmgr)
/******/
#define QSE_MMGR(obj) ((obj)->mmgr)
/****m* Base/QSE_XTN
* NAME
* QSE_XTN - get a pointer to extension space
* DESCRIPTION
* The QSE_XTN() macro is a convenience macro to retrieve the pointer to
* extension space located at the end of an object. The type of the object
* should be known in advance for it to work properly.
* SYNOPSIS
/**
* The QSE_XTN() macro is a convenience macro to retrieve the pointer to
* extension space located at the end of an object. The type of the object
* should be known in advance for it to work properly.
*/
#define QSE_XTN(obj) ((void*)(obj + 1))
/******/
/****m* Base/QSE_IMPLEMENT_COMMON_FUNCTIONS
* NAME
* QSE_IMPLEMENT_COMMON_FUNCTIONS - implement common functions
* SYNOPSIS
/**
* The QSE_IMPLEMENT_COMMON_FUNCTIONS() implement common functions for
* an object.
*/
#define QSE_IMPLEMENT_COMMON_FUNCTIONS(name) \
void qse_##name##_setmmgr (qse_##name##_t* name, qse_mmgr_t* mmgr) \
@ -226,7 +238,5 @@ void* qse_##name##_getxtn (qse_##name##_t* name) \
{ \
return QSE_XTN(name); \
}
/******/
#endif

View File

@ -25,52 +25,74 @@
#include <qse/cmn/lda.h>
#include <qse/cmn/map.h>
/** @file
* A stream editor performs text transformation on a text stream.
*
* @code
* sed = qse_sed_open ();
* qse_sed_comp (sed);
* qse_sed_exec (sed);
* qse_sed_close (sed);
* @endcode
*
* @example sed01.c
* This example shows how to embed a basic stream editor.
*/
/**
* defines error numbers
*/
enum qse_sed_errnum_t
{
QSE_SED_ENOERR, /* no error */
QSE_SED_ENOMEM, /* no memory */
QSE_SED_ETMTXT, /* too much text */
QSE_SED_ECMDNR, /* command not recognized */
QSE_SED_ECMDMS, /* command missing */
QSE_SED_ECMDGB, /* command garbled */
QSE_SED_EREXBL, /* regular expression build error */
QSE_SED_EREXMA, /* regular expression match error */
QSE_SED_EA1PHB, /* address 1 prohibited */
QSE_SED_EA2PHB, /* address 2 prohibited */
QSE_SED_ENEWLN, /* a new line is expected */
QSE_SED_EBSEXP, /* \ is expected */
QSE_SED_EBSDEL, /* \ used a delimiter */
QSE_SED_EGBABS, /* garbage after \ */
QSE_SED_ESCEXP, /* ; is expected */
QSE_SED_ELABTL, /* label too long */
QSE_SED_ELABEM, /* label name is empty */
QSE_SED_ELABDU, /* duplicate label name */
QSE_SED_ELABNF, /* label not found */
QSE_SED_EFILEM, /* file name is empty */
QSE_SED_EFILIL, /* illegal file name */
QSE_SED_ENOTRM, /* not terminated properly */
QSE_SED_ETSNSL, /* translation set not the same length*/
QSE_SED_EGRNBA, /* group brackets not balanced */
QSE_SED_EGRNTD, /* group nested too deeply */
QSE_SED_EOCSDU, /* multiple occurrence specifiers */
QSE_SED_EOCSZE, /* occurrence specifier to s is zero */
QSE_SED_EOCSTL, /* occurrence specifier too large */
QSE_SED_EIOUSR /* user io error */
QSE_SED_ENOERR, /**< no error occurred */
QSE_SED_ENOMEM, /**< insufficient memory is available */
QSE_SED_ETMTXT, /**< too much text */
QSE_SED_ECMDNR, /**< a command is not recognized */
QSE_SED_ECMDMS, /**< a command is missing */
QSE_SED_ECMDGB, /**< command garbled */
QSE_SED_EREXBL, /**< regular expression build error */
QSE_SED_EREXMA, /**< regular expression match error */
QSE_SED_EA1PHB, /**< address 1 prohibited */
QSE_SED_EA2PHB, /**< address 2 prohibited */
QSE_SED_ENEWLN, /**< a new line is expected */
QSE_SED_EBSEXP, /**< \ is expected */
QSE_SED_EBSDEL, /**< \ used a delimiter */
QSE_SED_EGBABS, /**< garbage after \ */
QSE_SED_ESCEXP, /**< ; is expected */
QSE_SED_ELABTL, /**< label too long */
QSE_SED_ELABEM, /**< label name is empty */
QSE_SED_ELABDU, /**< duplicate label name */
QSE_SED_ELABNF, /**< label not found */
QSE_SED_EFILEM, /**< file name is empty */
QSE_SED_EFILIL, /**< illegal file name */
QSE_SED_ENOTRM, /**< not terminated properly */
QSE_SED_ETSNSL, /**< translation set not the same length*/
QSE_SED_EGRNBA, /**< group brackets not balanced */
QSE_SED_EGRNTD, /**< group nested too deeply */
QSE_SED_EOCSDU, /**< multiple occurrence specifiers */
QSE_SED_EOCSZE, /**< occurrence specifier to s is zero */
QSE_SED_EOCSTL, /**< occurrence specifier too large */
QSE_SED_EIOUSR /**< user io error */
};
typedef enum qse_sed_errnum_t qse_sed_errnum_t;
/**
* The qse_sed_option_t type defines various option codes for a stream editor.
* Options can be XOR'ed with each other and be passed to a stream editor with
* the qse_sed_setoption() function.
*/
enum qse_sed_option_t
{
QSE_SED_STRIPLS = (1 << 0), /* strip leading spaces from text*/
QSE_SED_KEEPTBS = (1 << 1), /* keep an trailing backslash */
QSE_SED_ENSURENL = (1 << 2), /* ensure NL at the text end */
QSE_SED_QUIET = (1 << 3), /* do not print pattern space */
QSE_SED_CLASSIC = (1 << 4)
QSE_SED_STRIPLS = (1 << 0), /**< strip leading spaces from text */
QSE_SED_KEEPTBS = (1 << 1), /**< keep an trailing backslash */
QSE_SED_ENSURENL = (1 << 2), /**< ensure NL at the text end */
QSE_SED_QUIET = (1 << 3), /**< do not print pattern space */
QSE_SED_CLASSIC = (1 << 4) /**< disable extended features */
};
/****e* AWK/qse_sed_io_cmd_t
* NAME
* qse_sed_io_cmd_t - define IO commands
* SYNOPSIS
/**
* The qse_sed_io_cmd_t type defines IO command codes. The code indicates
* the action to take in an IO handler.
*/
enum qse_sed_io_cmd_t
{
@ -80,8 +102,10 @@ enum qse_sed_io_cmd_t
QSE_SED_IO_WRITE = 3
};
typedef enum qse_sed_io_cmd_t qse_sed_io_cmd_t;
/******/
/**
* The qse_sed_io_arg_t type defines a data structure required by an IO handler.
*/
union qse_sed_io_arg_t
{
struct
@ -113,34 +137,43 @@ typedef union qse_sed_io_arg_t qse_sed_io_arg_t;
typedef struct qse_sed_t qse_sed_t;
/**
* The qse_sed_cmd_t type represents a compiled form of a stream editor
* command. The details are hidden.
*/
typedef struct qse_sed_cmd_t qse_sed_cmd_t;
/**
* The qse_sed_iof_t type defines an IO handler. An IO handler is called by
* qse_sed_execute().
*/
typedef qse_ssize_t (*qse_sed_iof_t) (
qse_sed_t* sed,
qse_sed_io_cmd_t cmd,
qse_sed_io_arg_t* arg
);
typedef struct qse_sed_cmd_t qse_sed_cmd_t; /* command */
typedef enum qse_sed_errnum_t qse_sed_errnum_t;
/**
* The qse_sed_t type defines a stream editor
*/
struct qse_sed_t
{
QSE_DEFINE_COMMON_FIELDS (sed)
qse_sed_errnum_t errnum;
int option;
/* source code pointers */
qse_sed_errnum_t errnum; /**< stores an error number */
int option; /**< stores options */
/** source text pointers */
struct
{
const qse_char_t* ptr;
const qse_char_t* end;
const qse_char_t* cur;
const qse_char_t* ptr; /**< beginning of the source text */
const qse_char_t* end; /**< end of the source text */
const qse_char_t* cur; /**< current source text pointer */
} src;
void* lastrex;
qse_str_t rexbuf; /* temporary regular expression buffer */
qse_str_t rexbuf; /**< temporary regular expression buffer */
/* command array */
/*qse_lda_t cmds;*/
struct
{
qse_sed_cmd_t* buf;
@ -148,23 +181,25 @@ struct qse_sed_t
qse_sed_cmd_t* cur;
} cmd;
qse_map_t labs; /* label map */
/** a table storing labels seen */
qse_map_t labs;
struct
{
/* current level of command group nesting */
/** current level of command group nesting */
int level;
/* temporary storage to keep track of the begining of a command group */
/** keeps track of the begining of a command group */
qse_sed_cmd_t* cmd[128];
} grp;
/* data for execution */
/** data for execution */
struct
{
/** data needed for output streams and files */
struct
{
qse_sed_iof_t f;
qse_sed_io_arg_t arg;
qse_sed_iof_t f; /**< an output handler */
qse_sed_io_arg_t arg; /**< output handling data */
qse_char_t buf[2048];
qse_size_t len;
@ -178,23 +213,25 @@ struct qse_sed_t
/*****************************************************/
} out;
/** data needed for input streams */
struct
{
qse_sed_iof_t f;
qse_sed_io_arg_t arg;
qse_sed_iof_t f; /**< an input handler */
qse_sed_io_arg_t arg; /**< input handling data */
qse_char_t xbuf[1];
int xbuf_len;
qse_char_t xbuf[1]; /**< a read-ahead buffer */
int xbuf_len; /**< data length in the buffer */
qse_char_t buf[2048];
qse_size_t len;
qse_size_t pos;
int eof;
qse_char_t buf[2048]; /**< input buffer */
qse_size_t len; /**< data length in the buffer */
qse_size_t pos; /**< current position in the buffer */
int eof; /**< EOF indicator */
qse_str_t line;
qse_size_t num;
qse_str_t line; /**< pattern space */
qse_size_t num; /**< current line number */
} in;
/** text buffers */
struct
{
qse_lda_t appended;
@ -203,100 +240,94 @@ struct qse_sed_t
qse_str_t subst;
} txt;
/** indicates if a successful substitution has been made
* since the last read on the input stream.
*/
int subst_done;
} e;
};
#ifdef __cplusplus
extern "C" {
#endif
QSE_DEFINE_COMMON_FUNCTIONS (sed)
/****f* Text Processor/qse_sed_open
* NAME
* qse_sed_open - create a stream editor
* SYNOPSIS
/**
* The qse_sed_open() function creates a stream editor.
* @return A pointer to a stream editor on success, QSE_NULL on a failure
*/
qse_sed_t* qse_sed_open (
qse_mmgr_t* mmgr,
qse_size_t xtn
qse_mmgr_t* mmgr, /**< a memory manager */
qse_size_t xtn /**< the size of extension in bytes */
);
/******/
/****f* Text Processor/qse_sed_close
* NAME
* qse_sed_close - destroy a stream editor
* SYNOPSIS
/**
* The qse_sed_close() function destroyes a stream editor.
*/
void qse_sed_close (
qse_sed_t* sed
qse_sed_t* sed /**< a stream editor */
);
/******/
/****f* Text Processor/qse_sed_init
* NAME
* qse_sed_init - initialize a stream editor
* SYNOPSIS
/**
* The qse_sed_init() function initializes a stream editor.
*/
qse_sed_t* qse_sed_init (
qse_sed_t* sed,
qse_mmgr_t* mmgr
qse_sed_t* sed, /**< a stream editor */
qse_mmgr_t* mmgr /**< a memory manager */
);
/******/
/****f* Text Processor/qse_sed_fini
* NAME
* qse_sed_fini - finalize a stream editor
* SYNOPSIS
/**
* The qse_sed_init() function finalizes a stream editor.
*/
void qse_sed_fini (
qse_sed_t* sed
qse_sed_t* sed /**< a stream editor */
);
/******/
/****f* Text Processor/qse_sed_getoption
* NAME
* qse_sed_getoption - get option
* SYNOPSIS
/**
* The qse_sed_getoption() function retrieves the current options set in
* a stream editor.
* @return 0 or a number XOR'ed of qse_sed_option_t values
*/
int qse_sed_getoption (
qse_sed_t* sed
qse_sed_t* sed /**< a stream editor */
);
/******/
/****f* Text Processor/qse_sed_setoption
* NAME
* qse_sed_setoption - set option
* SYNOPSIS
/**
* The qse_sed_setoption() function sets the option code.
*/
void qse_sed_setoption (
qse_sed_t* sed,
int option
qse_sed_t* sed, /**< a stream editor */
int opt /**< 0 or a number XOR'ed of qse_sed_option_t values */
);
/*****/
/****f* Text Processor/qse_sed_geterrmsg
* NAME
* qse_sed_geterrmsg - get an error message
* SYNOPSIS
/**
* The qse_sed_geterrmsg() function retrieves an error message
* @return a pointer to a string describing an error occurred
*/
const qse_char_t* qse_sed_geterrmsg (
qse_sed_t* sed
);
/******/
int qse_sed_compile (
qse_sed_t* sed,
const qse_char_t* sptr,
qse_size_t slen
qse_sed_t* sed /**< a stream editor */
);
int qse_sed_execute (
qse_sed_t* sed,
qse_sed_iof_t inf,
qse_sed_iof_t outf
/**
* The qse_sed_comp() function compiles stream editor commands into an
* internal form.
* @return 0 on success, -1 on error
*/
int qse_sed_comp (
qse_sed_t* sed, /**< a stream editor */
const qse_char_t* ptr, /**< a pointer to a string containing commands */
qse_size_t len /**< the number of characters in the string */
);
/**
* The qse_sed_exec() function executes the compiled commands.
* @return 0 on success, -1 on error
*/
int qse_sed_exec (
qse_sed_t* sed, /**< a stream editor */
qse_sed_iof_t in, /**< stream reader */
qse_sed_iof_t out /**< stream writer */
);
#ifdef __cplusplus

View File

@ -1268,7 +1268,7 @@ static int compile_source (
return 0;
}
int qse_sed_compile (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen)
int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen)
{
return compile_source (sed, sptr, slen);
}
@ -1392,11 +1392,13 @@ static int read_line (qse_sed_t* sed, int append)
if (!append) qse_str_clear (&sed->e.in.line);
if (sed->e.in.eof)
{
#if 0
/* no more input detected in the previous read.
* set eof back to 0 here so that read_char() is called
* if read_line() is called again. that way, the result
* of subsequent calls counts on read_char(). */
sed->e.in.eof = 0;
#endif
return 0;
}
@ -1406,8 +1408,9 @@ static int read_line (qse_sed_t* sed, int append)
if (n <= -1) return -1;
if (n == 0)
{
if (len == 0) return 0;
sed->e.in.eof = 1;
if (len == 0) return 0;
/*sed->e.in.eof = 1;*/
break;
}
@ -2052,18 +2055,15 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
sed->errnum = QSE_SED_ENOMEM;
return QSE_NULL;
}
/* move past the last command so as to start
* the next cycle */
jumpto = sed->cmd.cur;
}
else
{
/* TODO: prearrange for CHANGE to be executed on the lastline wihtout
matchng the second address */
qse_str_clear (&sed->e.in.line);
}
/* move past the last command so as to start
* the next cycle */
jumpto = sed->cmd.cur;
break;
case QSE_SED_CMD_DELETE_FIRSTLN:
@ -2077,12 +2077,22 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
QSE_T('\n'));
if (nl != QSE_NULL)
{
/* if a new line is found */
/* if a new line is found. delete up to it */
qse_str_del (&sed->e.in.line, 0,
nl - QSE_STR_PTR(&sed->e.in.line) + 1);
/* arrange to start the the next cycle */
jumpto = sed->cmd.cur;
if (QSE_STR_LEN(&sed->e.in.line) > 0)
{
/* if the pattern space is not empty,
* arrange to execute from the first
* command */
jumpto = sed->cmd.cur + 2;
}
else
{
/* arrange to start the the next cycle */
jumpto = sed->cmd.cur;
}
break;
}
@ -2191,8 +2201,9 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
if (n <= -1) return QSE_NULL;
if (n == 0)
{
/* eof is reached. quit */
jumpto = sed->cmd.cur + 1;
/* EOF is reached. */
/*jumpto = sed->cmd.cur + 1;*/
jumpto = sed->cmd.cur;
}
break;
@ -2202,8 +2213,9 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
if (n <= -1) return QSE_NULL;
if (n == 0)
{
/* eof is reached. quit */
jumpto = sed->cmd.cur + 1;
/* EOF is reached. */
/*jumpto = sed->cmd.cur + 1;*/
jumpto = sed->cmd.cur;
}
break;
@ -2333,7 +2345,7 @@ static void close_outfile (qse_map_t* map, void* dptr, qse_size_t dlen)
}
}
int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
int qse_sed_exec (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
{
qse_sed_cmd_t* c, * j;
qse_ssize_t n;
@ -2455,6 +2467,7 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
qse_lda_clear (&sed->e.txt.appended);
qse_str_clear (&sed->e.txt.read);
again:
c = sed->cmd.buf;
while (c < sed->cmd.cur)
{
@ -2470,25 +2483,24 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
j = exec_cmd (sed, c);
if (j == QSE_NULL) { ret = -1; goto done; }
if (j > sed->cmd.cur)
{
/* finish the current cycle */
QSE_ASSERT (j == sed->cmd.cur + 1);
goto done;
}
if (j == sed->cmd.cur + 1) goto done;
if (j == sed->cmd.cur + 2) goto again;
QSE_ASSERT (j <= sed->cmd.cur);
/* go to the next command */
c = j;
}
if (!(sed->option & QSE_SED_QUIET))
{
/* write the pattern space */
n = write_str (sed,
QSE_STR_PTR(&sed->e.in.line),
QSE_STR_LEN(&sed->e.in.line));
if (n <= -1) { ret = -1; goto done; }
}
/* write text read in by the r command */
n = write_str (
sed,
QSE_STR_PTR(&sed->e.txt.read),
@ -2496,6 +2508,7 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
);
if (n <= -1) { ret = -1; goto done; }
/* write appeneded text by the a command */
for (i = 0; i < QSE_LDA_SIZE(&sed->e.txt.appended); i++)
{
qse_xstr_t* t = QSE_LDA_DPTR(&sed->e.txt.appended, i);

View File

@ -16,10 +16,6 @@
limitations under the License.
*/
/****S* SED/Simple Example
* SOURCE
*/
#include <qse/utl/sed.h>
#include <qse/utl/stdio.h>
#include <qse/utl/main.h>
@ -119,7 +115,7 @@ int sed_main (int argc, qse_char_t* argv[])
if (argc == 3) qse_sed_setoption (sed, qse_strtoi(argv[2]));
if (qse_sed_compile (sed, argv[1], qse_strlen(argv[1])) == -1)
if (qse_sed_comp (sed, argv[1], qse_strlen(argv[1])) == -1)
{
qse_fprintf (QSE_STDERR,
QSE_T("cannot compile - %s\n"),
@ -128,7 +124,7 @@ int sed_main (int argc, qse_char_t* argv[])
goto oops;
}
if (qse_sed_execute (sed, in, out) == -1)
if (qse_sed_exec (sed, in, out) == -1)
{
qse_fprintf (QSE_STDERR,
QSE_T("cannot execute - %s\n"),
@ -148,5 +144,3 @@ int qse_main (int argc, char* argv[])
{
return qse_runmain (argc, argv, sed_main);
}
/******/