&type "The sum is %21 acres."and variable 21 at that time contained the value "40.25", the SML processor would "see" that line as:
&type "The sum is 40.25 acres."and proceed to execute that command. SML variables are stored as character strings, which may be numeric or nonnumeric. Numeric strings (if resulting from a calculation) are formatted by the SML processor according to the FORTRAN fixed decimal format 17.5, i.e. up to 11 digits before the decimal point and five digits after. Nonnumeric strings are limited to 80 characters.
It is important to note that there are two types of variables: local and global. Local variables, introduced in version 3.5, are only accessible within a routine, whereas global variables may be accessed by all routines.
Local variables are numbered -20 through -1. When one routine calls another, the slate will be wiped clean for that routine; upon return to the parent routine, its local variables will be restored. The following example makes use of the &lv (or &listvar) directive to list variable contents: TEST1.SML
&sv -1 10 &sv -2 20 &run test2 &lv -2 -1 &returnTEST2.SML
&sv -1 11 &sv -2 12 &lv -2 -1 &returnWhen TEST1 is executed, the output is as follows:
VAR. VALUE %-002 12 %-001 11 VAR. VALUE %-002 20 %-001 10The chief advantage of local variables is to provide scratch space for routines and to help prevent variable collision, which will be discussed under Debugging.
Global variables may in turn be categorized as memory and extended.
Memory variables, numbers 1 through 50, are memory resident and are useful as short term variables, especially those involved in frequent or iterated calculations, since run time is a bit faster. Memory variables are global in that they are accessible from all routines running within a particular SML processor. Those variables are not globally accessible, however, from other SML processors. Thus if an SML program running under ARC were to call a routine running under ARCEDIT, the routine running under ARCEDIT would not have access to the memory variables of the parent routine; rather, it would have a "clean slate". The ARC memory variables are not eradicated, though: they will be available once again after termination of ARCEDIT.
Extended variables, numbered 51 through 9999, are globally accessible from all SML processors invoked in a PC ARC/INFO session; their values are maintained by default in the file %WKSP%t$extsml.var (see discussion of DOS environment variables below), which is created at the beginning of the ARC session and deleted upon quitting.
Variable 0 is a dummy variable, and is generally used as an argument to the SHOW command when not all returned values are desired:
SHOW STATISTICS 0 0 0 -11 0
Question: Why cannot local variables be saved using the &save directive (even though the directive permits it)? Answer: Because after the resulting SML is executed, the parent routine's local variables will be restored. Any information to be saved must be assigned to global variables or sent to a temporary file:
&rem **** save local variables &value -20 WKSP &openw %-20t$sav.lis &write "%-1" &write "%-2" &write "%-3" &write "%-4" &closew ... &rem **** restore local variables &open %-20t$sav.lis error &read -1 error &read -2 error &read -3 error &read -4 error &close
&sv 11 4.00000001 &cv 12 5.00000001 &sv 13 "%11 * %12" &cv 14 %11 * %12variable 11 will be assigned a value of "4.00000001", variable 12 will be assigned a value of "5", variable 13 will be assigned a value of "4.00000001 * 5", and variable 14 will be assigned a value of "20". The &cv directive supports complex arithmetic statements with multiple levels of parentheses (I have yet to discover its limits); see the SML command reference entry &calcvar for an exhaustive list of operators and functions.
[TIP: The SML Developer's Toolkit has an SML program which uses Newton's method to calculate square roots. Forget it. Just use the exponentiation operator (e.g. 2 ** 0.5), which is quite as accurate (and far quicker).]
The &extract directive is very useful to extract tokens from a string, i.e. substrings separated by a delimiter such as a space or a backslash. For example, in the following lines:
&sv 11 "SML is Your friend." &extract 12 11 3 &extract 13 11 3 Lvariable 12 will be assigned the value "YOUR" and variable 13 the value "Your"; by default, &extract converts substrings to upper case: the "L" option preserves the case of the substring. If the delimiter is anything other than a space, the extracted string will retain the delimiter at the end. This is a mixed blessing because on one hand, you know you have reached the final token if the delimiter is missing:
&rem **** Variable 51 contains full path and name of coverage ****** &sv 1 0 &label loop &cv 1 %1 + 1 &extract 11 51 %1 # \ &goback loop &if &cn %11 \ &label endIn this example, if variable 51 contains "C:\HOME\PROJECT1\TOPO", the final value of variable 11 will be "TOPO". On the other hand, in all other cases you'll most likely want to get rid of the delimiterthat is where &length, which returns the length of a string, comes in handy:
&sv 11 "Archaic|Pueblo I|Late Pueblo III" &extract 12 11 2 L | &length 13 "%12" &cv 13 %13 - 1 &value 12 12 1 %13The &value directive has three different functions: 1) to assign the contents of an SML variable, 2) to assign a substring of a variable (as above), and 3) to assign the contents of a DOS environment variable (see below). Note that SML is structured in such a way as to allow pointers, i.e. variables which refer to other variables. For example, in the following lines:
&cv %49 12 / 3 &value 11 %49if variable 49 contains the value "101", variables 101 and 11 both will be assigned the value "4". Pointers are useful for manipulating primitive arrays, or lists of values.
&value also allows the substitution of one string into another:
&sv -1 123 &sv -2 abcdefghi &value -2 -1 1 3 4 6In the above example, variable -2 will be assigned the value "abc123ghi".
The SHOW command in the ALLOCATE, ARCEDIT, ARCPLOT, and ROUTE modules allows you to assign a variety of session-related values to SML variables. For example, if in ARCPLOT a project area is to be divided into mapsheets, you can create a polygon coverage MAPSHEET which may be reselected by the item NAME to determine the mapextent for the plot. The problem: if you use MAPE POLY MAPSHEET, the resulting mapextent is 10% larger than what you want. The solution: a bit of arithmetic.
&rem **** variable 51 contains the name of the mapsheet ************ RES MAPSHEET POLY NAME = '%51' MAPE POLY MAPSHEET SHOW MAPE 11 12 13 14 &cv 11 %11 + ( ( %13 - %11 ) / 22 ) &cv 12 %12 + ( ( %14 - %12 ) / 22 ) &cv 13 %13 - ( ( %13 - %11 ) / 22 ) &cv 14 %14 - ( ( %14 - %12 ) / 22 ) &sv 15 "%11 %12 %13 %14" &type "%15" MAPE %15The lines involving variable 15 are redundant, but they highlight an important point: should there be any possibility that an expression for &sv or &type contains spaces, enclose it in quotes. If your program types out incomplete text, check your &type statements; if you get the error message "Could not format value", check your &sv statements.
&value -2 -1 %<lpos \ %-1 + 1>and to extract the path from a file specification:
&value -2 -1 1 %<lpos \ %-1>
PATH C:\WINDOWS;C:\;C:\DOS;C:\ARCEXE\CMD;C:\DBASEDOS variables may be utilized directly within a DOS batch program by bracketing the variable reference with percent characters. For example, you could create a batch program utool.bat (residing in a PATH directory) as follows:
@ECHO OFF A %ARC%\UTOOL :DO IF "%1-" == "-" GOTO END CD %1 SHIFT GOTO DO :ENDAssuming that autoexec.bat contains the following line:
SET ARC=C:\ARCEXEif you were to type "UTOOL" you would end up in C:\ARCEXE\UTOOL, or if you were to type "UTOOL SOURCE" you would end up in the directory C:\ARCEXE\UTOOL\SOURCE. (Further discussion of batch programming is beyond the scope of this article.)
[TIP: A.exe is a handy little utility supplied with PC ARC/INFO which allows you to jump to a combined drive/directory specification; you do not need to be at the ARC prompt to use it. Note, however, that the application is 16 bit and does not support long directory names.]
Finally, the contents of DOS variables may be assigned to SML variables using the &value directive. The DOS variable WKSP, which is set at the beginning of the ARC session to establish a unique location for system files, also provides a convenient location to store temporary SML programs created by a parent program, as in the following example:
COPYINFO impacted.pat area_a ADDITEM area_a area_a acres 8 12 f 4 &value 51 WKSP &openw %51t$calc.sml &write "SEL area_a" &write "RES area < 0" &write "PURGE" &write "Y" &write "CALC acres = area / 4047" &write "Q" &closew TABLES %51t$calc.sml & DEL %51t$calc.smlNote that a backslash is not required after "%51" because %WKSP%, in an ARC session, ends in a backslash. The "& " at the final line is equivalent to &sys, indicating that a system or DOS command is to be executed.
DOS environment variables reside in the portion of memory allocated as "environment": in Windows 95, this space should be dynamically allocated (see Installing PC A/I 3.5.1 in Windows 95 for details).