Oxygen Basic

Programming => Bugs & Feature Requests => Topic started by: Brian Alvarez on May 19, 2019, 02:32:53 PM

Title: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 19, 2019, 02:32:53 PM

This code works fine when using STRING, but crashes when using WSTRING.

Code: [Select]
SUB TESTVARIABLEWSTRING()
   WSTRING p1
   WSTRING p2
   p1 = ("TEST")
   IF p1 <> p2 THEN
       print "Leave me here" "remark me and the program works"     ' remark the second string literal and the program runs fine.
   END IF
END SUB

FUNCTION PBMAIN() AS INT
     TESTVARIABLEWSTRING()
END FUNCTION

PBMAIN() ' invoke entry point
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 19, 2019, 03:53:13 PM
even simpler:

Code: [Select]
print "one" "two"
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 19, 2019, 06:08:45 PM
Yes, the problem is between 2 string literals without an explicit '+' or '&' operator.. I'm trying to fix it.

Code: [Select]
print "one "+"two " 'okay
Title: Re: Using WSTRING crashes string concatenations.
Post by: JRS on May 19, 2019, 07:01:45 PM
Fix that?

One would expect a , or a & in a PRINT statement.
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 19, 2019, 07:13:23 PM
One would expect a , or a & in a PRINT statement.

Charles, made it that way. Thats fine with me. It makes debugging quicker.

Charles... unfortunately it is also happening with & or + in a script i have here. Thats what initially made me suspect of WSTRING, if all that
changes in the whole file are that W's, thats the difference between working fine and crashing. Let me know if you want me to send the files to you.
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 19, 2019, 07:16:28 PM
O2 assumes an implicit '+' in any expression where operators are absent.

Anyway, I've now fixed the quoted string problem by removing an unhealthy optimization. Always pleased to remove excess code :)

I'll check wstrings ...
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 19, 2019, 07:35:28 PM
Thats good news Charles, thank you! :)
Title: Re: Using WSTRING crashes string concatenations.
Post by: JRS on May 19, 2019, 07:52:17 PM
Quote
O2 assumes an implicit '+' in any expression where operators are absent.

I feel that sacrifices readability for laziness.

When did pressing a space become more efficient than pressing a +?
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 19, 2019, 11:59:53 PM
John,

This has always been a feature. Very useful for simplifying string concatenations. Rarely induces errors.


Brian,

Wstrings pass my wide-string tests.
Title: Re: Using WSTRING crashes string concatenations.
Post by: Aurel on May 20, 2019, 05:10:20 AM
I don't know for you but most logical way is using sign +
and that should be explicit in every case.
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 20, 2019, 06:31:51 AM
Charles, this is part of a script i made, i made it to test that passing all types of parameters to modules behave correctly when passed BYREF and when passed BYVAL.
It works fine with STRING, but with WSTRING it crashes before the code is able to do much.

 Heres for STRING:


Code: [Select]
$ filename "C:\Users\Diamante\Documents\PluriBASIC\Clean\SMALLER.exe"

uses rtl32
uses console

DIM STRING ¤SYSTEM_UDT_OFFSETS(0)
STRING ¤TMPS = "" ' a temporary string.
DECLARE FUNCTION ¤GetLastError        Lib "Kernel32.dll" Alias "GetLastError" () AS LONG
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 ¤INI_QUAD(dword v1, v2) as quad
    quad v = 0
    copy @v+0, @v2, 4
    copy @v+4, @v1, 4
    return v
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 ¤SET_ERR(n)
    Err.err = n
    Err.erl = Err.erp
END MACRO

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 ¤WriteConsole     LIB "KERNEL32.DLL" ALIAS "WriteFile" (BYVAL hFile AS SYS, lpBuffer AS ANY, BYVAL nNumberOfBytesToWrite AS dword, lpNumberOfBytesWritten AS dword, lpReserved AS long) AS LONG
DECLARE FUNCTION ¤AllocConsole     LIB "KERNEL32.DLL" ALIAS "AllocConsole" () AS LONG
DECLARE FUNCTION ¤FlushFileBuffers LIB "KERNEL32.DLL" ALIAS "FlushFileBuffers" (BYVAL hFile AS SYS) AS LONG
DECLARE FUNCTION ¤GetStdHandle     LIB "KERNEL32.DLL" Alias "GetStdHandle" (ByVal nStdHandle AS DWORD) AS SYS

' STARTS PLURIBASIC_PREPARE.BIN
' This code is executed before anything else, if you want to do something after defining other things, see PLURIBASIC_INIT




#DEF HANDLE SYS






TYPE ¤SYSNMHDR
    hwndFrom AS SYS
    idFrom   AS SYS
    Code     AS DWORD
END TYPE


class ¤SYSF


                             
    FUNCTION CONSTRUCTOR()
    END FUNCTION       
           
END CLASS

new ¤SYSF EXE()


' END OF PLURIBASIC_PREPARE.BIN
' STARTS STRINGN.BIN
//Assigns a truncated null terminated string.
MACRO ¤STRN_SET(v, c, l  b)   
    string b = c
    if len(b) > l then
        b = left(b, l)
    elseif len(b) < l then
        b += space(l-len(b))
    end if
    v = b               
END MACRO


' END OF STRINGN.BIN
' STARTS PRINTR.BIN

SUB ¤INITCONSOLE()
    STATIC Allc AS LONG
    IF Allc=0 THEN
        ¤AllocConsole()
        Allc = 1
    END IF   
END SUB

MACRO ¤STDOUT() 
  INT lWritten = 0     
  SYS hFile    = 0
  INT Btc      = 0
  STRING TTsnd = ""
 
  ¤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), byval 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

SUB PRINTR(CHAR *c, byval string b)
    string s = c   
    ¤STDOUT()     
END SUB

'SUB PRINTR(WCHAR *c, byval string b)
'    string s = c   
'    ¤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 LCASE$.BIN
' LCASE$ stock code (not required by oxygen)
' END OF LCASE$.BIN
' STARTS CALLBACKDATA.BIN
' END OF CALLBACKDATA.BIN


DECLARE SUB QUERYVARIABLESTRING(BYVAL P1 AS STRING, P2 AS STRING)
DECLARE SUB TESTVARIABLESTRING()
DECLARE FUNCTION PBMAIN() AS LONG
STRING ¤¤on16k36
STRING ¤¤mn1ak36


' Initializes various things in the script.
FUNCTION PluriBASIC_Initialize() AS LONG

END FUNCTION

SUB QUERYVARIABLESTRING(STRING »p1, STRING *p2)
   ¤SYSERR Err
   STRING p1 = »p1
   IF (p1=¤¤on16k36) THEN
      PRINTR("*Success " & "Passing byval " & LCASE("STRING") & " to a module" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Passing byval " & LCASE("STRING") & " to a module" & " in " & "QUERYVARIABLESTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p1 & " but expected " & ¤¤on16k36 & chr(13,10), chr(13, 10))
   END IF
   IF (p2=¤¤on16k36) THEN
      PRINTR("*Success " & "Passing byref " & LCASE("STRING") & " to a module" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Passing byref " & LCASE("STRING") & " to a module" & " in " & "QUERYVARIABLESTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p2 & " but expected " & ¤¤on16k36 & chr(13,10), chr(13, 10))
   END IF
   p2 = (¤¤mn1ak36)
END SUB

SUB TESTVARIABLESTRING()
   ¤SYSERR Err
   STRING p1
   STRING p2
   p1 = ¤¤on16k36
   p2 = ¤¤on16k36
   IF (p1=¤¤on16k36) THEN
      PRINTR("*Success " & "Default value assignation for " & LCASE("STRING") & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Default value assignation for " & LCASE("STRING") & " in " & "TESTVARIABLESTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p1 & " but expected " & ¤¤on16k36 & chr(13,10), chr(13, 10))
   END IF
   QUERYVARIABLESTRING(p1, p2)
   IF (p1=¤¤on16k36) THEN
      PRINTR("*Success " & "Retaining original value after passed byval" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Retaining original value after passed byval" & " in " & "TESTVARIABLESTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p1 & " but expected " & ¤¤on16k36 & chr(13,10), chr(13, 10))
   END IF
   IF (p2=¤¤mn1ak36) THEN
      PRINTR("*Success " & "Retaining changes made in module when passed byref" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Retaining changes made in module when passed byref" & " in " & "TESTVARIABLESTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p2 & " but expected " & ¤¤mn1ak36 & chr(13,10), chr(13, 10))
   END IF
   PRINTR("-------", chr(13, 10))
END SUB

FUNCTION PBMAIN() AS INT
   INT ¤RETVAL = 0
   ¤SYSERR Err
   ¤¤on16k36 = ("ORIG")
   ¤¤mn1ak36 = ("MODIFIED")
   TESTVARIABLESTRING()
   PRINTR("DONE:  " & "INFO", "</br>")
   RETURN ¤RETVAL
END FUNCTION

PBMAIN() ' invoke entry point

And here is for WSTRING:

Code: [Select]
$ filename "C:\Users\Diamante\Documents\PluriBASIC\Clean\SMALLER.exe"

uses rtl32
uses console

DIM STRING ¤SYSTEM_UDT_OFFSETS(0)
STRING ¤TMPS = "" ' a temporary string.
DECLARE FUNCTION ¤GetLastError        Lib "Kernel32.dll" Alias "GetLastError" () AS LONG
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 ¤INI_QUAD(dword v1, v2) as quad
    quad v = 0
    copy @v+0, @v2, 4
    copy @v+4, @v1, 4
    return v
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 ¤SET_ERR(n)
    Err.err = n
    Err.erl = Err.erp
END MACRO

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 ¤WriteConsole     LIB "KERNEL32.DLL" ALIAS "WriteFile" (BYVAL hFile AS SYS, lpBuffer AS ANY, BYVAL nNumberOfBytesToWrite AS dword, lpNumberOfBytesWritten AS dword, lpReserved AS long) AS LONG
DECLARE FUNCTION ¤AllocConsole     LIB "KERNEL32.DLL" ALIAS "AllocConsole" () AS LONG
DECLARE FUNCTION ¤FlushFileBuffers LIB "KERNEL32.DLL" ALIAS "FlushFileBuffers" (BYVAL hFile AS SYS) AS LONG
DECLARE FUNCTION ¤GetStdHandle     LIB "KERNEL32.DLL" Alias "GetStdHandle" (ByVal nStdHandle AS DWORD) AS SYS

' STARTS PLURIBASIC_PREPARE.BIN
' This code is executed before anything else, if you want to do something after defining other things, see PLURIBASIC_INIT




#DEF HANDLE SYS






TYPE ¤SYSNMHDR
    hwndFrom AS SYS
    idFrom   AS SYS
    Code     AS DWORD
END TYPE


class ¤SYSF


                             
    FUNCTION CONSTRUCTOR()
    END FUNCTION       
           
END CLASS

new ¤SYSF EXE()


' END OF PLURIBASIC_PREPARE.BIN
' STARTS WSTRING.BIN
//assigns a truncated null terminated string.
MACRO ¤WSTR_SET(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 PRINTR.BIN

SUB ¤INITCONSOLE()
    STATIC Allc AS LONG
    IF Allc=0 THEN
        ¤AllocConsole()
        Allc = 1
    END IF   
END SUB

MACRO ¤STDOUT() 
  INT lWritten = 0     
  SYS hFile    = 0
  INT Btc      = 0
  STRING TTsnd = ""
 
  ¤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), byval 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

SUB PRINTR(CHAR *c, byval string b)
    string s = c   
    ¤STDOUT()     
END SUB

'SUB PRINTR(WCHAR *c, byval string b)
'    string s = c   
'    ¤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 LCASE$.BIN
' LCASE$ stock code (not required by oxygen)
' END OF LCASE$.BIN
' STARTS CALLBACKDATA.BIN
' END OF CALLBACKDATA.BIN


DECLARE SUB QUERYVARIABLEWSTRING(BYVAL P1 AS WSTRING, P2 AS WSTRING)
DECLARE SUB TESTVARIABLEWSTRING()
DECLARE FUNCTION PBMAIN() AS LONG
WSTRING ¤¤on16k33
WSTRING ¤¤mn1ak33


' Initializes various things in the script.
FUNCTION PluriBASIC_Initialize() AS LONG

END FUNCTION

SUB QUERYVARIABLEWSTRING(WSTRING »p1, WSTRING *p2)
   ¤SYSERR Err
   WSTRING p1 = »p1
   IF (p1=¤¤on16k33) THEN
      PRINTR("*Success " & "Passing byval " & LCASE("WSTRING") & " to a module" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Passing byval " & LCASE("WSTRING") & " to a module" & " in " & "QUERYVARIABLEWSTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p1 & " but expected " & ¤¤on16k33 & chr(13,10), chr(13, 10))
   END IF
   IF (p2=¤¤on16k33) THEN
      PRINTR("*Success " & "Passing byref " & LCASE("WSTRING") & " to a module" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Passing byref " & LCASE("WSTRING") & " to a module" & " in " & "QUERYVARIABLEWSTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p2 & " but expected " & ¤¤on16k33 & chr(13,10), chr(13, 10))
   END IF
   p2 = (¤¤mn1ak33)
END SUB

SUB TESTVARIABLEWSTRING()
   ¤SYSERR Err
   WSTRING p1
   WSTRING p2
   p1 = ¤¤on16k33
   p2 = ¤¤on16k33
   IF (p1=¤¤on16k33) THEN
      PRINTR("*Success " & "Default value assignation for " & LCASE("WSTRING") & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Default value assignation for " & LCASE("WSTRING") & " in " & "TESTVARIABLEWSTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p1 & " but expected " & ¤¤on16k33 & chr(13,10), chr(13, 10))
   END IF
   QUERYVARIABLEWSTRING(p1, p2)
   IF (p1=¤¤on16k33) THEN
      PRINTR("*Success " & "Retaining original value after passed byval" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Retaining original value after passed byval" & " in " & "TESTVARIABLEWSTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p1 & " but expected " & ¤¤on16k33 & chr(13,10), chr(13, 10))
   END IF
   IF (p2=¤¤mn1ak33) THEN
      PRINTR("*Success " & "Retaining changes made in module when passed byref" & chr(13,10), chr(13, 10))
   ELSE
      PRINTR("*Failure " & "Retaining changes made in module when passed byref" & " in " & "TESTVARIABLEWSTRING"  & "*" & chr(13,10), chr(13, 10))
      PRINTR("         got " & p2 & " but expected " & ¤¤mn1ak33 & chr(13,10), chr(13, 10))
   END IF
   PRINTR("-------", chr(13, 10))
END SUB

FUNCTION PBMAIN() AS INT
   INT ¤RETVAL = 0
   ¤SYSERR Err
   ¤¤on16k33 = ("ORIG")
   ¤¤mn1ak33 = ("MODIFIED")
   TESTVARIABLEWSTRING()
   PRINTR("DONE:  " & "INFO", "</br>")
   RETURN ¤RETVAL
END FUNCTION

PBMAIN() ' invoke entry point

At first I thought that some functions could be expecting a STRING instead of a WSTRING, but after i remarked everything that could use it,
the program still crashed. It could still be my fault, somehow, but...
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 20, 2019, 07:55:23 AM
Hi Brian,

I could not get either to work, unfortunately. Only a flash of console. Something unstable?
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 20, 2019, 08:55:20 AM
Hmm... when i comment out the part that outputs to console, the app crashes anyway. Im not sure what it is causing it.
I can comment out everything and it still crashes, except for these lines, that when i remove, it works:

Code: [Select]
PRINTR("*Failure " & "Passing byval " & LCASE("STRING") & " to a module" & " in " & "QUERYVARIABLESTRING"  & "*" & chr(13,10), chr(13, 10))
PRINTR("         got " & p1 & " but expected " & ¤¤on16k36 & chr(13,10), chr(13, 10))

 Did you see anything odd on your side?
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 25, 2019, 02:47:20 PM
Charles, i narrowed it down to this:

Code: [Select]
sub testwstr(byref wstring p1)
 
   IF (p1 = "orig") THEN   ' crashes if you bracket the condition.
   'IF p1 = "orig" THEN    ' doesnt crash if you dont use brackets, but comparation fails.
                           ' (i guess it is making a byte per byte comparison which obviously fails, given one is ANSI and theother is UNICODE).
      print("+Success")
   ELSE
      print("-Failure" & "")  ' crashes with bracketed condition + an extra string concatenated here...
   END IF
   
end sub
   
testwstr("orig")

I think it is worth a fix for the next update. :)

Needless to say, it works also fine if you use string instead of wstring.

Added:
 When the bracket condition is unbracketed, it does not crash, but it displays Failure, when it should display Success... or not?
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 26, 2019, 01:36:41 AM
Yes, Ive found the source of the error. It will be fixed. Thanks Brian.

You will need to match string widths for comparison:

Code: [Select]
wstring s="123"
if  (s + L"" = L"12" + L"3" )
  print s
else
  print "nok"
endif
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 27, 2019, 02:42:05 PM
 Thanks charles, its good to hear it will make it in the next update! :)

:)
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 27, 2019, 02:47:43 PM
This raises a new question... how do i compare an ansi string variable to a unicode string variable? how do i make the unicode to ansi conversion?

I ask because this example returns EQUAL...

Code: [Select]
FUNCTION CMPR(STRING »a, STRING »b) AS INT
   STRING a = »a
   STRING b = »b
   RETURN (a=b)
END FUNCTION

   WSTRING su
   STRING sa
   su = "compare 1"
   sa = "compare 2"
   IF CMPR(su, sa) THEN
      print "EQUAL"
   ELSE
      print "DIFFERENT"
   END IF
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 27, 2019, 10:31:37 PM
Hi Brian,

Comparing different string types is a mine-field. So the best strategy is to assign to a matching type. Then use it for the comparison expression.

typeof(leftside) rightside 'dim a matching type
rightside=rightside_expression


Code: [Select]
string  s="abc"
wstring t="abc"
char    u="abc"
wchar   v="abc"

typeof(t) rs 'dim a matching type

'these will auto-convert
'rs=s
rs=u
'rs=v

if t=rs
  print "ok"
else
  print "nok"
endif


Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 27, 2019, 10:48:34 PM
I understand, no problem. I can handle comparisons and make them seamless.

 However, I would like you to take a look at this Charles:

Code: [Select]
FUNCTION CMPR(STRING »a, STRING »b) AS INT
   STRING a = »a
   STRING b = »b
   IF (a=b) THEN
      print "equal 1"
   ELSE
      print "different 1"
   END IF
   RETURN (a = b)
END FUNCTION

   STRING su
   STRING sa
   su = "compare2"
   sa = "compare3"
   IF CMPR(su, sa) THEN
      print "equal 2"
   ELSE
      print "different 2"
   END IF

This outputs:

Code: [Select]
different 1
equal 2

 I think the comparison is correct, but the return value is wrong...
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 28, 2019, 12:36:59 AM
Yes, there is a confusion between assignment and equality.

This fixes it:

return (a == b)

Code: [Select]
FUNCTION CMPR(STRING »a, STRING »b) AS INT
   STRING a = »a
   STRING b = »b
   IF (a=b) THEN
      print "equal 1"
   ELSE
      print "different 1"
   END IF
int c=(a==b)
print c
   return (a == b)
   'function = (a == b)
END FUNCTION

   STRING su
   STRING sa
   su = "compare3"
   sa = "compare3"
   IF CMPR(su, sa) THEN
      print "equal 2"
   ELSE
      print "different 2"
   END IF

You can see the difference more clearly here:

Code: [Select]
'assignments vs logical expressions
int a,b,c,d
c=2
d=2
a=(c=d)
b=(c==d)
print a ",  " b
Title: Re: Using WSTRING crashes string concatenations.
Post by: Aurel on May 28, 2019, 05:01:13 AM
What kind of sign is this prefix of a  :o
I don't have such a symbol on my keyboard.
and really why complicate with ==  ::)
Title: Re: Using WSTRING crashes string concatenations.
Post by: jack on May 28, 2019, 08:46:40 AM
in the case of OxygenBasic using == seems appropriate, because of the support C'ish syntax, which can come in handy when porting C code to O2
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 28, 2019, 09:03:24 AM
What kind of sign is this prefix of a  :o
I don't have such a symbol on my keyboard.
and really why complicate with ==  ::)

 That is the idea, to add a symbol that is not in the keyboard. I thought that symbol was apropriate
because the parameters are being "passed". Oxygen does not have a full byval feature, so, one has to
add a manual copy in some cases, a copy that can be altered if necessary.

Although i think in this case is not necessary for editing the parameter, it is necessary to make conversion from unicode to ANSI.

 In the real code, you never have to touch the symbol, see the image attached.



Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 28, 2019, 10:22:28 AM
After investigating this Assignment-versus-Equality problem, I will allow (a=b) to be an equality expression instead an assignment expression. This will now have the same behaviour as (a==b)

But we still have the Pascal-style assignment operator available (a := b)

There may be one or two eamples using assignment expressions like:

a=b=c=d

These will have to be changed to:

a = b := c := d
Title: Re: Using WSTRING crashes string concatenations.
Post by: Brian Alvarez on May 28, 2019, 10:28:53 AM
Perfect! Thanks! :)
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 28, 2019, 10:38:00 AM
Speaking of Unicode, o2 required some small fixes to be able to read Unicode source-code files.
Unicode string literals will now be possible. Note the 'L' prefix before the quote mark for Unicode.


Code: [Select]
uses corewin
messageboxW 0, l"Γεια σου κόσμο",l"title",0
Title: Re: Using WSTRING crashes string concatenations.
Post by: Charles Pegge on May 29, 2019, 08:16:40 AM
o2 will also support Unicode symbols:

Code: [Select]
double φ, ϕ, π

φ = (sqr(5)+1)/2
ϕ = (sqr(5)-1)/2
π = pi()

print φ chr(13) ϕ