Contents of Article


Miscellaneous Considerations

General Statements

Program Control Structures

Operators

Macro Headers

ISREDIT calls

Rexx Functions 



Introduction


If you come from an IBM ISPF background, you may have used or written TSO/Rexx scripts to interface with ISPF. While our thinBasic scripts and the capabilities of SPFLite are not exactly the same, there are enough similarities that you may be able to convert some existing Rexx scripts to thinBasic and have them perform useful work in the SPFLite environment.


You will not be able to convert ISPF-specific features, like access to the Dialog Manager, Table Services, File Tailoring, etc. but for scripts that simply interface with an edit session, there is enough functional commonality that a workable conversion may be possible.


We can't give you every possible conversion strategy and technique, or cover every syntax requirement, but the following may be a good starting point to help you. Because this topic is large and complicated, what is presented here should be considered as the first draft of a work in progress. We invite all users with ISPF/Rexx experience to test out these ideas, and we welcome any and all suggestions for improving on these conversion strategies.


Keep in mind, in addition to ISPF vs. SPFLite differences, that the thinBasic functions and features are comparable but may not be identical to Rexx. Be sure to consult the thinBasic documentation for any features you are not familiar with, and to ensure that function parameters and results are what you expected.



Miscellaneous Considerations


    • A major difference between Rexx and thinBasic is that Rexx treats all values as strings, which you don't need to declare, whereas thinBasic is a more "strongly typed" language, and does require you to predeclare string and numeric variables before you use them.


    • If you have Rexx code that is checking return codes from ISREDIT and ISPEXEC calls, be aware the SPFLite return codes are different. Both treat a return code of 0 as "normal" and non-zero is usually treated as a "problem occurred". Beyond that, there is no similarity.


    • Rexx scripts return messages back to ISPF using a call to ISPEXEC SETMSG MSG(msgID). In many cases, this call will reference two Dialog variables, ZerrSm and ZerrLm, the "short error message" and "long error message". ISPF will first display a "short" message, and if you press F1, it will first display the longer message, then launch a Help panel. SPFLite does not implement this two-stage messaging; there is only a single message displayed by SET_MSG. If you are converting ISPF Rexx scripts with ISPEXEC SETMSG calls, you will have to pick the message you like the best (either short or long) as the one and only message displayed. Because the SPFLite screen can handle fairly long messages, you may want to choose the ZerrLm value for SET_MSG. If you really need both the short and long messages, you may wish to call MSGBOX instead of SET_MSG. (You might use the "long" message as the MSGBOX message, and the "short" message as the MSGBOX title.)  Some message ID codes for ISPEXEC SETMSG refer to fixed messages in the ISPF message library, and do not use the contents of Dialog variables ZerrSm and ZerrLm. You would need to know what those messages were, and/or have access to a copy of that library, to be able to convert such messages to SPFLite.


    • ISREDIT commands that deal with lines use visible line number values. SPFLite uses the Line Pointer concept. In most cases, you can treat Line Pointers as if they were line numbers, for purposes of converting the Rexx script. You will need to add code to ensure that IS_DATA(linePointer) is TRUE, so you don't attempt to process non-data lines in your edit file.


    • Any Rexx statements involving LINE functions such as LINEIN and LINEOUT that you wish to convert to thinBasic will require a USES "FILE" statement in your macro. Be aware that if you attempt to perform file I/O on files that SPFLite already has opened, it could result in runtime conflicts. 


    • Rexx has a command called INTERPRET, which will take a string and treat it as a Rexx statement, which is immediately parsed and executed. thinBasic does not have an INTERPRET capability per se, but it does have a series of functions that begin with "Eval" which are used to evaluate string and math expressions. If you are converting a Rexx script with INTERPRET, one of the Eval functions may work for you, if the Rexx INTERPRET operation is limited to dynamic expression evaluation. Consult the thinBasic documentation for more information on the Eval functions.


    • Rexx scripts tend to frequently use the PARSE facility. Often this is simply to grab arguments passed to a subroutine or to read values from a file or queue. However, you may run into cases where PARSE is being used in more complex ways. thinBasic has a PARSE function, which operates differently than Rexx, but it may be enough for simpler cases. Otherwise, you may have a bit of work to do converting this.


    • Rexx has a novel way of storing string values, in which you can define a fixed "base" variable name and append a dynamic "stem" to it. Rexx uses this stem approach to substitute for arrays, which is doesn't support. If you have a Rexx script that uses stemmed variables, you may have considerable work to convert them. Often, Rexx stem variables are simply used as arrays, and thinBasic supports these natively. If your Rexx script does anything fancier than that with stems, you might be able to use SPFLite Globally Stored Data as a substitute for stem variables.


    • ISPF has a way to store variable values in the "shared pool" or the "profile pool" using ISPEXEC VGET and ISPEXEC VPUT. If you have a script that does this, you will have to rewrite it. Here are some strategies for going about this:


      • You can get edit Profile values using Get_Profile$, and can set Profile values using a SPF_CMD call, like SET_CMD("START FIRST")
      • Other than standard Profile values, you cannot add user-defined values to an SPFLite edit profile
      • For "shared variables", Globally Stored Data may be sufficient, as long as you understand it is not persistent across SPFLite instances. Once you close down SPFLite and restart it, the values will be gone.
      • If you want to store persistent values, you can use Set_SETVAR and Get_SETVAR$ to access the SPFLite SET variable pool. If you do this, be careful not to inadvertently write over any existing values. You can use SET names that have dots in them; this allows you to form "qualified SET names". Adopt a consistent naming convention for the SET symbols you define this way.
      • Because SPFLite SET names are persistent, you need to evaluate whether the script you are converting intended its variables to be persistent or not. If not, using SET names may not be not the right approach, and you may wish to use Globally Stored Data instead.
      • For example, if you are converting a script that stored name ABC in the shared pool, and XYZ in the profile pool, you could use those pool names as SET name qualifiers. Keep in mind that if you call Get_SETVAR for an undefined name, the function will return an empty (null) string. Example:


Rexx


"ISPEXEC VGET ABC SHARED"

"ISPEXEC VGET XYZ PROFILE"


"ISPEXEC VPUT ABC SHARED"

"ISPEXEC VPUT XYZ PROFILE"


SPFLite


DIM ABC,XYZ AS STRING


ABC = Get_SETVAR ("SHARED.ABC")

XYZ = Get_SETVAR ("PROFILE.XYZ")


Set_SETVAR ("SHARED.ABC", ABC)

Set_SETVAR ("PROFILE.XYZ", XYZ)






General Statements



Rexx

thinBasic

ADDRESS

not needed


ARG, PARSE ARG

Get_Arg$

UCASE$(Get_Arg())


CALL routine

routine     [CALL keyword not used]


DO

see Program Control Structures below


DROP

REDIM may apply, but probably not needed


EXIT

HALT


EXIT returnCode

HALT (returnCode, "message")


IF

see Program Control Structures below


INTERPRET

thinBasic Eval functions may apply. See thinBasic help for more information.


ITERATE

ITERATE FOR|WHILE|DO

thinBasic ITERATE cannot reference an outer nested block, but only the closest one


LEAVE

EXIT FOR|WHILE|DO

thinBasic EXIT has a "number of times" operand to exit from multiple FOR/NEXT blocks


LINEIN

USES "FILE"

various I/O statements; see thinBasic Help


LINEOUT

USES "FILE"

various I/O statements; see thinBasic Help


NOP    (used for "do nothing" branches of IF statements)

NOP


-- thinBasic does not natively have a NOP statement, but SPFLite has added one. It is essentially a SUB named NOP that does nothing. -- 


NUMERIC

not supported


PARSE

thinBasic has a number of parsing functions, including PARSE, PARSE$, PARSECOUNT and PARSESET$, as well as several other string functions. See the thinBasic documentation for more information.


PROCEDURE

SUB and FUNCTION


PULL

not supported


PUSH

not supported


QUEUE

not supported


RAISE

not supported. In Rexx, RAISE is sometimes used to simulate a GOTO statement, which thinBasic does not support either. It is possible some use of EXIT may be applied.


RETURN [expression]

RETURN [expression]


SAY




SAY string

SPF_DEBUG

SET_MSG

MSGBOX


USES "CONSOLE"

PRINTL string  ' displays on a console window


' PRINT instead of PRINTL will output the

' string without a line terminator.

' You can use CLS to clear the screen

' See CONSOLE module documentation for more

' details.


SIGNAL

not supported. In Rexx, SIGNAL is sometimes used to simulate a GOTO statement, which thinBasic does not support either. It is possible some use of EXIT may be applied.


TRACE

SPF_TRACE

functionality is different





Program Control Structures


The main difference here is that Rexx uses a common DO ... END structure for all blocks of code (like PL/1 which it is modeled after) while thinBasic has unique delimiters for each type of block. You will also notice that in Rexx you will often see an END prior to an ELSE,  ELSE IF or WHEN/OTHERWISE clauses, whereas in thinBasic for ELSE, ELSEIF and CASE, that is not necessary.


Note that in thinBasic:

    • ELSEIF is all one word
    • END IF is two words, where the IF part is required
    • END SELECT is two words, where the SELECT part is required
    • In FOR/NEXT loops, NEXT does not require an index name afterwards like NEXT N. It's just NEXT. Specifying the N value is supported and is probably a good idea for documenting purposes.
    • SELECT CASE defines a common expression, which is tested by each CASE clause, whereas a Rexx SELECT defines a test at each WHEN clause, and there is no common expression on the Rexx SELECT clause. This means there is more to do than merely changing keywords; may will have to restructure your SELECT statements. If your WHEN clauses compare against a common value, you can move that value into the SELECT CASE expression. Otherwise, you can specify this as SELECT CASE OF, and ensure that each WHEN clause is rewritten to be a CASE clause with an expression that produces a "truth" value of -1 or 0. You can ensure that by enclosing each expression in the thinBasic function IsTrue
    • The OF keyword is a bit of "magic" supported by SPFLite; just code it as is when converting Rexx SELECT statements.
    • If you are converting a Rexx WHEN clause that is already in the form of a comparison like COUNT = 5, the expression will automatically produce a thinBasic "truth value" of -1 or 0, and so enclosing it in a thinBasic function IsTrue would not be required.


Rexx

thinBasic

statement1 ; statement2

statement1 : statement2


if cond then statement

if cond then statement


if cond1 then do

    statement1

end

else if cond2 then

    statement2

end

else do

    statement3

end

if cond1 then

    statement1

elseif cond2 then

    statement2

else

    statement3

end if

do i = 1 to 10

  if cond1 then leave

    statement

    if cond2 then iterate

end


do i = 1 to 10 by -1

  if cond1 then leave

    statement

    if cond2 then iterate

end

for i = 1 to 10

    if cond1 then exit for

    statement

    if cond2 then iterate for

next


for i = 1 to 10 step -1

    if cond1 then exit for

    statement

    if cond2 then iterate for

next


do while cond

    if cond1 then leave

    statement

    if cond2 then iterate

end

do while cond

    if cond1 then exit do

    statement

    if cond2 then iterate do

loop


do forever

    statement

end

do

    statement

loop


select

    when cond1 

    do

        statement1

    end

    when var = value 

    do

        statement2

    end

    when var1 = value1, var2 = value2 

    do

        statement3

    end

/* ... */

    otherwise do

        statement3

    end

end


' NOTE 1: In Rexx, a comma-separated expr

' list on WHEN implies an AND test

select case of

    case IsTrue(cond1)


       statement1


    case var = value


       statement2


    case (var1 = value1) and (var2 = value2)


        statement3


    case else

        statement3


end select


' NOTE 1: the "of" after SELECT CASE is a

' keyword supported only within SPFLite.

' It won't work in stand-alone thinBasic.


' NOTE 2: In thinBasic, a comma-separated expr

' list on CASE implies an OR test


 ,    (comma as line continuation)


 _    (underscore as line continuation)



/* line comment */




/*

   block comment

*/

/* line comment */

           (or)

' line comment


/*

   block comment

*/


' NOTE: Using /* */ as block comments is

' non-standard for BASIC, but thinBasic 

' allows it.




Operators


Operators that are the same are not mentioned


Rexx

thinBasic

&

AND


|

OR


||     (concatenate)

&

+


/=  \=  ¬=  <>  ><

<>


<<  <<=  >>  >>=  ==

<  <=  >  >=  =


¬    \

NOT


one two       (concatenation with blank)  

(one)(two)    (abuttal)

one & " " & two

one&two


/             (real divide)

/


%             (integer divide)

\


**            (power)

^


&&

XOR





Macro Headers


Rexx

thinBasic

/* REXX other comments */

"ISREDIT MACRO (arg1,arg2) PROCESS"

' macname.MACRO 

DIM arg1,arg2 AS STRING

arg1 = Get_Arg$(1)

arg2 = Get_Arg$(2)


/* REXX other comments */

"ISREDIT MACRO (arg1,arg2) NOPROCESS"

"ISREDIT PROCESS RANGE C"

' macname.MACRO 

DIM arg1,arg2 AS STRING

DIM _ZFRANGE,_ZLRANGE AS NUMBER = 0

arg1 = Get_Arg$(1)

arg2 = Get_Arg$(2)


if is_line_cmd and _

(get_src_lcmd$="C" or get_src_lcmd$="CC") then

    _ZFRANGE = get_src1_lptr

    _ZLRANGE = get_src2_lptr

end if





ISREDIT calls


Rexx

thinBasic

"ISREDIT AUTOSAVE ON|OFF PROMPT|NOPROMPT"

SPF_CMD("AUTOSAVE ON|OFF PROMPT|NOPROMPT")


"ISREDIT (var) = BLKSIZE"

var = GET_PROFILE$("LRECL")


"ISREDIT BOUNDS left right"

SPF_CMD("BOUNDS left right")


"ISREDIT (left,right) = BOUNDS"

left = Get_Lbound

right = Get_Rbound


"ISREDIT (var) = CAPS"

var = GET_PROFILE$("CAPS")


"ISREDIT CAPS = ON|OFF"

SPF_CMD("CAPS ON|OFF")


"ISREDIT CHANGE operands"

SPF_CMD("C operands")


"ISREDIT (times) = CHANGE_COUNTS"

"ISREDIT (times,lines) = CHANGE_COUNTS"

DIM msg, times, lines AS STRING

SPF_CMD("CHANGE operands")

msg = GET_MSG$

times = PARSE$(msg, " ", 4)

lines = PARSE$(msg, " ", 7)

if lines = "" then lines = times


"ISREDIT COPY operands"

SPF_CMD("COPY operands")


"ISREDIT (line,col) = CURSOR"

line = Get_LNUM(Get_CSR_LPTR))

col = Get_CSR_COL


"ISREDIT CURSOR = line col"

SET_CSR(line,col,0)


"ISREDIT CUT operands"

SPF_CMD("CUT operands")


"ISREDIT (var) = DATA_CHANGED"

var = IIF$(GET_MODIFIED,"YES","NO")


"ISREDIT DELETE operands"

SPF_CMD("DELETE operands")


"ISREDIT EXCLUDE operands"

SPF_CMD("EXCLUDE operands")

SPF_CMD("X operands")


"ISREDIT FIND operands"

SPF_CMD("FIND operands")

SPF_CMD("F operands")


"ISREDIT (times) = FIND_COUNTS"

"ISREDIT (times,lines) = FIND_COUNTS"

DIM msg, times, lines AS STRING

SPF_CMD("FIND operands")

msg = GET_MSG$

times = PARSE$(msg, " ", 4)

lines = PARSE$(msg, " ", 7)

if lines = "" then lines = times


"ISREDIT FLIP operands"

SPF_CMD("FLIP operands")


"ISREDIT HEX = ON|OFF"

SPF_CMD("HEX ON|OFF")


"ISREDIT var = HEX"

var = GET_PROFILE$("HEX")


"ISREDIT HIDE operand"

SPF_CMD("HIDE")


"ISREDIT RESET HIDE"

SPF_CMD("RESET HIDE")


"ISREDIT HILITE [ON|OFF] [AUTO] [FIND]"

SPF_CMD("HILITE [ON|OFF] [AUTO] [FIND]")


"ISREDIT INSERT label|linenum [lines]"

SPF_CMD("LINE I" & TSTR$(lines) & label)

SPF_CMD("LINE N" & TSTR$(lines) & label)


"ISREDIT (var) = LABEL .label|linenum"

var = GET_Label$(GET_LPTR(label))


"ISREDIT LABEL .label|linenum = .newlabel

SPF_CMD("LINE '.newlabel' .label")


"ISREDIT (var) = LINE .label|linenum"

var = GET_LINE$(GET_LPTR(label_or_linenum))


"ISREDIT LINE .label|linenum = data"

SET_LINE(GET_LPTR(label_or_linenum),data)


"ISREDIT LINE_AFTER .label|linenum = data"

SPF_CMD("LINE N label_or_linenum")

SET_LINE(GET_LPTR(label_or_linenum)+1,data)


"ISREDIT LINE_AFTER .label|linenum = NOTELINE data"

SPF_CMD("LINE NOTE label_or_linenum")

SET_LINE(GET_LPTR(label_or_linenum)+1,data)


"ISREDIT LINE_BEFORE .label|linenum = data"

DIM LPTR AS NUMBER

LPTR = GET_LPTR(.label|linenum) - 1

IF LPTR > 0 THEN

   SPF_CMD("LINE N !" & TSTR$(LPTR))

   SET_LINE(LPTR+1, data) 

END IF


"ISREDIT LINE_BEFORE .label|linenum = NOTELINE data"

DIM LPTR AS NUMBER

LPTR = GET_LPTR(.label|linenum) - 1

IF LPTR > 0 THEN

   SPF_CMD("LINE NOTE !" & TSTR$(LPTR))

   SET_LINE(LPTR+1, data) 

END IF


"ISREDIT (var) = LINENUM .label"

var = GET_LNUM(GET_LPTR(".label"))


"ISREDIT LOCATE operands"

SPF_CMD("LOCATE operands")


"ISREDIT (var) = LRECL"

var = GET_PROFILE$("LRECL")


"ISREDIT (var) = MEMBER"

var = GET_FILEBASE$


"ISREDIT PASTE operands"

SPF_CMD("PASTE operands")


"ISREDIT PRESERVE ON|OFF|C"

SPF_CMD("PRESERVE ON|OFF|C")


"ISREDIT (var) = PRESERVE"

var = GET_PROFILE$("PRESERVE")


"ISREDIT PROCESS [DEST] [RANGE cmd1 [cmd2]]"

The ISPF line command names cmd1 and cmd2 can be up to 6 characters and can contain any alphabetic or special character except blank, hyphen (-), or apostrophe (). SPFLite line command names are not predeclared in this way, but use the GET_SRC_LCMD$ and GET_DEST_LCMD$ functions. You cannot define arbitrary line command names for use in a macro the way ISPF does this. If you use the macro as a primary command, possible source commands are C/CC and M/MM, while line-command macros use the name of the macro itself as the name of the source line range. Possible destination commands are A/AA, B/BB, H/HH, W/WW, O/RR and OR/ORR for both types of macros.


SPFLite line command names are currently limited to four characters.


"ISREDIT (var) = RANGE_CMD"

var = GET_SRC_LCMD$

    -- or --

var = GET_DEST_LCMD$


"ISREDIT RCHANGE"

SPF_CMD("RCHANGE")


"ISREDIT (var) = RECFM"

var = GET_PROFILE$("RECFM")


"ISREDIT REPLACE operands"

SPF_CMD("REPLACE operands")


"ISREDIT RFIND"

SPF_CMD("RFIND")


"ISREDIT SEEK operands"

SPF_CMD("FIND operands DX")


"ISREDIT (times) = SEEK_COUNTS"

"ISREDIT (times,lines) = SEEK_COUNTS"

DIM msg, times, lines AS STRING

SPF_CMD("FIND operands DX")

msg = GET_MSG$

times = PARSE$(msg, " ", 4)

lines = PARSE$(msg, " ", 7)

if lines = "" then lines = times


"ISREDIT (var) = SESSION"

-- may return EDIT or VIEW --

var = GET_SESSION_TYPE$

-- may return EDIT, BROWSE or other values --


ZerrSm = "short message"

ZerrLm = "long message"

"ISPEXEC "SETMSG MSG(msgCode)

Set_Msg ([rc,] ZerrLm)


-- see notes above about ISPEXEC SETMSG --


"ISREDIT SETUNDO operands"

SPF_CMD("SETUNDO number")

-- SPFLite SETUNDO not compatible with ISPF --


"ISREDIT SHIFT ( lnum_or_label [n]"

"ISREDIT SHIFT ) lnum_or_label [n]"

"ISREDIT SHIFT < lnum_or_label [n]"

"ISREDIT SHIFT > lnum_or_label [n]"

SPF_CMD("LINE (n !" & GET_LPTR(lnum_or_label)))

SPF_CMD("LINE )n !" & GET_LPTR(lnum_or_label)))

SPF_CMD("LINE <n !" & GET_LPTR(lnum_or_label)))

SPF_CMD("LINE >n !" & GET_LPTR(lnum_or_label)))


"ISREDIT SORT operands"

SPF_CMD("SORT operands")


"ISREDIT SOURCE operand"

"ISREDIT (var) = SOURCE"

"ISREDIT RESET SOURCE"

SPF_CMD("SOURCE operand")

var = GET_PROFILE$("SOURCE")

SPF_CMD("RESET SOURCE")


"ISREDIT SUBMIT operands"

SPF_CMD("SUBMIT operands")


"ISREDIT TABS ON|OFF"

"ISREDIT (var) = TABS"

SPF_CMD("TABS ON|OFF")

var = GET_PROFILE$("TABS")


"ISREDIT (var) = TABSLINE"

DIM var AS STRING 

SPF_CMD("LINE TABS !2")

var = GET_LINE$(3)

SPF_CMD("LINE D !3")   


"ISREDIT = TABSLINE = data"

SPF_CMD("LINE TABS !2")

SET_LINE$(3,data)

SPF_CMD("LINE D !3")   


"ISREDIT TFLOW lnum_or_label [n]"

SPF_CMD("LINE TF" & n & "lnum_or_label") 


"ISREDIT TSPLIT lnum_or_label [n]"

SPF_CMD("LINE TS" & n & "lnum_or_label") 





Rexx Functions  


Rexx

thinBasic

abbrev(longString,shortString)

StartsWith(longString,shortString,0)


abs(value)

abs(value)


address()

n/a


arg()

get_arg_count


arg(n)

get-arg$(n)


center(string,len)

center(string,len,pad)

cset$(string,len)

cset$(string,len,pad)


changestr(needle,haystack,newneedle)

replace$(haystack,needle,newneedle)


copies(string,n)

repeat$(n,string)


countstr(needle,haystack)

tally(haystack,needle)


date()

date$()    (format operands are different)


delstr(string,pos,len)

strdelete$(string,pos,len)


str = directory()



directory(newdirectory)

USES "FILE"

str = DIR_GetCurrent


USES "FILE"

DIR_Change(newdirectory)




filespec("Drive",fullpath)

filespec("Path",fullpath)

filespec("Location",fullpath)

filespec("Name",fullpath)

filespec("Extension",fullpath)

USES "FILE" ' -- for all calls


LEFT$(FILE_PATHSPLIT(fullpath,%Path_root),2)

MID$(FILE_PATHSPLIT(fullpath,%Path_Rootpath),3)

FILE_PATHSPLIT(fullpath,%Path_Rootpath)

FILE_PATHSPLIT(fullpath,%Path_FileExt)

FILE_PATHSPLIT(fullpath,%Path_Ext)


format()

format$()    (format operands are different)


insert(new,target,pos)

strinsert$(target,new,pos)


left(string,len)

left(string,len,pad)

left$(string,len)

lset$(left$(string,len),len,pad)


lastpos(needle,haystack)

lastpos(needle,haystack,start)

instr(-1,haystack,needle)

instr(start-len(haystack)-1,haystack,needle)


length(string)

len(string)


lower(string)

lcase$(string)


max(str1,str2,etc)

max(num1,num2,etc)

max$(str1,str2,etc)

max(num1,num2,etc)


min(str1,str2,etc)

min(num1,num2,etc)

min$(str1,str2,etc)

min(num1,num2,etc)


pos(needle,haystack)

pos(needle,haystack,start)

instr(haystack,needle)

instr(start,haystack,needle)


reverse(string)

strreverse$(string)


right(string,len)

right$(string,len)


sign(number)

sgn(number)


space(string)

space(string,n)

space(string,0)

trimfull$(string)

replace$(trimfull$(string)," ",lset$("",3))

remove$(string, " ")


strip(string)

strip(string,"Both")

strip(string,"Leading")

strip(string,"Trailing")


strip(string,,char)

strip(string,"Both",char)

strip(string,"Leading",char)

strip(string,"Trailing",char)

trim$(string)

trim$(string)

ltrim$(string)

rtrim$(string)


trim$(string,char)

trim$(string,char)

ltrim$(string,char)

rtrim$(string,char)


substr(data,pos,len)

substr(data,pos)

mid$(data,pos,len)

mid$(data,pos)


time()

time$        (format is different)


translate(string)

ucase$(string)


translate(string,newCharSet,oldCharSet)

replace$(string, ANY oldCharSet, newCharSet)


trunc(string)


' trunc is often used to extract a "qualified

' option" like "3" from a string like "3.4"

extract$(string,".")

upper(string)

ucase$(string)


verify(string,charset)

verify(,string,charset)


Created with the Personal Edition of HelpNDoc: Maximize Your Productivity with a Help Authoring Tool