implemented w & W commands for sed
This commit is contained in:
parent
b0c9b08d56
commit
b36f20a4a2
@ -167,7 +167,12 @@ struct qse_sed_t
|
|||||||
qse_size_t len;
|
qse_size_t len;
|
||||||
int eof;
|
int eof;
|
||||||
|
|
||||||
qse_map_t files;
|
/*****************************************************/
|
||||||
|
/* the following two fields are very tightly-coupled.
|
||||||
|
* don't make any partial changes */
|
||||||
|
qse_map_t files;
|
||||||
|
qse_sed_t* files_ext;
|
||||||
|
/*****************************************************/
|
||||||
} out;
|
} out;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -1119,7 +1119,6 @@ qse_printf (QSE_T("command %c\n"), cmd->type);
|
|||||||
if (get_file (sed, &cmd->u.file) <= -1) return -1;
|
if (get_file (sed, &cmd->u.file) <= -1) return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case QSE_T('s'):
|
case QSE_T('s'):
|
||||||
cmd->type = c;
|
cmd->type = c;
|
||||||
ADVSCP (sed);
|
ADVSCP (sed);
|
||||||
@ -1315,6 +1314,75 @@ static int read_char (qse_sed_t* sed, qse_char_t* c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int read_file (qse_sed_t* sed, const qse_char_t* path, int line)
|
||||||
|
{
|
||||||
|
qse_ssize_t n;
|
||||||
|
qse_sed_io_arg_t arg;
|
||||||
|
qse_char_t buf[256];
|
||||||
|
|
||||||
|
arg.open.path = path;
|
||||||
|
n = sed->eio.in.f (sed, QSE_SED_IO_OPEN, &arg);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/*sed->errnum = QSE_SED_EIOUSR;
|
||||||
|
return -1;*/
|
||||||
|
/* it is ok if it is not able to open a file */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
/* EOF - no data */
|
||||||
|
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
arg.read.buf = buf;
|
||||||
|
arg.read.len = QSE_COUNTOF(buf);
|
||||||
|
|
||||||
|
n = sed->eio.in.f (sed, QSE_SED_IO_READ, &arg);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &arg);
|
||||||
|
sed->errnum = QSE_SED_EIOUSR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (n == 0) break;
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
qse_size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (qse_str_ccat (&sed->eio.in.line, buf[i]) == (qse_size_t)-1)
|
||||||
|
{
|
||||||
|
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &arg);
|
||||||
|
sed->errnum = QSE_SED_ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: support different line ending scheme */
|
||||||
|
if (buf[i] == QSE_T('\n')) goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qse_str_ncat (&sed->eio.in.line, buf, n) == (qse_size_t)-1)
|
||||||
|
{
|
||||||
|
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &arg);
|
||||||
|
sed->errnum = QSE_SED_ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int read_line (qse_sed_t* sed, int append)
|
static int read_line (qse_sed_t* sed, int append)
|
||||||
{
|
{
|
||||||
qse_size_t len = 0;
|
qse_size_t len = 0;
|
||||||
@ -1583,7 +1651,15 @@ static int write_str_to_file (
|
|||||||
sed->errnum = QSE_SED_EIOUSR;
|
sed->errnum = QSE_SED_EIOUSR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// TOOD: what if n is 0???
|
if (n == 0)
|
||||||
|
{
|
||||||
|
/* EOF is returned upon opening a write stream.
|
||||||
|
* it is also an error as it can't write any more */
|
||||||
|
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, ap);
|
||||||
|
ap->close.handle = QSE_NULL;
|
||||||
|
sed->errnum = QSE_SED_EIOUSR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
@ -1593,10 +1669,21 @@ static int write_str_to_file (
|
|||||||
n = sed->eio.out.f (sed, QSE_SED_IO_WRITE, ap);
|
n = sed->eio.out.f (sed, QSE_SED_IO_WRITE, ap);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
|
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, ap);
|
||||||
|
ap->close.handle = QSE_NULL;
|
||||||
|
sed->errnum = QSE_SED_EIOUSR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
/* eof is returned on the write stream.
|
||||||
|
* it is also an error as it can't write any more */
|
||||||
|
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, ap);
|
||||||
|
ap->close.handle = QSE_NULL;
|
||||||
sed->errnum = QSE_SED_EIOUSR;
|
sed->errnum = QSE_SED_EIOUSR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// TODO: what if n is 0???
|
|
||||||
|
|
||||||
len -= n;
|
len -= n;
|
||||||
}
|
}
|
||||||
@ -1937,9 +2024,13 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_SED_CMD_READ_FILE:
|
case QSE_SED_CMD_READ_FILE:
|
||||||
|
n = read_file (sed, cmd->u.file.ptr, 0);
|
||||||
|
if (n <= -1) return QSE_NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_SED_CMD_READ_FILELN:
|
case QSE_SED_CMD_READ_FILELN:
|
||||||
|
n = read_file (sed, cmd->u.file.ptr, 1);
|
||||||
|
if (n <= -1) return QSE_NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_SED_CMD_WRITE_FILE:
|
case QSE_SED_CMD_WRITE_FILE:
|
||||||
@ -1954,15 +2045,29 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_SED_CMD_WRITE_FILELN:
|
case QSE_SED_CMD_WRITE_FILELN:
|
||||||
|
{
|
||||||
|
const qse_char_t* ptr = QSE_STR_PTR(&sed->eio.in.line);
|
||||||
|
const qse_char_t* len = QSE_STR_LEN(&sed->eio.in.line);
|
||||||
|
qse_size_t i;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
/* TODO: handle different line end scheme */
|
||||||
|
if (ptr[i] == QSE_T('\n'))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
n = write_str_to_file (
|
n = write_str_to_file (
|
||||||
sed,
|
sed,
|
||||||
QSE_STR_PTR(&sed->eio.in.line),
|
ptr, i,
|
||||||
QSE_STR_LEN(&sed->eio.in.line),
|
|
||||||
cmd->u.file.ptr,
|
cmd->u.file.ptr,
|
||||||
cmd->u.file.len
|
cmd->u.file.len
|
||||||
);
|
);
|
||||||
if (n <= -1) return QSE_NULL;
|
if (n <= -1) return QSE_NULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case QSE_SED_CMD_BRANCH:
|
case QSE_SED_CMD_BRANCH:
|
||||||
if (cmd->u.branch.target == QSE_NULL)
|
if (cmd->u.branch.target == QSE_NULL)
|
||||||
@ -1993,11 +2098,12 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd)
|
|||||||
static void close_outfile (qse_map_t* map, void* dptr, qse_size_t dlen)
|
static void close_outfile (qse_map_t* map, void* dptr, qse_size_t dlen)
|
||||||
{
|
{
|
||||||
qse_sed_io_arg_t* arg = dptr;
|
qse_sed_io_arg_t* arg = dptr;
|
||||||
QSE_ASSERT (dlen = QSE_SIZEOF(*arg));
|
QSE_ASSERT (dlen == QSE_SIZEOF(*arg));
|
||||||
|
|
||||||
if (arg->close.handle != QSE_NULL)
|
if (arg->close.handle != QSE_NULL)
|
||||||
{
|
{
|
||||||
map->eio.out.f (map, QSE_SED_IO_CLOSE, arg);
|
qse_sed_t* sed = *(qse_sed_t**)QSE_XTN(map);
|
||||||
|
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, arg);
|
||||||
arg->close.handle = QSE_NULL;
|
arg->close.handle = QSE_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2024,6 +2130,7 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
|
|||||||
sed->errnum = QSE_SED_ENOMEM;
|
sed->errnum = QSE_SED_ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*(qse_sed_t**)QSE_XTN(&sed->eio.out.files) = sed;
|
||||||
qse_map_setcopier (
|
qse_map_setcopier (
|
||||||
&sed->eio.out.files, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);
|
&sed->eio.out.files, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);
|
||||||
qse_map_setscale (
|
qse_map_setscale (
|
||||||
@ -2075,11 +2182,27 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
|
|||||||
sed->eio.out.eof = 1;
|
sed->eio.out.eof = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clear states */
|
|
||||||
for (c = sed->cmd.buf; c < sed->cmd.cur; c++)
|
for (c = sed->cmd.buf; c < sed->cmd.cur; c++)
|
||||||
{
|
{
|
||||||
|
/* clear states */
|
||||||
c->state.a1_matched = 0;
|
c->state.a1_matched = 0;
|
||||||
c->state.c_ready = 0;
|
c->state.c_ready = 0;
|
||||||
|
|
||||||
|
if (c->type == QSE_SED_CMD_WRITE_FILE ||
|
||||||
|
c->type == QSE_SED_CMD_WRITE_FILELN)
|
||||||
|
{
|
||||||
|
/* call this function to open output files */
|
||||||
|
n = write_str_to_file (
|
||||||
|
sed, QSE_NULL, 0,
|
||||||
|
c->u.file.ptr, c->u.file.len
|
||||||
|
);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* TODO: set the error code more specific.
|
||||||
|
* cannot open file */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -2140,6 +2263,7 @@ int qse_sed_execute (qse_sed_t* sed, qse_sed_iof_t inf, qse_sed_iof_t outf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
qse_map_clear (&sed->eio.out.files);
|
||||||
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, &sed->eio.out.arg);
|
sed->eio.out.f (sed, QSE_SED_IO_CLOSE, &sed->eio.out.arg);
|
||||||
done2:
|
done2:
|
||||||
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &sed->eio.in.arg);
|
sed->eio.in.f (sed, QSE_SED_IO_CLOSE, &sed->eio.in.arg);
|
||||||
|
@ -81,7 +81,7 @@ static qse_ssize_t out (
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case QSE_SED_IO_CLOSE:
|
case QSE_SED_IO_CLOSE:
|
||||||
if (arg->close.handle != QSE_STDIN)
|
if (arg->close.handle != QSE_STDOUT)
|
||||||
qse_fclose (arg->close.handle);
|
qse_fclose (arg->close.handle);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user