added QSE_SIO_KEEPPATH and qse_sio_getpath().
fixed a file inclusion bug in awk and xli
This commit is contained in:
@ -279,7 +279,7 @@ static int end_include (qse_xli_t* xli)
|
||||
* xli->sio.inp again. */
|
||||
|
||||
cur = xli->sio.inp;
|
||||
xli->sio.inp = xli->sio.inp->next;
|
||||
xli->sio.inp = xli->sio.inp->prev;
|
||||
|
||||
QSE_ASSERT (cur->name != QSE_NULL);
|
||||
QSE_MMGR_FREE (xli->mmgr, cur);
|
||||
@ -299,43 +299,35 @@ static int end_include (qse_xli_t* xli)
|
||||
|
||||
static int begin_include (qse_xli_t* xli)
|
||||
{
|
||||
qse_ssize_t op;
|
||||
qse_link_t* link;
|
||||
qse_xli_io_arg_t* arg = QSE_NULL;
|
||||
qse_htb_pair_t* pair = QSE_NULL;
|
||||
|
||||
/* store the file name to xli->sio_names */
|
||||
pair = qse_htb_ensert (
|
||||
xli->sio_names,
|
||||
QSE_STR_PTR(xli->tok.name),
|
||||
QSE_STR_LEN(xli->tok.name) + 1, /* to include '\0' */
|
||||
QSE_NULL, 0
|
||||
);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
qse_xli_seterror (xli, QSE_XLI_ENOMEM, QSE_NULL, &xli->tok.loc);
|
||||
goto oops;
|
||||
}
|
||||
link = (qse_xli_io_arg_t*) qse_xli_callocmem (xli,
|
||||
QSE_SIZEOF(*link) + QSE_SIZEOF(qse_char_t) * (QSE_STR_LEN(xli->tok.name) + 1));
|
||||
if (link == QSE_NULL) goto oops;
|
||||
|
||||
/*QSE_HTB_VPTR(pair) = QSE_HTB_KPTR(pair);
|
||||
QSE_HTB_VLEN(pair) = QSE_HTB_KLEN(pair);*/
|
||||
qse_strncpy ((qse_char_t*)(link + 1), QSE_STR_PTR(xli->tok.name), QSE_STR_LEN(xli->tok.name));
|
||||
link->link = xli->sio_names;
|
||||
xli->sio_names = link;
|
||||
|
||||
arg = (qse_xli_io_arg_t*) qse_xli_callocmem (xli, QSE_SIZEOF(*arg));
|
||||
if (arg == QSE_NULL) goto oops;
|
||||
|
||||
arg->flags = QSE_XLI_IO_INCLUDED;
|
||||
arg->name = QSE_HTB_KPTR(pair);
|
||||
arg->name = (const qse_char_t*)(link + 1);
|
||||
arg->line = 1;
|
||||
arg->colm = 1;
|
||||
|
||||
op = xli->sio.inf (xli, QSE_XLI_IO_OPEN, arg, QSE_NULL, 0);
|
||||
if (op <= -1)
|
||||
/* let the argument's prev point field to the current */
|
||||
arg->prev = xli->sio.inp;
|
||||
|
||||
if (xli->sio.inf (xli, QSE_XLI_IO_OPEN, arg, QSE_NULL, 0) <= -1)
|
||||
{
|
||||
if (xli->errnum == QSE_XLI_ENOERR)
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EIOUSR, QSE_NULL);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
arg->next = xli->sio.inp;
|
||||
/* i update the current pointer after opening is successful */
|
||||
xli->sio.inp = arg;
|
||||
/* xli->parse.depth.incl++; */
|
||||
|
||||
@ -353,6 +345,9 @@ static int begin_include (qse_xli_t* xli)
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
/* i don't need to free 'link' since it's linked to
|
||||
* xli->sio_names that's freed at the beginning of qse_xli_read()
|
||||
* or by qse_xli_fini() */
|
||||
if (arg) QSE_MMGR_FREE (xli->mmgr, arg);
|
||||
return -1;
|
||||
}
|
||||
@ -726,6 +721,17 @@ oops:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void qse_xli_clearsionames (qse_xli_t* xli)
|
||||
{
|
||||
qse_link_t* cur;
|
||||
while (xli->sio_names)
|
||||
{
|
||||
cur = xli->sio_names;
|
||||
xli->sio_names = cur->link;
|
||||
QSE_MMGR_FREE (xli->mmgr, cur);
|
||||
}
|
||||
}
|
||||
|
||||
int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io)
|
||||
{
|
||||
qse_ssize_t n;
|
||||
@ -741,7 +747,7 @@ int qse_xli_read (qse_xli_t* xli, qse_xli_io_impl_t io)
|
||||
xli->sio.arg.line = 1;
|
||||
xli->sio.arg.colm = 1;
|
||||
xli->sio.inp = &xli->sio.arg;
|
||||
qse_htb_clear (xli->sio_names);
|
||||
qse_xli_clearsionames (xli);
|
||||
|
||||
n = xli->sio.inf (xli, QSE_XLI_IO_OPEN, xli->sio.inp, QSE_NULL, 0);
|
||||
if (n <= -1)
|
||||
@ -771,15 +777,15 @@ oops:
|
||||
* closed. close them */
|
||||
while (xli->sio.inp != &xli->sio.arg)
|
||||
{
|
||||
qse_xli_io_arg_t* next;
|
||||
qse_xli_io_arg_t* prev;
|
||||
|
||||
/* nothing much to do about a close error */
|
||||
close_stream (xli);
|
||||
|
||||
next = xli->sio.inp->next;
|
||||
prev = xli->sio.inp->prev;
|
||||
QSE_ASSERT (xli->sio.inp->name != QSE_NULL);
|
||||
QSE_MMGR_FREE (xli->mmgr, xli->sio.inp);
|
||||
xli->sio.inp = next;
|
||||
xli->sio.inp = prev;
|
||||
}
|
||||
|
||||
close_stream (xli);
|
||||
|
@ -33,11 +33,10 @@ typedef struct xtn_t
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
qse_sio_t* sio; /* the handle to an open file */
|
||||
qse_cstr_t dir;
|
||||
} file;
|
||||
/*
|
||||
nothing to maintain for file here
|
||||
*/
|
||||
|
||||
struct
|
||||
{
|
||||
const qse_char_t* ptr;
|
||||
@ -150,118 +149,85 @@ static qse_sio_t* open_sio_std (qse_xli_t* xli, qse_sio_std_t std, int flags)
|
||||
return sio;
|
||||
}
|
||||
|
||||
static int open_readstd (qse_xli_t* xli, xtn_t* xtn)
|
||||
static qse_ssize_t sf_in_open (qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
||||
{
|
||||
qse_xli_iostd_t* psin = xtn->s.in.x;
|
||||
|
||||
switch (psin->type)
|
||||
if (arg->name == QSE_NULL)
|
||||
{
|
||||
/* normal source files */
|
||||
|
||||
case QSE_XLI_IOSTD_FILE:
|
||||
if (psin->u.file.path == QSE_NULL ||
|
||||
(psin->u.file.path[0] == QSE_T('-') &&
|
||||
psin->u.file.path[1] == QSE_T('\0')))
|
||||
{
|
||||
/* no path name or - -> stdin */
|
||||
qse_sio_t* tmp;
|
||||
|
||||
tmp = open_sio_std (xli, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
|
||||
xtn->s.in.u.file.sio = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_sio_t* tmp;
|
||||
const qse_char_t* base;
|
||||
|
||||
tmp = open_sio (xli, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
|
||||
xtn->s.in.u.file.sio = tmp;
|
||||
|
||||
base = qse_basename (psin->u.file.path);
|
||||
if (base != psin->u.file.path)
|
||||
{
|
||||
xtn->s.in.u.file.dir.ptr = psin->u.file.path;
|
||||
xtn->s.in.u.file.dir.len = base - psin->u.file.path;
|
||||
}
|
||||
|
||||
}
|
||||
if (psin->u.file.cmgr)
|
||||
qse_sio_setcmgr (xtn->s.in.u.file.sio, psin->u.file.cmgr);
|
||||
return 0;
|
||||
|
||||
case QSE_XLI_IOSTD_STR:
|
||||
xtn->s.in.u.str.ptr = psin->u.str.ptr;
|
||||
xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static qse_ssize_t sf_in_open (
|
||||
qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
||||
{
|
||||
if (arg == QSE_NULL || !(arg->flags & QSE_XLI_IO_INCLUDED))
|
||||
{
|
||||
/* handle normal source input streams specified
|
||||
* to qse_xli_readstd() */
|
||||
|
||||
qse_ssize_t x;
|
||||
|
||||
x = open_readstd (xli, xtn);
|
||||
if (x >= 0)
|
||||
qse_xli_iostd_t* psin = xtn->s.in.x;
|
||||
|
||||
switch (psin->type)
|
||||
{
|
||||
/* perform some manipulation about the top-level input information */
|
||||
if (xtn->s.in.x->type == QSE_XLI_IOSTD_FILE)
|
||||
xli->sio.arg.name = xtn->s.in.x->u.file.path;
|
||||
else
|
||||
xli->sio.arg.name = QSE_NULL;
|
||||
/* normal source files */
|
||||
case QSE_XLI_IOSTD_FILE:
|
||||
if (psin->u.file.path == QSE_NULL ||
|
||||
(psin->u.file.path[0] == QSE_T('-') &&
|
||||
psin->u.file.path[1] == QSE_T('\0')))
|
||||
{
|
||||
/* no path name or - -> stdin */
|
||||
arg->handle = open_sio_std (xli, QSE_SIO_STDIN, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg->handle = open_sio (xli, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH);
|
||||
}
|
||||
if (arg->handle == QSE_NULL) return -1;
|
||||
if (psin->u.file.cmgr) qse_sio_setcmgr (arg->handle, psin->u.file.cmgr);
|
||||
return 0;
|
||||
|
||||
case QSE_XLI_IOSTD_STR:
|
||||
xtn->s.in.u.str.ptr = psin->u.str.ptr;
|
||||
xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_EINTERN, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERT (arg->prev != QSE_NULL);
|
||||
|
||||
/* handle the included file - @include */
|
||||
const qse_char_t* file;
|
||||
const qse_char_t* path, * outer;
|
||||
qse_char_t fbuf[64];
|
||||
qse_char_t* dbuf = QSE_NULL;
|
||||
|
||||
QSE_ASSERT (arg->name != QSE_NULL);
|
||||
|
||||
file = arg->name;
|
||||
if (xtn->s.in.u.file.dir.len > 0 && arg->name[0] != QSE_T('/'))
|
||||
path = arg->name;
|
||||
outer = qse_sio_getpath (arg->prev->handle);
|
||||
if (outer)
|
||||
{
|
||||
qse_size_t tmplen, totlen;
|
||||
|
||||
totlen = qse_strlen(arg->name) + xtn->s.in.u.file.dir.len;
|
||||
if (totlen >= QSE_COUNTOF(fbuf))
|
||||
const qse_char_t* base;
|
||||
|
||||
/* i'm being included from another file */
|
||||
base = qse_basename (outer);
|
||||
if (base != outer && arg->name[0] != QSE_T('/'))
|
||||
{
|
||||
dbuf = qse_xli_allocmem (
|
||||
xli, QSE_SIZEOF(qse_char_t) * (totlen + 1)
|
||||
);
|
||||
if (dbuf == QSE_NULL) return -1;
|
||||
qse_size_t tmplen, totlen, dirlen;
|
||||
|
||||
file = dbuf;
|
||||
dirlen = base - outer;
|
||||
|
||||
totlen = qse_strlen(arg->name) + dirlen;
|
||||
if (totlen >= QSE_COUNTOF(fbuf))
|
||||
{
|
||||
dbuf = qse_xli_allocmem (
|
||||
xli, QSE_SIZEOF(qse_char_t) * (totlen + 1)
|
||||
);
|
||||
if (dbuf == QSE_NULL) return -1;
|
||||
|
||||
path = dbuf;
|
||||
}
|
||||
else path = fbuf;
|
||||
|
||||
tmplen = qse_strncpy ((qse_char_t*)path, outer, dirlen);
|
||||
qse_strcpy ((qse_char_t*)path + tmplen, arg->name);
|
||||
}
|
||||
else file = fbuf;
|
||||
|
||||
tmplen = qse_strncpy (
|
||||
(qse_char_t*)file,
|
||||
xtn->s.in.u.file.dir.ptr,
|
||||
xtn->s.in.u.file.dir.len
|
||||
);
|
||||
qse_strcpy ((qse_char_t*)file + tmplen, arg->name);
|
||||
}
|
||||
|
||||
arg->handle = qse_sio_open (
|
||||
xli->mmgr, 0, file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
|
||||
xli->mmgr, 0, path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH
|
||||
);
|
||||
|
||||
if (dbuf) QSE_MMGR_FREE (xli->mmgr, dbuf);
|
||||
@ -278,15 +244,17 @@ static qse_ssize_t sf_in_open (
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static qse_ssize_t sf_in_close (
|
||||
qse_xli_t* xli, qse_xli_io_arg_t* arg, xtn_t* xtn)
|
||||
{
|
||||
if (arg == QSE_NULL || !(arg->flags & QSE_XLI_IO_INCLUDED))
|
||||
if (arg->name == QSE_NULL)
|
||||
{
|
||||
switch (xtn->s.in.x->type)
|
||||
{
|
||||
case QSE_XLI_IOSTD_FILE:
|
||||
qse_sio_close (xtn->s.in.u.file.sio);
|
||||
QSE_ASSERT (arg->handle != QSE_NULL);
|
||||
qse_sio_close (arg->handle);
|
||||
break;
|
||||
|
||||
case QSE_XLI_IOSTD_STR:
|
||||
@ -312,16 +280,15 @@ static qse_ssize_t sf_in_read (
|
||||
qse_xli_t* xli, qse_xli_io_arg_t* arg,
|
||||
qse_char_t* data, qse_size_t size, xtn_t* xtn)
|
||||
{
|
||||
|
||||
if (arg == QSE_NULL || !(arg->flags & QSE_XLI_IO_INCLUDED))
|
||||
if (arg->name == QSE_NULL)
|
||||
{
|
||||
qse_ssize_t n;
|
||||
|
||||
switch (xtn->s.in.x->type)
|
||||
{
|
||||
case QSE_XLI_IOSTD_FILE:
|
||||
QSE_ASSERT (xtn->s.in.u.file.sio != QSE_NULL);
|
||||
n = qse_sio_getstrn (xtn->s.in.u.file.sio, data, size);
|
||||
QSE_ASSERT (arg->handle != QSE_NULL);
|
||||
n = qse_sio_getstrn (arg->handle, data, size);
|
||||
if (n <= -1)
|
||||
{
|
||||
qse_cstr_t ea;
|
||||
@ -382,6 +349,8 @@ static qse_ssize_t sf_in (
|
||||
{
|
||||
xtn_t* xtn = QSE_XTN (xli);
|
||||
|
||||
QSE_ASSERT (arg != QSE_NULL);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case QSE_XLI_IO_OPEN:
|
||||
|
@ -67,22 +67,12 @@ int qse_xli_init (qse_xli_t* xli, qse_mmgr_t* mmgr)
|
||||
xli->tok.name = qse_str_open (mmgr, 0, 128);
|
||||
if (xli->tok.name == QSE_NULL) goto oops;
|
||||
|
||||
xli->sio_names = qse_htb_open (
|
||||
mmgr, QSE_SIZEOF(xli), 128, 70, QSE_SIZEOF(qse_char_t), 1
|
||||
);
|
||||
if (xli->sio_names == QSE_NULL) goto oops;
|
||||
*(qse_xli_t**)QSE_XTN(xli->sio_names) = xli;
|
||||
qse_htb_setstyle (xli->sio_names,
|
||||
qse_gethtbstyle(QSE_HTB_STYLE_INLINE_KEY_COPIER)
|
||||
);
|
||||
|
||||
xli->root.type = QSE_XLI_LIST;
|
||||
xli->xnil.type = QSE_XLI_NIL;
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
qse_xli_seterrnum (xli, QSE_XLI_ENOMEM, QSE_NULL);
|
||||
if (xli->sio_names) qse_htb_close (xli->sio_names);
|
||||
if (xli->tok.name) qse_str_close (xli->tok.name);
|
||||
|
||||
for (i = QSE_COUNTOF(xli->tmp); i > 0; )
|
||||
@ -97,13 +87,14 @@ void qse_xli_fini (qse_xli_t* xli)
|
||||
qse_size_t i;
|
||||
|
||||
qse_xli_clear (xli);
|
||||
qse_htb_close (xli->sio_names);
|
||||
qse_str_close (xli->tok.name);
|
||||
|
||||
for (i = QSE_COUNTOF(xli->tmp); i > 0; )
|
||||
{
|
||||
if (xli->tmp[--i]) qse_str_close (xli->tmp[i]);
|
||||
}
|
||||
|
||||
qse_xli_clearsionames (xli);
|
||||
}
|
||||
|
||||
qse_mmgr_t* qse_xli_getmmgr (qse_xli_t* xli)
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
#include <qse/xli/xli.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
typedef struct qse_xli_tok_t qse_xli_tok_t;
|
||||
@ -63,7 +62,7 @@ struct qse_xli_t
|
||||
qse_xli_io_arg_t arg; /* for top level */
|
||||
qse_xli_io_arg_t* inp; /* current */
|
||||
} sio;
|
||||
qse_htb_t* sio_names;
|
||||
qse_link_t* sio_names;
|
||||
};
|
||||
|
||||
|
||||
@ -78,6 +77,8 @@ void qse_xli_fini (qse_xli_t* xli);
|
||||
const qse_char_t* qse_xli_dflerrstr (
|
||||
const qse_xli_t* xli, qse_xli_errnum_t errnum);
|
||||
|
||||
void qse_xli_clearsionames (qse_xli_t* xli);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user