FUNCTION and SUB Procedures

The main difference between a FUNCTION and a SUB is that a FUNCTION returns a value to the FUNCTION call expression.

FUNCTION...END FUNCTION procedure


Syntax:
 
 FUNCTION TheName([Parameters][AS data type])[,AS data type]
 DIM ReturnValue
     [Statements]
 FUNCTION = ReturnValue
 END FUNCTION

 Parameters:

  • TheName This is the name of the function. The value returned by the function can be indicated by using a data type indicator symbol at the end of TheName. For example, if the value returned is a string, the name of the function would be TheName$. If the function returned a double, its name would be TheName#.

    The data type of the value returned by the function also can be indicated by appending an AS data type phrase. For example, if the value returned is a string, the phrase would be AS STRING. If the function returned a double, the phrase would be AS DOUBLE.

  • ([Parameters][AS data type]) is zero or more comma separated variables used to pass values to the function. The data type of each parameter must be indicated. BCX uses this information to construct prototypes for the functions so the data type must be explicit for any variables except integers. For example, if a string is being passed, Parameters$ or Parameters AS CHAR would be used. If a DOUBLE is being passed, Parameters# or Parameters AS DOUBLE would be used.

    By default, string variables are passed by reference, while numeric variables are passed by value. To pass numeric values by reference instead of by value, see the BYREF qualifier.

  • The FUNCTION = ReturnValue statement causes an immediate exit from the function returning to the function caller the value contained in ReturnValue.

    While other BASIC dialects use TheName of the FUNCTION as the variable to return the value created by the function, BCX can use any user defined variable name as long as the variable is the correct data type.

    If an empty string is to be returned explicitly, use either

     
     FUNCTION = ""
    
    

    or

     
     RAW temp$
     temp$ = ""
     FUNCTION = temp$
    
    

    or else use

     
     FUNCTION = NUL$
    
    
  • ReturnValue is the return value of the function. Like all variables ReturnValue must be dimensioned before use. This can be done within the function or externally as a GLOBAL.

Example:

 
 DIM A!
 DIM X!
 DIM Y!

 X! = 2.2
 Y! = 3.1

 A! = Myfunc!(X!, Y!)
 PRINT A!

 FUNCTION Myfunc!(M!, P!)
  FUNCTION = (M! * P!)
 END FUNCTION

Remarks:

Note Well ! Do not modify a literal value or string used as an argument in the FUNCTION calling statement. For example, the attempt to modify "literal" in,

 
 DIM str1$

 str1$ = FOO$("literal")
 PRINT str1$

 FUNCTION FOO$(a$)
  a$ = "k"
  FUNCTION = a$
 END FUNCTION

will cause a crash when the program is run.

OVERLOADED or OPTIONAL FUNCTION procedures are NOT allowed in a user defined type structure.

BCX has support for functions in single line declaration/assignments, for example,

 
 DIM RAW RetVal = foo(x, y, z) AS INTEGER

BCX allows static SUB/FUNCTION to be coded as:

 
 PRIVATE FUNCTION MyFunction() AS INTEGER
 
 PRIVATE SUB MySub()

User defined string functions that rely on other string functions usually need to use an intermediate string.

Example:

 
 DIM A$

 A$ = Blurb$(65, 66, 67)
 PRINT A$

 FUNCTION Blurb$(A, B, C)
  DIM Z$
  Z$ = CHR$(A) & CHR$(B) & CHR$(C)
  FUNCTION = Z$
 END FUNCTION

FUNCTION declarations emit a TYPE that may be reused.

 
 DIM FUNCTION Foo$(a$)
 Any further declarations can be written as:
 DIM MyFunctionPointer AS Foo_TYPE

The following is an example which uses the emitted FUNCTION TYPE declaration as a member of a user defined type.

 
 DIM FUNCTION Foo$(a$)
  
 TYPE MyType                                 
   DYNAMIC A$[]
   DYNAMIC FN[] AS Foo_TYPE
   B AS INTEGER
 END TYPE
  
 DIM mt AS MyType
  
 REDIM mt.A$[2]
 REDIM mt.FN[3]
  
 mt.A$[0] = "Hello " 
 mt.A$[1] = "World"
 mt.FN[0] = LCASE$
 mt.FN[1] = MCASE$
 mt.FN[2] = UCASE$
 
 PRINT mt.FN$[0](mt.A$[0]), mt.FN$[0](mt.A$[1])
 PRINT mt.FN$[1](mt.A$[0]), mt.FN$[1](mt.A$[1])
 PRINT mt.FN$[2](mt.A$[0]), mt.FN$[2](mt.A$[1])

CALLBACK FUNCTION...END FUNCTION procedure

OVERLOADED or OPTIONAL FUNCTION procedures are NOT allowed in a User Defined TYPE structure.


Syntax 1:
 
 CALLBACK FUNCTION CBFuncName()
     [Statements]
 END FUNCTION

 Parameters:

  • The following C code is emitted by BCX from the above syntax
     
    
     LRESULT CALLBACK CBFuncName(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
     {
      [Statements];
    
      return DefWindowProc(hWnd, Msg, wParam, lParam);
    
    
  • CALLBACK FUNCTION syntax does not use any function parameters because BCX automatically emits the following :
    
     (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    
    
  • When using the automatically emitted function parameters hWnd, Msg, wParam, and lParam, it is important to remember that they must be written as case sensitive.
  • CALLBACK FUNCTION does not require a FUNCTION = ReturnValue statement because BCX automatically emits the following function return statement:
     
     return DefWindowProc,(hWnd,Msg,wParam,lParam);
    
    

Example 1 : This example of Syntax 1 shows how to set up two forms subclassing the second with a CALLBACK. The trick involves:


 GUI "Two_Forms_Demo"
  
 GLOBAL Form1 AS HWND
 GLOBAL Form2 AS HWND
  
 GLOBAL Form1_Button1 AS HWND
 GLOBAL Form2_Button1 AS HWND
  
 GLOBAL lpForm2_Proc AS WNDPROC
  
 CONST  IDC_FORM1_BUTTON1 = 201
 CONST  IDC_FORM2_BUTTON1 = 202
  
 SUB FormLoad
  
   Form1 = BCX_FORM("Form 1", 100, 100, 160, 100)
   Form1_Button1 = BCX_BUTTON("Show", Form1, IDC_FORM1_BUTTON1, 64, 40, 40, 14)
  
   Form2 = BCX_FORM("Form 2", 270, 110, 200, 140)
   Form2_Button1 = BCX_BUTTON("Hide",Form2, IDC_FORM2_BUTTON1,  80, 70, 40, 14)
  
   lpForm2_Proc = SubclassWindow(Form2, Form2_Proc)
  
   SHOW   (Form1)
 END SUB
  
 BEGIN EVENTS
   SELECT CASE CBMSG
  
     '**********************
     CASE WM_COMMAND
     '**********************
     IF CBCTL = IDC_FORM1_BUTTON1 THEN
       SHOW (Form2)
     END IF
     EXIT FUNCTION
  
     '**********************
     CASE WM_CLOSE
     '**********************
     DIM RAW id
     id = MSGBOX("Are you sure?","Close Window!",MB_YESNO OR MB_ICONQUESTION)
     IF id THEN PostQuitMessage(0)
     EXIT FUNCTION
  
     '**********************
     CASE WM_DESTROY
     '**********************
     PostQuitMessage(0)
     EXIT FUNCTION
   END SELECT
 END EVENTS
  
  
 CALLBACK FUNCTION Form2_Proc()
   SELECT CASE CBMSG
     '**********************
     CASE WM_COMMAND
     '**********************
     IF CBCTL = IDC_FORM2_BUTTON1 THEN HIDE (CBHWND)
     EXIT FUNCTION
  
     '**********************
     CASE WM_CLOSE
     '**********************
     HIDE (CBHWND)   'Don't CLOSE it, HIDE it
     EXIT FUNCTION
  
     '**********************
     CASE WM_DESTROY  'Don't DESTROY it, HIDE it
     '**********************
     HIDE (CBHWND)
   END SELECT
 END FUNCTION


Syntax 2:
 
 FUNCTION CBFuncName(hWnd AS HWND, _
                       Msg AS UINT, _
                  wParam AS WPARAM, _
                  lParam AS LPARAM) _
               AS data type CALLBACK
  [Statements]
 FUNCTION = ReturnValue
 END FUNCTION

 Parameters:

  • Any parameter names can be used but the parameter data types are fixed by the CALLBACK Win32API define.
  • The FUNCTION = ReturnValue statement causes an immediate exit from the function, returning to the caller the value contained in ReturnValue.
  • data type Specifies the data type of the value returned by the function. The LRESULT data type would be used when the CallWindowProc, DefWindowProc, DefMDIChildProc or DefFrameProc function is used as a function return. In a CALLBACK function which returns TRUE or FALSE either a BOOL data type or an INT_PTR Dataype would be used.
  • ReturnValue The value returned by the function. This value must be the same data type as specified in the FUNCTION declaration. Most commonly a Win32API CallWindowProc, DefWindowProc, DefMDIChildProc or DefFrameProc function is used as a function return in a BCX CALLBACK function.
  • WARNING ! The DefDlgProc function or the DefWindowProc function must not be called by a dialog box callback procedure; doing so results in recursive execution.

Example 2:

In the sample below, each label control is subclassed and reflects the WM_CTLCOLORSTATIC message to the subclassed windows procedure. This demo of CALLBACK function Syntax 2 creates a form with a black background and two BCX_LABELS that have their foreground and background colors changed by the CALLBACK functions.


 GUI "test"
  
 GLOBAL Form1   AS CONTROL
 GLOBAL Label_1 AS CONTROL
 GLOBAL Label_2 AS CONTROL
  
 SUB FORMLOAD
   Form1 = BCX_FORM("test",67,42,160,130)
   Label_1 = BCX_LABEL("Label 1",Form1,100,5,10)
   Label_2 = BCX_LABEL("Label 2",Form1,101,5,50)
  
   BCX_SET_FORM_COLOR(Form1,RGB(0,0,0))
  
   SubClassLabel1()
   SubClassLabel2()
  
   CENTER(Form1)
   SHOW(Form1)
 END SUB
  
 BEGIN EVENTS
   IF CBMSG = WM_CTLCOLORSTATIC THEN
     FUNCTION = SendMessage((HWND)lParam, Msg, wParam, lParam)
   END IF
 END EVENTS
  
 SUB SubClassLabel1
   GLOBAL Original_Label_1_WndProc AS WNDPROC
   Original_Label_1_WndProc = SetWindowLong(Label_1,GWL_WNDPROC,Label_1_WndProc)
 END SUB
  
 SUB SubClassLabel2
   GLOBAL Original_Label_2_WndProc AS WNDPROC
   Original_Label_2_WndProc = SetWindowLong(Label_2,GWL_WNDPROC,Label_2_WndProc)
 END SUB
  
 FUNCTION Label_1_WndProc(hWnd AS HWND, _
                           Msg AS UINT, _
                      wParam AS WPARAM, _
                      lParam AS LPARAM) _
                    AS LRESULT CALLBACK
   IF CBMSG = WM_CTLCOLORSTATIC THEN
     FUNCTION = SetColor(RGB(0,225,0),RGB(0,0,0),wParam,lParam)
   END IF
   FUNCTION = CallWindowProc(Original_Label_1_WndProc,hWnd,Msg,wParam,lParam)
 END FUNCTION
  
 FUNCTION Label_2_WndProc(hWnd AS HWND, _
                           Msg AS UINT, _
                      wParam AS WPARAM, _
                      lParam AS LPARAM) _
                    AS LRESULT CALLBACK
   IF CBMSG = WM_CTLCOLORSTATIC THEN
     FUNCTION = SetColor(RGB(255,0,0),RGB(0,0,0),wParam,lParam)
   END IF
   FUNCTION = CallWindowProc(Original_Label_2_WndProc,hWnd,Msg,wParam,lParam)
 END FUNCTION
  
 FUNCTION SetColor(TxtColr, BkColr, wParam, lParam) AS LRESULT
   GLOBAL ReUsableBrush AS HBRUSH
   DeleteObject(ReUsableBrush)
   ReUsableBrush = CreateSolidBrush(BkColr)
   SetTextColor((HDC)wParam, TxtColr)
   SetBkColor((HDC)wParam, BkColr)
   FUNCTION =(LRESULT) ReUsableBrush
 END FUNCTION
 

If a return value is not required then the CALLBACK syntax can be expressed as for a SUB using VOID for the CALLBACK data type.


Syntax 3:
 
 FUNCTION CBFuncName(hWnd AS HWND, _
                       Msg AS UINT, _
                  wParam AS WPARAM, _
                  lParam AS LPARAM) _
                   AS VOID CALLBACK
   [Statements]
 END FUNCTION

 Parameters:

  • Any parameter names can be used but the parameter data types are fixed by the CALLBACK Win32API define.
  • VOID indicates that a return value is not expected to be made.

SUB ... END SUB procedure

OVERLOADED or OPTIONAL SUB procedures are NOT allowed in a User Defined TYPE structure.


Syntax 3:
 
 SUB SubName(Parameters)
  [Statements]
 END SUB

 Parameters:

  • SubName is the name of the subroutine. Do not use a data type with the SubName because an error will occur in translation. Subname does not need a data type because a SUB does not return a value.
  • ([Parameters][AS data type]) is zero(the use of Parameters is optional) or more comma separated variables used to pass values to the subroutine. The data type of each parameter must be indicated. BCX uses this information to construct prototypes for the subroutines so the data type must be explicit for any variables except integers. For example, if a string is being passed, Parameters$ or Parameters AS CHAR would be used. If a DOUBLE is being passed, Parameters# or Parameters AS DOUBLE would be used.

    By default, string variables are passed by reference, while numeric variables are passed by value. To pass numeric values by reference instead of by value, see the BYREF qualifier.

Note Well ! Do not modify a literal value or string used as an argument in the SUB calling statement. For example, the attempt to modify "literal" in,

 
 CALL FOO("literal")

 SUB FOO(a$)
  a$ = "k"
 END SUB

will cause a crash when the program is run.

CALL statement

Although subroutines can be invoked with or without the CALL keyword remember that if a SUB does not take arguments and parentheses are omitted, then CALL MUST be used. Following are the only valid methods of calling a SUB with no arguments:

CALL Foo()

or CALL Foo

or Foo()

Let's start with a small Example:

 
 CALL Greeting("Hello from the World of Programming!")

 Greeting("Hello from the World of Programming!")

 SUB Greeting(a$)
  PRINT a$
 END SUB

Values can be passed to subroutines. The data type(declarator) of the parameter passing the argument to the subroutine must be indicated. BCX uses this information to construct prototypes for the subroutines and functions so the data type must be explicit for anything except integers. For example, if a string is being passed SUB Passit(A$) would be used not SUB Passit(A). If a DOUBLE is being passed SUB Passit(A#) would be used.

 
 SetConsoleTitle("BCX Demonstration")
 
 COLOR 15, 1
 frame(15, 10, 65, 20)
 DIM a
 INPUT a
 COLOR 7, 0
 CLS
 
 SUB frame(x1, y1, x2, y2) ' while interesting, this is meant only as a
   DIM x                     ' sample SUB.  The run-time PANEL statement
   DIM y                     ' is much faster and more flexible
   FOR y = y1 TO y2
     FOR x = x1 TO x2
       LOCATE y, x, 0
       PRINT " ";
     NEXT
   NEXT
 END SUB

Note Well ! Do not modify a literal value or string used as an argument in the FUNCTION or SUB calling statement. For example, the attempt to modify "literal" in,

 
 CALL FOO("literal")

 SUB FOO(a$)
  a$ = "k"
 END SUB

will cause a crash when the program is run.

Recursive calls can be made from a subroutine. What this means is that the subroutine can be called from within itself. Here's an Example:


 DIM C$
 
 C$ = "1,2,3,4,5,666,777,88888,99999,101010101010101010"
 
 Parse(C$)
 
 SUB Parse(A$)
   LOCAL Sep
   LOCAL B$
   Sep = INSTR(A$ , ",")
   IF Sep > 0 THEN
     B$ = LEFT$(A$, Sep - 1)
     PRINT B$
     A$ = MID$(A$, Sep + 1, 256)
     Parse(A$)  ' --- Recursive Call ---
   ELSE
     PRINT A$
   END IF
 END SUB

Subroutines can be prematurely exited by using the EXIT SUB statement. If you want to use values created in a Subroutine outside of it, then GLOBAL variables must hold the values.

 
 JumpOut()

 PRINT a$

 SUB JumpOut()
 GLOBAL a$
 a$ = "JumpOut"
  IF a$ = "JumpOut" THEN
   EXIT SUB
  END IF
  PRINT "This line is not executed."
 END SUB

Arguments and Parameters

Arguments are passed to procedures through parameters.

Passing Arguments to FUNCTION and SUB Procedures

Example 1: This example demonstrates passing a one-dimensional integer array to a function.

 
 DIM A_RAY[10] AS INTEGER
 
 Foo(&A_RAY[0], 3)
 
 PRINT A_RAY[3]
 
 SUB Foo(BYVAL A[], Index AS INTEGER)
  A [Index] = 12345
 END SUB

Example 2: This example demonstrates filling a global two-dimensional array in a function.

 
 GLOBAL DYNAMIC A[10][10] AS INTEGER
 GLOBAL a AS INTEGER
 GLOBAL b AS INTEGER
 
 CALL FILL(A,10,10)
 
 FOR a = 0 TO 9
  FOR b = 0 TO 9
   ? A[a][b];
  NEXT
  ?
 NEXT
 
 ! getchar();
 
 SUB FILL(B AS INTEGER PTR PTR, Dim1 AS INTEGER, Dim2 AS INTEGER)
  'The data type descriptor for the B parameter,
  'in the line above, requires one "PTR"
  'for EACH DIMENSION of the passed array.
  RAW a1
  RAW b1
  Dim1--
  Dim2--
  FOR a1 = 0 TO Dim1
    FOR b1 = 0 TO Dim2
      B[a1][b1] = a1 + b1
    NEXT
  NEXT
 END SUB

Example 3: treats the multi-dimensioned array as a one-dimensioned array inside the sub, and does a little simple maths to calculate the position of elements.

 
 DIM i, j
 DIM mat[3][3]
 
 FOR i = 0 TO 2
  FOR j = 0 TO 2
   mat[i][j] = i * 10 + j
  NEXT
 NEXT
 
 PRINT "Initialized data to: "
 FOR i = 0 TO 2
  FOR j = 0 TO 2
   PRINT mat[i][j]
  NEXT
 NEXT
 
 TRY2(mat[0], 3, 3)
 
 KEYPRESS
 
 SUB TRY2(Mymat[], n1 , n2)
  DIM k, h
 
  PRINT "Using simple maths: "
  FOR k = 0 TO n1-1
    FOR h = 0 TO n2-1
      PRINT Mymat[k * n2 + h]
    NEXT
  NEXT
 END SUB

Example 4: stores the array in a TYPE variable, and passes the address of the TYPE to the function.

 
 DIM i, j
  
 TYPE MYARRAY
   a[3][3]
 END TYPE
  
 DIM mat AS MYARRAY
  
 FOR i = 0 TO 2
   FOR j = 0 TO 2
     mat.a[i][j] = i*10+j
   NEXT
 NEXT
  
 PRINT "Initialized data to: "
 FOR i = 0 TO 2
   FOR j = 0 TO 2
     PRINT mat.a[i][j]
   NEXT
 NEXT
  
 TRY1(mat, 3, 3)
 getchar()
  
 SUB TRY1(Mymat AS MYARRAY, n1, n2)
   DIM k, h
  
   PRINT "Using a TYPE to hold the array: "
   FOR k = 0 TO n1 - 1
     FOR h = 0 TO n2 - 1
       PRINT Mymat.a[k][h]
     NEXT
   NEXT
 END SUB

Example 5: Here is an easy way to pass mutidimensional static arrays by enclosing the array in a TYPE.


 TYPE fltarray2D
   CA![100, 2]
 END TYPE
   
 GLOBAL myfloat AS fltarray2D
   
 CALL foo(&myfloat)
 PRINT myfloat.CA![1, 1]
   
 SUB foo(Myfloat AS fltarray2D PTR)
   Myfloat->CA![1, 1] = 5.33
 END SUB

Example 6: Using a DYNAMIC array.


 GLOBAL DYNAMIC CA![100, 2]
   
 CALL foo(CA)
 PRINT CA[1, 1]
   
 SUB foo(Myfloat AS FLOAT PTR PTR)
  'The data type descriptor for the Myfloat parameter,
  'in the line above, requires one "PTR"
  'for EACH DIMENSION of the passed array.
  Myfloat[1, 1] = 5.33
 END SUB

Example 7: The following simple example shows how to pass DYNAMIC multi-dimensional numeric arrays to a procedure by reference

 
 OPTION BASE 1
 GLOBAL DYNAMIC A[2, 2, 2] AS FLOAT
 LOCAL I, J, K
  
 A[1, 1, 1] = 1
 A[1, 1, 2] = 2
 A[1, 2, 1] = 3
 A[1, 2, 2] = 4
 A[2, 1, 1] = 5
 A[2, 1, 2] = 6
 A[2, 2, 1] = 7
 A[2, 2, 2] = 8
  
 FOR I = 1 TO 2
   FOR J = 1 TO 2
     FOR K = 1 TO 2
       PRINT "[", I, ",", J, ",", K, "] = ", XXX!(A, I, J, K)
     NEXT K
   NEXT J
 NEXT I
 KEYPRESS
 END PROGRAM
 
 FUNCTION XXX!(B AS FLOAT PTR PTR PTR, i, j, k)
  'The data type descriptor for the B parameter,
  'in the line above, requires one "PTR"
  'for EACH DIMENSION of the passed array.
  FUNCTION = 3.14 * B[i, j, k]
 END FUNCTION
 

Example 8: The following example shows how to pass TYPE and UNION structures to to a procedure

 
 TYPE STA
  DIM A$
  DIM B AS INTEGER
 END TYPE

 TYPE STB
  DIM A AS INTEGER
  DIM B AS INTEGER
 END TYPE

 ' union of all the structures
 UNION STUNION
  Atype AS STA
  Btype AS STB
 END UNION

 'the actual structure that is going to be used
 TYPE STALL
  DIM ID AS INTEGER 'tells what structure in the union is going to be used
  DIM UN AS STUNION
 END TYPE

 DIM st AS STALL

 st.ID = 1
 st.UN.Atype.A$ = "How is this?"

 CALL ExeSTX(&st)

 st.ID = 2
 st.UN.Btype.A = 2

 CALL ExeSTX(&st)

 getchar();

 SUB ExeSTX(s AS STALL PTR)
  SELECT CASE s->ID
    CASE 1
    ? s->UN.Atype.A$
    CASE 2
    ? s->UN.Btype.A
  END SELECT
 END SUB

BCX is able to correctly translate a parameter formed from a call to a FUNCTION as in this example.


 $TYPEDEF char * (__cdecl *STF_TYPE)(char *)
 
 SET pfStringFunctions[] AS STF_TYPE
   do1,
   do2,
   do3,
   NULL
 END SET
 
 '---------word functions-----------------------------------------
 FUNCTION do1$(whatstring$)
   FUNCTION = REVERSE$(whatstring$)
 END FUNCTION
 
 FUNCTION do2$(whatstring$)
   FUNCTION = UCASE$(whatstring$)
 END FUNCTION
 
 FUNCTION do3$(whatstring$)
   FUNCTION = ENC$(whatstring$)
 END FUNCTION
 
 '------------sentence function--------------------------------------
 'Now I have a function that will loop through a string and do something
 'to each word:
 FUNCTION dotoeachword$(whatsentence$, dowhat AS STF_TYPE)
   DIM tmp$
   'for each word in sentence (etc.)
   tmp$ = dowhat$(whatsentence$)
   'next
   FUNCTION = tmp$
 END FUNCTION
 
 '----------main function----------------------------------------
 DIM sentence$,sentence1$,sentence2$,sentence3$
 sentence$ = "George went to town."
 sentence1$ = dotoeachword$(sentence$, do1)
 sentence2$ = dotoeachword$(sentence$, do2)
 sentence3$ = dotoeachword$(sentence$, do3)
 PRINT sentence1$
 PRINT sentence2$
 PRINT sentence3$

OPTIONAL Parameters in Functions and Subroutines

An OPTIONAL parameter used in a FUNCTION or SUB declaration is defined with a default value. This value is used if the OPTIONAL parameter is omitted in the calling function or subroutine procedure. If a value is specified in the OPTIONAL parameter in the calling procedure, then that value is used instead of the default.

OPTIONAL parameters are not permitted in exported DLL functions.

Many BCX functions and subroutines have optional parameters already built in. For example, all the BCX GUI functions have optional window style and extended window style parameters which provide a default that is replaced when an OPTIONAL value is specified.


 Syntax 1:
 
 FUNCTION MyFunc% OPTIONAL(Normalparam$, Optionalparam$ = "BCX")

 Syntax 2:
 
 FUNCTION MyFunc% OPTIONAL(Normalparam$, Optionalparam AS data type = Value)

In the function or subroutine call, OPTIONAL parameters can be omitted from the right side of the parameter list.

The 'value' assigned to OPTIONAL parameters must be a scalar value, that is a string literal or number, not a function or some other complex expression.

Example:


 Alert()
 Alert("     Hello BCX Lovers!       ")
 Alert("Announcing OPTIONAL ARGUMENTS", "Very Cool!", 64)
 
 SUB Alert OPTIONAL(_Message$ = "" , _Title$ = "", Style = 0)
   LOCAL Message$, Title$
   Message$ = _Message$ & ""
   Title$   = _Title$   & ""
   IF TRIM$(Message$) = "" THEN
     Message$ = "  Alert ... Alert ...Alert!  "
   END IF
   IF TRIM$(Title$)   = "" THEN
     Title$   = "Generic Default Title"
   END IF
   IF Style = 0 THEN Style = MB_OK
   MSGBOX Message$, Title$, Style
 END SUB

$FSSTATIC directive

The $FSSTATIC directive causes the BCX translator to place the storage class specifier 'static' before function and subroutine definitions in the output C code.

 
 $FSSTATIC
 SUB GoForward(iBrowser AS IWebBrowser2 PTR)

 END SUB

translates to


 static void GoForward(IWebBrowser2 *iBrowser)
 {
 }

and without $FSSTATIC, BCX translates

 
 SUB GoForward(iBrowser AS IWebBrowser2 PTR)

 END SUB

to

 

 void GoForward(IWebBrowser2 *iBrowser)
 {
 }