SET ... END SET statement

Purpose:

Akin to the DIM statement, SET gives you a convenient means of declaring and loading array variables in one easy statement. SET supports local and global contexts. If SET is used inside a SUB or FUNCTION then the variable and its data, implicity, are local in scope.

Syntax:

SET VArray[] AS data type
 Comma,
 delimited,
 values,
 list
END SET

Parameters:

  • Data type: Identifier
    VArray Name of an array into which to load the values from the comma delimited list. The size of the array is automatically calculated when the SET statement is used.
  • data type Specifies the data type of the array and, as well, the values in the comma delimited list.

Remarks:

👉 The OPTION BASE statement does not work with the arrays generated with the SET statement.

When a partial initalization is being done, braces { } are used to delimit the parts of the SET to be initialized. For example,

TYPE foo
 A AS INTEGER
 B AS INTEGER
 C AS BYTE
END TYPE

SET MyFoo[] AS foo
 {12,13},
 {19,20}
END SET

would initialize as:

MyFoo[0].A = 12
MyFoo[0].B = 13
MyFoo[0].C =  0 👉 not initialized
MyFoo[1].A = 19
MyFoo[1].B = 20
MyFoo[1].C =  0 👉 not initialized

Here are some examples using SET.

Instead of coding this:

DIM A[6] AS DOUBLE

A[0] = 1.1
A[1] = 5.5
A[2] = 9.9
A[3] = 3.3
A[4] = 10.1
A[5] = 4.41

Do this instead! The size of the array is automatically calculated.

SET A[] AS DOUBLE
 1.1, 5.5, 9.9,
 3.3, 10.1, 4.4
END SET

Here's another example using strings

SET B$[3]
 "apples",
 "oranges",
 "bananas"
END SET

which is the same as

DIM B$[3]

 B$[0] = "apples"
 B$[1] = "oranges"
 B$[2] = "bananas"

The example below demonstrates SET in a subroutine.

TEST()

SUB TEST ()

  SET b$[10] AS CHAR PTR
    "one" ,  "two",
    "three", "four",
    "five",  "six",
    "seven", "eight"
  END SET

  PRINT b$[0]
  PRINT b$[1]
  PRINT b$[2]
  PRINT b$[3]
  PRINT b$[4]
  PRINT b$[5]
  PRINT b$[6]
  PRINT b$[7]

END SUB

Result:

one
two
three
four
five
six
seven
eight

Here is an example of SET with comments.

SET C[16] AS COLORREF
 16777215, 'white
 16776960, 'cyan
 16711935, 'pink
 16711680, 'blue
 65535,    'yellow
 65280,    'green
 255,      'red
 12632256, 'lightgray
 8421504,  'darkgray
 8421376,  'darkcyan
 8388736,  'darkpink
 8388608,  'darkblue
 32896,    'brown
 32768,    'darkgreen
 128,      'darkred
 0        'black
END SET

Here is an example using pointers.

SET errmsg[] AS CHAR PTR
 "Overflow",
 "Division by zero",
 "etc",
 "etc"
END SET

DIM i

FOR i = 0 TO 3
 ? "Error ";i;" ";errmsg$[i]
NEXT

PAUSE

Result:

Error  0 Overflow
Error  1 Division by zero
Error  2 etc
Error  3 etc

Here is an example using BCX functions and operators.

SET iX[] AS INTEGER
  ASC("A"),
  ASC("c"),
  23 AND 14,
  1 OR 3,
  5 XOR 6,
  BNOT 8
END SET

DIM i%

FOR i% = 0 TO 5
  PRINT iX[i]
NEXT i%
PAUSE

Result:

65
99
6
3
3
-9

Here is how to use SET to read mixed type data which needs to be modified at run-time.

TYPE GameData
  s$
  x1, y1, z1, x2, y2, z2
  u
  v
END TYPE

SET GD[] AS GameData
  "outside a house",
  1,0,0,1,0,0,
  0,
  0,
  "by a window",
  0,1,0,0,0,0,
  1,
  0
END SET

PRINT GD[0].s$
PRINT GD[0].x1
GD[0].s$ = "Inside the door"
GD[0].x1 = 345
PRINT GD[0].s$
PRINT GD[0].x1
PRINT GD[1].s$
PRINT GD[1].x1
PAUSE

Result:

outside a house
 1
Inside the door
 345
by a window
 0

The example below uses SET in functions.

PRINT Month$(2)," has", DaysInMonth(2), " days, 29 on leap years."

FUNCTION DaysInMonth (MonthNumber)

  SET nDays[] AS LONG
    31,28,31,30,
    31,30,31,31,
    30,31,30,31
  END SET

  IF MonthNumber>0 AND MonthNumber<13 THEN
    FUNCTION = nDays [MonthNumber-1]
  ELSE
    FUNCTION = 0
  END IF

END FUNCTION

FUNCTION Month$  (MonthNumber)

  SET _months[] AS PSTR
    "January", "February", "March", "April"
    "May", "June", "July", "August",
    "September", "October", "November", "December"
  END SET

  IF MonthNumber>0 AND MonthNumber<13 THEN
    FUNCTION = _months$ [MonthNumber-1]
  ELSE
    FUNCTION = 0
  END IF

END FUNCTION

Result:

February has 28 days, 29 on leap years.

Although SET data within a SUB, implicitly, is local, the example below shows that it can be accessed from outside the SUB.

CALL TEST_LOCAL_SCOPE

SUB TEST_LOCAL_SCOPE
 LOCAL  UpperLimit
 SET Buff[] AS CHAR PTR
  "A",
  "D",
  "C",
  "B",
  "F",
  "H",
  "E",
  "G"
 END SET

 UpperLimit = UBOUND(Buff) + 1

 QSORT DYNAMIC Buff$, 4
 CALL PrintTheBuff(Buff$, UpperLimit)

 QSORT DYNAMIC Buff$, UpperLimit
 CALL PrintTheBuff(Buff$, UpperLimit)

END SUB

SUB PrintTheBuff (A AS STRARRAY, UpLim)
 DIM Aye
 WHILE Aye < UpLim
  IF LEN( A[Aye] ) > 0 THEN PRINT A$[Aye] ' IF A$ [Aye] > "" THEN ... will not work. 
  INCR Aye
 WEND
 ?
END SUB

Result:

A
B
C
D
F
H
E
G

A
B
C
D
E
F
G
H

BCX Console Sample Programs using the SET function.

SHAREDSET ... END SET statement

SHAREDSET can be used instead of SET. When SHAREDSET is used, the C code generated does not have the static storage class qualifier that is generated with SET. This difference comes into play when multiple files are being compiled to object files and then linked together. All the object files can see the SHAREDSET, while SET can only be seen in the object in which it is coded.

Syntax:

SHAREDSET VArray[] AS data type
 Comma,
 delimited,
 values,
 list
END SET

Parameters:

  • Data type: Identifier
    VArray Name of an array into which to load the values from the comma delimited list. The size of the array is automatically calculated when SHAREDSET statement is used.
  • data type Specifies the data type of the array and, as well, the values in the comma delimited list.

Example:

Copy the following three files to a directory and run the batch file to translate and compile.

File 1. Build.bat

call povars32.bat
bc Level1
bc SharedSet
pocc -W1 -Ot -Gd -Ze -Zx -Tx86-coff Level1.c
pocc -W1 -Ot -Gd -Ze -Zx -Tx86-coff SharedSet.c
polink -release -machine:ix86 -subsystem:console SharedSet.obj Level1.obj
ECHO Finished!

File 2. SharedSet.bas

$PRJUSE Level1.use
#INCLUDE "Level1.h"

SHAREDSET B$[3]
 "apples",
 "oranges",
 "bananas"
END SET

CALL LEVEL1

File 3. Level1.bas

$PRJ
$NOMAIN

SUB LEVEL1
 EXTERN B$[]
 PRINT B$[2]
END SUB

Result:

bananas

Remarks:

Using SHAREDSET in the preceding example,

generates this C code for the array

CHAR   B[3][BCXSTRSIZE]=
{
"apples",
"oranges",
"bananas"
};

When SET is used instead of SHAREDSET, this C code is generated for the array.

STATIC CHAR   B[3][BCXSTRSIZE]=
{
"apples",
"oranges",
"bananas"
};

and the compiler errors out with this message.

SharedSet.c(206): warning #2135: Static 'B' is not referenced.
POLINK: error: Unresolved external symbol '_B' - referenced from 'Level1.obj'.
POLINK: fatal error: 1 unresolved external(s).