added QSE_SIO_KEEPPATH and qse_sio_getpath().

fixed a file inclusion bug in awk and xli
This commit is contained in:
2013-05-15 12:05:24 +00:00
parent 8bc5ea07e3
commit 639391d887
16 changed files with 316 additions and 331 deletions

View File

@ -1500,7 +1500,7 @@ int StdAwk::SourceFile::open (Data& io)
{
qse_sio_t* sio;
if (!(io.getFlags() & QSE_AWK_SIO_INCLUDED))
if (io.getName() == QSE_NULL)
{
// open the main source file.
@ -1519,32 +1519,23 @@ int StdAwk::SourceFile::open (Data& io)
}
else
{
const qse_char_t* base;
sio = open_sio (
io, QSE_NULL, this->name,
(io.getMode() == READ?
(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR):
(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH):
(QSE_SIO_WRITE | QSE_SIO_CREATE |
QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR))
);
if (sio == QSE_NULL) return -1;
if (this->cmgr) qse_sio_setcmgr (sio, this->cmgr);
base = qse_basename (this->name);
if (base != this->name)
{
dir.ptr = this->name;
dir.len = base - this->name;
}
}
io.setName (this->name);
if (this->cmgr) qse_sio_setcmgr (sio, this->cmgr);
}
else
{
// open an included file
const char_t* ioname, * file;
const char_t* ioname, * file, * outer;
char_t fbuf[64];
char_t* dbuf = QSE_NULL;
@ -1552,35 +1543,43 @@ int StdAwk::SourceFile::open (Data& io)
QSE_ASSERT (ioname != QSE_NULL);
file = ioname;
if (dir.len > 0 && ioname[0] != QSE_T('/'))
outer = qse_sio_getpath ((qse_sio_t*)io.getPrevHandle());
if (outer)
{
size_t tmplen, totlen;
totlen = qse_strlen(ioname) + dir.len;
if (totlen >= QSE_COUNTOF(fbuf))
const qse_char_t* base;
base = qse_basename (outer);
if (base != outer && ioname[0] != QSE_T('/'))
{
dbuf = (qse_char_t*) QSE_MMGR_ALLOC (
((Awk*)io)->getMmgr(),
QSE_SIZEOF(qse_char_t) * (totlen + 1)
);
if (dbuf == QSE_NULL)
size_t tmplen, totlen, dirlen;
dirlen = base - outer;
totlen = qse_strlen(ioname) + dirlen;
if (totlen >= QSE_COUNTOF(fbuf))
{
((Awk*)io)->setError (QSE_AWK_ENOMEM);
return -1;
dbuf = (qse_char_t*) QSE_MMGR_ALLOC (
((Awk*)io)->getMmgr(),
QSE_SIZEOF(qse_char_t) * (totlen + 1)
);
if (dbuf == QSE_NULL)
{
((Awk*)io)->setError (QSE_AWK_ENOMEM);
return -1;
}
file = dbuf;
}
else file = fbuf;
file = dbuf;
tmplen = qse_strncpy ((char_t*)file, outer, dirlen);
qse_strcpy ((char_t*)file + tmplen, ioname);
}
else file = fbuf;
tmplen = qse_strncpy ((char_t*)file, dir.ptr, dir.len);
qse_strcpy ((char_t*)file + tmplen, ioname);
}
sio = open_sio (
io, QSE_NULL, file,
(io.getMode() == READ?
(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR):
(QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH):
(QSE_SIO_WRITE | QSE_SIO_CREATE |
QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR))
);
@ -1615,7 +1614,7 @@ int StdAwk::SourceString::open (Data& io)
{
qse_sio_t* sio;
if (!(io.getFlags() & QSE_AWK_SIO_INCLUDED))
if (io.getName() == QSE_NULL)
{
// open the main source file.
// SourceString does not support writing.

View File

@ -151,15 +151,6 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_awk_prm_t* pr
if (init_token (mmgr, &awk->tok) == -1) goto oops;
if (init_token (mmgr, &awk->ntok) == -1) goto oops;
awk->sio_names = qse_htb_open (
mmgr, QSE_SIZEOF(awk), 128, 70, QSE_SIZEOF(qse_char_t), 1
);
if (awk->sio_names == QSE_NULL) goto oops;
*(qse_awk_t**)QSE_XTN(awk->sio_names) = awk;
qse_htb_setstyle (awk->sio_names,
qse_gethtbstyle(QSE_HTB_STYLE_INLINE_KEY_COPIER)
);
/* TODO: initial map size?? */
awk->tree.funs = qse_htb_open (
mmgr, QSE_SIZEOF(awk), 512, 70, QSE_SIZEOF(qse_char_t), 1
@ -256,7 +247,6 @@ oops:
if (awk->parse.named) qse_htb_close (awk->parse.named);
if (awk->parse.funs) qse_htb_close (awk->parse.funs);
if (awk->tree.funs) qse_htb_close (awk->tree.funs);
if (awk->sio_names) qse_htb_close (awk->sio_names);
fini_token (&awk->ntok);
fini_token (&awk->tok);
fini_token (&awk->ptok);
@ -286,12 +276,13 @@ int qse_awk_close (qse_awk_t* awk)
qse_htb_close (awk->parse.funs);
qse_htb_close (awk->tree.funs);
qse_htb_close (awk->sio_names);
fini_token (&awk->ntok);
fini_token (&awk->tok);
fini_token (&awk->ptok);
qse_awk_clearsionames (awk);
/* destroy dynamically allocated options */
for (i = 0; i < QSE_COUNTOF(awk->opt.mod); i++)
{
@ -391,9 +382,9 @@ int qse_awk_clear (qse_awk_t* awk)
awk->tree.chain_size = 0;
/* this table must not be cleared here as there can be a reference
* to an entry of this table from errinf.fil when qse_awk_parse()
* to an entry of this table from errinf.loc.file when qse_awk_parse()
* failed. this table is cleared in qse_awk_parse().
* qse_htb_clear (awk->sio_names);
* qse_awk_claersionames (awk);
*/
return 0;
}

View File

@ -203,7 +203,7 @@ struct qse_awk_t
qse_awk_sio_arg_t arg; /* for the top level source */
qse_awk_sio_arg_t* inp; /* current input argument. */
} sio;
qse_htb_t* sio_names;
qse_link_t* sio_names;
/* previous token */
qse_awk_tok_t ptok;

View File

@ -605,19 +605,19 @@ oops:
* closed. close them */
while (awk->sio.inp != &awk->sio.arg)
{
qse_awk_sio_arg_t* next;
qse_awk_sio_arg_t* prev;
/* nothing much to do about a close error */
awk->sio.inf (
awk, QSE_AWK_SIO_CLOSE,
awk->sio.inp, QSE_NULL, 0);
next = awk->sio.inp->next;
prev = awk->sio.inp->prev;
QSE_ASSERT (awk->sio.inp->name != QSE_NULL);
QSE_MMGR_FREE (awk->mmgr, awk->sio.inp);
awk->sio.inp = next;
awk->sio.inp = prev;
}
}
else if (ret == 0)
@ -649,6 +649,17 @@ oops:
return ret;
}
void qse_awk_clearsionames (qse_awk_t* awk)
{
qse_link_t* cur;
while (awk->sio_names)
{
cur = awk->sio_names;
awk->sio_names = cur->link;
QSE_MMGR_FREE (awk->mmgr, cur);
}
}
int qse_awk_parse (qse_awk_t* awk, qse_awk_sio_t* sio)
{
int n;
@ -667,7 +678,7 @@ int qse_awk_parse (qse_awk_t* awk, qse_awk_sio_t* sio)
QSE_ASSERT (awk->parse.depth.expr == 0);
qse_awk_clear (awk);
qse_htb_clear (awk->sio_names);
qse_awk_clearsionames (awk);
QSE_MEMSET (&awk->sio, 0, QSE_SIZEOF(awk->sio));
awk->sio.inf = sio->in;
@ -708,7 +719,7 @@ static int end_include (qse_awk_t* awk)
* awk->sio.inp again. */
cur = awk->sio.inp;
awk->sio.inp = awk->sio.inp->next;
awk->sio.inp = awk->sio.inp->prev;
QSE_ASSERT (cur->name != QSE_NULL);
QSE_MMGR_FREE (awk->mmgr, cur);
@ -728,9 +739,8 @@ static int end_include (qse_awk_t* awk)
static int begin_include (qse_awk_t* awk)
{
qse_ssize_t op;
qse_awk_sio_arg_t* arg = QSE_NULL;
qse_htb_pair_t* pair = QSE_NULL;
qse_link_t* link;
if (qse_strlen(QSE_STR_PTR(awk->tok.name)) != QSE_STR_LEN(awk->tok.name))
{
@ -746,50 +756,49 @@ static int begin_include (qse_awk_t* awk)
return -1;
}
/* store the file name to awk->sio_names */
pair = qse_htb_ensert (
awk->sio_names,
QSE_STR_PTR(awk->tok.name),
QSE_STR_LEN(awk->tok.name) + 1, /* to include '\0' */
QSE_NULL, 0
);
if (pair == QSE_NULL)
{
SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->ptok.loc);
goto oops;
}
/*QSE_HTB_VPTR(pair) = QSE_HTB_KPTR(pair);
QSE_HTB_VLEN(pair) = QSE_HTB_KLEN(pair);*/
if (awk->opt.incldirs.ptr)
{
/* include directory is set... */
/* TODO: */
}
arg = (qse_awk_sio_arg_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*arg));
/* store the include-file name into a list
* and this list is not deleted after qse_awk_parse.
* the errinfo.loc.file can point to a string here. */
link = (qse_link_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*link) +
QSE_SIZEOF(*arg) + QSE_SIZEOF(qse_char_t) * (QSE_STR_LEN(awk->tok.name) + 1));
if (link == QSE_NULL)
{
ADJERR_LOC (awk, &awk->ptok.loc);
goto oops;
}
qse_strncpy ((qse_char_t*)(link + 1), QSE_STR_PTR(awk->tok.name), QSE_STR_LEN(awk->tok.name));
link->link = awk->sio_names;
awk->sio_names = link;
arg = (qse_awk_sio_arg_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*awk));
if (arg == QSE_NULL)
{
ADJERR_LOC (awk, &awk->ptok.loc);
goto oops;
}
arg->flags = QSE_AWK_SIO_INCLUDED;
arg->name = QSE_HTB_KPTR(pair);
arg->name = (const qse_char_t*)(link + 1);
arg->line = 1;
arg->colm = 1;
/* let the argument's prev field point to the current */
arg->prev = awk->sio.inp;
CLRERR (awk);
op = awk->sio.inf (awk, QSE_AWK_SIO_OPEN, arg, QSE_NULL, 0);
if (op <= -1)
if (awk->sio.inf (awk, QSE_AWK_SIO_OPEN, arg, QSE_NULL, 0) <= -1)
{
if (ISNOERR(awk)) SETERR_TOK (awk, QSE_AWK_EOPEN);
else awk->errinf.loc = awk->tok.loc; /* adjust error location */
goto oops;
}
arg->next = awk->sio.inp;
/* i update the current pointer after opening is successful */
awk->sio.inp = arg;
awk->parse.depth.incl++;
@ -807,6 +816,8 @@ static int begin_include (qse_awk_t* awk)
return 0;
oops:
/* i don't need to free 'link' here since it's linked to awk->sio_names
* that's freed at the beginning of qse_awk_parse() or by qse_awk_close(). */
if (arg) QSE_MMGR_FREE (awk->mmgr, arg);
return -1;
}

View File

@ -84,6 +84,10 @@ int qse_awk_initgbls (
qse_awk_t* awk
);
void qse_awk_clearsionames (
qse_awk_t* awk
);
#ifdef __cplusplus
}
#endif

View File

@ -84,11 +84,8 @@ typedef struct xtn_t
union
{
struct
{
qse_sio_t* sio; /* the handle to an open file */
qse_cstr_t dir;
} file;
/* nothing to maintain here for file */
struct
{
const qse_char_t* ptr;
@ -669,7 +666,7 @@ static qse_sio_t* open_sio_std_rtx (qse_awk_rtx_t* rtx, qse_sio_std_t std, int f
/*** PARSESTD ***/
static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index)
static int open_parsestd (qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn, qse_size_t index)
{
qse_awk_parsestd_t* psin = &xtn->s.in.x[index];
@ -689,37 +686,27 @@ static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index)
if (tmp == QSE_NULL) return -1;
if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE)
qse_sio_close (xtn->s.in.u.file.sio);
qse_sio_close (arg->handle);
xtn->s.in.u.file.sio = tmp;
arg->handle = tmp;
}
else
{
qse_sio_t* tmp;
const qse_char_t* base;
tmp = open_sio (awk, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR);
tmp = open_sio (awk, psin->u.file.path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH);
if (tmp == QSE_NULL) return -1;
if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE)
qse_sio_close (xtn->s.in.u.file.sio);
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;
}
qse_sio_close (arg->handle);
arg->handle = tmp;
}
if (psin->u.file.cmgr)
qse_sio_setcmgr (xtn->s.in.u.file.sio, psin->u.file.cmgr);
if (psin->u.file.cmgr) qse_sio_setcmgr (arg->handle, psin->u.file.cmgr);
return 0;
case QSE_AWK_PARSESTD_STR:
if (index >= 1 && xtn->s.in.x[index-1].type == QSE_AWK_PARSESTD_FILE)
qse_sio_close (xtn->s.in.u.file.sio);
qse_sio_close (arg->handle);
xtn->s.in.u.str.ptr = psin->u.str.ptr;
xtn->s.in.u.str.end = psin->u.str.ptr + psin->u.str.len;
@ -734,21 +721,23 @@ static int open_parsestd (qse_awk_t* awk, xtn_t* xtn, qse_size_t index)
static qse_ssize_t sf_in_open (
qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn)
{
if (arg == QSE_NULL || !(arg->flags & QSE_AWK_SIO_INCLUDED))
if (arg->name == QSE_NULL)
{
/* handle normal source input streams specified
* to qse_awk_parsestd() */
qse_ssize_t x;
x = open_parsestd (awk, xtn, 0);
x = open_parsestd (awk, arg, xtn, 0);
if (x >= 0)
{
xtn->s.in.xindex = 0; /* update the current stream index */
#if 0
/* perform some manipulation about the top-level input information */
if (xtn->s.in.x[0].type == QSE_AWK_PARSESTD_FILE)
awk->sio.arg.name = xtn->s.in.x[0].u.file.path;
else
awk->sio.arg.name = QSE_NULL;
#endif
}
return x;
@ -756,39 +745,43 @@ static qse_ssize_t sf_in_open (
else
{
/* handle the included source 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;
base = qse_basename (outer);
if (base != outer && arg->name[0] != QSE_T('/'))
{
dbuf = qse_awk_allocmem (
awk, QSE_SIZEOF(qse_char_t) * (totlen + 1)
);
if (dbuf == QSE_NULL) return -1;
qse_size_t tmplen, totlen, dirlen;
dirlen = base - outer;
totlen = qse_strlen(arg->name) + dirlen;
if (totlen >= QSE_COUNTOF(fbuf))
{
dbuf = qse_awk_allocmem (
awk, QSE_SIZEOF(qse_char_t) * (totlen + 1)
);
if (dbuf == QSE_NULL) return -1;
path = dbuf;
}
else path = fbuf;
file = dbuf;
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 (
awk->mmgr, 0, file, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR
awk->mmgr, 0, path, QSE_SIO_READ | QSE_SIO_IGNOREMBWCERR | QSE_SIO_KEEPPATH
);
if (dbuf) QSE_MMGR_FREE (awk->mmgr, dbuf);
@ -808,12 +801,13 @@ static qse_ssize_t sf_in_open (
static qse_ssize_t sf_in_close (
qse_awk_t* awk, qse_awk_sio_arg_t* arg, xtn_t* xtn)
{
if (arg == QSE_NULL || !(arg->flags & QSE_AWK_SIO_INCLUDED))
if (arg->name == QSE_NULL)
{
switch (xtn->s.in.x[xtn->s.in.xindex].type)
{
case QSE_AWK_PARSESTD_FILE:
qse_sio_close (xtn->s.in.u.file.sio);
QSE_ASSERT (arg->handle != QSE_NULL);
qse_sio_close (arg->handle);
break;
case QSE_AWK_PARSESTD_STR:
@ -839,8 +833,7 @@ static qse_ssize_t sf_in_read (
qse_awk_t* awk, qse_awk_sio_arg_t* arg,
qse_char_t* data, qse_size_t size, xtn_t* xtn)
{
if (arg == QSE_NULL || !(arg->flags & QSE_AWK_SIO_INCLUDED))
if (arg->name == QSE_NULL)
{
qse_ssize_t n;
@ -848,8 +841,8 @@ static qse_ssize_t sf_in_read (
switch (xtn->s.in.x[xtn->s.in.xindex].type)
{
case QSE_AWK_PARSESTD_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;
@ -889,18 +882,11 @@ static qse_ssize_t sf_in_read (
if (xtn->s.in.x[next].type != QSE_AWK_PARSESTD_NULL)
{
/* open the next stream if available. */
if (open_parsestd (awk, xtn, next) <= -1) n = -1;
if (open_parsestd (awk, arg, xtn, next) <= -1) n = -1;
else
{
/* if successful, close the current stream */
xtn->s.in.xindex = next; /* update the next to the current */
/* perform some manipulation about the top-level input information */
if (xtn->s.in.x[next].type == QSE_AWK_PARSESTD_FILE)
awk->sio.arg.name = xtn->s.in.x[next].u.file.path;
else
awk->sio.arg.name = QSE_NULL;
goto again;
}
}
@ -2536,11 +2522,8 @@ done:
if (ret >= 0)
{
qse_awk_val_t* retv;
if (rv)
{
int x;
qse_awk_rtx_refupval (rtx, rv);
ret = qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv);
qse_awk_rtx_refdownval (rtx, rv);