added more commands

This commit is contained in:
hyung-hwan 2009-05-14 07:22:36 +00:00
parent a512a77bba
commit b0c9b08d56
4 changed files with 309 additions and 67 deletions

View File

@ -67,6 +67,11 @@ enum qse_sed_option_t
QSE_SED_CLASSIC = (1 << 4)
};
/****e* AWK/qse_sed_io_cmd_t
* NAME
* qse_sed_io_cmd_t - define IO commands
* SYNOPSIS
*/
enum qse_sed_io_cmd_t
{
QSE_SED_IO_OPEN = 0,
@ -74,16 +79,44 @@ enum qse_sed_io_cmd_t
QSE_SED_IO_READ = 2,
QSE_SED_IO_WRITE = 3
};
typedef enum qse_sed_io_cmd_t qse_sed_io_cmd_t;
/******/
union qse_sed_io_arg_t
{
struct
{
void* handle; /* out */
const qse_char_t* path; /* in */
} open;
struct
{
void* handle; /* in */
qse_char_t* buf; /* out */
qse_size_t len; /* in */
} read;
struct
{
void* handle; /* in */
const qse_char_t* data; /* in */
qse_size_t len; /* in */
} write;
struct
{
void* handle; /* in */
} close;
};
typedef union qse_sed_io_arg_t qse_sed_io_arg_t;
typedef struct qse_sed_t qse_sed_t;
typedef qse_ssize_t (*qse_sed_iof_t) (
qse_sed_t* sed,
qse_sed_io_cmd_t cmd,
qse_char_t* data,
qse_size_t count
qse_sed_io_arg_t* arg
);
typedef struct qse_sed_cmd_t qse_sed_cmd_t; /* command */
@ -128,15 +161,19 @@ struct qse_sed_t
struct
{
qse_sed_iof_t f;
qse_sed_io_arg_t arg;
qse_char_t buf[2048];
qse_size_t len;
int eof;
qse_map_t files;
} out;
struct
{
qse_sed_iof_t f;
qse_sed_io_arg_t arg;
qse_char_t xbuf[1];
int xbuf_len;
@ -149,6 +186,7 @@ struct qse_sed_t
qse_str_t line;
qse_size_t num;
} in;
} eio;
struct

View File

@ -62,7 +62,7 @@ void qse_sed_close (qse_sed_t* sed)
qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr)
{
QSE_MEMSET (sed, 0, sizeof(*sed));
QSE_MEMSET (sed, 0, QSE_SIZEOF(*sed));
sed->mmgr = mmgr;
if (qse_str_init (&sed->rexbuf, mmgr, 0) == QSE_NULL)
@ -246,13 +246,16 @@ static void free_command (qse_sed_t* sed, qse_sed_cmd_t* cmd)
QSE_MMGR_FREE (sed->mmgr, cmd->u.transet.ptr);
break;
case QSE_SED_CMD_R:
case QSE_SED_CMD_RR:
case QSE_SED_CMD_W:
case QSE_SED_CMD_WW:
case QSE_SED_CMD_READ_FILE:
case QSE_SED_CMD_READ_FILELN:
case QSE_SED_CMD_WRITE_FILE:
case QSE_SED_CMD_WRITE_FILELN:
if (cmd->u.file.ptr != QSE_NULL)
QSE_MMGR_FREE (sed->mmgr, cmd->u.file.ptr);
break;
default:
break;
}
}
@ -1279,11 +1282,11 @@ static int read_char (qse_sed_t* sed, qse_char_t* c)
{
if (sed->eio.in.pos >= sed->eio.in.len)
{
sed->eio.in.arg.read.buf = sed->eio.in.buf;
sed->eio.in.arg.read.len = QSE_COUNTOF(sed->eio.in.buf);
n = sed->eio.in.f (
sed, QSE_SED_IO_READ,
sed->eio.in.buf, QSE_COUNTOF(sed->eio.in.buf)
sed, QSE_SED_IO_READ, &sed->eio.in.arg
);
if (n <= -1)
{
sed->errnum = QSE_SED_EIOUSR;
@ -1312,12 +1315,13 @@ static int read_char (qse_sed_t* sed, qse_char_t* c)
}
}
static int read_line (qse_sed_t* sed)
static int read_line (qse_sed_t* sed, int append)
{
qse_size_t len = 0;
qse_char_t c;
int n;
qse_str_clear (&sed->eio.in.line);
if (!append) qse_str_clear (&sed->eio.in.line);
if (sed->eio.in.eof)
{
/* no more input detected in the previous read.
@ -1334,7 +1338,7 @@ static int read_line (qse_sed_t* sed)
if (n <= -1) return -1;
if (n == 0)
{
if (QSE_STR_LEN(&sed->eio.in.line) == 0) return 0;
if (len == 0) return 0;
sed->eio.in.eof = 1;
break;
}
@ -1344,8 +1348,9 @@ static int read_line (qse_sed_t* sed)
sed->errnum = QSE_SED_ENOMEM;
return -1;
}
len++;
// TODO: different line convenstion
// TODO: support different line end convension
if (c == QSE_T('\n')) break;
}
@ -1360,10 +1365,9 @@ static int flush (qse_sed_t* sed)
while (sed->eio.out.len > 0)
{
n = sed->eio.out.f (
sed, QSE_SED_IO_WRITE,
&sed->eio.out.buf[pos], sed->eio.out.len
);
sed->eio.out.arg.write.data = &sed->eio.out.buf[pos];
sed->eio.out.arg.write.len = sed->eio.out.len;
n = sed->eio.out.f (sed, QSE_SED_IO_WRITE, &sed->eio.out.arg);
if (n <= -1)
{
@ -1405,13 +1409,27 @@ static int write_str (qse_sed_t* sed, const qse_char_t* str, qse_size_t len)
return 0;
}
static int write_num (qse_sed_t* sed, qse_size_t x, int base, int width)
static int write_first_line (
qse_sed_t* sed, const qse_char_t* str, qse_size_t len)
{
qse_size_t last = x % base;
qse_size_t y = 0;
qse_size_t i;
for (i = 0; i < len; i++)
{
if (write_char (sed, str[i]) <= -1) return -1;
/* TODO: handle different line ending scheme... */
if (str[i] == QSE_T('\n')) break;
}
return 0;
}
#define NTOC(n) (((n) >= 10)? (((n) - 10) + QSE_T('A')): (n) + QSE_T('0'))
static int write_num (qse_sed_t* sed, qse_ulong_t x, int base, int width)
{
qse_ulong_t last = x % base;
qse_ulong_t y = 0;
int dig = 0;
QSE_ASSERT (base >= 2 && base <= 10);
QSE_ASSERT (base >= 2 && base <= 36);
if (x < 0)
{
@ -1439,7 +1457,7 @@ static int write_num (qse_sed_t* sed, qse_size_t x, int base, int width)
while (y > 0)
{
if (write_char (sed, (y % base) + QSE_T('0')) <= -1) return -1;
if (write_char (sed, NTOC(y % base)) <= -1) return -1;
y = y / base;
dig--;
}
@ -1450,7 +1468,7 @@ static int write_num (qse_sed_t* sed, qse_size_t x, int base, int width)
if (write_char (sed, QSE_T('0')) <= -1) return -1;
}
if (last < 0) last = -last;
if (write_char (sed, last + QSE_T('0')) <= -1) return -1;
if (write_char (sed, NTOC(last)) <= -1) return -1;
return 0;
}
@ -1507,13 +1525,20 @@ static int write_str_clearly (
if (QSE_ISPRINT(c)) WRITE_CHAR (sed, c);
else
{
qse_size_t i;
qse_byte_t* b = (qse_byte_t*)&c;
# ifdef QSE_CHAR_IS_MCHAR
WRITE_CHAR (sed, QSE_T('\\'));
for (i = 0; i < QSE_SIZEOF(c)/QSE_SIZEOF(*b); i++)
WRITE_NUM (sed, c, 8, QSE_SIZEOF(qse_char_t)*3);
# else
if (QSE_SIZEOF(qse_char_t) <= 2)
{
WRITE_NUM (sed, b[i], 8, 3);
WRITE_STR (sed, QSE_T("\\u"), 2);
}
else
{
WRITE_STR (sed, QSE_T("\\U"), 2);
}
WRITE_NUM (sed, c, 16, QSE_SIZEOF(qse_char_t)*2);
# endif
}
}
}
@ -1525,6 +1550,60 @@ static int write_str_clearly (
return 0;
}
static int write_str_to_file (
qse_sed_t* sed, const qse_char_t* str, qse_size_t len,
const qse_char_t* path, qse_size_t plen)
{
qse_ssize_t n;
qse_map_pair_t* pair;
qse_sed_io_arg_t* ap;
pair = qse_map_search (&sed->eio.out.files, path, plen);
if (pair == QSE_NULL)
{
qse_sed_io_arg_t arg;
QSE_MEMSET (&arg, 0, QSE_SIZEOF(arg));
pair = qse_map_insert (&sed->eio.out.files,
path, plen, &arg, QSE_SIZEOF(arg));
if (pair == QSE_NULL)
{
sed->errnum = QSE_SED_ENOMEM;
return -1;
}
}
ap = QSE_MAP_VPTR(pair);
if (ap->open.handle == QSE_NULL)
{
ap->open.path = path;
n = sed->eio.out.f (sed, QSE_SED_IO_OPEN, ap);
if (n <= -1)
{
sed->errnum = QSE_SED_EIOUSR;
return -1;
}
// TOOD: what if n is 0???
}
while (len > 0)
{
ap->write.data = str;
ap->write.len = len;
n = sed->eio.out.f (sed, QSE_SED_IO_WRITE, ap);
if (n <= -1)
{
sed->errnum = QSE_SED_EIOUSR;
return -1;
}
// TODO: what if n is 0???
len -= n;
}
return 0;
}
static int match_a (qse_sed_t* sed, qse_sed_a_t* a)
{
switch (a->type)
@ -1592,10 +1671,11 @@ static int match_a (qse_sed_t* sed, qse_sed_a_t* a)
return 0;
}
}
}
default:
QSE_ASSERT (a->type == QSE_SED_A_NONE);
return 1; /* match */
}
}
/* match an address against input.
@ -1713,7 +1793,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
case QSE_SED_CMD_CHANGE:
if (cmd->state.c_ready)
{
/* change the input space */
/* change the pattern space */
n = qse_str_ncpy (
&sed->eio.in.line,
QSE_STR_PTR(&cmd->u.text),
@ -1738,14 +1818,14 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
break;
case QSE_SED_CMD_DELETE:
/* delete the input space */
/* delete the pattern space */
qse_str_clear (&sed->eio.in.line);
/* move past the last command so as to start
* the next cycle */
jumpto = sed->cmd.cur;
break;
case QSE_SED_CMD_PRINT_LNUM:
case QSE_SED_CMD_PRINT_LNNUM:
if (write_num (sed, sed->eio.in.num, 10, 0) <= -1) return QSE_NULL;
if (write_char (sed, QSE_T('\n')) <= -1) return QSE_NULL;
break;
@ -1759,6 +1839,15 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
if (n <= -1) return QSE_NULL;
break;
case QSE_SED_CMD_PRINT_FIRSTLN:
n = write_first_line (
sed,
QSE_STR_PTR(&sed->eio.in.line),
QSE_STR_LEN(&sed->eio.in.line)
);
if (n <= -1) return QSE_NULL;
break;
case QSE_SED_CMD_PRINT_CLEARLY:
n = write_str_clearly (
sed,
@ -1769,6 +1858,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
break;
case QSE_SED_CMD_HOLD:
/* copy the pattern space to the hold space */
if (qse_str_ncpy (&sed->text.held,
QSE_STR_PTR(&sed->eio.in.line),
QSE_STR_LEN(&sed->eio.in.line)) == (qse_size_t)-1)
@ -1779,6 +1869,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
break;
case QSE_SED_CMD_HOLD_APPEND:
/* append the pattern space to the hold space */
if (qse_str_ncat (&sed->text.held,
QSE_STR_PTR(&sed->eio.in.line),
QSE_STR_LEN(&sed->eio.in.line)) == (qse_size_t)-1)
@ -1789,6 +1880,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
break;
case QSE_SED_CMD_RELEASE:
/* copy the hold space to the pattern space */
if (qse_str_ncpy (&sed->eio.in.line,
QSE_STR_PTR(&sed->text.held),
QSE_STR_LEN(&sed->text.held)) == (qse_size_t)-1)
@ -1798,11 +1890,8 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
}
break;
case QSE_SED_CMD_EXCHANGE:
qse_str_swap (&sed->eio.in.line, &sed->text.held);
break;
case QSE_SED_CMD_RELEASE_APPEND:
/* append the hold space to the pattern space */
if (qse_str_ncat (&sed->eio.in.line,
QSE_STR_PTR(&sed->text.held),
QSE_STR_LEN(&sed->text.held)) == (qse_size_t)-1)
@ -1812,6 +1901,69 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
}
break;
case QSE_SED_CMD_EXCHANGE:
/* exchange the pattern space and the hold space */
qse_str_swap (&sed->eio.in.line, &sed->text.held);
break;
case QSE_SED_CMD_NEXT:
/* output the current pattern space */
n = write_str (
sed,
QSE_STR_PTR(&sed->eio.in.line),
QSE_STR_LEN(&sed->eio.in.line)
);
if (n <= -1) return QSE_NULL;
/* read the next line and fill the pattern space */
n = read_line (sed, 0);
if (n <= -1) return QSE_NULL;
if (n == 0)
{
/* eof is reached. quit */
jumpto = sed->cmd.cur + 1;
}
break;
case QSE_SED_CMD_NEXT_APPEND:
/* append the next line to the pattern space */
n = read_line (sed, 1);
if (n <= -1) return QSE_NULL;
if (n == 0)
{
/* eof is reached. quit */
jumpto = sed->cmd.cur + 1;
}
break;
case QSE_SED_CMD_READ_FILE:
break;
case QSE_SED_CMD_READ_FILELN:
break;
case QSE_SED_CMD_WRITE_FILE:
n = write_str_to_file (
sed,
QSE_STR_PTR(&sed->eio.in.line),
QSE_STR_LEN(&sed->eio.in.line),
cmd->u.file.ptr,
cmd->u.file.len
);
if (n <= -1) return QSE_NULL;
break;
case QSE_SED_CMD_WRITE_FILELN:
n = write_str_to_file (
sed,
QSE_STR_PTR(&sed->eio.in.line),
QSE_STR_LEN(&sed->eio.in.line),
cmd->u.file.ptr,
cmd->u.file.len
);
if (n <= -1) return QSE_NULL;
break;
case QSE_SED_CMD_BRANCH:
if (cmd->u.branch.target == QSE_NULL)
{
@ -1838,6 +1990,18 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
return jumpto;
}
static void close_outfile (qse_map_t* map, void* dptr, qse_size_t dlen)
{
qse_sed_io_arg_t* arg = dptr;
QSE_ASSERT (dlen = QSE_SIZEOF(*arg));
if (arg->close.handle != QSE_NULL)
{
map->eio.out.f (map, QSE_SED_IO_CLOSE, arg);
arg->close.handle = QSE_NULL;
}
}
int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
{
qse_sed_cmd_t* c, * j;
@ -1855,6 +2019,19 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
sed->eio.out.f = outf;
sed->eio.out.eof = 0;
sed->eio.out.len = 0;
if (qse_map_init (&sed->eio.out.files, sed->mmgr, 128, 70) == QSE_NULL)
{
sed->errnum = QSE_SED_ENOMEM;
return -1;
}
qse_map_setcopier (
&sed->eio.out.files, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);
qse_map_setscale (
&sed->eio.out.files, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t));
qse_map_setcopier (
&sed->eio.out.files, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE);
qse_map_setfreeer (
&sed->eio.out.files, QSE_MAP_VAL, close_outfile);
sed->eio.in.f = inf;
sed->eio.in.eof = 0;
@ -1863,11 +2040,13 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
sed->eio.in.num = 0;
if (qse_str_init (&sed->eio.in.line, QSE_MMGR(sed), 256) == QSE_NULL)
{
qse_map_fini (&sed->eio.out.files);
sed->errnum = QSE_SED_ENOMEM;
return -1;
}
n = sed->eio.in.f (sed, QSE_SED_IO_OPEN, QSE_NULL, 0);
sed->eio.in.arg.open.path = QSE_NULL;
n = sed->eio.in.f (sed, QSE_SED_IO_OPEN, &sed->eio.in.arg);
if (n <= -1)
{
ret = -1;
@ -1881,7 +2060,8 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
goto done2;
}
n = sed->eio.out.f (sed, QSE_SED_IO_OPEN, QSE_NULL, 0);
sed->eio.out.arg.open.path = QSE_NULL;
n = sed->eio.out.f (sed, QSE_SED_IO_OPEN, &sed->eio.out.arg);
if (n <= -1)
{
ret = -1;
@ -1896,13 +2076,17 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
}
/* clear states */
for (c = sed->cmd.buf; c < sed->cmd.cur; c++) c->state.a1_matched = 0;
for (c = sed->cmd.buf; c < sed->cmd.cur; c++)
{
c->state.a1_matched = 0;
c->state.c_ready = 0;
}
while (1)
{
qse_size_t i;
n = read_line (sed);
n = read_line (sed, 0);
if (n <= -1) { ret = -1; goto done; }
if (n == 0) goto done;
@ -1956,10 +2140,11 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
}
done:
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, QSE_NULL, 0);
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, &sed->eio.out.arg);
done2:
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, QSE_NULL, 0);
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &sed->eio.in.arg);
done3:
qse_str_fini (&sed->eio.in.line);
qse_map_fini (&sed->eio.out.files);
return ret;
}

View File

@ -62,9 +62,9 @@ struct qse_sed_cmd_t
QSE_SED_CMD_DELETE = QSE_T('d'),
QSE_SED_CMD_DD = QSE_T('D'),
QSE_SED_CMD_PRINT_LNUM = QSE_T('='),
QSE_SED_CMD_PRINT_LNNUM = QSE_T('='),
QSE_SED_CMD_PRINT = QSE_T('p'),
QSE_SED_CMD_PP = QSE_T('P'),
QSE_SED_CMD_PRINT_FIRSTLN = QSE_T('P'),
QSE_SED_CMD_PRINT_CLEARLY = QSE_T('l'),
QSE_SED_CMD_HOLD = QSE_T('h'),
@ -73,22 +73,17 @@ struct qse_sed_cmd_t
QSE_SED_CMD_RELEASE_APPEND = QSE_T('G'),
QSE_SED_CMD_EXCHANGE = QSE_T('x'),
QSE_SED_CMD_N = QSE_T('n'),
QSE_SED_CMD_NN = QSE_T('N'),
QSE_SED_CMD_NEXT = QSE_T('n'),
QSE_SED_CMD_NEXT_APPEND = QSE_T('N'),
/* branch */
QSE_SED_CMD_BRANCH = QSE_T('b'),
QSE_SED_CMD_T = QSE_T('t'),
/* r filename - append a text from a file */
QSE_SED_CMD_R = QSE_T('r'),
/* R filename - append a line from a file */
QSE_SED_CMD_RR = QSE_T('R'),
/* w filename - write pattern space to a file */
QSE_SED_CMD_W = QSE_T('w'),
/* W filename - write first line of pattern space to a file */
QSE_SED_CMD_WW = QSE_T('W'),
QSE_SED_CMD_READ_FILE = QSE_T('r'),
QSE_SED_CMD_READ_FILELN = QSE_T('R'),
QSE_SED_CMD_WRITE_FILE = QSE_T('w'),
QSE_SED_CMD_WRITE_FILELN = QSE_T('W'),
/* s/regex/str/ - replace matching pattern with a new string */
QSE_SED_CMD_S = QSE_T('s'),

View File

@ -27,22 +27,34 @@
#include <qse/cmn/chr.h>
static qse_ssize_t in (
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_char_t* buf, qse_size_t len)
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg)
{
switch (cmd)
{
case QSE_SED_IO_OPEN:
if (arg->open.path == QSE_NULL ||
arg->open.path[0] == QSE_T('\0'))
{
arg->open.handle = QSE_STDIN;
}
else
{
arg->open.handle = qse_fopen (arg->open.path, QSE_T("r"));
if (arg->open.handle == QSE_NULL) return -1;
}
return 1;
case QSE_SED_IO_CLOSE:
if (arg->close.handle != QSE_STDIN)
qse_fclose (arg->close.handle);
return 0;
case QSE_SED_IO_READ:
{
qse_cint_t c;
c = qse_fgetc (QSE_STDIN);
c = qse_fgetc (arg->read.handle);
if (c == QSE_CHAR_EOF) return 0;
buf[0] = c;
arg->read.buf[0] = c;
return 1;
}
}
@ -51,22 +63,34 @@ static qse_ssize_t in (
}
static qse_ssize_t out (
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_char_t* buf, qse_size_t len)
qse_sed_t* sed, qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg)
{
switch (cmd)
{
case QSE_SED_IO_OPEN:
if (arg->open.path == QSE_NULL ||
arg->open.path[0] == QSE_T('\0'))
{
arg->open.handle = QSE_STDOUT;
}
else
{
arg->open.handle = qse_fopen (arg->open.path, QSE_T("w"));
if (arg->open.handle == QSE_NULL) return -1;
}
return 1;
case QSE_SED_IO_CLOSE:
if (arg->close.handle != QSE_STDIN)
qse_fclose (arg->close.handle);
return 0;
case QSE_SED_IO_WRITE:
{
qse_size_t i = 0;
for (i = 0; i < len; i++)
qse_fputc (buf[i], QSE_STDOUT);
return len;
for (i = 0; i < arg->write.len; i++)
qse_fputc (arg->write.data[i], arg->write.handle);
return arg->write.len;
}
}