Chapter Contents |
Previous |
Next |
Debugger PROFILEs, Configuration Files, and EXECs |
See Setting Up a Debugger PROFILE for information about the use of the debugger PROFILE, a feature of the debugger in which a CLIST or an EXEC is passed automatically to the debugger for execution when the debugger is invoked.
address 'CDEBUG'
There is no restriction against mixing CLISTs and REXX EXECs. A program of either type can call one of the other type. While a REXX EXEC is active, attention interrupts are trapped by the EXEC and not by the debugger. See exec (TSO) for additional information about executing CLISTs and EXECs under TSO.
Under CMS, the EXEC must be written in REXX or EXEC2 and have filetype CDEBUG. See exec (TSO) for additional information about executing EXECs under CMS.
Command Considerations |
The auto keyword of the transfer
command also supports exececho
. See transfer for additional
information.
Return Codes |
You can design a CLIST or EXEC to test the value of a global variable that contains the previous condition code that is passed back from the debugger. Global Variables That Contain Condition Code Values lists global variables that can be checked for condition code values.
Command Language | Global Variable |
---|---|
CLIST | &LASTCC |
EXEC | rc |
EXEC2 | &RC |
SAS/C Debugger commands set the return codes that are listed in Return Codes Set by Debugger Commands. The column labeled "Successful" shows the return code passed back to a CLIST if the debugger command is executed. The column labeled "Unsuccessful" shows the code that is passed if the debugger command is not executed.
In Return Codes Set by Debugger Commands * indicates the request number is returned, even if there is unrecognized text after a valid command.
Example REXX EXEC Application |
The first listing, BTREE, is a program that generates a binary tree. When it is run under the control of the debugger, it opens up a Termin window in which you can type several data lines. The program inserts the lines in a binary tree and then performs an in-order traversal, printing the data lines in sorted order.
Note:
Since the input is stdin
, you could type some lines in a file
and redirect stdin
to the file.
However, typing the lines from the Termin window is simpler.
The second listing, DUMPTREE,
is a REXX EXEC that can be used to display
the nodes of the binary tree that is created by BTREE.
#include <stdlib.h> #include <string.h> #include <stdio.h> typedef struct TREENODE { size_t length; char *value; struct TREENODE *left, *right; } TreeNode; static TreeNode *alloc_TreeNode(size_t, const char *); static void insert_TreeNode(TreeNode *, size_t, const char *); static void print_Tree(TreeNode *); void main(void) { TreeNode *tree = NULL; char io_buffer[258]; fgets(io_buffer, 256, stdin); while (!feof(stdin) && !ferror(stdin)) { size_t length = strlen(io_buffer) - 1; if (io_buffer[length] != '\ n') { printf("String \ "%.40s \ " is too long.\ n", io_buffer); exit(8); } if (tree == NULL) tree = alloc_TreeNode(length, io_buffer); else insert_TreeNode(tree, length, io_buffer); fgets(io_buffer, 256, stdin); } if (ferror(stdin)) { puts("Error reading input file."); exit(8); } print_Tree(tree); exit(0); } static void insert_TreeNode(TreeNode *root, size_t length, const char *string) { int cmp; cmp = memcmp(string, root->value, min(length, root->length)); if (cmp == 0) cmp = length - root->length; if (cmp > 0) { if (root->left != NULL) insert_TreeNode(root->left, length, string); else root->left = alloc_TreeNode(length, string); } else if (cmp < 0) { if (root->right != NULL) insert_TreeNode(root->right, length, string); else root->right = alloc_TreeNode(length, string); } else return; } static void print_Tree(TreeNode *root) { if (root->right != NULL) print_Tree(root->right); printf("%.*s\ n", root->length, root->value); if (root->left != NULL) print_Tree(root->left); } static TreeNode *alloc_TreeNode(size_t length, const char *string) { TreeNode *new; char *val; new = malloc(sizeof(TreeNode)); if (new == NULL || (val = malloc(length)) == NULL) { puts("Can't allocate a new node"); exit(8); } memcpy(val, string, length); new->length = length; new->value = val; new->left = new->right = NULL; return new; }
'/* REXX */' trace ?r /* Use "trace o to turn off tracing */ address 'CDEBUG' parse arg root if root = '' then do 'DBLOG DUMPTREE Error: root name not specified.' exit 4 end signal on error 'TRANSFER ROOT_TYPE TYPEOF' root 'TRANSFER ROOT_PTR VALUE' root call dump root_ptr, root_type exit 0 error: 'DBLOG DUMPTREE Error: debugger command at line' sigl 'failed.' exit 4 dump: procedure parse arg root_ptr, root_type 'TRANSFER RIGHT_PTR VALUE (('root_type')'root_ptr')->right' if right_ptr ¬ = '0p00000000' then call dump right_ptr, root_type 'TRANSFER LENGTH VALUE (('root_type')'root_ptr')->length' 'TRANSFER STRING STR (('root_type')'root_ptr')->value,' length 'DBLOG DUMPTREE:' string 'TRANSFER LEFT_PTR VALUE (('root_type')'root_ptr')->left' if left_ptr ¬ = '0p00000000' then call dump left_ptr, root_type return
break
command
to set a breakpoint at the entry to the print_Tree
function.
go
command
in order to start program execution.
Y
in the EOF: field of the Termin window in order to signal the end of
the file.
print_Tree
breakpoint, use the exec
or %
command to execute the DUMPTREE EXEC.
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.