While working in Prism, there are circumstances in which you may want to write expressions that Prism will evaluate. For example, you can print or display expressions, and you can specify an expression as a condition under which an action is to take place. You can write these expressions in the language of the program you are working on. This section discusses additional aspects of writing expressions.
Multiple variables and procedures can have the same name in a program. This can be a problem when you specify a variable or procedure in an expression. To determine which variable or procedure you mean, Prism tries to resolve its name by using these rules:
It first tries to resolve the name using the scope of the current function. For example, if you use the name x and there is a variable named x in the current function or the current file, Prism uses that x. The current function is ordinarily the function at the program's current stopping point, but you can change this. See " Choosing the Current File and Function".
If this fails to resolve the name, Prism goes up the call stack and tries to find the name in the caller of the current function, then its caller, and so on, following the scoping and visibility rules of the current language.
If no match is found in any routine active on the stack, Prism searches the static and global name spaces. If no match is found, Prism prints an error.
If the name is not found in the call stack, Prism arbitrarily chooses one of the variables or procedures with the name in the source code. When Prism prints out the information, it adds a message of the form "[using qualified name]". Qualified names are discussed below.
Issue the which command to find out which variable or procedure Prism would choose; the command displays the fully qualified name, as described below.
You can override Prism's procedure for resolving names by qualifying the name.
A fully qualified name starts with a back-quotation mark (`). The symbol farthest to the left in the name is the load object, followed optionally by the file, followed optionally by the procedure, followed by the variable name. Each is preceded by a backquote (`). Examples of Prism's identifier syntax are shown in Table 2-4.
Table 2-4 Prism Identifier Syntax
Syntax |
Description |
---|---|
a |
Specifies the variable a in the current scope. An error will be reported if no variable a exists in the current scope. |
`a |
Specifies the variable a in the global scope. |
``a |
Specifies the variable a in the global or file-static scope. |
`foo.c`a |
Specifies the variable a in file foo.c. |
`foo.c`foo`a |
Specifies the a in the procedure foo in the file foo. |
`foo`a |
Specifies the variable a in function foo (if foo is active). |
`a.out`foo.c`foo`a |
Specifies the variable a in function foo in file foo.c in load object a.out. |
`a.out`foo.c`foo:line`a |
Specifies the variable a in function foo at line number line in file foo.c in load object a.out. |
`foo.x`foo.cc`Bar::print:71`dummy |
Specifies the variable dummy in member function print of class Symbol at line number 71 in file foo.cc in load object foo.x. |
"foo.c":line |
Specifies the line number line in the file foo.c. Note the use of double quotes. |
Partially qualified names do not begin with `, but have a ` in them. For example,
foo`a
In this case, Prism looks up the function name on the left first and picks the innermost symbol with that name that is visible from your current location. This is useful primarily in referring to variables in routines on the call stack.
Use the whereis command to display a list of all the fully qualified names that match the identifier you specify.
Prism assigns its own names (using the function:line syntax, where function is the function and line is the line number where the variable declaration appeared) to variables in local blocks of C code. This disambiguates variable names, in case you reuse a variable name in more than one of these local blocks.
When debugging Fortran, Prism attempts to be case-insensitive in interpreting names, but will use case to resolve ambiguities.
Prism supports the use of a subset of Fortran intrinsic functions in writing expressions; the intrinsics work for all languages that Prism supports, except as noted below.
The intrinsics, along with the supported arguments, are
ALL(logical array) - Determines whether all elements are true in a logical array. Works for Fortran only.
ANY(logical array) - Determines whether any elements are true in a logical array. Works for Fortran only.
CMPLX(numeric-arg, numeric-arg) - Converts the arguments to a complex number. If the intrinsic is applied to Fortran variables, the second argument must not be of type complex or double (double-precision complex).
COUNT(logical array) - Counts the number of true elements in a logical array. Works for Fortran only.
ILEN(I) - Returns one less than the length, in bits, of the two's-complement representation of an integer. If I is nonnegative, ILEN(I) has the value log2(I + 1); if I is negative, ILEN(I) has the value log2(-I).
The intrinsics can be either upper- or lowercase.
Prism handles arrays slightly differently from the way C handles them.
In a C program, if you have the declaration
int a[10];
and you use a in an expression, the type of a converts from "array of ints" to "pointer to int". Following the rules of C, therefore, a Prism command like
(prism) print a + 2
should print a hexadecimal pointer value. Instead, it prints two more than each element of a (that is, a[0] + 2, a[1] + 2, etc.). This allows you to do array operations and use visualizers on C arrays in Prism. (The print command and visualizers are discussed in Chapter 5, Visualizing Data.)
To get the C behavior, issue the command as follows:
(prism) print &a + 2
You can use Fortran 90 array-section syntax when specifying C arrays. This syntax is useful, for example, if you want to print the values of only a subset of the elements of an array. The syntax is:
(lower-bound: upper-bound: stride)
where
lower-bound is the lowest-numbered element you choose along a dimension; it defaults to 0.
upper-bound is the highest-numbered element you choose along the dimension; it defaults to the highest-numbered element for the dimension.
stride is the increment by which elements are chosen between the lower bound and upper bound; it defaults to 1.
You must enclose the values in parentheses (rather than brackets), as in Fortran. If your array is multidimensional, you must separate the dimension specifications with commas within the parentheses, once again as in Fortran.
For example, if you have this array:
int a[10][20];
then you can issue this command in Prism to print the values of elements 2-4 of the first dimension and 2-10 of the second dimension:
(prism) print a(2:4,2:10)
Prism provides expressions that you can use to detect NaNs (values that are "not a number") and infinities in your data. These expressions derive from the way NaNs and infinities are defined in the IEEE standard for floating-point arithmetic.
To find out if x is a NaN, use the expression:
(x .ne. x)
For example, if x is an array, issue the command
(prism) where (x .ne. x) print x
to print only the elements of x that are NaNs. (The print command is discussed in Chapter 5, Visualizing Data.)
Also, note that if there are NaNs in an array, the mean of the values in the array will be a NaN. (The mean is available via the Statistics selection in the Options menu of a visualizer--see Chapter 5, Visualizing Data.)
To find out if x is an infinity, use the expression:
(x * 0.0 .ne. 0.0)