Author Topic: BaCon Embedded Scripting  (Read 8522 times)

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
BaCon Embedded Scripting
« on: January 01, 2013, 03:55:49 PM »
This is an example of embedding ScriptBasic within a BaCon application. (< 49 KB console mode interpreter)

BaCon Project Site

ScriptBasic Project Site

bi.bac
Code: [Select]
' BaCon Command Line Interpreter

PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h
PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram

cmdln$ = ARGUMENT$
SPLIT cmdln$ BY " " TO opts$ SIZE cnt

pProgram = scriba_new(malloc,free)
ok = scriba_LoadConfiguration(pProgram,"/etc/scriba/basic.conf")
ok = scriba_SetFileName(pProgram, opts$[1])
ok = scriba_LoadSourceProgram(pProgram)
ok = scriba_Run(pProgram,opts$[2])
scriba_destroy(pProgram)

E01.sb
Code: [Select]
cmd = COMMAND()

PRINT "ARG = ",cmd,"\n"

FOR x = 1 TO 10
PRINT x,"\n"
NEXT

jrs@laptop:~/BaCon/B29$ ./bacon bi.bac
Converting 'bi.bac'... done.
Compiling 'bi.bac'... done.
Program 'bi' ready.
jrs@laptop:~/BaCon/B29$ ./bi E01.sb JRS
ARG = JRS
1
2
3
4
5
6
7
8
9
10
jrs@laptop:~/BaCon/B29$

« Last Edit: January 01, 2013, 04:48:23 PM by JRS »

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: BaCon Embedded Scripting
« Reply #1 on: January 01, 2013, 04:01:00 PM »
This is an API demo created by Charles Pegge with assistance from Armando I. Rivera (AIR) that was used in a SB embedding code challenge from awhile back. I converted it to run under BaCon.

sbapi.bac
Code: [Select]
' ScriptBasic API Demo

PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram
DECLARE ReturnData TYPE SbData
DECLARE ArgData[4] TYPE SbData

lVal = 11

' RUN SB SCRIPT
pProgram = scriba_new(malloc,free)
ok = scriba_LoadConfiguration(pProgram,"/etc/scriba/basic.conf")
ok = scriba_SetFileName(pProgram, "E03.sb")
ok = scriba_LoadSourceProgram(pProgram)
ok = scriba_Run(pProgram,"")

' ACCESSING GLOBAL DATA
vsn = scriba_LookupVariableByName(pProgram, "main::a")
ok = scriba_SetVariable(pProgram, vsn, 2, 500, 0, "", 0)

' CALLING SIMPLE SUBROUTINE
f1 = scriba_LookupFunctionByName(pProgram, "main::dprint")
ok = scriba_Call(pProgram, f1)

' CALLING FUNCTION, RETURNING DATA AND GETTING ALTERED PARAMS
f2 = scriba_LookupFunctionByName(pProgram, "main::eprint")

' SETUP ARGUMENTS (these can be used for both input and output)

FOR cArgs = 0 TO 3
  ArgData[cArgs].type = SBT_LONG
  ArgData[cArgs].size = 0
  ArgData[cArgs].v.l = lVal+cArgs
NEXT cArgs

ok = scriba_CallArgEx(pProgram, f2, &ReturnData, cArgs, ArgData)
PRINT "Return type:", ReturnData.type
PRINT "Value: ";

' READ RETURNED VALUE
SELECT ReturnData.type
  CASE SBT_UNDEF
    PRINT "Undefined"
  CASE SBT_DOUBLE
    PRINT ReturnData.v.d
  CASE SBT_LONG
    PRINT ReturnData.v.l
  CASE SBT_STRING;
  CASE SBT_ZCHAR
    r$ = ReturnData.v.s
    PRINT r$
END SELECT

scriba_destroy(pProgram)


E03.sb
Code: [Select]
' ----------------
' GLOBAL VARIABLES
' ================
'
a=42
b=sqr(2)
s="hello world!"

q=dprint()
q=eprint(1,2,3,4)

' ---------
' FUNCTIONS
' =========

function dprint
  sp="  "
  cr="\n"
  tab=chr$(9)
  print "Dprint Globals: " & s & sp & a & sp & b & cr
  dprint=1
end function

function eprint(a,b,c,d)
  sp="  "
  cr="\n"
  tab=chr$(9)
  print "Eprint Args: " & a & sp & b & sp & c & sp & d & cr
  ans=a+b+c+d
  eprint="Sum = " & ans
end function

jrs@laptop:~/BaCon/B29$ ./bacon sbapi.bac
Converting 'sbapi.bac'... done.
Compiling 'sbapi.bac'... done.
Program 'sbapi' ready.
jrs@laptop:~/BaCon/B29$ ./sbapi
Dprint Globals: hello world!  42  1.414214
Eprint Args: 1  2  3  4
Dprint Globals: hello world!  500  1.414214
Eprint Args: 11  12  13  14
Return type:3
Value: Sum = 50
jrs@laptop:~/BaCon/B29$

You can also load a script and not run it. This comes in handy if you have a library of script functions/subs and want to call them from your BaCon program.

ok = scriba_NoRun(pProgram)

Notice the change in results when the initial global variables aren't set.

jrs@laptop:~/BaCon/B29$ ./sbapi
Dprint Globals:   500 
Eprint Args: 11  12  13  14
Return type:3
Value: Sum = 50
jrs@laptop:~/BaCon/B29$

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: BaCon Embedded Scripting
« Reply #2 on: January 01, 2013, 04:02:04 PM »
Here is a Hello World example where the script is a BaCon string.

Code: [Select]
PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram

pgm$ = CONCAT$("PRINT ",CHR$(34),"Hello World\\n",CHR$(34),CHR$(10))

pProgram = scriba_new(malloc,free)
ok = scriba_SetFileName(pProgram, "dummy")
ok = scriba_LoadProgramString(pProgram, pgm$, LEN(pgm$))
ok = scriba_Run(pProgram,"")
scriba_destroy(pProgram)

jrs@laptop:~/BaCon/B29$ ./bacon pgmstr.bac
Converting 'pgmstr.bac'... done.
Compiling 'pgmstr.bac'... done.
Program 'pgmstr' ready.
jrs@laptop:~/BaCon/B29$ ./pgmstr
Hello World
jrs@laptop:~/BaCon/B29$

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: BaCon Embedded Scripting
« Reply #3 on: January 01, 2013, 04:03:01 PM »
This example is using the binary compiled form of the script. This loads and runs the scripts faster as there is no prep work to do. It also adds a level of security to your scripts as they are stored on disk in a binary format.

Skipped Steps
  • scriba_ReadSource()
  • scriba_DoLexicalAnalysis()
  • scriba_DoSyntaxAnalysis()
  • scriba_BuildCode()



Code: [Select]
PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram

cmdln$ = ARGUMENT$
SPLIT cmdln$ BY " " TO opts$ SIZE cnt

pProgram = scriba_new(malloc,free)
ok = scriba_LoadConfiguration(pProgram,"/etc/scriba/basic.conf")
ok = scriba_SetFileName(pProgram, opts$[1])
ok = scriba_LoadBinaryProgram(pProgram)
ok = scriba_Run(pProgram,opts$[2])
scriba_destroy(pProgram)

jrs@laptop:~/BaCon/B29$ scriba -o E01.bin E01.bas
jrs@laptop:~/BaCon/B29$ ./bacon bbi.bac
Converting 'bbi.bac'... done.
Compiling 'bbi.bac'... done.
Program 'bbi' ready.
jrs@laptop:~/BaCon/B29$ ./bbi E01.bin secrete_password
ARG = secrete_password
1
2
3
4
5
6
7
8
9
10
jrs@laptop:~/BaCon/B29$

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: BaCon Embedded Scripting
« Reply #4 on: January 01, 2013, 04:03:44 PM »
The example Charles & AIR demonstrated of calling a function was in it's most advanced form.  (passing arguments by reference, returning a value) If all your interested in is calling a SUB and passing arguments by value, ScriptBasic has a easier API call to work with.

Code: [Select]
PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram

pProgram = scriba_new(malloc,free)
ok = scriba_SetFileName(pProgram, "E04.sb")
ok = scriba_LoadSourceProgram(pProgram)
ok = scriba_NoRun(pProgram)

s1 = scriba_LookupFunctionByName(pProgram, "main::prtargs")
ok = scriba_CallArg(pProgram, s1, "i s r", 2012, "BaCon", 1.29)

scriba_destroy(pProgram)

Code: [Select]
SUB prtargs(arg1, arg2, arg3)
PRINT arg1,"\n"
PRINT arg2,"\n"
PRINT FORMAT("%g",arg3),"\n"
END SUB
jrs@laptop:~/BaCon/B29$ ./bacon callarg.bac
Converting 'callarg.bac'... done.
Compiling 'callarg.bac'... done.
Program 'callarg' ready.
jrs@laptop:~/BaCon/B29$ ./callarg
2012
BaCon
1.29
jrs@laptop:~/BaCon/B29$

Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: BaCon Embedded Scripting
« Reply #5 on: January 01, 2013, 04:04:25 PM »
I thought I would give my new remote (socket) SB debugger a try with an embedded BaCon application.

Code: [Select]
PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h basext.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram
DECLARE *debuggers[1] TYPE char

debuggers[0] = "sdbg"
debuggers[1] = NULL

pProgram = scriba_new(malloc,free)
ok = scriba_LoadConfiguration(pProgram,"/etc/scriba/basic.conf")
ok = scriba_LoadInternalPreprocessor(pProgram, debuggers)
ok = scriba_SetFileName(pProgram, "E04.sb")
ok = scriba_LoadSourceProgram(pProgram)
ok = scriba_Run(pProgram,"")

s1 = scriba_LookupFunctionByName(pProgram, "main::prtargs")
ok = scriba_CallArg(pProgram, s1, "i s r", 2012, "BaCon", 1.29)

scriba_destroy(pProgram)

Console 1
jrs@laptop:~/BaCon/B29$ ./bacon debugit.bac
Converting 'debugit.bac'... done.
Compiling 'debugit.bac'... done.
Program 'debugit' ready.
jrs@laptop:~/BaCon/B29$ ./debugit
2012
BaCon
1.29
jrs@laptop:~/BaCon/B29$

Console 2
jrs@laptop:~$ cd sb/test
jrs@laptop:~/sb/test$ scriba dbgcon.sb
Application: ScriptBasic Remote Debugger
Version: 1.0
Source-File-Count: 1
Source-File: E04.sb
Current-Line: 1
-> l -
 [0001] SUB prtargs(arg1, arg2, arg3)
 [0002] PRINT arg1,"\n"
 [0003] PRINT arg2,"\n"
 [0004] PRINT FORMAT("%g",arg3),"\n"
 [0005] END SUB
Current-Line: 1
-> s
Current-Line: 2
-> s
Current-Line: 3
-> s
Current-Line: 4
-> s
Current-Line: 5
-> q
Debug session closed.
jrs@laptop:~/sb/test$


Offline John

  • Forum Support / SB Dev
  • Posts: 3510
    • ScriptBasic Open Source Project
Re: BaCon Embedded Scripting
« Reply #6 on: January 01, 2013, 04:05:14 PM »
Here is an example of using the ScriptBasic SQLite3 extension module and passing the resulting record set back to BaCon.

Code: [Select]
PRAGMA OPTIONS -I/home/jrs/sb/source
PRAGMA LDFLAGS scriba pthread
PRAGMA INCLUDE scriba.h getopt.h

PROTO scriba_destroy

DECLARE pProgram TYPE pSbProgram
DECLARE pVariable TYPE pSbData

pProgram = scriba_new(malloc,free)
ok = scriba_LoadConfiguration(pProgram,"/etc/scriba/basic.conf")
ok = scriba_SetFileName(pProgram, "E05.sb")
ok = scriba_LoadSourceProgram(pProgram)
ok = scriba_Run(pProgram,"")

vsn = scriba_LookupVariableByName(pProgram, "main::dbstr")
ok = scriba_GetVariable(pProgram, vsn, &pVariable)

dbstr$ = pVariable[0].v.s
SPLIT dbstr$ BY "|" TO row$ SIZE cnt

FOR x = 0 TO cnt-1
PRINT row$[x]
NEXT x

jrs@laptop:~/BaCon/B29$ ./bacon sqlext.bac
Converting 'sqlext.bac'... done.
Compiling 'sqlext.bac'... done.
Program 'sqlext' ready.
jrs@laptop:~/BaCon/B29$ ./sqlext
123-hello
234-cruel
345-world

jrs@laptop:~/BaCon/B29$

E05.sb
Code: [Select]
IMPORT sqlite.bas

db = sqlite::open("testsql")

sqlite::execute(db,"CREATE TABLE demo (someval integer, sometxt text);")
sqlite::execute(db,"INSERT INTO demo VALUES (123,'hello');")
sqlite::execute(db, "INSERT INTO demo VALUES (234, 'cruel');")
sqlite::execute(db, "INSERT INTO demo VALUES (345, 'world');")

stmt = sqlite::query(db,"SELECT * FROM demo")

WHILE (sqlite::row(stmt) = sqlite::SQLITE3_ROW)
  IF sqlite::fetchhash(stmt,column) THEN
    dbstr &= column{"someval"} & "-" & column{"sometxt"} & "|"
  END IF
WEND

sqlite::close(db)