-added Awk::Value::getFirstIndex() & Awk::Value::getNextIndex()
-fixed a few bugs in the Awk::Value class
This commit is contained in:
parent
814ed89e53
commit
9b6eb94664
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: Awk.hpp 229 2009-07-12 13:06:01Z hyunghwan.chung $
|
||||
* $Id: Awk.hpp 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -239,6 +239,69 @@ public:
|
||||
void operator delete (void* p) throw ();
|
||||
void operator delete[] (void* p) throw ();
|
||||
|
||||
class Index
|
||||
{
|
||||
public:
|
||||
friend class Value;
|
||||
|
||||
Index (): ptr (EMPTY_STRING), len (0) {}
|
||||
Index (const char_t* ptr, size_t len):
|
||||
ptr (ptr), len (len) {}
|
||||
|
||||
const char_t* ptr;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
class IntIndex: public Index
|
||||
{
|
||||
public:
|
||||
IntIndex (long_t num);
|
||||
|
||||
protected:
|
||||
// 2^32: 4294967296
|
||||
// 2^64: 18446744073709551616
|
||||
// 2^128: 340282366920938463463374607431768211456
|
||||
// -(2^32/2): -2147483648
|
||||
// -(2^64/2): -9223372036854775808
|
||||
// -(2^128/2): -170141183460469231731687303715884105728
|
||||
#if QSE_SIZEOF_LONG_T > 16
|
||||
# error SIZEOF(qse_long_t) TOO LARGE.
|
||||
# error INCREASE THE BUFFER SIZE TO SUPPORT IT.
|
||||
#elif QSE_SIZEOF_LONG_T == 16
|
||||
char_t buf[41];
|
||||
#elif QSE_SIZEOF_LONG_T == 8
|
||||
char_t buf[21];
|
||||
#else
|
||||
char_t buf[12];
|
||||
#endif
|
||||
};
|
||||
|
||||
class IndexIterator
|
||||
{
|
||||
public:
|
||||
friend class Value;
|
||||
|
||||
static IndexIterator END;
|
||||
|
||||
IndexIterator (): pair (QSE_NULL), buckno (0) {}
|
||||
IndexIterator (pair_t* pair, size_t buckno):
|
||||
pair (pair), buckno (buckno) {}
|
||||
|
||||
bool operator== (const IndexIterator& ii) const
|
||||
{
|
||||
return pair == ii.pair && buckno == ii.buckno;
|
||||
}
|
||||
|
||||
bool operator!= (const IndexIterator& ii) const
|
||||
{
|
||||
return !operator== (ii);
|
||||
}
|
||||
|
||||
protected:
|
||||
pair_t* pair;
|
||||
size_t buckno;
|
||||
};
|
||||
|
||||
Value ();
|
||||
Value (Run& run);
|
||||
Value (Run* run);
|
||||
@ -302,62 +365,75 @@ public:
|
||||
int setStr (Run* r, const char_t* str);
|
||||
|
||||
int setIndexedVal (
|
||||
const char_t* idx, size_t isz, val_t* v);
|
||||
const Index& idx,
|
||||
val_t* v
|
||||
);
|
||||
|
||||
int setIndexedVal (
|
||||
Run* r, const char_t* idx, size_t isz, val_t* v);
|
||||
Run* r,
|
||||
const Index& idx,
|
||||
val_t* v
|
||||
);
|
||||
|
||||
int setIndexedInt (
|
||||
const char_t* idx, size_t isz, long_t v);
|
||||
const Index& idx,
|
||||
long_t v
|
||||
);
|
||||
|
||||
int setIndexedInt (
|
||||
Run* r, const char_t* idx, size_t isz, long_t v);
|
||||
Run* r,
|
||||
const Index& idx,
|
||||
long_t v);
|
||||
|
||||
int setIndexedReal (
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
const Index& idx,
|
||||
real_t v
|
||||
);
|
||||
|
||||
int setIndexedReal (
|
||||
Run* r,
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
const Index& idx,
|
||||
real_t v
|
||||
);
|
||||
|
||||
int setIndexedStr (
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
const Index& idx,
|
||||
const char_t* str,
|
||||
size_t len
|
||||
);
|
||||
|
||||
int setIndexedStr (
|
||||
Run* r,
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
const Index& idx,
|
||||
const char_t* str,
|
||||
size_t len
|
||||
);
|
||||
|
||||
int setIndexedStr (
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
const Index& idx,
|
||||
const char_t* str
|
||||
);
|
||||
|
||||
int setIndexedStr (
|
||||
Run* r,
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
const Index& idx,
|
||||
const char_t* str
|
||||
);
|
||||
|
||||
bool isIndexed () const;
|
||||
|
||||
int getIndexed (
|
||||
const char_t* idx,
|
||||
size_t isz,
|
||||
Value& val
|
||||
const Index& idx,
|
||||
Value* val
|
||||
) const;
|
||||
|
||||
IndexIterator getFirstIndex (
|
||||
Index* idx
|
||||
) const;
|
||||
|
||||
IndexIterator getNextIndex (
|
||||
Index* idx,
|
||||
const IndexIterator& iter
|
||||
) const;
|
||||
|
||||
protected:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: StdAwk.hpp 229 2009-07-12 13:06:01Z hyunghwan.chung $
|
||||
* $Id: StdAwk.hpp 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -23,9 +23,11 @@
|
||||
|
||||
/**
|
||||
* @example awk05.cpp
|
||||
* This program demonstrates how to embed QSE::StdAwk in C++.
|
||||
* This program demonstrates how to embed QSE::StdAwk::loop().
|
||||
* @example awk06.cpp
|
||||
* This program demonstrates how to embed QSE::StdAwk in C++.
|
||||
* This program demonstrates how to use QSE::StdAwk::call().
|
||||
* @example awk07.cpp
|
||||
* This program demonstrates how to handle an indexed value.
|
||||
*/
|
||||
|
||||
/////////////////////////////////
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: awk.h 228 2009-07-11 03:01:36Z hyunghwan.chung $
|
||||
* $Id: awk.h 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -1809,6 +1809,18 @@ void* qse_awk_rtx_alloc (
|
||||
qse_size_t size /**< block size in bytes */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_awk_rtx_realloc() function resizes a memory block pointed to
|
||||
* by @a ptr to @a size bytes using the memory manager associated with
|
||||
* a runtime context @a rtx.
|
||||
* @return the pointer to a memory block on success, #QSE_NULL on failure.
|
||||
*/
|
||||
void* qse_awk_rtx_realloc (
|
||||
qse_awk_rtx_t* rtx, /**< runtime context */
|
||||
void* ptr, /**< memory block */
|
||||
qse_size_t size /**< block size in bytes */
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_awk_rtx_free() function frees a memory block pointed to by @a ptr
|
||||
* using the memory manager of a runtime ocntext @a rtx.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: types.h 220 2009-07-01 13:14:39Z hyunghwan.chung $
|
||||
* $Id: types.h 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -70,24 +70,31 @@ typedef enum qse_tri_t qse_tri_t;
|
||||
(QSE_SIZEOF_VOID_P == QSE_SIZEOF_LONG)
|
||||
typedef long qse_int_t;
|
||||
typedef unsigned long qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF_LONG
|
||||
#elif defined(__SPU__) && (QSE_SIZEOF_VOID_P == QSE_SIZEOF_LONG)
|
||||
typedef long qse_int_t;
|
||||
typedef unsigned long qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF_LONG
|
||||
#elif QSE_SIZEOF_VOID_P == QSE_SIZEOF_INT
|
||||
typedef int qse_int_t;
|
||||
typedef unsigned int qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF_INT
|
||||
#elif QSE_SIZEOF_VOID_P == QSE_SIZEOF_LONG
|
||||
typedef long qse_int_t;
|
||||
typedef unsigned long qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF_LONG
|
||||
#elif QSE_SIZEOF_VOID_P == QSE_SIZEOF_LONG_LONG
|
||||
typedef long long qse_int_t;
|
||||
typedef unsigned long long qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF_LONG_LONG
|
||||
#elif QSE_SIZEOF_VOID_P == QSE_SIZEOF___INT32
|
||||
typedef __int32 qse_int_t;
|
||||
typedef unsigned __int32 qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF___INT32
|
||||
#elif QSE_SIZEOF_VOID_P == QSE_SIZEOF___INT64
|
||||
typedef __int64 qse_int_t;
|
||||
typedef unsigned __int64 qse_uint_t;
|
||||
#define QSE_SIZEOF_INT_T QSE_SIZEOF___INT64
|
||||
#else
|
||||
# error unsupported pointer size
|
||||
#endif
|
||||
@ -101,12 +108,15 @@ typedef enum qse_tri_t qse_tri_t;
|
||||
#if QSE_SIZEOF_LONG_LONG > 0
|
||||
typedef long long qse_long_t;
|
||||
typedef unsigned long long qse_ulong_t;
|
||||
#define QSE_SIZEOF_LONG_T QSE_SIZEOF_LONG_LONG
|
||||
#elif QSE_SIZEOF___INT64 > 0
|
||||
typedef __int64 qse_long_t;
|
||||
typedef unsigned __int64 qse_ulong_t;
|
||||
#define QSE_SIZEOF_LONG_T QSE_SIZEOF___INT64
|
||||
#else
|
||||
typedef long qse_long_t;
|
||||
typedef unsigned long qse_ulong_t;
|
||||
#define QSE_SIZEOF_LONG_T QSE_SIZEOF_LONG
|
||||
#endif
|
||||
|
||||
/** @typedef qse_int8_t
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: Awk.cpp 229 2009-07-12 13:06:01Z hyunghwan.chung $
|
||||
* $Id: Awk.cpp 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -170,6 +170,51 @@ Awk::Console::Mode Awk::Console::getMode () const
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
const Awk::char_t* Awk::Value::EMPTY_STRING = QSE_T("");
|
||||
Awk::Value::IndexIterator Awk::Value::IndexIterator::END;
|
||||
|
||||
Awk::Value::IntIndex::IntIndex (long_t x)
|
||||
{
|
||||
ptr = buf;
|
||||
len = 0;
|
||||
|
||||
#define NTOC(n) ((n) + QSE_T('0'))
|
||||
|
||||
int base = 10;
|
||||
long_t last = x % base;
|
||||
long_t y = 0;
|
||||
int dig = 0;
|
||||
|
||||
if (x < 0) buf[len++] = QSE_T('-');
|
||||
|
||||
x = x / base;
|
||||
if (x < 0) x = -x;
|
||||
|
||||
while (x > 0)
|
||||
{
|
||||
y = y * base + (x % base);
|
||||
x = x / base;
|
||||
dig++;
|
||||
}
|
||||
|
||||
while (y > 0)
|
||||
{
|
||||
buf[len++] = NTOC (y % base);
|
||||
y = y / base;
|
||||
dig--;
|
||||
}
|
||||
|
||||
while (dig > 0)
|
||||
{
|
||||
dig--;
|
||||
buf[len++] = QSE_T('0');
|
||||
}
|
||||
if (last < 0) last = -last;
|
||||
buf[len++] = NTOC(last);
|
||||
|
||||
buf[len] = QSE_T('\0');
|
||||
|
||||
#undef NTOC
|
||||
}
|
||||
|
||||
void* Awk::Value::operator new (size_t n, Run* run) throw ()
|
||||
{
|
||||
@ -326,7 +371,11 @@ int Awk::Value::getInt (long_t* v) const
|
||||
{
|
||||
real_t rv;
|
||||
int n = qse_awk_rtx_valtonum (run->rtx, val, &lv, &rv);
|
||||
if (n <= -1) return -1;
|
||||
if (n <= -1)
|
||||
{
|
||||
run->awk->retrieveError (run->rtx);
|
||||
return -1;
|
||||
}
|
||||
if (n >= 1) lv = rv;
|
||||
}
|
||||
|
||||
@ -346,7 +395,11 @@ int Awk::Value::getReal (real_t* v) const
|
||||
{
|
||||
long_t lv;
|
||||
int n = qse_awk_rtx_valtonum (run->rtx, val, &lv, &rv);
|
||||
if (n <= -1) return -1;
|
||||
if (n <= -1)
|
||||
{
|
||||
run->awk->retrieveError (run->rtx);
|
||||
return -1;
|
||||
}
|
||||
if (n == 0) rv = lv;
|
||||
}
|
||||
|
||||
@ -379,6 +432,7 @@ int Awk::Value::getStr (const char_t** str, size_t* len) const
|
||||
if (qse_awk_rtx_valtostr (
|
||||
run->rtx, val, &out) == QSE_NULL)
|
||||
{
|
||||
run->awk->retrieveError (run->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -440,7 +494,11 @@ int Awk::Value::setInt (Run* r, long_t v)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makeintval (r->rtx, v);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int n = setVal (r, tmp);
|
||||
QSE_ASSERT (n == 0);
|
||||
@ -457,7 +515,11 @@ int Awk::Value::setReal (Run* r, real_t v)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makerealval (r->rtx, v);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int n = setVal (r, tmp);
|
||||
QSE_ASSERT (n == 0);
|
||||
@ -474,7 +536,11 @@ int Awk::Value::setStr (Run* r, const char_t* str, size_t len)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makestrval (r->rtx, str, len);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int n = setVal (r, tmp);
|
||||
QSE_ASSERT (n == 0);
|
||||
@ -491,27 +557,37 @@ int Awk::Value::setStr (Run* r, const char_t* str)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makestrval0 (r->rtx, str);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int n = setVal (r, tmp);
|
||||
QSE_ASSERT (n == 0);
|
||||
return n;
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedVal (const char_t* idx, size_t isz, val_t* v)
|
||||
int Awk::Value::setIndexedVal (const Index& idx, val_t* v)
|
||||
{
|
||||
if (run == QSE_NULL) return -1;
|
||||
return setIndexedVal (run, idx, isz, v);
|
||||
return setIndexedVal (run, idx, v);
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedVal (Run* r, const char_t* idx, size_t isz, val_t* v)
|
||||
int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v)
|
||||
{
|
||||
QSE_ASSERT (r != QSE_NULL);
|
||||
|
||||
if (val->type != QSE_AWK_VAL_MAP)
|
||||
{
|
||||
/* the previous value is not a map.
|
||||
* a new map value needs to be created first */
|
||||
val_t* map = qse_awk_rtx_makemapval (run->rtx);
|
||||
if (map == QSE_NULL) return -1;
|
||||
val_t* map = qse_awk_rtx_makemapval (r->rtx);
|
||||
if (map == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_awk_rtx_refupval (r->rtx, map);
|
||||
qse_awk_rtx_refupval (r->rtx, v);
|
||||
@ -519,12 +595,13 @@ int Awk::Value::setIndexedVal (Run* r, const char_t* idx, size_t isz, val_t* v)
|
||||
/* update the map with a given value */
|
||||
pair_t* pair = qse_map_upsert (
|
||||
((qse_awk_val_map_t*)map)->map,
|
||||
(char_t*)idx, isz, v, 0);
|
||||
(char_t*)idx.ptr, idx.len, v, 0);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
qse_awk_rtx_refdownval (r->rtx, v);
|
||||
qse_awk_rtx_refdownval (r->rtx, map);
|
||||
run->setError (ERR_NOMEM, 0, QSE_NULL, 0);
|
||||
r->setError (ERR_NOMEM, 0, QSE_NULL, 0);
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -545,6 +622,7 @@ int Awk::Value::setIndexedVal (Run* r, const char_t* idx, size_t isz, val_t* v)
|
||||
{
|
||||
// it can't span across multiple runtime contexts
|
||||
run->setError (ERR_INVAL);
|
||||
run->awk->retrieveError (run->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -552,11 +630,12 @@ int Awk::Value::setIndexedVal (Run* r, const char_t* idx, size_t isz, val_t* v)
|
||||
|
||||
pair_t* pair = qse_map_upsert (
|
||||
((qse_awk_val_map_t*)val)->map,
|
||||
(char_t*)idx, isz, v, 0);
|
||||
(char_t*)idx.ptr, idx.len, v, 0);
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
qse_awk_rtx_refdownval (r->rtx, v);
|
||||
run->setError (ERR_NOMEM);
|
||||
run->awk->retrieveError (run->rtx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -564,79 +643,94 @@ int Awk::Value::setIndexedVal (Run* r, const char_t* idx, size_t isz, val_t* v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedInt (const char_t* idx, size_t isz, long_t v)
|
||||
int Awk::Value::setIndexedInt (const Index& idx, long_t v)
|
||||
{
|
||||
if (run == QSE_NULL) return -1;
|
||||
return setIndexedInt (run, idx, isz, v);
|
||||
return setIndexedInt (run, idx, v);
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedInt (Run* r, const char_t* idx, size_t isz, long_t v)
|
||||
int Awk::Value::setIndexedInt (Run* r, const Index& idx, long_t v)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makeintval (r->rtx, v);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_awk_rtx_refupval (r->rtx, tmp);
|
||||
int n = setIndexedVal (r, idx, isz, tmp);
|
||||
int n = setIndexedVal (r, idx, tmp);
|
||||
qse_awk_rtx_refdownval (r->rtx, tmp);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedReal (const char_t* idx, size_t isz, real_t v)
|
||||
int Awk::Value::setIndexedReal (const Index& idx, real_t v)
|
||||
{
|
||||
if (run == QSE_NULL) return -1;
|
||||
return setIndexedReal (run, idx, isz, v);
|
||||
return setIndexedReal (run, idx, v);
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedReal (Run* r, const char_t* idx, size_t isz, real_t v)
|
||||
int Awk::Value::setIndexedReal (Run* r, const Index& idx, real_t v)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makerealval (r->rtx, v);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_awk_rtx_refupval (r->rtx, tmp);
|
||||
int n = setIndexedVal (r, idx, isz, tmp);
|
||||
int n = setIndexedVal (r, idx, tmp);
|
||||
qse_awk_rtx_refdownval (r->rtx, tmp);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedStr (const char_t* idx, size_t isz, const char_t* str, size_t len)
|
||||
int Awk::Value::setIndexedStr (const Index& idx, const char_t* str, size_t len)
|
||||
{
|
||||
if (run == QSE_NULL) return -1;
|
||||
return setIndexedStr (run, idx, isz, str, len);
|
||||
return setIndexedStr (run, idx, str, len);
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedStr (
|
||||
Run* r, const char_t* idx, size_t isz, const char_t* str, size_t len)
|
||||
Run* r, const Index& idx, const char_t* str, size_t len)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makestrval (r->rtx, str, len);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_awk_rtx_refupval (r->rtx, tmp);
|
||||
int n = setIndexedVal (r, idx, isz, tmp);
|
||||
int n = setIndexedVal (r, idx, tmp);
|
||||
qse_awk_rtx_refdownval (r->rtx, tmp);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedStr (const char_t* idx, size_t isz, const char_t* str)
|
||||
int Awk::Value::setIndexedStr (const Index& idx, const char_t* str)
|
||||
{
|
||||
if (run == QSE_NULL) return -1;
|
||||
return setIndexedStr (run, idx, isz, str);
|
||||
return setIndexedStr (run, idx, str);
|
||||
}
|
||||
|
||||
int Awk::Value::setIndexedStr (
|
||||
Run* r, const char_t* idx, size_t isz, const char_t* str)
|
||||
int Awk::Value::setIndexedStr (Run* r, const Index& idx, const char_t* str)
|
||||
{
|
||||
val_t* tmp;
|
||||
tmp = qse_awk_rtx_makestrval0 (r->rtx, str);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
r->awk->retrieveError (r->rtx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_awk_rtx_refupval (r->rtx, tmp);
|
||||
int n = setIndexedVal (r, idx, isz, tmp);
|
||||
int n = setIndexedVal (r, idx, tmp);
|
||||
qse_awk_rtx_refdownval (r->rtx, tmp);
|
||||
|
||||
return n;
|
||||
@ -649,30 +743,68 @@ bool Awk::Value::isIndexed () const
|
||||
return val->type == QSE_AWK_VAL_MAP;
|
||||
}
|
||||
|
||||
int Awk::Value::getIndexed (const char_t* idx, size_t isz, Value& v) const
|
||||
int Awk::Value::getIndexed (const Index& idx, Value* v) const
|
||||
{
|
||||
QSE_ASSERT (val != QSE_NULL);
|
||||
|
||||
// not a map. v is just nil. not an error
|
||||
if (val->type != QSE_AWK_VAL_MAP)
|
||||
{
|
||||
v.clear ();
|
||||
v->clear ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get the value from the map.
|
||||
qse_awk_val_map_t* m = (qse_awk_val_map_t*)val;
|
||||
pair_t* pair = qse_map_search (m->map, idx, isz);
|
||||
pair_t* pair = qse_map_search (m->map, idx.ptr, idx.len);
|
||||
|
||||
// the key is not found. it is not an error. v is just nil
|
||||
if (pair == QSE_NULL)
|
||||
{
|
||||
v.clear ();
|
||||
v->clear ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if v.set fails, it should return an error
|
||||
return v.setVal (run, (val_t*)QSE_MAP_VPTR(pair));
|
||||
return v->setVal (run, (val_t*)QSE_MAP_VPTR(pair));
|
||||
}
|
||||
|
||||
Awk::Value::IndexIterator Awk::Value::getFirstIndex (Index* idx) const
|
||||
{
|
||||
QSE_ASSERT (val != QSE_NULL);
|
||||
|
||||
if (val->type != QSE_AWK_VAL_MAP) return IndexIterator::END;
|
||||
|
||||
size_t buckno;
|
||||
qse_awk_val_map_t* m = (qse_awk_val_map_t*)val;
|
||||
pair_t* pair = qse_map_getfirstpair (m->map, &buckno);
|
||||
if (pair == QSE_NULL) return IndexIterator::END; // no more key
|
||||
|
||||
idx->ptr = (const char_t*)QSE_MAP_KPTR(pair);
|
||||
idx->len = QSE_MAP_KLEN(pair);
|
||||
|
||||
return IndexIterator (pair, buckno);
|
||||
}
|
||||
|
||||
Awk::Value::IndexIterator Awk::Value::getNextIndex (
|
||||
Index* idx, const IndexIterator& iter) const
|
||||
{
|
||||
QSE_ASSERT (val != QSE_NULL);
|
||||
|
||||
if (val->type != QSE_AWK_VAL_MAP) return IndexIterator::END;
|
||||
|
||||
qse_awk_val_map_t* m = (qse_awk_val_map_t*)val;
|
||||
|
||||
pair_t* pair = (pair_t*)iter.pair;
|
||||
size_t buckno = iter.buckno;
|
||||
|
||||
pair = qse_map_getnextpair (m->map, pair, &buckno);
|
||||
if (pair == QSE_NULL) return IndexIterator::END;
|
||||
|
||||
idx->ptr = (const char_t*)QSE_MAP_KPTR(pair);
|
||||
idx->len = QSE_MAP_KLEN(pair);
|
||||
|
||||
return IndexIterator (pair, buckno);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -724,35 +856,6 @@ int Awk::Argument::getNextIndex (Awk::Argument& val) const
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Awk::Return::setIndexed (long_t idx, real_t v)
|
||||
{
|
||||
if (this->run == QSE_NULL) return -1;
|
||||
|
||||
char_t ri[128];
|
||||
|
||||
int rl = Awk::sprintf (
|
||||
(awk_t*)this->run->awk, ri, QSE_COUNTOF(ri),
|
||||
#if QSE_SIZEOF_LONG_LONG > 0
|
||||
QSE_T("%lld"), (long long)idx
|
||||
#elif QSE_SIZEOF___INT64 > 0
|
||||
QSE_T("%I64d"), (__int64)idx
|
||||
#elif QSE_SIZEOF_LONG > 0
|
||||
QSE_T("%ld"), (long)idx
|
||||
#elif QSE_SIZEOF_INT > 0
|
||||
QSE_T("%d"), (int)idx
|
||||
#else
|
||||
#error unsupported size
|
||||
#endif
|
||||
);
|
||||
|
||||
if (rl < 0)
|
||||
{
|
||||
this->run->setError (ERR_INTERN, 0, QSE_NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return setIndexed (ri, rl, v);
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
@ -1270,6 +1373,7 @@ int Awk::call (const char_t* name, Value* ret, const Value* args, size_t nargs)
|
||||
if (ptr == QSE_NULL)
|
||||
{
|
||||
runctx.setError (ERR_NOMEM);
|
||||
retrieveError (runctx.rtx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: misc.c 220 2009-07-01 13:14:39Z hyunghwan.chung $
|
||||
* $Id: misc.c 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -983,6 +983,11 @@ void* qse_awk_rtx_alloc (qse_awk_rtx_t* rtx, qse_size_t size)
|
||||
return qse_awk_alloc (rtx->awk, size);
|
||||
}
|
||||
|
||||
void* qse_awk_rtx_realloc (qse_awk_rtx_t* rtx, void* ptr, qse_size_t size)
|
||||
{
|
||||
return qse_awk_realloc (rtx->awk, ptr, size);
|
||||
}
|
||||
|
||||
void qse_awk_rtx_free (qse_awk_rtx_t* rtx, void* ptr)
|
||||
{
|
||||
qse_awk_free (rtx->awk, ptr);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* $Id: run.c 228 2009-07-11 03:01:36Z hyunghwan.chung $
|
||||
* $Id: run.c 230 2009-07-13 08:51:23Z hyunghwan.chung $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
@ -243,6 +243,9 @@ typedef qse_awk_val_t* (*binop_func_t) (
|
||||
qse_awk_rtx_t* run, qse_awk_val_t* left, qse_awk_val_t* right);
|
||||
typedef qse_awk_val_t* (*eval_expr_t) (qse_awk_rtx_t* run, qse_awk_nde_t* nde);
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define xstr_to_cstr(x) ((qse_cstr_t*)x)
|
||||
#else
|
||||
static qse_cstr_t* xstr_to_cstr (qse_xstr_t* xstr)
|
||||
{
|
||||
/* i use this function to typecast qse_cstr_t* to
|
||||
@ -252,6 +255,7 @@ static qse_cstr_t* xstr_to_cstr (qse_xstr_t* xstr)
|
||||
* haved changed to something else. */
|
||||
return (qse_cstr_t*)xstr;
|
||||
}
|
||||
#endif
|
||||
|
||||
qse_size_t qse_awk_rtx_getnargs (qse_awk_rtx_t* run)
|
||||
{
|
||||
@ -3328,7 +3332,6 @@ static qse_awk_val_t* do_assignment (
|
||||
goto exit_on_error;
|
||||
}
|
||||
|
||||
|
||||
ret = do_assignment_pos (run, (qse_awk_nde_pos_t*)var, val);
|
||||
}
|
||||
else
|
||||
@ -3463,7 +3466,7 @@ static qse_awk_val_t* do_assignment_map (
|
||||
(var->type == QSE_AWK_NDE_LCLIDX)?
|
||||
(qse_awk_val_map_t*)STACK_LCL(run,var->id.idxa):
|
||||
(qse_awk_val_map_t*)STACK_ARG(run,var->id.idxa);
|
||||
}
|
||||
}
|
||||
|
||||
if (map->type == QSE_AWK_VAL_NIL)
|
||||
{
|
||||
|
@ -11,13 +11,15 @@ awk03_SOURCES = awk03.c
|
||||
awk04_SOURCES = awk04.c
|
||||
|
||||
if ENABLE_CXX
|
||||
bin_PROGRAMS += awk05 awk06 awk07
|
||||
bin_PROGRAMS += awk05 awk06 awk07 awk08
|
||||
|
||||
awk05_SOURCES = awk05.cpp
|
||||
awk06_SOURCES = awk06.cpp
|
||||
awk07_SOURCES = awk07.cpp
|
||||
awk08_SOURCES = awk08.cpp
|
||||
|
||||
awk05_LDADD = -lqseawk++ $(LDADD)
|
||||
awk06_LDADD = -lqseawk++ $(LDADD)
|
||||
awk07_LDADD = -lqseawk++ $(LDADD)
|
||||
awk08_LDADD = -lqseawk++ $(LDADD)
|
||||
endif
|
||||
|
@ -34,7 +34,7 @@ build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
bin_PROGRAMS = awk01$(EXEEXT) awk02$(EXEEXT) awk03$(EXEEXT) \
|
||||
awk04$(EXEEXT) $(am__EXEEXT_1)
|
||||
@ENABLE_CXX_TRUE@am__append_1 = awk05 awk06 awk07
|
||||
@ENABLE_CXX_TRUE@am__append_1 = awk05 awk06 awk07 awk08
|
||||
subdir = samples/awk
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
@ -49,7 +49,7 @@ mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/include/qse/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
@ENABLE_CXX_TRUE@am__EXEEXT_1 = awk05$(EXEEXT) awk06$(EXEEXT) \
|
||||
@ENABLE_CXX_TRUE@ awk07$(EXEEXT)
|
||||
@ENABLE_CXX_TRUE@ awk07$(EXEEXT) awk08$(EXEEXT)
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
@ -83,6 +83,10 @@ am__awk07_SOURCES_DIST = awk07.cpp
|
||||
@ENABLE_CXX_TRUE@am_awk07_OBJECTS = awk07.$(OBJEXT)
|
||||
awk07_OBJECTS = $(am_awk07_OBJECTS)
|
||||
@ENABLE_CXX_TRUE@awk07_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||
am__awk08_SOURCES_DIST = awk08.cpp
|
||||
@ENABLE_CXX_TRUE@am_awk08_OBJECTS = awk08.$(OBJEXT)
|
||||
awk08_OBJECTS = $(am_awk08_OBJECTS)
|
||||
@ENABLE_CXX_TRUE@awk08_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/qse
|
||||
depcomp = $(SHELL) $(top_srcdir)/ac/au/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@ -106,10 +110,11 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
|
||||
$(LDFLAGS) -o $@
|
||||
SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
||||
$(awk04_SOURCES) $(awk05_SOURCES) $(awk06_SOURCES) \
|
||||
$(awk07_SOURCES)
|
||||
$(awk07_SOURCES) $(awk08_SOURCES)
|
||||
DIST_SOURCES = $(awk01_SOURCES) $(awk02_SOURCES) $(awk03_SOURCES) \
|
||||
$(awk04_SOURCES) $(am__awk05_SOURCES_DIST) \
|
||||
$(am__awk06_SOURCES_DIST) $(am__awk07_SOURCES_DIST)
|
||||
$(am__awk06_SOURCES_DIST) $(am__awk07_SOURCES_DIST) \
|
||||
$(am__awk08_SOURCES_DIST)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
@ -258,9 +263,11 @@ awk04_SOURCES = awk04.c
|
||||
@ENABLE_CXX_TRUE@awk05_SOURCES = awk05.cpp
|
||||
@ENABLE_CXX_TRUE@awk06_SOURCES = awk06.cpp
|
||||
@ENABLE_CXX_TRUE@awk07_SOURCES = awk07.cpp
|
||||
@ENABLE_CXX_TRUE@awk08_SOURCES = awk08.cpp
|
||||
@ENABLE_CXX_TRUE@awk05_LDADD = -lqseawk++ $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk06_LDADD = -lqseawk++ $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk07_LDADD = -lqseawk++ $(LDADD)
|
||||
@ENABLE_CXX_TRUE@awk08_LDADD = -lqseawk++ $(LDADD)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
@ -343,6 +350,9 @@ awk06$(EXEEXT): $(awk06_OBJECTS) $(awk06_DEPENDENCIES)
|
||||
awk07$(EXEEXT): $(awk07_OBJECTS) $(awk07_DEPENDENCIES)
|
||||
@rm -f awk07$(EXEEXT)
|
||||
$(CXXLINK) $(awk07_OBJECTS) $(awk07_LDADD) $(LIBS)
|
||||
awk08$(EXEEXT): $(awk08_OBJECTS) $(awk08_DEPENDENCIES)
|
||||
@rm -f awk08$(EXEEXT)
|
||||
$(CXXLINK) $(awk08_OBJECTS) $(awk08_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
@ -357,6 +367,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk05.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk06.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk07.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/awk08.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
|
@ -17,652 +17,103 @@
|
||||
*/
|
||||
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/main.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
class MyAwk;
|
||||
#ifdef _WIN32
|
||||
static BOOL WINAPI stop_run (DWORD ctrl_type);
|
||||
#else
|
||||
static void stop_run (int sig);
|
||||
#endif
|
||||
|
||||
static void set_intr_run (void);
|
||||
static void unset_intr_run (void);
|
||||
|
||||
MyAwk* app_awk = QSE_NULL;
|
||||
static bool verbose = false;
|
||||
|
||||
class MyAwk: public QSE::StdAwk
|
||||
static void print_error (unsigned long line, const qse_char_t* msg)
|
||||
{
|
||||
public:
|
||||
MyAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL)
|
||||
|
||||
{
|
||||
#ifdef _WIN32
|
||||
heap = QSE_NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
~MyAwk ()
|
||||
{
|
||||
close ();
|
||||
}
|
||||
|
||||
int open ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
QSE_ASSERT (heap == QSE_NULL);
|
||||
heap = ::HeapCreate (0, 1000000, 1000000);
|
||||
if (heap == QSE_NULL) return -1;
|
||||
#endif
|
||||
|
||||
int n = StdAwk::open ();
|
||||
if (n <= -1)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HeapDestroy (heap);
|
||||
heap = QSE_NULL;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
idLastSleep = addGlobal (QSE_T("LAST_SLEEP"));
|
||||
if (idLastSleep <= -1) goto failure;
|
||||
|
||||
if (addFunction (QSE_T("sleep"), 1, 1,
|
||||
(FunctionHandler)&MyAwk::sleep) <= -1) goto failure;
|
||||
|
||||
if (addFunction (QSE_T("sumintarray"), 1, 1,
|
||||
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto failure;
|
||||
|
||||
if (addFunction (QSE_T("arrayindices"), 1, 1,
|
||||
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto failure;
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
StdAwk::close ();
|
||||
|
||||
#ifdef _WIN32
|
||||
HeapDestroy (heap);
|
||||
heap = QSE_NULL;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
void close ()
|
||||
{
|
||||
StdAwk::close ();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (heap != QSE_NULL)
|
||||
{
|
||||
HeapDestroy (heap);
|
||||
heap = QSE_NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int sleep (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
run.setError (ERR_INVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long_t x = args[0].toInt();
|
||||
|
||||
/*Argument arg;
|
||||
if (run.getGlobal(idLastSleep, arg) == 0)
|
||||
qse_printf (QSE_T("GOOD: [%d]\n"), (int)arg.toInt());
|
||||
else { qse_printf (QSE_T("BAD:\n")); }
|
||||
*/
|
||||
|
||||
if (run.setGlobal (idLastSleep, x) <= -1) return -1;
|
||||
|
||||
#ifdef _WIN32
|
||||
::Sleep ((DWORD)(x * 1000));
|
||||
return ret.set ((long_t)0);
|
||||
#else
|
||||
return ret.set ((long_t)::sleep (x));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sumintarray (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
long_t x = 0;
|
||||
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
Argument idx(run), val(run);
|
||||
|
||||
int n = args[0].getFirstIndex (idx);
|
||||
while (n > 0)
|
||||
{
|
||||
size_t len;
|
||||
const char_t* ptr = idx.toStr(&len);
|
||||
|
||||
if (args[0].getIndexed(ptr, len, val) <= -1) return -1;
|
||||
x += val.toInt ();
|
||||
|
||||
n = args[0].getNextIndex (idx);
|
||||
}
|
||||
if (n != 0) return -1;
|
||||
}
|
||||
else x += args[0].toInt();
|
||||
|
||||
return ret.set (x);
|
||||
}
|
||||
|
||||
int arrayindices (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
if (!args[0].isIndexed()) return 0;
|
||||
|
||||
Argument idx (run);
|
||||
long_t i;
|
||||
|
||||
int n = args[0].getFirstIndex (idx);
|
||||
for (i = 0; n > 0; i++)
|
||||
{
|
||||
size_t len;
|
||||
const char_t* ptr = idx.toStr(&len);
|
||||
n = args[0].getNextIndex (idx);
|
||||
if (ret.setIndexed (i, ptr, len) <= -1) return -1;
|
||||
}
|
||||
if (n != 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Run* parse (const char_t* in, const char_t* out)
|
||||
{
|
||||
srcInName = in;
|
||||
srcOutName = out;
|
||||
return StdAwk::parse ();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool onLoopEnter (Run& run)
|
||||
{
|
||||
set_intr_run ();
|
||||
return true;
|
||||
}
|
||||
|
||||
void onLoopExit (Run& run, const Argument& ret)
|
||||
{
|
||||
unset_intr_run ();
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
size_t len;
|
||||
const char_t* ptr = ret.toStr (&len);
|
||||
qse_printf (QSE_T("*** return [%.*s] ***\n"), (int)len, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int openSource (Source& io)
|
||||
{
|
||||
Source::Mode mode = io.getMode();
|
||||
FILE* fp = QSE_NULL;
|
||||
|
||||
// TODO: use sio instead of stdio
|
||||
if (mode == Source::READ)
|
||||
{
|
||||
if (srcInName == QSE_NULL)
|
||||
{
|
||||
io.setHandle (stdin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srcInName[0] == QSE_T('\0')) fp = stdin;
|
||||
else fp = qse_fopen (srcInName, QSE_T("r"));
|
||||
}
|
||||
else if (mode == Source::WRITE)
|
||||
{
|
||||
if (srcOutName == QSE_NULL)
|
||||
{
|
||||
io.setHandle (stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srcOutName[0] == QSE_T('\0')) fp = stdout;
|
||||
else fp = qse_fopen (srcOutName, QSE_T("w"));
|
||||
}
|
||||
|
||||
if (fp == QSE_NULL) return -1;
|
||||
io.setHandle (fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int closeSource (Source& io)
|
||||
{
|
||||
FILE* fp = (FILE*)io.getHandle();
|
||||
if (fp == stdout || fp == stderr) fflush (fp);
|
||||
if (fp != stdin && fp != stdout && fp != stderr) fclose (fp);
|
||||
io.setHandle (QSE_NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t readSource (Source& io, char_t* buf, size_t len)
|
||||
{
|
||||
FILE* fp = (FILE*)io.getHandle();
|
||||
ssize_t n = 0;
|
||||
|
||||
while (n < (ssize_t)len)
|
||||
{
|
||||
qse_cint_t c = qse_fgetc (fp);
|
||||
if (c == QSE_CHAR_EOF)
|
||||
{
|
||||
if (qse_ferror(fp)) n = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[n++] = c;
|
||||
if (c == QSE_T('\n')) break;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t writeSource (Source& io, char_t* buf, size_t len)
|
||||
{
|
||||
FILE* fp = (FILE*)io.getHandle();
|
||||
size_t left = len;
|
||||
|
||||
while (left > 0)
|
||||
{
|
||||
if (*buf == QSE_T('\0'))
|
||||
{
|
||||
if (qse_fputc(*buf,fp) == QSE_CHAR_EOF) return -1;
|
||||
left -= 1; buf += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int chunk = (left > QSE_TYPE_MAX(int))? QSE_TYPE_MAX(int): (int)left;
|
||||
int n = qse_fprintf (fp, QSE_T("%.*s"), chunk, buf);
|
||||
if (n < 0 || n > chunk) return -1;
|
||||
left -= n; buf += n;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void* allocMem (size_t n) throw ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ::HeapAlloc (heap, 0, n);
|
||||
#else
|
||||
return ::malloc (n);
|
||||
#endif
|
||||
}
|
||||
|
||||
void* reallocMem (void* ptr, size_t n) throw ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (ptr == NULL)
|
||||
return ::HeapAlloc (heap, 0, n);
|
||||
else
|
||||
return ::HeapReAlloc (heap, 0, ptr, n);
|
||||
#else
|
||||
return ::realloc (ptr, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
void freeMem (void* ptr) throw ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::HeapFree (heap, 0, ptr);
|
||||
#else
|
||||
::free (ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
const char_t* srcInName;
|
||||
const char_t* srcOutName;
|
||||
|
||||
int idLastSleep;
|
||||
|
||||
#ifdef _WIN32
|
||||
void* heap;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
static BOOL WINAPI stop_run (DWORD ctrl_type)
|
||||
{
|
||||
if (ctrl_type == CTRL_C_EVENT ||
|
||||
ctrl_type == CTRL_CLOSE_EVENT)
|
||||
{
|
||||
if (app_awk) app_awk->stop ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
|
||||
static int setsignal (int sig, void(*handler)(int), int restart)
|
||||
{
|
||||
struct sigaction sa_int;
|
||||
|
||||
sa_int.sa_handler = handler;
|
||||
sigemptyset (&sa_int.sa_mask);
|
||||
|
||||
sa_int.sa_flags = 0;
|
||||
|
||||
if (restart)
|
||||
{
|
||||
#ifdef SA_RESTART
|
||||
sa_int.sa_flags |= SA_RESTART;
|
||||
#endif
|
||||
}
|
||||
if (line > 0)
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s at LINE %lu\n"), msg, line);
|
||||
else
|
||||
{
|
||||
#ifdef SA_INTERRUPT
|
||||
sa_int.sa_flags |= SA_INTERRUPT;
|
||||
#endif
|
||||
}
|
||||
return sigaction (sig, &sa_int, NULL);
|
||||
}
|
||||
|
||||
static void stop_run (int sig)
|
||||
{
|
||||
int e = errno;
|
||||
if (app_awk) app_awk->stop ();
|
||||
errno = e;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_intr_run (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler (stop_run, TRUE);
|
||||
#else
|
||||
/*setsignal (SIGINT, stop_run, 1); TO BE MORE COMPATIBLE WITH WIN32*/
|
||||
setsignal (SIGINT, stop_run, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void unset_intr_run (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler (stop_run, FALSE);
|
||||
#else
|
||||
setsignal (SIGINT, SIG_DFL, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_error (const qse_char_t* msg)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
const qse_char_t* name;
|
||||
MyAwk::Option opt;
|
||||
} otab[] =
|
||||
{
|
||||
{ QSE_T("implicit"), MyAwk::OPT_IMPLICIT },
|
||||
{ QSE_T("explicit"), MyAwk::OPT_EXPLICIT },
|
||||
{ QSE_T("bxor"), MyAwk::OPT_BXOR },
|
||||
{ QSE_T("shift"), MyAwk::OPT_SHIFT },
|
||||
{ QSE_T("idiv"), MyAwk::OPT_IDIV },
|
||||
{ QSE_T("rio"), MyAwk::OPT_RIO },
|
||||
{ QSE_T("rwpipe"), MyAwk::OPT_RWPIPE },
|
||||
{ QSE_T("newline"), MyAwk::OPT_NEWLINE },
|
||||
{ QSE_T("stripspaces"), MyAwk::OPT_STRIPSPACES },
|
||||
{ QSE_T("nextofile"), MyAwk::OPT_NEXTOFILE },
|
||||
{ QSE_T("crlf"), MyAwk::OPT_CRLF },
|
||||
{ QSE_T("reset"), MyAwk::OPT_RESET },
|
||||
{ QSE_T("maptovar"), MyAwk::OPT_MAPTOVAR },
|
||||
{ QSE_T("pablock"), MyAwk::OPT_PABLOCK }
|
||||
};
|
||||
|
||||
static void print_usage (const qse_char_t* argv0)
|
||||
{
|
||||
const qse_char_t* base;
|
||||
int j;
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
|
||||
base = qse_strrchr(argv0, QSE_T('/'));
|
||||
if (base == QSE_NULL) base = qse_strrchr(argv0, QSE_T('\\'));
|
||||
if (base == QSE_NULL) base = argv0; else base++;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("Usage: %s [-si file]? [-so file]? [-ci file]* [-co file]* [-w o:n]* \n"), base);
|
||||
qse_printf (QSE_T(" -si file Specify the input source file\n"));
|
||||
qse_printf (QSE_T(" The source code is read from stdin when it is not specified\n"));
|
||||
qse_printf (QSE_T(" -so file Specify the output source file\n"));
|
||||
qse_printf (QSE_T(" The deparsed code is not output when is it not specified\n"));
|
||||
qse_printf (QSE_T(" -ci file Specify the input console file\n"));
|
||||
qse_printf (QSE_T(" -co file Specify the output console file\n"));
|
||||
qse_printf (QSE_T(" -w o:n Specify an old and new word pair\n"));
|
||||
qse_printf (QSE_T(" o - an original word\n"));
|
||||
qse_printf (QSE_T(" n - the new word to replace the original\n"));
|
||||
qse_printf (QSE_T(" -v Print extra messages\n"));
|
||||
static int run_awk (QSE::StdAwk& awk)
|
||||
{
|
||||
QSE::StdAwk::Run* run;
|
||||
|
||||
const qse_char_t* script = QSE_T(
|
||||
"function pa (x) {\n"
|
||||
" reset ret;\n"
|
||||
" for (i in x) { print i, \"=>\", x[i]; ret += x[i]; }\n"
|
||||
" return ret;\n"
|
||||
"}\n"
|
||||
"function pb (x) {\n"
|
||||
" reset ret;\n"
|
||||
" for (i in x) { ret[-i] = -x[i]; }\n"
|
||||
" return ret;\n"
|
||||
"}"
|
||||
);
|
||||
|
||||
qse_printf (QSE_T("\nYou may specify the following options to change the behavior of the interpreter.\n"));
|
||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||
QSE::StdAwk::SourceString in (script);
|
||||
QSE::StdAwk::SourceFile out (QSE_T("awk07.out"));
|
||||
|
||||
// parse the script and deparse it to awk07.out
|
||||
run = awk.parse (&in, &out);
|
||||
if (run == QSE_NULL) return -1;
|
||||
|
||||
QSE::StdAwk::Value arg[1];
|
||||
|
||||
for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
qse_printf (QSE_T(" -%-20s -no%-20s\n"), otab[j].name, otab[j].name);
|
||||
if (arg[0].setIndexedInt (
|
||||
run, QSE::StdAwk::Value::IntIndex(i), i*20) <= -1) return -1;
|
||||
}
|
||||
|
||||
QSE::StdAwk::Value r;
|
||||
|
||||
// call the 'pa' function
|
||||
if (awk.call (QSE_T("pa"), &r, arg, QSE_COUNTOF(arg)) <= -1) return -1;
|
||||
|
||||
// output the result in various types
|
||||
qse_printf (QSE_T("RESULT: (int) [%lld]\n"), (long long)r.toInt());
|
||||
qse_printf (QSE_T(" (real) [%Lf]\n"), (long double)r.toReal());
|
||||
qse_printf (QSE_T(" (str) [%s]\n"), r.toStr(QSE_NULL));
|
||||
|
||||
// call the 'pb' function
|
||||
if (awk.call (QSE_T("pb"), &r, arg, QSE_COUNTOF(arg)) <= -1) return -1;
|
||||
|
||||
// output the returned map.
|
||||
QSE_ASSERT (r.isIndexed());
|
||||
|
||||
QSE::StdAwk::Value::IndexIterator iter;
|
||||
QSE::StdAwk::Value::Index idx;
|
||||
QSE::StdAwk::Value v;
|
||||
|
||||
qse_printf (QSE_T("RESULT:\n"));
|
||||
|
||||
iter = r.getFirstIndex (&idx);
|
||||
while (iter != QSE::StdAwk::Value::IndexIterator::END)
|
||||
{
|
||||
if (r.getIndexed (idx, &v) <= -1) return -1;
|
||||
|
||||
qse_printf (QSE_T("\t[%.*s]=>[%lld]\n"),
|
||||
(int)idx.len, idx.ptr, (long long)v.toInt());
|
||||
|
||||
iter = r.getNextIndex (&idx, iter);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
MyAwk awk;
|
||||
MyAwk::Run* run;
|
||||
QSE::StdAwk awk;
|
||||
|
||||
int mode = 0;
|
||||
const qse_char_t* srcin = QSE_T("");
|
||||
const qse_char_t* srcout = NULL;
|
||||
qse_size_t nsrcins = 0;
|
||||
qse_size_t nsrcouts = 0;
|
||||
int ret = awk.open();
|
||||
|
||||
if (awk.open() <= -1)
|
||||
{
|
||||
print_error (awk.getErrorMessage());
|
||||
return -1;
|
||||
}
|
||||
// allow returning a map from a function and enable 'reset'
|
||||
awk.setOption (
|
||||
awk.getOption() |
|
||||
QSE::StdAwk::OPT_MAPTOVAR |
|
||||
QSE::StdAwk::OPT_RESET);
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk05")) <= -1)
|
||||
{
|
||||
print_error (awk.getErrorMessage());
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
if (ret >= 0) ret = run_awk (awk);
|
||||
if (ret <= -1) print_error (awk.getErrorLine(), awk.getErrorMessage());
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (mode == 0)
|
||||
{
|
||||
if (qse_strcmp(argv[i], QSE_T("-si")) == 0) mode = 1;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-so")) == 0) mode = 2;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-ci")) == 0) mode = 3;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-co")) == 0) mode = 4;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-w")) == 0) mode = 5;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-v")) == 0)
|
||||
{
|
||||
verbose = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argv[i][0] == QSE_T('-'))
|
||||
{
|
||||
int j;
|
||||
|
||||
if (argv[i][1] == QSE_T('n') && argv[i][2] == QSE_T('o'))
|
||||
{
|
||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||
{
|
||||
if (qse_strcmp(&argv[i][3], otab[j].name) == 0)
|
||||
{
|
||||
awk.setOption (awk.getOption() & ~otab[j].opt);
|
||||
goto ok_valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||
{
|
||||
if (qse_strcmp(&argv[i][1], otab[j].name) == 0)
|
||||
{
|
||||
awk.setOption (awk.getOption() | otab[j].opt);
|
||||
goto ok_valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
|
||||
ok_valid:
|
||||
;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argv[i][0] == QSE_T('-'))
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == 1) // source input
|
||||
{
|
||||
if (nsrcins != 0)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcin = argv[i];
|
||||
nsrcins++;
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 2) // source output
|
||||
{
|
||||
if (nsrcouts != 0)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcout = argv[i];
|
||||
nsrcouts++;
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 3) // console input
|
||||
{
|
||||
if (awk.addArgument (argv[i]) <= -1)
|
||||
{
|
||||
print_error (QSE_T("too many console inputs"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 4) // console output
|
||||
{
|
||||
if (awk.addConsoleOutput (argv[i]) <= -1)
|
||||
{
|
||||
print_error (QSE_T("too many console outputs"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 5) // word replacement
|
||||
{
|
||||
const qse_char_t* p;
|
||||
qse_size_t l;
|
||||
|
||||
p = qse_strchr(argv[i], QSE_T(':'));
|
||||
if (p == QSE_NULL)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l = qse_strlen (argv[i]);
|
||||
|
||||
awk.setWord (
|
||||
argv[i], p - argv[i],
|
||||
p + 1, l - (p - argv[i] + 1));
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode != 0)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
run = awk.parse (srcin, srcout);
|
||||
if (run == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"),
|
||||
awk.getErrorLine(), awk.getErrorMessage());
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
awk.enableRunCallback ();
|
||||
app_awk = &awk;
|
||||
|
||||
if (awk.loop () <= -1)
|
||||
{
|
||||
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
||||
awk.getErrorLine(), awk.getErrorMessage());
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
MyAwk::Return args[2];
|
||||
|
||||
args[0].setRun (run);
|
||||
args[1].setRun (run);
|
||||
|
||||
if (awk.call (QSE_T("add"), args, 2) <= -1)
|
||||
{
|
||||
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
||||
awk.getErrorLine(), awk.getErrorMessage());
|
||||
awk.close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
app_awk = QSE_NULL;
|
||||
awk.close ();
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
|
671
qse/samples/awk/awk08.cpp
Normal file
671
qse/samples/awk/awk08.cpp
Normal file
@ -0,0 +1,671 @@
|
||||
/*
|
||||
* $Id: Awk.cpp 341 2008-08-20 10:58:19Z baconevi $
|
||||
*
|
||||
Copyright 2006-2009 Chung, Hyung-Hwan.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include <qse/awk/StdAwk.hpp>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <qse/cmn/main.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
class MyAwk;
|
||||
#ifdef _WIN32
|
||||
static BOOL WINAPI stop_run (DWORD ctrl_type);
|
||||
#else
|
||||
static void stop_run (int sig);
|
||||
#endif
|
||||
|
||||
static void set_intr_run (void);
|
||||
static void unset_intr_run (void);
|
||||
|
||||
MyAwk* app_awk = QSE_NULL;
|
||||
static bool verbose = false;
|
||||
|
||||
class MyAwk: public QSE::StdAwk
|
||||
{
|
||||
public:
|
||||
MyAwk (): srcInName(QSE_NULL), srcOutName(QSE_NULL)
|
||||
|
||||
{
|
||||
#ifdef _WIN32
|
||||
heap = QSE_NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
~MyAwk ()
|
||||
{
|
||||
close ();
|
||||
}
|
||||
|
||||
int open ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
QSE_ASSERT (heap == QSE_NULL);
|
||||
heap = ::HeapCreate (0, 1000000, 1000000);
|
||||
if (heap == QSE_NULL) return -1;
|
||||
#endif
|
||||
|
||||
int n = StdAwk::open ();
|
||||
if (n <= -1)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HeapDestroy (heap);
|
||||
heap = QSE_NULL;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
idLastSleep = addGlobal (QSE_T("LAST_SLEEP"));
|
||||
if (idLastSleep <= -1) goto failure;
|
||||
|
||||
if (addFunction (QSE_T("sleep"), 1, 1,
|
||||
(FunctionHandler)&MyAwk::sleep) <= -1) goto failure;
|
||||
|
||||
if (addFunction (QSE_T("sumintarray"), 1, 1,
|
||||
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto failure;
|
||||
|
||||
if (addFunction (QSE_T("arrayindices"), 1, 1,
|
||||
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto failure;
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
StdAwk::close ();
|
||||
|
||||
#ifdef _WIN32
|
||||
HeapDestroy (heap);
|
||||
heap = QSE_NULL;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
void close ()
|
||||
{
|
||||
StdAwk::close ();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (heap != QSE_NULL)
|
||||
{
|
||||
HeapDestroy (heap);
|
||||
heap = QSE_NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int sleep (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
run.setError (ERR_INVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
long_t x = args[0].toInt();
|
||||
|
||||
/*Argument arg;
|
||||
if (run.getGlobal(idLastSleep, arg) == 0)
|
||||
qse_printf (QSE_T("GOOD: [%d]\n"), (int)arg.toInt());
|
||||
else { qse_printf (QSE_T("BAD:\n")); }
|
||||
*/
|
||||
|
||||
if (run.setGlobal (idLastSleep, x) <= -1) return -1;
|
||||
|
||||
#ifdef _WIN32
|
||||
::Sleep ((DWORD)(x * 1000));
|
||||
return ret.set ((long_t)0);
|
||||
#else
|
||||
return ret.set ((long_t)::sleep (x));
|
||||
#endif
|
||||
}
|
||||
|
||||
int sumintarray (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
long_t x = 0;
|
||||
|
||||
if (args[0].isIndexed())
|
||||
{
|
||||
Argument idx(run), val(run);
|
||||
|
||||
int n = args[0].getFirstIndex (idx);
|
||||
while (n > 0)
|
||||
{
|
||||
size_t len;
|
||||
const char_t* ptr = idx.toStr(&len);
|
||||
|
||||
if (args[0].getIndexed(ptr, len, val) <= -1) return -1;
|
||||
x += val.toInt ();
|
||||
|
||||
n = args[0].getNextIndex (idx);
|
||||
}
|
||||
if (n != 0) return -1;
|
||||
}
|
||||
else x += args[0].toInt();
|
||||
|
||||
return ret.set (x);
|
||||
}
|
||||
|
||||
int arrayindices (Run& run, Return& ret, const Argument* args, size_t nargs,
|
||||
const char_t* name, size_t len)
|
||||
{
|
||||
if (!args[0].isIndexed()) return 0;
|
||||
|
||||
Argument idx (run);
|
||||
long_t i;
|
||||
|
||||
int n = args[0].getFirstIndex (idx);
|
||||
for (i = 0; n > 0; i++)
|
||||
{
|
||||
size_t len;
|
||||
const char_t* ptr = idx.toStr(&len);
|
||||
n = args[0].getNextIndex (idx);
|
||||
if (ret.setIndexed (i, ptr, len) <= -1) return -1;
|
||||
}
|
||||
if (n != 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Run* parse (const char_t* in, const char_t* out)
|
||||
{
|
||||
srcInName = in;
|
||||
srcOutName = out;
|
||||
return StdAwk::parse ();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool onLoopEnter (Run& run)
|
||||
{
|
||||
set_intr_run ();
|
||||
return true;
|
||||
}
|
||||
|
||||
void onLoopExit (Run& run, const Argument& ret)
|
||||
{
|
||||
unset_intr_run ();
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
size_t len;
|
||||
const char_t* ptr = ret.toStr (&len);
|
||||
qse_printf (QSE_T("*** return [%.*s] ***\n"), (int)len, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int openSource (Source& io)
|
||||
{
|
||||
Source::Mode mode = io.getMode();
|
||||
FILE* fp = QSE_NULL;
|
||||
|
||||
// TODO: use sio instead of stdio
|
||||
if (mode == Source::READ)
|
||||
{
|
||||
if (srcInName == QSE_NULL)
|
||||
{
|
||||
io.setHandle (stdin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srcInName[0] == QSE_T('\0')) fp = stdin;
|
||||
else fp = qse_fopen (srcInName, QSE_T("r"));
|
||||
}
|
||||
else if (mode == Source::WRITE)
|
||||
{
|
||||
if (srcOutName == QSE_NULL)
|
||||
{
|
||||
io.setHandle (stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srcOutName[0] == QSE_T('\0')) fp = stdout;
|
||||
else fp = qse_fopen (srcOutName, QSE_T("w"));
|
||||
}
|
||||
|
||||
if (fp == QSE_NULL) return -1;
|
||||
io.setHandle (fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int closeSource (Source& io)
|
||||
{
|
||||
FILE* fp = (FILE*)io.getHandle();
|
||||
if (fp == stdout || fp == stderr) fflush (fp);
|
||||
if (fp != stdin && fp != stdout && fp != stderr) fclose (fp);
|
||||
io.setHandle (QSE_NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t readSource (Source& io, char_t* buf, size_t len)
|
||||
{
|
||||
FILE* fp = (FILE*)io.getHandle();
|
||||
ssize_t n = 0;
|
||||
|
||||
while (n < (ssize_t)len)
|
||||
{
|
||||
qse_cint_t c = qse_fgetc (fp);
|
||||
if (c == QSE_CHAR_EOF)
|
||||
{
|
||||
if (qse_ferror(fp)) n = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
buf[n++] = c;
|
||||
if (c == QSE_T('\n')) break;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t writeSource (Source& io, char_t* buf, size_t len)
|
||||
{
|
||||
FILE* fp = (FILE*)io.getHandle();
|
||||
size_t left = len;
|
||||
|
||||
while (left > 0)
|
||||
{
|
||||
if (*buf == QSE_T('\0'))
|
||||
{
|
||||
if (qse_fputc(*buf,fp) == QSE_CHAR_EOF) return -1;
|
||||
left -= 1; buf += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int chunk = (left > QSE_TYPE_MAX(int))? QSE_TYPE_MAX(int): (int)left;
|
||||
int n = qse_fprintf (fp, QSE_T("%.*s"), chunk, buf);
|
||||
if (n < 0 || n > chunk) return -1;
|
||||
left -= n; buf += n;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void* allocMem (size_t n) throw ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return ::HeapAlloc (heap, 0, n);
|
||||
#else
|
||||
return ::malloc (n);
|
||||
#endif
|
||||
}
|
||||
|
||||
void* reallocMem (void* ptr, size_t n) throw ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (ptr == NULL)
|
||||
return ::HeapAlloc (heap, 0, n);
|
||||
else
|
||||
return ::HeapReAlloc (heap, 0, ptr, n);
|
||||
#else
|
||||
return ::realloc (ptr, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
void freeMem (void* ptr) throw ()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
::HeapFree (heap, 0, ptr);
|
||||
#else
|
||||
::free (ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
const char_t* srcInName;
|
||||
const char_t* srcOutName;
|
||||
|
||||
int idLastSleep;
|
||||
|
||||
#ifdef _WIN32
|
||||
void* heap;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
static BOOL WINAPI stop_run (DWORD ctrl_type)
|
||||
{
|
||||
if (ctrl_type == CTRL_C_EVENT ||
|
||||
ctrl_type == CTRL_CLOSE_EVENT)
|
||||
{
|
||||
if (app_awk) app_awk->stop ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
|
||||
static int setsignal (int sig, void(*handler)(int), int restart)
|
||||
{
|
||||
struct sigaction sa_int;
|
||||
|
||||
sa_int.sa_handler = handler;
|
||||
sigemptyset (&sa_int.sa_mask);
|
||||
|
||||
sa_int.sa_flags = 0;
|
||||
|
||||
if (restart)
|
||||
{
|
||||
#ifdef SA_RESTART
|
||||
sa_int.sa_flags |= SA_RESTART;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SA_INTERRUPT
|
||||
sa_int.sa_flags |= SA_INTERRUPT;
|
||||
#endif
|
||||
}
|
||||
return sigaction (sig, &sa_int, NULL);
|
||||
}
|
||||
|
||||
static void stop_run (int sig)
|
||||
{
|
||||
int e = errno;
|
||||
if (app_awk) app_awk->stop ();
|
||||
errno = e;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_intr_run (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler (stop_run, TRUE);
|
||||
#else
|
||||
/*setsignal (SIGINT, stop_run, 1); TO BE MORE COMPATIBLE WITH WIN32*/
|
||||
setsignal (SIGINT, stop_run, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void unset_intr_run (void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleCtrlHandler (stop_run, FALSE);
|
||||
#else
|
||||
setsignal (SIGINT, SIG_DFL, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_error (const qse_char_t* msg)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR, QSE_T("ERROR: %s\n"), msg);
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
const qse_char_t* name;
|
||||
MyAwk::Option opt;
|
||||
} otab[] =
|
||||
{
|
||||
{ QSE_T("implicit"), MyAwk::OPT_IMPLICIT },
|
||||
{ QSE_T("explicit"), MyAwk::OPT_EXPLICIT },
|
||||
{ QSE_T("bxor"), MyAwk::OPT_BXOR },
|
||||
{ QSE_T("shift"), MyAwk::OPT_SHIFT },
|
||||
{ QSE_T("idiv"), MyAwk::OPT_IDIV },
|
||||
{ QSE_T("rio"), MyAwk::OPT_RIO },
|
||||
{ QSE_T("rwpipe"), MyAwk::OPT_RWPIPE },
|
||||
{ QSE_T("newline"), MyAwk::OPT_NEWLINE },
|
||||
{ QSE_T("stripspaces"), MyAwk::OPT_STRIPSPACES },
|
||||
{ QSE_T("nextofile"), MyAwk::OPT_NEXTOFILE },
|
||||
{ QSE_T("crlf"), MyAwk::OPT_CRLF },
|
||||
{ QSE_T("reset"), MyAwk::OPT_RESET },
|
||||
{ QSE_T("maptovar"), MyAwk::OPT_MAPTOVAR },
|
||||
{ QSE_T("pablock"), MyAwk::OPT_PABLOCK }
|
||||
};
|
||||
|
||||
static void print_usage (const qse_char_t* argv0)
|
||||
{
|
||||
const qse_char_t* base;
|
||||
int j;
|
||||
|
||||
base = qse_strrchr(argv0, QSE_T('/'));
|
||||
if (base == QSE_NULL) base = qse_strrchr(argv0, QSE_T('\\'));
|
||||
if (base == QSE_NULL) base = argv0; else base++;
|
||||
|
||||
qse_printf (QSE_T("Usage: %s [-si file]? [-so file]? [-ci file]* [-co file]* [-w o:n]* \n"), base);
|
||||
qse_printf (QSE_T(" -si file Specify the input source file\n"));
|
||||
qse_printf (QSE_T(" The source code is read from stdin when it is not specified\n"));
|
||||
qse_printf (QSE_T(" -so file Specify the output source file\n"));
|
||||
qse_printf (QSE_T(" The deparsed code is not output when is it not specified\n"));
|
||||
qse_printf (QSE_T(" -ci file Specify the input console file\n"));
|
||||
qse_printf (QSE_T(" -co file Specify the output console file\n"));
|
||||
qse_printf (QSE_T(" -w o:n Specify an old and new word pair\n"));
|
||||
qse_printf (QSE_T(" o - an original word\n"));
|
||||
qse_printf (QSE_T(" n - the new word to replace the original\n"));
|
||||
qse_printf (QSE_T(" -v Print extra messages\n"));
|
||||
|
||||
|
||||
qse_printf (QSE_T("\nYou may specify the following options to change the behavior of the interpreter.\n"));
|
||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||
{
|
||||
qse_printf (QSE_T(" -%-20s -no%-20s\n"), otab[j].name, otab[j].name);
|
||||
}
|
||||
}
|
||||
|
||||
static int awk_main (int argc, qse_char_t* argv[])
|
||||
{
|
||||
MyAwk awk;
|
||||
MyAwk::Run* run;
|
||||
|
||||
int mode = 0;
|
||||
const qse_char_t* srcin = QSE_T("");
|
||||
const qse_char_t* srcout = NULL;
|
||||
qse_size_t nsrcins = 0;
|
||||
qse_size_t nsrcouts = 0;
|
||||
|
||||
if (awk.open() <= -1)
|
||||
{
|
||||
print_error (awk.getErrorMessage());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ARGV[0]
|
||||
if (awk.addArgument (QSE_T("awk05")) <= -1)
|
||||
{
|
||||
print_error (awk.getErrorMessage());
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (mode == 0)
|
||||
{
|
||||
if (qse_strcmp(argv[i], QSE_T("-si")) == 0) mode = 1;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-so")) == 0) mode = 2;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-ci")) == 0) mode = 3;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-co")) == 0) mode = 4;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-w")) == 0) mode = 5;
|
||||
else if (qse_strcmp(argv[i], QSE_T("-v")) == 0)
|
||||
{
|
||||
verbose = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argv[i][0] == QSE_T('-'))
|
||||
{
|
||||
int j;
|
||||
|
||||
if (argv[i][1] == QSE_T('n') && argv[i][2] == QSE_T('o'))
|
||||
{
|
||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||
{
|
||||
if (qse_strcmp(&argv[i][3], otab[j].name) == 0)
|
||||
{
|
||||
awk.setOption (awk.getOption() & ~otab[j].opt);
|
||||
goto ok_valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < (int)QSE_COUNTOF(otab); j++)
|
||||
{
|
||||
if (qse_strcmp(&argv[i][1], otab[j].name) == 0)
|
||||
{
|
||||
awk.setOption (awk.getOption() | otab[j].opt);
|
||||
goto ok_valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
|
||||
ok_valid:
|
||||
;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argv[i][0] == QSE_T('-'))
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == 1) // source input
|
||||
{
|
||||
if (nsrcins != 0)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcin = argv[i];
|
||||
nsrcins++;
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 2) // source output
|
||||
{
|
||||
if (nsrcouts != 0)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
srcout = argv[i];
|
||||
nsrcouts++;
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 3) // console input
|
||||
{
|
||||
if (awk.addArgument (argv[i]) <= -1)
|
||||
{
|
||||
print_error (QSE_T("too many console inputs"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 4) // console output
|
||||
{
|
||||
if (awk.addConsoleOutput (argv[i]) <= -1)
|
||||
{
|
||||
print_error (QSE_T("too many console outputs"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
else if (mode == 5) // word replacement
|
||||
{
|
||||
const qse_char_t* p;
|
||||
qse_size_t l;
|
||||
|
||||
p = qse_strchr(argv[i], QSE_T(':'));
|
||||
if (p == QSE_NULL)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
l = qse_strlen (argv[i]);
|
||||
|
||||
awk.setWord (
|
||||
argv[i], p - argv[i],
|
||||
p + 1, l - (p - argv[i] + 1));
|
||||
|
||||
mode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode != 0)
|
||||
{
|
||||
print_usage (argv[0]);
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
run = awk.parse (srcin, srcout);
|
||||
if (run == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (stderr, QSE_T("cannot parse: LINE[%d] %s\n"),
|
||||
awk.getErrorLine(), awk.getErrorMessage());
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
awk.enableRunCallback ();
|
||||
app_awk = &awk;
|
||||
|
||||
if (awk.loop () <= -1)
|
||||
{
|
||||
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
||||
awk.getErrorLine(), awk.getErrorMessage());
|
||||
awk.close ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
MyAwk::Return args[2];
|
||||
|
||||
args[0].setRun (run);
|
||||
args[1].setRun (run);
|
||||
|
||||
if (awk.call (QSE_T("add"), args, 2) <= -1)
|
||||
{
|
||||
qse_fprintf (stderr, QSE_T("cannot run: LINE[%d] %s\n"),
|
||||
awk.getErrorLine(), awk.getErrorMessage());
|
||||
awk.close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
app_awk = QSE_NULL;
|
||||
awk.close ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_main (int argc, qse_achar_t* argv[])
|
||||
{
|
||||
return qse_runmain (argc,argv,awk_main);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user