diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..5be3d4f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +libmawk author is Tibor 'Igor2' Palinkas +contact: http://igor2.repo.hu/contact.html + +Original mawk, from which libmawk forked: +Mike Brennan, brennan@whidbey.com. diff --git a/Changelog b/Changelog index d3752d3..d23ed88 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,22 @@ Changelog for libmawk ~~~~~~~~~~~~~~~~~~~~~ +libmawk 1.0.1 (released: 2019-02-26, r1307) + [build] -Fix: don't daisy-chain so symlinks (debian patch applied) + [build] -Add: install (3) and (7) manual pages + [build] -Add: scconfig --libarchdir, for /usr/lib64 + [build] -Add: install awklib in non-arch-dependent lib dir + [doc] -Add: AUTHORS file + [doc] -Update: COPYING: fsf address and formatting + [libmawk] -Add: handle --help and --version + [da_bin] -Fix: don't depend on sizeof(long) == 4 + [math] -Fix: if the result of non-NaN arithmetics is nan in emulated nan, rather make it DBL_MAX so it doesn't look like NaN + [math] -Fix: protect all basic math functions from nan input in emulated nan setup + [math] -Fix: for systems with unsafe NaN: manual atan2 arg validation + [math] -Fix: print and printf treats nan specially to make sure "nan" is printed on all platforms (including emulated NaN) + [math] -Fix: emulated nan strtonum: set endptr propery on nan + [math] -Fix: when there's no safe nan support, manual convert "nan" to nan on str->num conversion + -Cleanup: replace #warning with portable macro + libmawk 1.0.0 (released: 2018-11-11, r1276) [API] -Change: resume capable function call entries [build] -Fix: make clean should remove custom C test objects and executables diff --git a/README b/README index ebb6ee0..693dff6 100644 --- a/README +++ b/README @@ -23,8 +23,6 @@ will use symlinks instead of actual copying of files which is useful if you develop libmawk, the library itself. -Debian package can be installed from http://repo.hu/debian. - 4. Compatibility with mawk Compatibility with mawk is maintained to some degree. Currently libmawk diff --git a/Release_notes b/Release_notes index eebcfd1..fa6d4df 100644 --- a/Release_notes +++ b/Release_notes @@ -1,5 +1,6 @@ -Release notes for libmawk 1.0.0 +Release notes for libmawk 1.0.1 -This release introduces runlimits, better floating point handling on -corner cases (i.e. NaN) and memory leak cleanups. +Minor bugfix release; main focus is on fixing all packaging +related bugs learned in 1.0.0 and NaN related bugs on less common +architectures. diff --git a/scconfig/hooks.c b/scconfig/hooks.c index 9e24d00..77cf5ca 100644 --- a/scconfig/hooks.c +++ b/scconfig/hooks.c @@ -7,7 +7,7 @@ #define VER1 "1" #define VER2 "0" -#define VER3 "0" +#define VER3 "1" static void help(void) { @@ -21,6 +21,7 @@ printf(" --profile build profiling version if available (-pg)\n"); printf(" --symbols include symbols (add -g, but no -O0 or extra asserts)\n"); printf(" --numeric=int change the internal numeric type (default is double)\n"); + printf(" --libarchdir=relpath relative path under prefix for arch-lib-dir (e.g. lib64)\n"); printf("\n"); } @@ -42,6 +43,10 @@ } if (strcmp(key, "profile") == 0) { put("/local/profile", strue); + return 1; + } + if (strcmp(key, "libarchdir") == 0) { + put("/local/libarchdir", value); return 1; } if (strcmp(key, "numeric") == 0) { @@ -78,6 +83,7 @@ put("/local/debug", sfalse); put("/local/symbols", sfalse); put("/local/profile", sfalse); + put("/local/libarchdir", "lib"); report("Configuring libmawk.\n"); logprintf(0, "Configuring libmawk.\n"); @@ -105,6 +111,7 @@ put("/local/version/1", VER1); put("/local/version/2", VER2); put("/local/version/3", VER3); + /* if there was no custom requirement from the command line, run all requirements in non-fatal mode */ if (num_custom_reqs < 1) { @@ -137,6 +144,7 @@ require("cc/fpic", 0, 1); require("cc/soname", 0, 0); require("cc/rdynamic", 0, 0); + require("cc/pragma_message", 0, 0); require("fstools/chmodx", 0, 1); require("fstools/cp", 0, 1); require("fstools/rm", 0, 1); diff --git a/scconfig/src/default/db.c b/scconfig/src/default/db.c index 5d012a5..fcf53b7 100644 --- a/scconfig/src/default/db.c +++ b/scconfig/src/default/db.c @@ -129,7 +129,7 @@ int export(const char *fn, int export_empty, const char *root) { FILE *f; - int ret; + int ret = 0; /* ht_t *table; */ ht_entry_t *h; diff --git a/scconfig/src/default/deps_default.c b/scconfig/src/default/deps_default.c index da8c503..a086062 100644 --- a/scconfig/src/default/deps_default.c +++ b/scconfig/src/default/deps_default.c @@ -52,6 +52,9 @@ dep_add("cc/declspec/dllimport/*", find_declspec_dllimport); dep_add("cc/declspec/dllexport/*", find_declspec_dllexport); dep_add("cc/argmachine/*", find_cc_argmachine); + dep_add("cc/pragma_message/*", find_cc_pragma_message); + dep_add("cc/static_libgcc/*", find_cc_static_libgcc); + dep_add("libs/ldl", find_lib_ldl); dep_add("libs/LoadLibrary/*", find_lib_LoadLibrary); dep_add("libs/lpthread", find_lib_lpthread); @@ -71,6 +74,12 @@ dep_add("libs/proc/_spawnvp/*", find_proc__spawnvp); dep_add("libs/proc/fork/*", find_proc_fork); dep_add("libs/proc/wait/*", find_proc_wait); + dep_add("libs/proc/_getpid/*", find_proc__getpid); + dep_add("libs/proc/CreateProcessA/*",find_proc_CreateProcessA); + dep_add("libs/proc/getexecname/*", find_proc_getexecname); + dep_add("libs/proc/GetModuleFileNameA/*",find_proc_GetModuleFileNameA); + dep_add("libs/proc/shmget/*", find_proc_shmget); + dep_add("libs/proc/CreateFileMappingA/*",find_proc_CreateFileMappingA); dep_add("libs/fs/realpath/*", find_fs_realpath); dep_add("libs/fs/_fullpath/*", find_fs__fullpath); dep_add("libs/fs/readdir/*", find_fs_readdir); @@ -112,6 +121,8 @@ dep_add("libs/time/_mkgmtime/*", find_time_mkgmtime); dep_add("libs/time/gmtime_r/*", find_time_gmtime_r); dep_add("libs/time/gmtime_s/*", find_time_gmtime_s); + dep_add("libs/time/localtime_r/*", find_time_localtime_r); + dep_add("libs/time/localtime_s/*", find_time_localtime_s); dep_add("libs/env/main_3arg/*", find_main_arg3); dep_add("libs/env/putenv/*", find_putenv); dep_add("libs/env/setenv/*", find_setenv); @@ -161,6 +172,8 @@ dep_add("sys/types/void_ptr/*", find_types_void_ptr); dep_add("str/strcasecmp/*", find_strcasecmp); dep_add("str/strncasecmp/*", find_strncasecmp); + dep_add("str/stricmp/*", find_stricmp); + dep_add("str/strnicmp/*", find_strnicmp); dep_add("/internal/filelist/cmd", find_filelist); dep_add("/internal/filelist/method", find_filelist); diff --git a/scconfig/src/default/find.h b/scconfig/src/default/find.h index 4314e81..ae0bb93 100644 --- a/scconfig/src/default/find.h +++ b/scconfig/src/default/find.h @@ -24,6 +24,8 @@ int find_ldflags_so(const char *name, int logdepth, int fatal); int find_alloca(const char *name, int logdepth, int fatal); int find__exit(const char *name, int logdepth, int fatal); +int find_cc_pragma_message(const char *name, int logdepth, int fatal); +int find_cc_static_libgcc(const char *name, int logdepth, int fatal); /* libs */ int find_lib_ldl(const char *name, int logdepth, int fatal); @@ -76,6 +78,12 @@ int find_proc__spawnvp(const char *name, int logdepth, int fatal); int find_proc_fork(const char *name, int logdepth, int fatal); int find_proc_wait(const char *name, int logdepth, int fatal); +int find_proc__getpid(const char *name, int logdepth, int fatal); +int find_proc_CreateProcessA(const char *name, int logdepth, int fatal); +int find_proc_getexecname(const char *name, int logdepth, int fatal); +int find_proc_GetModuleFileNameA(const char *name, int logdepth, int fatal); +int find_proc_shmget(const char *name, int logdepth, int fatal); +int find_proc_CreateFileMappingA(const char *name, int logdepth, int fatal); /* fstools */ int find_fstools_cp(const char *name, int logdepth, int fatal); @@ -106,6 +114,8 @@ /* find_str.c */ int find_strcasecmp(const char *name, int logdepth, int fatal); int find_strncasecmp(const char *name, int logdepth, int fatal); +int find_stricmp(const char *name, int logdepth, int fatal); +int find_strnicmp(const char *name, int logdepth, int fatal); /* find_sys.c */ int find_sys_ptrwidth(const char *name, int logdepth, int fatal); @@ -129,6 +139,8 @@ int find_time_mkgmtime(const char *name, int logdepth, int fatal); int find_time_gmtime_s(const char *name, int logdepth, int fatal); int find_time_gmtime_r(const char *name, int logdepth, int fatal); +int find_time_localtime_s(const char *name, int logdepth, int fatal); +int find_time_localtime_r(const char *name, int logdepth, int fatal); /* find_types.c */ int find_types_stdint(const char *name, int logdepth, int fatal); diff --git a/scconfig/src/default/find_cc.c b/scconfig/src/default/find_cc.c index 6403459..cbb8cc0 100644 --- a/scconfig/src/default/find_cc.c +++ b/scconfig/src/default/find_cc.c @@ -1035,3 +1035,45 @@ return 1; } +int find_cc_pragma_message(const char *name, int logdepth, int fatal) +{ + const char *test_c = + NL "#include " + NL "#define DO_PRAGMA(arg) _Pragma(#arg)" + NL "#define TODO(x) DO_PRAGMA(message(\"TODO: \" #x))" + NL "TODO(test)" + NL "int main()" + NL "{" + NL " puts(\"OK\");" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for _Pragma(message)... "); + logprintf(logdepth, "find_cc_pragma_message: trying to find pragma_message...\n"); + logdepth++; + if (try(logdepth, NULL, test_c, "OK")) { + put("cc/pragma_message", strue); + report("Found.\n"); + return 0; + } + put("cc/pragma_message", sfalse); + report("Not found.\n"); + return 1; +} + +int find_cc_static_libgcc(const char *name, int logdepth, int fatal) +{ + const char *test_c = test_hello_world; + const char *key = "cc/static_libgcc"; + + require("cc/cc", logdepth, fatal); + + report("Checking for -static-libgcc... "); + logprintf(logdepth, "find_cc_static_libgcc: trying to find -static-libgcc...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, NULL, NULL, "-static-libgcc")) return 0; + return try_fail(logdepth, key); +} diff --git a/scconfig/src/default/find_fscalls.c b/scconfig/src/default/find_fscalls.c index 4aa2320..7e990d2 100644 --- a/scconfig/src/default/find_fscalls.c +++ b/scconfig/src/default/find_fscalls.c @@ -105,7 +105,8 @@ NL " if (found == 1)" NL " puts(\"OK\");" NL " return 0;" - NL "}"; + NL "}" + NL; char *includes[] = { "#include ", "#include ", /* 4.2BSD */ @@ -145,7 +146,8 @@ NL " if (found > 0)" NL " puts(\"OK\");" NL " return 0;" - NL "}"; + NL "}" + NL; require("cc/cc", logdepth, fatal); diff --git a/scconfig/src/default/find_proc.c b/scconfig/src/default/find_proc.c index fec68a4..9442476 100644 --- a/scconfig/src/default/find_proc.c +++ b/scconfig/src/default/find_proc.c @@ -48,6 +48,44 @@ if (try_icl(logdepth, "libs/proc/_spawnvp", test_c, "#include ", NULL, NULL)) return 0; return try_fail(logdepth, "libs/proc/_spawnvp"); +} + +int find_proc_CreateProcessA(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/proc/CreateProcessA"; + char *test_c = + NL "#include " + NL "char buf[2000];" + NL "int main() {" + NL " const char *cmd;" + NL " STARTUPINFOA si;" + NL " PROCESS_INFORMATION pi;" + NL " cmd = getenv(\"COMSPEC\");" + NL " if (cmd == NULL) { /* fallback to guessing */" + NL " UINT len = GetWindowsDirectoryA(buf, sizeof(buf));" + NL " strcpy(buf+len, \"\\\\system32\\\\cmd.exe\");" + NL " cmd = buf;" + NL " }" + NL " memset(&si, 0, sizeof(si)); si.cb = sizeof(si);" + NL " if (!CreateProcessA(cmd, \"/c \\\"echo OK\\\"\"," + NL " NULL, NULL, TRUE," + NL " 0, NULL, NULL, &si, &pi))" + NL " return 1;" + NL " if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0)" + NL " abort();" + NL " return 0;" + NL "}" + NL ; + + require("cc/cc", logdepth, fatal); + + report("Checking for CreateProcessA... "); + logprintf(logdepth, "find_proc_CreateProcessA: trying to find CreateProcessA...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) return 0; + + return try_fail(logdepth, key); } @@ -135,3 +173,194 @@ return try_fail(logdepth, "libs/proc/wait"); } + +int find_proc__getpid(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/proc/_getpid"; + const char *test_c = + NL "#include " + NL "int main()" + NL "{" + NL no_implicit(int, "_getpid", "_getpid") + NL " if (_getpid() != (-1))" + NL " puts(\"OK\");" + NL " return 0;" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for _getpid()... "); + logprintf(logdepth, "find_proc__getpid: trying to find _getpid()...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) + return 0; + + return try_fail(logdepth, key); +} + +int find_proc_getexecname(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/proc/getexecname"; + const char *test_c = + NL "void my_puts(const char *s);" + NL "int main()" + NL "{" + NL no_implicit(const char*, "getexecname", "getexecname") + NL " getexecname();" + NL " my_puts(\"OK\");" + NL " return 0;" + NL "}" + NL "#include " + NL "void my_puts(const char *s)" + NL "{" + NL " puts(s);" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for getexecname()... "); + logprintf(logdepth, "find_proc_getexecname: trying to find getexecname()...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) + return 0; + + return try_fail(logdepth, key); +} + +int find_proc_GetModuleFileNameA(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/proc/GetModuleFileNameA"; + const char *test_c = + NL "void my_puts(const char *s);" + NL "char path_buffer[5000];" + NL "int main()" + NL "{" + NL " HMODULE hModule = GetModuleHandleA(NULL);" + NL " if (GetModuleFileNameA(hModule, path_buffer, sizeof(path_buffer)) != 0)" + NL " my_puts(\"OK\");" + NL " return 0;" + NL "}" + NL "#include " + NL "void my_puts(const char *s)" + NL "{" + NL " puts(s);" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for GetModuleFileNameA()... "); + logprintf(logdepth, "find_proc_GetModuleFileNameA: trying to find GetModuleFileNameA()...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) + return 0; + if (try_icl(logdepth, key, test_c, "#include ", NULL, "-lkernel32")) + return 0; + + return try_fail(logdepth, key); +} + +int find_proc_shmget(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/proc/shmget"; + const char *test_c = + NL "void my_puts(const char *s);" + NL "int main()" + NL "{" + NL " int shmid;" + NL " char *addr;" + NL " shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT|IPC_EXCL|0600);" + NL " if (shmid < 0)" + NL " return 1;" + NL " addr = (char *)shmat(shmid, (void *)0, 0);" + NL " if (addr == (char *)0) {" + NL " shmctl(shmid, IPC_RMID, (void *)0);" + NL " return 1;" + NL " }" + NL " if (shmctl(shmid, IPC_RMID, (void *)0) != 0)" + NL " return 1;" + NL " if (addr[2] != 0)" + NL " return 1;" + NL " addr[0] = 'O'; addr[1] = 'K';" + NL " my_puts(addr);" + NL " return 0;" + NL "}" + NL "#include " + NL "void my_puts(const char *s)" + NL "{" + NL " puts(s);" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for shmget()... "); + logprintf(logdepth, "find_proc_shmget: trying to find shmget()...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include \n#include ", NULL, NULL)) + return 0; + + return try_fail(logdepth, key); +} + +int find_proc_CreateFileMappingA(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/proc/CreateFileMappingA"; + const char *test_c = + NL "void my_puts(const char *s);" + NL "#define MAP_BUF_SIZE 4096" + NL "int main()" + NL "{" + NL " char *addr;" + NL " HANDLE hMap = CreateFileMappingA(" + NL " INVALID_HANDLE_VALUE," + NL " NULL," + NL " PAGE_READWRITE," + NL " 0," + NL " MAP_BUF_SIZE," + NL " NULL);" + NL " if (hMap == NULL)" + NL " return 1;" + NL " addr = (char *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS," + NL " 0, 0, MAP_BUF_SIZE);" + NL " if (addr == NULL) {" + NL " CloseHandle(hMap);" + NL " return 1;" + NL " }" + NL " if (addr[2] != 0) {" + NL " UnmapViewOfFile(addr);" + NL " CloseHandle(hMap);" + NL " return 1;" + NL " }" + NL " addr[0] = 'O'; addr[1] = 'K';" + NL " my_puts(addr);" + NL " UnmapViewOfFile(addr);" + NL " CloseHandle(hMap);" + NL " return 0;" + NL "}" + NL "#include " + NL "void my_puts(const char *s)" + NL "{" + NL " puts(s);" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for CreateFileMappingA()... "); + logprintf(logdepth, "find_proc_CreateFileMappingA: trying to find CreateFileMappingA()...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) + return 0; + if (try_icl(logdepth, key, test_c, "#include ", NULL, "-lkernel32")) + return 0; + + return try_fail(logdepth, key); +} diff --git a/scconfig/src/default/find_str.c b/scconfig/src/default/find_str.c index 5e29531..afd015c 100644 --- a/scconfig/src/default/find_str.c +++ b/scconfig/src/default/find_str.c @@ -74,3 +74,49 @@ return try_fail(logdepth, "str/strncasecmp"); } + +int find_stricmp(const char *name, int logdepth, int fatal) +{ + const char *test_c = + NL "#include " + NL "#include " + NL "int main() {" + NL " if ((stricmp(\"foo\", \"FoO\") == 0) && (stricmp(\"foo\", \"bar\") != 0))" + NL " puts(\"OK\");" + NL " return 0;" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for stricmp()... "); + logprintf(logdepth, "find_fs_stricmp: trying to find stricmp...\n"); + logdepth++; + + if (try_icl(logdepth, "str/stricmp", test_c, NULL, NULL, NULL)) return 0; + return try_fail(logdepth, "str/stricmp"); +} + + +int find_strnicmp(const char *name, int logdepth, int fatal) +{ + const char *test_c = + NL "#include " + NL "#include " + NL "int main() {" + NL " if ((strnicmp(\"foo1\", \"FoO2\", 3) == 0) && (strnicmp(\"foo1\", \"bar2\", 3) != 0))" + NL " puts(\"OK\");" + NL " return 0;" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for strnicmp()... "); + logprintf(logdepth, "find_fs_strnicmp: trying to find strnicmp...\n"); + logdepth++; + + if (try_icl(logdepth, "str/strnicmp", test_c, NULL, NULL, NULL)) return 0; + return try_fail(logdepth, "str/strnicmp"); +} + diff --git a/scconfig/src/default/find_time.c b/scconfig/src/default/find_time.c index e7189e3..25a91a5 100644 --- a/scconfig/src/default/find_time.c +++ b/scconfig/src/default/find_time.c @@ -245,3 +245,69 @@ return 0; return try_fail(logdepth, "libs/time/gmtime_s"); } + +int find_time_localtime_r(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/time/localtime_r"; + const char test_c[] = + NL "void my_puts(const char *s);" + NL "int main() {" + NL " time_t tim = 1543645850;" + NL " struct tm tm;" + NL " if (localtime_r(&tim, &tm)" /* returns '&tm' */ + NL " && 0!=tm.tm_sec" /* depends on TZ: sadly we can't sure in anything */ + NL " && 0!=tm.tm_min" + NL " && 0!=tm.tm_hour)" + NL " my_puts(\"OK\");" + NL " return 0;" + NL "}" + NL "#include " + NL "void my_puts(const char *s)" + NL "{" + NL " puts(s);" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for localtime_r()... "); + logprintf(logdepth, "find_time_localtime_r: trying to find localtime_r...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) + return 0; + return try_fail(logdepth, key); +} + +int find_time_localtime_s(const char *name, int logdepth, int fatal) +{ + const char *key = "libs/time/localtime_s"; + const char test_c[] = + NL "void my_puts(const char *s);" + NL "int main() {" + NL " time_t tim = 1543645850;" + NL " struct tm tm;" + NL " if (0==localtime_s(&tm, &tim)" /* returns errno */ + NL " && 0!=tm.tm_sec" /* depends on TZ: sadly we can't sure in anything */ + NL " && 0!=tm.tm_min" + NL " && 0!=tm.tm_hour)" + NL " my_puts(\"OK\");" + NL " return 0;" + NL "}" + NL "#include " + NL "void my_puts(const char *s)" + NL "{" + NL " puts(s);" + NL "}" + NL; + + require("cc/cc", logdepth, fatal); + + report("Checking for localtime_s()... "); + logprintf(logdepth, "find_time_localtime_s: trying to find localtime_s...\n"); + logdepth++; + + if (try_icl(logdepth, key, test_c, "#include ", NULL, NULL)) + return 0; + return try_fail(logdepth, key); +} diff --git a/scconfig/src/default/lib_try.c b/scconfig/src/default/lib_try.c index da03685..e926a27 100644 --- a/scconfig/src/default/lib_try.c +++ b/scconfig/src/default/lib_try.c @@ -292,7 +292,7 @@ { char **pkg_ver, **s; int num_pkg_ver; - int res; + int res = 0; (void) includes; /* not used */ run_pkg_config_lst(logdepth, pkgpat, &num_pkg_ver, &pkg_ver); diff --git a/scconfig/src/default/str.c b/scconfig/src/default/str.c index b2b2034..b02a2cf 100644 --- a/scconfig/src/default/str.c +++ b/scconfig/src/default/str.c @@ -130,6 +130,10 @@ sum += len[v]; } + /* first string is NULL; return a new allocation that is a simple \0, empty string to avoid a nasty corner case */ + if (sum == 0) + return calloc(1, 1); + sl = strlen(sep); sum += (v-1) * sl + 1; /* + a sep between each two strings and a terminator at the end */ o = out = malloc(sum); diff --git a/scconfig/src/tmpasm/tmpasm_scconfig.c b/scconfig/src/tmpasm/tmpasm_scconfig.c index 3f8145c..5bfb6d3 100644 --- a/scconfig/src/tmpasm/tmpasm_scconfig.c +++ b/scconfig/src/tmpasm/tmpasm_scconfig.c @@ -183,6 +183,27 @@ put(addr, val); free(addr); free(val); +} + +static void instr_resolve(tmpasm_t *ctx, char *iname, int argc, tmpasm_arg_t *argv[]) +{ + char *dst, *srca; + const char *src; + (void) iname; /* not used */ + if (argc != 2) { + char str[16]; + sprintf(str, "%d", argc); + tmpasm_runtime_error(ctx, -1, str); + return; + } + + dst = tmpasm_arg2str(ctx, argv[0], 1); + srca = tmpasm_arg2str(ctx, argv[1], 0); + src = scc_get(ctx, srca); + if (*dst != '\0') + put(dst, src); + free(dst); + free(srca); } @@ -522,6 +543,8 @@ /* TODO: make this a hash */ if (strcmp(name, "put") == 0) return instr_put; + if (strcmp(name, "resolve") == 0) + return instr_resolve; if (strcmp(name, "append") == 0) return instr_append; if (strcmp(name, "print") == 0) diff --git a/src/Makefile b/src/Makefile index 4f0ceaa..3968ef1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,6 @@ all: cd libmawk && $(MAKE) + cd awklib && $(MAKE) # cd example_apps && $(MAKE) all test: @@ -7,14 +8,17 @@ install: cd libmawk && $(MAKE) install + cd awklib && $(MAKE) install # cd example_apps && $(MAKE) install uninstall: cd libmawk && $(MAKE) uninstall + cd awklib && $(MAKE) uninstall # cd example_apps && $(MAKE) uninstall linstall: cd libmawk && $(MAKE) linstall + cd awklib && $(MAKE) linstall # cd example_apps && $(MAKE) linstall clean: diff --git a/src/awklib/Makefile.in b/src/awklib/Makefile.in index 7b36b23..fb80040 100644 --- a/src/awklib/Makefile.in +++ b/src/awklib/Makefile.in @@ -3,7 +3,8 @@ print [@ # Generated by scconfig from Makefile.in -LIBPATH=$(install_root)/usr/lib/libmawk +PREFIX=@/local/prefix@ +LIBPATH=$(DESTDIR)$(install_root)$(PREFIX)/lib/libmawk all: diff --git a/src/libmawk/COPYING b/src/libmawk/COPYING index a43ea21..d159169 100644 --- a/src/libmawk/COPYING +++ b/src/libmawk/COPYING @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -291,7 +291,7 @@ the "copyright" line and a pointer to where the full notice is found. - Copyright (C) 19yy + Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -303,16 +303,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -335,5 +335,5 @@ This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General +library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diff --git a/src/libmawk/INSTALL b/src/libmawk/INSTALL deleted file mode 100644 index f114627..0000000 --- a/src/libmawk/INSTALL +++ /dev/null @@ -1,47 +0,0 @@ -Look at the file config.user and edit to set user defines. - -if your system is one of - apollo - convex - mips - sgi - ultrix-mips - cray - hpux (read below) - unixware (read below) - -and you don't have gcc or prefer to use cc, then you may want to -copy config-user/your_system to config.user and edit that. - -run - - configure - make - - -If you have problems, please report it. If you can fix the problem, by -changing config.user, please send the results. Else send output from -configure, make and config.h. Send to brennan@whidbey.com. - - - -DOS: -Look at the file msdos/INSTALL - - -HPUX: -Evidently there is more than one compiler and/or math library. Some -configurations work out of the box (configure/make). Others need -CFLAGS='+O2 +FPZO'. On HPUX 9.05 with the ansi compiler HP92453-01 -A.09.77 set CFLAGS='-Ae +O2 +FPZO'. Thanks to Dr. Rafael R. -Pappalardo for this info. - - - -UNIXWARE: -On some but not all versions, configure might decide you don't have -memcpy. Remove #define NO_MEMCPY 1 from config.h. -If the fpe_test check fails, change the definition of TURN_ON_FPE_TRAPS -to - -#define TURN_ON_FPE_TRAPS() fpsetmask(fpgetmask()|FP_X_DZ|FP_X_OFL|FP_X_INV) diff --git a/src/libmawk/Makefile b/src/libmawk/Makefile index 557ecec..ff4f4e2 100644 --- a/src/libmawk/Makefile +++ b/src/libmawk/Makefile @@ -122,17 +122,30 @@ install_ : lmawk libmawk.so $(MKDIR) $(BINDIR) $(MKDIR) $(MANDIR) + $(MKDIR) $(MAN3DIR) + $(MKDIR) $(MAN7DIR) $(MKDIR) $(INCDIR) - $(MKDIR) $(LIBDIR) + $(MKDIR) $(LIBARCHDIR) $(CP) $(PWD)/lmawk $(BINDIR) $(CHMODX) $(BINDIR)/lmawk $(CP) $(PWD)/man/lmawk.1 $(MAWKMAN) + $(CP) $(PWD)/man/libmawk_append_input.3libmawk $(MAN3DIR)/libmawk_append_input.3libmawk + $(CP) $(PWD)/man/libmawk_call_function.3libmawk $(MAN3DIR)/libmawk_call_function.3libmawk + $(CP) $(PWD)/man/libmawk_cell_destroy.3libmawk $(MAN3DIR)/libmawk_cell_destroy.3libmawk + $(CP) $(PWD)/man/libmawk_get_var.3libmawk $(MAN3DIR)/libmawk_get_var.3libmawk + $(CP) $(PWD)/man/libmawk_initialize.3libmawk $(MAN3DIR)/libmawk_initialize.3libmawk + $(CP) $(PWD)/man/libmawk_initialize_stage.3libmawk $(MAN3DIR)/libmawk_initialize_stage.3libmawk + $(CP) $(PWD)/man/libmawk_register_function.3libmawk $(MAN3DIR)/libmawk_register_function.3libmawk + $(CP) $(PWD)/man/libmawk_run_main.3libmawk $(MAN3DIR)/libmawk_run_main.3libmawk + $(CP) $(PWD)/man/libmawk_set_cell.3libmawk $(MAN3DIR)/libmawk_set_cell.3libmawk + $(CP) $(PWD)/man/libmawk_uninitialize.3libmawk $(MAN3DIR)/libmawk_uninitialize.3libmawk + $(CP) $(PWD)/man/example.7libmawk $(MAN7DIR)/example.7libmawk $(CHMOD) 0644 $(MAWKMAN) - $(CP) $(PWD)/libmawk.so $(LIBDIR)/libmawk.so.$(SOVER1).$(SOVER2).$(SOVER3) - rm $(LIBDIR)/libmawk.so.$(SOVER1).$(SOVER2) $(LIBDIR)/libmawk.so.$(SOVER1) 2>/dev/null ; true - ln -s libmawk.so.$(SOVER1).$(SOVER2).$(SOVER3) $(LIBDIR)/libmawk.so.$(SOVER1).$(SOVER2) - ln -s libmawk.so.$(SOVER1).$(SOVER2) $(LIBDIR)/libmawk.so.$(SOVER1) - ln -s libmawk.so.$(SOVER1) $(LIBDIR)/libmawk.so + $(CP) $(PWD)/libmawk.so $(LIBARCHDIR)/libmawk.so.$(SOVER1).$(SOVER2).$(SOVER3) + rm $(LIBARCHDIR)/libmawk.so.$(SOVER1).$(SOVER2) $(LIBARCHDIR)/libmawk.so.$(SOVER1) 2>/dev/null ; true + ln -s libmawk.so.$(SOVER1).$(SOVER2).$(SOVER3) $(LIBARCHDIR)/libmawk.so.$(SOVER1).$(SOVER2) + ln -s libmawk.so.$(SOVER1).$(SOVER2).$(SOVER3) $(LIBARCHDIR)/libmawk.so.$(SOVER1) + ln -s libmawk.so.$(SOVER1) $(LIBARCHDIR)/libmawk.so for h in $(IHEADERS); do $(CP) $(PWD)/$$h $(INCDIR)/$$h; done $(CP) $(PWD)/../libmawk.h $(INCDIR)/../libmawk.h diff --git a/src/libmawk/Makefile.conf.in b/src/libmawk/Makefile.conf.in index a823aaa..fb3dde6 100644 --- a/src/libmawk/Makefile.conf.in +++ b/src/libmawk/Makefile.conf.in @@ -22,11 +22,14 @@ # where to put mawk BINDIR = $(DESTDIR)$(install_root)$(PREFIX)/bin # where to put libraries +LIBARCHDIR = $(DESTDIR)$(install_root)$(PREFIX)/@/local/libarchdir@ LIBDIR = $(DESTDIR)$(install_root)$(PREFIX)/lib # where to put include files INCDIR = $(DESTDIR)$(install_root)$(PREFIX)/include/libmawk # where to put the man pages MANDIR = $(DESTDIR)$(install_root)$(PREFIX)/share/man/man1 +MAN3DIR = $(DESTDIR)$(install_root)$(PREFIX)/share/man/man3 +MAN7DIR = $(DESTDIR)$(install_root)$(PREFIX)/share/man/man7 # where to put the doc DOCDIR = $(DESTDIR)$(install_root)$(PREFIX)/share/doc/libmawk MANEXT = 1 diff --git a/src/libmawk/bi_funct.c b/src/libmawk/bi_funct.c index 1dccdb5..44b5a38 100644 --- a/src/libmawk/bi_funct.c +++ b/src/libmawk/bi_funct.c @@ -269,11 +269,24 @@ } #ifndef MAWK_NO_FLOAT + +#ifndef MAWK_HAVE_SAFE_NAN +# define handle_nan_1arg() \ + if (P_isnan((sp)->d.dval)) { \ + sp->d.dval = P_nan(); \ + return sp; \ + } +#else +# define handle_nan_1arg() +#endif + + mawk_cell_t *mawk_bi_sin(mawk_state_t *MAWK, mawk_cell_t *sp) { #if ! STDC_MATHERR if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + handle_nan_1arg(); sp->d.dval = sin(sp->d.dval); return sp; #else @@ -282,6 +295,9 @@ errno = 0; if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + + handle_nan_1arg(); + x = sp->d.dval; sp->d.dval = sin(sp->d.dval); if (errno) @@ -295,6 +311,7 @@ #if ! STDC_MATHERR if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + handle_nan_1arg(); sp->d.dval = cos(sp->d.dval); return sp; #else @@ -303,6 +320,7 @@ errno = 0; if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + handle_nan_1arg(); x = sp->d.dval; sp->d.dval = cos(sp->d.dval); if (errno) @@ -313,10 +331,19 @@ mawk_cell_t *mawk_bi_atan2(mawk_state_t *MAWK, mawk_cell_t *sp) { + #if ! STDC_MATHERR sp--; if (TEST2(sp) != TWO_NUMS) mawk_cast2_to_num(MAWK, sp); + +#ifndef MAWK_HAVE_SAFE_NAN + if (P_isnan(sp->d.dval) || P_isnan((sp+1)->d.dval)) { + sp->d.dval = P_nan(); + return sp; + } +#endif + sp->d.dval = atan2(sp->d.dval, (sp + 1)->d.dval); return sp; #else @@ -325,6 +352,15 @@ sp--; if (TEST2(sp) != TWO_NUMS) mawk_cast2_to_num(MAWK, sp); + + +#ifndef MAWK_HAVE_SAFE_NAN + if (P_isnan(sp->d.dval) || P_isnan((sp+1)->d.dval)) { + sp->d.dval = P_nan(); + return sp; + } +#endif + sp->d.dval = atan2(sp->d.dval, (sp + 1)->d.dval); if (errno) mawk_rt_error(MAWK, "atan2(0,0) : domain error"); @@ -339,6 +375,9 @@ errno = 0; if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + + handle_nan_1arg(); + x = sp->d.dval; PM_BEGIN sp->d.dval = P_log(sp->d.dval); @@ -352,9 +391,11 @@ mawk_cell_t *mawk_bi_exp(mawk_state_t *MAWK, mawk_cell_t *sp) { + #if ! STDC_MATHERR if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + handle_nan_1arg(); sp->d.dval = exp(sp->d.dval); return sp; #else @@ -363,6 +404,7 @@ errno = 0; if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + handle_nan_1arg(); x = sp->d.dval; sp->d.dval = exp(sp->d.dval); if (errno && sp->d.dval) @@ -377,6 +419,7 @@ { if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + handle_nan_1arg(); sp->d.dval = mawk_num_int(sp->d.dval); return sp; } @@ -387,6 +430,8 @@ if (sp->type != C_NUM) mawk_cast1_to_num(MAWK, sp); + + handle_nan_1arg(); x = sp->d.dval; @@ -919,7 +964,7 @@ else mawk_set_errno(MAWK, "2 object is not a function"); -#warning this should be some common code in execute.c? +TODO("this should be some common code in execute.c?") for (i = 0; i < numargs; i++) { mawk_cell_destroy(MAWK, &sp[i]); sp[i].type = C_NOINIT; @@ -1016,7 +1061,7 @@ sp -= numargs; sp--; -#warning TODO: cell destroy all the allocated but unused args? +TODO(": cell destroy all the allocated but unused args?") return sp; error:; diff --git a/src/libmawk/conf.h.in b/src/libmawk/conf.h.in index deb385a..4634467 100644 --- a/src/libmawk/conf.h.in +++ b/src/libmawk/conf.h.in @@ -70,6 +70,20 @@ cons: zmalloc's uninit will throw them out in less cpu cycles. */ /* #define MAWK_MEM_PEDANTIC */ +@] + +print {\n/* Code warnings for TODO, portable (unlike #warning) */} +if ?cc/pragma_message +then +print [@ +#define DO_PRAGMA(arg) _Pragma(#arg) +#define TODO(x) DO_PRAGMA(message("TODO: " #x)) +@] +else +print {\n/* Not available */\n#define TODO(x)\n} +end + +print [@ #endif @] diff --git a/src/libmawk/da_bin.c b/src/libmawk/da_bin.c index 3c66034..f791767 100644 --- a/src/libmawk/da_bin.c +++ b/src/libmawk/da_bin.c @@ -25,6 +25,8 @@ #include "vars.h" #include "f2d.h" #include + +typedef long int da_word; /* for load sanity checks declare large maximums; without these a malformed binary may cause libmawk to allocate a lot of memory */ @@ -535,9 +537,9 @@ return 0; } -static int save_bin_sect(mawk_state_t * MAWK, void *fd, int (*write)(void *fd, const void *buff, size_t len), INST *b, int len) -{ - if (write(fd, &len, 4) != 4) +static int save_bin_sect(mawk_state_t * MAWK, void *fd, int (*write)(void *fd, const void *buff, size_t len), INST *b, da_word len) +{ + if (write(fd, &len, sizeof(da_word)) != sizeof(da_word)) return -1; if (b != NULL) { int l; @@ -553,7 +555,8 @@ header_t h; link_t l; int n; - long int len, begin_len, end_len, main_len, num_func; + long int begin_len, end_len, main_len; + da_word num_func, len; long int *flen; struct mawk_fdump **fps; struct mawk_fdump *fp; @@ -599,23 +602,23 @@ /* L1: save nums */ len = l.numsu; - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); write(fd, l.nums, sizeof(mawk_num_t) * l.numsu); - write(fd, &num_func, 4); + write(fd, &num_func, sizeof(da_word)); /* L2: save strings */ len = l.strsu; - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); for(n = 0; n < l.strsu; n++) { len = safe_strlen(l.strs[n]); - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); if (len > 0) write(fd, l.strs[n], len); } /* L3: save vars */ len = l.varsu; - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); for(n = 0; n < l.varsu; n++) { const char *name; SYMTAB *stp; @@ -633,12 +636,12 @@ /* save name len and name*/ len = strlen(name); - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); write(fd, name, len); /* save value len and content - empty for now */ len = 0; - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); } /* L4: save begin/end/main sections */ @@ -655,7 +658,7 @@ fp = fps[n]; len = strlen(fp->fbp->name); /* fprintf(stderr, "da_bin function %s/%d len=%d\n", fp->fbp->name, len,flen[n]); */ - write(fd, &len, 4); + write(fd, &len, sizeof(da_word)); write(fd, fp->fbp->name, len); /* fprintf(stderr, "NARGS=%d %d\n", fp->fbp->nargs, fp->fbp->typev[0]); */ write(fd, &fp->fbp->nargs, 2); @@ -676,8 +679,8 @@ #ifndef MAWK_NO_EXEC static int bin_load_func(mawk_state_t *MAWK, void *fd, int (*read)(void *fd, void *buff, size_t len), FBLOCK *fbp) { - int len; - read(fd, &len, 4); + da_word len; + read(fd, &len, sizeof(da_word)); if (len > 0) { if (len > BIN_CODE_MAXLEN) return -1; @@ -690,9 +693,9 @@ static int bin_load_sect(mawk_state_t *MAWK, void *fd, int (*read)(void *fd, void *buff, size_t len), int scope) { - int len; - - read(fd, &len, 4); + da_word len; + + read(fd, &len, sizeof(da_word)); if (len > 0) { MAWK->scope = scope; if ((scope == SCOPE_BEGIN) || (scope == SCOPE_END)) @@ -728,8 +731,8 @@ SYMTAB *stp; header_t h; link_t l; - int n, num_func; - long int len; + int n; + da_word num_func, len; int ret; memset(&l, 0, sizeof(l)); @@ -776,17 +779,18 @@ /* L1: load nums */ - read(fd, &len, 4); + len = 0; + read(fd, &len, sizeof(da_word)); l.numsa = l.numsu = len; len = sizeof(*l.nums) * l.numsa; if (len > BIN_MAXVARS) goto err; l.nums = malloc(len); read(fd, l.nums, len); - read(fd, &num_func, 4); + read(fd, &num_func, sizeof(da_word)); /* L2: load strings */ - read(fd, &len, 4); + read(fd, &len, sizeof(da_word)); l.strsa = l.strsu = len; len = sizeof(*l.strs) * l.strsa; if (len > BIN_MAXSTRS) @@ -795,7 +799,7 @@ for(n = 0; n < l.strsu; n++) { char *name; - read(fd, &len, 4); + read(fd, &len, sizeof(da_word)); if (len > BIN_NAME_MAXLEN) goto err; if (len > 0) { @@ -814,7 +818,7 @@ } /* L3: load vars */ - read(fd, &len, 4); + read(fd, &len, sizeof(da_word)); l.varsa = l.varsu = len; len = sizeof(*l.vars) * l.varsa; if (l.varsa > BIN_MAXVARS) @@ -830,7 +834,7 @@ read(fd, &stype, 1); /* load name len and name*/ - read(fd, &len, 4); + read(fd, &len, sizeof(da_word)); if (len > BIN_NAME_MAXLEN) goto err; name = mawk_zmalloc(MAWK, len+1); @@ -866,7 +870,7 @@ /* fprintf(stderr, "LOAD var name='%s' type=%d len=%d: %d -> %p\n", name, type, len, n, l.vars[n].cp); */ /* load value len and content - empty for now */ - read(fd, &len, 4); + read(fd, &len, sizeof(da_word)); if (len != 0) { ret = MAWK_EWRONGVAL; goto err2; @@ -890,7 +894,7 @@ char *name; FBLOCK *fbp; - read(fd, &len, 4); + read(fd, &len, sizeof(da_word)); /* fprintf(stderr, "LOAD function len=%d\n", len); */ if (len > BIN_NAME_MAXLEN) goto err; diff --git a/src/libmawk/error.c b/src/libmawk/error.c index 2eee157..fba78b3 100644 --- a/src/libmawk/error.c +++ b/src/libmawk/error.c @@ -16,7 +16,7 @@ #include "conf.h" -#warning this should be gone: +TODO("this should be gone:") #include #include "mawk.h" diff --git a/src/libmawk/fin_exec.c b/src/libmawk/fin_exec.c index 770fa39..6d0d516 100644 --- a/src/libmawk/fin_exec.c +++ b/src/libmawk/fin_exec.c @@ -46,7 +46,7 @@ FNR->d.dval = MAWK_NUM_ZERO; MAWK->rt_fnr = 0; MAWK->main_input = mawk_file_find_(MAWK, "/dev/stdin", F_IN, 1); -#warning TODO: abstract +TODO(": abstract") MAWK->main_input->fin->flags |= MAWK_INPF_MAIN; } @@ -99,7 +99,7 @@ mawk_errmsg(MAWK, errno, "cannot open %s", string(cp)->str); mawk_exitval(MAWK, 2, NULL); } -#warning TODO abstract this +TODO("TODO abstract this") MAWK->main_input->fin->flags |= MAWK_INPF_MAIN; /* success -- set FILENAME and FNR */ @@ -341,7 +341,7 @@ if (MAWK->rs_shadow.type == SEP_MLR) { char *s; /* trim blank lines from front of file */ -#warning TODO: probably accept \r as well +TODO(": probably accept \r as well") for(s = fin->next; *s == '\n'; s++) ; if (*s == '\0') { /* emptied the buffer with all the \n's... so get back to initial state */ diff --git a/src/libmawk/init.c b/src/libmawk/init.c index 40b598a..016956f 100644 --- a/src/libmawk/init.c +++ b/src/libmawk/init.c @@ -16,6 +16,7 @@ #include "conf.h" #include #include +#include #include #include "mawk.h" #include "code.h" @@ -423,8 +424,13 @@ break; case '-': - if (argv[i][2] != 0) + if (argv[i][2] != 0) { + if ((strcmp(argv[i], "--version") == 0) || (strcmp(argv[i], "--help") == 0)) { + printf("\nlmawk is libmawk " LMAWK_VER "\nFor more info, see the manual page for lmawk(1) and\nhttp://repo.hu/projects/libmawk.\n\n"); + exit(0); + } bad_option(MAWK, argv[i]); + } i++; goto no_more_opts; #ifndef MAWK_NO_COMP diff --git a/src/libmawk/libmawk.c b/src/libmawk/libmawk.c index 0abefe4..2104676 100644 --- a/src/libmawk/libmawk.c +++ b/src/libmawk/libmawk.c @@ -55,7 +55,7 @@ m2 = mawk_initialize_argv(m, argc, argv); if (m2 == NULL) { -#warning TODO: cleanup m +TODO(": cleanup m") return NULL; } m = m2; @@ -312,7 +312,7 @@ else fbp = fs->stval.fbp; -#warning TODO: check if we need to grow the stack +TODO(": check if we need to grow the stack") orig_sp = MAWK->sp; va_start(ap, argtypes); @@ -360,7 +360,7 @@ else fbp = fs->stval.fbp; -#warning TODO: check if we need to grow the stack +TODO(": check if we need to grow the stack") orig_sp = MAWK->sp; for(numargs = 0;*argtypes != '\0';argtypes++,numargs++,args++) { @@ -405,7 +405,7 @@ else fbp = fs->stval.fbp; -#warning TODO: check if we need to grow the stack +TODO(": check if we need to grow the stack") for(n = 0; n< argc; n++) { inc_mawksp(); @@ -453,7 +453,7 @@ break; case C_STRNUM: case C_MBSTRN: -#warning TODO: we should be able to convert the above two +TODO(": we should be able to convert the above two") case C_RE: case C_SPACE: case C_SNULL: diff --git a/src/libmawk/man/example.7libmawk b/src/libmawk/man/example.7libmawk new file mode 100644 index 0000000..0f59471 --- /dev/null +++ b/src/libmawk/man/example.7libmawk @@ -0,0 +1,49 @@ +.\" Copyright 2009 Tibor Palinkas (mawk@inno.bme.hu) +.\" +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one. +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" +.TH EXAMPLE 7 2009-08-10 "libmawk" "libmawk manual" +.SH NAME +libmawk example \- how to use the library +.SH SYNOPSIS +.nf +.B #include +.sp +.SH DESCRIPTION +Libmawk is a library that lets applications to embed awk scripts using the +code of the popular implementation +.B mawk. +The normal process is to call libmawk_initialize() to set up a new mawk +context (with script(s) loaded), then in the main loop feed it using +libmawk_append_input(). For "out of band" communication, the program +may also call functions implemented in awk and read (or modify) global +variables of the awk script. The hos tapplication usally will also bind +some of its functions to the context using libmawk_register_function, which +allows the awk script to call the host applicaiton's functions directly as +they were awk builtins or user defined functions. After the main loop, the +application destroys the context freeing up all memory allocated for +the script(s). +.sp +One context is for one awk program. One awk program may consist of multiple +script files (just as with command line awk, with multiple -f filename +arguments). Libmawk is instance safe, the host application may create +multiple instances of contexts with the same or with different set of +awk scripts loaded. These contexts are totally separate, no variables, +functions or any sort of states are shared. However, the host application +may provide means of communication between those scripts by custom functions +or by copying variable contents between them. +.SH Example application +The following example application creates a single context to demonstrate +all the above mentioned functionality. +.nf +.fi diff --git a/src/libmawk/math_wrap.h b/src/libmawk/math_wrap.h index 72ad5da..b847886 100644 --- a/src/libmawk/math_wrap.h +++ b/src/libmawk/math_wrap.h @@ -59,11 +59,16 @@ # define P_isnan_manual(x) 0 #else +#include /* broken or missing NAN support, always have to check manually */ # define P_nansafe1(dest, operation, operand) \ do { \ if (P_isnan(operand) || P_isnan(dest)) (dest) = P_nan(); \ - else (dest) = (operation); \ + else { \ + (dest) = (operation); \ + if (P_isnan(dest)) \ + (dest) = DBL_MAX; \ + } \ } while(0) # define P_isnan_manual P_isnan #endif diff --git a/src/libmawk/num_double.c b/src/libmawk/num_double.c index 23e2b51..135bd5a 100644 --- a/src/libmawk/num_double.c +++ b/src/libmawk/num_double.c @@ -66,3 +66,15 @@ PM_END return r; } + +#ifndef MAWK_HAVE_SAFE_NAN +double mawk_strtonum_(const char *nptr, char **endptr) +{ + if (((nptr[0] == 'n') || (nptr[0] == 'N')) && ((nptr[1] == 'a') || (nptr[1] == 'A')) && ((nptr[2] == 'n') || (nptr[2] == 'N'))) { + if (endptr != NULL) + *endptr = (char *)(nptr+3); + return P_nan(); + } + return strtod(nptr, endptr); +} +#endif diff --git a/src/libmawk/num_double.h b/src/libmawk/num_double.h index 2d92d4c..670d879 100644 --- a/src/libmawk/num_double.h +++ b/src/libmawk/num_double.h @@ -17,14 +17,17 @@ #ifdef MAWK_HAVE_SAFE_NAN #define P_isnan(x) isnan(x) #define P_nan() nan("nan") +#define strtonum(nptr, endptr) strtod(nptr, endptr) #else #define NUM_NAN HUGE_VAL #define P_isnan(x) ((x) == NUM_NAN) #define P_nan() (NUM_NAN) +#define strtonum(nptr, endptr) mawk_strtonum_(nptr, endptr) +double mawk_strtonum_(const char *nptr, char **endptr); #endif double mawk_num_pow(double x, double y); double P_fmod(double x, double y); -#define strtonum(nptr, endptr) strtod(nptr, endptr) + diff --git a/src/libmawk/print.c b/src/libmawk/print.c index 765bc3e..0511913 100644 --- a/src/libmawk/print.c +++ b/src/libmawk/print.c @@ -72,6 +72,11 @@ { Int ival = mawk_d_to_I(p->d.dval); const char *txt; + + if (P_isnan(p->d.dval)) { + mawk_vio_write_str(MAWK, fnode->vf, "nan"); + break; + } txt = mawk_num_print_spec(ival); if (txt != NULL) @@ -399,7 +404,15 @@ bad_conversion(MAWK, num_conversion, who, format); if (cp->type != C_NUM) mawk_cast1_to_num(MAWK, cp); - pf_type = PF_F; + if (P_isnan(cp->d.dval)) { + cp->ptr = (PTR) mawk_new_STRING(MAWK, "nan"); + cp->type = C_STRING; + cp->d.dval = 42; + p = "%s"; + pf_type = PF_S; + } + else + pf_type = PF_F; break; #endif diff --git a/src/libmawk/regression/Makefile.dabs b/src/libmawk/regression/Makefile.dabs index e7013a2..f7b34cb 100644 --- a/src/libmawk/regression/Makefile.dabs +++ b/src/libmawk/regression/Makefile.dabs @@ -21,4 +21,4 @@ ../examples/gdecl.dab\ ../examples/nocomment.dab\ ../examples/primes.dab\ -../examples/qsort.dab\ +../examples/qsort.dab diff --git a/src/libmawk/vio_fifo.c b/src/libmawk/vio_fifo.c index 67101ea..04a3a49 100644 --- a/src/libmawk/vio_fifo.c +++ b/src/libmawk/vio_fifo.c @@ -72,7 +72,7 @@ mawk_vio_fifo_t *v = (mawk_vio_fifo_t *)vf; if (!v->is_awk2app) return -1; -#warning TODO +TODO("TODO") abort(); return -1; } diff --git a/src/libmawk/vio_orig.c b/src/libmawk/vio_orig.c index 9250f4c..6aa8f31 100644 --- a/src/libmawk/vio_orig.c +++ b/src/libmawk/vio_orig.c @@ -162,7 +162,7 @@ -#warning TODO print runtime warnings +TODO("TODO print runtime warnings") mawk_vio_t *mawk_vio_orig_open(mawk_state_t *MAWK, const char *name, mawk_vio_open_mode_t mode) { mawk_vio_orig_t *vf; @@ -287,7 +287,7 @@ close(remote_fd); /* we could deadlock if future child inherit the local fd , set close on exec flag */ -#warning TODO: better do this by hand - close on exec is not really portable +TODO(": better do this by hand - close on exec is not really portable") CLOSE_ON_EXEC(local_fd); break; }