From 0342737c4763de343d9d87c0cb25a8e31f0211e7 Mon Sep 17 00:00:00 2001 From: glyn Date: Fri, 25 Sep 2015 14:49:58 +0100 Subject: [PATCH] Just pushing the latest copy of my development / staging DataFlex stuff into git; it's been a long time. Alas, there are not many actual changes, most notable change is addition of regex routines using GNU regex libraries: http://www.gnu.org/software/libc/manual/html_node/Regular-Expressions.html --- README.md | 12 ++- src/c/Makefile | 17 +++- src/c/df32func.c | 132 +++++++++++++++++++++++++++++- src/c/df32func.h | 6 +- src/df32/console.h | 2 +- src/df32/console.inc | 16 ++-- src/df32/data.inc | 147 +++++++++++++++++++++++----------- src/df32/date.inc | 2 +- src/df32/depmacro.inc | 2 +- src/df32/df32func.inc.autodoc | 35 +++++--- src/df32/df32func.mk | 38 ++++++--- src/df32/encode.h | 2 +- src/df32/errors.h | 13 ++- src/df32/hash.inc | 2 +- src/df32/macro.inc | 4 +- src/df32/math.inc | 2 +- src/df32/string.inc | 59 ++++++++++++-- src/df32/tstamp.inc | 2 +- src/df32/win32.h | 5 +- src/df32/win32.inc | 58 +++++++++++--- 20 files changed, 443 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index 4ddfd28..dd17dcd 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,12 @@ Some useful helper functions to speed up development when working with DataFlex Requirements ------------ -MinGW or compatible GNU C compiler: http://www.mingw.org/ -DataFlex 3.2 Console Mode or greater: http://www.dataaccess.com/ +MinGW or compatible GNU C compiler: + http://www.mingw.org/ +DataFlex 3.2 Console Mode or greater: + http://www.dataaccess.com/ +For regex functionality requires the GNU posix regex libraries: + http://sourceforge.net/projects/mingw/files/Other/UserContributed/regex/mingw-regex-2.5.1/mingw-libgnurx-2.5.1-src.tar.gz/download Installation ------------ @@ -38,3 +42,7 @@ The dataflex precompiled package: Alternatively include the dataflex includes as required directly in dataflex source code. + +Once everything is built, copy the dataflex .pki and .flp files to the location where +your dataflex setup expects to find it's pkg and flx files. Copy both df32func.dll and +libgnurx-0.dll to a location in your path. diff --git a/src/c/Makefile b/src/c/Makefile index 7806731..16aea76 100644 --- a/src/c/Makefile +++ b/src/c/Makefile @@ -1,11 +1,16 @@ # Project: df32func +# +# df32func dll extension for Console Mode DataFlex 3.2 +# +# Copyright (c) 2007-2015, glyn@8kb.co.uk +# Author: Glyn Astill CC = gcc.exe WINDRES = windres.exe RES = df32func.res -OBJ = df32func.o $(RES) -LINKOBJ = df32func.o $(RES) -LIBS = --no-export-all-symbols --add-stdcall-alias -lwsock32 +OBJ = df32func.o memman.o gnuregex.o $(RES) +LINKOBJ = df32func.o memman.o gnuregex.o $(RES) +LIBS = --no-export-all-symbols --add-stdcall-alias -lwsock32 -lgnurx BIN = df32func.dll CFLAGS = -O2 DLLWRAP=dllwrap.exe @@ -26,5 +31,11 @@ $(BIN): $(LINKOBJ) df32func.o: df32func.c $(CC) -c df32func.c -o df32func.o $(CFLAGS) +memman.o: memman.c + $(CC) -c memman.c -o memman.o $(CFLAGS) + +gnuregex.o: gnuregex.c + $(CC) -c gnuregex.c -o gnuregex.o $(CFLAGS) + df32func.res: df32func.rc $(WINDRES) -i df32func.rc --input-format=rc -o $(RES) -O coff diff --git a/src/c/df32func.c b/src/c/df32func.c index 6b221c4..bb02e79 100644 --- a/src/c/df32func.c +++ b/src/c/df32func.c @@ -2,17 +2,32 @@ * df32func.c * df32func extensions for Console Mode DataFlex 3.2 * - * Copyright (c) 2007-2009, glyn@8kb.co.uk + * Copyright (c) 2007-2015, glyn@8kb.co.uk * Author: Glyn Astill * *------------------------------------------------------------------------- */ -#include "df32func.h" #include #include #include #include +#include +#include "gnuregex.h" +#include "df32func.h" + +/* + * Used by GetTzi + * http://msdn.microsoft.com/en-us/library/ms724253.aspx + */ +typedef struct _REG_TZI_FORMAT +{ + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +} REG_TZI_FORMAT; SOCKET s, sc; /* Socket handle */ @@ -196,6 +211,119 @@ DLLIMPORT unsigned int RdtscRand(){ return n; } +/* + * Pull back timezone information from windows registry + */ +DLLIMPORT int GetTzi (TCHAR* zone, TCHAR *result) +{ + DWORD dwStatus, dwType, cbData; + int cch; + TCHAR szTime[128], szDate[128], szSubKey[256]; + HKEY hKey; + REG_TZI_FORMAT tzi; + + /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms647490%28v=vs.85%29.aspx */ + lstrcpy(szSubKey, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\")); + + /* + * https://msdn.microsoft.com/en-us/library/aa272954%28v=vs.60%29.aspx + * https://msdn.microsoft.com/en-us/library/h1x0y282.aspx + */ + _tcscat(szSubKey, zone); + + dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey); + if (dwStatus != NO_ERROR) + return GetLastError(); + + cbData = sizeof(REG_TZI_FORMAT); + dwStatus = RegQueryValueEx (hKey, TEXT("TZI"), NULL, &dwType, (LPBYTE)&tzi, &cbData); + if (dwStatus != NO_ERROR) + return GetLastError(); + + /* + * tzi.StandardDate and tzi.DaylightDate are not a real SYSTEMTIME + * but we should look at them to depict daylight saving + * if month = 0 then not supported, year = 0 means every year. + * http://msdn.microsoft.com/en-us/library/ms725481.asp + */ + + _stprintf(result, "%d,%d,%d,%d/%d/%d/%d,%d:%d:%d,%d/%d/%d/%d,%d:%d:%d", + tzi.Bias,tzi.StandardBias,tzi.DaylightBias, + tzi.StandardDate.wYear,tzi.StandardDate.wMonth,tzi.StandardDate.wDay,tzi.StandardDate.wDayOfWeek,tzi.StandardDate.wHour,tzi.StandardDate.wMinute,tzi.StandardDate.wSecond, + tzi.DaylightDate.wYear,tzi.DaylightDate.wMonth,tzi.DaylightDate.wDay,tzi.DaylightDate.wDayOfWeek,tzi.DaylightDate.wHour,tzi.DaylightDate.wMinute,tzi.DaylightDate.wSecond + ); + + return -1; +} + +/* + * Check for a regex match + */ +DLLIMPORT int RegexpMatch (const char *str, const char *pattern, const char *flags, int errors) +{ + return regexp_match(str, pattern, flags, errors); +} + +/* + * Return all matches in the regex as a string and return in custom format + */ +DLLIMPORT int RegexpMatches(const char *str, const char *pattern, const char *flags, char *output, int output_len, int errors) +{ + char *matches = regexp_matches(str, pattern, flags, errors); + int matches_len; + int result = 0; + + if (matches != NULL) + { + matches_len = strlen(matches); + if (matches_len <= output_len) + { + strncpy(output, matches, matches_len); + result = 0; + } + else + result = -1; + + wfree(matches); + } + else + result = -2; + + return result; +} + +/* + * Substitutes matches with the regex pattern in the string with the replacement + * pattern/string. + */ +DLLIMPORT int RegexpReplace(const char *str, const char *pattern, const char *replacement, const char *flags, char *output, int output_len, int errors) +{ + char *replaced = regexp_replace(str, pattern, replacement, flags, errors); + int replaced_len; + int result = 0; + + if (replaced != NULL) + { + replaced_len = strlen(replaced); + + if (replaced_len <= output_len) + { + strncpy(output, replaced, replaced_len); + result = 0; + } + else + result = -1; + + wfree(replaced); + } + else + result = -2; + + + return result; +} + + /* * DLL entry point */ diff --git a/src/c/df32func.h b/src/c/df32func.h index 7460c62..791e102 100644 --- a/src/c/df32func.h +++ b/src/c/df32func.h @@ -2,7 +2,7 @@ * df32func.h * df32func extension definitions * - * Copyright (c) 2007-2009, glyn@8kb.co.uk + * Copyright (c) 2007-2015, glyn@8kb.co.uk * Author: Glyn Astill * *------------------------------------------------------------------------- @@ -21,5 +21,9 @@ DLLIMPORT int ServerSocket(int PortNo); DLLIMPORT int AcceptClient(); DLLIMPORT unsigned int PseudoRand(unsigned int w); DLLIMPORT unsigned int RdtscRand(); +DLLIMPORT int GetTzi (TCHAR* zone, TCHAR *result); +DLLIMPORT int RegexpMatch(const char *str, const char *pattern, const char *flags, int errors); +DLLIMPORT int RegexpMatches(const char *str, const char *pattern, const char *flags, char *output, int output_len, int errors); +DLLIMPORT int RegexpReplace(const char *str, const char *pattern, const char *replacement, const char *flags, char *output, int output_len, int errors); #endif /* _DF32FUNC_H_ */ diff --git a/src/df32/console.h b/src/df32/console.h index 9e56ea1..fd03a0b 100644 --- a/src/df32/console.h +++ b/src/df32/console.h @@ -4,7 +4,7 @@ // // This file is to be included when using bigText in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/console.h //------------------------------------------------------------------------- diff --git a/src/df32/console.inc b/src/df32/console.inc index 75c8c42..4174a0e 100644 --- a/src/df32/console.inc +++ b/src/df32/console.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/console.inc //------------------------------------------------------------------------- @@ -51,9 +51,9 @@ function screen_display global string argv returns integer move 0 to l_iTotalLines move 0 to l_iTotalWidth - direct_input channel default_file_channel argv + direct_input channel DEFAULT_FILE_CHANNEL argv while not (seqeof) - readln channel default_file_channel l_sBuf + readln channel DEFAULT_FILE_CHANNEL l_sBuf move (rtrim(l_sBuf)) to l_sbuf move (replaces("{YELLOW}",l_sBuf,"")) to l_sBuf move (replaces("{WHITE}",l_sBuf,"")) to l_sBuf @@ -66,15 +66,15 @@ function screen_display global string argv returns integer if (length(l_sBuf) > l_iTotalWidth) move ((length(l_sBuf))+1) to l_iTotalWidth increment l_iTotalLines loop - close_input channel default_file_channel + close_input channel DEFAULT_FILE_CHANNEL while not (key.escape) - direct_input channel default_file_channel argv + direct_input channel DEFAULT_FILE_CHANNEL argv for l_i from 1 to l_iLineAt - readln channel default_file_channel + readln channel DEFAULT_FILE_CHANNEL loop for l_i from 1 to 22 - readln channel default_file_channel l_sBuf + readln channel DEFAULT_FILE_CHANNEL l_sBuf gotoxy (l_i-1) 0 if (uppercase(l_sBuf) contains "{YELLOW}") begin @@ -113,7 +113,7 @@ function screen_display global string argv returns integer show (pad(mid(l_sBuf,80,l_iWidthAt),80)) screenmode 1 loop - close_input channel default_file_channel + close_input channel DEFAULT_FILE_CHANNEL move "lines " to l_sTmp append l_sTmp (l_iLineAt+1) "-" (l_iLineAt+22) " of " (l_iTotalLines) diff --git a/src/df32/data.inc b/src/df32/data.inc index 2bd8fa1..14eafd7 100644 --- a/src/df32/data.inc +++ b/src/df32/data.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/data.inc //------------------------------------------------------------------------- @@ -799,6 +799,8 @@ end_class // hash_is_unique - Add a unique constraint on the hash // remove_hash_is_unique - Remove a unique constraint from the hash // matrix_index_lookup_clear - Clear the lookup buffer +// matrix_append_csv - Append some data in CSV format to the array E.g. ('My Name,"My,\"address\""') +// matrix_copy_csv - Copy csv data from sprecified file into matrix // // Set methods: // matrix_value - Set a value at X, Y @@ -815,19 +817,22 @@ end_class // matrix_index_lookup_clear - Clear the buffer for an indexed lookup // matrix_index_count_from_value - Get a count of rows with a particular value // matrix_index_from_value - Get the next X pos (row) with indexed value. Returns -1 when nothing left to find. +// item_count - Get count of rows in matrix +// item_width - Get count of columns in matrix // // Example usage: // -// // object test is a matrix // end_object // // set matrix_value of (test(current_object)) item 0 item 1 to "1" - x then y pos to Value // get matrix_value of (test(current_object)) item 0 item 1 to tmpStr - x then y pos to Value +// send matrix_append_csv to test ('My Name,"My,\"address\""') - Append CSV data to the end of the matrix +// send matrix_copy_csv to (test(current_object)) "f:\data.csv" - Copy data from csv file into matrix // send matrix_sort to (test(current_object)) 1 - x then y pos to sort by // send matrix_delete to (test(current_object)) 1 1 - x then y pos to delete // send matrix_delete_row to (test(current_object)) 1 - x essentially blanks record out, no reshuffle -// send delete_item to (test1(current_object)) 1 - x pos (not v efficient), reshuffles +// send delete_item to (test(current_object)) 1 - x pos (not v efficient), reshuffles // // Hash indexed columns usage: // @@ -841,12 +846,16 @@ end_class // get matrix_index_from_value of (test(current_object)) item "1" to x_pos // get matrix_indextable_from_value of (test(current_object)) item "1" to tmpStr // get matrix_hash_from_value of (test(current_object)) item "1" to tmpInt +// get item_count of (test(current_object) to tmpInt +// get item_width of (test(current_object) to tmpInt class matrix is an array procedure construct_object integer argc object mTokens is a StringTokenizer end_object - + object mTokens2 is a StringTokenizer + end_object + forward send construct_object property integer c_iWidth public argc property integer c_iHashOn @@ -1024,6 +1033,44 @@ class matrix is an array end end_procedure + procedure matrix_append_csv string row + local integer l_iMax l_iValues l_i + local string l_sBuf + + forward get item_count to l_iMax + + send delete_data to (mTokens2(current_object)) + send set_string_csv to (mTokens2(current_object)) row + get token_count of (mTokens2(current_object)) to l_iValues + + for l_i from 0 to l_iValues + get token_value of (mTokens2(current_object)) item l_i to l_sBuf + indicate err false + set matrix_value item l_iMax item l_i to l_sBuf + if (err) forward send delete_item l_iMax + if (err) break + loop + + end_procedure + + procedure matrix_copy_csv string fname + local string l_sBuf + + if (does_exist(fname)) begin + direct_input channel DEFAULT_FILE_CHANNEL fname + while not (seqeof) + readln channel DEFAULT_FILE_CHANNEL l_sBuf + if (seqeof) break + if (trim(l_sBuf) <> "") begin + send matrix_append_csv l_sBuf + end + loop + close_input channel DEFAULT_FILE_CHANNEL + end + else; + custom_error ERROR_CODE_FILE_NOT_FOUND$ ERROR_MSG_FILE_NOT_FOUND ERROR_DETAIL_FILE_NOT_FOUND fname + end_procedure + function matrix_string integer itemx integer itemy returns string local string l_sBuf l_sTmp @@ -1181,6 +1228,12 @@ class matrix is an array procedure set item_count integer newVal forward set item_count to newVal end_procedure + + function item_width returns integer + local integer l_iWidth + get c_iWidth to l_iWidth + function_return l_iWidth + end_function procedure matrix_delete integer itemx integer itemy local string l_sBuf l_sTmp l_sOldVal @@ -1529,39 +1582,39 @@ class rss20 is a matrix get c_itemCount to l_itemCount get c_ttl to l_iTtl - direct_output channel default_file_channel rssFileName - writeln channel default_file_channel '' - writeln channel default_file_channel '' - write channel default_file_channel '' + direct_output channel DEFAULT_FILE_CHANNEL rssFileName + writeln channel DEFAULT_FILE_CHANNEL '' + writeln channel DEFAULT_FILE_CHANNEL '' + write channel DEFAULT_FILE_CHANNEL '' // skipHours skipDays cloud - all currently not used // Write out Channel - writeln channel default_file_channel ' ' - writeln channel default_file_channel ' ' (trim(l_rssTitle)) '' - writeln channel default_file_channel ' ' (trim(l_rssLink)) '' - writeln channel default_file_channel ' ' (trim(l_rssDesc)) '' - writeln channel default_file_channel ' en-gb' - writeln channel default_file_channel ' Df32func RSS Object Generator' - writeln channel default_file_channel ' Copyright ' (trim(l_rssTitle)) ' (C) ' (now("date")) '' - writeln channel default_file_channel ' ' (rssdate((now("date")),(now("longtime")))) '' - writeln channel default_file_channel ' ' (rssdate((now("date")),(now("longtime")))) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_rssTitle)) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_rssLink)) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_rssDesc)) '' + writeln channel DEFAULT_FILE_CHANNEL ' en-gb' + writeln channel DEFAULT_FILE_CHANNEL ' Df32func RSS Object Generator' + writeln channel DEFAULT_FILE_CHANNEL ' Copyright ' (trim(l_rssTitle)) ' (C) ' (now("date")) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (rssdate((now("date")),(now("longtime")))) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (rssdate((now("date")),(now("longtime")))) '' - if (l_manEditor <> "") writeln channel default_file_channel ' ' l_manEditor '' - if (l_webMaster <> "") writeln channel default_file_channel ' ' l_webMaster '' - if (l_iTtl <> 0) writeln channel default_file_channel ' ' l_iTtl '' + if (l_manEditor <> "") writeln channel DEFAULT_FILE_CHANNEL ' ' l_manEditor '' + if (l_webMaster <> "") writeln channel DEFAULT_FILE_CHANNEL ' ' l_webMaster '' + if (l_iTtl <> 0) writeln channel DEFAULT_FILE_CHANNEL ' ' l_iTtl '' // Write out image if ((l_imgUrl <> "") and (l_imgx > 0) and (l_imgy > 0)) begin - writeln channel default_file_channel ' ' - writeln channel default_file_channel ' ' (trim(l_imgTitle)) '' - writeln channel default_file_channel ' ' (trim(l_imgUrl)) '' - writeln channel default_file_channel ' ' (trim(l_imgLink)) '' - writeln channel default_file_channel ' ' l_imgx '' - writeln channel default_file_channel ' ' l_imgy '' - writeln channel default_file_channel ' ' (trim(l_rssDesc)) '' - writeln channel default_file_channel ' ' + writeln channel DEFAULT_FILE_CHANNEL ' ' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_imgTitle)) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_imgUrl)) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_imgLink)) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_imgx '' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_imgy '' + writeln channel DEFAULT_FILE_CHANNEL ' ' (trim(l_rssDesc)) '' + writeln channel DEFAULT_FILE_CHANNEL ' ' end // Write out items @@ -1580,10 +1633,10 @@ class rss20 is a matrix move (replaces('<',l_itemDesc,"<")) to l_itemDesc move (replaces('>',l_itemDesc,">")) to l_itemDesc - writeln channel default_file_channel ' ' - writeln channel default_file_channel ' ' l_itemTitle '' - writeln channel default_file_channel ' ' l_itemLink '' - writeln channel default_file_channel ' ' l_itemDesc '' + writeln channel DEFAULT_FILE_CHANNEL ' ' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_itemTitle '' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_itemLink '' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_itemDesc '' if (l_itemGuID = "") begin move 0 to l_iConflict @@ -1595,17 +1648,17 @@ class rss20 is a matrix end if (l_itemGuID <> "") append l_itemLink "#" l_itemGuID - writeln channel default_file_channel ' ' l_itemLink '' - if ((l_pubDate = "") or (l_pubDate = "NOW")) writeln channel default_file_channel ' ' (rssdate((now("date")),(now("longtime")))) '' - else writeln channel default_file_channel ' ' l_pubDate '' - writeln channel default_file_channel ' ' l_itemCat '' - writeln channel default_file_channel ' ' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_itemLink '' + if ((l_pubDate = "") or (l_pubDate = "NOW")) writeln channel DEFAULT_FILE_CHANNEL ' ' (rssdate((now("date")),(now("longtime")))) '' + else writeln channel DEFAULT_FILE_CHANNEL ' ' l_pubDate '' + writeln channel DEFAULT_FILE_CHANNEL ' ' l_itemCat '' + writeln channel DEFAULT_FILE_CHANNEL ' ' loop // Write out file/channel close - writeln channel default_file_channel ' ' - writeln channel default_file_channel '' - close_output channel default_file_channel + writeln channel DEFAULT_FILE_CHANNEL ' ' + writeln channel DEFAULT_FILE_CHANNEL '' + close_output channel DEFAULT_FILE_CHANNEL end_procedure @@ -1674,13 +1727,13 @@ class filelist is a matrix set c_filelistDirectory to filelistDirectory set c_filelistName to filelistName - direct_input channel default_file_channel (filelistDirectory+filelistName) + direct_input channel DEFAULT_FILE_CHANNEL (filelistDirectory+filelistName) read_block l_sHead 256 while not (seqeof) //Block of 128 split 41\33\54 - read_block channel default_file_channel l_sRootName 41 - read_block channel default_file_channel l_sUserDisplayName 33 - read_block channel default_file_channel l_sFileName 54 + read_block channel DEFAULT_FILE_CHANNEL l_sRootName 41 + read_block channel DEFAULT_FILE_CHANNEL l_sUserDisplayName 33 + read_block channel DEFAULT_FILE_CHANNEL l_sFileName 54 move filelistDirectory to l_sUrn append l_sUrn (trim(cstring(l_sFileName))) ".FD" @@ -1698,7 +1751,7 @@ class filelist is a matrix increment l_iFileNumber end loop - close_input channel default_file_channel + close_input channel DEFAULT_FILE_CHANNEL set c_itemCount to l_iFileNumber end_procedure diff --git a/src/df32/date.inc b/src/df32/date.inc index fe997e5..9981107 100644 --- a/src/df32/date.inc +++ b/src/df32/date.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/date.inc //------------------------------------------------------------------------- diff --git a/src/df32/depmacro.inc b/src/df32/depmacro.inc index 112a6fa..31ac1eb 100644 --- a/src/df32/depmacro.inc +++ b/src/df32/depmacro.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/depmacro.inc //------------------------------------------------------------------------- diff --git a/src/df32/df32func.inc.autodoc b/src/df32/df32func.inc.autodoc index 2936ec1..d2df0a8 100644 --- a/src/df32/df32func.inc.autodoc +++ b/src/df32/df32func.inc.autodoc @@ -1,14 +1,17 @@ -df32func.inc last compiled on 09/04/2009 at 21:45:13.05 +df32func.inc last compiled on 25/09/2015 at 14:46:00.74 df32func DLL functions: -tcpcomm.h:external_function ClientSocket "ClientSocket" df32func.dll dword port string host returns integer -tcpcomm.h:external_function ServerSocket "ServerSocket" df32func.dll dword port returns integer -tcpcomm.h:external_function AcceptClient "AcceptClient" df32func.dll returns integer -tcpcomm.h:external_function Send "Send" df32func.dll dword socket string data returns integer -tcpcomm.h:external_function Receive "Receive" df32func.dll dword socket pointer dataOut returns integer -tcpcomm.h:external_function CloseConnection "CloseConnection" df32func.dll dword socket returns integer -tcpcomm.h:external_function PseudoRand "PseudoRand" df32func.dll dword w returns integer -tcpcomm.h:external_function RdtscRand "RdtscRand" df32func.dll returns integer -win32.h:external_function GetDateFormat "GetDateFormatA" kernel32.dll dword LCID dword dwFlags pointer lpsSystemTime pointer lpFormat pointer lpDateStr integer cchDate returns integer +df32func.h:external_function ClientSocket "ClientSocket" df32func.dll dword port string host returns integer +df32func.h:external_function ServerSocket "ServerSocket" df32func.dll dword port returns integer +df32func.h:external_function AcceptClient "AcceptClient" df32func.dll returns integer +df32func.h:external_function Send "Send" df32func.dll dword socket string data returns integer +df32func.h:external_function Receive "Receive" df32func.dll dword socket pointer dataOut returns integer +df32func.h:external_function CloseConnection "CloseConnection" df32func.dll dword socket returns integer +df32func.h:external_function PseudoRand "PseudoRand" df32func.dll dword w returns integer +df32func.h:external_function RdtscRand "RdtscRand" df32func.dll returns integer +df32func.h:external_function GetTzi "GetTzi" df32func.dll pointer lpTimeZone pointer lpResult returns integer +df32func.h:external_function RegexpMatch "RegexpMatch" df32func.dll pointer str pointer pattern pointer flags integer errors returns integer +df32func.h:external_function RegexpMatches "RegexpMatches" df32func.dll pointer str pointer pattern pointer flags pointer out pointer out_len integer errors returns integer +df32func.h:external_function RegexpReplace "RegexpReplace" df32func.dll pointer str pointer pattern pointer replacement pointer flags pointer out pointer out_len integer errors returns integerwin32.h:external_function GetDateFormat "GetDateFormatA" kernel32.dll dword LCID dword dwFlags pointer lpsSystemTime pointer lpFormat pointer lpDateStr integer cchDate returns integer win32.h:external_function GetTimeFormat "GetTimeFormatA" kernel32.dll dword LCID dword dwFlags pointer lpsSystemTime pointer lpFormat pointer lpTimeStr integer cchTime returns integer win32.h:external_function GetFileTime "GetFileTime" kernel32.dll handle hFileHandle pointer lpCreationTime pointer lpLastAccessTime pointer lpLastWriteTime returns integer win32.h:external_function FileTimeToSystemTime "FileTimeToSystemTime" kernel32.dll pointer lpFileTime Pointer lpSystemTime returns integer @@ -53,6 +56,8 @@ win32.h:external_function CopyMemory "RtlMoveMemory" kernel32.dll pointer pDst p win32.h:external_function EnumProcesses "EnumProcesses" psapi.dll pointer lpidProcess integer cb pointer cbNeeded returns integer win32.h:external_function EnumProcessModules "EnumProcessModules" psapi.dll handle hProcess pointer lphModule integer cb integer cbNeeded returns integer win32.h:external_function WideCharToMultiByte "WideCharToMultiByte" kernel32.dll integer cp dword dwF pointer lpWCS integer cchWC pointer lpMBS integer cchMB string dC string uDC returns integer +win32.h:external_function CharToOem "CharToOemA" user32.dll pointer lpszSrc pointer lpszDst returns integer +win32.h:external_function OemToChar "OemToCharA" user32.dll pointer lpszSrc pointer lpszDst returns integer win32.h:external_function GetSystemTime "GetSystemTime" kernel32.dll Pointer lpGST returns VOID_TYPE win32.h:external_function GetTickCount "GetTickCount" kernel32.dll returns dWord win32.h:external_function32 CoCreateGuid "CoCreateGuid" ole32.dll pointer pGUIDStructure returns word @@ -87,7 +92,6 @@ win32.h:external_function CryptStringToBinary "CryptStringToBinaryA" crypt32.dll win32.h:external_function GetVersionEx "GetVersionExA" kernel32.dll pointer lpVersionInfo returns integer win32.h:external_function GetSystemTime "GetSystemTime" kernel32.dll pointer lpSystemTime returns integer win32.h:external_function GetTimeZoneInformation "GetTimeZoneInformation" kernel32.dll pointer lpTimeZoneInformation returns integer -win32.h:external_function GetTzi "GetTzi" timezone.dll pointer lpTimeZone pointer lpResult returns integer df32func functions: console.inc:function set_mode global integer argv returns integer console.inc:function screen_display global string argv returns integer @@ -133,6 +137,11 @@ math.inc:function decround global number argv integer argv2 returns string math.inc:function rshift global integer argv integer shift_by returns integer math.inc:function lshift global integer argv integer shift_by returns integer math.inc:function ternary global string argv string argv2 string argv3 returns string +regex.inc:function regexp_match global string str string pattern string flags returns integer +regex.inc:function regexp_matches global string str string pattern string flags returns string +regex.inc:function regexp_replace global string str string pattern string replacement string flags returns string +regex.inc:function regexp_matches_count global string argv returns integer +regex.inc:function regexp_matches_item global string argv integer argv2 returns string string.inc:function titlecase global string argv returns string string.inc:function replaceall global string argv string argv2 string argv3 returns string string.inc:function zeropad global string argv integer argv2 returns string @@ -180,6 +189,8 @@ win32.inc:function file_size_bytes global string argv returns integer win32.inc:function to_ascii global string argv returns string win32.inc:function to_unicode global string argv returns string win32.inc:function to_utf8 global string argv returns string +win32.inc:function ansi_to_oem global string argv returns string +win32.inc:function oem_to_ansi global string argv returns string win32.inc:function get_procs global integer argv returns integer win32.inc:function time_data global integer argv returns string win32.inc:function fill_0 global integer iValue integer iSize returns string @@ -224,4 +235,6 @@ data.inc:class UnicodeReader is an array data.inc:class ListDirectory is a matrix data.inc:class ProcessList is an array string.inc:class StringTokenizer is an array +tap.inc:class TAP is an array +tap.inc:class TAP_harness is a TAP win32.inc:class msAdvCrypt is an array diff --git a/src/df32/df32func.mk b/src/df32/df32func.mk index 9ebc725..909316d 100644 --- a/src/df32/df32func.mk +++ b/src/df32/df32func.mk @@ -4,7 +4,7 @@ // // This is the file to be compiled by the dfcomp command // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/df32func.mk //------------------------------------------------------------------------- @@ -21,9 +21,9 @@ // Set dataflex epoch and set date format to 4 digit years //------------------------------------------------------------------------- -set_date_attribute date4_state to dftrue -set_date_attribute epoch_value to 80 -set_date_attribute sysdate4_state to dftrue +set_date_attribute date4_state to dftrue +set_date_attribute epoch_value to 80 +set_date_attribute sysdate4_state to dftrue //------------------------------------------------------------------------- // Standard DF32 Console Mode packages @@ -39,9 +39,25 @@ Use DLL //this package allows import of // Defines used to control some compile time behaviour //------------------------------------------------------------------------- -//Define enable_dfassert -Define no_backslash_quote -Define default_file_channel for 9 +//Define ENABLE_DFASSERT + +Define NO_BACKSLASH_QUOTE + +#IFDEF DEFAULT_FILE_CHANNEL +#ELSE + Define DEFAULT_FILE_CHANNEL for 9 +#ENDIF + +#IFDEF MAX_DFREGEX_BUFFER +#ELSE + Define MAX_DFREGEX_BUFFER for 16384 +#ENDIF + +#IFDEF ERRORS_TO_STDERR +#ELSE + Define ERRORS_TO_STDERR for 0 +#ENDIF + //------------------------------------------------------------------------- // Global variables used to control some runtime behaviour @@ -72,8 +88,8 @@ indicate show_debug_lines false //Including header file win32.h #INCLUDE win32.h -//Including include file tcpcom.h -#INCLUDE tcpcomm.h +//Including include file df32func.h +#INCLUDE df32func.h //Including include file console.h #INCLUDE console.h //Including include file encode.h @@ -84,6 +100,10 @@ indicate show_debug_lines false #INCLUDE macro.inc //Including include file math.inc #INCLUDE math.inc +//Including include file tap.inc +#INCLUDE tap.inc +//Including include file regex.inc +#INCLUDE regex.inc //Including include file win32.inc #INCLUDE win32.inc //Including include file string.inc diff --git a/src/df32/encode.h b/src/df32/encode.h index 9d9eb56..d605fdc 100644 --- a/src/df32/encode.h +++ b/src/df32/encode.h @@ -4,7 +4,7 @@ // // This file is to be included when using RC4/Base64 encoding in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/encode.h //------------------------------------------------------------------------- diff --git a/src/df32/errors.h b/src/df32/errors.h index 5c7bb00..b63ad95 100644 --- a/src/df32/errors.h +++ b/src/df32/errors.h @@ -4,8 +4,8 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk -// +// Copyright (c) 2006-2015, glyn@8kb.co.uk +// // df32func/errors.h //------------------------------------------------------------------------- @@ -27,7 +27,11 @@ enum_list Define ERROR_CODE_INVALID_TIMESTAMP$ Define ERROR_CODE_INVALID_POSIX_NUMBER$ Define ERROR_CODE_INVALID_SYSTEM_TIMEZONE$ + Define ERROR_CODE_COMPARISON_OPERATOR$ Define ERROR_CODE_INVALID_BOOLEAN$ + Define ERROR_CODE_REGEX_BUFFER_OVERFLOW$ + Define ERROR_CODE_REGEX_COMPILE_FAILURE$ + Define ERROR_CODE_FILE_NOT_FOUND$ end_enum_list //------------------------------------------------------------------------- @@ -51,6 +55,10 @@ end_enum_list #REPLACE ERROR_MSG_INVALID_POSIX_NUMBER "Invalid posix number: ??" #REPLACE ERROR_MSG_INVALID_SYSTEM_TIMEZONE "Invalid system timezone" #REPLACE ERROR_MSG_INVALID_BOOLEAN "Value does not evaluate to boolean" +#REPLACE ERROR_MSG_COMPARISON_OPERATOR "Not a valid operator: ??" +#REPLACE ERROR_MSG_REGEX_BUFFER_OVERFLOW "Regex output buffer too small: ??" +#REPLACE ERROR_MSG_REGEX_COMPILE_FAILURE "Regex compilation failed" +#REPLACE ERROR_MSG_FILE_NOT_FOUND "File not found or permission denied" //------------------------------------------------------------------------- // Error message detail @@ -61,3 +69,4 @@ end_enum_list #REPLACE ERROR_DETAIL_GETLASTERROR "GetLastError = ??" #REPLACE ERROR_DETAIL_INVALID_TIMESTAMP "Format: ??" #REPLACE ERROR_DETAIL_INVALID_BOOLEAN "Value ?? != true/false" +#REPLACE ERROR_DETAIL_FILE_NOT_FOUND "File: ??" diff --git a/src/df32/hash.inc b/src/df32/hash.inc index 9b668ea..02d595c 100644 --- a/src/df32/hash.inc +++ b/src/df32/hash.inc @@ -6,7 +6,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/hash.inc //------------------------------------------------------------------------- diff --git a/src/df32/macro.inc b/src/df32/macro.inc index 9c250a9..6ca54ce 100644 --- a/src/df32/macro.inc +++ b/src/df32/macro.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/macro.inc //------------------------------------------------------------------------- @@ -29,7 +29,7 @@ // ASSERT (1=2) "TEST ASSERT" // #COMMAND ASSERT R - #IFDEF enable_dfassert + #IFDEF ENABLE_DFASSERT #IF (!0=2) #IFTYPE !1 "I" if (!1 = 0); diff --git a/src/df32/math.inc b/src/df32/math.inc index 98a7ee4..70e738e 100644 --- a/src/df32/math.inc +++ b/src/df32/math.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/math.inc //------------------------------------------------------------------------- diff --git a/src/df32/string.inc b/src/df32/string.inc index 9607e63..f951c2e 100644 --- a/src/df32/string.inc +++ b/src/df32/string.inc @@ -5,7 +5,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/string.inc //------------------------------------------------------------------------- @@ -87,7 +87,7 @@ end_function // Standard escaping via C standard. // -// For PostgreSQL when no_backslash_quote is defined single quotes are +// For PostgreSQL when NO_BACKSLASH_QUOTE is defined single quotes are // escaped per SQL standard by doubling '' rather than \' because in // some encodings multibyte characters have a last byte numerically // equivalent to ASCII escaped by backslash "\". @@ -97,7 +97,7 @@ function addslashes global string argv returns string local string l_sReturn move (replaces("\",argv,"\\")) to l_sReturn - #IFDEF no_backslash_quote + #IFDEF NO_BACKSLASH_QUOTE move (replaces("'",l_sReturn,"''")) to l_sReturn #ELSE move (replaces("'",l_sReturn,"\'")) to l_sReturn @@ -249,9 +249,9 @@ function msxsl global string engine string source string stylesheet string param if (outfile = "") begin move (file_size_bytes(l_sFile)) to l_iFileSize - direct_input channel default_file_channel l_sFile - read_block channel default_file_channel l_sReturn l_iFileSize - close_input channel default_file_channel + direct_input channel DEFAULT_FILE_CHANNEL l_sFile + read_block channel DEFAULT_FILE_CHANNEL l_sReturn l_iFileSize + close_input channel DEFAULT_FILE_CHANNEL move (fileopp("delete",l_sFile,"")) to l_iThrow end else move outfile to l_sReturn @@ -268,8 +268,11 @@ end_function // String tokenizer class // // Send message methods: -// set_string -// +// set_string - Send the string to be tokenized and the delimiter to split on +// set_string_csv - Send a CSV string to be tokenized. As per general CSV data: +// * Items containting commas to be enclosed in double quotes: '"' +// * Double quotes in quotes to be escaped with a backslash: '\' +// // Set methods: // token_value // @@ -329,6 +332,46 @@ class StringTokenizer is an array set c_iTokenOn to 0 set c_iTokens to l_iTokens end_procedure + + procedure set_string_csv string argv + local integer l_i l_iQuot l_iTokens + local string l_sChar l_sLast l_sNext l_sBuf + + move -1 to l_iTokens + move 0 to l_iQuot + move "" to l_sLast + + for l_i from 0 to (length(argv)) + move (mid(argv,1,l_i)) to l_sChar + move (mid(argv,1,l_i+1)) to l_sNext + move (mid(argv,1,l_i-1)) to l_sLast + + if ((l_iQuot) and (l_sChar = '\') and (l_sNext = '"')) break begin + + if ((l_sChar = '"') and (l_sLast <> '\')) begin + if (l_iQuot) move 0 to l_iQuot + else move 1 to l_iQuot + end + if ((l_sChar = '"') and (l_sLast <> '\')) break begin + + if ((l_sChar = ',') and not (l_iQuot)) begin + //fwd to Array + increment l_iTokens + forward set array_value item l_iTokens to l_sBuf + move "" to l_sBuf + end + if ((l_sChar = ',') and not (l_iQuot)) break begin + + append l_sBuf l_sChar + loop + + //fwd to Array + increment l_iTokens + forward set array_value item l_iTokens to l_sBuf + + set c_iTokenOn to 0 + set c_iTokens to l_iTokens + end_procedure procedure set token_value integer itemx string val forward set array_value item itemx to val diff --git a/src/df32/tstamp.inc b/src/df32/tstamp.inc index e5519a3..dd43470 100644 --- a/src/df32/tstamp.inc +++ b/src/df32/tstamp.inc @@ -6,7 +6,7 @@ // // This file is to be included in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/tstamp.inc //------------------------------------------------------------------------- diff --git a/src/df32/win32.h b/src/df32/win32.h index 64553e8..8c42634 100644 --- a/src/df32/win32.h +++ b/src/df32/win32.h @@ -6,7 +6,7 @@ // // This file is to be included when using Win32 capabilities in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/win32.h //------------------------------------------------------------------------- @@ -62,6 +62,8 @@ external_function CopyMemory "RtlMoveMemory" kernel32.dll pointer pDst pointer p external_function EnumProcesses "EnumProcesses" psapi.dll pointer lpidProcess integer cb pointer cbNeeded returns integer external_function EnumProcessModules "EnumProcessModules" psapi.dll handle hProcess pointer lphModule integer cb integer cbNeeded returns integer external_function WideCharToMultiByte "WideCharToMultiByte" kernel32.dll integer cp dword dwF pointer lpWCS integer cchWC pointer lpMBS integer cchMB string dC string uDC returns integer +external_function CharToOem "CharToOemA" user32.dll pointer lpszSrc pointer lpszDst returns integer +external_function OemToChar "OemToCharA" user32.dll pointer lpszSrc pointer lpszDst returns integer external_function GetSystemTime "GetSystemTime" kernel32.dll Pointer lpGST returns VOID_TYPE external_function GetTickCount "GetTickCount" kernel32.dll returns dWord external_function32 CoCreateGuid "CoCreateGuid" ole32.dll pointer pGUIDStructure returns word @@ -96,7 +98,6 @@ external_function CryptStringToBinary "CryptStringToBinaryA" crypt32.dll pointer external_function GetVersionEx "GetVersionExA" kernel32.dll pointer lpVersionInfo returns integer external_function GetSystemTime "GetSystemTime" kernel32.dll pointer lpSystemTime returns integer external_function GetTimeZoneInformation "GetTimeZoneInformation" kernel32.dll pointer lpTimeZoneInformation returns integer -external_function GetTzi "GetTzi" timezone.dll pointer lpTimeZone pointer lpResult returns integer //------------------------------------------------------------------------- // Constants diff --git a/src/df32/win32.inc b/src/df32/win32.inc index 5a91c13..cd6dc5a 100644 --- a/src/df32/win32.inc +++ b/src/df32/win32.inc @@ -5,7 +5,7 @@ // // This file is to be included when using Win32 capabilities in df32func.mk // -// Copyright (c) 2006-2009, glyn@8kb.co.uk +// Copyright (c) 2006-2015, glyn@8kb.co.uk // // df32func/win32.inc //------------------------------------------------------------------------- @@ -681,15 +681,15 @@ function to_ascii global string argv returns string move (trim(argv)) to l_sUnicode if (l_sUnicode <> "") begin - zerostring 100 to l_sAscii + zerostring (length(l_sUnicode)) to l_sAscii getAddress of l_sAscii to l_pAscii getAddress of l_sUnicode to l_pUnicode - // set the length of cchWideChar to -1 and function assumes null termination and calculates lenght itsself + // set the length of cchWideChar to -1 and function assumes null termination and calculates length itsself move (WideCharToMultiByte(CP_OEMCP,0,l_pUnicode,-1,0,0,0,0)) to l_iCharsNeeded move (WideCharToMultiByte(CP_OEMCP,0,l_pUnicode,-1,l_pAscii,l_iCharsNeeded,0,0)) to l_iThrow end - function_return l_sAscii + function_return (cstring(l_sAscii)) end_function // Attempt to convert a string from ASCII to unicode via MultiByteToWideChar @@ -700,15 +700,15 @@ function to_unicode global string argv returns string move (trim(argv)) to l_sAscii if (l_sAscii <> "") begin - zerostring 100 to l_sUnicode + zerostring (length(l_sAscii)*2) to l_sUnicode getAddress of l_sUnicode to l_pUnicode getAddress of l_sAscii to l_pAscii - // set the length of cchWideChar to -1 and function assumes null termination and calculates lenght itsself + // set the length of cchWideChar to -1 and function assumes null termination and calculates length itsself move (MultiByteToWideChar(CP_ACP,0,l_pAscii,-1,0,0,0,0)) to l_iCharsNeeded move (MultiByteToWideChar(CP_ACP,0,l_pAscii,-1,l_pUnicode,l_iCharsNeeded,0,0)) to l_iThrow end - function_return l_sUnicode + function_return (cstring(l_sUnicode)) end_function // Attempt to convert a string from ascii to UTF8 via WideCharToMultiByte @@ -719,7 +719,7 @@ function to_utf8 global string argv returns string move (trim(argv)) to l_sUnicode if (l_sUnicode <> "") begin - zerostring 100 to l_sUTF8 + zerostring (length(l_sUnicode)) to l_sUTF8 getAddress of l_sUTF8 to l_pUTF8 getAddress of l_sUnicode to l_pUnicode @@ -728,7 +728,47 @@ function to_utf8 global string argv returns string move (WideCharToMultiByte(CP_UTF8,0,l_pUTF8,-1,l_pUnicode,l_iCharsNeeded,0,0)) to l_iThrow end - function_return l_sUTF8 + function_return (cstring(l_sUTF8)) +end_function + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647473%28v=vs.85%29.aspx +// Note security considerations, as this function doesn't enforce string lengths +function ansi_to_oem global string argv returns string + local string l_sOem l_sAnsi + local pointer l_pOem l_pAnsi + local integer l_iResult + + if (length(argv) <> 0) begin + move argv to l_sAnsi + getaddress of l_sAnsi to l_pAnsi + zerostring (length(l_sAnsi)+1) to l_sOem + getaddress of l_sOem to l_pOem + move (CharToOem(l_pAnsi, l_pOem)) to l_iResult + end + else; + move argv to l_sOem + + function_return (cstring(l_sOem)) +end_function + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms647493%28v=vs.85%29.aspx +// Note security considerations, as this function doesn't enforce string lengths +function oem_to_ansi global string argv returns string + local string l_sOem l_sAnsi + local pointer l_pOem l_pAnsi + local integer l_iResult + + if (length(argv) <> 0) begin + move argv to l_sOem + getaddress of l_sOem to l_pOem + zerostring (length(l_sOem)+1) to l_sAnsi + getaddress of l_sAnsi to l_pAnsi + move (CharToOem(l_pOem, l_pAnsi)) to l_iResult + end + else; + move argv to l_sAnsi + + function_return (cstring(l_sAnsi)) end_function // Get running processes on the system -- 2.39.2