Working with TLC Record Files
Tutorial Overview
Objective: Understand the structure of record files and learn how to parse them with TLC directives.
Open the Example:
openExample('simulinkcoder/AdviceAboutTLCTutorialsExample') cd('tlctutorial/guide')
In this tutorial you interpret a simple file of structured records with a series of TLC
scripts. You will learn how records are structured, and how TLC %assign
and %<>
token expansion directives are used to process them. In addition, the
tutorial illustrates loops using %foreach, and scoping using
%with.
The tutorial includes these steps, which you should follow sequentially:
Structure of Record Files — Some background and a simple example
Interpret Records — Presenting contents of the record file
Anatomy of a TLC Script — Deconstructing the presentation
Modify
read-guide.tlc— Experiment with TLCPass and Use a Parameter— Pass parameters from the command line to TLC files
Review
Structure of Record Files
The code generator compiles models into a structured form called a record file, referred
to as . Such compiled model files are
similar in syntax and organization to source model files, in that they contain a series of
hierarchically nested records of the formmodel.rtw
recordName {itemName itemValue}Item names are alphabetic. Item values can be strings or numbers. Numeric values can be scalars, vectors, or matrices. Curly braces set off the contents of each record, which may contain one or more items, delimited by space, tab, or return characters.
In a file, the top-level (first)
record’s name is model.rtwCompiledModel. Each block is represented by a subrecord
within it, identified by the block’s name. TLC can parse well-formed record files, as this
exercise illustrates.
The following listing is a valid record file that TLC can parse, although not one for which it can generate code. Comments are indicated by a pound sign (#):
#
# File: guide.rtw Illustrative record file, which can't be used by Simulink
# Note: string values MUST be in quotes
Top { # Outermost Record, called Top
Date "21-Aug-2008" # Name/Value pair named Top.Date
Employee { # Nested record within the Top record
FirstName "Arthur" # Alpha field Top.Employee.FirstName
LastName "Dent" # Alpha field Top.Employee.LastName
Overhead 1.78 # Numeric field Top.Employee.Overhead
PayRate 11.50 # Numeric field Top.Employee.PayRate
GrossRate 0.0 # Numeric Field Top.Employee.GrossRate
} # End of Employee record
NumProject 3 # Indicates length of following list
Project { # First list item, called Top.Project[0]
Name "Tea" # Alpha field Name, Top.Project[0].Name
Difficulty 3 # Numeric field Top.Project[0].Difficulty
} # End of first list item
Project { # Second list item, called Top.Project[1]
Name "Gillian" # Alpha field Name, Top.Project[1].Name
Difficulty 8 # Numeric field Top.Project[1].Difficulty
} # End of second list item
Project { # Third list item, called Top.Project[2]
Name "Zaphod" # Alpha field Name, Top.Project[2].Name
Difficulty 10 # Numeric field Top.Project[2].Difficulty
} # End of third list item
} # End of Top record and of fileAs long as programmers know the names of records and fields, and their expected contents, they can compose TLC statements to read, parse, and manipulate record file data.
Interpret Records
Here is the output from a TLC program script that reads guide.rtw,
interprets its records, manipulates field data, and formats descriptions, which are directed
to the MATLAB® Command Window:
Using TLC you can: * Directly access a field's value, e.g. %<Top.Date> -- evaluates to: "21-Aug-2008" * Assign contents of a field to a variable, e.g. "%assign worker = Top.Employee.FirstName" worker expands to Top.Employee.FirstName = "Arthur" * Concatenate string values, e.g. "%assign worker = worker + " " + Top.Employee.LastName" worker expands to worker + " " + Top.Employee.LastName = "Arthur Dent" * Perform arithmetic operations, e.g. "%assign wageCost = Top.Employee.PayRate * Top.Employee.Overhead" wageCost expands to Top.Employee.PayRate * Top.Employee.Overhead <- 11.5 * 1.78 = 20.47 * Put variables into a field, e.g. Top.Employee.GrossRate starts at 0.0 "%assign Top.Employee.GrossRate = wageCost" Top.Employee.GrossRate expands to wageCost = 20.47 * Index lists of values, e.g. "%assign projects = Top.Project[0].Name + ", " + Top.Project[1].Name..." "+ ", " + Top.Project[2].Name" projects expands to Top.Project[0].Name + ", " + Top.Project[1].Name + ", " + Top.Project[2].Name = Tea, Gillian, Zaphod * Traverse and manipulate list data via loops, e.g. - At top of Loop, Project = Tea; Difficulty = 3 - Bottom of Loop, i = 0; diffSum = 3.0 - At top of Loop, Project = Gillian; Difficulty = 8 - Bottom of Loop, i = 1; diffSum = 11.0 - At top of Loop, Project = Zaphod; Difficulty = 10 - Bottom of Loop, i = 2; diffSum = 21.0 Average Project Difficulty expands to diffSum / Top.NumProject = 21.0 / 3 = 7.0
This output from guide.rtw was produced by invoking TLC from the
MATLAB Command Window, executing a script called read-guide.tlc.
Do this yourself now, by following these steps:
In MATLAB, change folder (
cd) to your copy oftlctutorial/guidewithin your working folder.To produce the output just listed, process
guide.rtwwith the TLC scriptread-guide.tlcby typing the following command:tlc -v -r guide.rtw read-guide.tlc
Note command usage:
The
-rswitch (for read) identifies the input data file, in this caseguide.rtw.The TLC script handling the data file is specified by the last token typed.
The
-vswitch (for verbose) directs output to the command window, unless the TLC file handles this itself.
Anatomy of a TLC Script
You now dissect the script you just ran. Each “paragraph” of output from
guide.tlc is discussed in sequence in the following brief
sections:
Coding Conventions — Before you begin
File Header — Header info and a formatting directive
Token Expansion— Evaluating field and variable identifiers
General Assignment — Using the
%assigndirectiveString Processing Plus — Methods of assembling strings
Arithmetic Operations — Computations on fields and variables
Modify Records — Changing, copying, appending to records
Index Lists — Referencing list elements with subscripts
Loop Over Lists — Details on loop construction and behavior
Coding Conventions
These are some basic TLC syntax and coding conventions:
%% Comment
| TLC comment, which is not output |
/* comment */
| Comment, to be output |
%keyword
| TLC directive (keyword), start with
“%” |
%<expr> | TLC token operator |
. (period) | Scoping operator, for example, Top.Lev2.Lev3 |
... (at end-of-line) | Statement continuation (line break is not output) |
\ (at end-of-line) | Statement continuation (line break is output) |
localvarIdentifier
| Local variables start in lowercase |
GlobalvarIdentifier
| Global variables start in uppercase |
RecordIdentifier
| Record identifiers start in uppercase |
EXISTS()
| TLC built-in functions are named in uppercase Note: TLC identifiers are case-sensitive. |
For further information, see TLC Coding Conventions.
File Header
The file read-guide.tlc begins with:
%% File: read-guide.tlc (This line is a TLC Comment, and will not print) %% %% To execute this file, type: tlc -v -r guide.rtw read-guide.tlc %% Set format for displaying real values (default is "EXPONENTIAL") %realformat "CONCISE"
Lines 1 through 4 — Text on a line following the characters
%%is treated as a comment (ignored, not interpreted or output).Line 5 — As explained in the text of the fourth line, is the TLC directive (keyword)
%realformat, which controls how subsequent floating-point numbers are formatted when displayed in output. Here we want to minimize the digits displayed.
Token Expansion
The first section of output is produced by the script lines:
Using TLC you can: * Directly access a field's value, e.g. %assign td = "%" + "<Top.Date>" %<td> -- evaluates to: "%<Top.Date>"
Lines 1 and 2 — (and lines that contain no TLC directives or tokens) are simply echoed to the output stream, including leading and trailing spaces.
Line 3 — Creates a variable named
tdand assigns the string value%<Top.Date>to it. The%assigndirective creates new and modifies existing variables. Its general syntax is:The optional double colon prefix specifies that the variable being assigned to is a global variable. In its absence, TLC creates or modifies a local variable in the current scope.%assign ::variable = expression
Line 4 — Displays
The preceding line enables TLC to print%<Top.Date> -- evaluates to:
%<Top.Date>without expanding it. It constructs the string by pasting together two literals.As discussed in String Processing Plus, the plus operator concatenates strings as and adds numbers, vectors, matrices, and records.%assign td = "%" + "<Top.Date>"
Line 5 — Evaluates (expands) the record
Top.Date. More precisely, it evaluates the fieldDatewhich exists in scopeTop. The syntax%<expr>causes expressionexpr(which can be a record, a variable, or a function) to be evaluated. This operation is sometimes referred to as an eval.
Note
You cannot nest the %<expr> operator (that is,
%<foo%<bar>> is not allowed).
Note
When you use the %<expr> operator within quotation marks,
for example, "%<Top.Date>", TLC expands the expression and then
encloses the result in quotation marks. However, placing %assign
within quotation marks, for example, "%assign foo = 3", simply echoes
the statement enclosed in quotation marks to the output stream.
No assignment results (the value of foo
remains unchanged or undefined).
General Assignment
The second section of output is produced by the script lines:
* Assign contents of a field to a variable, e.g. %assign worker = Top.Employee.FirstName "%assign worker = Top.Employee.FirstName" worker expands to Top.Employee.FirstName = %<worker>
Line 1 — Echoed to output.
Line 2 — An assignment of field
FirstNamein theTop.Employeerecord scope to a new local variable calledworker.Line 3 — Repeats the previous statement, producing output by enclosing it in quotation marks.
Line 4 — Explains the following assignment and illustrates the token expansion. The token
%<worker>expands toArthur.
String Processing Plus
The next section of the script illustrates string concatenation, one of the uses of
the “+” operator:
* Concatenate string values, e.g. %assign worker = worker + " " + Top.Employee.LastName "%assign worker = worker + " " + Top.Employee.LastName" worker expands to worker + " " + Top.Employee.LastName = "%<worker>"
Line 1 — Echoed to output.
Line 2 — Performs the concatenation.
Line 3 — Echoes line 2 to the output.
Line 4 — Describes the operation, in which a variable is concatenated to a field separated by a space character. An alternative way to do this, without using the
+operator, isThe alternative method uses evals of fields and is equally efficient.%assign worker = "%<Top.Employee.FirstName> %<Top.Employee.LastName>"
The + operator, which is associative, also works for numeric types,
vectors, matrices, and records:
Numeric Types — Add two expressions together; both operands must be numeric. For example:
Output:* Numeric Type example, e.g. Top.Employee.PayRate = %<Top.Employee.PayRate> Top.Employee.Overhead = %<Top.Employee.Overhead> %assign td = Top.Employee.PayRate + Top.Employee.GrossRate td = Top.Employee.PayRate + Top.Employee.Overhead td evaluates to %<td>
* Numeric Type example, e.g. Top.Employee.PayRate = 11.5 Top.Employee.Overhead = 1.78 td = Top.Employee.PayRate + Top.Employee.Overhead td evaluates to 13.28
Vectors — If the first argument is a vector and the second is a scalar value, TLC appends the scalar value to the vector. For example:
Output:* Vector example, e.g. %assign v1 = [0, 1, 2, 3] v1 is %<v1> %assign tp1d = Top.Project[1].Difficulty Top.Project[1].Difficulty is %<tp1d> %assign v2 = v1 + tp1d v2 = v1 + Top.Project[1].Difficulty v2 evaluates to: %<v2>
* Vector example, e.g. v1 is [0, 1, 2, 3] Top.Project[1].Difficulty is 8 v2 = v1 + Top.Project[1].Difficulty v2 evaluates to: [0, 1, 2, 3, 8]
Matrices — If the first argument is a matrix and the second is a vector of the same column-width as the matrix, TLC appends the vector as another row to the matrix. For example:
Output:* Matrices example, e.g. %assign mx1 = [[4, 5, 6, 7]; [8, 9, 10, 11]] mx1 is %<mx1> v1 is %<v1> %assign mx = mx1 + v1 mx = mx1 + v1 mx evaluates to %<mx>
* Matrices example, e.g. mx1 is [ [4, 5, 6, 7]; [8, 9, 10, 11] ] v1 is [0, 1, 2, 3] mx = mx1 + v1 mx evaluates to [ [4, 5, 6, 7]; [8, 9, 10, 11]; [0, 1, 2, 3] ]
Records — If the first argument is a record, TLC adds the second argument as a parameter identifier (with its current value). For example:
Output:* Record example, e.g. %assign StartDate = "August 28, 2008" StartDate is %<StartDate> %assign tsd = Top + StartDate Top + StartDate Top.StartDate evaluates to %<Top.StartDate>
* Record example, e.g. StartDate is August 28, 2008 Top + StartDate Top.StartDate evaluates to August 28, 2008
Arithmetic Operations
TLC provides a full complement of arithmetic operators for numeric data. In the next portion of our TLC script, two numeric fields are multiplied:
* Perform arithmetic operations, e.g. %assign wageCost = Top.Employee.PayRate * Top.Employee.Overhead "%assign wageCost = Top.Employee.PayRate * Top.Employee.Overhead" wageCost expands to Top.Employee.PayRate * Top.Employee.Overhead ... <- %<Top.Employee.PayRate> * %<Top.Employee.Overhead> = %<wageCost>
Line 1 — Echoed to output.
Line 2 —
%assignstatement that computes the value, which TLC stores in local variablewageCost.Line 3 — Echoes the operation in line 2.
Lines 4 and 5 — Compose a single statement. The ellipsis (typed as three consecutive periods, for example,
...) signals that a statement is continued on the following line, but if the statement has output, TLC does not insert a line break. To continue a statement and insert a line break, replace the ellipsis with a backslash (\).
Modify Records
Once read into memory, you can modify and manipulate records just like variables you
create by assignment. The next segment of read-guide.tlc replaces the
value of record field Top.Employee.GrossRate:
* Put variables into a field, e.g. %assign Top.Employee.GrossRate = wageCost "%assign Top.Employee.GrossRate = wageCost" Top.Employee.GrossRate expands to wageCost = %<Top.Employee.GrossRate>
Such changes to records are nonpersistent (because record files are inputs to TLC; other file types, such as C source code, are outputs), but can be useful.
You can use several TLC directives besides %assign to modify
records:
%createrecord | Creates new top-level records, and might also specify subrecords within them, including name/value pairs. |
%addtorecord | Adds fields to an existing record. The new fields can be name/value pairs or aliases to existing records. |
%mergerecord | Combines one or more records. The first record contains itself plus copies of the other records' contents specified by the command, in sequence. |
%copyrecord | Creates a new record as %createrecord does, except the
components of the record come from the existing record you specify. |
%undef var | Removes (deletes) var (a variable or a record) from scope.
If var is a field in a record, TLC removes the field from the
record. If var is a record array (list), TLC removes the first
element of the array; the remaining elements remain accessible. You can remove
only records you create with %createrecord or
%copyrecord. |
See Target Language Compiler Directives for details on these directives.
Index Lists
Record files can contain lists, or sequences of records having the same identifier.
Our example contains a list of three records identified as Project
within the Top scope. List references are indexed, numbered from 0, in
the order in which they appear in the record file. Here is TLC code that compiles data
from the Name field of the Project list:
* Index lists of values, e.g. %assign projects = Top.Project[0].Name + ", " + Top.Project[1].Name... + ", " + Top.Project[2].Name "%assign projects = Top.Project[0].Name + ", " + Top.Project[1].Name..." "+ ", " + Top.Project[2].Name" projects expands to Top.Project[0].Name + ", " + Top.Project[1].Name + ", " + Top.Project[2].Name = %<projects>
The Scope.Record[n].Field syntax is similar to that used in C to
reference elements in an array of structures.
While explicit indexing, such as the above, is perfectly acceptable, it is often preferable to use a loop construct when traversing entire lists, as shown in Loop Over Lists.
Loop Over Lists
By convention, the section of a record file that a list occupies is preceded by a
record that indicates how many list elements are present. In
files, such parameters are
declared as model.rtwNum, where
Ident is the identifier used for records
in the list that follows. In Identguide.rtw, the Project
list looks like this:
NumProject 3 # Indicates length of following list
Project { # First list item, called Top.Project[0]
Name "Tea" # Alpha field Name, Top.Project[0].Name
Difficulty 3 # Numeric field Top.Project[0].Difficulty
} # End of first list item
Project { # Second list item, called Top.Project[1]
Name "Gillian" # Alpha field Name, Top.Project[1].Name
Difficulty 8 # Numeric field Top.Project[1].Difficulty
} # End of second list item
Project { # Third list item, called Top.Project[2]
Name "Zaphod" # Alpha field Name, Top.Project[2].Name
Difficulty 10 # Numeric field Top.Project[2].Difficulty
} # End of third list itemThus, the value of NumProject describes how many
Project records occur.
Note
model.rtw files might also contain records that start with
Num but are not list-size parameters. TLC does not require that
list size parameters start with Num. Therefore you need to be
cautious when interpreting Num record
identifiers. The built-in TLC function IdentSIZE() can determine the
number of records in a specified scope, hence the length of a list.
The last segment of read-guide.tlc uses a
%foreach loop, controlled by the NumProject
parameter, to iterate the Project list and manipulate its values.
* Traverse and manipulate list data via loops, e.g. %assign diffSum = 0.0 %foreach i = Top.NumProject - At top of Loop, Project = %<Top.Project[i].Name>; Difficulty =... %<Top.Project[i].Difficulty> %assign diffSum = diffSum + Top.Project[i].Difficulty - Bottom of Loop, i = %<i>; diffSum = %<diffSum> %endforeach %assign avgDiff = diffSum / Top.NumProject Average Project Difficulty expands to diffSum / Top.NumProject = %<diffSum> ... / %<Top.NumProject> = %<avgDiff>
As you may recall, the TLC output looks like this:
* Traverse and manipulate list data via loops, e.g. - At top of Loop, Project = Tea; Difficulty = 3 - Bottom of Loop, i = 0; diffSum = 3.0 - At top of Loop, Project = Gillian; Difficulty = 8 - Bottom of Loop, i = 1; diffSum = 11.0 - At top of Loop, Project = Zaphod; Difficulty = 10 - Bottom of Loop, i = 2; diffSum = 21.0 Average Project Difficulty expands to diffSum / Top.NumProjects = 21.0 / 3 = 7.0
diffSum, a
%foreach loop is entered, with variable i declared
as the loop counter, iterating up to NumProject. The scope of the loop
is all statements encountered until the corresponding
%endforeach is reached (%foreach loops may be
nested).Note
Loop iterations implicitly start at zero and range to one less than the index that specifies the upper bound. The loop index is local to the loop body.
Modify read-guide.tlc
Now that you have studied read-guide.tlc, it is time to modify it.
This exercise introduces two important TLC facilities, file control and
scoping control. You implement both within the
read-guide.tlc script.
File Control Basics
TLC scripts almost invariably produce output in the form of streams of characters.
Output is normally directed to one or more buffers and files, collectively called
streams. So far, you have directed output from
read-guide.tlc to the MATLAB Command Window because you included the -v switch on the
command line. Prove this by omitting -v when you run
read-guide.tlc. Type
tlc -r guide.rtw read-guide.tlc
Nothing appears to happen. In fact, the script was executed, but output was directed to a null device (sometimes called the “bit bucket”).
There is one active output file, even if it is null. To specify, open, and close files, use the following TLC directives:
%openfile streamid ="filename" , "mode" %closefile streamid %selectfile streamid
If you do not give a file name, subsequent output flows to the memory buffer named by
streamid. If you do not specify a mode, TLC opens the file for
writing and deletes any existing content (subject to
system-level file protection mechanisms). Valid mode identifiers are a
(append) and w (write, the default). Enclose these characters in
quotes.
The %openfile directive creates a file/buffer (in
w mode), or opens an existing one (in a mode).
Note the required equal sign for file specification. Multiple streams can be open for
writing, but only one can be active at one time. To switch output streams, use the
%selectfile directive. You do not need to close files until you are
done with them.
The default output stream, which you can respecify with the stream ID
NULL_FILE, is null. Another built-in stream is
STDOUT. When activated using %selectfile,
STDOUT directs output to the MATLAB Command Window.
Note
The streams NULL_FILE and STDOUT are
always open. Specifying them with
%openfile generates errors. Use %selectfile to
activate them.
The directive %closefile closes the current output file or buffer.
Until an %openfile or a %selectfile directive is
encountered, output goes to the previously opened stream (or, if
none exists, to null). Use %selectfile to
designate an open stream for reading or writing. In practice, many TLC scripts write
pieces of output data to separate buffers, which are then selected in a sequence and their
contents spooled to one or more files.
Implement Output File Control
In your tlctutorial/guide folder, find the file
read-guide-file-src.tlc. The supplied version of this file contains
comments and three lines of text added. Edit this file to implement output file control,
as follows:
Open
read-guide-file-src.tlcin your text editor.Save the file as
read-guide-file.tlc.Note five comment lines that begin with
%% ->.Under each of these comments, insert a TLC directive as indicated.
Save the edited file as
read-guide-file.tlc.Execute
read-guide-file.tlcwith the following command:tlc -r guide.rtw read-guide-file.tlc
If you succeeded, TLC creates the file
guidetext.txtwhich contains the expected output, and the MATLAB Command Window displays*** Output being directed to file: guidetext.txt *** We're almost done . . . *** Processing completed.
If you did not see these messages, or if a text file was not produced, review the
material and try again. If problems persist, inspect
read-guide-file.tlc in the guide/solutions
subfolder to see how you should specify file control.
Scope Basics
Structure of Record Files explains the hierarchical organization of records.
Each record exists within a scope defined by the records in which it is nested. The
example file, guide.rtw, contains the following scopes:
Top Top.Employee Top.Project[0] Top.Project[1] Top.Project[2]
To refer to a field or a record, specify its scoping, even if
no other context that contains the identifier exists. For
example, in guide.rtw, the field FirstName exists
only in the scope Top.Employee. You must refer to it as
Top.Employee.FirstName whenever accessing it.
When models present scopes that are deeply nested, this can lead to extremely long identifiers that are tedious and error prone to type. For example:
CompiledModel.BlockOutputs.BlockOutput.ReusedBlockOutput
This identifier has a scope that is long and has similar item names that you could easily enter incorrectly.
The %with/%endwith directive eases the burden of coding TLC scripts
and clarifies their flow of control. The syntax is
%with RecordName [TLC statements] %endwith
Every %with is eventually followed by an
%endwith, and these pairs might be nested (but not overlapping). If
RecordName is below the top level, you need not include the top-level
scope in its description. For example, to make the current scope of
guide.rtw
Top.Employee, you can specify
%with Employee [TLC statements] %endwith
Naturally, %with Top.Employee is also valid syntax. Once bracketed
by %with/%endwith, record identifiers in TLC statements do not require
you to specify their outer scope. However, note the following conditions :
You can access records outside of the current
%withscope, but you must qualify them fully (for example, using record name and fields).Whenever you make assignments to records inside a
%withdirective, you must qualify them fully.
Change Scope Using %with
In the last segment of this exercise, you modify the TLC script by adding a
%with/%endwith directive. You also need to edit record identifier
names (but not those of local variables) to account for the changes of scope resulting
from the %with directives.
Open the TLC script
read-guide-scope-src.tlcin the text editor.Save the file as
read-guide-scope.tlc.Note comment lines that commence with
%% ->.Under each of these comments, insert a TLC directive or modify statements already present, as indicated.
Save the edited file as
read-guide-scope.tlc.Execute
read-guide-scope.tlcwith the following command:tlc -v -r guide.rtw read-guide-scope.tlc
The output should be exactly the same as from read-guide.tlc,
except possibly for white space that you might have introduced by indenting sections of
code inside %with/%endwith or by eliminating blank lines.
Fully specifying a scope inside a %with context is not an error, it
is simply unnecessary. However, failing to fully specify its scope when assigning it to a
record (for example, %assign GrossRate = wageCost) is invalid.
If errors result from running the script, review the discussion of scoping above and
edit read-guide-scope.tlc to eliminate them. As a last resort, inspect
read-guide-scope.tlc in the /solutions subfolder
to see how you should have handled scoping in this exercise.
For additional information, see Variable Scoping.
Pass and Use a Parameter
You can use the TLC commands and built-in functions to pass parameters from the command
line to the TLC file being executed. The most general command switch is
-a, which assigns arbitrary variables. For example:
tlc -r input.rtw -avar=1 -afoo="abc" vars.tlc
The result of passing this pair of strings via -a is the same as
declaring and initializing local variables in the file being executed (here,
vars.tlc). For example:
%assign var = 1 %assign foo = "abc"
You do not need to declare such variables in the TLC file, and they are available for
use when set with -a. However, errors result if the code assigns
undeclared variables that you do not specify with the -a switch when
invoking the file. Also note that (in contrast to the -r switch) a space
should not separate -a from the parameter you are declaring.
In the final section of this tutorial, you use the built-in function
GET_COMMAND_SWITCH() to print the name of the record file being used in
the TLC script, and provide a parameter to control whether or not the code is suppressed. By
default the code is executed, but is suppressed if the command line contains
-alist=0:
Open the TLC script
read-guide-param-src.tlcin your text editor.Save the file as
read-guide-param.tlc.To enable your program to access the input filename from the command line, do the following:
Below the line
%selectfile STDOUT, add the line:%assign inputfile = GET_COMMAND_SWITCH ("r")The
%assigndirective declares and sets variables. In this instance, it holds a string filename identifier.GET_COMMAND_SWITCH()returns whatever string argument follows a specified TLC command switch. You must use UPPERCASE for built-in function names.Change the line “
*** WORKING WITH RECORDFILE” to read as follows:*** WORKING WITH RECORDFILE %<inputfile>
To control whether or not a section of TLC code is executed, do the following:
Below the line “
%assign inputfile = GET_COMMAND_SWITCH ("r")”, add:The program checks whether a list parameter has been declared, via the intrinsic (built-in) function%if (!EXISTS(list)) %assign list = 1 %endif
EXISTS(). If no list variable exists, the program assigns one. This defineslistand by default its value isTRUE.Enclose lines of code within an
%ifblock.%if (list) * Assign contents of a field to a variable, e.g. %assign worker = FirstName "%assign worker = FirstName" worker expands to FirstName = %<worker> %endifNow the code to assign
workeris sent to the output only whenlistisTRUE.Save
read-guide-param.tlc.
Execute
read-guide-param.tlcand examine the output, using the commandtlc -r guide.rtw read-guide-param.tlc
This yields
*** WORKING WITH RECORDFILE [guide.rtw] * Assign contents of a field to a variable, e.g. "%assign worker = FirstName" worker expands to FirstName = Arthur ***ENDExecute
read-guide-param.tlcwith the command:tlc -r guide.rtw -alist=0 read-guide-param.tlc
With the
-alist=0switch, the output displays only the information outside of theifstatement.*** WORKING WITH RECORDFILE [guide.rtw] ***END
Review
The preceding exercises examined the structure of record files, and expanded on how to use TLC directives. The following TLC directives are commonly used in TLC scripts (see Target Language Compiler Directives for detailed descriptions):
%addincludepath | Enable TLC to find included files. |
%addtorecord | Add fields to existing record. New fields can be name/value pairs or aliases to existing records. |
%assign | Create or modify variables. |
%copyrecord | Create new record and, if applicable, specify subrecords within them, including name/value pairs. The components of the record come from the existing record specified. |
%createrecord | Create new top-level records and, if applicable, specify subrecords within them, including name/value pairs. |
%foreach/%endforeach | Iterate loop variable from 0 to upper limit. |
%if/%endif | Control whether code is executed, as in C. |
%include | Insert one file into another, as in C. |
%mergerecord | Combine one or more records. The first record contains itself plus copies of the other records contents specified by the command, in sequence. |
%selectfile | Direct outputs to a stream or file. |
%undef var | Remove (delete) var (a variable or a record) from scope. If
var is a field in a record, TLC removes the field from the
record. If var is a record array (list), TLC removes the first
element of the array; the remaining elements remain accessible. Only records created
via %createrecord or %copyrecord can be
removed. |
%with/%endwith | Add scope to simplify referencing blocks. |