PowerAda Using Expressions

From OC Systems Wiki!
Jump to: navigation, search

Structured statements and numerous debugger commands use expressions. An expression can be any Ada expression that is legal at the current location within the program, with certain restrictions and extensions.

Expression Restrictions:

  1. Only a restricted set of attributes is available:

    Array'first(Dimension) -- for
    Array'last(Dimension) -- multidimensional
    Arraylength(Dimension) -- arrays

  2. Type'Attribute is not supported by the debugger.

  3. A delayed-substitution debugger variable cannot be used in an expression that is the condition of a structured statement. For example:

    if $command_count = 5 then
    -- $command_count does not work
    -- because it is not evaluated
    -- until command execution

  4. An immediate debugger variable can be used in a conditional expression:

    if command_count = 5 then
    -- evaluated at command entry time if !command_count = 5 then
    -- evaluated at command entry time

Expression Extensions:

  1. The debugger can work with static data, or constants, wherever they are located. Global objects in the bodies of other packages can be referred to. For example, if a variable SPEED is declared globally in the body of package WIND_MGR, it can be used in an expression in the context of the body of package DISTANCES:

    if distances.cur_wind_speed > wind_mgr.speed then

  2. The debugger can read an out parameter and assign it to a variable if it had a value:

    Debug 14> source 5..7
    5: procedure Convert(Num : in Digit_Integer;
    6: ASCII : out Five_Char_String) is
    7: Ascii_String : Five_Char_String;
    Debug 15> break 25; continue
    25> ASCII := Ascii_String;
    Breakpoint encountered at 25, sec/diction (convert)
    Debug 16> ? ASCII -- read an out parameter
    ASCII => "seven"

Defining New Debugger Variables: DECLARE

Debugger variables are defined using the DECLARE command. Its syntax is:

declare Variable[,Variable]...

where Variable is the name of the variable you want to declare. The debugger displays an error message if any of the variables already exists; otherwise, it creates and assigns a null value to each variable in the list.

Some examples are:

declare my_variable
declare a,b,c,d

Getting Text from the Keyboard: GET_LINE

The GET_LINE command reads a line of text from the keyboard and stores it in the specified debugger variable. Its syntax is:

get_line Variable

where Variable is a previously declared debugger variable. For example, the following script commands read in a value for the debugger variable, UPPER_BOUND:

declare upper_bound
get_line upper_bound

Assigning an Environment Variable: IMPORT

The IMPORT command Assigns the value of an environment variable to a debugger variable

import Variable [from String]

where Variable specifies the debugger variable to set and String specifies the name of the environment variable to import.

The IMPORT command copies the value of an environment variable into a debugger variable. This is most useful for including system information, such as the names of file directories, in debugger log files. For example:

import some_variable
   -- Assumes this environment variable is set
import ada_directory from "USER"

You can find explanations of predefined environment variables in the AIX documentation for parameter substitution in the shell interpreters.

Displaying Text on the Terminal: PUT, PUT_LINE

These commands operate much like the TEXT_IO subprogram s of the same names. They are primarily useful for interactive macros that prompt for input from the keyboard. The syntax of these commands is:

put Expression
put_line Expression

where Expression is an Ada expression. PUT or PUT_LINE evaluates the expression and displays the results on the terminal. If the expression evaluates to a type other than character or string, the command displays an image of the result. PUT_LINE differs from PUT by including a new line (carriage return) after the text is displayed. For example, the following macro reads a value into the variable NEWSEED.

declare newseed
macro seedmac is
put "Enter new seed value:  "
get_line newseed
put_line newseed
end seedmac

Removing Debugger Variables: UNDECLARE

The UNDECLARE command removes the definitions of the listed variables. Its syntax is:

undeclare Variable[,Variable]...

where Variable is a debugger variable. Certain variables the debugger uses internally (for example, PROMPT) cannot be removed. Some examples are:

undeclare my_variable
undeclare a,b,c,d

Displaying Variables: ?

This command displays information related to a particular object. Object represents the name of the object whose characteristics you want to display. Generally, this object can be represented as anything that is allowed on the left side of an Ada assignment statement at the current location within the program.

The various forms of syntax for the command are:

?  Object
? [CompilationUnit.]Object
?  Object'size
?  Object'address
?  Object:layout
?  Object:type
?  Array'first
?  Array'last
?  Array'length
? [function_name {"(" [parameters] ")"}

where Object is the name of the object that is to be displayed. Object can be a program value such as a variable, an array, a record, or an access type. It can also be the name of a debugger variable. Certain restrictions apply; for example you cannot display the value that would be returned by a function call.

If Object is a simple object (an object that is not qualified with the dot notation), the debugger resolves the object referenced by using the name Object, the current source location, and Ada's visibility rules. A debugger variable will hide a program object of the same name unless a qualified name is used to denote the object.

If Object is a qualified object and the display request is made within the scope of the corresponding object's declaration, the referenced object is displayed, whether it is directly visible or not. Such objects are displayed using either positional or named aggregate notation.

If Object is an indexed or selected component, only information relating to the specified component is displayed.

The table below summarizes the forms of syntax for the display command. More information is provided in the paragraphs following the table.

Syntax Action Examples


Displays the value of the specified object. In this case, Object can also be the name of a debugger variable. The value of an object is displayed in a format that is suitable for its type. Scalars are displayed in

(approximately) the notation used by 'IMAGE for the type.

?Object'size Displays the number of bits allocated to hold the object.
?Object'address Displays the address of the first storage unit allocated to the object.
?Object:layout Displays the location, the bit level mapping, and the alignment of the object.
?Object:type Displays the source lines containing the declaration of the type of Object specified.
?Array'first ?Array'last ?Array'length Displays the specified attributes of the array.

Displaying Simple Variables:

The first example from the table asks for the value of a local variable INDEX. The second uses a qualified name to ask for the value of the variable COUNT, which is located in the subprogram or package EVENT_MANAGER. The third asks for entry number INDEX in the array COUNT, which is in the RECORD_NAME variable defined in package PACKAGE_NAME.


Displaying Objects and Selected Components:

The debugger can display both full objects and selected components of an object (such as fields of records and elements of arrays). The following is an example of object and component selection within the record TEXT.

type Text is
    Value: String(1..5);
       Size : Natural;
    end record;
My_String : Text := ("Hello",5);

You can get a display of the value of the entire record by using the command


or of the value of MY_STRING.VALUE by using:


Displaying the Sizes and Machine Addresses of Variables:

The debugger can display the sizes and machine addresses of variables or of objects referenced by pointers. For a variable, use:

       -- or --

For example, you can get a display of the address of the variable DENSITY by using the command:


Displaying Access Objects and Their Referents:

To display the address of an object referenced by an access type, enter:


This displays the value of the access object, which is the same as the address of the referenced object. The value is shown in hexadecimal notation. To display the referenced object, use the .ALL selector. For example, given the following definitions,

type Int_Reference is access Integer;
Int : Int_Reference;

you can display the address of the integer referenced by using the command:


You can display the integer referenced by INT (equal to the value of the access object INT) by using the .ALL selector:


Displaying Linked Data Structures:

The debugger can display interior elements of linked data structures, such as linked lists and trees. For example, the commands:


display the first, second, and third records in a linked list of records. Using qualified names in this way to identify links to new nodes, you can traverse a tree or a linked list to display the value of each node.

Displaying the Result of a Function Call

The ? command can be used to execute a function within the program being debugged. The syntax for the function call is analogous to the syntax for the INVOKE command. For example, given the following function declaration,

function Elapsed_Time (Last : Integer) return Integer;

? can be used to execute the procedure as follows:

? Elapsed_Time(0)

? can also be used to execute simple desk-calculator style functions, as follows:

? 25680/16

Changing Values of Variables: :=

The ":=" command is used to change the value of program and debugger local variables; it behaves like the Ada assignment operator.

The syntax of the command is:

Object := Expression

where Object is the name of the variable whose value ("expression") you want to change.

Here is an example of a debug session where the user changes the value of the variable LIGHT_IS_ON:

Debug 1> run
  Program Ready
Debug 2> source 10-18
  11=  Light_Is_On: boolean := true;
  12:  --
  13:  -- Boolean control of light switch.
  14:  --
  16=  task type Filter_Prime is
  17:   entry Init (Prime,Row,Column : integer);
  18:   entry Take_A_Number(Candidate : integer);
Debug 3> br 11
  Breakpoint set at 11,sec/sieve (sieve)
Debug 4> br 16
  Breakpoint set at 16,sec/sieve (sieve)
Debug 5> cont
  Breakpoint encountered at 11,sec/sieve (sieve)
  11>  Light_Is_On: boolean := true;
Debug 6> cont
  Breakpoint encountered at 16,sec/sieve (sieve)
  16>  task type Filter_Prime is
Debug 7> light_is_on:=false
Debug 8> cont

Debugger variables can be assigned strings of any length. The values of certain debugger variables, such as TIME and COMMAND_COUNT, have special meaning and cannot be changed. For more information on debugger variables, refer to "Manipulating Debugger and Program Variables". Generally, you can change the value of any variable that the Ada program itself could change at that point in execution. Ada rules determine whether the attempted assignment is allowed. For example, it is not permitted in Ada, and in the debugger, to attempt to change a field of a record subordinate to a discriminant if that discriminant does not contain the proper value. It is also not permitted to attempt to assign a value to an array element outside the bounds of an array.

If a variable cannot be modified, its value is left unchanged; no exceptions are raised in the program. If the value of a variable has changed, that value remains in effect until the program changes it again, you change it again, or the variable's scope is exited.

Warning: If you change an Ada string variable to a string of greater length than declared, the full length of the new string will be written into memory, possibly changing the current value of other variables. To determine the declared length of a string, you can examine the Ada source line where the string is declared. You can also use the size attribute, 'SIZE, and divide the reported size by 8 to determine the length.