QTIPS - Local Language Sets
Reader's Clinic - Functions and Subroutines
Reader's Letters - Jim Owen
Playing with Scan Codes
Argument passing - Subroutines and Functions - Mike Pope
Reader's Clinic - Line Length > 256 Characters
QTIPS - String Space
QTIPS - String Space Format Errors
Reader's Forum - Numeric Precision in R/Basic - Hal Wyman
VERBatim - V126
Esc.To.Exit
Uncommon Knowledge - WC_WST_CHAR%
QTIPS - Using @Upper.Case and @Lower.Case with Foreign Languages
@ATTACK - @Lower.Case
@ATTACK - @Upper.Case
Sorting out Collation Sequences by Mike Pope
RTP Series - RTP27
QTIPS - Printing Large Variables from the Debugger
VERBatim - V87
File Variables
Argument passing - Subroutines and Functions - Mike Pope
RevTech Replies - Mike Pope (RevTech UK Ltd)
Symbol Table Structure
Argument passing - Subroutines and Functions - Mike Pope
@ATTACK - @Return.Value
RTP Series - RTP42
VERBatim - V65
Argument passing - Subroutines and Functions - Mike Pope
Utility Diskette # 4
RTP Series - RTP5
VERBatim - V22
Play it Again, Cam
Reader's Forum - Mark Hirst Revelation C Interface - Part 1
Reader's Forum - Numeric Precision in R/Basic - Hal Wyman
QTIPS - Use of Mouse
Reader's Forum The C Interface Part 2 - Mark Hirst (Senior Techie - ICS) Reader's Clinic
VERBatim - V85
A RevTechie Replies - And Miscellaneous Jottings - Mike Pope - Revelation Technologies (UK) Ltd
QTIPS - Inconsistent @Variable Behaviour
What's New (and un(der)documented!) In 2.12
What Happens At Logon
@ATTACK - @UserName
Reader's Clinic
RTP Series - RTP18
Redefining Keys
Reader's Clinic - Line Length > 256 Characters
VERBatim - V39
Securing TCL Access
@ATTACK - @Sentence
QTIPS - Command Line Options
QTIPS - TCL Disabled
Reader's Clinic - ReEnable TCL from Debugger
QTIPS - PERFORM Arguments and FMT Specifications
VERBatim - V86
@ATTACK - @Help.Level
@ATTACK - @Window.Level
Utility Diskette # 3 - Part II
VERBatim - V1
VERBatim - V2
Advanced Revelation Initialisation Sequence (Overview) by Mike Pope
Form.List.S
QTIPS - Aesthetically Improving RLIST Reports
QTIPS - Form Processor
QTIPS - Suppressing Initial Form Feed
QTIPS - Using RTP29 In Place of V6
QTIPS - Modifying EasyWriter To Display Field Descriptions
@ATTACK - @Modal
Reader's Clinic - Functions and Subroutines
Argument passing - Subroutines and Functions - Mike Pope
@ATTACK - @Reduction.Done
Utility Diskette # 3 - Part I
Utility Diskette # 3 - Part II
@ATTACK - @Macro.Words
Argument passing - Subroutines and Functions - Mike Pope
Descripter - Larry Coon
@ATTACK - @Attrbt.Ptr
@ATTACK - @Query.Table
REVMEDIA Revisited
Uncommon Knowledge - WC_Table_Exit_Mode%
QTIPS - New Catalyst Option
Version 3 Technical Highlights - Deleting Tables Programmatically
Version 3 Technical Highlights - Aliasing Tables Programmatically
Version 3 TCL Subroutines - Creating Tables
Version 3 TCL Subroutines - Deleting Tables
Version 3 TCL Subroutines - Aliasing Tables
Symbol Table Structure
Argument passing - Subroutines and Functions - Mike Pope
Caching in on the Frames Array - Mike Pope
QTIPS - Fast Dynamic Array Building
SecureUser
VERBatim - V25
@ATTACK - @Files.System
Advanced Revelation Initialisation Sequence (Overview) by Mike Pope
REVMEDIA Revisted

RevMedia FKB

DocumentV3I1A7
TitleArgument passing - Subroutines and Functions - Mike Pope
KeywordsARGUMENT
SUBROUTINE
FUNCTION
COMMON
VARIABLE
DESCRIPTER
ARRAY
DESCRIPTOR
TRANSFER
UNASSIGNED
TextJim Owens notes that "the C esque use of local vs global VARIABLES doesn't
apply to R[/]BASIC" True but misleading; there is in fact a notion of
local shared and global VARIABLES it's just that it doesn't work as it
does WITH C

For beginners look at these two versions of essentially the same
user DEFINED subroutine:

Version 1
FUNCTION SPC(STRING LENGTH JUST)
JUST = JUST : '#' : LENGTH
STRING = FMT(STRING JUST)
RETURN STRING

Version 2
FUNCTION SPC(STRING LENGTH JUST)
TEMP JUST = JUST : '#' : LENGTH
RETURN STRING = FMT(STRING TEMP JUST)
RETURN RETURN STRING

What's the difference? Both return a formatted string But the second one
does so without altering any of the data passed to it The first one
modifies two variables: STRING (by reformatting its contents) and JUST (by
reassigning it WITH a full justification specification) This explains the
results Mr Owen experienced WITH his problem

In the former case the values of these VARIABLES will be changed in the
program that called this one This is true because the VARIABLES are shared
with the CALLING program by virtue of being passed as ARGUMENTS In the
latter EXAMPLE by contrast the contents of the variable TEMP JUST is
"invisible" to the CALLING program because it is a local variable it is
neither one of the VARIABLES used in the argument list nor is it the
explicit return value for the function


LOCAL SHARED COMMON GLOBAL AND GLOBAL VARIABLES
There are four types of shared data areas in R/BASIC summarized as follows:

Global @Variables These may be globally readable (@USERNAME)
globally settable (@USER0 @SENTENCE) or readable/settable
for the CURRENT recursive (TCL) level (@LEVEL @RECUR)

Common Global Common areas established WITH a label i e LABELLED common
Information in LABELLED common is available to all programs
(main or subroutine/function) that declare the same label
Information is maintained for the entirety of the logon
SESSION unless explicitly nulled (although this does not
de allocate the LABELLED area)

Shared Argument lists and explicit COMMON VARIABLES This is a
limited form of inheritance by which one program can share
data WITH programs "below" it VARIABLES of these types can
be shared between one main program and any subroutines or
functions called by that main program including subroutines
that call further subroutines A main program cannot
however share ARGUMENTS or common VARIABLES WITH another
main program Any change made to a shared variable in any of
the interrelated programs is reflected for all subsequent
access to that variable There are differences in the way
ARGUMENTS and common VARIABLES are handled (See below)

Local VARIABLES in a program that are not one of the above i e
that are not @ VARIABLES LABELLED common common or part of
an argument list


PASSING BY REFERENCE PASSING BY VALUE
R/BASIC passes information in argument lists common LABELLED common and
@variables by reference This means that the variable in the CALLING and
called program are referencing the same physical data (more accurately the
same area of memory) even if the VARIABLES in the two programs happened to
have DIFFERENT NAMES By extension this means that if a subroutine changes
the value of a variable passed to it in an argument list or shared via a
COMMON declaration this change is reflected in the main program because
both programs are actually referring to the same information

It is possible to pass by value which means that the CALLING and called
routines have separate copies of the data This is done in R/BASIC by
passing an expression (rather than a variable) in an argument list or common
area (this doesn't work for @Variables) For example:
CALL MYSUB(A:B 2 + 3 "TEST")

All three ARGUMENTS in the EXAMPLE are expressions and are therefore passed
by value In other words the subroutine will receive the values represented
by the expressions However no change can be made to the ARGUMENTS as this
calling syntax does not allow for a value to be returned USING the argument
list (Functions can be called successfully in this manner as they return a
value "in place")


DESCRIPTERS
Underlying R/BASIC's use of VARIABLES is a fairly common operating system
technology known as a descripter (or descriptor) table Simply put the
descripter table is an array of all the VARIABLES currently in use anywhere
in the system including @variables (mostly) local VARIABLES labelled
common VARIABLES and a couple of other lower level types If you like you
can think of a descripter table as a large bank of pigeonholes or postboxes
into which information about the data in a variable can be stored

Each variable in each program has one entry (usually) in the descripter
table Each entry in the descripter table is 10 bytes long and the table as
a whole can be thought of as a single huge variable (more accurately a
single segment) and is therefore limited to 64k By deduction the maximum
number of VARIABLES that can be allocated in toto for one SESSION is 64k/10
or 6 535 The system itself has grabbed about one thousand of these by the
time the USER takes CONTROL however so there are somewhat closer to 5 000
available at level 1 TCL


ALLOCATION OF DESCRIPTERS
In the simplest scenario when a program is loaded the system allocates a
descripter for every variable in the program One of the data in a program
is the number of VARIABLES it requires so this is known as soon as the
program OBJECT CODE is READ For EXAMPLE if a program uses 5 local
variables the system allocates 5 descripter table entries when the program
is loaded When the program terminates the descripters are de allocated
and those slots in the table again become available

When you call a subroutine or function the system loads the code for the
routine and allocates descripters for its VARIABLES as well (but see below)
When the subroutine or function executes a RETURN STATEMENT however its
descripters are not de allocated They remain in the table (as in fact its
code remains in the program stack) until the main program that called them
terminates WITH a STOP STATEMENT


DIMENSIONED ARRAYS
One relatively common problem arises out of the attempt to dimension a
particularly large array (for EXAMPLE DIM ARRAY(100 100)) This results in
the ERROR "maximum number of errors exceded [sic]" As it happens R/BASIC
attempts to allocate one DESCRIPTOR table entry for each element in the
dimensioned array (plus 2 extra) For EXAMPLE the statement
DIM ARRAY (100 100) attempts to allocate 10 002 descripters considerably
beyond the SIZE of the table The result is as noted (This is not a problem
for DYNAMIC ARRAYS because dynamics ARRAYS are treated as a single variable
that just happens to have delimiters in it As a note of interest this
explains why access to the 5 000th element of a dimensioned array is faster
than access to the 5 000th element of a dynamic array In the former case
the system can EXTRACT the data as if it were its own variable which in
effect it is In the latter case the system must SCAN through a single
large string looking for the 4 999th and 5 000th delimiters)

ARGUMENTS
Shared VARIABLES passed as ARGUMENTS are handled a bit differently In the
main program they are allocated as individual entries in the descripter
table In the called routines however a variable that is in the argument
list is not simply allocated a new independent descripter table entry
Shared VARIABLES in a subroutine do in fact get entries in the table but
the entries are not "normal" entries Indeed they are pointers to the
descripters that do contain the data for that variable Thus a reference to
an argument in a subroutine is looked up in the descripter table which
points it to another entry The effect as noted earlier is that there is
only one "real" descripter for a shared variable and only one physical
location for the data All other references to it via argument lists all
point to this one entry

Given the explanation of "passing by reference" it should ALSO be clear how
passing an expression in an argument list is DIFFERENT In that case the
argument in the argument list has no relationship WITH an existing
descripter since it isn't a variable that is being passed but an actual
value there is nothing to point to except a data value DIRECTLY

If a subroutine or function is called recursively each new iteration sets
up a new descripter variable (local or shared) in the subroutine or
function If the variable is part of an argument list the descripter for
that variable points to the descripter referenced by the CALLING routine so
that the descripter for an argument to a subroutine that has called itself
twice contains a POINTER to a pointer to a pointer to a variable
Fortunately if you pass dimensioned ARRAYS the system is intelligent
enough not to reallocate new descripters for each element Instead the
argument contains a pointer to one of those extra array descripters
mentioned earlier one that contains information about the dimension of the
array and other such salient data

The fact that a new descripter is allocated in a recursively called
subroutine for each argument explains why an endless LOOP of recursive calls
will sometimes abort WITH "out of memory" but other times WITH "too many
variables" In the latter case the first limit that was reached was the
number of possible entries in the descripter table for the VARIABLES used by
that routine


COMMON AND LABELLED COMMON VARIABLES
Although the common VARIABLES are often thought to be interchangeable with
argument lists they are handled differently in the descripter table The
declaration of a common area (labelled or "normal") alerts the COMPILER to
tag the VARIABLES in question in the OBJECT code and likewise alerts the
program loader to allocate new descripters for those VARIABLES only if they
are not already allocated Instead of USING a STACK of indirect pointers as
is done WITH ARGUMENTS the system resolves all references to a common
variable by ACCESSING the same descripter each TIME This results in a
slight improvement in efficiency for lookup and obviously saves the extra
descripter entries

@VARIABLES
@Variables are handled differently yet again These are pre DEFINED in the
compiler so the system already knows something about their locations in the
descripter table A specific reference is therefore compiled right into the
program so that a new descripter is not allocated when the program that
references them is loaded

FUN WITH DESCRIPTERS
There isn't a great deal you can do WITH descripters DIRECTLY FROM R/BASIC
but there are a few tricks Three R/BASIC accessible statements and
functions deal specifically WITH descripters:

Transfer When you assign a value to a variable you allocate a
descripter and place information into the descripter If you
assign the value of one variable to another (e g A = B) you
allocate a second descripter look up the value represented by
the first one COPY it and then assign it to the second
descripter The end result is two descripters and more
importantly two copies of the data The TRANSFER command
short circuits this PROCESS Instead of copying the data and
assigning it anew the COMMAND simply copies the first
descripter wholesale to the second one This literally
transfers one descripter to another including information
about the data it represents This is a much faster operation
than copying the data and assigning it a new descripter
However because two descripters cannot point to the same data
the first one is reassigned a null value

Unassigned An EXTERNAL function (DECLARE it) available somewhere around
release 1 1 the UNASSIGNED function tells you whether a
variable has been assigned a value You might guess how it
works It reads the descripter table entry for the variable you
pass it and REPORTS back WITH true if the descripter contains
the special value placed in there at allocation time (before
any value is assigned to the variable)

Descripter The best for last The internal function DESCRIPTER hands back
to you the actual descripter table entry for the variable you
pass it If you are enterprising (and are reasonably familiar
WITH the ways of bit level data handling) you can probably use
this function to figure how descripters are built and what
they actually contain Beyond that it has limited use although
it can be useful on odd occasions when DEBUGGING


(Volume 3 Issue 1 Pages 11 15)
[revmedia/copyrigh.htm]

Page last modified: 30/01/03