Oxygen Basic
Programming => Bugs & Feature Requests => Topic started by: Brian Alvarez on May 05, 2019, 11:25:48 AM
-
Hello Charles, I am noticing something really weird and i am at the point that i am considering this a bug in oxygen... i cant find any other explanation.
I am converting the following code from PluriBASIC to Oxygen:
(https://www.oxygenbasic.org/forum/index.php?action=dlattach;topic=1873.0;attach=6893;image)
I have a TYPE called ABC. As follows.
TYPE ABC
CHAR astr[20]
WCHAR wstr[20]
CHAR ast2[20]
END TYPE
Then, in a module i declare some variables as follow:
DWORD ff
ABC a
CHAR b[20]
INT c
WSTRING inputstring
Let me explain the issue:
If i remark "GET #FF,,B" Everything works as expected, the code also displays the contents of a.astr, which are: *This is 1 ASCII* But when I execute the code, and PluriBASIC generates this macros:
¤GETSTR(bstring, ff, -1, b, ¤TMPV2, 20)
¤STRN(b, ¤TMPV2, 20)
Then, the last byte of b gets written in the first byte of the a UDT, particularily at the beggining of a.astr, so, the null byte causes that STDOUT truncates the output to a null string.
In the ¤STRN macro, i explicitly limit the contents of b to its maximum size, as follows:
//Assigns a truncated null terminated string.
MACRO ¤STRN(v, c, l b)
string b = c
if len(b) > l then b = left(b, l)
v = b
END MACRO
And everything works as expected (except the loading of the b variable) if i remark the v = b part.
Everything works as expected also if i change the size of the b string to 10 characters, or 200. But if i specifically state 20 characters, Oxygen is allocating overlapped bytes.
Im sorry if my error reports are long and hard to understand. Its the simplest way i have to explain it.
-
By the way, before i forget, Oxygen also goes crazy if i save to file the string *It's an ascii str*, it seems like it doesnt like the ' character, it truncates everything in a weird way. Maybe the tokenizer is acting up again.
Im going to test the newest version now.
-
Also... dont let this deceive you:
B = SPACE$(LOF(FF))
Even though i am stating that the string should load more content that it is supposed to hold, i just did that to make sure it is not doing it. In fact LOF is out of service right now. The string only loads 20 bytes. Also, i was thinking that oxygen is creating a base 0 array for b[20], creating 21 bytes, but the problem occurs if i cut the string 1 byte in the ¤STRN() macro.
Here is the code that pluribasic is generating, in case you want to play with it. It is probably a simple thing that i am overlooking:
'Generated with PluriBASIC 6.0.233801.0
$ filename "C:\Users\Diamante\Documents\PluriBASIC\projects\fulll_file_test.exe"
uses rtl32
uses console
Declare Function ¤MessageBoxa Lib "user32.dll" Alias "MessageBoxA"
Declare Function ¤MessageBoxw Lib "user32.dll" Alias "MessageBoxW"
STRING ¤TMPS = "" ' a temporary string.
DECLARE FUNCTION ¤GetAsyncKeyState Lib "User32.dll" Alias "GetAsyncKeyState" (ByVal vKey AS LONG) AS short
DECLARE SUB ¤Sleep lib "Kernel32.dll" alias "Sleep" (dword mSec)
function ¤QINI(int v1, v2) as quad
quad qs=0x10000 : qs*=0x10000
return qs*v1+v2
end function
DECLARE FUNCTION ¤OpenProcess Lib "KERNEL32.DLL" Alias "OpenProcess" (ByVal dwDesiredAccess AS DWORD, ByVal bInheritHandle AS LONG, ByVal dwProcessId AS SYS) AS SYS
DECLARE FUNCTION ¤TerminateProcess Lib "KERNEL32.DLL" Alias "TerminateProcess" ( ByVal hProcess AS SYS, ByVal uExitCode AS DWORD) AS LONG
DECLARE FUNCTION ¤CloseHandle Lib "KERNEL32.DLL" Alias "CloseHandle" (ByVal hObject AS SYS) AS LONG
DECLARE FUNCTION ¤GetCurrentProcessId Lib "KERNEL32.DLL" Alias "GetCurrentProcessId" () AS SYS
MACRO ¤ONERR(l, e)
Err.err = e
IF (Err.err>0) THEN
Err.ers = Err.erp
Err.erl = l
IF Err.Oe1 THEN
JMP Err.Oe1
ELSEIF Err.Oe2 THEN
CALL Err.Oe2
END IF
else
Err.ers = ""
Err.erl = 0
END IF
END MACRO
MACRO ERRCLEAR
Err.err = 0
Err.erl = 0
Err.ers = ""
END MACRO
CLASS ¤SYSERR
public sys Oe1 = 0
public sys Oe2 = 0
public int err = 0
public int erl = 0
public string erp = ""
public string ers = ""
END CLASS
declare FUNCTION ¤CloseHandle LIB "KERNEL32.DLL" ALIAS "CloseHandle" (byval fHandle AS SYS) AS DWORD
DECLARE FUNCTION ¤CreateFileA LIB "KERNEL32.DLL" ALIAS "CreateFileA" ( _
ByVal lpFileName AS DWORD, _
ByVal dwDesiredAccess AS DWORD, _
ByVal dwShareMode AS DWORD, _
ByVal lpSecurityAttributes AS DWORD, _
ByVal dwCreationDisposition AS DWORD, _
ByVal dwFlagsAndAttributes AS DWORD, _
BYVAL hTemplateFile AS DWORD) AS DWORD
DECLARE FUNCTION ¤CreateFileW LIB "KERNEL32.DLL" ALIAS "CreateFileW" ( _
ByVal lpFileName AS DWORD, _
ByVal dwDesiredAccess AS DWORD, _
ByVal dwShareMode AS DWORD, _
ByVal lpSecurityAttributes AS DWORD, _
ByVal dwCreationDisposition AS DWORD, _
ByVal dwFlagsAndAttributes AS DWORD, _
BYVAL hTemplateFile AS DWORD) AS DWORD
DECLARE FUNCTION ¤SetFilePointerEx LIB "KERNEL32.DLL" ALIAS "SetFilePointerEx" ( _
BYVAL hFile AS SYS, _
BYVAL lDistanceToMove AS SYS, _
BYREF lpNewFilePointer AS SYS, _
BYVAL dwMoveMethod AS DWORD) AS INT
DECLARE FUNCTION ¤WriteFile LIB "Kernel32.dll" ALIAS "WriteFile" ( _
BYVAL hFile AS SYS, BYVAL lpBuffer AS SYS, _
BYVAL nNumberOfBytesToWrite AS DWORD, lpNumberOfBytesWritten AS DWORD, _
lpOverlapped AS DWORD) AS DWORD
DECLARE FUNCTION ¤ReadFile LIB "Kernel32.dll" ALIAS "ReadFile" ( _
BYVAL hFile AS SYS, BYVAL lpBuffer AS SYS, _
BYVAL nNumberOfBytesToRead AS DWORD, lpNumberOfBytesRead AS DWORD, _
lpOverlapped AS DWORD) AS DWORD
DECLARE FUNCTION ¤WriteConsole LIB "KERNEL32.DLL" ALIAS "WriteFile" (BYVAL hFile AS DWORD, lpBuffer AS ANY, BYVAL nNumberOfBytesToWrite AS LONG, lpNumberOfBytesWritten AS LONG, lpOverlapped AS ANY) AS LONG
DECLARE FUNCTION ¤AllocConsole LIB "KERNEL32.DLL" ALIAS "AllocConsole" () AS LONG
DECLARE FUNCTION ¤FlushFileBuffers LIB "KERNEL32.DLL" ALIAS "FlushFileBuffers" (BYVAL hFile AS DWORD) AS LONG
DECLARE FUNCTION ¤GetStdHandle LIB "KERNEL32.DLL" Alias "GetStdHandle" (ByVal nStdHandle AS DWORD) AS DWORD
TYPE ¤HPROP
long elem
long dmode
sys oldProc
sys curProc
'long user1
'long user2
END TYPE
Function ¤DEFAULT_CALLBACK_PROC(sys hwnd, wMsg, wParam, lParam) as sys callback
sys retval = 0
return retval
End Function
' STARTS PLURIBASIC_PREPARE.BIN
' This code is executed before anything else, if you want to do something after defining other things, see PLURIBASIC_INIT
' STARTS TERMINATE.BIN
' STARTS MSGBOX.BIN
FUNCTION MSGBOX(wstring wText, int mOptions, string aCaption) AS LONG
wstring wCaption = mid(aCaption, 1)
FUNCTION = ¤MessageBoxw(0, wText, wCaption, mOptions)
end function
FUNCTION MSGBOX(string aText, int mOptions, wstring wCaption) AS LONG
wstring wText = mid(aText, 1)
FUNCTION = ¤MessageBoxw(0, wText, wCaption, mOptions)
end function
FUNCTION MSGBOX(wstring wText, int mOptions, wstring wCaption) AS LONG
FUNCTION = ¤MessageBoxw(0, wText, wCaption, mOptions)
end function
FUNCTION MSGBOX(string aText, int mOptions, string aCaption) AS LONG
FUNCTION = ¤MessageBoxa(0, aText, aCaption, mOptions)
END FUNCTION
FUNCTION MSGBOX(string aText) AS LONG
string aCaption = "PluriBASIC"
int mOptions = 0
FUNCTION = ¤MessageBoxa(0, aText, aCaption, mOptions)
END FUNCTION
FUNCTION MSGBOX(wstring wText) AS LONG
wString wCaption = "PluriBASIC"
int mOptions = 0
FUNCTION = ¤MessageBoxw(0, wText, wCaption, mOptions)
END FUNCTION
FUNCTION MSGBOX(string aText, int mOptions) AS LONG
string aCaption = "PluriBASIC"
FUNCTION = ¤MessageBoxa(0, aText, aCaption, mOptions)
END FUNCTION
FUNCTION MSGBOX(wstring wText, int mOptions) AS LONG
wString wCaption = "PluriBASIC"
FUNCTION = ¤MessageBoxw(0, wText, wCaption, mOptions)
END FUNCTION
' END OF MSGBOX.BIN
' CONTINUES (1) TERMINATE.BIN
FUNCTION _TERMINATE(string sText = "") as long
if len(sText) then
MSGBOX(sText, 64)
end if
sys hProcess = ¤OpenProcess(1, 0, ¤GetCurrentProcessId())
If (hProcess<>0) And (hProcess <> 0xFFFFFFFF) Then
¤TerminateProcess(hProcess, 0)
¤CloseHandle(hProcess)
End If
END FUNCTION
' END OF TERMINATE.BIN
' CONTINUES (12) PLURIBASIC_PREPARE.BIN
#DEF HANDLE SYS
MACRO ¤SET_ERR(n)
Err.err = n
Err.erl = Err.erp
END MACRO
MACRO ¤UDTCOPY(s, u, n)
copy u, n, s
END MACRO
macro ¤USETV(vu, ai, of, dt, nv, ln a, c)
sys a = ai + of
dt c = nv
copy a, @c, ln
end macro
macro ¤USETA(vu, ai, of, nv, ln a, c)
sys a = ai + of
string c = left(nv, ln)
c = (c + news(ln-len(c)))
copy(a, strptr(c), ln)
end macro
macro ¤USETW(vu, ai, of, nv, ln a, c)
sys a = ai + of
wstring c = left(nv, ln)
c = (c + news(ln-len(c)))
copy(a, strptr(c), ln*2)
end macro
macro ¤MSETV(vu, of, dt, nv, ln c)
dt c = nv
copy @vu + of, @c, ln
end macro
macro ¤MSETA(vu, of, nv, ln c)
string c = left(nv, ln)
c = (c + news(ln-len(c)))
copy(@vu + of, strptr(c), ln)
end macro
macro ¤MSETW(vu, of, nv, ln c)
wstring c = left(nv, ln)
c = (c + news(ln-len(c)))
copy(@vu + of, strptr(c), ln*2)
end macro
macro ¤MINCR(vu, of, dt, nv, ln c, a)
dt a = 0
copy @, @vu + of, ln
dt c = (a + (nv))
copy @vu + of, @c, ln
end macro
macro ¤MDECR(vu, of, dt, nv, ln c, a)
dt a = 0
copy @, @vu + of, ln
dt c = (a - (nv))
copy @vu + of, @c, ln
end macro
macro ¤SDT_VAL(nm, dt)
function nm(sys hBuffer, of) as dt
sys a = hBuffer + of
dt r
copy @r, a, sizeof(dt)
return r
end function
end macro
macro ¤SDT_STR(nm)
function nm(sys hBuffer, offset, int ln) as string
sys addr = (hBuffer + offset)
string bb = space(ln+1)
copy(strptr(bb), addr, ln)
return bb
end function
end macro
macro ¤SDT_WST(nm)
function nm(sys hBuffer, of, int ln) as wstring
sys addr = (hBuffer + of)
wstring bb = news(ln)
copy(strptr(bb), addr, ln*2)
return bb
end function
end macro
TYPE ¤SYSNMHDR
hwndFrom AS SYS
idFrom AS SYS
Code AS DWORD
END TYPE
' flags for internal file system.
% ·SYSFILE = 1
% ·SYSTCP = 2
% ·SYSUDP = 4
% ·SYSCOMM = 8
'% ·SYS?? = 16 ' RESERVED
% ·ASSIGN = 32
% ·ASSIGNED = 64
% ·HANDLE = 128
'% ·????? = 512 ' RESERVED
% ·BINARY = 512
% ·RANDOM = 1024
% ·INPUT = 2048
% ·OUTPUT = 4096
% ·APPEND = 8192
% ·ANSI = 16384
% ·WIDE = 32768
% ·LOCK_WRITE = 65536
% ·LOCK_READ = 131072
% ·BASE_ZERO = 262144
% ·BASE_ONE = 524288
class ¤SYSF
public int CURHN
public int FHNDL[32767] ' File handle.
public int FFLAG[32767] ' Socket flags.
public int FRLEN[32767] ' Record length
int LRNGN ' Last Random number generated.
int LRNUB ' Last RND upper bound.
int LRNLB ' Last RND lower bound.
' Default UDT member bounds...
function m(int d1) as long {return d1}
function m(int d1, d2) as long {return (d1 * d2)}
function m(int d1, d2, d3) as long {return ((d1 * d2) + d3)}
' Custom UDT member bounds...
' UDT member readers.
¤SDT_VAL(byt, byte)
¤SDT_VAL(wrd, word)
¤SDT_VAL(int, int)
¤SDT_VAL(lng, long)
¤SDT_VAL(sys, sys)
¤SDT_VAL(dwd, dword)
¤SDT_VAL(qud, quad)
¤SDT_VAL(ext, extended)
¤SDT_VAL(cur, extended)
¤SDT_VAL(cux, extended)
¤SDT_VAL(sng, single)
¤SDT_VAL(dbl, double)
¤SDT_STR(asz)
¤SDT_STR(chr)
¤SDT_WST(wsz)
FUNCTION CONSTRUCTOR()
this.CURHN = 1
END FUNCTION
END CLASS
new ¤SYSF EXE()
' END OF PLURIBASIC_PREPARE.BIN
' STARTS WSTRING.BIN
//assigns a truncated null terminated string.
MACRO ¤WSTR(v, c, l b)
wstring b = c
if len(b) > l then b = left(b, l)
v = b
END MACRO
' END OF WSTRING.BIN
' STARTS UDT_ASSIGNER.BIN
// copies binary data into a UDT
MACRO UDT_ASSIGNER(src, trg buf, i)
string buf
int i = sizeof(src)
buf = trg
if i > len(buf) then i = len(buf)
copy @src, strptr(buf), i
END MACRO
' END OF UDT_ASSIGNER.BIN
' STARTS STRING.BIN
//Assigns a truncated null terminated string.
MACRO ¤STRN(v, c, l b)
string b = c
if len(b) > l then b = left(b, l)
v = b
END MACRO
' END OF STRING.BIN
' STARTS STR$.BIN
' STARTS LTRIM$.BIN
// returns a trimed string
FUNCTION LTRIM(string src, long a = 0, string ch = " ") as string
if len(src) = 0 then return ""
if len(ch) = 0 then return ""
byte srcchar at strptr(src)
byte trichar at strptr(ch)
long p1 = 1
long index
long cha
if a then
for index = 1 to len(src)
for cha = 1 to len(ch)
if srcchar[index] = trichar[cha] then
goto checknextchar
end if
next
p1 = index
exit for
checknextchar:
next
return mid(src, p1)
else
for index = 1 to len(src)
for cha = 1 to len(ch)
if srcchar[index+cha-1] <> trichar[cha] then
goto nomorematches
end if
next
p1 += len(ch)
next
nomorematches:
return mid(src, p1)
end if
END FUNCTION
' END OF LTRIM$.BIN
' CONTINUES (1) STR$.BIN
FUNCTION ¤STR(double v, long d = 8) as string
long d2 = d-1
string ss = ""
'int dp ' DECIMAL PLACES
'int trz ' STRIP TRAILING ZEROS
'int sn ' SCIENTIFIC NOTATION BY DEFAULT
'int sdp ' INHIBIT ZERO BEFORE DECIMAL POINT
'int sns ' LEADING SPACE FOR NON NEGATIVE NUMBERS
'int lps ' LEAD PADDING SPACES
'numberformat(8,0,0,0,1,0) 'default settings
if v < 0 then
ss = str(v, d2)
else
ss = str(v, d2)
if instr(ss, ".") then
ss = " " & LTRIM(ss, 0, "0")
else
ss = " " & ltrim(ss)
end if
end if
'numberformat 'return to default
return ss
END FUNCTION
'FUNCTION ¤STR(quad v, long d = 16) as string
' 'PRINT " TWO " + V
' long d2 = d-1
' if v < 0 then
' return str(v, d2)
' else
' string ss = str(v, d2)
' return " " & ltrim(ss)
' end if
'END FUNCTION
' END OF STR$.BIN
' STARTS PRINTR.BIN
SUB ¤INITCONSOLE()
STATIC Allc AS LONG
IF Allc=0 THEN
¤AllocConsole()
Allc = 1
END IF
END SUB
MACRO ¤STDOUT()
LOCAL lWritten AS LONG
LOCAL hFile AS DWORD
LOCAL Btc AS LONG
LOCAL TTsnd AS STRING
¤INITCONSOLE()
¤Sleep(0)
hFile = ¤GetStdHandle(-11)
FOR Btc = 1 TO 50
IF ((Btc*32000)-31999) > len(s) THEN EXIT FOR
TTsnd = MID$(s, ((Btc*32000)-31999), 32000)
¤WriteConsole(hFile, ByVal StrPtr(TTsnd), Len(TTsnd), lWritten, ByVal 0&)
NEXT Btc
¤FlushFileBuffers(hFile)
END MACRO
SUB PRINTR(byval s AS WSTRING, byval b as string)
¤STDOUT()
END SUB
SUB PRINTR(byval s AS STRING, byval b as string)
¤STDOUT()
END SUB
' END OF PRINTR.BIN
' STARTS PLURIBASIC_INIT.BIN
' This code is executed before anything else, if you want to do something before nything else, see PLURIBASIC_PREPARE
' END OF PLURIBASIC_INIT.BIN
' STARTS OPEN.BIN
'h = handle must be an open file handle.
'fn = filename.
'm = input mode
'a = access mode
'l = lock mode
'ff = filenumber.
'ln = record lenght
'bs = base address
'ch = 1 = anso, 2 = WIDE
' Opens a file by its already opened handle.
SUB ¤OPENHANDLE(int h, int m, a, l, ff, ln, bs, ch, ¤SYSERR Err)
IF (ff < 1) OR (ff > 32767) THEN ¤SET_ERR(57) : EXIT FUNCTION
IF EXE.FFLAG[ff] <> ·ASSIGN THEN ¤SET_ERR(57) : EXIT FUNCTION
EXE.FFLAG[ff] = (EXE.FFLAG[ff] OR ·ASSIGNED OR ·SYSFILE OR ·HANDLE)
END SUB
'========================================================================================
' Opens a file by its filename.
SUB ¤OPENFILENM(string fn, int m, a, l, ff, ln, bs, ch, BYREF ¤SYSERR Err)
IF (ff < 1) OR (ff > 32767) THEN
¤SET_ERR(57)
EXIT FUNCTION
END IF
IF EXE.FFLAG[ff] <> ·ASSIGN THEN
¤SET_ERR(57)
EXIT FUNCTION
END IF
EXE.FFLAG[ff] = 0
string fname = fn + chr(0)
long fAccess = 0
long fLock = 0
long fCreation = 0
long fFlags = 0
Select CASE m ' Mode
CASE 2 ' output
EXE.FFLAG[ff] = ·OUTPUT
fCreation = 4 ' create
fAccess = 2
if ((a and 1) = 1) THEN ' access READ??
¤SET_ERR(70)
EXIT FUNCTION
end if
case 3 ' append
EXE.FFLAG[ff] = ·APPEND
fCreation = 4 ' create
fAccess = 2
if ((a and 1) = 1) THEN ' access READ??
¤SET_ERR(70)
EXIT FUNCTION
end if
case 4 ' binary
EXE.FFLAG[ff] = ·BINARY
fCreation = 4 ' create
if a = 0 then a = 3
CASE ELSE
fCreation = 3 ' open_existing
END SELECT
if ((a and 1) = 1) then fAccess = (fAccess or 0x80000000) ' access read
if ((a and 2) = 2) then fAccess = (fAccess or 0x40000000) ' access write
if (fLock <> 0) then
if ((l and 1) <> 1) then fLock = (fLock or 0x80000000) ' lock read operations
if ((l and 2) <> 2) then fLock = (flock or 0x40000000) ' lock write operations
end if
IF ch = 1 THEN
EXE.FHNDL[ff] = ¤CreateFileA(strptr(fName), fAccess, fLock, 0, fCreation, fFlags, 0)
'PRINTR(¤STR(fAccess) + ¤STR(m) + ¤STR(fLock) + ¤STR(fCreation), chr(10, 13))
IF EXE.FHNDL[ff] = -1 THEN
¤SET_ERR(70)
ELSE
'¤CloseHandle(EXE.FHNDL[ff])
'EXE.FHNDL[ff] = ¤CreateFileA(strptr(fName), fAccess, fLock, 0, 3, fFlags, 0)
EXE.FFLAG[ff] = (EXE.FFLAG[ff] OR ·ASSIGNED OR ·SYSFILE OR ·ANSI)
END IF
ELSE
EXE.FHNDL[ff] = ¤CreateFileW(StrPtr(fName), fAccess, fLock, 0, fCreation, fFlags, 0)
IF EXE.FHNDL[ff] = -1 THEN
¤SET_ERR(70)
ELSE
'¤CloseHandle(EXE.FHNDL[ff])
'EXE.FHNDL[ff] = ¤CreateFileA(strptr(fName), fAccess, fLock, 0, 3, fFlags, 0)
EXE.FFLAG[ff] = (EXE.FFLAG[ff] OR ·ASSIGNED OR ·SYSFILE OR ·WIDE)
END IF
END IF
if m = 3 then
' set append position here.
'¤SetFilePointer(EXE.FHNDL[ff], 0, byval 0, FILE_END)
end if
END SUB
' END OF OPEN.BIN
' STARTS LOF.BIN
'Returns the size of a file in bytes.
FUNCTION LOF(byval int fn) AS QUAD
END FUNCTION
' END OF LOF.BIN
' STARTS INP.BIN
'
FUNCTION INP( ) AS LONG
END FUNCTION
' END OF INP.BIN
' STARTS GET.BIN
' This file contains all the variations of use for the PUT statement.
' Writes a string to an open file.
SUB ¤ReadBinary(byval long fn, byval quad fp, byref string st, int sl, byref ¤SYSERR Err)
IF ((EXE.FFLAG[fn] and ·BINARY) <> ·BINARY) AND ((EXE.FFLAG[fn] and ·RANDOM) <> ·RANDOM) THEN
¤SET_ERR(70)
return
END IF
int w = 0
IF (sl>0) THEN
IF fp > -1 then
¤SetFilePointerEx(EXE.FHNDL[fn], byval (fp-1), byval 0, byval 0)
end if
¤ReadFile(EXE.FHNDL[fn], strptr(st), sl, w, null)
IF w = 0 THEN
¤SET_ERR(70)
END IF
END IF
END SUB
MACRO ¤GETUDT(vt, fn, fp, var, tv, ts c, t)
string tv = news(ts)
¤ReadBinary(fn, fp, tv, ts, Err)
END MACRO
MACRO ¤GETSTR(vt, fn, fp, var, tv, sl ln, gg)
int ln = sl
IF sl < 1 THEN
ln = len(var)
END IF
string tv = space(20)
¤ReadBinary(fn, fp, tv, ln, Err)
END MACRO
MACRO ¤GETVAR(vt, fn, fp, var, tv, ln tt)
string tt = news(ln)
¤ReadBinary(fn, fp, tt, ln, Err)
vt tv
copy @tv, tt, ln
END MACRO
' END OF GET.BIN
' STARTS FREEFILE.BIN
' returns the next free handle.
FUNCTION FREEFILE() AS LONG
int i = EXE.CURHN
for i = i to 32767
if EXE.FFLAG[i] = 0 then
EXE.CURHN = i
EXE.FFLAG[i] = ·ASSIGN
EXE.FHNDL[i] = 0
EXE.FRLEN[i] = 0
return i
end if
next
for i = 1 to EXE.CURHN
if EXE.FFLAG[i] = 0 then
EXE.CURHN = i
EXE.FFLAG[i] = ·ASSIGN
EXE.FHNDL[i] = 0
EXE.FRLEN[i] = 0
return i
end if
next
return 0
END FUNCTION
' END OF FREEFILE.BIN
' STARTS CLOSE.BIN
' Closes an opened file.
FUNCTION CLOSE(int ff, BYREF ¤SYSERR Err) AS LONG
IF (ff < 1) OR (ff > 32767) THEN
¤SET_ERR(57)
EXIT FUNCTION
END IF
IF EXE.FFLAG[ff] = ·ASSIGN THEN
¤SET_ERR(57)
EXIT FUNCTION
END IF
IF ((EXE.FFLAG[ff] and ·HANDLE) <> ·HANDLE) THEN
if (¤CloseHandle(EXE.FHNDL[ff]) = 0) then
¤SET_ERR(70)
EXIT FUNCTION
end if
END IF
EXE.FFLAG[ff] = 0
EXE.FHNDL[ff] = 0
EXE.FRLEN[ff] = 0
END FUNCTION
' END OF CLOSE.BIN
' STARTS CALLBACKDATA.BIN
' END OF CALLBACKDATA.BIN
TYPE ABC
CHAR astr[20]
WCHAR wstr[20]
CHAR ast2[20]
END TYPE
' SYSTEM DECLARES FOR ARRAYS
DECLARE FUNCTION PBMAIN() AS LONG
' Initializes various things in the script.
FUNCTION PluriBASIC_Initialize() AS LONG
END FUNCTION
FUNCTION PBMAIN() AS INT
INT ¤RETVAL = 0
¤SYSERR Err
DWORD ff
ABC a
CHAR b[20]
INT c
WSTRING inputstring
ff = FREEFILE()
¤OPENFILENM("C:\Users\Diamante\Documents\Test.txt", 4, 0, 0, ff, 128, 1, 1, Err)
IF Err.err THEN
PRINTR("ERROR" + ¤STR(Err.err, byval 0) & " OPENING THE FILE.", chr(13, 10))
ELSE
PRINTR("SUCCES OPENING THE FILE.", chr(13, 10))
END IF
¤GETUDT(abc, ff, 1, a, ¤TMPV1, 80)
¤UDTCOPY(80, @a, ¤TMPV1)
¤STRN(b, SPACE(LOF(ff)), 20)
¤GETSTR(bstring, ff, -1, b, ¤TMPV2, 20)
¤STRN(b, ¤TMPV2, 20)
CLOSE(ff, Err)
PRINTR("-----------" & chr(13,10), chr(13, 10))
PRINTR("Done:" & chr(13,10), chr(13, 10))
PRINTR(EXE.chr(@a, 0, 20) & chr(13,10), chr(13, 10))
PRINTR(EXE.chr(@a, 60, 20) & chr(13,10), chr(13, 10))
PRINTR(EXE.wsz(@a, 20, 20) & chr(13,10), chr(13, 10))
PRINTR(b & chr(13,10), chr(13, 10))
PRINTR(¤STR(c, byval 0) & chr(13,10), chr(13, 10))
RETURN ¤RETVAL
END FUNCTION
PBMAIN() ' invoke entry point
-
Hi Brian,
Just a brief observation for now:
Each member in this structure can hold a max 19 character string + null terminator.
Overflows are possible with these fixed length strings.
TYPE ABC
CHAR astr[20]
WCHAR wstr[20]
CHAR ast2[20]
END TYPE
-
Hello Charles.
I dont see the need for UDT members to store a null character at the end of strings when the length of the string is exactly the number of characters specified for the element other than when using it as a string parameter via its pointer. But that is up to you.
Since i am not using Oxygen's internal mechanism to read UDT members that doesnt affect the code im generating (i made my own address and offset manager because of the udt dimensions). That said, the issue is not with UDT's. it is with stand-alone fixed-length strings writing in the space of (what should be) a completely unrelated udt (the memory space should not conflict). But i understand it. For now i will be fixing it by appending a couple extra characters to the fixed length strings. Hopefully that will fix it. I mean... i will do that if you have not yet fixed it in newer versions of Oxygen (i have yet to test).
However, i suspect it could more likely have something to do with something not being freed correctly on Oxygen's macros. Hopefully im wrong, because that would affect a whole other lof of my code.
-
I just tested the newest version of Oxygen, unfortunately it complains about something else that is not very clear:
; ASM ERR: _56!! Unidentified instruction: _56
; AFTER: .'
; LINE: 83
Line 83:
(https://www.oxygenbasic.org/forum/index.php?action=dlattach;topic=1873.0;attach=6895;image)
-
Went back to the version i was using. Adding 2 extra bytes fixes everything. Confirming it is an overflow error by Oxygen's internals. :(
-
Hi Brian,
My preference is to stay with null-terminated chars without boundary checks, but I'll look into it.