diff --git a/qse/include/qse/sys/Makefile.am b/qse/include/qse/sys/Makefile.am index c5f1610f..5928ec69 100644 --- a/qse/include/qse/sys/Makefile.am +++ b/qse/include/qse/sys/Makefile.am @@ -10,6 +10,7 @@ pkginclude_HEADERS = \ if ENABLE_CXX pkginclude_HEADERS += \ - SocketAddress.hpp + SocketAddress.hpp \ + Socket.hpp endif diff --git a/qse/include/qse/sys/Makefile.in b/qse/include/qse/sys/Makefile.in index 997107c8..bcab59ad 100644 --- a/qse/include/qse/sys/Makefile.in +++ b/qse/include/qse/sys/Makefile.in @@ -78,7 +78,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_CXX_TRUE@am__append_1 = \ -@ENABLE_CXX_TRUE@ SocketAddress.hpp +@ENABLE_CXX_TRUE@ SocketAddress.hpp \ +@ENABLE_CXX_TRUE@ Socket.hpp subdir = include/qse/sys DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ @@ -118,7 +119,7 @@ am__can_run_installinfo = \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__pkginclude_HEADERS_DIST = cnd.h intr.h mtx.h mux.h rwl.h thr.h \ - SocketAddress.hpp + SocketAddress.hpp Socket.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ diff --git a/qse/include/qse/sys/SocketAddress.hpp b/qse/include/qse/sys/SocketAddress.hpp index fd12089b..25ae561a 100644 --- a/qse/include/qse/sys/SocketAddress.hpp +++ b/qse/include/qse/sys/SocketAddress.hpp @@ -41,7 +41,7 @@ public: SocketAddress (const qse_skad_t* skad); SocketAddress (const qse_nwad_t* nwad); SocketAddress (const struct sockaddr* ptr, int len); - + int getFamily () const; qse_skad_t* getAddrPtr() diff --git a/qse/lib/awk/fnc.c b/qse/lib/awk/fnc.c index 1c33fb7a..37bb07d1 100644 --- a/qse/lib/awk/fnc.c +++ b/qse/lib/awk/fnc.c @@ -58,27 +58,32 @@ static qse_awk_fnc_t sysfnctab[] = { {QSE_T("int"), 3}, 0, { {1, 1, QSE_NULL}, fnc_int, 0 }, QSE_NULL}, /* string functions */ - { {QSE_T("index"), 5}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_index, 0 }, QSE_NULL}, - { {QSE_T("substr"), 6}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_substr, 0 }, QSE_NULL}, - { {QSE_T("length"), 6}, 1, { {0, 1, QSE_NULL}, qse_awk_fnc_length, 0 }, QSE_NULL}, - { {QSE_T("split"), 5}, 0, { {2, 3, QSE_T("vrx")}, qse_awk_fnc_split, 0 }, QSE_NULL}, - { {QSE_T("tolower"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_tolower, 0 }, QSE_NULL}, - { {QSE_T("toupper"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_toupper, 0 }, QSE_NULL}, - { {QSE_T("gsub"), 4}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 }, QSE_NULL}, - { {QSE_T("sub"), 3}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_sub, 0 }, QSE_NULL}, - { {QSE_T("match"), 5}, 0, { {2, 3, QSE_T("vxv")}, qse_awk_fnc_match, 0 }, QSE_NULL}, - { {QSE_T("sprintf"), 7}, 0, { {1, A_MAX, QSE_NULL}, qse_awk_fnc_sprintf, 0 }, QSE_NULL}, + { {QSE_T("index"), 5}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_index, 0 }, QSE_NULL}, + { {QSE_T("substr"), 6}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_substr, 0 }, QSE_NULL}, + { {QSE_T("length"), 6}, 1, { {0, 1, QSE_NULL}, qse_awk_fnc_length, 0 }, QSE_NULL}, + { {QSE_T("split"), 5}, 0, { {2, 3, QSE_T("vrx")}, qse_awk_fnc_split, 0 }, QSE_NULL}, + { {QSE_T("tolower"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_tolower, 0 }, QSE_NULL}, + { {QSE_T("toupper"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_toupper, 0 }, QSE_NULL}, + { {QSE_T("gsub"), 4}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 }, QSE_NULL}, + { {QSE_T("sub"), 3}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_sub, 0 }, QSE_NULL}, + { {QSE_T("match"), 5}, 0, { {2, 3, QSE_T("vxv")}, qse_awk_fnc_match, 0 }, QSE_NULL}, + { {QSE_T("sprintf"), 7}, 0, { {1, A_MAX, QSE_NULL}, qse_awk_fnc_sprintf, 0 }, QSE_NULL}, /* math functions */ - { {QSE_T("sin"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("cos"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("tan"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("atan"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("atan2"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("log"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("log10"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("exp"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, - { {QSE_T("sqrt"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL} + { {QSE_T("sin"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("cos"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("tan"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("atan"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("atan2"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("log"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("log10"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("exp"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("sqrt"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL}, + + /* time functions */ + { {QSE_T("mktime"), 6}, 0, { {A_MAX, 0, QSE_T("sys") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("strftime"), 8}, 0, { {A_MAX, 0, QSE_T("sys") }, QSE_NULL, 0 }, QSE_NULL}, + { {QSE_T("systime"), 7}, 0, { {A_MAX, 0, QSE_T("sys") }, QSE_NULL, 0 }, QSE_NULL} }; qse_awk_fnc_t* qse_awk_addfnc (qse_awk_t* awk, const qse_char_t* name, const qse_awk_fnc_spec_t* spec) @@ -90,7 +95,6 @@ qse_awk_fnc_t* qse_awk_addfnc (qse_awk_t* awk, const qse_char_t* name, const qse ncs.ptr = (qse_char_t*)name; ncs.len = qse_strlen (name); - if (ncs.len <= 0) { qse_awk_seterrnum (awk, QSE_AWK_EINVAL, QSE_NULL); @@ -1243,7 +1247,7 @@ int qse_awk_fnc_match (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) } int qse_awk_fnc_sprintf (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) -{ +{ qse_size_t nargs; qse_awk_val_t* a0; qse_str_t out, fbu; diff --git a/qse/lib/awk/mod-sys.c b/qse/lib/awk/mod-sys.c index a0d4cc22..c24df1fc 100644 --- a/qse/lib/awk/mod-sys.c +++ b/qse/lib/awk/mod-sys.c @@ -26,6 +26,7 @@ #include "mod-sys.h" #include +#include #include #include #include @@ -51,6 +52,7 @@ #endif #include /* getenv, system */ +#include static int fnc_fork (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) { @@ -496,6 +498,213 @@ static int fnc_settime (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) return 0; } +static int fnc_mktime (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) +{ + qse_ntime_t nt; + qse_size_t nargs; + qse_awk_val_t* retv; + + nargs = qse_awk_rtx_getnargs (rtx); + if (nargs >= 1) + { + int sign; + qse_char_t* str, * p, * end; + qse_size_t len; + qse_awk_val_t* a0; + qse_btime_t bt; + + a0 = qse_awk_rtx_getarg (rtx, 0); + str = qse_awk_rtx_getvalstr (rtx, a0, &len); + if (str == QSE_NULL) return -1; + + /* the string must be of the format YYYY MM DD HH MM SS[ DST] */ + p = str; + end = str + len; + QSE_MEMSET (&bt, 0, QSE_SIZEOF(bt)); + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.year = bt.year * 10 + (*p++ - QSE_T('0')); + bt.year *= sign; + bt.year -= 1900; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.mon = bt.mon * 10 + (*p++ - QSE_T('0')); + bt.mon *= sign; + bt.mon -= 1; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.mday = bt.mday * 10 + (*p++ - QSE_T('0')); + bt.mday *= sign; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.hour = bt.hour * 10 + (*p++ - QSE_T('0')); + bt.hour *= sign; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.min = bt.min * 10 + (*p++ - QSE_T('0')); + bt.min *= sign; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.sec = bt.sec * 10 + (*p++ - QSE_T('0')); + bt.sec *= sign; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + sign = 1; + if (p < end && *p == QSE_T('-')) { sign = -1; p++; } + while (p < end && QSE_ISDIGIT(*p)) bt.isdst = bt.isdst * 10 + (*p++ - QSE_T('0')); + bt.isdst *= sign; + while (p < end && (QSE_ISSPACE(*p) || *p == QSE_T('\0'))) p++; + + qse_awk_rtx_freevalstr (rtx, a0, str); + qse_timelocal (&bt, &nt); + } + else + { + /* get the current time when no argument is given */ + qse_gettime (&nt); + } + + retv = qse_awk_rtx_makeintval (rtx, nt.sec); + if (retv == QSE_NULL) return -1; + + qse_awk_rtx_setretval (rtx, retv); + return 0; +} + + +static int fnc_strftime (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) +{ + qse_mchar_t* fmt; + qse_size_t len; + qse_awk_val_t* retv; + + fmt = qse_awk_rtx_valtombsdup (rtx, qse_awk_rtx_getarg (rtx, 0), &len); + if (fmt) + { + qse_ntime_t nt; + qse_btime_t bt; + qse_awk_int_t tmpsec; + + nt.nsec = 0; + if (qse_awk_rtx_valtoint (rtx, qse_awk_rtx_getarg (rtx, 1), &tmpsec) <= -1) + { + nt.sec = 0; + } + else + { + nt.sec = tmpsec; + } + + if (qse_localtime (&nt, &bt) >= 0) + { + qse_mchar_t tmpbuf[64], * tmpptr; + struct tm tm; + qse_size_t sl; + + QSE_MEMSET (&tm, 0, QSE_SIZEOF(tm)); + tm.tm_year = bt.year; + tm.tm_mon = bt.mon; + tm.tm_mday = bt.mday; + tm.tm_hour = bt.hour; + tm.tm_min = bt.min; + tm.tm_sec = bt.sec; + tm.tm_isdst = bt.isdst; + + sl = strftime (tmpbuf, QSE_COUNTOF(tmpbuf), fmt, &tm); + if (sl <= 0 || sl >= QSE_COUNTOF(tmpbuf)) + { + /* buffer too small */ + qse_mchar_t* tmp; + qse_size_t tmpcapa, i, count = 0; + +/* +man strftime >>> + +RETURN VALUE + The strftime() function returns the number of bytes placed in the array s, not including the terminating null byte, provided the + string, including the terminating null byte, fits. Otherwise, it returns 0, and the contents of the array is undefined. (This + behavior applies since at least libc 4.4.4; very old versions of libc, such as libc 4.4.1, would return max if the array was too + small.) + + Note that the return value 0 does not necessarily indicate an error; for example, in many locales %p yields an empty string. + +-------------------------------------------------------------------------------------- +* +I use 'count' to limit the maximum number of retries when 0 is returned. +*/ + + for (i = 0; i < len;) + { + if (fmt[i] == QSE_MT('%')) + { + count++; /* the nubmer of % specifier */ + i++; + if (i < len) i++; + } + else i++; + } + + tmpptr = QSE_NULL; + tmpcapa = QSE_COUNTOF(tmpbuf); + if (tmpcapa < len) tmpcapa = len; + + do + { + if (count <= 0) + { + if (tmpptr) qse_awk_rtx_freemem (rtx, tmpptr); + tmpbuf[0] = QSE_MT('\0'); + tmpptr = tmpbuf; + break; + } + count--; + + tmpcapa *= 2; + tmp = qse_awk_rtx_reallocmem (rtx, tmpptr, tmpcapa * QSE_SIZEOF(*tmpptr)); + if (!tmp) + { + if (tmpptr) qse_awk_rtx_freemem (rtx, tmpptr); + tmpbuf[0] = QSE_MT('\0'); + tmpptr = tmpbuf; + break; + } + + tmpptr = tmp; + sl = strftime (tmpptr, tmpcapa, fmt, &tm); + } + while (sl <= 0 || sl >= tmpcapa); + } + else + { + tmpptr = tmpbuf; + } + qse_awk_rtx_freemem (rtx, fmt); + + retv = qse_awk_rtx_makestrvalwithmbs (rtx, tmpptr); + if (tmpptr && tmpptr != tmpbuf) qse_awk_rtx_freemem (rtx, tmpptr); + if (retv == QSE_NULL) return -1; + + qse_awk_rtx_setretval (rtx, retv); + } + else + { + qse_awk_rtx_freemem (rtx, fmt); + } + } + return 0; +} + static int fnc_getenv (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) { qse_mchar_t* var; @@ -544,7 +753,7 @@ static int fnc_getnwifcfg (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) if (qse_getnwifcfg (&cfg) >= 0) { - /* make a map value containg configuration */ + /* make a map value containg configuration */ qse_awk_int_t index, mtu; qse_char_t addr[128]; qse_char_t mask[128]; @@ -693,9 +902,12 @@ static fnctab_t fnctab[] = { QSE_T("gettime"), { { 0, 0, QSE_NULL }, fnc_gettime, 0 } }, { QSE_T("getuid"), { { 0, 0, QSE_NULL }, fnc_getuid, 0 } }, { QSE_T("kill"), { { 2, 2, QSE_NULL }, fnc_kill, 0 } }, + { QSE_T("mktime"), { { 0, 1, QSE_NULL }, fnc_mktime, 0 } }, { QSE_T("settime"), { { 1, 1, QSE_NULL }, fnc_settime, 0 } }, { QSE_T("sleep"), { { 1, 1, QSE_NULL }, fnc_sleep, 0 } }, + { QSE_T("strftime"), { { 2, 2, QSE_NULL }, fnc_strftime, 0 } }, { QSE_T("system"), { { 1, 1, QSE_NULL }, fnc_system, 0 } }, + { QSE_T("systime"), { { 0, 0, QSE_NULL }, fnc_gettime, 0 } }, /* alias to gettime() */ { QSE_T("wait"), { { 1, 1, QSE_NULL }, fnc_wait, 0 } } }; diff --git a/qse/lib/sys/Makefile.am b/qse/lib/sys/Makefile.am index 253f662d..4b3ba94f 100644 --- a/qse/lib/sys/Makefile.am +++ b/qse/lib/sys/Makefile.am @@ -20,7 +20,8 @@ libqsesys_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) if ENABLE_CXX lib_LTLIBRARIES += libqsesysxx.la libqsesysxx_la_SOURCES = \ - SocketAddress.cpp + SocketAddress.cpp \ + Socket.cpp libqsesysxx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined libqsesysxx_la_LIBADD = -lqsecmnxx -lqsecmn endif diff --git a/qse/lib/sys/Makefile.in b/qse/lib/sys/Makefile.in index a359e886..9fcf93da 100644 --- a/qse/lib/sys/Makefile.in +++ b/qse/lib/sys/Makefile.in @@ -140,8 +140,9 @@ libqsesys_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libqsesys_la_CFLAGS) \ $(CFLAGS) $(libqsesys_la_LDFLAGS) $(LDFLAGS) -o $@ libqsesysxx_la_DEPENDENCIES = -am__libqsesysxx_la_SOURCES_DIST = SocketAddress.cpp -@ENABLE_CXX_TRUE@am_libqsesysxx_la_OBJECTS = SocketAddress.lo +am__libqsesysxx_la_SOURCES_DIST = SocketAddress.cpp Socket.cpp +@ENABLE_CXX_TRUE@am_libqsesysxx_la_OBJECTS = SocketAddress.lo \ +@ENABLE_CXX_TRUE@ Socket.lo libqsesysxx_la_OBJECTS = $(am_libqsesysxx_la_OBJECTS) libqsesysxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -422,7 +423,8 @@ libqsesys_la_CFLAGS = $(PTHREAD_CFLAGS) libqsesys_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined libqsesys_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) @ENABLE_CXX_TRUE@libqsesysxx_la_SOURCES = \ -@ENABLE_CXX_TRUE@ SocketAddress.cpp +@ENABLE_CXX_TRUE@ SocketAddress.cpp \ +@ENABLE_CXX_TRUE@ Socket.cpp @ENABLE_CXX_TRUE@libqsesysxx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined @ENABLE_CXX_TRUE@libqsesysxx_la_LIBADD = -lqsecmnxx -lqsecmn @@ -508,6 +510,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesys_la-cnd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesys_la-intr.Plo@am__quote@ diff --git a/qse/lib/sys/SocketAddress.cpp b/qse/lib/sys/SocketAddress.cpp index f648e3ae..f831d6ca 100644 --- a/qse/lib/sys/SocketAddress.cpp +++ b/qse/lib/sys/SocketAddress.cpp @@ -132,7 +132,6 @@ void SocketAddress::setIpaddr (const qse_ip4ad_t* ipaddr) { struct sockaddr_in* v4 = (struct sockaddr_in*)&this->skad; QSE_MEMCPY (&v4->sin_addr, ipaddr, QSE_SIZEOF(*ipaddr)); - } #endif }