Oxygen Basic
Information => Open Forum => Topic started by: Frankolinox on May 11, 2012, 12:11:42 AM
-
hello charles, hello oxygenbasic friends.
I have more a technology question about my "funbasic" interpreter project and I am looking for a way for bundling a textfile (*.bas) into an exe file. do you think it's possible to use assembler code parts from oxygen to built an exe file for an usual basic interpreter (built with powerbasic) ? I think it's not very intelligent, because the assembler code will create an pe file and doesn't concern (or have access) to the textfile of an interpreter at all?
any help or link or answer would be good.
you did a great job here, charles, thanks for that great oxygenbasic tool :)
best regards, nice day to the north, frank
-
I will cask you why in PowerBasic, ok i can understand that you maybe used to PowerBasic like me
to Ebasic but i think that is Oxygen Basic powerful enough for this job.
-
I have no experience of bundling, Frank. Eros is familiar with the technology. For Oxygen there is one facility we need for integrated interpreters: the ability to embed files within the binary and link them in. Perhaps something like:
sys p=embed "myprog.prg"
Charles
-
Frank if yo mean binder or how bind text(source) to exe this is not so problematic.
Just put your 'source' as binary buffer into memory ,then put your exe into another membuffer
then connect -> exeBuffer + srcBuffer and save to disk.
-
thanks aurel, charles for your fast replies. I will check what I can find by googling this topic and will show my feedback some days later. I wanted to use my "funbasic" interpreter with some assembler code lines to built (bundle) this exe. that was my idea. compression the file should be also possible. but my knowledge at this moment is very low I can say ;)
sys p=embed "myprog.prg"
charles, do you're meaning to embed my interpreter ("funbasic.dll" or texteditor "funbasicz_editor.exe" ) into oxygenbasic? (*smiling*)
eros hold this big secrets for bundling for himself I can undersand this one very good ;) no problem here about it. I will find another, my own way for it.
aurel: I am working with powerbasic, will continue working with this great software (in my eyes).
nice day, thanks, frank
-
By embedding, I mean including any form of data in an exe or dll, and making it accessible to the program. - a generic form of resources.
The data could be a script or byte code, and the program could be an interpreter.
Charles
-
Here is an example of embedding ScriptBasic in PowerBASIC. (courtesy of Charles)
Charles Pegge sent me his embedded code challenge examples for PowerBASIC, FreeBASIC and Oxygen.
Thanks for the all the hard work you put into this code challenge so far. I'm looking forward to Phase II where a set of ScriptBasic functions and subs are loaded and you call them from the host application along with accessing SB variables.
'-----
Embedding ScriptBasic in FreeBasic, PowerBasic, thinBasic, o2Basic
'----
While this is not exactly gift-wrapped, it shows how ScripBasic might be embedded in applications using several kinds of BASIC running under MS Windows.
Two points to note:
First, all the ScriptBasic calls use the stdcall convention where parameters are passed onto the stack right to left, and the callee procedure cleans the stack before returning control to the caller. But the memory callbacks that SB will make to the application must be cdecll where the stack cleanup is done by the caller instead.
Second, the console must be up and running before SB is loaded, if SB requires access to it. This means that for GUI applications that do not startup with a console, ScriptBasic must be late loaded and late-bound to the application, then explicitly released at the end.
The zip below includes the various header files, source code, DLLs and executables and scripts used in this project.
Charles
PowerBASIC - PBembeds.bas
#COMPILE EXE
#DIM ALL
'---------------------
'José Roca Headers 110
'=====================
'
#INCLUDE ONCE "windows.inc"
#INCLUDE ONCE "oleauto.inc"
'--------------------
'Late Binding Headers
'====================
'
%PowerBasic=1
#INCLUDE ONCE "scribaLate.inc"
'------------------------------
'MEMORY CALLBACKS FOR LIBSCRIBA
'==============================
FUNCTION newmem CDECL (BYVAL le AS LONG) AS LONG
FUNCTION=SysAllocStringByteLen (BYVAL 0,BYVAL le)
END FUNCTION
SUB freemem CDECL (BYVAL p AS LONG)
SysFreeString BYVAL p
END SUB
'-------------------------
FUNCTION PBMAIN () AS LONG
'=========================
AllocConsole
' DIM consIn AS LONG,consOut AS LONG,consErr AS LONG
' ConsIn =GetStdHandle (%STD_INPUT_HANDLE)
' ConsOut=GetStdHandle (%STD_OUTPUT_HANDLE)
' ConsErr=GetStdHandle (%STD_ERROR_HANDLE)
'
' DIM bufout AS ASCIIZ*8000
' DIM buflen AS LONG
' DIM bufrit AS LONG
'
'
' BOOL WINAPI WriteConsole(
' __in HANDLE hConsoleOutput,
' __in const VOID *lpBuffer,
' __in DWORD nNumberOfCharsToWrite,
' __out LPDWORD lpNumberOfCharsWritten,
' __reserved LPVOID lpReserved
' );
SetConsoleTitle "PowerBasic (PbWin) ScriptBasic Embedding Test"
' bufout="Hello" : buflen=LEN(bufout)
' WriteConsole ConsOut,bufout,buflen,bufrit,0
'---------------------------
'LATE BINDING TO SCRIPTBASIC
'---------------------------
'SB must be loaded after the console is up and running
DIM sbl AS DWORD
DIM newSb AS DWORD, LoadConfiguration AS DWORD, SetFileName AS DWORD, LoadSourceProgram AS DWORD, RunSb AS DWORD, destroySb AS DWORD
sbl=LoadLibrary("libscriba.dll")
IF sbl=0 THEN MSGBOX "libscriba.dll not located" : EXIT FUNCTION
newSb = GetProcAddress(sbl,"scriba_new")
LoadConfiguration = GetProcAddress(sbl,"scriba_LoadConfiguration")
SetFileName = GetProcAddress(sbl,"scriba_SetFileName")
LoadSourceProgram = GetProcAddress(sbl,"scriba_LoadSourceProgram")
RunSb = GetProcAddress(sbl,"scriba_Run")
destroySb = GetProcAddress(sbl,"scriba_destroy")
DIM pProgram AS DWORD,iError AS DWORD
CALL DWORD newSb USING scriba_new (CODEPTR(newmem), CODEPTR(freemem) ) TO pProgram
'msgbox str$(pProgram)
CALL DWORD LoadConfiguration USING scriba_LoadConfiguration(pProgram,"c:\scriptbasic\bin\scriba.conf")
CALL DWORD SetFileName USING scriba_SetFileName(pProgram,"E02.bas")
CALL DWORD LoadSourceProgram USING scriba_LoadSourceProgram(pProgram)
CALL DWORD RunSb USING scriba_Run(pProgram,"Hello") TO iError
CALL DWORD destroySb USING scriba_destroy(pProgram)
FreeLibrary sbl
'messageBox 0,"ok: "+HEX$(iError)+" "+HEX$(pProgram),"PowerBasic",0
END FUNCTION 'PBMAIN
ScriptBasic - E02.bas
cmd = command()
print "ARG = ",cmd,"\n"
for x=1 to 10
print x,"\n"
next x
print "Enter: "
line input a
scribaLate.inc (http://files.allbasic.info/Oxygen/scribaLate.inc.txt) - For PowerBasic, thinBasic and Oxygen
(http://www.allbasic.info/mboard/index.php?action=dlattach;topic=776.0;attach=276;image)
embed_SB.zip (http://www.allbasic.info/mboard/index.php?action=dlattach;topic=776.0;attach=278)
-
Ah yes, a different kind of embedding..
We have Oxygen embedding SriptBasic and ScriptBasicEmbedding Oxygen. In the latter case ScriptBasic uses Oxygen to control a Window asynchronously in a thread. I am doing a few minor fixes. The code is in
projects/ScriptBasic
Charles
-
By embedding, I mean including any form of data in an exe or dll, and making it accessible to the program. - a generic form of resources.
The data could be a script or byte code, and the program could be an interpreter.
Charles...
Do you mean like standard executable resource and when you say :
'and the program could be an interpreter'
which one ? -> this program from resource or main program?
-
It puts the file content into the data section of the program, not into the resources section (which is mswindows specific)
The data can then be accessed as a pseudo-bstring.
Example
MyScript.txt
print "Hello world"
Oxygen Program embedding the script file:
bstring src
embedfile "MyScript.txt",b
'test
print b 'result: print "Hello World"
Charles
-
Never know for this function ???
embedfile
Or this is just example how can be done in future?
-
I'm testing a version of it right now, Aurel.
-
Aha i see... ;)
This will be really cool :)
-
thanks all for feedback and the "embedfile" command, if you have an working example it's possible to send it to here at the board, charles? I will try this example to embed to my funbasic project too.
here another (dummy) question:
it's general possible to convert an oxygen assembler part (here: "#FILE") for an interpreter (*.bas files) to produce an exe file (pe) ?
I don't believe thats working, but I have convert some parts to powerbasic and I am wondering if that's working (if I have translate/convert all other parts for it) ? ;)
a) what's the meaning of command "lcase" in oxygen (similar to lcase$) ? I cannot finde more in source part. A index searching tool for commands or functions could be very senseful for the future too :)
my experimental code part for "#File" (the beginning):
' it's possible to convert oxygen "#File" part to powerbasic ? does this horrible job does make sense ? :)
' experimental take out by frank brübach, 14.mai.2012
'------------------------------------------------------
#COMPILE EXE
#DIM ALL
GLOBAL ert,cpuw,pem,ccx,rbr,ct1,ct2,sr1,sr2,iq1,iq2,iq3,iq4 AS LONG
'global lbr=40,rbr=41,iq1=34,iq2=96,iq3=96,ct1=39,ct2=59,sr1=58,sr2=58
GLOBAL ers,wdg AS STRING
DECLARE FUNCTION SysAllocStringByteLen LIB "OLEAUT32.DLL" ALIAS "SysAllocStringByteLen" ( _
BYREF psz AS ASCIIZ _ ' __in LPCSTR psz
, BYVAL len AS DWORD _ ' __in unsigned int len
) AS DWORD ' BSTR
DECLARE FUNCTION mword(BYREF s AS STRING, BYREF i AS DWORD) AS STRING
'-----------------------------------------------------------
FUNCTION mword(BYREF s AS STRING, BYREF i AS DWORD) AS STRING
'===========================================================
'??? ' hardstuff
END FUNCTION
FUNCTION tword(BYREF s AS STRING, BYREF i AS LONG) AS STRING
'??? hardstuff
END FUNCTION
SUB regnames()
'??? hardstuff
END SUB
'------------------------------------
SUB ascii_to_float(BYVAL s AS STRING)
'====================================
END SUB
'------------------------------------------
FUNCTION wval(BYVAL w1 AS STRING) AS DOUBLE
'==========================================
'
IF ASC(w1)=0 THEN EXIT FUNCTION
'
! push "w1"
! call ascii_to_float 'in o2runt.bas
! fstp qword ptr function ; [function]
END FUNCTION
'---------------------------
SUB cpus(BYREF wr AS STRING)
'===========================
DIM a AS LONG
a=wval(wr)
IF a THEN
pem=a
IF a=64 THEN cpuw=8 ELSE cpuw=4
regnames() 'SET 32/64 BIT REG NAMES
END IF
END SUB
FUNCTION isx(BYVAL a AS DWORD) AS DWORD
'==================================
rbr=41
! mov al,a
! xor ecx,ecx
! inc ecx
! cmp al,44
! jz disx
! cmp al,rbr
! jz disx
! cmp al,93
! jz disx
! cmp al,125
! jz disx
! cmp al,sr1
! jz disx
! cmp al,sr2
! jz disx
! cmp al,13
! jbe disx
! cmp al,ct1
! jz disx
! cmp al,ct2
! jz disx
! jmp xisx
disx:
! mov function,ecx
xisx:
END FUNCTION
'----------------------------------
FUNCTION isq(BYVAL a AS LONG) AS LONG
'==================================
! mov al,a
! cmp al,iq1
! jz disq
! cmp al,iq2
! jz disq
! cmp al,iq3
! jz disq
! cmp al,iq4
! jz disq
! jmp xisq
disq:
! mov dword ptr function,1
xisq:
END FUNCTION
FUNCTION noquotes(BYREF wr AS STRING) AS STRING
'==============================================
'
DIM a AS LONG,b AS LONG,c AS LONG
a=ASC(wr) : b=1 : c=LEN(wr)
IF isq(a) THEN b+=1 : c-=2
'
FUNCTION=MID$(wr,b,c)
'
END FUNCTION
'---------------------------------------------------------
'--------------------------------------------------------------
FUNCTION instrword(BYREF s AS STRING, BYREF w AS STRING) AS LONG
'==============================================================
'
DIM d AS LONG,e AS LONG,f AS LONG
IF w="" THEN EXIT FUNCTION
d=1 : e=LEN(w)
DO
d=INSTR(d,s,w) : f=0
IF d=0 THEN EXIT DO 'NOT FOUND
IF d=1 THEN
f=1 'LEFT BOUNDARY
ELSE
IF ASC(s,d-1)<33 THEN f=1
END IF
IF (f=1)AND(ASC(s,d+e)<33) THEN EXIT DO
d+=e
LOOP
'
FUNCTION=d
'
END FUNCTION
FUNCTION dic(BYVAL s AS STRING, BYVAL wr AS STRING) AS LONG
'=========================================================
'
'LOOKUP KEYWORD AND RETURN NUMBER (ASSUMED HEXADECIMAL)
'
DIM a AS LONG
DIM p AS STRING PTR
p=STRPTR(s)
a=instrword(s,wr)
IF a THEN
a+=LEN(wr)
! mov ecx,p
! add ecx,a
! dec ecx
! call hexaval
! mov function,eax
END IF
'
END FUNCTION
SUB hexaval()
END SUB
'---------------------------- MAIN ------------
FUNCTION PBMAIN () AS LONG
'---------------------------- MAIN ------------
LOCAL md AS LONG
LOCAL pexn AS STRING
LOCAL cpuw AS LONG
LOCAL pef AS LONG
LOCAL ascn AS LONG '' ascn ascii of next word
LOCAL s AS STRING, w1 AS STRING
LOCAL i AS LONG, independent AS LONG, continue AS LONG ', exitap as long
'exitap = exit
independent = 0
'----------------------------------
lcases: '2328
'============
! push esi
! mov esi,[esp+8]
! mov edi,0
! cmp esi,0 'null string test
! jz lwrx1
! mov edi,[esi-4]
lwrx1:
! push edx
! push edi
! push 0
CALL SysAllocStringByteLen("",i)
! pop edx
! mov ecx,edi
! mov edi,eax
! push eax
! and edx,0 ;xff ;'supporting wide code
' converting idea but very hard stuff and some problem zones ...
'---------------------------------------------------------------------
'#FILE + #FILE + #FILE + #FILE + #FILE + #FILE + #FILE + #FILE +
'---------------------------------------------------------------------
'#define lcasesa 2328 'lcase
'#define ucasesa 2336 'ucase
'
IF md=35 THEN
IF isx(ascn)=0 THEN
pexn=noquotes(mword(s,i))
'------ what is LCASE ? --------------------------------------
' w1=lcase(RIGHT(pexn,3)) 'what is "lcase" ??? = lcase$ ???
'------ what is LCASE ? --------------------------------------
pef=dic(" dll 1, exe 2, ",w1)
IF pef=0 THEN
ert=5 : ers="#file requires name.exe or name.dll " : GOTO exitap
END IF
'
DO
IF isx(ascn) THEN EXIT DO
w1=tword(s,i)
IF w1="independent" THEN independent=1 : continue = 0'DO
cpus(w1)
IF cpuw=4 THEN ccx=0 ELSE ccx=2 'ms64
LOOP
END IF
GOTO mainloop
END IF
' converting idea but very hard stuff and some problem zones ...
'---------------------------------------------------------------------
'#FILE + #FILE + #FILE + #FILE + #FILE + #FILE + #FILE + #FILE +
'---------------------------------------------------------------------
'========================
mainloop: 'main line loop
'========================
'
'nl=1 : bg=j : skiplspace(s,i) : typa1=0
'
'=============================================
exitap: 'COMPILE TERMINATION AND ERROR HANDLING
'==============================================
' hardstuff
MSGBOX "some importants parts are mission, sorry", %MB_OK, "only an idea for #file convertion"
END FUNCTION
'-------------------------------------------------
SUB skiplspace (BYREF s AS STRING, BYREF i AS LONG)
'=================================================
DIM le AS LONG, nwd AS LONG
le=LEN(s)
! mov ecx,"s"
! mov ecx,ecx ;'deref
! mov edi,ecx
! mov esi,le
! mov edx,i
! mov edx,edx
! add ecx,edx
! dec ecx
rskipl:
! inc ecx
! cmp edx,esi ;' END OF STRING
! jle skbld
! mov al,0
! jmp xskipl
skbld:
! inc edx
' ! mov al,ecx-1
! cmp al,9 ;' TAB
! jz rskipl
! cmp al,13 ;' END OF LINE
! jbe xskipl
! cmp al,32 ;'OTHER WHITE SPACE
! jbe rskipl
xskipl:
CALL lascn
! sub ecx,edi
! mov eax,i
! mov eax,ecx ;'SAVE INDEX BYREF
! mov nwd,ecx
END SUB
SUB lascn()
LOCAL ascn AS STRING
'==========
! cmp al,65
! jb skuc
! cmp al,90
! ja skuc
! add al,32
skuc:
! mov ascn,al
END SUB
most of assember code in oxygen I can convert to powerbasic, that was very surprising for me.
new edit: but the idea to embed is more efficient I can suppose. it was only a test, what's possible to convert and what not. for creation of pe file there's a lot of more necessary I see.
best regards, frank
-
Hi Frank,
I am unable to give a quick answer, other than to say you can bind script to your script engine and compile it with Oxygen. And there you have your standalone EXE file. Not sure how you do this with PowerBasic.
ScriptBasic also has a system for binding script to script engine to make an EXE.
I will attempt a simple example later.
Charles
-
thanks charles, the embed a file idea I like very mucho :)
a) I have tested your new example: the embedfile for "scriptbasic" (project folder) doesn't work here correct. I can compile the scriptbasic example with oxygen but there's no running.
b) "#file": that was only an idea to cut some parts of oxygen (assembler code) from the "#file" part and wanted to include and convert to powerbasic (that was a very hard work to collect all files!) but was a good exercise too. mword/tword part I haven't translated all the functions are linked to another oxygen include files (haha *smile*) and so I can imagine it's better to convert all files or bind oxygen.dll for my "funbasic" project. but "PE" has to implement too, that's a very big job I can see but how does it work for powerbasic I haven't idea at this moment..
c) my thoughts about that topic today is that it's nearly impossible to create a "compile" file (I wanted to create from powerbasic side an exe file that's do the work for me to start the compiling job for my funbasic *.bas file. the idea I liked very much, but that's not working here ;)
thanks for feedback, I have still to learn much more about oxygenbasic and the source is very, very interesting stuff.
perhaps I will send you an example next days, what's possible here or if that's working for embedding my "funbasic.dll" and an example file (*.bas) to compile (exe bundle) . nice weekend, frank
-
Hi Frank,
PE file generation is quite a challenge. Most of the code for this can be found in o2hdrs.bas
I found the most difficult part was debugging, since there are no helpful error messages! If the system finds fault with the PE file, it spits it out with contempt!
Microsoft's official specification for the PE format can be obtained here:
http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx
The parser is a good starting point. I will continue work on script language code examples. I am all for experimenting with new languages.
Charles
-
The parser is a good starting point. I will continue work on script language code examples. I am all for experimenting with new languages.
Good to know that.. :)
-
hello charles, short question: do you are using "ELF" technique for making your executable / dll file creation ? If you agree to it with yes: Why do you are using "ELF"? ;) the whole examples I've found of pe file creation at official sites from msdn or vb is a hell to understand here at the moment. but I will continue to search a good solution for my purposes :)
best regards, frank
-
Hi Frank,
ELF is used in Linux and other Unix-based operating systems. MS Windows uses PE. Both of these system evolved from another format called COFF. They are both organised as a bunch of fixed length records and variable length records. They carry quite a lot of information, for mapping a program into memory, ready for execution.
So I will need to use ELF for Linux, and other forms of coding for systems like Android. Producing C-source code or LLVM for native compilers is also a feasible way of extending Oxygen's reach.
Charles