The first script tutorial showed how to write a basic script. This tutorial discusses how execute statements and delcarations can be organized. It also discusses how scripts can evolve and grow under SparForte.
Structuring a Script
Suppose you want to write a script that does something useful, such as email someone with a "bob" login when there are files waiting in a certain directory. In SparForte, the following commands can do the job:
num_files : integer := numerics.value( `ls -1 incomingdir | wc -l;` );
But consider the following questions:
SparForte scripts can be more than a list of commands. SparForte has a number of features that allow scripts to be "well-structured" (or modular). Well-structured scripts are easier to read and debug. Here's an example of a well-structured SparForte script:
The first part of this script is called the header. The header defines what kind of script this is, who wrote it, what version it is, and what restrictions or SparForte pragmas will apply to this script.
The very first line of a script is the header line. This line begins with a "#!" at the top of the script, flush with the left margin. This character combination identifies the kind of script. UNIX-based O/S uses this information to start the right program to run the script. For SparForte scripts, this line contains the absolute pathname to where the SparForte shell resides. On many systems, this will be /usr/local/bin/bush.
If you don't know the location of the SparForte shell, use the "whereis" command to find it:
=> whereis spar
The header line is followed by annotations describing the purpose of the script and who wrote it. This is important in case your script needs to be debugged in an emergency situation. The help command can read the annotations in scripts.
=> help checkfiles
The main script is wrapped in a procedure statement. The procedure statement divides the script into two sections: declaring variables and commands to run. Putting all the declarations for a script in one place makes it easy for someone to refer to them while reading the script.
The commands are declared as command variables. A command variable is a special SparForte variable type: when a command variable is declared, SparForte verifies that the command exists and that it can be run. If the command cannot be run, SparForte stops the script before any command are executed.
Without command variables, SparForte searches several directories for the command you want to run. If it can't find it, the script will stop with an error after executing part of the script. In this circumstance, it is difficult to determine where the script left off and what needs to be done to continue. Instead, command variables and other "sanity checks" should be put at the top of the script, or in the variable declarations, to ensure that when the script fails because of these kind of errors that the system will be left in a consistent state.
After the main portion of the script runs (the part that does the actual work), the script should clean up after itself. Any open files should be closed or deleted and the script should return a status code to the person or program running the script. In this case, there are no files to clean up. All that is necessary is the set_exit_status command( 0 ) which indicates that the script ran successfully.
A subprogram is a piece of a program that is given a name.
Subprograms can be functions,
routines that return a value for an expression, or procedures that stand alone. A SparForte script
itself can be contained in a main procedure.
In this example, "Bottles" is the main procedure for the script. Variable declarations are placed between "is" and "begin" (in this case, there are none). Between the "begin" and "end" are the executable statements that the script will run.
Procedures and Functions
Additional procedures and functions can be declared in declared in
the declaration section of the procedure.
There is another kind of subprogram, a declare block, that is discussed in the reference section.
The trace command will show each line of a script as SparForte reads it.
There are two pragmas for debugging. pragma assert tests for a condition and stops the script if the condition is false. pragma debug will run a backquoted command. This debugging statements only run if SparForte is in debugging mode with the --debug option (or pragma debug with no parameters). With these pragmas, you won't need to remove or comment out your debugging statements and risk changing your script's behavior.
ten : integer := double( 5 );
To perform more complex debugging, SparForte has a built-in debugger called the breakout mode. Using the breakout mode, you can stop a script at specific points, examine values and more. You can find out more about using the debugger in another tutorial.
See the Debugging Tutorial for more info
Standards Compliance and Portability
SparForte scripts can be copied or moved to other tools such as GCC (for binary applications), JGNAT (JVM applications) or A# (.Net applets). Although tools like GCC understand most AdaScript features, they have no knowledge of Bourne shell commands or features only available on SparForte. The more commands, pipes and other shell features you use, the more difficult it will be to port your scripts to other tools. At the same time, these special features make writing scripts easier.
GCC, JGNAT, A# and SparForte are all designed for compatibility with ISO-standard Ada. If your source code needs to be portable, use pragma ada_95. This pragma will disallow most of the Bourne shell features and will make your script as compatible as possible with the ISO-standard Ada language. This does not mean that your script can no longer perform its job but you may have to rewrite the parts of your script using Ada-friendly features. For example, you will no longer be able to use the "?" command, a SparForte-specific feature, but you can rewrite "?" commands to use put_line which is supported by GCC and other Ada- based tools. You lose the convenience of some features but gain source code reusability without a major rewrite of your work.
To further improve the portability of the script, you can turn off unnecessary features with pragma restriction. For example, pragma restriction( no_external_commands ) will prevent any external operating system commands from running.
The final script looks like this.
-- math.sp: do some simple math
Retiring a Script
When a script becomes obsolete, use
(or depreciated) to specify name of the new
script which makes the current script obsolete. The old script
will continue to run but when it completes a warning message will
announce that the script is obsolete and SparForte will give the name of the
new script. In this way, old scripts can continue to run as
programmers slowly upgrade to the new script.
|Back To Top|