SAS/C Development System User's Guide Volume 2: Debugger, Utilities, Assembler Version 6.0 SAS Institute Inc. SAS Campus Drive Cary, NC 27513 The correct bibliographic citation for this manual is as follows: SAS Institute Inc., SAS/C Development System User's Guide, Volume 2: Debugger, Utilities, Assembler, Version 6.0, Cary, NC: SAS Institute Inc., 1992. 363 pp. SAS/C Development System User's Guide, Volume 2: Debugger, Utilities, Assembler, Version 6.0 Copyright 1992 by SAS Institute Inc., Cary, NC, USA. ISBN 1-55544-497-0 All rights reserved. Printed in the United States of America. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, or otherwise, without the prior written permission of the publisher, SAS Institute Inc. 1st printing, June 1992 The SAS System is an integrated system of software providing complete control over data access, management, analysis, and presentation. Base SAS software is the foundation of the SAS System. Products within the SAS System include SAS/ACCESS, SAS/AF, SAS/ASSIST, SAS/CPE, SAS/DMI, SAS/ETS, SAS/FSP, SAS/GRAPH, SAS/IML, SAS/IMS-DL/I, SAS/OR, SAS/QC, SAS/REPLAY-CICS, SAS/SHARE, SAS/STAT, SAS/CALC, SAS/CONNECT, SAS/DB2, SAS/EIS, SAS/ENGLISH, SAS/INSIGHT, SAS/LAB; SAS/LOOKUP, SAS/NVISION, SAS/PH-Clinical, SAS/SQL-DS, SAS/TOOLKIT, and SAS/TUTOR software. Other SAS Institute products are SYSTEM 2000 Data Management Software, with basic SYSTEM 2000, CREATE, Multi-User, QueX, Screen Writer, and CICS interface software; NeoVisuals software; JMP, JMP IN, and JMP Serve software; SAS/RTERM software; and the SAS/CI Compiler and the SAS/CX Compiler. MultiVendor Architecture and MVA are trademarks of SAS Institute Inc. SAS Institute also offers SAS Consulting and On-Site Ambassador services. SAS Communications, SAS Training, SAS Views, the SASware Ballot, and Observations are published by SAS Institute Inc. All trademarks above are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. (r) indicates USA registration. The Institute is a private company devoted to the support and further development of its software and related services. Amiga Includes and Development Tools Version 2.0 Copyright (c) 1990 Commodore-Amiga, Inc. All rights reserved. Amiga Workbench Version 2.0 Copyright (c) 1988, 1990 Commodore-Amiga, Inc. All rights reserved. Installer Copyright(c) 1991-1992 Commodore-Amiga, Inc. All rights reserved. AmigaGuide and WDisplay Copyright(c) 1991-1992 Commodore-Amiga, Inc. All rights reserved. Distributed under license from Commodore. Amiga, AmigaDOS, Workbench, and AmigaGuide are registered trademarks or trademarks of Commodore-Amiga, Inc. Commodore is a registered trademark or trademark of Commodore Electronics Limited. Other brand and product names are registered trademarks or trademarks of their respective companies. Doc S17, Ver212.0, 062492 Contents vii Reference Aids ix Credits xi Acknowledgments xiii Using This Book Part 1 Using the SAS/C Debugger Page 3 Chapter 1 Introduction to CodeProbe 3 Introduction 4 CodeProbe Overview 9 Compiling and Linking Your Program 9 Running CodeProbe 12 CodeProbe Windowing Interface 16 Entering Commands 25 Chapter 2 Sample CodeProbe Session 25 Introduction 25 A Walk through a Typical Application 35 Chapter 3 Debugging Your Program 35 Introduction 37 Sample Program 1 39 Controlling Program Execution 53 Sample Program 2 57 Examining Data and Data Structures 73 Chapter 4 Setting Up the Debugging Environment 73 Introduction 77 Determining Source File Location 78 Choosing Command-line Options 81 CodeProbe Initialization 82 Setting and Showing Options within CodeProbe 89 Customizing Dialog Window Commands 95 Chapter 5 Working in Cross-Development Mode 95 Introduction 95 Why Debug in Cross-Development Mode? 96 Using the Cross Debugger iv Contents 101 Chapter 6 Using AREXX Macros with CodeProbe 101 The AREXX Interface 101 Macros Provided by CodeProbe 102 Invoking Macros 103 Values Returned from CodeProbe Commands 105 Chapter 7 Debugging Resident Libraries 105 Introduction 105 Setting Breakpoints 106 The symload Command 106 The libraries.cpr AREXX Macro 106 Cautions 106 Limitations 106 Example 107 Chapter 8 Debugging Multitasking Programs 107 Introduction 108 Types of Tasks 108 How CodeProbe Handles Tasks 109 Commands Used to Control Tasks 113 Design Considerations for Debugger Compatibility 115 Chapter 9 Commands and Built-in Functions 115 Introduction 115 CodeProbe Commands 118 Special Parameters 126 Command Reference 202 Built-in Functions 203 Built-in Function Reference Part 2 Using the SAS/C Utilities 215 Chapter 10 Utility Reference Part 3 Using the SAS/C Macro Assembler 299 Chapter 11 Using Assembly Language with C Language 299 Introduction 300 Writing Assembly Language Functions 314 Communicating between Assembly Language and C Language 323 Running the Assembler v Contents Part 4 Using the SAS/C opeimizer 329 Chapter 12 Optimizing Your Code 329 Introduction 329 The Global Optimizer 334 The Peephole Optimizer 334 Running the Optimizers Part 5 Appendix 341 Appendix diff File-Matching Algorithm 343 Index vi vii Reference Aids Displays 12 1.1 Initial CodeProbe Screen 13 1.2 CodeProbe Windows 28 2.1 Source Window Showing Mixed Mode 28 2.2 Source Window Showing Assembly Mode Figures 275 10.1 Example File Dependencies 317 11.1 The Stack after the func Module Is Called Tables 17 1.1 Command Line Editing Functions 18 1.2 Escape Sequences in Character Strings 19 1.3 Escape Sequences in Commands 20 1.4 Pull-down Menu Items 23 1.5 Function and Special Keys 24 1.6 Menu Accelerator Keys viii ix Credits Software The SAS/C Development System is designed, built, and tested through the combined effort of many people at SAS Institute. The AmigaDOS development group includes the following individuals: Principal Steve Krueger, Douglas Walker, Michael S. Developers Whitcher Testing and Twilah K. Blevins, Jim Cooper, Bob Patten, Technical Khristi Tomlinson Support These individuals continue to support future development of the SAS/C Development System. Others who have contributed to the SAS/C Development System are as follows: Development Edmund Burnette, Dave Frederick, Russell Gonsalves, Tony Hefner, loe Hutchinsoll, Glenn Musial, John Roth Testing and Alan R. Beale, John W. Gillikin, Charles Tudor Technical Support Documentation Composition Candy R. Farrell, Denise T. Jones, Pamela A. Troutman Graphic Design Creative Services Department Proofreading Patsy P. Blessis, Heather B. Dees, Laurie J. Medley, Karen A. Olander, Josephine P. Pope, Christian Schwoerke, Susan E. Willard Technical Review Elizabeth Brownrigg, Edmund Burnette, Jim Cooper, Steve Krueger, Johll Roth, Khristi Tomlinson, Douglas Walker, Michael S. Whitcher Writing and Jeanne Ferneyhough, Hanna lIicks, Keith Wagner, Editing Steve Krueger, Douglas Walker, Helen Weeks, Khristi Tomlinsorl x xi Acknowledgments Many people make significant and continuing contributions to the development of the SAS/C Development System. First among them is John A. Toebes VIII, who was instrumental in the development of Versions 4.0 and 5.0 and who directed the early development of Version 6.0. Others who have contributed to the development and testing of Version 6.0 of the SAS/C Development System include Ralph Babel, Bruce M. Drake, Nathan S. Fish, Maximilian Hantsch, Randell Jesup, David N. Junod, Andrew Kopp, Martin J. Laubach, Christian Ludwig, Andrew N. Mercier, Mike Meyer, Larry Rosenman, Carolyn Scheppner, Steve Shireman, Michael Sinz, Martin Taillefer, Steve Tibbett, John Wiederhirn, Loren Wilton, and Kenneth Yarnall. The final responsibility for the SAS/C Development System lies with SAS Institute alone. We hope that you will always let us know your feelings about our product and its documentation. It is through such communication that the progress of SAS software continues to be accomplished. Not to mention the two pirates who spent hours of their own time reproducing this document. Mikey The Bad & Deicide still live! xii xiii Using This Book Purpose SAS/C Development System User's Guide, Volume II: Debugger, Utilities, Assembler describes how to use some of the major tools available to the SAS/C programmer under AmigaDOS: the debugger, the macro assembler, the optimizer, and the various utilities that are part of the SAS/C Development System. "Using This Book" describes how you can best use this book. It describes the book's intended audience, the audience's prerequisite knowledge, the book's organization and its conventions, and additional documentation that is available to you. Audience The information in this book is written for experienced C programmers. This book assumes you have a working knowledge of the C language and the AmigaDOS operating system. To use the SAS/C Macro Assembler, you also need a working knowledge of assembly language. For a list of publications you can use to learn the C language or the AmigaDOS operating system, refer to the "Additional Documentation" section at the end of "Using This Book." How to Use This Book This section gives an overview of the book's organization and content. The book's chapters are described, followed by a section on how to use each chapter. Organization SAS/C Development System User's Guide, Volume II: Debugger, Utilities, Assembler is divided into four parts plus an appendix; the chapters contained in each part and the appendix are described here: Part 1: Using the SAS/C Debugger Part 1 contains nine chapters that discuss CodeProbe and how to use it to debug your program. Chapter 1, "Introduction to CodeProbe" explains what CodeProbe does, how it works, and what tasks are involved in debugging a program. This chapter also describes how to compile and link your program under CodeProbe control. xiv Using This Book Chapter 2, "Sample CodeProbe Session" contains a brief sample session using the lines.c program in the sc:examples drawer. You can follow this sample session to gain experience with the most commonly used debugger commands. Chapter 3, "Debugging Your Program" describes the CodeProbe commands most frequently used for stepping through your program, displaying code and data, and modifying code or data. Chapter 4, "Setting Up the Debugging Environment" describes the commands and options you can use to customize the environment in which you debug your program. Chapter 5, "Working in Cross-Development Mode" describes how to run your executable code from a serially- connected Amiga system. Chapter 6, "Using AREXX Macros with CodeProbe" describes how to use AREXX macros from inside CodeProbe. This chapter contains a list of valid AREXX commands. Chapter 7, "Debugging Resident Libraries" describes how to use CodeProbe to debug resident libraries. Chapter 8, "Debugging Multitasking Programs" describes how to use CodeProbe with applications that spawn additional tasks. Chapter 9, "Commands and Built In Functions" describes each CodeProbe command and built-in function in detail. Part 2: Using the SAS/C Utilities Part 2 contains only one chapter. This chapter discusses the SAS/C utilities. Chapter 10, "Utility Reference" describes each of the utilities (such as smake, scopts, and tb) provided by the SAS/C Development System. Part 3: Using the SAS/C Macro Assembler Part 3 contains only one chapter. This chapter discusses how to use assembly language with C language. Chapter 11, "Using Assembly Language with C Language" describes how to communicate between C language and the assembler. You can incorporate assembler routines as part of your C program or call C functions from assembly language. xv Using This Book Part 4: Using the SAS/C Optimizer Part 4 contains only one chapter. This chapter discusses how to use the SAS/C Optimizer. Chapter 12, "Optimizing Your Code" describes what the global and peephole optimizers do and how to run the optimizers during compilation. The appendix, "diff File-Matching Algorithm," describes the algorithm used by the diff utility to compare files. What you should read. The following table points you to specific chapters in this book for information on particular topics. For other references, refer to "Additional Documentation" later in this section. For information on You should read compiling, linking, and running your program Chapters 1 and 4 under the debugger using the most common debugger commands Chapters 2 and 3 customizing your debugging environment Chapter 4 running your program on one machine and Chapter 5 debugging it on another machine using AREXX macros Chapter 6 debugging resident libraries Chapter 7 debugging multitasking programs Chapter 8 Conventions This section covers the typographical and syntax conventions used in this book. Typographical Conventions The SAS/C books for AmigaDOS use special fonts to depict specific Conventions types of information. These typographical conventions are as follows: roman is the basic type style used for most text. monospace is used to show example statements or programs. Monospace is used also for items specific to the xvi Using this Book C language, such as the names of functions, header files, and keywords. obligue is used for arguments or variables whose values are supplied by the user; for example, you should enter an appropriate filename when you see filename. italic is used for terms that are defined. Italic is also used to indicate arguments for which you supply a value. Syntax Conventions This book uses the following conventions for syntax: monospace indicates commands, keywords, and switches that should be spelled exactly as shown. These arguments may or may not be optional, depending on whether they are enclosed in square brackets. italic indicates arguments for which you supply a value. [] indicate an optional argument when they surround the (square argument. brackets) . . . (ellipsis) indicates that you can repeat the argument or group of arguments preceding the ellipsis any number of times. | means to choose one item from a group of items (vertical bar) separated by the bars. The following example illustrates these syntax conventions: env [function | integer] env is a command name, so it appears in monospace type. function is a function for which you supply the name, so it appears in italic type. [function | integer] are both optional, so they are enclosed in square brackets. function | integer indicates that you can specify only one of the items separated by the vertical bar. xvii Using This Book Additional Documentation The following sections list documentation you may find helpful in using the SAS/C Development System. SAS Documentation If you are interested in SAS documentation, you need to contact the Book Sales department by writing to the following address or by calling the following number: SAS Institute Inc Book Sales Department SAS Campus Drive Cary, NC 27513 919-677-8000 SAS/C Development System This book is part of a set of publications for the SAS/C Development System. There are three other publications in the set: SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor describes how to install the SAS/C Development System on your Amiga system use your development environment create files in the editor compile and link C files. SAS/C Development System Library Reference describes how to access libraries create your own libraries use header files to reduce the amount of time and space required by your program. SAS/C Development System Quick Reference, Version 6.0 contains reference tables for the library functions, compiler and linker options, and debugger commands. These volumes are sold together as a set. You can order them by specifying order #A56l85. Other Documentation The following sections list additional reference material specific to the C language, Amiga and AmigaDOS programrning, and the Motorola 68xxx microprocessor. xviii Using This Book C Language The following books describe the C programming language: American National Standards Committee (1990), American National Standard for Information Systems--Programming Language C, Document Number X3J11/90-013, Washington, D.C.: X3 Secretariat: Computer and Business Equipment Manufacturers Association. Harbison, Samuel P. and Steele, Guy L., Jr. (1990), C: A Reference Manual, Third Edition, Englewood Cliffs, NJ: Prentice-Hall, Inc. Kernighan, Brian W. and Ritchie, Dennis M. (1988), The C Programming Language, Second Edition, Englewood Cliffs, NJ: Prentice-Hall, Inc. Amiga and AmigaDOS The following books provide information specifically about programming on the Amiga system. Most of the examples in these books are written in the C or assembler languages. Commodore-Amiga, Inc. (1991), Amiga Hardware Reference Manual, 3rd Edition, Reading, MA: Addison-Wesley Publishing Company. Commodore-Amiga, Inc. (1991), Amiga ROM Kernal Reference Manual: Devices, 3rd Edition, Reading, MA: Addison-Wesley Publishing Company. Commodore-Amiga, Inc. (1991), Amiga ROM Kernal Reference Manual: Includes and Autodocs, 3rd Edition, Reading, MA: Addison-Wesley Publishing Company. Commodore-Amiga, Inc. (1991), Amiga User Interface Style Guide, Reading, MA: Addison-Wesley Publishing Company. Commodore-Amiga, Inc. (1991), The AmigaDOS Manual, 3rd Edition, New York, NY: Bantam Books. Commodore-Amiga, Inc. (1992), Amiga ROM Kernal Reference Manual: Libraries, 3rd Edition, Reading, MA: Addison-Wesley Publishing Company. Motorola 68xxx The following books contain information specifically about programming the Motorola 68xxx microprocessor. Motorola, Inc. (1987), MC68881/MC68882 Floating-Point Coprocessor User's Manual, First Edition, Englewood Cliffs, NJ: Prentice-Hall, Inc. Motorola, Inc. (1989), MC68030 Enhanced 32-Bit Microprocessor User's Manual, Second Edition, Englewood Cliffs, NJ: Prentice-Hall, Inc. Motorola, Inc. (1989), Programmer's Reference Manual, Phoenix, AZ: Motorola Literature Distribution. xix Using This Book Contacting CATS You can contact Commodore Application and Technical Support at the following address: 1200 Wilson Drive West Chester, PA 19380 215-429-0643 1 Part 1 Using the SAS/C Debugger Chapters 1 Introduction to CodeProbe 2 Sample CodeProbe Session 3 Debugging Your Program 4 Setting Up the Debugging Environment S Working in Cross-Development Mode 6 Using AREXX Macros with CodeProbe 7 Debugging Resident Libraries 8 Debugging Multitasking Programs 9 Commands and Built-in Functions 2 3 1 Introduction to CodeProbe 3 Introduction 4 CodeProbe Overview 4 Basic Features 4 Multitasking Features S Summary of Changes and Enhancements for Version 6.0 of the CodeProbe Debugger 5 Terminology 7 How CodeProbe Works 9 Compiling and Linking Your Program 9 Running CodeProbe 9 The cpr Command 10 The quit Command 10 Workbench Support 11 Line Mode 12 CodeProbe Windowing Interface 12 Screen Layout 14 CodeProbe Windows 16 Entering Commands 16 Command Line 20 Pull-Down Menus 22 Function and Special Keys 23 Menu Accelerator Keys Introduction CodeProbe is a powerful source-level debugger that enables you to monitor, line by line, the behavior of programs written in C language, assembly language, or a combination of the two. CodeProbe has many useful features and commands designed to aid you in tracking down your program's problems. Some of these aids provide the ability to examine and modify variables, address and data registers, and user- specified memory locations. CodeProbe gives you absolute control over the execution of your program by enabling you to stop execution at any point. It also enables you to examine both the C source and the (Throughout this manual, the terms CodeProbe and the debugger are used interchallgeably to refer to this debugger program.) 4 Chapter 1 assembler generated for your program at the same time so you can see what is really occurring at the assembly language level. This chapter explains what CodeProbe does, how it works, and what is involved in debugging a program. CodeProbe Overview CodeProbe implements a number of commands and features specifically designed to ease the debugging of C programs. In addition to a command-line interface, the debugger provides you with a sophisticated, screen-oriented interface where you can take advantage of multiple windows and pull-down menus. Shortcuts that are built into the program enable you to issue commands with a couple of keystrokes or mouse clicks. Basic Features As a source-level debugger, CodeProbe allows you to single-step through programs either in C source code or the generated assembler code set breakpoints on C source lines, or an individual assembly language statement continue program execution until a specified function or line number is reached, or until a variable contains a specified value or its value changes examine variables and code at the C language level display C data types--including structures, unions, arrays, enums, typedefs, and bit fields--in their C formats display memory dumps in a variety of formats continuously watch any C variable, array element, or structure member assign a value to a C variable fill an area of memory copy one C array or structure to another copy a string from one place to another view and manipulate register data access storage classes of data, including automatic, static, and register as well as external. Multitasking Features CodeProbe allows you to debug multitasking programs. Any new tasks or processes created by a program that is being debugged are automatically under debugger control. The following multitasking features are provided: Breakpoints can be set and trapped for any task generated under debugger control. 5 Introduction to CodeProbe The state of any task in a multitasking application can be displayed including the stack and registers. Tasks can be started and stopped selectively. Tasks that are executing independently of the debugger can be intercepted and attached to the debugger. This can be useful if a process enters an infinite loop or waits indefinitely on a message port. Summary of Changes and Enhancements for Version 6.0 of CodeProbe Debugger The following changes and enhancements are introduced with Version 6.0 of the CodeProbe debugger: Cross debugger support IS provided via the serial port or a communications network. Debugging of shared libraries and devices has been simplified. C expression parsing is allowed with most debugger commands. The ability to display ranges within arrays is provided. The alias and define commands provide greater flexibility. 68881 floating-point registers are supported. Motorola fast floating-point format (ffp) display is provided. The env and where commands enable you to look back up the function call chain. The args command displays arguments to the current function. More compact debugging format saves space on disk. The AmigaDos Version 2.0 look and feel is provided, including public screens and three-dimensional look. The call command enables you to call application functions directly from the debugger. The source command enables you to specify the new name of a source file. The symbol, shell, and window commands have been added. Calls, Modules, and Memory windows have been added. Enhanced AREXX support is provided. Cross-referenced online help is provided in a separate window. The log command provides a Dialog window command logging capability. The jump command provides the ability to change the current location. Terminology This book frequently uses terms that you may not be familiar with. The following definitions are new or have unique meanings to the CodeProbe documentation: breakpoint is an address used to control program execution. Program execution is suspended when the breakpoint address is reached. 6 Chapter 1 call frame is the stack area associated with a function's formal parameters, automatic variables, temporaries, saved registers, and the return address. There is one call frame per function invocation. cross-debugging is a debugging technique that uses two machines that are linked together. CodeProbe runs on one machine, and the application runs on the other. (See host machine and target machine later in this list.) environment in CodeProbe documentation, environment means the state of the machine. The state of the machine consists of the contents of memory, the contents of the registers, the contents of the stack, and the point of execution in the source code. The run environment is the actual environment at which you are stopped. The user environment is the last environment set with the env command. This environment is used when displaying registers and variables. It is reset to the run environment after a go command or any of the commands that step the program. host machine when cross-debugging, the host machine is the machine that is used to display the CodeProbe user interface. The actual debugging session takes place on this machine. (See cross-debugging earlier in this list.) image is an executable program, an AmigaDOS shared library, or an AmigaDOS device. The name of the image is the same as the name of the disk file from which the image is loaded. An image can be specified with several CodeProbe commands as part of the location parameter. line boundary is the imaginary boundary in the machine code that specifies the end of the code generated for a C source line. log file is a file created by CodeProbe that contains details of all of the activity that occurred in the Dialog window. A log session can be turned off and on with the log command. By default, the log file is turned off. 7 Introduction to CodeProbe module is all code generated by a single C source file. The name of the module is the same as the name of the C source file that generated pass count is the number of times that a line has been executed. The after parameter is used with commands such as go and break to specify a pass count. symbol is a series of letters and numbers that specify a function, memory location, or a variable. target machine when cross-debugging, the target machine is the machine used to run the application. (See cross-debugging earlier in this list.) How CodeProbe Works CodeProbe requires debugging information to be present in the executable files before you can use most of its powerful debugging features. This means that if you want to run CodeProbe and view the C source file while it is running, you must compile that C source file with one of the debugging options, such as line, full, or symbol. The compiler will then include information in the executable files that will enable CodeProbe to reflect accurately the state of your application program in the Source window. The compiler supports several debugging options specifying the amount of debugging information that is passed on to the linker. The linker (slink) also allows you to add symbolic debugging information to modules compiled without debugging information or to strip all debugging information from the executable file. Refer to Chapter 4, "Setting Up the Debugging Environment," for a complete discussion of debugging options. When CodeProbe runs your program, it uses debugging information present in executable files to keep track of which C source lines correspond to which assembler instructions. When you specify one of the debug options to the compiler, the compiler generates debugging information in the form of H_DEBUG hunks that get placed into the object module for that source. The compiler can generate two different types of H_DEBUG hunks, line and symbolic. It also can vary the amount of information that goes into the symbolic H_DEBUG hunks based on the debug option. Hunks and H_DEBUG hunks are explained in Chapter 12, "How the Compiler Works," in the SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor. 8 Chapter 1 If you specify debug=line, then the compiler generates an H_DEBUG hunk that contains the source filename and a table of source line numbers to address offset pairs. CodeProbe uses this table to match up the line numbers for the source with the assembly instructions as your program is executing. In addition to debug=line, if you specify the addsym option to the linker (slink), then slink generates an H_SYMBOL hunk in the final executable file. The H_SYMBOL hunk contains a table of global symbols and their offsets into the data section. If you compile and link using the sc command, the addsym option is added automatically to the slink command line, provided that you specify any debug option except nodebug. Using the global symbol information, CodeProbe can locate the start of the symbol but not its size or type. CodeProbe assumes all such symbols are of type long. This feature can be useful if you are debugging large projects on small machines where there might not be enough memory to load symbolic debugging information. If you specify the debug=symbol or debug=full options to the compiler, then the compiler generates an H_DEBUG hunk containing high-level symbolic debugging information for the source. This includes information for external identifiers, information for structure or union tags and typedefs, local variables, and so on. CodeProbe searches this information when trying to display an item in C source mode. Controlling CodeProbe Among CodeProbe's controls are pull-down menus, Intuition-based windows, and mouse support. The debugger also has powerful commands that can be entered in the Dialog window. In addition, CodeProbe offers a number of special functions and keyboard shortcuts, including programmed function and menu accelerator keys to maximize efficiency. Debugging a Program Debugging a program using CodeProbe involves three basic steps: 1. Compile with debug information. (Use one of the debug= options with the sc command.) 2. Invoke the debugger. 3. Execute the program under debugger control. The next two sections of this chapter present the basic information you need to perform these steps. 9 Introduction to CodeProbe Compiling and Linking Your Program Before invoking CodeProbe you must compile and link your program as described in Chapter 8, "Compiling and Linking Your Program," of the SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor. The degree to which the debugger can access symbols defined in any module is determined by the compiler and linker options. Refer to Chapter 4, "Setting Up the Debugging Environment," to determine which options you need to use. In most cases, the debug=symbol flush option to the sc command specifies sufficient information to debug your program. A typical way to compile and link your program is with the following commands: sc debug=symbolflush link filename.c The sc command invokes the compiler, and debug=symbo 1 f lush (or debug=sf) causes the compiler to generate line number information, generate symbolic debugging information for variables in that module, and make sure those variables are flushed back to memory at line boundaries. The link option causes sc to invoke the linker. The addsym option is automatically passed to the linker because of the inclusion of a debug option. The addsym option forces slink to generate symbolic information for global symbols in libraries and for any file that does not have debug information. The filename.c argument specifies the source file. Running CodeProbe This section describes how to use the cpr command to invoke CodeProbe from the Shell use the quit command to stop the debugger at any time use CodeProbe to run applications from either a Shell or Workbench screen run CodeProbe as a line-mode debugger. The cpr Command The cpr command is invoked from a Shell to start CodeProbe for the first time during your debugging session. The cpr command uses the following syntax: cpr [cpr-options]application-name [application-arguments] 10 Chapter 1 The application-name and application-arguments parameters are determined by your application. You can specify any of the following cpr-options: -buffer -noprofile -wdialog -cli -screen -wregister -command -startup -wsource -i -w -wwatch -line -wb -cli Each of these options is discussed in the section "Choosing Command-line Options" in Chapter 4. When the cpr command is invoked, CodeProbe makes the following assumptions: The program specified on the command line exists in the current directory or somewhere on the command search path, as specified by the AmigaDOS path command. The modules making up the program to be debugged have been compiled with one or more of the debugging options discussed earlier and have been linked using the addsym option of the linker. Source files for modules that you will be accessing exist in either the current directory, your special source path list (as specified by the opt search command), or the directory in which the module was compiled. The quit Command The quit command can be issued from the Dialog window to stop the debugger at any time. However, you should allow your program to run to completion before using the quit command. While CodeProbe will attempt to do some cleanup for your program by calling the normal C exit routine, you should allow your program to do its own cleanup. Refer to Chapter 9 for more information about the quit command. Workbench Support CodeProbe can be run from the Amiga system's Workbench screen as well as from a Shell. Furthermore, CodeProbe itself can run applications in either a Shell or Workbench environment from either location. By default, CodeProbe runs its application in the same type of environment that invoked the debugger. 11 Introduction to CodeProbe The following options to the cpr command are used to change the default environment: -cli forces the application to run under the debugger as if it were invoked from a Shell. -wb forces the application to run under the debugger as if it were invoked from the Workbench screen. To facilitate debugging from the Workbench screen, a small stub tool called DEBUG can be placed in a project directory along with a corresponding tool icon. Both the tool and its icon may be found in the sc:starter_project drawer. DEBUG invokes CodeProbe and passes to it all Workbench startup messages. The SCSETUP utility automatically copies DEBUG and its icon into your project directories. To invoke CodeProbe from the Workbench screen, click once on the cpr or debug icon. Then, while holding down the Shift key, double- click on the icon for the application's executable. To set up CodeProbe command-line options, use the Workbench screen's Information menu item on the cpr or debug icon from the Workbench menu. Place the debugger command-line options in the ToolTypes field of the icon. The debugger will parse the options as if they were entered on the command line. The options may be placed on one ToolType edit line or they can be spread across several lines. To invoke CodeProbe on a program requiring command-line options, edit the debug icon the same way that you would edit it to set up CodeProbe command-line options. Add the -cli option as the last cpr option and follow it with the name of the executable file followed by its command-line options. By default debug invokes sc: c/cpr. If you rename or move cpr, DEBUG can find it if you assign the full pathname of the debugger to the environment variable sc/cprpath. This is done easily using the AmigaDOS setenv command as follows: setenv sc/cprpath pathname Line Mode You also can run CodeProbe as a line-mode debugger by starting it with the -line option. In line mode the debugger displays its output in the current Shell window. The -line option can be used to start the debugger from a remote Shell that has been started from an rlogin or from a Shell started across a serial line. For information about starting a Shell over a serial line, see the description of the AUX: device in The AmigaDOS Manual, 3rd Edition. 12 Chapter 1 CodeProbe Windowing Interface CodeProbe provides a sophisticated windowing interface with multiple windows and pull-down menus. Windows are used to issue debugger commands, to receive output from CodeProbe commands, or to browse through the source code for your program. Screen Layout CodeProbe starts with the Source and Dialog windows open, as shown in Display 1.1. (BUY THE PROGRAM!) 13 Introduction to CodeProbe Once CodeProbe is running, you can opell, close, move, and resize windows. Display 1.2 is a sample CodeProbe screen showing the following windows: Source window Dialog window Memory window Register window Watch window. 14 Chapter 1 CodeProbe Windows CodeProbe has 11 types of windows. You control the actual number of windows open during a debugging session. No matter how many windows are displayed, one of them will be the active window that is currently receiving, or waiting for, input. The title bar of the active window is highlighted (AmigaDOS Version 2.0 changes the color, and Version 1.3 ghosts the title bar when a window is not activated). The following list explains the function of each type of window: Calls window displays a stack traceback showing the calling sequence for the program being debugged. Each level of the traceback represents the state of the machine when a function was called. The state of the machine is also known as its environment. By double-clicking on a desired traceback entry in the Calls window, you can return CodeProbe to a previous environment. You will then see the code that was being executed at that time in the Source window, and you can see the contents of the registers as they were before the call in the Register window. The state of memory cannot be replicated for previous environments, so the Memory window reflects your current environment. A message is also displayed in the Dialog window informing you of your current location. As an example, suppose you have a main function that calls a function named s ort, which in turn calls a function named swap. When the execution of your program reaches the swap function, the calling sequence main, sort, swap is displayed in the Calls window. By double-clicking on the entry for the main function, you can return the machine to the state it was in when ma in called sort. You will see the source code that was executed and be able to view what was in the registers at the point at which ma in called sort; however, your program will still be executing at the same point in the swap function. Therefore, you can examine local variables, and they will have the values they had when main called sort, but global variables may have changed. If you single-step through the program, the code displayed in the Source window returns back to the last line executed in swap, and execution continues. Dialog window enables you to enter commands and review the results of those commands. Many of the same commands available through the pull- down menus can be invoked directly at the command line in the Dialog window. Help window displays help information for each of the CodeProbe commands as well as other selected topics. 15 Introduction to CodeProbe Input window automatically opens to request input for a task you are performing. Input windows allow you to enter data, such as selecting a value for the default number of lines to be displayed by the list command. You can exit out of an Input window without entering input by pressing the escape (Esc) key. Memory window displays a dump of memory in both character and hexadecimal format or disassembles code. Message window displays text passed to it by the wmsg command. Modules window displays a list of all the modules within the application program. Output window displays output that is directed to the terminal by your C program from functions such as printf. The Output window is the initial Shell if the program is run from the Shell, or the Shell Workbench window opened by the startup code otherwise. Register window displays the contents of the registers. This window is most useful to assembly-level programmers. It is also valuable for checking registerized variables defined in C source code. Once opened, it displays the current contents of all registers and the current values of the processor flags. Any registers that have been modified since the last breakpoint are highlighted. The Register window can be opened by pressing the F4 key. Source window displays the source code for the module currently being executed. As execution proceeds, the Source window is continually updated to reflect the current position. The Source window highlights the current position (the line about to be executed) and any breakpoints. Watch window watches and displays the value of variables. For installce, you can set a watch break such that the application will be stopped as SOOII as the watch variable changes value. The Watch window can be opened by pressing the Fl key. Opening Windows With the exceptions of the Input and Message windows, you can use the View menu to open any window. (See "Pull-Down Menus" later in 16 Chapter 1 this chapter.) Input windows open automatically when user input is required. The Message window is used to display messages from scripts and is opened automatically to display output from the wmsg command. The Help window can be opened with the Help icon or the help command, as well as from the menu. You can also use the window command to open any of the windows. Entering Commands You can issue debugger commands in several different ways. The methods of issuing commands are presented in the following order: entering commands from the Dialog window using pull-down menus to enter commands using special function keys to enter commands using menu accelerator keys to enter commands. Command Line The most flexible method of entering debugger commands is by typing them in at the command line of the Dialog window. The command line is marked by the > prompt. You can enter any of the debugger commands described in Chapter 9 in this manner. Command Syntax In order to understand the individual command descriptions, you must first understand the syntax conventions described in the "Using This Book" section. Command Name Shortcuts Command names need not be entered in their entirety. Generally, only the minimum number of characters necessary to uniquely identify a command is required. The Help menu, which is displayed in the Dialog window when you enter the help command, shows required keys in caps for command names while the rest are shown in lowercase. For example, RETurn in the Help menu indicates that only the first three letters of the command are required, but typing in return or retur would work also. The syntax conventions used in this book show the optional portion of a command in square brackets [ ]. Command-line Editing CodeProbe commands can be typed on the command line of the Dialog window in either uppercase or lowercase. The following command-line editing techniques are useful when entering commands in this manner. 17 Introduction to CodeProbe Determining Editing Modes The editing mode affects tne way characters are typed on the commarld line as well as the functioning of the numeric keypad. The current editing mode can be determined by examining the left end of the Dialog window's title bar. The first character in the title bar will be an I if in insert mode or C if in overwrite mode. When you are in insert mode, any characters you type on the command line are inserted between existing characters. Wherl you are in overwrite mode, any characters you type overwrite any existing characters. The Ins key on the numeric keypad is used to switch between insert and overwrite mode. (Use the zero key to switch between insert and overwrite modes on the A1000.) The second character in the title bar is always a slash (/), and the third character will be an F if tne numeric keypad is in functiorl mode or an N if in numeric mode. The keypad must be in functiorl mode to use the editing functions described in the next section. I o toggle between the numeric and function modes, press F10. Editing Function Keys Three control key sequences in function mode and the numeric keypad are used to perform command-line editing functions. In order to perform these functions you must be editing in function mode. Table 1.1 describes the command-line editing functions. Table 1. 1 Command Line Editing Functions Keys Description Ctrl X erases the current line Ctrl A toggles insert/overstrike Ctrl keypad-l erases from the cursor to the end of the line keypad-1 moves the cursor to the end of the line keypad-7 moves the cursor to the start of the line keypad-O starts inserting at the cursor keypad-. (Del) deletes the character urlder the cursor keypad-4 moves the cursor left one position keypad-6 moves the cursor right one position Shift keypad 4 moves the cursor left one word (continued) 18 Chapter 1 Table 1.1 (continued) Keys Description Shift keypad-6 moves the cursor right one word keypad-Enter sends the line to the program as input keypad-8 recalls the previous Dialog window command keypad-2 goes to the next Dialog window command keypad-9 (PgUp) moves the page up keypad-3 (PgDn) moves the page down Extending Commands across Lines A command line can extend across several input lines by ending all but the last line with a backslash (\) followed immediately by a carriage return. A command line can be up to 256 characters in length. Using Escape Characters There are three places where you might want to use escape characters: in character strings in character constants in commands. C character strings consist of text surrounded by double quotes (""). Standard C escapes starting with the backslash character are supported as shown in Table 1.2. Table 1.2 Escape Sequences in Character Strings Escape Sequence Meaning \n newline (0xOa) t tab (0xO9) b backspace (0x08) \r return (0xOd) \f form feed (0xOc) \v vertical tab (0xOb) \NNN octal constant (NNN is 3 octal digits.) \xNN hex constant (NN is 2 hexadecimal digits.) 19 Introduction to CodeProbe In a character string, a backslash followed by any other character will be interpreted as itself. Therefore, "\\" is a string consisting of a single backslash, and " a \ " b " is three characters long, an " a ", a double quote, and a "b". C character constants consist of a single character surrounded by single quotes (' '). The standard C escape sequences shown in Table 1.2 can be used with character constants. Escape characters also can be used in CodeProbe commands. Table 1.3 lists escape characters that can be used outside of character strings and constants. Table 1.3 Escape Sequences in Commands Escape Sequence Meaning \\ backslash \; command delimiter \, argument delimiter \" character string/constant delimiter \' constant delimiter/constant delimiter \( when or macro delimiters \) when or macro delimiters Outside of quotes, a backslash followed by any other character is not assigned any special meaning; it is interpreted as two distinct characters. Therefore, "b \mod\func" sets a breakpoint at function func of module mod, and not at a function called modfunc. Escape sequences are especially useful in the alias command, as in these examples: alias tb where;d x /* this is two commands */ alias tb where\;d x /* this is one command */ The first example runs an a 1 ias command followed by a display command; the second runs a single alias command. After executing the second example, tb is aliased to where;d x. Note, however, that these special escape sequences are not accepted in certain places that do not make sense. For example, you cannot use escape sequences in command and alias names. 20 Chapter 1 Pull-Down Menus The most common debugger activities can be performed by using pull- down menus. As with other Amiga applications, you use the right mouse button to control menu functions. CodeProbe has seven pull- down menus that enable you to enter commands. Table 1.4 lists the menu items along with their command-line equivalents. Table 1.4 Pull-down Menu Items Menu Item Command-line Equivalent File Menu Module list \module Line list [ line ] | [ address ] Find Current Line env Execute execute [ script-name ] Refresh Ctrl L Paste Quit quit Options Menu Source Mode opt source (c|asm|mixed) Radix Default opt radix ( hex | decimal) Context Lines opt context [integer] List Default opt list [integer] Unassemble Default opt unassemble [ integer] String Length opt strlen [ integer] Array Length opt arrdim [integer] Range Length opt rangelen [ integer] Autoswap Mode opt autoswap (on | off ) Echo Mode opt echo ( on | off ) (continued) 21 Introduction to CodeProbe Table 1.4 (continued) Menu Item Command-line Equivalent Instruction Bytes opt ibytes (on | off) Ignore Path opt ignorepath (on | off) Case Sensitivity opt case ( on | off) Maximum Bad Characters opt badchar [ integer] Step Into ResLib opt reslib ( on | off ) Catch New Devices opt devices ( on | off ) Catch New Tasks opt catch ( on | off ) View Menu Calls window calls Modules window modules Register window register Watch window watch Source window source Dialog window dialog Output window output Memory window memory Help window help Run Menu Trace Into trace Proceed Over proceed Go go Go Until go [ location ] Return return [ value ] Startstart [command line] Break Menu Set break [ location ] (continued) 22 Chapter 1 Table 1.4 (continued) Menu Item Command-line Equivalent List blist Clear bclear [arguments] Enable benable [arguments] Disable bdisable [arguments] All Clear bclear * Watch Menu Set watch [location] Breakw break [arguments] List wlist Clear wclear [arguments] Enable wenable [arguments] Disable wdisable [arguments] All Clear wclear * Memory Menu Size (Long, Word, Byte) Display As (Data, Code) Base Address (Static, Dynamic) The File menu has two items called Line and Find Current Line that automatically list lines of source code in the Dialog window. These options are displayed as Address and Find Current Address when the debugger is in assembler mode. When prompted for an address after choosing the Address item, you should enter a hexadecimal va]ue. A '0x" prefix is not required. The Source window will disassemble code beginning at the specified address. Function and Spaecial Keys The actions of the function keys (F1 through F10) are indicated on the debugger screen title bar. In addition to the function keys, there are three keys with special functions: Help, Ctrl L, and Ctrl W. I hese keys 23 Introduction to CodeProbe are not shown in the title bar. Table 1.5 explains the use of the function and special keys in more detail. Table 1.5 Function and Special Keys Key Action F1 toggles for opening/closing the Watch window Shift F1 toggles for opening/closing the Source window F2 zooms or unzooms the active window to the size of the screen F3 recalls the last command * Shift F3 recalls the previous command * F4 toggles for opening/closing the Register window F5 re-executes the last command * F6 activates the next window F7 steps into a line/instruction (trace) F8 steps over a line/instruction (proceed) F9 toggles for swap screens between the debugger and application screens F10 toggles the numeric keypad mode Help executes the help command Ctrl L refreshes the screen Ctrl W refreshes the screen * The Dialog window must be active to recall or re-execute commands. Menu Accelerator Keys Menu accelerator keys are familiar to most Amiga system users. Menu items with shortcuts can be executed from the keyboard by striking the right-Amiga key in combinatioIl with another specified key. If a menu item has an accelerator key, it is displayed on the menu after the item. The actions performed by the menu accelerator keys are shown in Table 1.6. 24 Chapter 1 Table 1.6 Menu Accelerator Keys Key Menu Action A Break Clears all breaks B Break Sets a breakpoint C Break Clears a breakpoint D Break Disables a breakpoint E Break Enables a breakpoint F File Refreshes the screen G Run Executes the go command H File Finds the current line L Break Lists the breakpoints M File Changes the currellt module N File Finds the line/address P Run Proceeds (steps over the current line/instruction) Q File Quits the debugger R Run Returns from the current function S Run Starts (restarts the program with same command line) T Run Traces (steps into the current line/instruction) W Run Where (displays stack frame backtrace) X File Executes a debugger command script from a file 25 2 Sample CodeProbe Session 25 Introduction 25 A Walk through a Typical Application 25 Starting the Debugger 26 Using the go and restart Commands 26 Using Online Help 27 Controlling the Debugging Session 34 Quitting the Debugger Introduction The best way to understand how to use CodeProbe is to walk through a sample debugging session. This chapter provides an example session that demonstrates several debugger commands and options. It also explains how to maneuver in the debugger's windows. The chapters that follow this one provide the necessary details to help you get the most out of CodeProbe. A Walk through a Typical Application The source code for the sample program, l ines . c, used in this chapter is located in the s c: e x amp 1 e s drawer. Starting the Debugger To start your debugging session you must first compile and link the application program and then invoke the debugger. This chapter provides instructions for performing these tasks with the sample program, lines.c. Additional information about compiling, linking, and invoking the debugger is located in Chapter 1, "Introduction to CodeProbe," and Chapter 4, "Setting Up the Debugging ~nvironment." Compiling and Linking the Program To compile the sample program, lines.c, invoke the compiler, SC, with the debug=symbolf lush (sf) option. This option outputs full debugging information for those symbols and structures referenced by the program. The link option invokes the linker automatically. sc debug=sf link lines.c 26 Chapter 2 Invoking the Debugger To start the debugger, type in c pr followed by the executable program's filename. cpr lines Note that the Dialog window and the Source window open by default. The Dialog window highlights the current edit line. In the same manner, the Source window highlights the next line of the program's source code to be executed. Using the go and restart Commands In order to use the debugger efficiently, you need to become familiar with both the go and the restart commands. The go command begins execution of your application program, which runs until a breakpoint is hit or the program exits. The restart command causes the application program to be reloaded and execute up to the first line of the main function. Both of these commands are described in Chapter 9, "Commands and Built-in Functions." When you invoke CodeProbe, a go main command is automatically issued unless you specified the -startup option when you invoked the debugger. This initial go command causes your application to run to the first line of the main function. You can always return to this point by entering as many go commands as necessary to cause your application program to run to completion and then issuing a single restart command. Using the restart command incorrectly can crash your machine. You can issue a restart command at any point in your program, which causes execution to jump back to the beginning of your code and run up to the first line of the main function. However, restart does not finish executing the rest of your program before it returns to the beginning, and cleanup procedures located at the end of a program are not executed. These cleanup procedures return memory and registers to a state expected by the operating system and other programs. Failing to complete execution of your program before restarting or exiting CodeProbe may leave the machine in an unacceptable state that will later cause a crash. Using Online Help At any point in your debugging session, you can use the help command to get online help regarding debugger commands and other CodeProbe features. The help command can be issued from the command line using either of the following forms: h[elp] [command] ? [command] Sample CodeProbe Session 27 The optional command parameter specifies the debugger command for which help information is to be displayed. A brief description, a summary of command syntax, some sample uses, and references to other commands is provided. If you enter the help command without the command parameter, a list of debugger commands is displayed along with other topics for which online help is available. To make a selection from the list, double-click the mouse pointer on one of these commands or topics. Controlling the Debugging Session After you have invoked the debugger, you control your debugging session by entering debugger commands as described in Chapter 1, "Introduction to CodeProbe." Reference information for each of the debugger commands is provided in Chapter 9, "Commands and Built-in Functions." Setting the Source Mode The source mode controls the way the source code is displayed in the Source window. You can use a pull-down menu to change the source mode. Hold down the right mouse button and drag the pointer through the menu items under the Options menu. The Source Mode option appears as a menu item and indicates C as the default mode. When the Source Mode option is highlighted, three subitems are offered as choices: C, Asm, and Mixed. Modifying the selected choice alters the appearance of the lines in the Source window accordingly. For instance, Display 2.1 shows the results of selecting mixed mode, while Display 2.2 shows the results of selecting assembly mode. When debugging a C application, you should usually choose C mode. Refer to the section "Source Mode" in Chapter 4 for additional information. 28 29 Sample CodeProbe Session Activating Autoswap Mode You also can activate Autoswap mode from the options nlellu. ~-he autoswap mode is on, the screen containing the application's OlltpUt is pushed to the front each time CodeProbe gives cont1ol to the application. When a breakpoint is reached, the debugge1 screen is pushed again to the front. If autoswal) mode is not on, you must change to the output screen manually using functio1l key 19 or the keyboard shortcut left-Amiga-m. Regardless of what metllo(l yoll use to swap screens, you must activate each screen by first clicking the left mouse button before entering any input. Stepping Over Code One of most useful features of the debugger is the ability to step through code. The proceed command enables you to single step over function calls. If you need to step into a called functioll you can use the trace command. Since the proceed command is the most frequently used command, CodeProbe is designed so that pressing the Return key causes the proceed command to be executed. Step over the first few lines of code as follows: lines:\lines.c\main 71 > lines:\lines.c\main 72 > lines:\lines.c\main 73 > lines:\lines.c\main 74 Select the Options menu and turn Autoswap mode on. Now step over several more lines of code. Notice the qllick flashing due to the display of the application window (the initial Workben( 1l ( Ll window) during each step. lines:\lines.c\main 79 > lines:\lines.c\main 80 > lines:\lines.c\main 81 > lines:\lines.c\main 82 30 Chapter 2 You will notice also that the debugger does not stop at every line. This is due to the fact that code is not generated for all lines. Code is not generally produced for lines that declare variables, such as lines 66-68, or lines that are blank or contain only comments. Continuing Execution If you do not want to take the time to execute each line individually, you can use the go command, which executes your application until it either encounters a breakpoint (a flag to stop execution) or the end of the program. You should always use go to complete execution of your program before quitting CodeProbe or using the restart command. Displaying a Structure Or an Array The display command, which can be abbreviated as d, allows you to display structures, arrays, and variables easily. For instance, to display the structure nw, issue the following command in the Dialog window: >display nw struct NewWindow { LeftEdge = 100 (0x64) TopEdge = 100 (0x64) Width = 300 (0x12C) Height = 100 (0x64) DetailPen = '\x02' 2 (0x02) BlockPen = '\x01' 1 (0x01) IDCMPFlags = 514 (0x202) Flags = 1039 (0x40F) FirstGadget = 0x0 CheckMark = 0x0 Title = 0x00226028 Screen = 0x0 BitMap = 0x0 MinWidth = 50 (0x32) MinHeight = 50 (0x32) MaxWidth = 640 (0x280) MaxHeight = 400 (0x190) Type = 1 (0x1) } Use F2 to zoom the Dialog window to full size so that the entire structure can be viewed at once. The value of the character pointer Title will probably be different on your screen, but the other values 31 Sample CodeProbe Session should be the same. When you have finished viewing, press F2 to restore the Dialog window to its original size. To display the two-dimensional array ox, issue the following command from the Dialog window: > display ox { [0] = { [0] = 0 [1] = 0 [2] = 0 . . . Then press F2 again to zoom the Dialog window to full size. While the values are not noteworthy, you can get an idea of the format that is displayed. Notice that the entire array does not fit in a full-size window. To see the beginning values, use the mouse and the Dialog window's vertical scroll bar to scroll backwards. Individual members of structures and unions, as well as elements of arrays, can be displayed using the display command, as in the following examples: > display nw.Type 1 (0x1) > display xIl] 0 (0x0) > display w->RPort 0x07F000FC > display 0x[1][5] 0 (0x0) > display nw.Title 0x00226028 > dzero nw.Title "Nervous Lines" You probably will find different results for the third and fifth examples. Notice that the last command dzero indicates that nw . Title should be treated as a pointer to a null terminated string and its contents displayed rather than the pointer itself. 32 Chapter 2 Setting a Breakpoint A breakpoint is an address at which program execution stops whenever encountered. To set a breakpoint, move the pointer to a given line of code in the Source window. Using the left mouse button, double-click on the line. This sets a breakpoint on the line, and the line is highlighted. If there is no code generated at the line, an error message is displayed in the Dialog window. The breakpoint can be removed easily by double-clicking again on the particular line of code. Executing up to a Breakpoint Use your mouse to scroll down to line 111 in the Source window and double-click on line 111 to set a breakpoint. Now execute the program up to the breakpoint by typing the go command on the command line. The breakpoint line is now highlighted in a different way to indicate that execution has proceeded to that point. Double-clicking on the line turns off the breakpoint. The line reverts back to normal, highlighting just the text, indicating this is the next line to be executed. Displaying the Value and Type of a Variable The debugger will display a variable's value and tell what type it is. Enter the following commands in the Dialog window: > display i 2 (0x2) > whatis i auto register variable in d7 (2 bytes) short i; > whatis x extern at 0022625E (8-byte array of 2 4-byte element(s)) int x[2]; > whatis nw extern at 00226036 (48 bytes) struct NewWindow nw; Notice that the whatis command can provide information about the location and attributes of any variable. This is particularly useful for keeping track of automatic variables, which may be placed in registers by the compiler, even though they were not explicitly declared as type register. Using the watch and watch break Commands A watch allows you to monitor a variable or area of memory to see when the value of the variable changes or when the area of memory is 33 Sample CodeProbe Session altered. Create a watch for the variable x by issuing the following command: > watch x Open the Watch window by pressing the ~1 key. You may have to adjust the size of the Watch window to see the entire display. Note that the output shown in the Watch window is a hex dump of the variable x: 1 x : 00 00 00 51 00 00 00 The number 1 at the left of the display identifies the watch. It is used by other commands that manipulate the Watch window. A watch break is similar to a watch but acts as a breakpoint when the variable or area of memory is changed. Create a watch break for the variable y by issuing the following command: > wbreak y At this point the Watch window should appear as follows: 1 x : 00 00 00 51 00 00 00 2! y : 00 00 00 30 00 00 00 Notice that the watch break is highlighted and has an exclamation mark (!) following the watch break number. The exclamation mark indicates that it is a watch break and not simply a watch. Executing Until the Variable Changes Value The Watch window is updated when control is returned to you by the debugger, such as at a breakpoint, and the new values of the watched areas are displayed. Note that runrling with set watch breaks can be a slow process because the CPU executes the application in trace mode. This means that control returns to the debugger after every instruction. The debugger must then check the memory for all watch breaks before restarting the application. The watch break feature is a powerful tool, and it is particularly useful for locating obscure bugs that cause memory to be overwritten from unusual places in the code; however, it should not be used indiscriminantly. 34 Chapter 2 To see the effect of the watch break, click in the Dialog window and issue the go command: > go break (watch #2) 2! y: 00 00 00 38 00 00 00 lines:\lines.c\main 117 Notice that the debugger reports the watch break number that caused the breakpoint to occur. Also, notice that the line that modified the variable was actually the previous line. Line 116 is the next line to be executed. Clearing All Watches and Watch Breaks To clear watches and watch breaks, issue the following Dialog window command: > wclear * The asterisk (*) is a wild card representing all watch and watch break identifiers. Now that all watches and watch breaks have been cleared, issue the go command to start the program l ines . c. Notice that no breakpoints can be reached now, so the program will continue until completion. Standard input/output is written to the application window on the Workbench screen. To see the application as it is running, you can use the left-Amiga-m key sequence to swap screens. The demo will run until the close gadget is activated on the l ines.c application window. After closing the application window, swap screens back to CodeProbe. The Dialog window should now display the following: Program exited with code 0. The code value cited, 0 in this case, is the return code from the program. Quitting the Debugger To quit the debugger, issue the command quit at the command line, or use the pull-down menu item in the File menu. 35 3 Debugging Your Program 35 Introduction 36 CodeProbe Commands 37 Sample Program 1 37 Source Code 39 Running Program 1 39 Controlling Program Execution 39 The go Command 44 Single Stepping 45 The trace Commands 46 The proceed Commands 47 Breakpoints 48 The break Command 53 Sample Program 2 54 Source Code 56 Running Program 2 57 Examining Data and Data Structures 57 The display Command 61 The dump Command 66 The register Command 68 The whatis Command 69 Walches and Watch Breaks 70 The watch and wbreak Commands Introduction This chapter explains the use of several common CodeProbe commands to perform the following tasks: control program execution examine data and data structures modify data use watches and watch breaks. The commands used to perform these tasks also are explained in this chapter because they can be complex to use effectively. 36 Chapter 3 CodeProbe Commands This chapter introduces the following complex CodeProbe commands: break go watch display proceed wbreak dump trace whatis There are additional commands that are not discussed here. For a complete listing of the commands and detailed reference information, refer to Chapter 9, "Commands and Built-in Functions." Commands for Running Sample Programs The following commands are useful when running the sample programs described in this chapter: bclear clears one or more breakpoints blist displays a list of all the breakpoints that have been set restart reloads your program and reinitializes your static data allowing you to start over from the top. Note: The restart command is an advanced command. Before using it to debug your programs, you should review carefully the restart command in Chapter 9. Additional Commands In addition to the commands described in this chapter, you should become familiar with the following commands, which are described in Chapter 9, to get the most out of CodeProbe: bdisable rflag wdisable benable set wenable call symbol wlist jump where return wclear 37 Debugging Your Program Sample Program 1 To view the commands described in the first part of this chapter, you should compile, link, and debug Sample Program 1. It is a simple program consisting of three modules (smain.c, sort.c, and swap.c) that first initializes an array of integers from O to 9 and then sorts the array into reverse order. The examples in this chapter are designed so that you start CodeProbe only once, at the beginning of the section, and then run each example in order. Running the examples out of order can produce results that do not agree with the documentation. Extra go and restart commands are included with several of the examples to position the file back at its beginning. The same results can be achieved by entering go, quitting CodeProbe, and starting a new debug session with the same program. Note, however, that you should always allow your program to run to completion before restarting or quitting CodeProbe. Source Code The following source code for Sample Program 1 is provided in the sc:examples/debugger drawer: /* SMAIN.C */ (1) #define ASIZE 10 (2) (3) void init(int *, int); (4) int sort(int *, int); (5) (6) int array[ASIZE]; (7) (8) void main(void) (9) { (10) init(array,ASIZE); /* initialize array[] */ (11) (12) /* Keep swapping elements until sorted */ (13) while (sort(array,ASIZE) != 0) (14) ; (15) } /* SORT.C */ (1) void swap(int *, int *); (2) (3) void init(int *ip, int size) 38 Chapter 3 (4) { (5) int i; (6) int *p; (7) (8) p = ip; (9) for (i = 0; i < size; i++) (10) *p++ = i; (11) } (12) (13) /* Reverse sort elements of an array */ (14) (l5) int sort(int *ip, int size) (16) { (17) int i, s; (18) int *p; (19) (20) p = ip; (21) s = 0; /* no swaps performed yet */ (22) (23) for (i=0; i < size - 1; i++) (24) if (p[i] < p[i+1] ) (25) { (26) swap(&p[i], &p[i+1] ); (27) s = 1; /* indicate a swap took place */ (28) } (29) (30) return(s); (31) } /* SWAP.C */ (1) void swap(int *x, int *y) (2) { (3) int tmp; (4) (5) tmp = *x; (6) *x = *y; (7) *y = tmp; (8) } 39 Debugging Your Program Running Program 1 To run Sample Program 1, compile, link, and load it into the debugger as follows: 1. Compile and link Sample Program 1 using the following command: sc debug=sf link sort.c smain.c swap.c 2. Start CodeProbe by entering the following command: cpr sort Controlling Program Execution With CodeProbe you can exercise a high degree of control over program execution. You can single step through your program (at either the assembly or C source level), step over or into function calls, set breakpoints at source line or instruction addresses, or go to a specific location. This section describes the following Dialog window commands for controlling program execution: break sets a breakpoint at the specified location. go starts the execution of the program you are debugging and continues until it hits a breakpoint or the end of the program. Execution begins at the line highlighted in the Source window. proceed single steps through your program or steps through it a given number of times, stepping over function calls, unless they contain a breakpoint. trace single steps through your program or steps through it a given number of times breaking at a function call. The go Command The go command starts the execution of the program you are debugging. This command uses the following syntax: g[o] [location [after(integer)] [when(expression) ]] 40 Chapter 3 The go command has three different parameters: location, after(integer), and when(expression). Note that the parentheses around the expression and integer parameters must be typed in. The optional location parameter indicates where execution should terminate. When the go command is used, the debugger sets a temporary (non-sticky) breakpoint at a specified location. This breakpoint is temporary in the sense that the breakpoint is deleted after it is encountered. If you already have a normal breakpoint at a particular location and execute the go command to that location, the original breakpoint is cleared. The after clause uses the integer parameter to specify the number of times that the line indicated by the location parameter should be executed. This is called a pass count and program execution stops after the line is passed the specified number of times. The when clause uses the expression parameter to specify the circumstances under which execution is suspended at location. In its most general form, the go command can be read as: go until location has been executed integer number of times and stop the next time location is reached when the expression is true. When used without parameters, the go command starts the execution of your program, which runs to normal completion if no active breakpoints are encountered. Specifying a Location The location parameter specifies the point in your program at which you want execution to stop. You can specify either an address or line number in a source file and a breakpoint will be set at that location. A location can take any of the following forms: address line function function line \module\function [line] image: function image: function [line] image:\module\function [line] The address form of the location parameter is used to specify an explicit address constant. This form is useful for setting breakpoints at specific addresses when debugging in assembly mode. 41 Debugging Your Program The line parameter is usually a number referring to the line number where you want execution to stop. Other possibilities for line are the following: $ refers to the current line e[ntry] refers to the first instruction of the specified function, or the current function if none is specified r[eturn] refers to the last instruction of the specified function, or the current function if none is specified. A line number is always relative to the beginning of the module. The line parameter can be used in conjunction with the function parameter to describe a location. For instance, in the form function line line refers to the line number of the module containing function. If the specified line is not inside the specified function, an error is printed. If a function is specified without a line parameter, the entry point to the function is assumed. When the specified location is reached, a message is displayed describing the source filename, the function name, and the line number. If mixed or assembly mode has been specified, the information is preceded by the breakpoint address. For example, using Sample Program 1 shown earlier in this chapter, the session log displayed in the Dialog window would look as follows, if C mode is currently chosen: > go swap 5 sort:\swap.c\swap 5 > opt source mixed > go swap 7 at 0x38974C sort:\swap.c\swap 7 > opt source c > go program exited with code 0. > restart starting "sort" sort:\smain.c\main 10 42 Chapter 3 Here execution has stopped after the second go command was issued, at line 7 of the file swap.c, and within the function swap. If the module is not specified, a search will be made among your modules, beginning with the current module, until function is found. In the unlikely event that you have defined two functions in separate modules with the same name and belonging to the same static storage class, then it is necessary to specify the module. If a function is not specified, the currently executing function is assumed. If an image parameter is specified, it refers to the name of a program or shared library that may or may not have been loaded. If it is not yet loaded, the debugger sets a deferred breakpoint in the library or program. When the library or program is loaded a breakpoint is set and program execution proceeds. If the debugger cannot find the debugging information for the image, it will halt when the image is loaded. At this point you can use the symload command to specify the location of the version to be debugged. For example, the following go command causes the program to execute until mylib.library is loaded, a breakpoint is then set at LIBmyfunc, and program execution continues. This example command will not work with Sample Program 1. go mylib.library:LIBmyfunc Specifying the after Clause As previously described, the after(integer) parameter is used to specify a pass count, which is the number of times that the line indicated by the location parameter should be executed. For example, if you enter the following command in the Dialog window after starting CodeProbe with Sample Program 1, execution will stop after the while statement on line 13 of the program has executed 5 times: > go 13 after(5) sort:\Work:examples/smain.c\main 13 Specifying the when Clause The when ( expression ) parameter is used to further control program execution. An expression can be any valid C expression. For example, any of the following expressions can be used with a when clause: i == 7 i < 12 || i > 5 i != 4 && strlen(string) != 7 43 Debugging Your Program Consider the following loop in the sort routine of Sample Program 1: for (i = 0; i < size - 1; i++) if (p[i] < p[i + 1]) You may want to stop at a point within the loop, but only after a certain number of iterations of the loop have been executed. Assuming that the f or statement is on line 23, this can be accomplished with the following go command: > go sort sort:\Work:examples/sort.c\20 > go 4 when (i == 7) sort:\Work:examples/sort.c\sort 4 This has the effect of planting a non-sticky breakpoint at line 24 of the current module. That is, the breakpoint will be triggered only if the when condition is true; otherwise execution will continue past the specified line. Note that the specified line is the line after the loop. This is because breakpoints are set at the beginning of a line, before the code on the line is executed. If the breakpoint had been set at the line on which the for statement occurs, the breakpoint would never have been encountered while the loop was executing. For example, if you give the following command the breakpoint would not be triggered, because i will never be less than 0 and the program will run to completion: > go 24 when (i == -1) program exited with code 0. Breakpoints are discussed in greater detail later in this section. If you make any mistakes in syntax when entering the condition, errors are not detected until the first time the specified location is reached and the debugger attempts to evaluate the condition. If the debugger cannot evaluate the condition, the breakpoint is triggered and an error message is displayed. The message indicates the position in the condition where syntax rules have been violated. For example, the 44 Chapter 3 following message indicates that ! < violates rules governing permitted relational symbols: > restart > go sort > go 24 when (i !< 1) Processing the when clause: (i !< 1) ^-------------syntax error sort:\sort.c\sort 24 Examples The following are examples of ways to use the go command: go main goes until the entry point of function main go return goes until the end of the current function go 0xc80200 goes until the address 0xc80200 is reached go sort 24 when ( i==5 ) goes until line 24 of the sort function when i equals 5 go init 10 after(5) when (i>4) goes until pass 5 at line 10 in the init function when i is greater than 4 Single Stepping The proceed and trace commands can be used to single step your program. Each command has two variations: one to single step at the assembler level and the other to single step at the C source level. The difference between the two commands lies in their handling of function calls. The proceed commands step over function calls; if a function call is encountered during the execution of a proceed command, the function is executed without a break occurring (unless one has been deliberately set in the function), and then the next line after the function call is highlighted. Execution continues in the calling function. This is in contrast to a trace command, which steps into function calls, highlighting the first line of the function as the next line to be executed. 45 Debugging Your Program The trace Command The trace commands, t and ts, are used to single step your program. The t command is for single stepping assembler instructiolls. The ts command stands for trace source and is used for single stepping C code. The syntax for the trace commands is as follows: t[racel [integer] ts [integer] The optional integer parameter indicates the number of steps to be executed; if absent, a single step is executed. A step is considered to be either one assembler instruction or a single line of C source code. Either trace command will step into any function calls encountered during the step. That is, the called function is entered and execution is suspended at its first instruction. The actions of these commands depend on the current source mode of the debugger. In C source mode, the two trace commands act identically, causing the execution of one line of C source code up to any imbedded function call. In assembly or mixed mode, t executes one machine instruction; ts always executes a single C source line. Both trace commands step into function calls. Regardless of the mode, if the current line contains a function call, then the first line of that function is executed and subsequent t commands execute lines within that function. In assembly mode, if the current line contains a JSR (Jump to SubRoutine) or a BSR (Branch to SubRoutine) instruction, then that instruction is executed and subsequent t commands execute instructions in the called function. Using Sample Program 1 given earlier in this chapter and starting over from main with the restart command, trace for several steps in source mode as shown here: > go program exited with code 0. > restart sort:\smain.c\main 10 > trace sort:\sort.c\init 4 > trace sort:\sort.c\init 8 > trace 3 sort:\sort.c\init 9 sort:\sort.c\init 9 (+0x2) sort:\sort.c\init 10 46 Chapter 3 sort:\sort.c\init 9 (+0x2) sort:\sort.c\init 10 sort:\sort.c\init 9 (+0x2) The first trace command carries us to the init call in main. The second then moves us into the init function. The third illustrates the use of a numeric argument to execute several steps. To step by a single machine instruction, you can set the source to either asm or mixed. For instance, you can set your source mode to asm by using the pulldown Options menu or by issuing the following command: opt source asm Similarly, you can set your source to mixed with the following command: opt source mixed At this point, you can enter the trace command to step over an assembler instruction. If source mode is set to asm and no line information is available, using the ts command is regarded as an error, and an appropriate error message is displayed. In mixed mode, the trace command causes stepping by machine instruction while the ts command causes stepping by C source line. The proceed Commands The proceed commands, p and ps, also are used to single step your program or to step it a given number of times. Unlike trace, however, a proceed command steps over function calls rather than stepping into them. That is, if a call to a function is encountered in the process of the step, the function is not stepped into as in the trace commands. The syntax for the proceed commands is as follows: p[roceedl [integer] ps [integer] 47 Debugging Your Program The integer parameter indicates the number of steps to be executed. The proceed and ps commands are analogous to the trace and ts commands with respect to source mode. Looking at the previous example, notice how the results of the proceed commands differ compared to the trace commands (C source mode is used again): > go program exited with code 0. > restart sort:\smain.c\main 10 > proceed sort:\smain.c\main 13 > proceed sort:\smain.c\main 14 > proceed sort:\smain.c\main 13 Here, a single step has been made for each source line of the function main. Function calls were made in the process of this stepping, but none of the called functions were entered. Pressing the Return key is equivalent to entering the p command. Continuing where the previous example left off, the following example demonstrates how this works: > sort:\smain.c\main 14 > sort:\smain.c\main 13 Using the ps command in assembly mode is regarded as an error if no source line information is available, while proceed can be used in mixed or assembly mode to single step by machine instruction. The ps command can be used in mixed mode to step by C source line in a manner similar to the ts command. Breakpoints A breakpoint is an address at which program execution stops. The break command enables you to suspend the execution of your program or to execute a set of debugger commands at any point you choose. By setting conditional breakpoints or by using a pass count to specify the number of times a program should pass a breakpoint before execution is stopped, you can suspend program execution at just the 48 Chapter 3 right stage of your program. This means, for example, that you can set a breakpoint at a line within a loop so that the program stops after going through 500 iterations of the loop. By triggering a breakpoint in this way, you are able to easily reach the point in the program that you want to examine. Besides breakpoint setting, additional commands allow you to manage your breakpoint list. bc lear provides you with the ability to clear a breakpoint, bdisable temporarily disables a breakpoint, benable enables it again, and blist lists the current breakpoints. The break Command The break command enables you to specify a breakpoint. Breakpoints are used to suspend the execution of a program at any point or execute a set of debugger commands instead of suspending execution. You can also set and clear breakpoints by double-clicking the mouse on a line in C source mode or an assembly instruction in asm or mixed mode. The syntax of the break command has two forms: b[reak] $ b[reak]location[after(integer)][when(expression)] [tr[ace]] [q[uiet]] [te[mp]] [{cmd-list}] In the first form, a breakpoint is set at the current location (which in C source mode is the cutrent line). This is handy when you have stepped to a certain point in your program and want to set a breakpoint quickly at the current line. Here is an example: > go sort sort:\sort.c\sort 20 > sort:\sort.c\sort 21 > sort:\sort.c\sort 23 > break $ > go sort:\sort.c\sort 23 In this case we have single stepped twice by pressing Return (the same as a proceed command). When the breakpoint is set with the break command, line 23 in the Source window is highlighted. A breakpoint also can be easily and quickly set or removed by double-clicking on the line in the Source window where you want the breakpoint. 49 Debugging Your Program The second form of the break command allows you to set a breakpoint at a specified line number and to ensure that the breakpoint is not triggered until that line has been executed a specified number of times. For example, suppose you want to set a breakpoint at the if statement in the sort routine, but you want the breakpoint triggered only after the fifth time that statement is executed. You can use the following commands: > break sort 24 after(5) > blist 1 0xC32DCA sort:\sort.c\sort 23 (1 hit) 2 0xC32DD4 sort:\sort.c\sort 24 after(5) > go sort:\sort.c\sort 24 > display i 4 (0x4) The fact that the value of i is 4 indicates that the loop has already executed five times. You will find the pass count feature to be especially useful in debugging programs containing loops that iterate many times. Conditional Breakpoints Although breakpoints with pass counts are a kind of conditional breakpoint, the break command also allows for a more generally useful kind of conditional breakpoint. Using the when option, you can specify a condition that depends upon the values of variables in your program. You might, for example, want to stop at the i f statement in sort when the value of p[i] is 8: > bclear * > break sort 26 when (p[i] == 8) > go sort:\sort.c\sort 26 > display p[i] 8 (0x8) Any valid C expression can be used as an argument in a when clause. Of course the after option can be used to specify a pass count in conjunction with the when clause. Both the pass count and the when 50 Chapter 3 clause conditions must be met. You may, for example, want to see if there is an instance where the array element is equal to the array index after three or more executions of a given line: > bclear * > go program exited with return code 0. > restart > break sort 26 after (3) when(p[i]==i) > go sort:\sort.c\sort 26 > dump i decimal reg d6: 2 > dump plil decimal 00C28708 2 Attaching Actions to Breakpoints Instead of just stopping at a breakpoint, you may want to have the debugger perform one or more actions. You can do this with the cmd_list parameter. The cmd_list parameter is a sequence of debugger commands enclosed in braces ({}) and separated by semicolons (;). The following example shows how to use the cmd_list parameter to stop at line 25 of the sort function and have the debugger automatically display the value of p[i] and the value of i. > bclear * > break sort 26 {display "p[i] = ", p[i] ; display "i = ", i} > go sort:\sort.c\sort 26 p[i] = 2 (0x2) i = 3 (0x3) > go sort:\sort.c\sort 26 p[i] = 2 (0x2) i = 4 (0x4) > go sort:\sort.c\sort 26 p[i] = 2 (0x2) i = 5 (0x5) 51 Debugging Your Program In fact, you can arrange for the debugger not to stop at the breakpoint but to continue by issuing the go command as the last command in your list, as in the following example: > bclear * > go program exited with code 0. > restart sort:\smain.c\main 10 > break sort 26 when (i < 3) {dump p L 4; go} > break sort 24 when (i >= 3) > blist 10 0xC32D4C sort:\sort.c\sort 26 when (i < 3) {dump p L 4; go} 11 0xC32D2C sort:\sort.c\sort 24 when (i >= 3) > go sort:\sort.c\sort 26 00C31260: 00000000 00000001 00000002 00000003 sort:\sort.c\sort 26 00C31260: 00000001 00000000 00000002 00000003 sort:\sort.c\sort 26 00C31260: 00000001 00000002 00000000 00000003 sort:\sort.c\sort 24 In this way, you can actually see the sort taking place and you do not need to type in the go command repeatedly. Using the trace option on the break command eliminates the need to include a final go in the command list parameter. This is demonstrated in the following example: > bclear * > break sort 26 when (i > 5) {dump p L 4; break sort 26 when (i == 8) trace; blist} > blist 12 0xC32D4C sort:\sort.c\sort 26 when (i > 5) {dump p L 4; break sort 26 when (i == 8) trace; blist} > go sort:\sort.c\sort 26 00C31260: 00000001 00000002 00000003 00000004 15 0xC32D4C sort:\sort.c\sort 26 when (i == 8) trace sort:\sort.c\sort 26 52 Chapter 3 Here a breakpoint is set at line 26 of sort and is to be triggered when i has a value greater than 5. When triggered, the breakpoint action displays the first four elements (16 bytes) of the array referenced by p, sets a new breakpoint at the same line, lists the new breakpoint, and continues execution. The new breakpoint is then triggered when its when condition is satisfied. This nesting of breakpoints within action lists is a powerful feature of the debugger. Since nested breakpoints may become complex, you should take great care in using them or you may lose your place in the program when some breakpoints replace themselves with others. You must also be aware that a breakpoint with an action may have an effect (and perhaps an unexpected one) on program execution. To consider a simple case, suppose you set a breakpoint on line 26 of sort and attach to it an action that will alter the value of i: > bclear * > break sort 26 when (i == 5) [set i = 2] > go sort:\sort.c\sort 26 > dump i decimal reg d6: 2 > go sort:\sort.c\sort 26 > dump i decimal reg d6: 2 In this simple case you have managed to create an infinite loop by means of your breakpoint and action list. Such a simple mistake is easy to find, but if you have planted a number of breakpoints or if your breakpoints are deeply nested, the error might be very difficult to detect. This example also demonstrates that the action for a breakpoint is executed before control is returned to you; by the time you examine the value of i, it has already been set to its new value by the set command. You can also use the trace, quiet, and temp options with the break command. The trace option causes execution to continue after the breakpoint is hit, the quiet option suppresses the default message that is printed when the breakpoint is hit, and the temp 53 Debugging Your Program option deletes the breakpoint after it is hit. The following example illustrates the use of these options: > go > restart > bclear * > break sort 26 trace quiet (display i) > break sort 30 temp > blist 1 0xC32D4C sort:\sort.c\sort 26 trace quiet (display i) 2 0xC32D66 sort:\sort.c\sort 30 temp > go 0 (0x0) 1 (0x1 ) 2 (0x2) 3 (0x3) 4 (0x4) 5 (0x5) 6 (0x6) 7 (0x7) 8 (0x8) sort:\sort.c\sort 30 > blist 1 0xC32D4C sort:\sort.c\sort 26 trace quiet (display i) Sample Program 2 To view the commands described in the second part of this chapter, you should compile, link, and debug Sample Program 2. It is a simple program consisting of one module (data.c). Sample Program 2 defines and initializes various data structures. It is intended only for exploring the data manipulatiorl fullctiolls of CodeProbe and has no practical use. The following sections use examples based on Sample Program 2 to explore various colnnlallds to display data and data structures. 54 Chapter 3 Source Code The following source code for Sample Program 2 is provided in the sc:examples/debugger drawer: #inclUde void main (void) { struct X { int a; int b[3]; int c; } x; struct Y { int a; int b; } Y; typedef struct X *XPTR; struct W { int x; struct Y y[2]; int z; } w; struct Z { char c; struct Y d; int e; } z; struct X3D { int a; int b[2][3][2]; int c; } x3d; int i,j; int arrayl[0]; int *intptr; 55 Debugging Your Program long lng; short shrt; float fl; double db; char *string = "Hello, World"; /* Initialize data structures. */ i = 33; j = 44; intptr = &i; lng = 6456; shrt = 89; fl = 3.14; db = 33.5; array[O] = 5; array[1] = 15; array[2] = 25; array[3] = 35; array[4] = 45; array[5] = 55; array[6] = 65; array[7] = 75; array[3] = 89; array[9] = 95; x.a= 5; x.b[0] = 1; x.b[1]=2; x.b[2]=3; x.c=11; y.a=5; y.b=6; w.x= 4 ; w.y[0] = y; w.y[1] = y; w.z = 9; 56 Chapter 3 z.c = 'r'; z.d = Y; z.e=3; intptr = &j; x3d.a=2; x3d.b[0][0][0] = 41; x3d.b[0][0][1] = 42; x3d.b[0][1][0] = 43; x3d.b[0][1][1] = 44; x3d.b[0][2][0] = 45; x3d.b[0][2][1] = 46; x3d.b[1][0][0] = 47; x3d.b[1][0][1] = 48; x3d.b[1][1][0] = 49; x3d.b[1][1][1] = 50; x3d.b[1][2][0] = 51; x3d.b[1][2][1] = 52; x3d.c=90; printf("%s!\n",string); } Running Program 2 To run sample program 2, compile, link, and load it into the debugger as follows: 1. Compile and link using the following command: sc debug=sf link math=standard noautoregister data.c 2. Start CodeProbe by entering the following command: cpr data 57 Debugging Your Program Examining Data and Data Structures CodeProbe offers several commands that you can use to display the data referenced by your program. This section describes the following commands for examining data and data structures: display displays an object, area of memory, or the result of an expression dump examines the value of any variable in a program, an arbitrary range of memory, a register, or an expression register displays or modifies the current settings of the machine integer registers watch sets a variable or area of memory to be watched wbreak sets a breakpoint when a watched variable or area of memory changes whatis determines the type and address of a variable or the fundamental C type to which a typedef identifier resolves. The display Command The display command displays C data structures and objects and can display an object or area of memory interpreted as a specified type of object. The syntax of the display command is as follows: d[isplay] (expression["format"] | string)[,...] The expression parameter can be any C expression containing constants, variables, and function calls from the program being debugged except expressions involving the comma operator (,), the ?: operator, the various assignment operators (+=, -=, and so on), or the prefix and postfix operators (++ and --) To override the default format, a format specification like those used with the printf statement can be used after each expression. The forrnat parameter can contain up to two conversion operators for short and long types, but only one for all other types. No error checking is done on the format and strange results are possible. If an address is specified as the expression parameter, and it is an address constant, then, in the absence of a forrnat parameter, the address is assumed to be of type char *. 58 Chapter 3 The string parameter can be any standard C string as described earlier in this chapter. The string is echoed in the Dialog window. The display command can accept multiple arguments, each of the following form: (expression["format"] | string) The arguments must be separated by commas. Given this information, the following are examples of the display command: > display i > display 0xC80FF8 > display i "i is equal to %d" > display a "a=%10.5e" > display p->d[5] + myfunction(3) > display x "X is %d", j "J is %d" Before using Sample Program 1 in the examples shown in this section, enter the following command to execute all of the data initialization code: > go 110 Now you can display the value of an integer variable as shown here: > display i 33 (0x21) To display its address, use the following command: > d &i 0xC309B8 Note that register variables do not have an address; if you try to use the and (&) operator on a register variable, you will get an error message. This is why the example program was compiled with the noautoregister option. 59 Debugging Your Program It is equally simple to display an array element as follows: > d *array 5 (0X5) > d array[0] 5 (0x5) You can display an entire array as follows: > display array { [0] = 5 (0x5) [1] = 15 (0xF) [2] = 25 (0x19) [3] = 35 (0x23) [4] = 45 (0x2D) [5] = 55 (0x37) [6] = 65 (0x41) [7] = 75 (0x4B) [8] = 85 (0x55) [9] = 95 (0x5F) } Structures are also easy to analyze using the display command as follows: > d x struct X { a = 5 (0x5) b = { [0] = 1 (0x1) [1] = 2 (0x2) [2] = 3 (0x3) } c = 11 (oxB) } 60 Chapter 3 > display z struct Z { c = 'r' 114 (0x72) d = struct Y { a = 5 (0x5) b = 6 (0x6) } e = 3 (0x3) } Multidimensional arrays are displayed in a format that enhances analysis as follows: > d x3d struct X3D { a = 2 (0x2) b= { [0] = { [0] = { [0] = 41 (0x29) [1] = 42 (0x2A) } [1] = { [0] = 43 (0x2B) [1] = 44 (0x2C) } [2] = { [0] = 45 (0x2D) [1] = 46 (0x2E) } } [1] = { [0] = { [0] = 47 (0x2F) [1] = 48 (0x30) } [1] = { [0] = 49 (0x31) [1] = 50 (0x32) } 61 Debugging Your Program [2] = { [0] = 51 (0x33) [1] = 52 (0x34) } } c = 90 (0x5a) } A conversion string can also be used as a format parameter: > display i "i is equal to %d" i is equal to 33 The dump Command The dump command provides a simple way for yoll to examine the value of any variable in your program or to examille an arbitrary range of memory. The syntax of the dump comlllalld is as follows: du[mp] [variable | address | range ] [$] [style . . . ] The variable, address, or range parameter specifies the location to be dumped. The style parameter controls the format of the dulllp. I or complete details on usirlg the dump comman(t, see tne dump section in Chapter 9. Dumping a Variable In its simplest form, dump displays the melllory at the address (tile contents) of a variable. For example, the followillg comlrlall(t disl)lays memory starting at the address of i: > dump i 003c8466: 00000021 Note that the hexadecimal value 00000021 eqllals the decimal value 33, the value of i. By default, dump displays memory in the hexadecimal format. The number to the left of the hexadecimal value, 003C8466, is the address of i. Tlle dump comlllarld always displays the addresses of the memory blocks displayed. To display memory in decimal format, use the decimal option. 62 Chapter 3 > dump i decimal 003C8466: 33 0 0 0 003C8476: 0 0 0 0 003C8486: 0 0 0 0 003C8496: 0 0 0 0 The variable parameter can be any valid C variable. When a variable parameter is specified, the amount of memory dumped is determined by the size of the object (or in the case of a pointer, the size of the object to which it points.) However, in the case of a character pointer or an address constant, 64 bytes of data are always displayed as follows: > dump string ascii 00394728: H e l l o , W o r l d \0 \0 % s 00394738: ! \n \0 \0 \0 \0 \0 \0 \0 \0 @ \0 \0 \0 \0 \0 00394748: \0 \0 \0 \0 \0 \0 \0 01 \0 \0 \0 \0 \0 \0 \0 \0 00394758: \0 \0 \0 01 \0 \0 \0 \0 \0 \0 \0 01 \0 \0 \0 01 Dumping an Address You can specify any valid address in the dump command, even addresses not under the control of your program. The following command specifies the address of the variable i. Note that the address parameter is preceded by a 0x. Here is an example: > dump 0x3c8466 decimal 003C8466: 33000 003C8476: 0000 003C8486: 0000 003C8496: 0000 Dumping a Range When a range parameter is specified, exactly that amount of data is displayed, unless the size of the range is not perfectly divisible by the size of the specified type of data items. For example, the following command specifies to dump 7 bytes of integer data starting at the first address: > dump 0x3c8466..0x3c846c decimal 0042D366: 33 -749469637 The dump actually includes an additional 1 byte of data to make up the second 4-byte integer. The dump command automatically rounds 63 Debugging Your Program the range up to the size necessary to correctly display at least all of the memory specified as the data type specified. You can also specify ranges by indicating the number of elements of a data type to display, starting at a specified address or variable. The following command dumps the decimal value of the integer i and the next 12 bytes of memory (three additional integers of 4 bytes each): > dump i L 4 decimal 003C8466: 33 2 41 4 The amount of memory that is displayed with a range option of this type depends on the size of the data type. A command with a range of four elements of type decimal will display 16 bytes. The default length of f loat for the dump command is 8, so a command with a range of four elements of type float will display 32 bytes. Dumping a Pointer Dumping pointers and memory pointed to by pointers can be confusing. In the Sample Program 2 (data . c) the following variables are defined and initialized: int i; int *intptr; i = 33; intptr = &i; The following commands dump the contents of the variable i: > dump i decimal 003C8466: 33 > dump intptr decimal 003C8466: 33 2 1 2 003C8476: 3 4 5 6 003C8486: 7 8 9 10 003C8496: 11 12 97 1927282688 > dump *intptr decimal 003C8466: 33 64 Chapter 3 > dump &i decimal 003C8466: 33 2 1 2 003C8476: 3 4 5 6 003C8486: 7 8 9 10 003C8496: 11 12 97 1927282688 All of these commands are equivalent. The dump command treats variables that are addresses as already de-referenced. The dump command assumes that, if you specify a pointer, you want to look at what the pointer is pointing at. If you want to see the actual address contained in the pointer, you can look at the first address in the dump. You will note that all of the preceding dumps have O 0 3C8 4 6 6 as the address containing 33, which is the address of i. To dump the actual address of the pointer variable, use the following command: > dump &intptr 0064F676: 003C8466 The address of the pointer is the first number displayed. Sometimes the compiler automatically stores a variable in a register. If this has occurred for a variable, the preceding command will yield the following result: > dump &intptr ^------cannot be applied to registers or constants Dumping Floating-Point Numbers The float option is used with the dump command to specify the format of floating-point numbers. The default number of bytes dumped by the float option is 8. This is equivalent to type double under C. Note that there is no double format specifier. To specify a 4-byte f loat, equivalent to type float under C, use the f loat4 option. Using the wrong format for a variable will cause the variable's value to appear incorrect. For example, compare the following commands and their results for the double variable db = 33.5 and the float variable f1 = 3.14: > dump db float4 004103FE: +3.0117187 > dump db float 004103FE: + 33.5 Debugging Your Program 65 > dump f1 float4 00410406: +3.1400001 > dump f1 float 00410406: +49.92001667991304 Dumping Integers The decimal option is used with the dump command to specify the format of integers. The decimal option dumps 32-bit (4 byte) integers. This is equivalent to type long under C, and type int if the shortinteger compiler option was not used. Note that the dump command cannot distinguish between modules compiled with 16-bit integers (using the shortintegers option) and those compiled with 32-bit integers (using the default.) Using the wrong format for a variable will cause the variable's value to appear incorrect. The following commands will dump an integer, a long, and a short. Note the required format for the short: > dump i decimal 00410436:33 > dump lng decimal 00410402: 6456 > dump shrt decimal 00410400: 5832704 > dump shrt decimal2 00410400: 89 Dumping Characters and Strings Characters and strings may be dumped in several ways. The simplest is to use the ASCII option as follows: > dump z.c ascii 00410472: r > dump string ascii 003BlB88: H e l l o , W o r l d \0 \0 % s 003BlB98: ! \n \0 \0 \0 \0 \0 \0 \0 \0 @ \0 \0 F E4 003BlBA8: \0 \0 \0 \0 \0 \0 \0 01 \0 \0 \0 \0 \0 \0 \0 \0 003BlBB8: \0 \0 \0 01 \0 \0 \0 \0 \0 \0 \0 01 \0 \0 \0 01 66 Chapter 3 When using the ASCII option, certain nonprintable characters appear as their usual C escape sequences: \b backspace \f formfeed \n new line \r carriage return \t horizontal tab \v vertical tab \o null byte (string terminator) Other characters are represented by the two-digit hexadecimal codes. You can also use the text option to display a block of data in character format. The text option displays the address of the data items on the left, the hexadecimal values in the middle, and the printable characters on the right. > dump string text 003BlB88: 48656C6C 6F2C2057 6F726C64 00002573 Hello, World..%s 003BlB98: 210A0000 00000000 00004000 0046E420 !.........@..F. 003BlBA8: 00000000 00000001 00000000 00000000 ................ 003BlBB8: 00000001 00000000 00000001 00000001 ................ The dzero command can also be used to display an ASCII text string terminated by a NULL character (\0) as shown here: > dzero string "Hello, World" The string at that location is displayed in double quotes. Normally you would use either a character pointer or an array name as the argument to this command. The register The register command has two forms, with and without parameters Command as follows: r[egister] r[egister] [register[ [=] expression ]] 67 Debugging Your Program The first form of the register command displays the contellts of all the registers, while the second form results in the specified value being placed in the named register. Displaying the Contents of Registers If you use the register command without parameters, the current contents of the registers are displayed in hexadecimal followed by the current flag settings as shown here: > register dO=OOOOOOOl dl=00000002 d2=000003ED d3=00000000 d4=00000000 dS=OOOOOOOO d6=00000000 d7=00000000 aO=OOC2C102 al=000223BO a2=OOC25CCO a3=OOC2C106 a4=OOC28F08 a5=00000000 a6=OOCOB9C8 sp=000229A8 pc=OOC32E82 ccr=OOOOOOOO na pl nz nv nc sort:\smain.c\main 110 Registers dO through d7 and aO through a6 are labeled and displayed. Register a7 is the stack pointer and is labeled sp. I'he program counter is labeled pc, and the condition code register is labeled ccr and is summarized by the two-letter flag abbreviations immediately following. Note that the current source line number is displayed immediately after the display of the registers and flags. ~Itering the Contents of Registers The second form of the register command is similar to the set command. It allows you to alter the contents of registers. You can specify the value you want placed in a register as an expression. Here is an example: > register d0=00000001 d1=00000002 d2=000003ED d3=00000000 d4=00000000 d5=00000000 d6=00000000 d7=00000000 a0=00C2C102 a1=000223B0 a2=00C25CC0 a3=00C2C106 a4=00C2BF08 a5=00000000 a6=00C0B9C8 sp=000229A8 pc=00C32E82 ccr=00000000 na pl nz nv nc sort:\smain.c\main 110 > register d7=5 > register a2=0x24la4a > register d0=00000001 d1=00000002 d2=000003ED d3=00000000 d4=00000000 d5=00000000 d6=00000000 d7=00000005 a0=00C2C102 a1=000223B0 a2=00241A4A a3=00C2C106 a4=00C2BF08 a5=00000000 a6=00C0B9C8 68 Chapter 3 sp=000229A8 pc=00C32E82 ccr=00000000 na pl nz nv nc sort:\smain.c\main 110 You also can set a register by using a program variable or other expression: > display i 33 (0x21) > register d3=i > register dO=00000001 d1=00000002 d2=000003ED d3=00000021 d4=00000000 dS=00000000 d6=00000000 d7=00000005 a0=00C2C102 a1=000223B0 a2=00241A4A a3=00C2C106 a4=00C2BF08 a5=00000000 a6=00COB9C8 sp=000229A8 pc=00C32E82 ccr=00000000 na pl nz nv nc sort:\smain.c\main 110 To set floating-point registers, refer to the fregister command in Chapter 9. The whatis The whatis command is used to determine the type of an object or Command the configuration of a type of object. It has two forms: wha[tis] expression wha[tis] (type) The expression and type parameters can be any expression or data types, including structures and unions, provided by the C language. Sample Program 2 defines the following objects: struct X { int a; int b[3]; int c; } x; typedef struct X *XPTR; The whatis command yields the following: > whatis x auto at 00221FBC (20 bytes) struct X x; 69 Debugging Your Program > whatis x.a object at 00221FBC (4 bytes) int a; > whatis x.b101 object at 00221FC0 (4 bytes) int > whatis (XPTR) typedef struct X { int a; int b[3]; int c; } *XPTR; > whatis (int) int > whatis (struct X) struct X { int a; int b[3]; int c; }; Notice that the typedefs are expanded in terms of the more fundamental types. Watches and Watch Breaks The watch commands allow you to set, list, disable, enable, and clear watches and watch breaks. A watch (also called a watch point) allows you to monitor a variable, an address, or a range of memory in order to see when the value of the variable changes or the area of memory is altered. A watch break is similar to a watch but acts as a breakpoint if the variable or area of memory changes. Like breakpoints, watches and watch breaks remain in memory until you clear them or exit the debugger. You may restart the program being debugged and still retain these watch settings. This allows you to run through the program again and again without resetting the watches and watch breaks. Watches and watch breaks are displayed in the Watch window. This window is updated when the debugger returns control to the user (as at a breakpoint), at which point the new values of the watched areas are displayed. You can open the Watch window with the F1 function key. You also can display the values of the watched areas by using the wlist command. For example, if a watch break is set on the variable tmp in the function swap in Sample Program 1, then execution will 70 Chapter 3 stop at line 6 of swap when the value of tmp changes. At this point, entering a wlist command will display the value of the watch as shown here: sort:\swap.c\swap 6 > wlist 1! tmp : 0 (0x0) The 1! refers to the numbered entry in the watch list. Watches provide a convenient way to watch memory on a continuing basis. It is often easier to examine the Watch window instead of entering a display or dump command after every step or breakpoint. You can also use the Memory window to keep track of an area of memory. Watch breaks can help you locate problem areas with precision. Often a variable or block of memory may be altered or corrupted at an unknown point in a program's execution. It can be very difficult to pinpoint the exact location where the corruption took place. By setting a watch break on the variable and executing the program, the problem can be isolated quickly. The watch and wbreak Commands The watch command is used to set watches, while the wbreak command is used to set watch breaks. The syntax of these commands is as follows: w[atch] variable | address | range [s[tatic] | d[ynamic]] wb[reak] variable | address | range [ s[tatic] | d[ynamic]] The variable, address, or range parameter specifies the location of the watch or watch break. The optional static or dynamic flag specifies the way in which the debugger evaluates the location of the object being watched. (See Chapter 9 for more information.) By default, watches are dynamic. This means that an expression being watched is re-evaluated whenever control is returned to the debugger. The static flag causes the address of a watched expression to be evaluated once when the watch is set. Conversely, watch breaks are static by default. The dynamic flag is used to specify that the address of a watch break should be re- evaluated every time control is returned to the debugger. With the watch command, the new value of the watched object is displayed in the Watch window whenever control is returned to you Debugging Your Program 71 (for example, at a breakpoint). If the Watch window is not open, you can use the wl i st command as a way of determining the new value. Watches (and watch breaks) can be set on structures or arrays by name. When this is done, the specification of the aggregate name is treated as an implicit range and a watch is set on that range. Assume the following declarations are in effect: struct x { int i; char a[20] ; double d; } x; char string[80] ; A watch can be set on ranges as follows: > watch x > watch string[5] L 10 > watch &string[17].. &string[19] Watches and watch breaks can be set on formal or automatic variables. In this case the watch is in effect only as long as the function-defining variable is executing. If you set a watch on a formal or automatic variable, the watch list displays the watch as not active when execution is taking place outside its defining function. When the function is re-entered, the watch is re-activated. You should, however, use caution when using variables to specify a range. For example, suppose that aut is an automatic variable and sta is a static variable. Issuing the following command sets a watch on the memory between the address of aut and the address of sta as follows: > watch &aut &sta Of course, the address of aut could change a number of times as its function is entered, executed, and exited. In the case of such artificial ranges the debugger translates the symbolic names into their current absolute address equivalents and sets the watch on the absolute address range. It is this absolute address range that is displayed in the watch list. In general, this sort of translation from symbolic range to absolute range takes place when the two variables you use to specify 72 Chapter 3 the range do not resolve to addresses within the same aggregate (structure, union, or array). While watch breaks can be useful in monitoring program execution, they are expensive in terms of execution time. You should expect your program to execute hundreds of times more slowly when watch breaks are enabled. This is not true of watches since the information for these is updated only when control is returned to you by the debugger. Watch breaks should be disabled whenever possible to speed execution. One way you can do this is to enable and disable a watch break dynamically depending on program conditions as shown here: > wbreak i > wdisable 1 > break sort 9 {we 1; go sort 20; wd 1; go} This command sequence installs a watch break whose number in the example is assumed to be 1 and then it sets a breakpoint that automatically enables the watch break, executes up to a certain point, disables the watch break, and continues execution. In this way, you can force the watch break to be active only when a certain portion of your program is executing. 73 4 Setting Up the Debugging Environment 73 Introduction 74 The debug= Options 76 Which Debugging Option To Use 77 Determining Source File Location 78 Choosing Command-line Options 81 CodeProbe Initialization 82 Setting and Showing Options within CodeProbe 83 Source Mode 84 Echo Mode 84 Instruction Bytes 85 Ignore Path 85 Case Sensitivity 85 Context 86 List Default 86 Unassemble Default 86 Radix Default 86 String Length 86 Array Dimension 87 Range Length 87 Maximum Bad Chars 87 Search Path: 88 Autoswap Mode 88 Catch New Devices 88 Step Into ResLib 89 Current Task 89 Catch New Tasks 89 Customizing Dialog Window Commands 89 The Alias Command 92 The Unalias Command 92 The Define Command 94 The Undefine Command Introduction To use CodeProbe efficiently, you need to know how to set up the optimal debugging environment for your particular application. This 74 Chapter 4 involves choosing the best debugging option to use, determining where to locate source files, and selecting necessary command-line options. This chapter discusses these and other topics pertinent to customizing your debugging environment. This section also describes the command used to invoke CodeProbe, cpr. Selecting the correct options for CodeProbe can determine whether a debugging session will be productive and useful. The debug= Options The degree to which CodeProbe can access symbols defined in a module is determined by the compiler debugging option used in compiling that module. The debug= option can be used with any of the following keywords to activate the debugging mode of the SAS/C Compiler: line or l generates the line number/offset table only. symbol or s in addition to the line number/offset table, generates full debugging information for those symbols referenced in the module. symbolflush or sf in addition to the line number/offset table, generates full debugging information for those symbols referenced in the module. Also forces the code generator to flush all registers to variable locations at line boundaries. full or f in addition to the line number/offset table, generates full debugging information for all symbols declared in the module even if there is no reference to them in the generated code. fullflush or ff in addition to the line number/offset table, generates full debugging information for all symbols declared in the program even if there is no reference to them in the generated code. Also causes the code generator to flush all registers at line boundaries. Each of the debug= options is described in more detail later in this section. You can mix modules compiled with different levels of debugging in the same program. The nodebug option can be used to suppress the generation of debugging information. nodebug is the default. The addsym option can be used to tell the linker to add symbol information to files that are compiled without debugging information. If a file was compiled with debugging information, addsym is not required. 75 Setting Up the Debugging Environment The debug=line Option Specifying the debug=line option causes the compiler to output the line number/offset table only. As a result of using the line option, the debugger can match the lines in a source file with the loaded code. This allows you to set breakpoints at source lines and step through the source code. In addition, some limited symbolic information is available for external variables and functions. Only the address of a symbol is available. There is no information about the symbol's attributes. For this reason, the debugger will attempt to display any variable as a long by default with the following warning message: > display fahr accessing extern with unknown attributes - assuming long 1101004800 (0x41A00000) To display a variable in its proper form, use a type cast with the display command as follows or use one of the dump commands. > display (float) fahr 20 See Chapter 9, "Commands and Built-in Functions," for details on the display and dump commands. While the line option provides limited information to the debugger, it is useful with large programs or when disk space is limited because it produces much smaller object files. The line option also provides all the information needed by the disassembler, omd. The debug=symbol Option Specifying debug=symbol causes the compiler to output full debugging information for all global and local variables, all functions, and all types referenced in the module, including s tructure, union, enum, and typedef types. If a module is compiled with this option, you can set breakpoints at source lines, display or alter data symbolically, set watches on variables or areas of memory, and list source code. The display command will properly format all data declared in the module. Debug information for a structure or union definition is generated only if it is used in a typedef declaration or as either a global or local variable. That is, if the structure or union is defined in a header file that is included by your program, but the tag associated with that structure or union is not used by your program, then no debug information will be generated for that tag. Most source modules use 76 Chapter 4 numerous include files that contain definitions that are never actually used. By limiting debug information to include only referenced definitions, the output module size is greatly reduced. The compiler will often manipulate a variable's contents in registers over several lines of code without replacing the results in the variable. If a breakpoint is reached in this section of code, the debugger will display the value in memory, not in the register. If you suspect that the debugger is not displaying the proper values, the code can be inspected in mixed mode, or the file can be recompiled with the symbolflush option. Note that register variables (automatic and formal variables that are only assigned to registers) will always be found in their proper register. The debug=symbolflush Option Specifyillg debug=symbolflush causes the compiler to output full debugging information for all global and local variables, all functions, and all types referenced in the module, including structure, union, enum, and typedef types. It does not generate debugging information for types that are defined but not referenced in the module. The symbolflush option also causes the code generator to Tflush all registers to variable locations at C source line boundaries. This can be useful because the debugger takes the value of a variable from its memory location, not a temporary register. While this option is recommellded for use with the debugger, it causes inefficient code generation. Any module compiled with this option should be recompiled before it is placed into production. The debug=full Option The debug=full option is similar to the debug=symbol option except that inforrnation for all declarations and definitions is generated including those that are defined but not referenced in a module. The debug=fullflush Option The debug=fullflush option is similar to the symbolflush option except that information for all declarations and definitions is generated including those that are defined but not referenced in a module. Which Debugger Option to Use In order to make full use of the debugger's features, you should always use either the symbol, symbolflush, full, or fullflush option. If the cornpiler keeps the value of a variable in a register, as it may in order to eliminate unnecessary loading and storing of values in its 77 Setting Up the Debugging Environment registers, then the true value of a variable at any given time may be in a register rather than in the variable's memory location. As a consequence, the value of the variable displayed by the debugger may not be its correct value. The s ymbolflush and fullflush options force the correct values of variables to be in the memory locations of the variables at line boundaries but at the cost of generating extra code required to store, and perhaps reload, the values. Only the symbolflush and fullflush options affect the quality of code generated by the compiler. The other options do not affect code generation and differ only in the amount of symbolic information they pass on to the linker. If you want to debug exactly the program you intend to use, you should use symbol or full rather than symbolflush or fullflush, and you should debug in mixed mode so that you can see the machine instructions corresponding to your C source lines. The opt source mixed command is used to specify mixed mode. When you do this, you will be able to tell if the value of a variable is being kept in a register rather than being flushed to memory, and you can then use the register command rather than the display or dump commands to determine the variable's value. See Chapter 9 for more details about these commands. To produce the final version of your program, use the stripdebug option of slink. For example, the following command will strip debugging information from an existing executable file, source-filename, and place it in a second file, destination-filename: slink from source-filename to destination-filename stripdebug If you are not concerned with debugging production quality code, you should use the symbolflush option, since the difference in generated code will have little effect. Even if you are attempting to create a piece of production software, you should begin your debugging by using the symbolflush option and then recompile with the symbol option when most of your bugs have been detected and repaired. Determining Source File Location If you have compiled your program with any of the debug= options, CodeProbe reads the name of the source file from the program being debugged. By default, this is the same name you passed to the compiler with the sc command. If you specify a full or partial pathname for your source file, the pathname is included. You can change the filename specification in the program's debugging information by using 78 Chapter 4 the sourceis option when you compile your program. Refer to Chapter 8, "Compiling and Linking Your Program," in SAS/C Development System User's Guide, Volume I for more details. You may want to direct CodeProbe to look for source files on a different disk or at a different location on the same disk by using the opt search command described later in this section. If CodeProbe cannot find the source file for the function it is currently executing, it displays the following message: Error: error opening source file filename Your source code will be displayed as long as you have used some debugging option, other than the nodebug option, with the compiler. The CodeProbe source command can be used to override the filename specified in the debugging information. This new association is remembered by CodeProbe throughout the current session. This command can prove useful when the name of the source file has been changed since the program was compiled. Choosing Command-line Options The CodeProbe environment can be customized by including command- line options when invoking the debugger. The format of the command is as follows: cpr [cpr-options] application-name [application-arguments] For information on how to use command-line options with the program you are debugging, see Chapter 1, "Introduction to CodeProbe." If you invoke CodeProbe from the Workbench screen, you can use command-line options by adding them as tool types to the debug icon created by scsetup. To add tool types, click on the icon, then select Info from the Workbench menu under AmigaDOS Version 1.3, or Information from the Icons menu under AmigaDOS Version 2.0. You can use the following command-line options when invoking CodeProbe: -buffer specifies the size of the Dialog window buffer. By default the Dialog window saves the last 4096 bytes displayed so that you can scroll 79 Setting Up the Debugging Environment backwards and review output. This size can be increased or decreased with this option. The syntax of the option is as follows: cpr -b[uffer] size The size parameter specifies the size of the buffer in bytes. -cli instructs CodeProbe to invoke the application as a CLI (Shell) process. CodeProbe passes arguments to the application through the normal command line interface. This option is the default if CodeProbe is invoked from a Shell. The option is necessary if CodeProbe is invoked from the Workbench screen, and you want your program to run as if invoked from a Shell. -command executes debugger commands at startup. The commands are executed after go main if the -startup option is not specified or after the profile script if it is specified. Profile scripts are discussed later in this section. For example, the commands cpr -command "proceed; display fahr" program-name would execute to main, step over 1 line of code, and display the variable fahr in the Dialog window before giving control to you. -i sets up a screen in interlace mode. By default, CodeProbe opens a new screen using the specifications set up by Preferences for Workbench screens. To force a screen to be opened in interlace mode, include the -i option before typing the application command name. -line starts CodeProbe in line mode. Line mode causes the debugger to run in the current Shell window. The equivalent of the Dialog window is provided, with no other windows available. Line mode is probably only useful for running from a script file, redirecting output using the Shell redirection facility, or running from a remote terminal over a communications port. -noprofile suppresses execution of the CodeProbe startup file. When CodeProbe is invoked, it automatically executes a script file named cprinit, which must be located in either the current directory or 80 Chapter 4 ENV:sc. If the startup file is found in the current directory, ENV:sc iS not searched. -screen instructs CodeProbe to open its windows on the named public screen. The syntax of the command is as follows: -sc[reen] name By default, CodeProbe creates a new public screen when it is invoked. If this option is specified, CodeProbe looks for an existing public screen with the given name, and if one is found it uses that screen to display its windows. If a screen with the given name does not exist, a new one is created with that name. To use the Workbench screen, specify -screen workbench. Public screens are a feature of Intuition 2.0. For users of earlier versions of Intuition, this option is not generally useful. However, specifying -screen workbench causes CodeProbe to use the Workbench screen on older releases. -startup suppresses the automatic go main that is normally executed by the debugger on startup. This option is useful if your application redefines _main or c.a so that no main function exists, or if you want to step through such code. If this option is used, no initialization of any kind will have been performed by the application process before control is given to you. If the quit, start, or restart commands are invoked and an application process has not exited, the debugger normally calls exit to clean up any process resources that may not have been freed. However, if the -startup option was used, exit will not be called. -w runs CodeProbe on the Workbench screen. This is the same as specifying -screen workbench. -wb instructs CodeProbe to invoke the application as a Workbench process. It passes arguments to the application through a Workbench startup message. This option is the default if CodeProbe is invoked from a Workbench icon. The option is necessary if CodeProbe is invoked from a Shell, but you want the application to run as if invoked from the Workbench screen. 81 Setting Up the Debugging Environment -wdialog, -wregister, -wsource, -wwatch specifies start up window coordinates for the Dialog, Register, Source, and Watch windows, respectively. Window coordinates are measured in character positions. A width or height of 0 causes the window to extend to the screen border on the right or bottom, respectively. The option names can be abbreviated to two letters: -wd[ialog] left top width height -wr[egister] left top width height -ws[ource] left top width height -ww[atch] left top width height Here is an example: cpr -ws 0 1 50 12 -wd 0 13 50 0 ftoc Note that the Register and Watch windows will not be displayed on startup; however, when they are opened by pressing the appropriate function key (either Fl or F4), they will open to the coordinates specified on the command line. -. suppresses the copyright banner that is displayed at startup. CodeProbe Initialization Since you will probably want CodeProbe to start the debugger with the same options most of the time, CodeProbe allows you to create a debugger command script file that is executed each time the debugger is invoked. The profile script, named cprinit, is executed after the initial go main but before any commands specified with the -command option are executed. CodeProbe first looks for cprinit in the current directory and then in the ENV: SC directory. Only one cprinit script will be run; therefore, if a script is located in both directories, the one in the current directory is used. The following are examples of scripts displayed from the Shell window using the AmigaDOS type command: 1> type cprinit /* This is the debugger startup profile */ 82 Chapter 4 opt search dh0:mysource, df0:mysource, ram: opt radix h opt ibytes off 1> type env:sc/cprinit /* This is a debugger profile script for a project */ opt source mixed proceed display argc, argv Note that C style comments can be placed in profile scripts as long as they exist on a single line. Setting and Showing Options within CodeProbe In addition to the command-line options discussed above, a number of options can be set from within CodeProbe to customize the way information is displayed or handled. Most of these options are modified with the opt command or through the Options menu. To see the default options while in the debugger, activate the Options menu or execute the opt command without any parameters as follows: > opt Source mode.........c Echo mode...........Off Instruction bytes...Off Ignore path.........Off Case sensitivity....Off Context.............2 lines List default........6 lines Unassemble default..4 lines Radix default.......Decimal String Length.......128 Array Dimension.....20 Range Length........64 Maximum Bad Chars...3 Search path: Autoswap mode.......Off Catch New Devices...No Step into ResLib....No Current Task........sort at 0001DC20 Catch New Tasks.....No 83 Setting Up the Debugging Environment A CPR initialization script can be used to change options automatically when you invoke the debugger. See "CodeProbe Initialization" earlier in this chapter for more information. Source Mode There are three source modes: C, assembly, and mixed. The current source mode can be determined by means of the opt command or by activating the Options menu. It can be changed by means of the opt source command or the Source selection in the Options menu. C source mode is the default. The syntax of the opt source command is as follows: op[t] so[urce] c | a[sm] | m[ixed] | n[ext] Repeatedly choosing opt source next cycles through the three possible source modes. C Mode In C mode, CodeProbe displays C source lines when the trace or proceed commands are executed or when a breakpoint is triggered. To change the current source mode to C mode, enter the following command: > opt source c While in C source mode, you cannot single step by assembly instruction. Assembly Mode In assembly mode, disassembled code is displayed in the Source window. Single trace or proceed commands will step by assembly instruction. To change the current source mode to assembly mode, use the following command: > opt source asm Mixed Mode In mixed mode, both assembly instructions and C source lines, if available, are displayed in the Source window. For each C source line displayed, the corresponding assembly instructions are displayed as well. 84 Chapter 4 To change the current source mode to mixed mode, enter the following command: > opt source mixed In mixed mode, you can take advantage of the two different forms of the trace and proceed commands in order to step by either C source line or assembly instruction. Echo Mode When echo mode is on, commands are echoed in the Dialog window before being executed. This option is useful if you want to execute debugger command files and see the command lines as they are executed along with their output. Commands that are invoked by menu selections or double-clicking the mouse are also displayed as they are executed. By default, this option is set to of f . It is not needed while entering commands in the Dialog window because command lines are displayed as they are entered anyway. The syntax is as follows: op[t] e[cho] [on | off] Instruction Bytes The ibytes option affects the display format of disassembled code in the Source window and the output of the unassemble command. If the option is set to on, the second field of the disassembly contains a hex dump of the instruction. The following fields contain the op-code and its operands. If the option is set to off, the hexadecimal dump is suppressed. The syntax is as follows: op[t] ib[ytes] [on | off] Here is an example: > opt ibytes on > unassemble 7 main: 7{ 0025F950 48E70130 MOVEM.L D7/A2-A3,-(A7) 0025F954 BFEC0004C MPA.L 0004(A4),A7 0025F958 65001BD6 BCS 00261530 > opt ib off > unassemble 7 85 Setting Up the Debugging Environment main: 7 { 0025F950 MOVEM.L D7/A2-A3,-(A7) 0025F954 CMPA.L 0004(A4),A7 0025F958 BCS 00261530 Ignore Path If the ignorepath option is set to on, CodeProbe ignores the directory part of the source filename. In this case, CodeProbe looks in the current directory for the source file. By default, ignorepath is set to of f and CodeProbe uses the entire pathname when searching for the source file. The syntax is as follows: op[t] ig[norepath][ on | off ] This option is useful in conjunction with the opt search command to override the source filename specified in the object file. For more information, see the SOURCEIS option in Chapter 8, "Compiling and Linking Your Program," of the SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor. Case Sensitivity The case option controls case sensitivity for the search command. The search command is used to search for a string in the Source window. When case is set to on, a case-sensitive search is made whenever a search command is executed. The syntax for the case option is as follows: op[t] cas[e][ on | off ] Context As you proceed through an application program by tracing and breakpointing, CodeProbe always keeps the current source line or assembler instruction displayed in the Source window. CodeProbe attempts to keep at least a minimum number of context lines of code displayed above and below the current line. The number of these context lines can be controlled by the context option. Note that, in mixed mode, it is not always possible to keep the right number of lines above or below, but the source code line will always be displayed and the assembler instruction will be displayed if possible. The default number of context lines is 2. The maximum number of context lines possible is limited by the number of lines in the Source window. The syntax is as follows: op[t] co[ntext] integer 86 Chapter 4 List Default The list option determines the number of source lines displayed by the list command. The list command is discussed in Chapter 9. The default value for this option is 6. The syntax is as follows: op[t] l[ist] integer Unassemble Default The unassemble option determines the number of instructions displayed by the unassemble command. The default value for this option is 4. The syntax is as follows: op[t] U[nassemble] integer Note that the default value is only used when no source file is available. When a source file is available for a section of code, unassemble displays the disassembly for a single source line by default. Radix Default The radix option controls the default input type for constants. The choices are decimal and hexadecimal. The default is decimal. When set to hex, this option can be used to avoid having to type the initial 0x on hexadecimal constants. The syntax is as follows: op[t] rad[ix] [d[ecimal] | h[ex]] String Length The strlen option controls the maximum number of bytes that are displayed when a character string is displayed with the di spl ay or dzero commands. If the string contains bad characters, fewer may be displayed. The default is 128. The syntax of the strlen option is as follows: op[t] st[rlen] integer The integer parameter specifies the number of bytes. Array Dimension The arrdim option specifies the maximum number of array elements that will be displayed by the display command. The syntax for the arrdim option is as follows: op[t] ar[rdim] integer The integer parameter specifies the maximum number of array elements. The default value is 20. Arrays with integer or fewer 87 Setting Up the Debugging Environment elements are displayed in their entirety. Larger arrays will have their first integer elements displayed followed by an ellipsis (. . .). Range Length The rangelen option controls the default size of memory dumps when no other source of information is available, for example, when dumping an absolute addresss. The rangelen option is used when commands such as display, dump, or watch have only an address parameter. The rangelen option specifies the number of elements after the address to display, dump, or watch. The syntax for the rangelen option is as follows: op[t] ran[gelen] integer The integer parameter specifies default range size in number of elements of a type to be displayed. The default value is 64. Maximum Bad Chars The badchar option determines how many nonprintable characters must be encountered before the dzero or display command stops printing a string. The syntax of the badchar command is as follows: op[t] b[adchar] integer The integer parameter specifies the number of nonprintable characters allowed. The default value is 3. A 0 indicates no limit. Search Path: The search path is used to find the source modules used when compiling the application. When a module is compiled with one of the debug options, the full pathname of the source module is saved in the debug information. CodeProbe always looks for the source module in its original location first, then it looks in the current directory, and finally, it walks through each of the directories specified in its search path in order. If you have moved the source module to some other location, use the opt search command to add the new location to your search path. The opt search command takes four forms: Op[t] se[arch] op[t] se[arch] dir[, dir[...]] op[t] se[arch] + dir[, dir[...]] op[t] se[arch] - dir[, dir[...]] 88 Chapter 4 The first form lists the current paths in the search path list, which is empty by default. The second form sets the search path to the list of directories on the command line. The third form appends the list of directories on the command line to the current search path. The last form deletes the list of directories from the current search path. This list is empty by default. Here are some examples: > opt search c:, df0:, dh0:mysource > opt search + df1:test > opt search - df0:, c: The search option cannot be set from the Options menu. Autoswap Mode When in autoswap mode, the screen containing the application's output is pushed to the front each time CodeProbe gives control to the application. When a breakpoint is reached, the debugger screen is again pushed to the front. If you are single stepping through source code, the switching of screens will probably appear as a brief flash. If the autoswap mode is set to of f, which is the default, the application screen will not be pushed to the front. The autoswap feature can be set to on or of f with the opt command. The syntax is as follows: op[t] au[toswap] [ on | off ] Autoswap mode is particularly useful when debugging programs that require input from the keyboard. The application's screen is displayed whenever input is required. Catch New Devices When a device is opened for the first time a new task may be created. If the process that opened the device is under debugger control, then CodeProbe will catch the new task provided the Catch New Devices option is set to on. The default setting for this option is off . The syntax for the devices option is as follows: op[t] d[evices] [ on | off ] Step Into ResLib The Step Into ResLib option allows the user to decide whether to allow CodeProbe to step into resident libraries while tracing or runrling an application with watch breaks. This option should remain set to of f (default) unless you want to debug your own resident libraries. Tracing into systern libraries such as Exec or Intuition can lead to problerns. If this option remains off, it is safe to run with watch breaks on while stepping over system resident libraries. However, you should 89 Setting Up the Debugging Environment disable all watch breaks before stepping into a ROM-resident library routine. The syntax for the reslib option is as follows: op[t] res[lib] on | off Current Task The current task is displayed by entering the opt command with no parameters. This information cannot be displayed through the Options menu. The following line indicates that a program named sort is the current task and that execution has stopped at address 0001DC20. Current Task........sort at 0001DC20 The current task cannot be changed with the opt command; however, you can use the jump command to change the execution point. Catch New Tasks Whenever a new task is started by a task under CodeProbe's control, the new task is also under CodeProbe's control by default. This does not apply to tasks started by a call to the OpenDevice function. The catch option enables you to turn task catching on or off. The syntax of the catch command is as follows: cp[t] ca[tch] [ on | off ] Customizing Dialog Window Commands In order to provide CodeProbe with a more versatile command interface, the alias and def ine commands can be used to customize the Dialog window commands. Aliases enable you to redefine or customize commands. This capability is similar to the aliasing capabilities found in the Shell. Defines provide CodeProbe with a macro facility modeled after the C language's preprocessor #def ine facility. The Alias Command The alias command is used to create new aliases, display the definition of an existing alias, or display a list of all currently existing aliases. The syntax for the alias command is as follows: a[lias] [name[definition]] When entered with no parameters, the alias command displays the list of all currently defined aliases, with the alias listed on the left 90 Chapter 4 and the associated command on the right. The following example shows the list of aliases already defined for you by CodeProbe: > alias da dump $* $ ascii1 db dump $* $ hex1 text dc dump $* $ dec1 dd dump $* $ float8 df dump $* $ float4 dffp dump $* $ ffp4 di dump $* $ dec4 dl dump $* $ dec4 dp dump $* $ hex4 ds dump $* $ dec2 dw dump $* $ hex2 The definition for an existing alias is displayed if the alias command is entered with only the name argument. The following alias command causes the definition for the dffp alias to be displayed: > alias dffp dffp dump $* $ ffp4 Alias names are only expanded when they occur at the beginning of a command line. An alias definition can be a simple textual substitution or it can contain positional parameters to be expanded at execution time. Positional parameters are specified as $1, $2, $3, and so on. $0 represents the alias itself. $* represents all command-line parameters. If no positional parameter is specified in a definition, all parameters are placed after the expanded definition until it encounters a semicolon (;) or an end of line. To define an alias that expands into more than one command, enclose the definition in either double quotes ("") or curly braces ({ }). If the command string must contain double quotes, curly braces must be used or the quotes must be escaped. A backslash (\) can be used to continue the line. 91 Setting Up the Debugging Environment The following are examples of the alias command: > alias print display > alias dw dw dump $* S hex2 > alias look2 "g $1; where; g S2; where" > alias printgo {print "vars: ", S*; gO} After entering these alias commands you could enter the following command lines: > look2 sort swap sort:\sort.c\sort 20 1* In routine sort:\sort.c\sort 20 2 Called from sort:\smain.c\main 13 (+0xC) 3 Called from 0xC3162E sort:\swap.c\swap 5 1* in routine sort:\swap.c\swap 5 2 Called from sort:\sort.c\sort 26 (+0x12) 3 Called from sort:\smain.c\main 13 (+0xC) 4 Called from 0xC3162E > print tmp 10 (0xA) > dw x 0036c4a4: 0000 0001 > go sort > printgo i, p[i] vars: 0 (0x0) 0 (0x0) Program exited with code 0. The alias definitions in the previous example expand to the following commands: display tmp dump *y hex 2 g sort; where; g swap; where display "vars: ", i, p[i]; go If at least one parameter is specified in a definition, all unused parameters are thrown away in the expansion. Any unspecified parameter results in an empty expansion. For example, assume the 92 Chapter 4 alias given previously for look2. You can enter the following command lines: > look2 func1 func2 func3 > look2 func1 These command lines are expanded as follows: g func1; where; g func2; where g func1; where; g ; where Aliases can be nested in the definitions of other aliases. If the debugger detects a circular reference between aliases, it will expand until it detects the cycle. If an alias references itself, the reference will not be expanded. For example, alias where where args does not cause an infinite loop. Aliases can be used to redefine any native CodeProbe command except alias and unalias . To reference a command that has been aliased, escape the command name with a back-tick character ( ` ). For example, the following sequence defines aliases for the set and enter commands so they function as they did in CodeProbe Version 5.10: > alias set opt > alias enter `et Note the back-tick character used to escape the set command. The Unalias Command The unalias command removes entries from CodeProbe's list of aliases. The syntax for the unalias command is as follows: unal[ias] name unal[ias]* The name parameter should match the alias name to be removed. The asterisk (*) is used to remove all aliases. The Define Command The define command provides a more general macro text substitution facility than the alias command. Just as with the C preprocessor's definitions, macros defined in CodeProbe are expanded anywhere within a line of text unless hidden inside of double quotes. CodeProbe will not expand macro definitions that have been escaped 93 Setting Up the Debugging Environment by a back-tick character. The syntax for the def ine command is as follows: [#]def[ine] name [ definition ] [#]def[ine] name ( parm [, parm . . . ] ) [definition] The name parameter specifies the text to be replaced, and the definition parameter is the substitution text. In the second form, parameters are specified exactly as in the C language. Using the de f i ne command with no arguments displays all macro definitions currently recognized. Some examples are as follows: > define PI 3.14159 > display PI 3.14159 > define ISEQUAL(a,b) (a == b) > display ISEQUAL(1,5) 0 (0x0) > expand ISEQUAL(1,5) (1 == 5) To define a symbol to nothing, omit the def inition parameter as shown in the following command: > define FOO One difference between the C preprocessor #define capability and CodeProbe's is that the debugger treats def ine as a command statement, meaning that it will stop parsing the def ine when a semicolon is reached. To have CodeProbe treat a semicolon as part of a definition, precede it with an escape character as follows: \; The define command is intended to be used to define expressions. Although you can use the def ine command to create new commands, you should use the alias command to create custom commands. 94 Chapter 4 The Undefine Command The undef ine command removes a definition from CodeProbe's definition list. Compiler generated symbols may not be undefined. The syntax for the undef ine command is as follows: und[efine] name und[efine] * The first form removes the macro with the specified name from the definition list. The second form removes all definitions from the list. 95 5 Working in Cross- Development Mode 95 Introductlon 95 Why Debug in Cross-Development Mode? 96 Using the Cross Debugger 96 Preparing to Use the Cross Debugger 96 Running the Cross Debugger Introduction Version 6.0 of the SAS/C Development System comes with a new debugging capability: cross-debugging. This means that you can have your program run on one Amiga system, and debug it from another Amiga system. This is extremely useful when debugging a program that shuts down WorkBench, partially takes over the machine, or makes heavy use of graphics. When running in cross-development mode, CodeProbe communicates with a small kernel that controls the application via a serial communications port or over a network. Why Debug in Cross-Development Mode? There are several reasons why you may want to debug in cross- development mode: It is easier sometimes to see and send input to both the application and debugger if they have their own separate monitors and keyboards. Some applications use low-level graphics control, which takes control away from Intuition. Since CodeProbe's windowing system is built on top of Intuition, you cannot communicate with it while such an application is running. With very large applications in tight memory situations, there may not be enough memory available for both CodeProbe and the application. The CodeProbe cross-debugger kernel that runs on the machine with the application is small (less than 30K). It allows the application to use most of the available memory. Disk space limitations may make it difficult to have the debugger, all the necessary source files, and a copy of the application with debug 96 Chapter 5 information available on the same machine along with all the files needed by the running application. If the program being debugged crashes, you can continue to work on the machine with the source code while it is rebooting. Using the Cross Debugger In the following discussion, the machine containing the source code and the cross debugger (CPRX) is referred to as the host machine. Your actual debugging session occurs on the host machine. The machine on which the application will run under the kernel's control is referred to as the target machine. The cross debugger and kernel communicate with each other over a serial link or via a named pipe. Using named pipes, you can debug your program from an Amiga system connected to the target machine via a network. Preparing to Use the Cross Debugger To use the cross debugger, you will need two Amiga machines. You can use a NULL modem cable to connect the machines, or you can even debug over the phone, if both Amiga machines are connected to modems. If you use the serial port, use the serial icon in the Preferences menu to select the highest baud rate acceptable. With a NULL modem cable, 19200 works fine. Over the phone you probably will need to specify the maximum speed accepted by your modems. Running the Cross Debugger Two files must be installed on the target machine: the kernel (CPRK), and the application program that is to be debugged, unless the -x option is used. CPRX can automatically strip the application program of debug information and install it on the target machine if the -x option is used. CPRK provides direct control of the application program on the target machine. It communicates with CPRX, which is running on the host machine, over a serial line or through a pipe across a network. CPRK displays its copyright information and diagnostic output in a CLI window. CPRX runs like CodeProbe, except that the program being debugged runs on another machine. On the host machine, you need the source to your project and the executable file for the program you want to debug. The executable file should have been built with debug information. Debugging a program in cross development mode is a four-step process: 1. Start the kernel (CPRK) on the target machine. 2. Start the cross debugger (CPRX) on the host machine. 97 Working in Cross-Development Mode 3. Debug your application program. 4. Enter the f ini sh command in CPRX to terminate CPRK and CPRX. Note: When debugging over a serial port, you must start CPRK before starting CPRX. When using named pipes, the order does not matter. Defining the Communications Parameters CPRX and CPRK take the following command-line options that define and set parameters for the communications medium: -pipe [ name ] specifies that a named pipe is to be used instead of the serial port. If name is not specified, pipe: cpr is used. CPRX or CPRK will open two pipes using name as a base, name_ d and name_ k. To communicate successfully over a network, either CPRX or CPRK must be invoked with a pipe filename referring to a pipe on the other machine. If your network allows you to refer to a pipe device on an attached machine by specifying net: pipe/ you could invoke CPRK on the target machine with the option -pipe net:pipe/cpr and invoke CPRX on the host machine with the -pipe option and no parameters. This method works with the popular freely redistributable network parnet, written by the Software Distillery. -device [name] specifies that the named device should be opened for communications if -pipe was not specified. The default is serial.device. -unit [number] specifies the unit number of the communications device if -pipe was not specified. The default is zero (O). -speed [number] specifies the baud rate of the communications device if -pipe was not specified. The default is the value set in preferences. 98 Chapter 5 searting the Kernel (CPRK) Start the kernel on the target machine with the following Shell command: cprk [options] The only options CPRK accepts are the communications configuration options previously listed. CPRK cannot be invoked from the Workbench screen. Once invoked, CPRK acts as a server, waiting for a request to start a debugging session from a CPRX invocation on another machine. Note that if you are using the serial device, CPRK must be invoked before CPRX is invoked on the host machine. Starting the Cross Debugger (CPRX) Start the cross debugger on the host machine with the following Shell command: cprx [options]target-executable-filename [program-options] CPRX cannot be invoked from the Workbench screen. The target-executable-filename parameter is the name of the program to be debugged. By default, CPRX and CPRK look for the program in the current directory of both the host and the target machines. If the specified executable name is an absolute path, CPRX and CPRK look in that location on both machines. If the executable file is located in different places on the target and host, then use the -symf ile option on CPRX to specify where the executable file resides on the host machine. CPRK will still look in the location specified by target-executable-filename. Anything on the command line after the target-executable-filename is passed to the target program as command- line arguments. CPRX can be invoked with any of the options available to the native debugger (CPR) or with any of the communications configuration options previously listed. In addition, CPRX accepts the following options: -symfile filename specifies the location of the executable file on the host machine. Use this option if the location is not the same on the host and target machines. -nok[check] turns off checksum checking. By default, CPRX and CPRK examine a checksum on the executable files on the host and target machines 99 Working in Cross-Development Mode to verify that both sides are using the same executable file. If the checksum fails, CPRK does not load the program. -x strips all debugging information from the host's version of the executable file, copies the stripped version to the target machine, and tells CPRK to invoke the just-transmitted version. This allows CPRK to run constantly without changing disks or rebooting (as long as your program does not crash). Example 1 Suppose you want to start a cross-debugging session to debug a program named myprog using the serial port at 19200 baud. Assume that the program to be debugged resides in the current directory on the host machine, so use -x to copy it over. The following commands can be entered on the target and host machines: target machine cprk -speed 19200 host machine cprx -x -speed 19200 myprog Example 2 Suppose you want to start a cross-debugging session to debug a program named myprog using parnet and named pipes. Assume that the program to be debugged resides in TEMP: on the target machine and in work: test on the host machine. The following commands can be entered on the target and host machines: target machine cprk -pipe net:pipe/cpr host machine cprx -pipe -symfile work:test/myprog temp:myprog Debugging Your Application Once started, the cross debugger behaves just like the normal debugger, except entering CTRL-C in the CPRX Dialog window does not always stop the program executing on the target machine. All interaction with the debugger occurs on the host machine via CPRX; all interaction with the program being debugged occurs on the target machine in the normal fashion. Terminating CPRX and CPRK If communications have not yet been established, you can terminate CPRX or CPRK by entering CTRL-C in the Shell window that you 100 Chapter 5 used to invoke the command. If CPRX does not open its windows after you invoke it, communications have not been successfully established. Once the program is loaded, you can choose to terminate debugging one of two ways: Terminate both CPRX and CPRK by entering the finish command in the CPRX Dialog window. The syntax is as follows: fin[ish] The program being debugged will automatically be terminated if it has not yet completed. Terminate only CPRX by using the normal CPR quit command. CPRK will continue running for use with a future CPRX debugging session. The program being debugged will automatically be terminated if it has not yet completed. You should allow your program to run to completion if possible before entering finish or quit to ensure that it cleans up all resources. 101 6 Using AREXX Macros with CodeProbe 101 The AREXX Interface 101 Macros Provided by CodeProbe 102 Invoking Macros 103 Values Returned from CodeProbe Commands 103 Return Codes 103 Command Output The AREXX Interface AREXX is a multitasking implementation of the REXX language, a high-level language designed for macro processing and general programming tasks. CodeProbe supports an AREXX interface for customization. This interface is provided through CodeProbe's REXX port, sc_cpr. Macros Provided by CodeProbe A number of macros are provided in the sc: rexx directory as examples. Some simulate commands supported by the Commodore debugger, wack, including the following: Macro Description avail.cpr displays the amount of available memory dbptr.cpr dumps memory as bytes from a given BPTR dbstr.cpr dumps memory as bytes for a given BSTR devices.cpr displays the devices in the system devs.cpr displays the list of system devices execbase.cpr dumps exec base information ints.cpr displays the list of interrupt handlers (continued) 102 Chapter 6 MacroDescription libraries.cpr displays the libraries in the system libs.cpr displays the list of resident libraries makeaptr.cpr converts a BPTR to an APTR memory.cpr displays regions of memory mods.cpr displays system resident modules ports.cpr displays the list of public ports regions.cpr displays regions of memory resource.cpr displays the list of system resources rsrcs.cpr displays the resources in the system showcli dumps CLI structure for a given command, process address, or task showprocess.cpr takes a process address or name and displays all of its task and process fields status.cpr shows all CLI tasks whichis.cpr identifies the CLI process associated with a command, task number, or task address For more details on how to use these macros while debugging, examine the macros in the text editor. Each macro has comments at the beginning of the file explaining how to use it. Invoking Macros CodeProbe recognizes macros with a.cpr extension. To invoke a macro from CodeProbe, simply enter the name of the macro from the command line. (The . cpr extension is optional.) CodeProbe first looks for the macro in the current directory, then in sc: rexx, and finally in REXX:. For example, the following macro, named avail.cpr, uses the storage function to display the amount of memory available. /* */ 'd "' || storage() 'bytes free"' exit(0) 103 Using AREXX Macros with CodeProbe To invoke this macro, enter avail from the command line. The display command in the avail.cpr macro displays the value returned by the storage function, 1953944, and the string "bytes free", as shown here. > avail 1953944 bytes free Values Returned from CodeProbe Commands CodeProbe commands provide return codes that are available to AREXX macros. Output from the debugger commands also can be assigned to the AREXX variable results. Return Codes CodeProbe commands return status codes to AREXX as follows: Return Code Explanation O The debugger command was successful. 1 The command was syntactically correct, but the program failed for some other reason. 2 A syntax error occurred. 3 The debugger could not allocate memory for the AREXX message. Command Output In addition to these return codes, an AREXX macro can receive the Output output of a debugger command as it would normally appear in the Dialog window by invoking the AREXX command options results. The output will then be accessible from the variable result, provided that the debugger returned a 0 return code. For example, to execute a debugger command from outside the debugger, you could execute the following REXX script: /* */ address "SC_CPR" /* only if macro was not invoked from CodeProbe */ options results 'any CodeProbe Dialog window command' 104 Chapter 6 The output from the CodeProbe command is assigned to the AREXX variable result. 105 7 Debugging Resident Libraries 105 Introduction 105 Setting Breakpoints 106 The symload Command 106 The libraries.cpr AREXX Macro 106 Cautions 106 Limitations 106 Example Introduction Debugging resident libraries has been simplified considerably with Version 6.0 of CodeProbe. When debugging a resident library you can set breakpoints in the library use the symload command to read symbol information from the library use the libraries .cpr AREXX macro to display the libraries in the system. Setting Breakpoints You can set breakpoints in any resident library that your program may use. For example, the following command sets a breakpoint on the function myfunc in library mylib. library: break mylib.library:myfunc If your program has not yet called OpenLibrary( ) to open mylib.library, then CodeProbe waits to install the breakpoint until the library has been opened. When CodeProbe detects that the library has been opened, it loads the debug information for that library. If myfunc does not exist, or if debug information for that library cannot be found, CodeProbe will halt the program at that point. This allows you to specify a different function or use the symload command to load debug information from a different location. 106 Chapter 7 The symload Command The symload command can be used to load debugging information for a resident library. For example, the following command loads debugging information for the library named mylib. library in the current directory: symload mylib.library Refer to Chapter 9, "Commands and Built-in Functions," for a complete description of the symload command. The libraries.cpr AREXX Macro The libraries.cpr AREXX macro can be used to display a list of the libraries that are currently loaded. To run this macro, enter libraries on the command line of the Dialog window. Refer to Chapter 6, "Using AREXX Macros with CodeProbe," for more information. Cautions Since there is only one code segment for a shared library, you must be careful in setting breakpoints. A breakpoint is just an illegal instruction that CodeProbe places in the code. When the child process encounters that instruction, CodeProbe handles the exception. However, if another process is also using the same library, it will cause a crash when the program encounters the illegal instruction. Therefore, do not set breakpoints in libraries that will be used by processes not under debugger control. Limitations When debugging a resident library, you cannot examine global variables declared in modules outside the library even if you specify the full pathname of the module. Example See the directory sc:examples/reslib for an example resident library with debugging instructions. 107 8 Debugging Multitasking Programs 107 Introduction 108 Types of Tasks 108 How CodeProbe Handles Tasks 109 Commands Used to Control Tasks 109 tasks 110 opt task 111 activate and deactivate 111 detach 112 catch 112 symload 113 Design Considerations for Debugger Compatibility Introduction CodeProbe can debug applications that spawn additional tasks. These applications are designed to take advantage of the Amiga system's multitasking capabilities. This chapter looks at the commands used to debug multitasking applications including the following: tasks displays all tasks under the debugger's control. opt task examines or modifies the state of some task besides the one currently at a breakpoint. deactivate prevents a task from running, even when a go command is executed from another current task. activate reactivates a task affected by the deactivate command. detach frees a task from debugger control. catch places a task under debugger control. symload changes the load module used for collecting debug information while the debugger is active. 108 Chapter 8 The discussion concludes by focusing on how to design applications with debugger compatibility in mind. CodeProbe is able to debug multitasking applications by intercepting every call to AddTask( ) and determining the identity of the calling task. If the calling task is under debugger control and the catch option is set to on, the new task will also be brought under debugger control. Any task under CodeProbe's control can be stopped by a set breakpoint or by single stepping. Also, if you enter Ctrl-C in the Dialog window while an application is running, all active tasks under debugger control will be stopped. Types of Tasks Two types of tasks can be spawned by an application. The first type, called a synchronous task, is created, runs to completion, and returns control to the parent process while the parent process waits. This type of task is not practical to debug with CodeProbe while running the parent process. You should debug the task as a separate program before debugging the parent process. The second type of task is an asynchronous task. When a parent process spawns an asynchronous task, control is returned to the parent process immediately after creation. The two applications then run independently, but both are under debugger control. This type of task can be debugged with CodeProbe. In this chapter, all references are to asynchronous tasks and their parent processes. How CodeProbe Handles Tasks It is important to understand the way tasks are handled when a breakpoint is hit or when you are stepping through a task. If several tasks are running under the debugger's control when a breakpoint is reached, all other tasks on the debugger's list are stopped as well as the one that encountered the breakpoint. This guarantees that the state of the application remains consistent while the user examines the task. The debugger will set the environment to that of the breakpoint task. That is, the current module, current line, and the registers displayed will all belong to the breakpointed task. The name and address of the Task Control Block for the current task are always displayed in the Dialog window's title bar. 109 Debugging Multitasking Programs Commands Used to Control Tasks CodeProbe provides a number of commands that are used to control tasks. tasks The tasks command displays all tasks under the debugger's control: >tasks Address Type Pri State SigWait StackPtr Debug Name OOC513B8 13 0 Waiting 80000000 OOCSSlCC act multi Note that there are eight fields (columns) displayed by this command: Address contains the address of the task control block. Type indicates the type of node that begins the task control block. The number 13 is used for processes, while 1 is used for simple tasks. For a complete list of the possible task types, see the header file exec/nodes.h. Pri contains the priority of the task. State indicates the process state. SigWait displays the SigWait field of the task control block. This field indicates which signal bits the task may be waiting on. StackPtr indicates the current position of the stack pointer. Note that this will be somewhat different from the value displayed in the sp register. The value displayed here includes any information placed on the stack by the trap handler or exception handler associated with this task. Debug indicates the task's status with the debugger: act denotes an active task, and inact denotes an inactive task. Tasks not under the control of the debugger will have no information in this field. Name refers to the name of the task as specified in the task's node structure. 110 Chapter 8 For more information on tasks and any of the fields except the debug field just discussed, see the Amiga ROM Kernel Reference Manual: Libraries and Devices. The tasks command accepts an option called all. This option causes all tasks in the system to be displayed. This is useful if you want to catch a task that is not currently under debugger control. For more details, see the discussion on the catch command later in this chapter. opt task The opt task command makes a new task current. This command is useful if several tasks are currently running under the debugger and you want to examine or modify the state of some task besides the one currently at a breakpoint. When a new task is made current by this command, a new set of registers is displayed. Highlighting of changed registers in the Register window may be misleading since the debugger only keeps track of changes while stepping through a single task. The module displayed in the Source window may change, or more likely, if the task was in a resident or linked library, assembler lines will be displayed. It may be possible to get information as to the calling sequence of the task by using the where command, but since assembler routines, including the Amiga system's resident libraries, do not follow C language calling conventions, the information displayed by where is only an intelligent guess. You can modify any registers, condition control register (CCR) flags, or stack variables, just as in the breakpointed task. You can even single step through the code. However, a word of caution is advised. A breakpoint is implemented by placing an illegal instruction at the desired location. All tasks under the debugger's control have a trap handler attached to catch the illegal instruction and report back to the debugger. A breakpoint in any shared code will insert an illegal instruction in any task that executes that code. If you must place a breakpoint in shared code, such as a resident library under test, be sure that any task that might open it is under debugger control. Never place breakpoints in libraries that you do not control. Improper use of breakpoints in these circumstances can crash your machine. The opt task command, like all commands that manipulate tasks, takes task-ID as an argument: op[t] t[ask] task-ID A task-ID can be either the name of the task or the address of the task control block. If the name is used, it should be unique (otherwise 111 Debugging Multitasking Programs the first task with that name in the debugger's task list will always be selected). If the name contains a blank, the entire name must be surrounded by double quotes. Task addresses are generally entered in hexadecimal with a 0x prefix. Task names and addresses can be determined with the tasks command. Some sample commands are >opt task Child >opt task 0xC85428 >opt task "Child of multi" Note: task command names are case sensitive. activate and deactivate While debugging a multiple task application, you may want to stop one or more tasks temporarily. The deactivate command allows you to prevent a task from running, even when the go command is performed from another current task. Later, the task can be reactivated by using the activate command. Both commands take task-ID as an argument. a[ctivate] task-ID dea[ctivate] task-ID detach At times, you may want to allow one or more tasks spawned by a task under the debugger to run freely and not under the control of CodeProbe. For example, a task designed to respond to Intuition events may cause the system to lock up if it does not respond to menu events quickly. It may not be desirable to allow such a task to be stopped when other tasks hit a breakpoint. Such a task can easily be freed from debugger control by using the detach command. To use the detach command, first set a breakpoint at the entry point to the task. When the breakpoint is reached, use the tasks command to identify the address or name of the task (you may know this based on your code). Then enter the detach command. The syntax is the same as the other task manipulation commands previously discussed. det[ach] task-ID A few cautionary words are in order regarding the use of the detach command. Once the task is free from the debugger, it can no longer handle breakpoints. Therefore, be sure that all breakpoints in code reachable from a detached task have been removed. Second, the task will not be removed automatically if you quit the debugger. The 112 Chapter 8 detached task can continue running even after you exit CodeProbe. Since CodeProbe frees all of the memory containing the code used by the detached task, subsequent code segments can use part of this free memory and a crash can occur. If you later want to re-attach a task to the debugger, this can be achieved using the catch command, the subject of the following discussion. catch At times, you may find that a process or task not started under the debugger is behaving in an unpredictable or undesired manner. For instance, the task may be caught in an infinite loop. Another possibility is that the task is waiting on some message port for a message that will never come. The catch command is used to capture tasks that are causing these types of problems. Its syntax is similar to those for other task commands: ca[tch] task-ID To debug a task that is stuck in an infinite loop, invoke CodeProbe with no filename. Then, when the debugger is up, use the command tasks all to find the name and address of the process in question. The catch command can then be used to capture the desired task and place it under debugger control. If the task is a process, this command will locate the code segments associated with the debug executable as available from the process structure. If the task is not a process, you will have to determine the address of the seglist and use the opt env command to tell the debugger how to map the debug information with the actual executable file. The opt env command takes as an argument the address of a seglist pointer, as in this example: opt env 0xC08418 For more information on segment lists, see The AmigaDOS Manual, 3rd Edition. symload The symload command enables you to change the executable file used for collecting debug information while the debugger is active. This is useful when debugging several interacting applications that are invoked from separate executable files. Note that this command does not load any code into memory or spawn any new processes or tasks. 113 Debugging Multitasking Programs The symload command can take several forms. The following command will find the executable file and the loaded memory segments associated with the specified process, if it has CLI structure: symload proc "process-name" executable The process is specified by the process-name parameter, and the executable file is specified by the executable parameter. Note that symload and proc are required keywords in this example. If the command has an executable filename as an additional argument, as in this example, any debug information associated with that file will be loaded instead of looking for the file associated with the process. The address of a process task block can be specified in place of the process name. This command also can be given a pointer to a segment list as an argument: symload seg 0x123456 executable The keyword seg is followed by the hexadecimal address pointing to the process seglist. The name of an executable file is also required. Design Considerations for Debugger Compatibility CodeProbe makes every effort to allow an application to run as it would while running outside of debugger control. However, in order to establish breakpoints and catch new tasks generated in a multitasking application, CodeProbe must manipulate certain resources in the application's task structure. In particular, CodeProbe redefines a task's exception handler, exception data, trap handler, and trap data fields. If it is necessary for an application to redefine any of these fields for its own purposes, it must do so in the way described in the Amiga ROM Kernel Reference Manual: Libraries and Devices. Exception handlers must save the address of the original exception handler and exception data fields and pass any unallocated exceptions back to those routines. Before invoking the original exception handler, be sure to restore the original exception data pointer in the task structure. The same practice applies to trap handlers. In particular, all exceptions besides allocated traps should be passed to the original trap 114 Chapter 8 handler. In order to control multitasking, CodeProbe performs a SetFunction on the AddTask, OpenLibrary, OpenDevice, and RemTask functions. These functions should not be redefined by an application. 115 9 Commands and Built-in Functions 115 Introduction 115 CodeProbe Commands 118 Special Parameters 118 address 119 array-slice 120 expression 120 location 121 number 121 range 122 register 123 string 123 subrange 124 type 125 variable 126 Command Reference 202 Built-in Functions 203 Built-in Function Reference Introduction This chapter provides complete reference information for each of the CodeProbe commands and the built-in functions. This information is provided in the following order: [] list of CodeProbe commands that shows acceptable abbreviations and provides a brief description of each command [] list of built-in functions with brief descriptions [] descriptions of special parameters, each of which is used with several CodeProbe commands [] reference information for each of the commands and built-in functions. CodeProbe Commands As explained in Chapter 1, "Introduction to CodeProbe," debugger commands can be entered four ways: from the Dialog window, from a pull-down menu, by function keys, or by menu-accelerator keys. This 116 Chapter 9 chapter describes each of the following debugger commands as they are entered from the Dialog window: a[ctivate] activates a task under debugger control al[ias] defines an alias for a debugger command ar[gs] displays the arguments to a function bc[lear] clears one or more breakpoints bd[isable] disables one or more breakpoints be[nable] enables one or more breakpoints bl[ist] lists all breakpoints b[reak] sets a breakpoint c[all] evaluates an expression and discards the result ca[tch] catches a task not currently under debugger control dea[ctivate] deactivates a task under debugger control def[ine] defines a macro det[ach] detaches a task from debugger control d[isplay] displays the value of an expression du[mp] dumps memory contents dz[ero] displays memory as a null-terminated ASCII string ec[ho] displays a string env sets the environment ex[ecute] executes a debugger command file expand expands and displays a command line fin[ish] terminates CPRK and CPRX fr[egister] displays or modifies floating-point registers g[o] continues execution until a breakpoint is encountered or the program exits h[elp] displays help information hu[nks] lists the addresses and sizes of all hunks j[ump] changes the current execution point 117 Commands and Built-in Functions l[ist] lists the lines in a source file lo[g] logs debugger commands to a file op[t] shows option values or changes the value of a debugger option p[roceed] single-steps over function calls ps single-steps over function calls by source line q[uit] terminates the debugger r[egister] displays or modifies registers res[tart] restarts the program being debugged ret[urn] returns immediately from the current function rf[lag] displays or modifies flags sea[rch] searches for a string in the current source file se[t] modifies the values of variables or memory locations sle[ep] pauses for the time specified so[urce] displays the source file sta[rt] restarts the program being debugged symb[ol] finds the symbol nearest to the specified address sym[load] reads symbol information from an executable file ta[sks] displays system tasks t[race] single-steps into function calls ts single-steps by source line into function calls unal[ias] deletes an alias u[nassemble] displays memory as assembler instructions und[efine] deletes a macro definition w[atch] sets a watch on a variable or memory wb[reak] sets a watch break wc[lear] clears one or more watches wd[isable] disables one or more watches we[nable] enables one or more watches 118 Chapter 9 wha[tis] determines the type of an object whe[re] shows the calling sequence wi[ndow] opens or closes a window wl[ist] lists all watches wmsg writes a message to the Message window. Special Parameters The following special parameters are described in this section: [] address [] array-slice [] expression [] location [] number [] range [] register [] string [] subrange [] type [] variable. Each of these parameters is used in several CodeProbe commands. address An address parameter is any expression that denotes an address. This may be a hexadecimal constant, a C pointer variable, a register, the result of prefixing & to a C identifier of the proper type, or the result of arithmetic calculations on other addresses. Note that the address operator & may not be applied to the identifier of a bitfield or a register. The following are examples of values of expressions that denote an address where p is a pointer, and i and x are integers: &i (&i + 8) &arrayl 3 1 &mystruct - x 0x00C85400 a0 (a0 + 0x22) 119 Commands and Built in Functions There are some cases where a register name may be ambiguous. For example, you may have defined a variable sp in your program. In the following command it is not clear whether you mean to dump data beginning at the variable sp, or at the address contained in the register SP: db sp In such cases the debugger will assume that you mean to refer to the variable sp. However, you can prefix the register name with a dollar sign ($) or use the register command to examine the value of the SP register even if you have declared a variable named sp. In certain commands, it is necessary to specify the type of an object to be modified or displayed. If the object is referred to by means of an address constant or register, the value is assumed to be a character pointer (char *). array-slice An array-slice parameter is a contiguous section of a unidimensional array of scalar variables, an ordered selection of elements from a multidimensional array, or an ordered selection of members from an array of complex types. An array-slice is specified using the following form: variable [[n . . m ] | [*]] Note: The inner brackets in this syntax diagram are not optional and do not denote optional parameters. The advantage of using an array-slice parameter over a range parameter is that the array-slice can be used to select isolated subcomponents, such as a particular structure member from an array of structures. The array-slice parameter also can be nested for multidimensional arrays or structure members that are arrays themselves. The subrange parameter is described later in this chapter. If a subrange is chosen as the index of an array-slice, those elements within the subrange are selected. The asterisk (*) index specifies that all elements of the array are to be contained in the array-slice. The following are examples of the array-slice parameter: a[3..7] matrix[i..j][1.ù3] b[*] a[3..6]->b 120 Chapter 9 expression Any C expression is accepted as an expression parameter, except those that use one or more of the following operators: ++ or -- , ?: = &= |= >>= <<= += -= *= /= %= ^= location A location parameter specifies a place in the code at which a breakpoint is to be set, code is to be unassembled, or a similar action is to be performed. When debugging in source mode, you can think of a location parameter as a line number in a source file or a function entry point. When debugging in assembly mode, you may want to place breakpoints at specific addresses. To do this, specify a hexadecimal address as the location parameter. The location parameter can be specified in one of two ways: [] hex address [] [[image:][\module\]function] line In the first form, the hex-address variable can be any valid absolute address specified as a hexadecimal integer. In the second form the values for the variables image, module, and function can be specified explicitly as follows: image is the name of the executable image (the program, library, or device) containing the location. It is usually specified in lowercase. If omitted, the current image is the default. In a program with only one image, it is never necessary to specify a value for image: Note the required colon (:). module is the name of the C source file compiled to yield the specified function. Note the backslash (\) postfix. 121 Commands and Built in Functions function is the name of a function in the application. You can put spaces between the value specified for image and its colon postfix and the value specified for module and its backslash postfix. but they are not necessary. You must put a space before the line parameter. The line parameter can specify any of the following points in the source code: integer a line number, relative to the start of the C source file containing the function $ the current location e[ntry] the entry to the function (prolog) r[eturn] the return from the function (epilog). If the function name is not specified with the line parameter, the debugger defaults to the current function. If a function is specified without a line, the debugger defaults to the first execution line. number A number parameter is a number in decimal, octal, or hexadecimal notation. An initial 0 digit causes the number to be interpreted as octal, an initial 0x (or 0x) causes the number to be interpreted as hexadecimal, and an initial 0n (or 0N) causes the number to be interpreted as decimal. The default is decimal. Examples of acceptable values for the number parameter include the following: 12345 0455 0x380 0X1849 0n12345 range A range parameter is a contiguous area of memory that can be specified in one of two ways: [] address..address [] address l number address L number 122 Chapter 9 In both forms, the first address variable is the start address, and the range begins at this address. In the first form, the second value for address is the end address, and the range includes the area of memory from the start address to the end address. In the second form, the l or L indicates that the value for the variable number is to be interpreted as a length. In this case, number indicates the number of elements and the range is from the start address through address+number-1. When the debugger sees a solitary l or L in a command, it is considered part of a range expression. The following examples fit the definition of the range parameter: 0x123456 .. 0x123461 0x123456 L 11 a1..a2 a7 l 20 &P[O] .. &P[5] P[0] .. P[5] &P[0] l 6 P[0] l 6 The first pair of examples are equivalent. The next pair are variants of the basic range expression. The remaining pairs are equivalent ranges, given the addressing policy described earlier in this section. register A register parameter refers to the name of any of the following 680xO registers: A0 - A7 are address registers. Register A7 functions as the stack pointer and can be specified as either A7 or SP. D0 - D7 are general-purpose registers. PC is the program counter. SP is the stack pointer. SR is the status register. It contains the CCR register as well as the current processor status. CCR is the condition code register. It resides in the lower byte of the status register, SR. 123 Commands and Built-in Functions If a math coprocessor is present, the following registers also can be specified as the register parameter: FP0 - FP7 are the floating-point registers. FCR is the floating-point control register. FSR is the floating-point status register. It contains the current floating-point condition codes. Optionally, registers can be prefixed with a dollar sign ($) to distinguish them from variables with the same name. For example, register D1 can be specified as $D1 to distinguish it from a variable named d1. string A string parameter can be any standard C string in double quotes ("). Standard C escape sequences starting with the backslash character are supported as follows: \n newline (0x0a) \t horizontal tab (0x09) \b backspace (0x08) \r carriage return (0x0d) \f form feed (0x0c) \v vertical tab (0x0b) \NNN octal constant, where NNN is a three-digit octal number \xNN hex constant, where NN is a two-digit hexadecimal number. A backslash followed by any character other than those shown previously in the escape sequences is interpreted as a plain character. For example, \ \ is a string consisting of a single backslash, and a \ " b is three characters long: an a, a double quote, and a b. The Dialog window does not recognize any of these escape sequences when they are displayed. You cannot use the \t escape sequence to tab in the Dialog window. The escape sequences are useful in line mode and when setting a character string. Like all debugger input, a string can be continued to the next line by ending the line with a backslash. The debugger does not support ANSI string concatenation. subrange A subrange parameter is a series of contiguous integers, inclusive of its bounds. The integers may be either integer constants or variables from 124 Chapter 9 the application being debugged. The form of the subrange parameter is as follows: [integer | variable]. . [integer | variable] The following are examples of the subrange parameter: 3..7 i..j type A type parameter can be any of the data types provided by the C language including any of the following: char unsigned char short unsigned short int unsigned int long Unsigned long unsigned float double struct union enum A type also can be any of the C types previously listed followed by some number of asterisks indicating that the type is a pointer to the base object. In addition, the type parameter can take any identifier defined by means of a typedef statement if the debugging information for the module supplies typedef information. 125 Commands and Built-in Functions variable A variable parameter is an expression in your program that designates an object. It can be either a simple identifier or an expression referring to an array element, structure member, or object pointed to by a pointer. In addition, it can begin with a specification of the following form: [[image:][\module\]function] See the location parameter earlier in this chapter for a description of the image, module, and function variables. The following are objects that fit the definition of the variable parameter: i max array[3] array io:readfile\length mystruct->name[2] mystruct *cptr main.c\opnf\count opnf\i mylib.library:LIBmyfunc\myvar 126 Chapter 9 Command Reference This section provides complete reference information for each of the CodeProbe commands. The commands are listed in alphabetical order. Most of the command descriptions include the following sections: Synopsis shows the format of the debugger command or built-in function Description describes the function of the debugger command or built-in function and contains all the information you need to use the command or function Example contains examples that illustrate how to use the command or function See Also refers you to the descriptions of other related commands or functions. 127 Commands and Built-in Functions activate Activates a task under debugger control Synopsis a[ctivate] [task-name | task-address | exe-name] Description: The activate command activates a task that has been deactivated by the deactivate command. The task is activated when the next go or proceed command is executed. The task-name, task-address, and exe-name parameters are the name of the task, the address of the task, and the executable name of the task as specified by the tasks command. Only one of these parameters can be specified. Examples activate Child activates the task named Child under debugger control. activate 0xC08540 activates the task with a task block starting at address 0xC08540. activate myprog activates the task executing the program myprog. See Also catch, deactivate, detach, tasks 128 Chapter 9 alias Defines an alias for a debugger command Synopsis al[ias] [name[definition]] Description: When entered with no arguments, the alias command displays the list of all currently defined aliases. If a value for name is provided as the only argument, the definition for that alias will be displayed. Any text following the name parameter is treated as a definition and is used to define the alias. Alias names are expanded only when they occur at the beginning of a Dialog window command line. An alias definition can be a simple textual substitution or it can contain positional parameters to be expanded at execution time. Positional parameters are specified as $1, $2, $3, and so on. $0 represents the alias name itself. $* represents command line parameters $1 through $n. If no positional parameter is specified in a definition, all parameters are placed after the expanded definition text. The alias command will parse a definition until it encounters a command delimiter character (;) or the end of the line. To define an alias that expands into more than one command, enclose the definition in either double quotes or curly braces. If the command string must contain double quotes, curly braces can be used or the quotes can be escaped. As in C and all other debugger commands, a backslash may be used to continue the line. Examples alias displays a list of all alias definitions. alias foo displays a definition of f oo. alias next proceed defines next to be an alias for proceed. alias pr display foo, bar, $* defines pr to be an alias that executes the display command printing the value of foo, bar, and any variables entered after the pr. alias doit {go $1; d foo} defines doit to execute the go command using the first parameter, and displays the variable named foo. alias doit {go $1;\ d foo} uses the backslash command to split a command across two lines. 129 Commands and Built-in Functions alias Defines an alias for a debugger command (continued) alias doit "go $1; d $2" uses positional parameters with multiple commands. The first parameter, $ 1, is passed to the go command, and the second parameter, $2, is passed to the display command. See Also define,unalias,undefine 130 Chapter 9 args Displays the arguments to a function Synopsis ar[gs] [function-name] Description: The args command displays all of the argument names and values to the current function or the function specified by the function-name parameter. If a function-name parameter is specified it must be in the calling sequence, as displayed by the where command. Examples args displays the arguments to the current function. args sort displays the arguments to the sort function. See Also display, env, where 131 Commands and Built-in Functions bclear Clears one or more breakpoints Synopsis bc[lear] integer[integer...] bc[lear]* | l[ast] bc[lear] integer .. integer Description: The bclear command clears one or more breakpoints. When a breakpoint is cleared, it ceases to exist and can be reinstated only by issuing the break command again. You should use the bdisable command to disable breakpoints temporarily. The integer parameter specifies the breakpoint number as displayed by the blist command. Any number of values can be specified as integer parameters. An asterisk specifies that all breakpoints should be cleared and last causes the most recently set breakpoint to be cleared. A range of breakpoints can be specified by integer. . integer. Examples bclear 2 5 6 clears the breakpoints numbered 2, 5, and 6. bclear last clears the last breakpoint set. bclear * clears all breakpoints. bclear 4 .. 7 clears breakpoints 4, 5, 6, and 7 See Also bdisable, benable, blist, break, wclear 132 Chapter 9 bdisable Disables one or more breakpoints Synopsis bd[isable]integer[integer...] bd[isable] * | l[ast] bd[isable]integer .. integer Description: The bdisable command disables the recognition of one or more breakpoints. When a breakpoint is disabled, it is not recognized by CodeProbe, but it does remain on the list of current breakpoints. A disabled breakpoint can be re-enabled by the benable command. The integer parameter specifies the breakpoint number as displayed by the blist command. Any number of values can be specified as integer parameters. An asterisk specifies that all breakpoints should be disabled and last causes the most recently set breakpoint to be disabled. A range of breakpoints can be specified by integer . . integer. Examples bdisable 2 5 6 disables the breakpoints numbered 2, 5, and 6. bdisable last disables the last breakpoint set. bdisable * disables all breakpoints. bdisable 4 .. 7 disables breakpoints 4, 5, 6, and 7. See Also bclear, benable, blist, break, wdisable 133 Commands and Built-in Functions benable Enables one or more breakpoints Synopsis be[enable] integer [integer ...] be[enable] * | l[ast] be[enable] integer .. integer Description: The benable command enables the recognition of one or more breakpoints that have been disabled by the bdisable command. The integer parameter specifies the breakpoint number as displayed by the blist command. Any number of values can be specified as integer parameters. An asterisk specifies that all breakpoints should be enabled and last causes the most recently set breakpoint to be enabled. A range of breakpoints can be specified by integer . . integer. Examples benable 2 5 6 enables the breakpoints numbered 2, S, and 6. benable last enables the last breakpoint set. benable * enables all breakpoints. benable 4 .. 7 enables breakpoints 4, 5, 6, and 7. See Also bclear, bdisable, blist, break, wenable 134 Chapter 9 blist Lists all breakpoints Synopsis bl[ist] Description: The blist command displays a list of all breakpoints. Each entry has a form similar to the following example: 5 0x40054 loop:\loop.c\main 8 (2 hits) after(4) when(i == 3) quiet {echo Hi} The number 5 in this example is the number used to refer to this breakpoint in bclear, bdisable, and benable commands. If an asterisk appears next to the number, that breakpoint has been disabled and will not be triggered. Following the breakpoint number is the hexadecimal address at which the breakpoint resides. If sufficient debug information is available, the address is followed by the location that it represents. The hit count, which represents a running count of the number of times the breakpoint has been triggered, is displayed after the location of the breakpoint. A breakpoint is triggered when all of the following conditions are true: [] execution has reached the address shown [] the when and after conditions are true, if specified [] the breakpoint is enabled. Breakpoints are triggered when the user steps to the address provided the last two conditions are met. The second line of output displayed by the blist command shows the options given when the break command was issued. See Also bclear, bdisable, benable, break, wlist 135 Commands and Built-in Functions break Sets a breakpoint Synopsis b[reak] location[after(integer)][when(expression)] [tr[ace]] [q[uiet]] [te[mp]] [{cmd-list}] Description: The break command is used to set a breakpoint at a location specified by the location parameter. You can use a dollar sign to specify the current location. The after option specifies the minimum number of times the specified line must be executed before the breakpoint is triggered. This is also known as specifying a pass count. For break commands that do not contain an after clause, the pass count is set to 1. Each time the breakpoint is hit, the pass count is tested. If the pass count equals 1, the breakpoint is triggered and execution stops. If the pass count is greater than 1, the pass count is decremented by 1, and execution continues. The blist command shows the current pass count for each breakpoint. If the when option is present, the breakpoint is triggered only if the specified expression evaluates to true (nonzero). The after and when options can be specified in any order. If both options are specified, the pass count is tested and decremented only when the when condition is true. The trace option continues execution automatically after the breakpoint is triggered, unless you reach the breakpoint by single- stepping, then the the trace option has no effect. The quiet option suppresses the default message showing the location when the breakpoint is triggered. The temp option causes the breakpoint to be deleted after it has been triggered. If the cmd-list parameter is present, the commands listed are performed each time the breakpoint is triggered. As in C commands and all other debugger commands, a backslash may be used to continue the line. Note: To avoid confusion, the break command does not use the default radix setting. You must specify ox for an address; otherwise, you will be specifying a line number. For example, even if the radix is set to hex, the following command specifies a break command for line 20 and not address 0x20: b 20 136 Chapter 9 break Sets a breakpoint (continued) Examples break $ sets a breakpoint at the current line. b 14 sets a breakpoint at line 14 of the current module. b sort sets a breakpoint at the first line of the sort function. break sort return sets a breakpoint at the return from the sort function. break \myfile.c\sort 14 sets a breakpoint at line 14 of sort in the module named myfile.c. break mylib.library:myfunc sets a breakpoint at the first line of the myf unc function in the shared library mylib. library. b $ after(5) breaks the fifth time the current line is executed. break 0x804A sets a breakpoint at the absolute address 0x804A. break 14 when (i > 5) (di p L 16; b sort 26 when (i == 8); bl; go) sets a breakpoint on line 14 that performs the commands given inside the curly braces if i > 5 evaluates true. b 8 trace quiet (d "i = ", i) prints a message of the form ~ i = value "every time line 8 is executed. break 100 temp (d foo) stops at line 100, prints f oo, and deletes this breakpoint. See Also bclear,bdisable,benable,blist,go 137 Commands and Built-in Functions call Evaluates an expression and discards the result Synopsis c[all] expression Description: The call command is used to evaluate an expression when you do not care about the value returned. It is equivalent to the following statement in C language: expression; The most common use of the call command is to call a function in the application program, though function calls also may appear in arbitrary expressions in other commands. If you want to see the value returned by the expression, use the display command. The debugger looks at the types of the parameters specified and not at the definition of the function or any prototype. Thus, the debugger does not flag an error if the wrong number of parameters are specified, nor does it perform automatic casting of types or allow passing of char, short, or f loat types. For example, the following command passes two parameters, an int and a double, regardless of how the function is declared: call f(2, 1.5) CodeProbe supports standard C syntax for function calls. Either a function name or an expression evaluating to a function type may be specified before the opening parenthesis. Thus, the call command can be used only to call functions or evaluate expressions that point to a function. For example, if pf is a function pointer, and f unc is a function, the following commands are allowed: call func() call (*pf)() However, the following commands are not allowed: call pf() call 0xl34() call register( ) You cannot use the call command to execute a function after a program has ended. 138 Chapter 9 call Evaluates an expression and discards the result (continued) If a breakpoint is hit, a signal is caught, or the program terminates in the middle of a function call, the debugger aborts the expression and leaves you at that location. A warning is printed if any parameters are not cleaned off the stack. This may cause a return to an invalid location later if execution is allowed to continue. Examples call status() calls the status function. call print("Test", 300) calls the print function passing in a string and an integer parameter. call (*fp)(&arr[5], j+10, 3.0) evaluates arbitrary expressions. See Also display,env,where 139 Commands and Built-in Functions catch Catches a task not currently under debugger control Synopsis ca[tch] [task-name I address I exe-name] Description: The catch command enables the debugger to gain control of tasks that were not started under the control of CPR. The task-name and address parameters can be found by issuing a t a s k s a 11 command. The exe-name parameter can be used to specify the name of the executable associated with the task you want to catch. Examples catch Child catches the task named Child. ca 0xC08540 catches the task with a task block starting address 0xC08540. catch myprog catches the task running the program myprog. See Also activate, deactivate, detach, symload, tasks 140 Chapter 9 deactivate Deactivates a task under debugger control Synopsis dea[ctivate] [task-name | address | exe-name ] Description: Normally all tasks under CPR's control are started when a go or proceed command is issued. The deactivate command can be used to deactivate a task. A task that is deactivated by this command is not started when the debugger allows the application to run unless it is the current task. The task can be reactivated with the activate command. The task-name and address parameters can be found by issuing a tasks command. The exe-name parameter can be used to specify the name of the executable associated with the task you want to catch. Examples dea Child deactivates the task named Child under CPR. deactivate 0xC08540 deactivates the task with a task block starting at address 0xC08540. deactivate myprog deactivates the task running the program named myprog. See Also activate, catch, detach, tasks 141 Commands and Built-in Functions define Defines a macro Synopsis [#]def[ine] name [definition] [#]def[ine] name(parm [,parm ... ]) [definition] Description: The define command provides a general macro substitution facility that is nearly identical to the mechanism provided in C syntax. Macros defined in the debugger are expanded anywhere within a line of text except inside quotes or filenames. The debugger also will not expand macro definitions that are prefixed with a backtick character ( ` ). The ANSI # and ## operators are not supported. Examples define displays all the macro definitions. define foo defines foo as a null definition. def foo bar defines foo to be bar. define func(a,b) (a+b) defines func with parameters. See Also alias, unalias, undefine 142 Chapter 9 detach Detaches a task from debugger control Synopsis det[ach] [task-name | address | exe-name ] Description: The detach command detaches a task from debugger control. The task can be brought under CodeProbe's control with the catch command. The task-name and address parameters can be found by issuing a tasks command. The exe-name parameter can be used to specify the name of the executable associated with the task you want to catch. When using the detach command make sure that no breakpoints are placed inside code that is executable from a detached task. Also, do not specify the detach command to the original program if any of its child processes continue to run in the same code segment. Examples detach Child detaches the task named Child from debugger control. det 0xC08540 detaches the task with a task block starting at address 0xC08540. det myprog detaches the task executing the program myprog. See Also activate, catch, deactivate, tasks 143 Commands and Built-in Functions display Displays the value of an expression Synopsis d[isplay] (expression["format"] | string) [, ...] Description: The display command evaluates the value of the expression parameter and displays the result. The expression parameter can be any C expression containing constants, variables, and function calls from the program being debugged. Any number of expressions and strings can be specified, separated by commas. All expressions are displayed on the same line. The display command chooses the default format based on the type of the expression. Values of type char are displayed as characters as well as in decimal and hexadecimal format. If the character is unprintable it is displayed as an escape sequence, for example, \n or \xAC. Values of type int and long are displayed in decimal and hexadecimal format, and f loats and doubles are displayed in floating-point best format. To override the default format, a printf style format can be specified optionally after each expression. No error checking is done on the format parameter, so strange results are possible. It may contain up to two conversion operators for short and long types but only one for all other types. All members of structures, unions, and arrays are displayed using the default formats. Partial arrays may be displayed using two integers to indicate the first and last elements to display. For example, the following command displays array elements 3, 4, and 5: display a[3..5] An asterisk may be used instead to indicate that all elements should be displayed. The string parameter can be any standard C string in double quotes as described earlier in this chapter in the "Special Parameters" section. To display a null-terminated string, use the dzero command. Use the dump command to dump an area of memory. Examples display displays the variable i. d a "a=%10.5e" displays a using a printf style format specifier. d p->d[5] + f(3) displays the value of an expression containing a function call. 144 Chapter 9 display Displays the value of an expression (continued) display "X is", x, "J is", j displays the value of several argu ments including strings. d x "X is %d", j "J is %d" displays the value of several arguments using printf style format specifiers. d a[3] displays the value of an element of an array. display a[3..5] displays the value of elements 3 through 5 in an array named a. d a[*] displays the value of every element of an array. See Also call,dump,dzero 145 Commands and Built-in Functions 145 dump Dumps memory contents Synopsis du[mp] [variable | address | range] [S] [format [itemsize] | text] Description: The dump command is used to examine an area of memory. You select the format of the dump, the length of each item being dumped, and whether or not you want text to appear on the right side of the dump. A dump command with no parameters continues where the previous dump command ended using the same dump specifications. The variable, address, or range parameter specifies the location to be dumped. The $ parameter can be used to specify the last dump address when the format or text parameters are used. The $ is ignored if a variable, address, or range parameter has already been specified making it useful for aliases where the dump address may be omitted. The format parameter controls the format of the dump and its value can be any of the following: a[scii] FFP[float] IEEE[float] b[inary] f[loat] o[ctal] d[ecimal] h[ex] u[nsigned] The default format is hex. If you specify a format parameter, you also can specify an itemsize parameter to control the length of each item dumped. The itemsize parameter can have a value of 1, 2, 4, or 8. The itemsize parameter is concatenated onto the end of the format parameter (for example, b4 for a binary format of length 4). If you do not specify itemsize, CodeProbe uses a default. As shown in the following table, the allowable size and default values depend on the format specified. The text parameter is used to specify that an ASCII representation of the memory dump should be displayed. 146 Chapter 9 dump Dumps memory contents (continued) The itemsize parameter has the following default values and allowable sizes: Format Default Allowed Sizes ascii 1 1 binary 1 1, 2, 4 decimal 4 1, 2, 4 FFPfloat 4 4 float 8 4, 8 hex 4 1, 2, 4 IEEEfloat 8 4, 8 octal 4 1, 2, 4 unsigned 4 1, 2, 4 Compatibility Aliases To provide backward compatibility with previous releases of CodeProbe, the following aliases for the dump command are supported: da dumps a range of memory as ASCII characters db dumps a range of memory in both hexadecimal and ASCII format dc dumps a range of memory in decimal format dd dumps a range of memory as 8-byte floating-point numbers in IEEE format df dumps a range of memory as 4-byte floating-point numbers in IEEE format dffp dumps a range of memory as 4-byte floating-point numbers in FFP format 147 Commands and Built-in Functions dump Dumps memory contents (continued) di or dl dumps a range of memory in integer format using decimal representations of the integers dw dumps a range of memory in short integer (16-bit) format using hexadecimal representations of the integers dp dumps a range of memory in 4-byte hexadecimal format ds dumps a range of memory in short integer (16-bit) format, using decimal representations of the integers. Examples dump var dumps memory contents of variable var. dump var L 13 hex1 dumps memory contents for 13 bytes using 1-byte hexadecimal format. dump var1 .. var2 ascii dumps memory contents between var 1 . . var 2 in ASCII format. dump 0xAF8100 L 8 dumps memory contents for 8 longs (32 bytes) starting at absolute address 0xAF8100. See Also display,dzero 148 Chapter 9 dzero Displays memory as a null-terminated ASCII string Synopsis dz[ero] variable | address | array-slice Description: The dzero command displays the contents of memory as a null- terminated (\0) string. If the location is the name of a nonpointer variable in the program being debugged, dzero displays the memory contents starting at the address of the variable and continuing until the null character is found. If the location is the name of a pointer variable, dzero uses the contents of the pointer and displays bytes starting at that address until a null character is encountered. If the address parameter is used to specify an absolute address, dzero displays the contents of that address until a null character is encountered. If the location is an array-slice, the address of each element in the array slice will be displayed until the null character is found. Examples dzero string displays characters until the null character is reached. dzero ptr displays data pointed to by ptr as a string. dzero ptr[3..7] displays each element in the array slice ptr [3..7] until the null character is reached. See Also display, dump 149 Commands and Built-in Functions echo Displays a string Synopsis ec[ho] [text] Description: The echo command writes the value specified for the text parameter in the Dialog window. This is useful for documenting the actions being taken in a debugger command file, the cprinit file, or AREXX macros. If the text parameter contains semicolons, they must be escaped with a backslash (\;). Defines or aliases are not expanded. Example echo Starting program\; loading defines . displays the message following the echo command in the Display window. See Also display, execute 150 Chapter 9 env Sets the environment Synopsis env[function | integer] env[-c[aller] | -s[ubroutine] | -u[p] | -d[own] | -integer | +integer] Description: The env command changes the environment for subsequent debugger commands. Environment is the state of the machine at a particular point in the calling sequence (that is, the contents of the stack and the contents of variables). Setting the environment to a previous point in the calling sequence, such as the point where the current function was called, returns the machine to the state it was in at that time. However, only the information that can be retrieved from the stack will have been restored. Scratch registers and other components, such as the values of externs, that are not dependent on the stack remain relative to the current execution point in the application and will not be changed. Nonscratch registers are restored to the correct values for the new environment. The environment can be set to an absolute or relative position in the call chain. To set it to an absolute position, specify the function name using the function parameter, or a level number using the integer parameter. The where command or Calls window can be used to display the level number. The other forms to the env command set the environment relative to the current function. To move the environment up one level to the caller of the current function, use the -caller, -up, or -1 flags. To move in the opposite direction, use the -subroutine, -down, or +1 flags. Use the +integer or -integer forms to move more than one level at a time. Level 1 is defined to be the function in which you are currently stopped. The caller's level is 2, its caller is level 3, and so on. These level number designations change as the program steps into and returns from functions. If you attempt to move the environment up or down more levels than there are in the call frame, a warning is displayed and the environment is moved as far as possible. After using the env command, commands that refer to line numbers and variables act as if the function specified by the function parameter is the current function. Any command that causes the program being debugged to resume execution, such as the go or trace commands, automatically resets the user environment to the last point of execution. Issuing the env command is the same as double-clicking on a function call entry in the Calls window. 151 Commands and Built-in Functions env Sets the environment (continued) Examples env sets the user environment to the last point of execution. env main; d i sets the user environment to main and display i. env -subroutine sets the environment to the called function (down 1 level). env -caller sets the environment to the caller function (up 1 level). env +5 moves the environment down 5 levels. env 7 moves the environment to the level 7. See Also where 152 Chapter 9 execute Executes a debugger command file Synopsis ex[ecute] filename Description: The execute command reads and executes CodeProbe commands from the file specified by the filename parameter. If the file cannot be found, CodeProbe appends a . cpr extension to it and tries again. Thus, you can place a set of debugger commands in a file with a .cpr extension and simply use the root filename, minus the extension, in the execute command. CodeProbe searches for the specified file in your normal Shell path as defined with the AmigaDOS PATH command. If the file cmds.cpr consists of the commands break sort blist trace trace then the execute command applied to this file would yield the following display: > execute cmds.cpr executing commands from cmds.cpr 1 0xC32D3E sort:\sort.c\sort 22 sort:\sort.c\init 5 sort:\sort.c\init 9 The debugger commands themselves are not echoed as part of the display unless echo mode is turned on. If you are debugging a program frequently and want to set a number of breakpoints at the same places, you can place all of your breakpoint commands in a file and then use the execute command on this file. This way you can avoid re-entering the same commands each time you want to use the debugger. If the execute command is used in a command list, it must be the last command in the list. Examples execute setvars executes the file named setvars or setvars .cpr. execute test/cmds.cpr executes the file named cmds.cpr located in the test directory. 153 Commands and Built-in Functions expand Expands and displays a command line Synopsis expand [alias] command-line Description: The expand command displays its arguments with all aliases or defines expanded. The command-line parameter specifies any valid command-line entry that includes aliases or defines. This command can be useful in trying to create more complex aliases and defines. If the alias keyword is not specified, aliases are not expanded, but defines will be expanded. Examples expand alias dp expands the alias for named dp to display the following: dump $ hex4 expand ISEQUAL(1,5) expands the macro ISEQUAL using the arguments 1 and 5. For example, if ISEQUAL has been defined as ( a == b ), then it would be expanded to ( 1 = = 5 ) . See Also alias, define 154 Chapter 9 ffnish Terminates CPRK and CPRX Synopsis fin[ish] Description: The finish command is used in cross-development mode to terminate the session. The cross debugger (CPRX) on the host machine instructs the kernel (CPRK) on the target machine to terminate after cleaning up and closing the communications link. The f i n i s h command must be entered on the host machine. The host machine is the one that is being used to display the CodeProbe user interface. The f i n i s h command does not work from the native version of CodeProbe. Example finish causes CPRK to terminate after disconnecting from CPRX. See Also quit 155 Commands and Built-in Functions fregister Displays or modifies floating-point registers Synopsis fr[egister] [register[[=] expression]] Description: On machines that have a math coprocessor chip installed, the fregister command displays or modifies the contents of the floating-point registers. If no parameters are specified, the fregister command displays the current contents of all the machine's floating- point registers in hexadecimal and as floating-point numbers. If only a register name is supplied, the contents of the register are displayed; otherwise, the value of the expression parameter is stored in the register specified. The display and set commands also can be used to display and modify the registers. Examples fr displays all floating-point registers and flags. fregister fp0 30.14 sets floating-point register fp0 to 30. 14. fr fp2 = sales sets floating-point register p2 equal to the value of sales. fregister fp1 displays the value of floating-point register fp1. See Also display,register,rflag,set 156 Chapter 9 go Continues execution until a breakpoint is encountered or the program exits Synopsis g[o][location[after(integer)] [when(expression)]] Description: The go command begins execution of the program at the current location, which is identified by the address stored in the program counter (pc) register. Execution continues until a breakpoint is reached or until the program terminates, either normally or with an error. The location parameter specifies an optional location for a temporary breakpoint. The breakpoint specified in the go command exists only for the duration of the go command. The next time program execution stops, the breakpoint is cleared, even if the temporary breakpoint was not reached. The after option specifies the minimum number of times the specified location must be reached before the temporary breakpoint is triggered. This is also known as specifying a pass count. For go commands that do not contain an after clause, the pass count is set to 1. Each time the temporary breakpoint is hit, the pass count is tested. If the pass count equals 1, the temporary breakpoint is triggered and execution stops. If the pass count is greater than 1, the pass count is decremented by 1 and execution continues. If the when option is present, the breakpoint is triggered only if the specified expression evaluates to true (nonzero). The after and when options can be specified in any order. If both are used, the pass count is only tested and decremented when the condition is true. Note: To avoid confusion, the go command does not use the default radix setting. You must specify ox for an address; otherwise, you will be specifying a line number. For example, even if the radix is set to hex, the following command specifies a go command for line 20 and not address 0x20: g 20 Examples go continues program execution to the next breakpoint or the end of the program. go 14 continues program execution to line 14 of the current module. Note that line numbers are relative to a module and not a function. This example assumes that code was generated at line 14. You cannot use the go command to go to a line with no code generated. 157 Commands and Built-in Functions go Continues execution until a breakpoint is encountered or the program (continued) exits go sort continues program execution to the first line of the sort function. go \myfile.c\sort 14 continues program execution to line 14 of the sort function in module my file.c . This example also assumes that code was generated at line 14. go mylib.library: myfunc continues program execution to the myfunc function in the shared library mylib. library. go $ after(5) continues program execution until the fifth time the current line is executed. go 0x804A continues program execution until absolute address 0x804A is reached. See Also break, proceed, ps, trace, ts 158 Chapter 9 help Displays help information Synopsis h[elp] [command] ? [command] Description: The help command displays information about commands and operands. If the command parameter is omitted, the Help window opens and a list of commands and topics is displayed. Entering one of the items on this list as the value for the command parameter displays information about that item. An alternate method of selecting an item is to double-click on the command or topic in the Help window. This method of selection can also be used from the help screens themselves. For example, at the bottom of the screen for the dump command there is a section that directs you to the display and dzero commands for additional information. You can access the help screen for either of these commands by double-clicking on the name of the command. Examples help displays a list of commands and topics. h break displays information about the break command. ? break displays information about the break command. 159 Commands and Built-in Functions hunks Lists the addresses and sizes of all hunks Synopsis hu[nks] Description: The hunks command displays the list of loaded hunks, their addresses, and their sizes for the current executable file. The following example shows the output from the hunks command: >hunks Hunk Address Size 0 00C32AE8 0xB54 (2900) 1 00C28570 0x27C (636) The size is displayed first in hexadecimal format followed by decimal format in parentheses. Example hunk s lists all hunks for the current executable file. 160 Chapter 9 jump Changes the current execution point Synopsis j[ump] location Description: The jump command updates the program counter to point to a new location. The effect of using this command is that the code between the previous execution point and the new location is not executed. Any value for the location parameter that is valid for the break or go commands can be used. It is important to note that the stack is not modified in any way. You should be very careful when using the j ump command because certain registers may not be set up the way the code that is jumped to expects. Using the j ump command is more likely to be safe if you always jump from one C source file line to another in the same function (not from assembly lines), and you have compiled with the debug=symbolflush or debug=fullflush options to make sure that registers are flushed to memory at C source line boundaries. If the jump command is used on optimized code, the registers are not likely to be set correctly. Note: To avoid confusion, the jump command does not use the default radix setting. You must specify 0x for an address; otherwise, you will be specifying a line number. For example, even if the radix is set to hex, the following command specifies a jump command for line 20 and not address 0x20: j 20 Examples jump 1 2 jumps to line 12 in the current function. jump 0x804E jumps to the address 0x804E. See Also env, go, return 161 Commands and Built in Functions list Lists the lines in a source file Synopsis l[ist] l[ist] $ l[ist] + | - integer [L length] l[ist] line-range l[ist] [image:]\module [line-range] l[ist] [[image:]\module\lfunction [line-range] Description: The list command is used when debugging in line mode to list the lines in a source file. The current list line is set to the source line at which the program being debugged is stopped each time the user regains control. The list command with no arguments displays lines starting with the current list line. The number of lines displayed is controlled by the opt list command. The $ parameter is used to list a number of lines above and below the current line at which the program is stopped. The number of lines above and below is controlled by the opt context command. The module parameter specifies the name of a module in the program. A range of lines is specified with the line-range parameter, which can have either of the following forms: line-1 [[..] Iine-2] line-1 L length In the first form the line-range parameter specifies a range of lines starting at line-1 and ending at line-2. In the second form a range of lines is specified as starting at line-1 and extending for length number of lines. If the list command is given an environment (module or function), then the source file for that environment is opened, if possible, and the desired line range is displayed. If no line range is given, and no function is given, the listing begins at line 1. If a function name is given and no line range is given, lines are listed beginning with the function declaration. Each time the list command is used, the current list line is set to the line immediately following the last listed line. Remember that the current list line is also updated each time the client program is allowed to execute. Examples list lists the next group of lines. The number of lines listed is set by the opt list command. 162 Chapter 9 list Lists the lines in a source file (continued) list $ lists lines around the line pointed to by the current program counter. list module lists first lines of the specified module. list \module 20 40 lists lines 20 through 40 of the specified module. list \module 20 L 10 lists 10 lines of the specified module starting at line 20. list +20 starts listing lines 20 lines down from the current line. list -20 starts listing lines 20 lines up from the current line. list -20 L 10 lists 10 lines, starting 20 lines up from the current line. list foo starts listing at the declaration of the function named foo. list foo 10 20 lists lines 10 through 20 of the function named foo. See Also opt, source, unassemble 163 Commands and Built-in Functions log Logs debugger commands to a file Synopsis lo[g] [log-command] Description The log command is used to save to a file a record of all activity in the Dialog window including commands and results. Menu selections are not saved by the log command. This information is stored in a log file. The name of the file is set with the log f ile command. The default filename is cpr. log. When issued without the log-command parameter, the log command can be used to display the current log state, either on or o f f, and the filename of the log file. The log-command parameter can be any of the following: append appends log information to the end of the log file file filename specifies the filename of the log file off closes the log file on opens a new log file snap snapshots contents of the Dialog window to the log file. If a command that enables the logging of your session, such as log on, log append, or log snap, is issued when logging is already enabled, the results of the command are added to the current log file. If the log filename is changed while logging is enabled, the current log file is closed, and a new one is opened. The log file is automatically closed when you exit CodeProbe. Examples log snap saves the dialog for the current session into the log file named cpr . log. log file foo.log sets the log file to the filename foo.log. log on enables the log file. 164 Chapter 9 log Logs debugger commands to a file (continued) log off disables the log file. log append enables the log file and appends new log information to the end of the log file. 165 Commands and Built-in Functions opt Shows option values or changes the value of a debugger option Synopsis op[t] op[t] aU[toswap] [on | off] op[t] ar[rdim] integer op[t] b[adchar] integer op[t] ca[se] [on | off] op[t] cat[ch][on | off] op[t] co[ntext] integer op[t] dev[ices][on | off] op[t] e[cho] [on | off] op[t] ib[ytes][on | off] op[t] ig[norepath] [on | off] op[t] l[ist] integer op[t] rad[ix][d[ecimal] | h[ex]] op[t] ran[gelen] integer op[t] re[slib][on | off] op[t] se[arch] [+ | -] director,v[, director,v [ . . . ]] op[t] so[urce] c | a[sm] | m[ixed] | n[ext] op[t] st[rlen] integer op[t] t[ask] [task-ID] op[t] u[nassemble] integer Description The opt command is used to show the value of debugger options or to change them. The opt command by itself shows the current settings of all options. The following are the options and their possible values: autoswap if set to on, pushes the screen containing the applications output to the front each time control is given to the application. If set to o f f, the application screen is not pushed to the front. The default is off. arrdim controls the maximum number of array elements that are displayed at one time with the display command. The default is 20. badchar controls the number of non-ASCII characters that a dzero or display command will accept when displaying a string referenced by a character pointer. The default is 3. case if set to on, causes the search command to perform case-sensitive string searches. The default is off. 166 Chapter 9 opt Shows option values or changes the value of a debugger option (continued) catch if set to on, catches any new task generated by a task under debugger control. The default is off. context controls the number of lines displayed in the Source window preceding the current line. The default is 2. devices if set to on, attaches to, or catches, any new device process or task generated by a task under debugger control. The default is off. echo if set to on, causes the debugger to echo all commands to the Dialog window. This is particularly useful when using the execute command to execute a file of debugger commands. The default is off. ibytes if set to on, causes the debugger to display the instruction bytes being disassembled. This affects the output of the unassemble command. In windowing mode, it also affects the Source window in mixed and asm source modes. The default is off. ignorepath if set to on, causes the debugger to ignore the pathname for the source file provided by the compiler. The default is off. list controls the default number of lines displayed by the list command in line mode. The default is 6. search defines a set of directories to search for the source code. If no + or -- is specified, the list of directories replaces the current list. Specifying a + at the beginning of the list appends the new list to the end of the current list. Specifying a -- at the beginning of the list removes the specified directories from the current list. source controls the display in the Source window in windowing mode. Repeatedly choosing the next values cycles through the possible display types in the order C, asm, and mixed. The source option controls the output when you execute a step or go. The default is C. 167 Commands and Built-in Functions opt Shows option values or changes the value of a debugger option (continued) strlen controls the maximum number of bytes that are displayed when a character string is displayed with the dzero command. The default is 128. task changes the current task to the task identified by the task-ID parameter. The task-ID parameter can be either the name of a task or the address of a task control block, as displayed by the tasks command. radix sets the default input type for constants. It is used to avoid having to type the initial 0x on hexadecimal constants. The default is decimal. rangelen controls the default size of ranges when no range size information is available. The default is 64. reslib if set to on, steps into resident libraries while tracing or running an application with watch breaks. The default is off . unassemble controls the default number of instructions that are disassembled by the unassemble command in line mode. It has no effect in C mode or windowing mode. The default is 4. Examples opt displays the settings of all options. opt unassemble 10 sets unassemble count to 10. opt search /src,/test sets search directories. opt search +test2 appends a new search directory. See Also display,dzero,list,unassemble 168 Chapter 9 proceed Single-steps over function calls Synopsis p[roceed] [integer] Description In C mode, the proceed command causes the debugger to step through the number of source statements specified by the integer parameter. In Mixed or Asm modes, it steps through integer number of machine instructions. If a function call is encountered, the function is executed as if it were a single statement. If the integer parameter is omitted, it defaults to 1. A proceed command is performed when you press the Return key without entering any commands in the Dialog window. The F6 key can also be used to enter the proceed command. Examples proceed steps 1 source statement in C mode or 1 machine instruction if in Mixed or Asm modes. proceed 5 steps 5 source statements in C mode or 5 machine instructions if in Mixed or Asm modes. See Also go, ps, trace, ts 169 Commands and Built-in Functions ps Single-steps over function calls by source line Synopsis ps [integer] Description The ps command causes the debugger to single-step through the number of C source statements specified by the integer parameter even if mode is set to Mixed or Asm. If a function call is encountered during stepping, the function is executed as if it were a single statement. If the integer parameter is omitted, it defaults to 1. Example ps2 steps through two source lines regardless of the debugger mode. See Also go, proceed, trace, ts 170 Chapter 9 quit Terminates the debugger Synopsis q[uit] Description The quit command terminates the debugging session and returns to the operating system prompt. When running in cross-development mode, the quit command only terminates the cross debugger (CPRX) on the host machine, leaving the kernel (CPRK) waiting for a new debug session. Normally, CodeProbe forces the application being debugged to call the exit function before terminating the application. The debugger then exits. If CodeProbe was started with the -startup option, the debugger exits without forcing the application to call exit. Example quit terminates the debugging session. 171 Commands and Built-in functions register Displays or modifies registers Synopsis r[egister] [register [[=] expression]] Description If no arguments are given, the register command displays the current contents of all the machine integer registers. If a register name is specified by the register parameter, the contents of that register are displayed. If an expression parameter is specified in addition to the register parameter, the value of the expression is stored in the register. The display and set commands can also be used to display and modify the contents of the registers. Examples register displays all registers and flags. register dS = 30 sets register D5 to 30. r d3 = index sets register D3 to the value of index. register a0 &x sets register A0 to the value pointed to by x. r a1 displays the value stored in register A1. See Also display, fregister, rflag, set 172 Chapter 9 restart Restarts the program being debugged Synopsis res[tart] [argument-list] Description The restart command causes the program you are debugging to be reloaded and executed up to the entry point of main, just as when the debugger was first invoked. (If the -startup option was specified when you invoked the debugger, execution will stop before the startup code is executed and not at the first line of the main function.) Because the program is reloaded, all static data is reinitialized. All breakpoints will be retained and watch breaks on static and external variables will be retained and disabled. The argument-list parameter provides the arguments for the program being debugged. These arguments are delimited by white space, just as would appear on the command line when invoking the program. The program will use these arguments as if it were invoked from the command line with them. The restart command cannot be used with the -command command-line option or as one of a sequence of commands separated by semicolons. When used, the restart command must occur at the end of a command line. The restart command potentially can cause your machine to crash if used improperly. When you enter the re s tart command, your application is immediately reloaded and re-executed with no cleanup of your currently running program other than calling the exit function to close files. This can leave the machine in an unacceptable state that can cause problems later. To avoid this problem, be sure to allow your application to run to completion if possible and do any necessary cleanup before issuing the restart command. The start and restart commands are the same if the same arguments are provided by the argument-list parameter. The significant difference between the two commands is their behavior when they are specified with no arguments. The start command restarts the program without any arguments; however, the restart command with no arguments restarts the program with the original arguments used when the debugger was invoked. 173 Commands and Built-in Functions restart Restarts the program being debugged (continued) Examples restart restarts the program using the same arguments with which it was initially invoked. restart myfile.txt 5 restarts the program passing it two arguments: myfile.txt and 5 restart "sample string" restarts the program passing in a string as an argument. See Also start 174 Chapter 9 return Returns immediately from the current function Synopsis ret[urn] [expression] Description The return command causes the current function to return to its caller without executing the rest of the function. The value of the expression parameter is used as the return value from the function. The value is converted to the appropriate type if necessary; however, it must be a scalar quantity (not a structure or union). An attempt to return a value from a function declared void is treated as an error, and a suitable message is displayed. Similarly, an error message is displayed if you use a simple return command (without a parameter) from within a function declared as having a return value. In all other cases, the return value is cast (if necessary) to the correct type and returned to the calling function. When a return command is given, the current function is returned immediately to the calling function. The return value, if any, is returned to the calling function, and execution is suspended as though a breakpoint were triggered in the calling function after the call was made. For instance, note the following code fragment: i = 5; j = func(i); if (j < 2) j++ ; Assume that the return command is issued during the execution of func in the form ret 7. Execution stops inside the line that did the call, just before the assignment to j. You can then single-step to the next statement. Examples return stringptr returns the value of stringptr. ret 5 returns an integer value of 5. return returns from a void function. 175 Commands and Built-in Functions rflag Displays or modifies flags Synopsis rf[lag] [flag ...] Description The rflag command can be used to display or modify the settings of the machine flags. If no parameters are specified, the current settings of the flags are displayed. With one or more arguments, the indicated flags are set or cleared according to the values given. The flag names are specific to the target machine. A flag setting can be one of the terms in the following table. The Set column comprises the terms used to set flags, while the Clear column comprises the terms used to clear flags. Flag Name Set Clear Overflow (yes/no) OV NV Sign (negative/positive) NG PL Zero (yes/no) ZR NZ Auxiliary Carry (yes/no) AC NA Carry (yes/no) CY NC Examples rflag displays all registers and flags. rflag cy sets the carry flag to 1. See Also fregister, register 176 Chapter 9 search Searches for a string in the current source file Synopsis sea[rch] [string] Description The search command searches the current source file for the specified string. In windowing mode, the search begins from the top line of the current Source window. In line mode, the search begins at the first line that would be displayed if a list command were entered with no arguments. In windowing mode, the cursor is positioned at the beginning of the matching string. The Source window is also repositioned so that the line containing the match is the number of lines specified by the context option from the top of the window. The context is set by the opt command. In line mode, the line containing the match is displayed. The search command with no arguments causes the debugger to search for the string specified in the last search argument, starting from the new current line. If no matches are found, a message is printed. If the user then enters search again, the search is resumed beginning at the top of the file. The case-sensitivity option, opt case, determines whether the search is case sensitive or not. Examples search foo finds the string "foo". search foo; finds the string "foo". The semicolon used in this command is a command delimiter and is not considered part of the search string. search foo\; finds the string "foo;" . The escape character (\) causes the semicolon to be part of the search string. search repeats the last search. See Also opt, list 177 Commands and Built in Functions set Modifies the values of variables or memory locations Synopsis se[t] (variable | register) = expression se[t] address [=] string Description The set command is used to modify the values of variables, registers, or memory locations in the program being debugged. You are most likely to use the first form of the set command in debugging C programs. It allows you to change the value of a variable in your program by referring to that variable by name. In this context, variable has a rather broad sense that includes references to array elements, structure members, and indirect references. The variable parameter cannot refer to an aggregate such as a structure, union, or array. The register parameter can be any valid register name, D0 through D7 and A0 through A7, and if a co-processor is present, FP0 through FP7. A $ prefix optionally may be used to distinguish the register from a variable of the same name. The expression parameter is the same as used in the C assignment statement. If necessary, the value for variable will be converted to the proper type in accordance with the normal C conversion rules; it is then entered into memory at the address of the first variable operand. This is similar to a C assignment statement for a scalar variable. The second form shown in the synopsis is used to store a string into memory. The null terminator is not copied unless it is explicitly present in the string. The equal sign is optional. Support for this form of set command may be removed in future releases. The built-in strcpy and memcpy functions are preferred. Examples set i = 5 sets the variable i equal to the integer value 5. set a = 3.1415 sets the variable a equal to the floating-point value 3.1415. set $d0 = 300 sets register D0 equal to 300. The $ is optional. set time->date = newtime sets the date member of the time structure equal to the value of the variable newtime. set stringptr "this string has no null byte" stores a string that is not null-terminated to the memory location pointed to by stringptr. 178 Chapter 9 set Modifies the values of variables or memory locations (continued) set stringptr "this string has a null byte\0" stores a null-terminated string to the memory location pointed to by stringptr. set stringptr "string one\0string two\0" stores two null-terminated strings to the memory location pointed to by stringptr. See Also fregister,memcpy,strcpy,register 179 Commands and Built-in Functions sleep Pauses for the time specified Synopsis sle[ep] number Description The sleep command pauses for the number of seconds specified by the number parameter. Example sleep 10 pauses for 10 seconds. 180 Chapter 9 source Displays the source file Synopsis so[urce] [filename] Description The source command overrides the C source file associated with the current module. The specified value for filename replaces the filename associated with the module for the rest of the current debugging session. The new file is displayed in the Source window immediately, and its name is echoed in the Dialog window. If no filename parameter is specified, the name of the current source file is echoed in the Dialog window but the current source file is not changed. If the filename you want to change to is the same as the default filename but the path is different, you can use the opt search command instead of the source command to change the locations that CodeProbe looks for source files. Examples source displays the current filename. source test/test1.c changes the filename for the current module to test1.c in the test directory. See Also opt 181 Commands and Built-in Functions start Restarts the program being debugged Synopsis sta[rt] [argument-list] Description The start command causes the program you are debugging to be reloaded and executed up to the entry point of main, just as when the debugger was first invoked. (If the -startup option was specified when you invoked the debugger, execution will stop before the startup code is executed and not at the first line of the main function.) Because the program is reloaded, all static data are reinitialized. All breakpoints are retained and watch breaks on static and external variables are retained and disabled. The argument-list parameter provides the arguments for the program being debugged. These arguments are delimited by white space, just as would appear on the command line when invoking the program. The program will use these arguments as if it were invoked from the command line with them. The start command cannot be used with the -command command-line option or as one of a sequence of commands separated by semicolons. When used, the start command must occur at the end of a command line. The start command potentially can cause your machine to crash if used improperly. When you enter the start command, your application is immediately reloaded and re-executed, with no cleanup of your currently running program other than calling the exit function to close files. This can leave the machine in an unacceptable state that can cause problems later. To avoid this problem, be sure to allow your application to run to completion and do any necessary cleanup before issuing the start command. The start and restart commands are the same if the same arguments are provided by the argument-list parameter. The significant difference between the two commands is their behavior when they are specified with no arguments. The start command restarts the program without any arguments; however, the restart command with no arguments restarts the program with the original arguments used when the debugger was invoked. 182 Chapter 9 start Restarts the program being debugged (continued) Examples start restartsthe program being debugged without passing it any arguments. start myfile.txt 5 restarts the program being debugged passing in the arguments myfile.text and 5. See Also restart 183 Commands and Built-in Functions symbol Finds the symbol nearest to the specified address Synopsis symb[ol] address Description The symbol command causes the debugger to search the symbol information and display the name of the symbol whose location is closest to the address specified by the address parameter. Example symbol 0x8040 displays the symbol whose address is nearest to 0x8040. See Also symload 184 Chapter 9 symload Reads symbol information from an executable file Synopsis sym[load] executable file sym[load] proc process-id sym[load] seg address executable-file Description The symload command associates an executable file and any debugging information found in that file with a loaded image. If given the filename of an executable-file, the symload command associates that file with the current hunk list. If the proc keyword is used, followed by the name of a process that is identified by the process-id parameter, the symload command attempts to map the segment list for the process with its executable file. If the seg keyword is specified along with an address and the filename of an executable file, the symload command treats the address as a pointer to a BCPL segment list and it maps the list to the executable file. Examples symload myapp reads the current segment list and symbols from the file named myapp. sym proc myapp reads the segment list and executable file for process myapp. symload proc 0xC85428 myapp reads the segment list and executable file for the process located at 0xc85428. symload seg 0xC84200 myapp uses the segment list at address 0xC84200. See Also hunks 185 Commands and Bui1t-in Functions tasks Displays system tasks Synopsis ta[sks] [a[ll]] Description The tasks command displays information about tasks. By default, it displays the tasks currently under debugger control. If the all option is specified, all system tasks are displayed. The opt task command can be used to change to a new task. Examples tasks displays a listing of all tasks under debugger control. ta all displays a listing of all tasks in the system. See Also activate, catch, deactivate, detach, opt 186 Chapter 9 trace Single-steps into function calls Synopsis t[race] [integer] Description In c mode, the trace command steps the number of source statements specified by the integer parameter. In Mixed or Asm modes, it steps the number of machine instructions specified by the integer parameter. If a function call is encountered, stepping continues into that function. If the integer parameter is omitted, trace will step one line. Examples trace steps one source statement if in C mode, or one machine instruction if in Mixed or Asm mode. t 5 steps five source statements or machine instructions. See Also go, proceed, ps, ts 187 Commands and Built-in Functions ts Single-steps by source line into function calls Synopsis ts [integer] Description The ts command is similar to the trace command in that it will step into functions encountered during execution. It is different in that ts will only step by C source line, even if the source mode is set to Asm or Mixed. The integer parameter specifies the number of C source lines to step. If no parameter is specified, ts will step one line at a time. Examples ts steps one source line regardless of the mode the debugger is in. ts 2 steps two source lines. See Also proceed,ps,trace 188 Chapter 9 unalias Deletes an alias Synopsis una[lias] name una[lias] * Description The unalias command removes entries from the debugger's list of aliases. The name parameter refers to any alias name. You can use the * parameter as a wildcard character to remove all aliases. Examples unalias foo deletes the alias for foo. una * deletes all aliases. See Also alias, define, undefine 189 Commands and Built-in Functions unassemble Displays memory as assembler instructions Synopsis u[nassemble] [location-1 [location-2]] Description The unassemble command displays the range of memory from location-1 to location-2 in assembler format. By default, the command begins disassembling at the current program counter. If subsequent unassemble commands are performed before the application is given control by a trace, proceed, or go command, it will continue disassembling from the point at which it finished the last invocation. If source line number information is available for the range of memory being disassembled, unassemble will display the C source line before displaying the corresponding instructions. It will display the number of assembler instructions generated for one C source line. If no source information is available for the range of memory being displayed, unassemble will display the default number of instructions as specified by the unassemble default item in the Options menu. By default this number is 4 instructions. The output of the unassemble command is equivalent in format to assembler mode output displayed in the Source Window. It will consist of three or four columns depending on the setting of the instruction bytes option, which is controlled by the opt ibytes command. (See Chapter 4, "Setting Up the Debugging Environment," for more information about setting instruction bytes.) The following is an example of unassemble output with instruction bytes on and source unavailable: > unassemble 0x25F950 48E70130 MOVEM.L D7/A2-A3,-(A7) 0x25F954 BFEC0004 CMPA.L 0004(A4),A7 0x25F958 65001BD6 BCS 00261530 The first field contains the hexadecimal address of the instruction being disassembled. The second field is a hexadecimal dump of the actual bytes composing the instruction. The third field consists of the M680X0 mnemonic for the given opcode. The fourth field consists of the operands to the instruction. If the instruction bytes option is turned off, the second field is not displayed. Examples unassemble \modl\func1 10 unassembles line 10 of func1 in mod1. unassemble 13 14 unassembles lines 13 to 14. 190 Chapter 9 unassemble Displays memory as assembler instructions (continued) unassemble func1 unassembles the first line of func1. unassemble func1 func2 unassembles from &func1 to &func2. unassemble continues unassembling at the last location. SeeAlso opt, list 191 Commands and Built in Functions undefine Deletes a macro definition Synopsis [#]und[efine] name [#]und[efine] * Description The undef ine command removes entries from the debugger's list of macro definitions. The name parameter specifies the name of the macro to removed. You can use the * as a wildcard character to remove all macro definitions. The # sign can be inserted before the undef ine command so that C header files (.hfiles) can be read by CodeProbe. Examples #undef foo deletes the macro named foo. undefine * deletes all macros. See Also alias, define, execute, unalias 192 Chapter 9 watch Sets a watch on a variable or memory Synopsis w[atch] expression | range [s[tatic] | d[ynamic]] Description The watch command is used to set a watch for the expression or memory range specified. Whenever control is returned to the user, for example by stepping or stopping at a breakpoint, the new value of the watched object is displayed in the Watch window. The Watch window can be opened with the View menu, the window command, or by pressing F1. In line mode, the object is not automatically displayed. You must use the w list command to display it. The watch command does not cause the debugger to stop execution when the value being watched changes; it just displays the changed value. Use the wbreak command to cause the debugger to stop when a value is changed. By default, watches are dynamic; that is, the expression being watched is re-evaluated whenever control returns to the debugger. The static option causes the watch expression to be evaluated once, when the watch is set. The result is treated as an address whose contents are displayed. Examples watch text->len sets a watch for the symbolic scalar text->len. w \mod\f1\a[0] L 20 sets a watch for a length of 20 bytes starting at the symbolic range specified by \mod\f1\a[0]. w &a[0] .. &a[5] sets a watch for the range from &a[0] to &a[5]. watch tmp[i] static if i = 3, watches tmp [3] regardless of changes to i. See Also wbreak,wclear,wdisable,wenable,wlist 193 Commands and Built-in Functions wbreak Sets a watch break Synopsis wb[reak] expression | range [s[tatic] | d[ynamic]] Description The wbreak command sets a watch break for the expression or memory range specified. Whenever any byte in a specified range is modified, control is returned to you. By default, watch breaks are static; that is, the expression is evaluated once when the watch break is set. The address result of the expression is then monitored by the watch break. The dynamic option indicates that the watch break expression or range should be re-evaluated whenever control returns to the debugger. Examples wbreak text->len sets a watch break for the symbolic scalar text->len. wb \mod\f1\a[0] L 20 sets a watch break for a length of 20 bytes starting at the symbolic range specified by \mod\f1\a[0]. wbreak &a[0].. &a[5] sets a watch break for the range from &a[0] to &a[5]. wb p->q dynamic sets a watch break for different locations depending on the value of p. See Also watch, wclear, wdisable, wenable, wlist 194 Chapter 9 wclear Clears one or more watches Synopsis wc[lear] integer [integer . . . ] wc[lear] * | l[ast] wc[lear] integer .. integer Description The wclear command is used to clear one or more watches or watch breaks. When a watch is cleared it ceases to exist and can be reinstated only by issuing the watch or wbreak command again. You can use the wdisable command to temporarily disable a watch. The integer parameter specifies the number of a watch as displayed by the wlist command. Any number of integer values can be specified as parameters to the wclear command. The * parameter specifies that all watches and watch breaks should be cleared. You can specify that all watches and watch breaks between two watch numbers be cleared by using the form integer . . integer. The last parameter can be specified to clear the last watch or watch break that was set. Examples wclear 2 5 6 clears watches or watch breaks numbered 2, 5, and 6. wclear last clears the last watch or watch break set. wc * clears all watches or watch breaks. wc4..7 clears watches 4, 5, 6, and 7. See Also watch, wbreak, wclear, wdisable, wlist 195 Commands and Built-in Functions wdisable Disables one or more watches Synopsis wd[isable] integer [integer ...] wd[isable] * | l[ast] wd[isable] integer .. integer Description The wdisable command is used to disable the recognition of one or more watches or watch breaks. When a watch or watch break is disabled, it is no longer recognized, but it remains on the current list of watches. A wenable command can be used to re-enable a watch or watch break that has been disabled with the wdisable command. The integer parameter specifies the number of a watch, as displayed by the wlist command. Any number of integer values can be specified as parameters to the wdisable command. The * parameter specifies that all watches and watch breaks should be disabled. You can specify that all watches and watch breaks between two watch numbers be disabled by using the form integer . . integer. The last parameter can be specified to disable the last watch or watch break that was set. Examples wdisable 2 5 6 disables watches or watch breaks numbered 2, 5, and 6. wdisable last disables the last watch or watch break set. wdisable * disables all watches or watch breaks. wdisable 4..7 disables watches 4, 5, 6, and 7. See Also watch, wbreak, wclear, wenable, wlist 196 Chapter 9 wenable Enables one or more watches Synopsis we[nable] integer ... we[nable][*] | l[ast] we[nable]integer .. integer Description The wenable command is used to enable the recognition of one or more watches or watch breaks that have been disabled by the wdisable command. The integer parameter specifies the number of a watch, as displayed by the wlist command. Any number of integer values can be specified as parameters to the wenable command. The * parameter specifies that all watches and watch breaks should be enabled. You can specify that all watches and watch breaks between two watch numbers be enabled by using the form integer . . integer. The last parameter can be specified to enable the last watch or watch break that was set. Examples we 2 5 6 enables watches or watch breaks numbered 2, 5, and 6. we last enables the last watch or watch break set. wenable * enables all watches or watch breaks. we 4..7 enables watches 4, 5, 6, and 7. See Also watch, wbreak, wclear, wdisable, wlist 197 Commands and Built-in Functions whatis Determines the type of an object Synopsis wha[tis] expression wha[tis] (type) Description The whatis command displays the type, location, and storage class of an object, or gives additional information about a data type. If an expression is given, whatis displays the C data type of the expression. If the result of the expression is a simple variable or a member of an array, whatis displays the address of the object and identifies it as either static, extern, or automatic. If the result of the expression is a function, whatis displays the address of the function, its return type, and its location. If a parenthesized type is given, including types that are defined by a typedef statement, whatis displays the full definition for the type. For struct, union, and enum types this means all members of the aggregate are displayed; for a type that has been defined by a typedef statement, this means the base type of the typedef is displayed. Using the whatis command on basic C data types such as int or long is allowed, but it is not very useful. Examples whatis i determines the type of a variable named i. wha main determines the type, address, and defining module for the main function. wha 3.5 determines the type of a constant. whatis Red determines the type of an enumeration constant. wha *p->c[3] determines the type of the expression *p- >c [3]. whatis (int) (1*3.4) determines the type of an expression with a type cast. whatis (node) determines the type of a typedef. whatis (struct X) displays the members of s truct X. 198 Chapter 9 where Shows the calling sequence Synopsis whe[re] [a[rgs]] [integer] Description The where command displays a backtrace of the function calls in the call sequence. Calls are listed in reverse order beginning with the most deeply nested function. The args option causes the where command to display the arguments to each function in a manner similar to the args command. The integer parameter specifies the number of calls to be displayed. By default, only the 20 most recent calls are printed. Here is an example of the output from the where command: > 1 In routine fpreg.o:\fpreg.c\five 48 > 2* Called from fpreg.o:\fpreg.c\six 68 (+0xE) > 3 Called from fpreg.o:\fpreg.c\seven 82 > 4 Called from fpreg.o:\fpreg.c\main 92 > ... The numbers on the left indicate a level number that can be passed to the env command. Level 1 is defined to be the function in which you are currently stopped or the run environment. The caller's level is 2, its caller is 3, and so on. These level number designations change over time as the program steps into and returns from functions. The asterisk indicates the current user environment as set by the env command. The Calls window also displays this information. Examples whe displays a list of the last 20 function calls. where S displays a list of the last 5 function calls. where a displays the arguments to each function. See Also args, env 199 Commands and Built-in Functions window Opens or closes a window Synopsis wi[ndow] window-name [on | off] Description The window command is used to open and close a specified window. Any of the following values can be specified as the window-name parameter: c[alls] mo[dules] w[atch] he[lp] ms[g] s[ource] me[mory] r[egister] If the window command is invoked with only a window-name parameter, the command acts as a toggle for the specified window; thus, if the window is currently opened, the window command will close it, and if it is currently closed it will be opened. If on or off is specified, the window is forced into that state, regardless of its current state. If a window that is already open is set to on, it will pop to the top of the window hierarchy. The window command is ignored in line mode. Examples wi register toggles the Register window. window help on opens the Help window or pops it to the top. 200 Chapter 9 wlist Lists all watches Synopsis wl[ist] Description The wlist command lists all watches and watch breaks. Disabled watches are marked with an asterisk. Watch breaks are distinguished from regular watches by an exclamation mark. The value associated with the watch is displayed if available. Example w list lists all watches. See Also watch, wbreak, wclear, wdisable, wenable 201 Commands and Built-in Functions wmsg Writes a message to the Message window Synopsis wmsg integer message-text Description The wmsg command is used to write the text specified by the message-text parameter in the Message window. The integer parameter specifies the location in the window for the text. Line 0 is the top line. This command is used primarily with debugger or AREXX scripts. Examples wmsg 0 --- This is the Message window. --- displays the string --- This is the Message window. --- on the top line of the Message window. wmsg 12 This goes on line 12. displays the string This goes on line 12. on line 12 of the Message window. 202 Chapter 9 Built-in Functions As described in Chapter 3, "Debugging Your Program", built-in functions are standard, commonly used functions recognized by the compiler and expanded inline for efflciency. The SAS/C Compiler defines several built-in functions that are described in Chapter 4, "Using the System Header Files to Access Libraries," of the SAS/C Development System Library Reference. CodeProbe also defines several built-in functions. These functions are related to the library built-in functions in that several of them share the same names and the same functionality. The CodeProbe built-in functions are provided for the following reasons: [] for use with the call and display commands. Since the built-in functions provided with the compiler generate in-line code, these commands would not be able to access them. [] to add convenience and functionality. CodeProbe's built-in functions provide functionality not available through other debugger commands. The compiler's built-in functions perform in accordance with the ANSI C standards. This may be slightly different from what CodeProbe's built-in functions do. For example, passing NULL to a built-in function is an error in CodeProbe. Overlapping memory blocks may be handled differently. Also, the parameters to CodeProbe's built-in functions are a little more flexible than the parameters to the C versions: formal type actual parameter types allowed void * constant, register, any pointer scalar, array, function, address, string constant char * constant, register, character pointer, unsigned character pointer, character array, string constant int constant, register, any integral scalar, bitfield, enumerated constant Floating-point constants and registers are not allowed, and string constants can only be specified as the source operand. 203 Commands and Built-in Functions Built-in Function Reference This section describes the following built-in functions: memcmp compares two memory blocks memcpy copies a memory block (non-overlapping) memmove copies a memory block (possibly overlapping) memset sets memory to a specified value strcat concatenates two strings strcmp compares two strings strcpy copies a string strlen returns the length of a string. 204 Chapter 9 memcmp Compares two memory blocks Synopsis i = memcmp ( a, b, n ); int i; /* comparison results */ void *a, *b; /* blocks being compared */ int n; /* block size in bytes */ Description The memcmp function compares two memory blocks and returns a value whose sign indicates the collating sequence of the blocks, as follows: Return Meaning Negative First block below the second Zero Blocks are equal Positive First block above the second CodeProbe has a built-in #define that causes all references to memcmp to be referenced to __builtin_memcmp, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called memcmp in your code, you should use the undef ine command to clear the define or use the backtick character to escape the function's name. Example display memcmp(ptr1, ptr2, n) displays the result of comparing ptr 1 and ptr2 for n bytes. b 27 when(memcmp(ptr1, ptr2, 10) < 0) breaks at line 27 when the 10 bytes pointed to by ptr 1 evaluate to a value less than the value of the 10 bytes pointed to by ptr2. See Also memcpy, memmove, memset 205 Commands and Built-in Functions memcpy Copies a memory block (non-overlapping) Synopsis to = memcpy(to, from, n); void *to; /* destination pointer */ void *from; /* source pointer*/ int n; /* block size in bytes */ Description The memcpy function copies data from one memory block to another. The destination pointer is returned. The memcpy function cannot be used to copy overlapping memory blocks. You should use the memmove function when copying overlapping blocks. Also note that you can crash your machine if there is not enough memory to hold the data at the destination memory location. CodeProbe has a built-in #define that causes all references to memcpy to be referenced to __builtin_memcpy, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called memcpy in your code, you should use the undef ine command to clear the define or use the backtick character to escape the function's name. Example call memcpy(ptr1, &j, 10) copies 10 bytes from ptr2 to ptr1. call memcpy(0x804a, myptr, 50) copies 50 bytes from myptr to location 0x804a. b 27 (memcpy(a0, a1, 15)] sets a breakpoint at line 27 with an action to copy 15 bytes from the memory pointed to by register A1 to the memory pointed to by register A0. See Also memcmp, memmove, memset 206 Chapter 9 memmove Copies a memory block (possibly overlapping) Synopsis to = memmove(to, from, n); void *to; /* destination pointer */ void *from; /* source pointer*/ int n; /* block size in bytes */ Description The memmove function copies data from one memory block to another. Overlapping blocks are handled correctly. The destination pointer is returned. Note that you can crash your machine if there is not enough memory to hold the data at the destination memory location. CodeProbe has a built-in #define that causes all references to memmove to be referenced to __builtin_memmove, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called memmove in your code, you should use the undef ine command to clear the define or use the backtick character to escape the function's name. Example call memmove(ptr1, &j, 10 ) copies 10 bytes from ptr2 to ptr 1. call memmove(0x804a, myptr, 50) copies 50 bytes from myptr to location 0x804a. b 27 {memmove(a0, a1, 15)} sets a breakpoint at line 27 with an action to copy 15 bytes from the memory pointed to by register A1 to the memory pointed to by register A0. See Also memcpy, memcmp, memset 207 Commands and Built-in Functions memset Sets memory to a specified value Synopsis to = memset(to , c , n ); void *to /* base of memory to be initialized */ int c; /* initialization value */ int n; /* number of bytes to be initialized */ Description The memset function sets the specified number of bytes of memory to the specified value. Note that you can crash your machine if there is not enough memory to hold the data at the destination memory location. CodeProbe has a built-in #define that causes all references to memset to be referenced to __builtin_memset, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called memset in your code, you should use the undef ine command to clear the define or use the backtick character to escape the function's name. Example call memset(ptr, 0, 100) sets 100 bytes to 0 starting at the address pointed to by ptr. call memset(a0, 'X', 50) sets 50 bytes to the ASCII character X starting at the address pointed to by register A0. See Also memcpy, memcmp, memmove 208 Chapter 9 strcat Concatenates two strings Synopsis to = strcat(to, from); char *to; /* destination pointer */ char *from; /* source pointer*/ Description The strcat function copies data from one string to the end of another string until a null character is found. Overlapping strings are not handled by the strcat function. Note that you can crash your machine if there is not enough memory to hold the string at the destination memory location. CodeProbe has a built-in #define that causes all references to strcat to be referenced to __builtin_strcat, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called strcat in your code, you should use the undefine command to clear the define or use the backtick character to escape the function's name. Example call strcat(myptr, "foo") concatenates the string "foo" after the string pointed to by the variable myptr. See Also strlen, strcmp, strcpy 209 Commands and Built-in Functions strcmp Compares two strings Synopsis i = strcmp(a, b); nt i; /* comparison result */ char *a, *b; /* strings being compared */ Description The strcmp function compares two strings and returns a value whose signs indicate the collating sequence of the blocks as follows: Return Meaning Negative First string below the second Zero Strings are equal Positive First string above the second CodeProbe has a built-in #define that causes all references to strcmp to be referenced to __builtin_strcmp, which is the actual name of the CodeProbe functioll. If you want to step into or call an actual function called strcmp in your code, you should use the undefine commalld to clear the define or use the backtick character to escape the functioll's name. Example display strcmp("abc", ~def") tests the strings "abc" and "def" and displays the return value. The value indicates whether the strings are equal or which string is higher. break myfunc when(strcmp(arg, "foobar") == 0) breaks at the furlction myfunc when the variable arg points to the string "foobar". See Also strlen,strcpy,strcat 210 Chapter 9 strcpy Copies a string Synopsis to = strcpy(to, from); char *to; /* destination pointer */ char *from; /* source pointer */ Description The strcpy function copies data from one string to another until a null character is found. Overlapping strings are not handled by the strcpy function. Note that you can crash your machine if there is not enough memory to hold the string at the destination memory location. CodeProbe has a built-in #define that causes all references to strcpy to be referenced to __builtin_strcpy, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called strcpyin your code, you should use the undefine command to clear the define or use the backtick character to escape the function's name. Example call strcpy(a, b) copies the string pointed to by b to the memory location pointed to by a. See Also strlen, strcmp, strcat 211 Commands and Built-in Functions strlen Returns the length of a string Synopsis len = strlen( s ); int len; /* length of string s */ char *s; /* string to scan for length */ Description The strlen function returns the length of a string, as determined by the index of the first null character found. CodeProbe has a built-in #define that causes all references to strlen to be referenced to __builtin_strlen, which is the actual name of the CodeProbe function. If you want to step into or call an actual function called strlen in your code, you should use the undefine command to clear the define or use the backtick character to escape the function's name. Example display strlen( "hello" ) displays the length of the string "hello", which is 5. display strlen(0x804a) displays the length of the string starting at address 0x804a. See Also strcmp, strcpy, strcat 212 213 Part 2 Using the SAS/C Utilities Chapter 10 Utility Reference 214 215 10 Utility Reference This chapter describes the utilities included with the SAS/C Development System. The utilities are described in alphabetical order. The description of each utility includes each of the following sections, if applicable: Synopsis shows the format of the command that invokes the utility Description describes what the utility does and contains all the information you need to use the utility Example contains examples that illustrate how to use the utility Error Messages describes the error messages, if any, produced by the utility and the action required to fix the error. 216 Chapter 10 cover Analyzes coverage data Synopsis cover [options] [datafile]. . . Description The cover utility analyzes the coverage data produced when you compile your program with the coverage option, link with the object file covutil.o, and run your program. Using this data, you can determine which lines of code in your program were executed and which were not. This information can help you design test cases that exercise all paths through your program. When you run your program, it writes coverage data to the file cover . dat in the current directory. If this file does not exist, your program creates it. If this file already exists, your program reads in the existing cover.dat, merges in the new coverage data, and writes the merged data back to cover.dat. This utility analyzes the coverage data file, locates your C source files, and produces new output files containing a copy of your C source with arrows pointing to lines that generated code that was not executed. Ihe output file has the same basename as the C source file, but with the extension .cov instead of .c. By default, cover looks for the coverage data file cover . dat in the current directory. If you choose to rename cover.dat, you must specify datafile when you run cover. Your program must adhere to the following rules: [] The main routine must be called main rather than _main because covutil.o replaces _main with an enhanced version. [] Your program must end by calling exit or by falling through the end of main. (Do not call XCEXIT or abort, for example.) [] Your prograrn must not be a resident library or device. To use cover, follow these steps: 1. Compile your program with the coverage and debug=line options. (You can use a higher debug level if you like.) I)o not specify the nostdio option. Specifying coverage slows down your program considerably, so do not specify coverage for production software. You can choose to compile only certair modules with coverage to reduce overhead. 2. Link your compiled program with covutil.o. This file is located in sc:examples/cover. The covutil.o file replaces the main and _exit functions in your program with enhallced versions that can constrllct and write out the coverage data. 3. Run your program normally to create cover.dat. 4. Run the cover utility. 217 Utility Reference cover Analyzes coverage data (continued) The cover utility supports the following options: dir =directory-pathname specifies the directory path or paths to search to locate the C source files. The coverage data contains the name of the C source file, but not its directory. If the C source file is not in the current directory, specify the dir= option with the proper directory as its argument. To specify multiple pathnames, separate each pathname with a plus (+) sign or a comma (,). Also, you can specify dir= as many times as necessary. merge filename tells cover to read the specified data files, merge the information contained in them, and write the merged data to filename. If you specify merge, cover does not look for C source files and does not produce a report. This option allows you to combine the results of a suite of tests to determine what code is exercised by the test suite as a whole. nosource tells cover not to read in the C source files. Instead, it prints a report to the Shell window listing the names of all source files and the lines in each file that were not executed. Example To analyze the coverage of the lines.c program, open a Shell and use the cd command to change to the sc:examples/lines drawer. Enter the following command: sc lines.c sc:examples/cover/covutil.o coverage debug=line link The compiler produces a program called lines. Run this program with no command-line options: lines Watch the lines for a few seconds, then click on the close gadget to terminate the program. The program produces a file called cover. dat. Run the cover utility on this file: cover 218 Chapter 10 cover Analyzes coverage data (continued) The cover utility reads cover .dat and lines.c and writes the file lines.cov. Use your editor to examine lines.cov. Lines that were not executed are highlighted with an arrow (==>) in the left margin. 219 Utility Reference diff Determines the differences between two files Synopsis diff[>destination] loptions] file1 file2 Description The diff utility determines the differences in contents between two files and describes the lines that you should delete from, add to, or change in file2 to make it look like file1. To help you find those lines, diff identifies the line numbers and gives the text of the lines. If you enter the diff command without specifying filenames, diff displays the version that you are using and describes the options available. Output from this utility is sent to the standard output device, unless you redirect it by specifying the -o option or by entering a greater than (>) sign followed by a destination. diff supports the following options: -bnn sets the size of the I/O buffer to the value specified by nn. The default I/O buffer size is 4K, and the maximum size is limited by the amount of available system memory. Increasing the size of the I/O buffer makes diff run faster. -c displays only those lines common to both files. -Fnn sets the column number where you want diff to begin comparing lines. For example, if you set nn to 25, diff ignores the first 25 characters on each line. -Lnn sets the column number where you want diff to stop comparing lines. For example, if you set nn to 75, diff ignores the characters beyond column 75 on each line. -lnn defines the number of lines, nn, per file that can be handled by diff. diff uses two tables (one for each file) to keep track of the lines read in from each file. The default size of each of these tables is 2000; the maximum number is limited by memory availability. If diff is running out of memory and your files are less than 2000 lines in length, you can use this option to increase the amount of memory available, or you can check to see if any other tasks are running concurrently and shut down any unwanted tasks. -ofile sends the output to the specified file (or device). You can use this option instead of the AmigaDOS redirection command. You can send the output to a different device by specifying the device name. For example, to send output to the printer, specify -oprt: . To send output to a file on drive df0:, specify -odf0:filename. 220 Chapter 10 diff Determines the differences between two files (continued) -p filters out unprintable characters from the input stream. You can use this option to clean out an AmigaDOS binary file. -q suppresses any messages if there are no differences between the specified files. -w ignores differences related solely to space or tab characters and reduces sequences of these characters to a single space. This option also removes trailing blanks. When you specify the -w option, diff uses additional memory to create a third table for each line in its compressed form. Note: The appendix, "diff File-Matching Algorithm," discusses the theory of file matching and how it affects diff . To compare the two files, newfile and oldfile, you enter the following command: diff newfile oldfile diff compares the two files and gives you a set of instructions to follow to change oldf ile into newf ile. The instructions begin with the following message: TO TRANSFORM oldfile INTO newfile ... The instructions are displayed in three types of blocks: a delete block, an append block, and a change block. A delete block describes the lines that you should delete from oldfile, and it has the following form: *** DELETE [i,j] FROM oldfile *** Text of first line that you should add. >Text of second line that you should add. >Text of third line that you should add. The number i is the line number in oldfile after which the lines should be added. A greater than (>) sign preceding a line of text indicates that you should add the line. Note: The line number i will not be correct if you make other changes to the lines in oldfile before line number i. A change block lists the lines in oldfile that you should change and shows how to change them. diff presents this information as a series of lines to delete and a series of lines to add in place of the deleted lines. A change block has the following form: *** CHANGE [i,j] IN oldfile TO [m,nl IN newfile *** New text (from newfile) for line 1 in oldfile. >New text (from newfile) for line 2 in oldfile. >New text (from newfile) for line 3 in oldfile. The numbers i and j are the first and last line numbers in oldfile of the lines to be deleted. The numbers m and n are the first and last line numbers in newfile of the lines you need to add to oldfile. Examples Suppose you wanted to compare the contents of the files cow and lamb. The file lamb contains the following lines: Mary had a little lamb. Its fleece was white as snow. Everywhere that Mary went, The lamb was sure to go. 222 Chapter 10 diff Determines the differences between two files (continued) The file cow contains the following lines: Mary had a very large cow. Its fleece was white as snow, Mary had a what? Everywhere that Mary went, If you entered the command diff lamb cow this utility would produce the following: TO TRANSFORM cow INTO lamb ... *** CHANGE 1 IN cow TO 1 IN lamb *** < Mary had a very large cow. Mary had a little lamb. *** DELETE 3 FROM cow *** < Mary had a what? *** APPEND AFTER 4 IN cow *** > The lamb was sure to go. Error Messages The diff utility may generate the following error messages: Can't open file indicates that diff cannot open the named file. The file may not exist or it may be protected. Diff I/O Error indicates an I/O problem. Improper -1 specification: nn indicates that diff cannot interpret the nn value specified with the -1 option as a number. 223 Utility Reference diff Determines the differences between two files (continued) Internal Error: ... indicates an internal error. Please contact the Technical Support Division at SAS Institute if you see this error message. The Technical Support representative will need the following information: [] the version of diff you are using [] the exact wording of the command line you used [] the exact wording of the message you received [] the size of the files you were trying to compare. Line table overflow indicates that one of the two line tables, in which diff stores the lines from each file while they are being compared, is too small to hold the lines in one of the files. Try increasing the line table size with the -l option. Not enough memory for nn lines per file indicates that you have used the -l option to increase the line table size, but you do not have enough memory to increase it by the amount you specified. Out of memory indicates that diff is out of memory. Try decreasing the line table size with the -l option if possible. Do not use the -w option. You can also try decreasing the size of the I/O buffer by using the -b option; however, this action makes diff run slower because more disk accesses may be required. If you are using a hard disk, this factor may be negligible. Too many file names: ... indicates that you have made an error on the command line in such a way that diff assumes you are attempting to operate on more than two files. Unrecognized option indicates that you specified an option that diff does not recognize. 224 Chapter 10 grep Searches for and prints regular expressions Synopsis grep [>destination] [options] pattern file . . . Description The grep utility searches the files you specify for all the lines that contain the specified pattern. For each file in which it finds the pattern, grep displays, on the screen, the filename, line number, and contents of the line that contains the matching string. The patterns that you can specify can be specific or general, and they are sometimes referred to as regular expressions. In this book, they are referred to as patterns. For example, suppose you are working on a long document in a file named document . txt. You originally were going to call the document a user manual, but you have decided to call it a user's guide. You need to see where you have used the word manual to describe the document. You could enter the following command: grep manual document.txt grep displays all of the lines in the file that contain the word manual. These lines could include such phrases as the manual, insert the paper manually, or refer to your AmigaDOS manual. By using special characters as described under "Specifying the Pattern" later in this discussion, you can tell grep exactly what to look for so that it does not display lines in which you are not interested. To specify the files that you want grep to search, you can use the AmigaDOS wildcards (#?). For example, to search all files in the current directory that have an extension of .c, enter # ?.c as the filename. To search all files in the root level directory of drive df 0: that begin with the letter g and have the extension .c, enter df0:g#?.c. AmigaDOS ignores the case of filenames. It will find the files you specify whether you enter the name in uppercase, lowercase, or mixed case. You can redirect the output from grep by specifying a greater than (>) sign followed by the destination where you want the output sent. You may want to redirect the output to a file and print that file. 225 Utility Reference grep Searches for and prints regular expressions (continued) grep supports the following options: -c prints the total number of matched lines. -f prints only the names of all files in which grep finds a string that matches the pattern. -n tells grep not to display line numbers. -p displays only printable ASCII characters. Non-printable characters are filtered out. This option is useful if you are searching a binary file that may contain control characters. -q does not display filenames or line numbers. -s displays the names of all files that grep searches. Normally, grep displays only those filenames in which it found a match for the pattern. -v prints only the lines in which a match of the pattern is not found. -v prints the version number of grep. -S tells grep not to distinguish between upper- and lowercase. For example, if you use this option, the pattern int would match int, INT, Int, and INt. Specifying the Pattern By using characters that grep interprets in special ways, you can specify some very complex patterns. Because grep is so flexible, you must also be specific about the pattern for which you are searching. The following list describes the special characters that you can use to specify the pattern for which you are looking: . is the grep wildcard character. A period will match any single character, including a space, tab, newline, or control character. A period followed by an asterisk(*) tells grep that any number of any characters can be present. The .* sequence is equivalent to the #? sequence for AmigaDOS commands. " " are used to enclose patterns that include space characters. 226 Chapter 10 grep Searches for and prints regular expressions (continued) [] are used to search for any one character from a set of characters by enclosing that set of characters inside square brackets. A set of characters enclosed in square brackets is called a character class. A character class will match one single character. For example, to search for lines that contain vowels, you can enter [aeiou]. - is used to specify a range. Inside a character class, you can specify a range of characters by entering the first character in the range and the last character in the range separated by a hyphen. The first character must occur alphabetically before the second. For example, to find any one of the lowercase alphabetic characters, you enter [ a- z ] . ! is used as the negation character when included as the first character in a character class. An exclamation point tells grep to find any character that is not in the character class. For example, to find any one character that is not a lowercase alphabetic character, enter [!a-z] . To find any one character that is not a lowercase alphabetic character and is not the end-of-line character, enter [!a-z\N]. * tells grep that the preceding character does not have to be present in the pattern but can be present an unlimited number of times. In other words, an asterisk means "zero or more of." A period followed by an asterisk tells grep that any number of any characters can be present. The .* sequence is equivalent to the #? sequence for AmigaDOS commands. + tells grep that the preceding character must be present in the pattern at least one time but can be present an unlimited number of times. In other words, a plus sign means "one or more of." For example, to find all lines in your file that contain one or more of the lowercase letter t, enter t+. ^ tells grep that the pattern must begin in column 0. Enter the caret (^) at the beginning of the pattern. grep will look only for those lines in which the pattern occurs beginning in column 0. For example, to find all lines that begin with a left parenthesis, enter ^(. 227 Utility Reference grep Searches for and prints regular expressions (continued) $ tells grep that the pattern must occur at the end of a line. Enter the dollar sign at the end of the pattern. For example, to find all lines that end with a right parenthesis, enter ) $. \ is the escape character. If you want to search for any of the special characters included in this list, you must enter a backslash before that character. For example, to find all lines that contain a caret, enter \~. Similarly, if you want to search for a backslash, enter two backslashes, \ \ . You also need to use the backslash to identify certain additional characters. These characters are as follows: \b backspace \n newline \r carriage return \s space \t tab \xij control character identified by hexadecimal digits ij For example, to locate all lines containing the Control-g character, enter \x07. You can combine these characters to specify any pattern you need. The way in which you specify the pattern to grep determines the response you will receive. grep does not convert tabs to spaces or change any combinations of spaces and tabs. If grep does not respond as you expect it to, try escaping any special characters with the backslash (\) character. Alternatively, try reducing the number of the special characters in your search pattern. Examples To search for one word, you need only specify the word and the file in which you want to search. For example, the following command searches the file document.txt for the word manual: grep manual document.txt To search for a string of words that are separated by spaces you must enclose the entire string within double quotes, as follows: grep "this is the string to search for" document.txt 228 Chapter 10 grep Searches for and prints regular expressions (continued) Specifying Any Single Character You can tell grep that a character can be any character by using a period (.) to designate that character. For example, you can specify a four-character pattern, beginning with th and ending with n, in which the third character can be anything, by specifying the following command: grep th.n document.txt This command will display all lines with patterns such as than then thanks Ethan The period will match any single character, including an alphabetic character, numberic character, space, tab, newline, or control character. For example, you can enter the following command: grep 123.45 document.txt This command will display all lines containing any of the following strings: 123a45 123 45 123!45 123(45 123.45 Specifying Character Classes A character class is useful when you need to look for characters that do not follow a pattern or when you do not care about the case of a character. For example, the following command displays all lines containing the symbols %, &, or ~: grep [%&~] document.txt If you want to display all lines containing either the or The, you can enter the following command: grep [Tt]he document.txt 229 Utility Reference grep Searches for and prints regular expressions (continued) Similarly, you can enter the following command: grep [Tt][Hh][Ee] document.txt This command displays all lines containing any of the following strings: THE THe The the thE tHE tHe ThE Using the -$ option produces the same results: grep -$ the document.txt Inside a character class, you can use a minus (--) sign to specify a range of characters. The first character must occur alphabetically before the second. For example, the following command displays all lines that contain a lowercase letter: grep [a-z] document.txt Similarly, the following command displays all lines that contain any lowercase letter, any uppercase letter, or any decimal number: grep [a-zA-ZO-9] document.txt A practical use of character classes arises when you need to display all the lines in your file in which you refer to a specific year. Since each character class matches one character, enter the following command: grep [0-9][0-9][O-9][O-9l document.txt If you are concerned only with years in the nineteenth and twentieth centuries, then enter this command: grep 1[89][0-9][0-9] document.txt 230 Chapter 10 grep Searches for and prints regular expressions (continued) Also, the exclamation point (!) means not if it occurs as the first character in a character class. For example, the following command displays all lines that contain any character that is not a lowercase letter: grep [!a-z] document.txt The following command displays all lines that contain any character that is not the number sign (#): grep [!#] document.txt Specifying the Number of Times a Character Can Appear An asterisk (*) tells grep that the preceding character can be present zero or more times. For example, you may have a file in which you have referred to Gail and mentioned a year in which some event has occurred. To display those lines in which both Gail and a year occur, enter the following command: grep "Gail.*[0-9][0-9][0-9][0-9]" document.txt The period (.) followed by an asterisk (*) tells grep that any character can be between Gail and the year and that you do not care how many of the characters appear. This command would display lines such as the following: Call Gail Barbara Industries at 1-999-629-9310. Gaillard de Marentonneau was a 1900s century botanist. My eldest daughter Gail was born in 1969. You can also use the asterisk (*) after a character class if you want to tell grep that you do not care how many of the characters in the character class occur in the pattern. For example, the following command displays any combination of zero or more lower- or uppercase letters t and the letters he: grep [tT]*he document.txt 231 Utility Reference grep Searches for and prints regular expressions (continued) This command displays lines containing strings such as the following: he tthe These hero penuche inherit mother Using the plus (+) sign instead of the asterisk (*) tells grep that you want the string to include at least one t. Using a plus sign displays the following strings: tthe These mother If you want to display only lines that contain the word the, you can use the following command: grep "[tT]+he" document.txt Of the previously listed words, this command displays only tthe. If you enter an asterisk (*) instead of a plus (+) sign, this command displays he and tthe. If you include an exclamation point (!) as the first character in the character class, this command displays only the following strings: he hero penuche inherit Specifying a Pattern at the Beginning or End of a Line As the first character in the pattern, a caret (^) tells grep to display only those lines that begin with the pattern. For example, to display only lines that begin with numerals, you can enter the following command: grep ^[10-9] document.txt Similarly, you can tell grep to display only those lines that end with a pattern by entering a dollar sign ($) as the last character in the pattern. For example, the following command tells grep to display all lines that end with the word the: grep "[tT]+he$" document.txt 232 Chapter 10 grep Searches for and prints regular expressions (continued) Specifying Patterns that Contain Special Characters Using a backslash (\), you can search for any of the special characters that grep recognizes. For example, if you want to search for a dollar sign ($), enter a backslash (\) in front of the dollar sign. grep assumes you are looking for a dollar sign and not for a pattern that occurs at the end of a line. Similarly, the following command displays all lines that contain left brackets ([): grep \[ document.txt You also can use the backslash (\) to tell grep that you want to display all lines that contain backslashes, as follows: grep \\ document.txt To locate all lines containing tab characters, enter the following command: grep \t document.txt You also can use the backslash (\) inside of a character class. For example, to find all lines that begin with a space or a tab character, you can enter the following command: grep "^[ \t]" document.txt Because the period (.) is the grep wildcard character, to search for the phrase and so on ..., use the following command: grep "and so on \.\.\." document.txt You can use \xij to search for control characters. Control characters are generally used as printer format instructions in files produced by word processors. Identify the character by its hexadecimal number (ij). For example, to display all lines that contain Control-g, enter the following command: grep \x07 document.txt 233 Utility Reference grep Searches for and prints regular expressions (continued) To find lines that contain Control-z, enter the following command: grep \xla document.txt The dollar sign ($) special character works much like the carat (^) except that it forces the match to occur only at the end of a line. For example, to search for all occurrences of the C language comment terminator, */, at the end of a line, enter the following command: grep \*/$ document.txt The backslash (\) tells grep not to interpret the asterisk (*) in its special sense as a closure operator. Suppose you have a number of C language source files, each with filenames that end with .c, and you need to search these files to find all calls of either of the read or fread functions. Enter the following command: grep "f*read *(" #?.c This command prints every line in these files that contains either read or fread, followed by O or more spaces and a left parenthesis. You also can search your files for all function definitions. Assume that each function definition begins with the function name and parameter list on a separate line. You can use the following command: grep "^[a-zA-Z_ ]+[a-zA-Z0-9_ ]*(" #?.c The pattern matches only expressions that begin a line. The expression must consist of one or more lowercase letters, uppercase letters, or the underscore (_), followed by 0 or more spaces, and then a left parenthesis. This command will print lines such as the following: get1(s) /* get a line */ _read () my_read(fp) {fread(fp,x);} However, this command will not select a line such as char *get1(p) /* get a line */ 234 Chapter 10 grep Searches for and prints regular expressions (continued) You can use grep to help locate mismatching left and right braces ({}). To print each line that contains a left or right brace, you can enter the following: grep [{}] #?.c Error Messages grep may generate the following error messages: Bad character class indicates that grep is unable to interpret a character class in the pattern you have asked it to find. Check to see if you have used any special symbols that you did not intend to use. This message also can be generated if, in specifying a character class and using the minus (--) character to indicate a range of characters, the first character in the range does not alphabetically precede the second (for example, [d-a]). Bad pattern indicates that grep is unable to interpret the pattern you are asking it to find. You may have used a special character in the pattern that does not make sense in this context. Check to see if you have forgotten to escape a special character. Can't find file(s) ... indicates that grep is unable to find one or more of the files you have asked it to search. The files may not exist, or you may have misspelled the filenames. Can't open ... indicates that grep is unable to open the named file. The file may not exist or may be protected. Closing ] not found indicates that grep believes that you have asked it to search for a pattern that contains a character class, but you have omitted the right bracket (]) that terminates the character class. If not, you may have included a left bracket ([) in the pattern but forgot to use a backslash (\) before it. Empty character class indicates that a character class you have used in your pattern has no members, for example []. 235 Utility Reference grep Searches for and prints regular expressions (continued) Improper hex specification indicates that you have used the x escape sequence but have not followed it with two recognizable hexadecimal digits. Incompatible combination of options indicates that the options with which you have invoked grep are contradictory. Internal Error: . . . indicates an internal error. Please contact the Technical Support Division at SAS Institute if you see this message. The Technical Support representative will need the following information: [] the version number of grep you are using [] the exact wording of the command line you used [] the exact wording of the resulting error message. Invalid option indicates that you have used a command line option that grep does not recognize. This message also can be generated if your pattern begins with a minus sign (--) but you have not escaped it or enclosed the pattern in double quote marks ("). No beginning double quote in pattern indicates that grep has detected double quote marks (") in a pattern that did not start with a double quote. You may need a backslash (\) before the double quote. No file arguments provided indicates that grep believes you have specified a pattern but no filenames. This message also may be generated if you invoke grep with a filename but no pattern. No pattern or file arguments given indicates that grep cannot find either a pattern or filename on its command line. Out of space indicates that grep has run out of space in constructing its pattern representation. Please contact the Technical Support Division at SAS Institute if you see this message. Pattern ill-formed: no terminating double quote indicates that you started the pattern with a double quote (") but failed to terminate it with one. 236 Chapter 10 grep Searches for and prints regular expressions (continued) Too few arguments to GREP indicates that grep demands at least two arguments on its command line: a pattern and at least one filename. 237 Utility Reference gst Manages global symbol tables Synopsis gst [gst-filename] [options] [symbol-name . . . ] Description A Global Symbol Table (GST) is a collection of all the information defined in a set of header files and stored in a format that the compiler can use easily and quickly. You can use GSTs to reduce significantly the processing time required for header files. However, GSTs require additional disk space and impose some restrictions on your header files. For information on creating and using GSTs, refer to Chapter 4, "Using the System Header Files to Access Libraries," in SAS/C Development System Library Reference. The gst utility helps you manage GSTs and extract information from a GST. With the gst utility, you can [] load a GST into memory [] unload a GST [] list all GSTs currently in memory [] extract symbol information from a GST. GSTs must be loaded into memory before they can be used. Normally, a GST is loaded automatically the first time you issue a command that needs the GST. After a GST is loaded, it will remaill in memory until either the system needs the memory, until you mallually unload it using the gst utility, or until you tell sc to recreate the GST. To load a GST into memory, specify the GST command as follows: gst gst-filename The gst utility loads the GST into memory and then exits. Note: You should do this only if you plan to remove the disk containing the GST from the drive. To display information about a symbol contained in a GS 1', specify the gst command as follows: gst gst-filename symbol-name Some symbols may occur more than once in the GST. For example, a symbol may occur once as a structure tag and again as an identifier. The gst utility prints all definitions of the same symbol. gst supports the following options: list lists all GSTs currently in memory. You can use this option to determine which GSTs to unload if you need more memory. 238 Chapter 10 gst Manages global symbol tables (continued) [name=]filename specifies a GST file created using the makegst option in the sc command. You do not need to specify name= unless you want to load a GST that has the same name as a keyword (for example, name = symbol ). [symbol=]symbol-name displays the type of symbol name and the filename and line number where symbol-name is defined. The type may be one of the following: tag struct, union, or enum name identifier variable or function name typedef typedef include #include filename preprocessor preprocessor macro or #define You do not need to specify symbol= unless you want information about a symbol that has the same name as a keyword (name, unload, and so on). unload forces a GST to be unloaded from memory. If you also specify symbol names on the command line, gst prints all definitions for those symbols before it unloads the GST. verbose prints the full definition of symbol-name. Examples To load the GST named pro ject.gst, enter the following command: gst project.gst The gst utility loads the GST into memory and then exits. If the header file intuition/intuition.h is included in pro ject.gst, you can display the definition of the Window structure as follows: gst project.gst Window 239 Utility Reference gst Manages global symbol tables (continued) If project.gst is not already loaded into memory, gst loads project.gst. After project.gst is loaded into memory, gst queries the GST and displays the following information: intuition/intuition.h 904 defines "Window" (struct) To display additional information, enter the following command: gst verbose project.gst Window gst also displays the contents of the Window structure with offsets for each member. Error Messages gst may generate the following error messages: No GST file specified indicates that you did not specify a GST filename. Can't find GST file "filename" indicates that gst cannot find the file specified. Symbol "symbol-name" not found indicates that gst could not find the specified symbol. Not enough memory to load GST indicates that the GST file could not be loaded due to insufficient memory. 240 Chapter 10 hypergst Displays the contents of GSTs Synopsis hypergst [gst-filename] Description The hypergst utility enables you to browse the definitions of symbols and data structures in GSTs (Global Symbol Tables) that are loaded into memory. The hypergst utility works with the AmigaGuide hypertext system. For information on using AmigaGuide, see Chapter 3, "Getting Help," in SAS/C Development System User's Guide, Volume I: Introduction, Editor, Compiler. To browse the definitions in a GST, the GST must be loaded in memory. You can invoke the hypergst utility and load a GST in one of the following two ways: [] You can enter the hypergst command followed by the name of the GST file that you want to browse. [] From the Workbench you can click on the HyperGST icon, then hold down the Shift key and double-click on the icon for the GST file that you want to browse. If the GST that you want to browse is already loaded into memory, you can invoke hypergst in one of the following two ways: [] You can enter the hypergst command without specifying a GST filename. The hypergst utility displays a screen listing the names of all GSTs in memory. To select a specific GST, click on the name of that GST file. [] You can double-click on the HyperGST icon. The hypergst utility displays a screen listing the names of all GSTs in memory. To select a specific GST, click on the name of that GST file. After the GST is loaded, hypergst displays a screen containing buttons for the various kinds of symbols defined in the GST. These buttons are as follows: Data Items displays external data items declared in header files in the GST such as DOSBase. Prototypes displays prototypes for functions including system functions and functions declared in your OWII header files. Typedefs displays custom data types defined with a typedef statement either in system header files or in your own header files. 241 Utility Reference hypergst Displays the contents of GSTs (continued) Structs/Unions/Enums displays structure, union, and enumerated type definitions. Preprocessor Symbols displays preprocessor macros defined in any header file including macros with arguments and simple substitution macros. If you click on one of these buttons, hypergst displays an alphabetical list of all symbols of that type in the GST. If you click on the name of a symbol, hypergst displays a symbol information screen for that symbol. This screen may contain other buttons that reference header files, structure tags, type definitions, and so on. You can click on any of these buttons to display more information about the highlighted item. Error Message hypergst may generate the following error message: No GST files in memory indicates that you have not loaded any GST files into memory. For example, you see this message if you invoke hypergst immediately following a reboot and do not specify any arguments. 242 Chapter 10 lprof Generates run-time statistics Synopsis lprof [-t=n] [>prog-output-dest] program [program-options] Description The lprof utility generates run-time statistics for a program. lprof records the amount of time spent in each routine that is called as your program runs. The lstat utility produces a report using the information compiled by lprof. This report will help you identify modules that run slowly or inefficiently. To use lprof with your program, you must compile your program with the debug option. lprof gathers statistics by determining, at regular intervals, what instruction your program is executing. The default interval is 33 milliseconds. You can change this interval by specifying a new interval (n) in milliseconds with the -t option as follows: lprof -t=n program You can redirect your program's output by specifying a greater than (>) sign followed by a destination. program is the name of the executable that you want to run. If program is not in the current directory, you must specify the full pathname. You can specify options for your program. After lprof loads your program, it runs the program and gathers statistics by examining the current program counter at given intervals. lprof writes your program's statistics to the file named prof . out in the current directory. You can use the lstat utility to produce a report from those statistics. Examples To gather statistics on a simple program named myprog that does not take any arguments, enter the following command: lprof myprog For a program that normally takes command-line arguments, you can add them after the program name, as follows: lprof myprog -opt 1 -flag If you want to redirect the program's output to a file named outfile, enter the following command: lprof >oUtfile myprog -opt 1 -flag 243 Utility Reference lprof Generates run-time statistics (continued) If the program is not in the current directory, you must give the full pathname, as follows: lprof >outfile C:myprog -opt 1 -flag 244 Chapter 10 lstat Analyzes and prints run-time statistics Synopsis lstat [>destination] [options] program [profile] Description The lstat utility analyzes the profile statistics file created by lprof. lprof runs the program, gathers statistics by examining the current program counter at given intervals, and writes this information to the file named prof . out in your current directory. lstat analyzes the information in this file and displays a report on the screen. You can redirect the output from lstat by specifying a greater than (>) sign followed by the destination where you want the output sent. You may want to redirect the output to a file and print that file. The profile is the name of the output file created by lprof. lstat first looks in your current directory for the default file produced by lprof, prof.out. If this file is not in your current directory, or if you have changed its name, you must specify its full pathname as the value for profile. You must specify the program name. lstat uses this name to get debugging and symbol information for its report. Note: This utility assumes that you have compiled the program with the debug compiler option. The debug option allows lstat to associate code with a specific line. If you do not compile with the debug option, lstat reports statistics based on subroutines only. lstat supports the following options: -z tells lstat to display statistics for all subroutines even if they were not encountered in profiling. By default, lstat does not report subroutines that it does not encounter. -f tells lstat to display full statistics for each subroutine, indicating the line numbers within a module that it encountered. By default, lstat displays only summary information about the subroutine. -t=n tells lstat to display only those routines that have at least n hits. By default, lstat prints all subroutines that it encountered even once. If the report produced by lstat shows that a large percentage of time is spent in one program module, you may want to [] redesign the module [] incorporate the module into the calling routines, thus eliminating calling overhead [] rewrite the routine in assembly language [] restructure your program. 245 Utility Reference lstat Analyzes and prints run-time statistics (continued) You also may find that most of the work being done involves the routine in question, and the percentage of time taken is reasonable. Examples These examples assume that you have the file named pro f . out in your current directory and that prof . out was produced with the following command: lprof testprog To display the basic statistics about your program, enter the command lstat testprog as follows: 1> lstat testprog header size 0x1c, ProfileHeader 0x1c 719 run + 158 ready + 77 wait = 954 75.367% run, 16.562% ready, 8.071% wait 8.067% samples (58) oUt of profile range counted = 660, RUN - NonTable 661 Routine % Total % Offset Hits Label 59.5455% 59.5455% lc44c 393 getrsc 8.9394% 68.4848% lc6fa 59 frersc 3.6364% 72.1212% 10d38 24 alcmem [lines 64-102 in mem.c] Most hits-1.2121% (8) on line 80 2.2727% 74.3939% 18252 15 instal [lines 117-146 in sym.cj Most hits-1.2121% (8) on line 132 0.l5l5% l00.0000% 1ca18 1 CXM22 You can display information about subroutines that lprof did not encounter by using the -z option. In this example, using this option produces information about the strcat and strncpy routines. These routines have O hits and account for 0% of the runtime, but IIOW appear in the output, as in the following: 1> lstat -z testprog 246 Chapter 10 lstat Analyzes and prints run-time statistics (continued) header size 0xlc, ProfileHeader 0xlc 719 run + 158 ready + 77 wait = 954 75.367% run, 16.562% ready, 8.071% wait 8.067% samples (58) out of profile range counted = 660, RUN - NonTable 661 Routine % Total % Offset Hits Label 59.5455% 59.5455% lc44c 393 getrsc 8.9394% 68.4848% lc6fa 59 frersc 3.6364% 72.1212% 10d38 24 alcmem llines 64-102 in mem.cl Most hits-1.2121% (8) on line 80 2.2727% 74.3939% 18252 15 instal llines 117-146 in sym.cl Most hits-1.2121% (8) on line 132 ... 0.0000% 100.0000% lca60 0 strcat 0.0000% 100.0000% lca78 0 strncpy For each routine that has line number information, you can display more detailed line number information by specifying the - f option. The -f option tells lstat to display the percentage of total runtime and number of hits for each line that was executed in that routine, as in the following: 1> lstat -f testprog header size 0xlc, ProfileHeader 0xlc 719 run + 158 ready + 77 wait = 954 75.367% rUn, 16.562% ready, 8.071% wait 8.067% samples (58) oUt of profile range counted = 660, RUN - NonTable 661 247 Utility Reference Istat Analyzes and prints run-time statistics (continued) Routine % Total % Offset Hits Label 59.5455% 59.5455% lc44c 393 getrsc 8.9394% 68.4848% lc6fa 59 frersc 3.6364% 72.1212% lOd38 24 alcmem llines 64-102 in mem.~] 0.3030% (2) on line 64 1.0606% (7) on line 68 0.7576% (5) on line 69 1.2121% (8) on line 80 0.3030% (2) on line 90 2.2727% 74.3939% 18252 15 instal [lines 117-146 in sym.c] 0.1515% (1) on line 117 0.1515% (1) on line 129 0.4545% (3) on line 131 1.2121% (8) on line 132 0.1515% (1) on line 133 0.1515% (1) on line 138 ... 0.1515% 100.0000% lcal8 1 CXM22 For a large program, you may want to limit the amount of information produced by lstat by using the -t option. You can use the -t option to set a minimum number of hits that must be recorded for a subroutine before that subroutine will be included in the display. With this option, the final total percentage may not be 100%. Here is an example: 1> lstat -f -t=2 testprog header size 0xlc, ProfileHeader 0xlc 719 run + 158 ready + 77 wait = 954 75.367% run, 16.562% ready, 8.071% wait 8.067% samples (58) out of profile range counted = 660, RUN - NonTable 661 248 Chapter 10 lstat Analyzes and prints run-time statistics (continued) Routine % Total % Offset Hits Label 59.5455% 59.545s% lc44c 393 getrsc 8.9394% 68.4848% lc6fa 59 frersc 3.6364% 72.1212% 10d38 24 alcmem [lines 64-102 in mem.c] 0.3030% (2) on line 64 1.0606% (7) on line 68 0.7576% (5) on line 69 1.2121% (8) on line 80 0.3030% (2) on line 90 2.2727% 74.3939% 18252 15 instal [lines 117-146 in sym.c] 0.1515% (1) on line 117 0.1515% (1) on line 129 0.4545% (3) on line 131 1.2121% (8) on line 132 0.1515% (1) on line 133 0.1515% (l) on line 138 ... 0.3030% 98.3333% lca00 2 xcovf 249 Utility Reference omd Disassembles object modules Synopsis omd [r>destination] [-x] object [source] Description The omd (Object Module Disassembler) utility program disassembles an object file produced by the SAS/C Compiler and produces a listing consisting of assembly language statements (interspersed with the original C source code if you specified a source filename). omd sends the output to the screen unless you redirect it by entering a greater than (>) sign followed by a destination. You rnay want to send the output to a file and then print the file. The -x option sets the size of the buffer used to hold the external symbol section of the object module. For example, -x250 establishes a buffer that can hold 250 external symbols. The default size is 200. You should increase the buffer size only if omd reports that there are too many external symbols. object is the object filename. You must specify the complete filename, including the .o extension. source is the source filename. If you specify source, you must specify the complete source filename, and the source file should have been compiled with the debug compiler option. The debug option allows omd to associate source lines with the object code they generated. If you did not use the debug option, C source lines will not appear in the output produced by omd. Examples The following example compiles myprog.c to produce myprog.o, which is then disassembled with omd. The disassembled listing is redirected to the file named myprog. 1st. sc debUg=line myprog omd >myprog.lst myprog.o myprog.c 250 Chapter 10 oml Manages libraries Synopsis oml [listfile] [options] libfile [command [module...]]... Description You can use the oml (Object Module Librarian) to manage your libraries. oml allows you to: [] create library files [] list the modules in a library file [] delete modules from a library file [] replace old modules with new modules. A link library is a group of object modules, each of which was originally in a separate file and consisted of one or more subroutines. Some advantages of using a link library are as follows: [] The subroutines in a library can be used by several programs. [] When you are linking your program, you specify only the library file instead of several individual object modules. [] The linker includes only those modules in the library that are required by your program. Each module within the library is identified by a module name, which is placed in the object module by the program (the SAS/C Assembler or Compiler) that generates the module. The assembler and compiler use the name of the object file. If a module does not contain a module name, oml assigns a module name of the form $nnn, where nnn is a decimal number. A module may define one or more public symbols. A public symbol is something in the module that is available to other modules, such as global variables or functions. When the linker resolves external references for a program, it examines each module in each library you specify. It decides which of the modules are required by the program it is linking by looking at the module's list of public symbols. If any of the program's unresolved external references match any of the module's public symbols, that module will be included in the executable module. When writing the modules for your library, be careful to avoid duplicate names for public symbols. If you create a library that defines a symbol more than once, oml issues a warning message. If you then link with that library without correcting the problem, the linker may include the wrong module or give a duplicate symbol error. To invoke oml, enter the oml command followed by a library name, as follows: oml mylib.lib 251 Utility Reference oml Manages libraries (continued) oml waits for you to enter commands (and module names, if necessary) from the keyboard.oml executes the commands as you enter them and displays a list of any duplicate symbol names that it finds. After you have entered all your commands, enter a Control backslash (Control-\) to terminate the oml. You also can include the commands and module names on the oml command line. If you enter commands on the command line, oml executes those commands and terminates. For example, the following command replaces the module ftoc.o in my lib.lib with the version of the same module in your current directory: oml mylib.lib r ftoc.o oml replaces the module, lists any duplicate symbol names it finds, and terminates. You also can enter some commands on the command line followed by some from the keyboard. If you include an at (@) sign at the end of the command line, oml executes the commands you enter on the command line and then waits for you to enter additional commands from the keyboard. You must enter a Control-\ to terminate oml. For example, the following command replaces the module ftoc.o in mylib.lib with the version of the same module in your current directory and then waits for you to enter additional commands from the keyboard: oml mylib.lib r ftoc.o @ You also can enter the commands into a file and tell oml to use that file as input. You can tell oml to use that file by either of the following methods: [] entering a less than (<) sign followed by the filename () sign followed by a filename. 252 Chapter 10 oml Manages libraries (continued) Specifying Com mands Commands specify the actions to be performed by oml with respect to the specified library file. Each command is specified as a single character, usually followed by a list of module names or object filenames. Separate commands and file and module names with one or more spaces. If you specify the r, d, or x command, oml assumes that the next item on the command line is a file or module name, so that item is not checked to determine if it is another command. If you need to enter a file or module name that may appear to oml to be a command, specify that file or module name as the first name following the command. oml supports the following commands: r file file . . . replaces the named object files in the library or adds them to the library, if they are not already present. Each module should be in a separate object file. To replace modules within a library, make sure that the module contains a module name and that the filename is the same as the module name. d module module . . . deletes the named modules from the library. oml assigns module names to those modules without names; therefore, you may need to get a listing of names in the library (using the 1 command) to determine the name of the module that you want to delete. x module module . . . extracts the named modules from the library and creates separate files using the same names. You may need to get a listing of names in the library (using the l command) to determine the correct name of the module that you want to extract. If the module name contains a pathname, oml attempts to create a file with that name. If the module name does not contain a pathname, oml creates the file in the current directory unless you specify a different pathname with the -o option. You can use an asterisk (*) to specify that you want all modules extracted. oml terminates if it cannot extract a module. You cannot extract and replace the same module with the same oml command line. l generates a listing of the modules in the library after all other commands have been executed. If you also specify the -s option, the listing includes the public symbols defined in each module. 253 Utility Reference oml Manages libraries (continued) @[filename] tells oml to execute the commands that you enter from stdin (usually defined as the keyboard) or from the filename, if specified. If you include this option it should be the last option on the command line. If you specify the r or d command, oml creates a temporary file in which it builds the new version of the library. After oml builds the new version, if it does not detect any errors, it deletes the original library file (if it existed) and renames the temporary file. Therefore, the original library file is not affected if an error occurs. Specifying Options oml supports the following options: -b tells oml not to issue prompts, including prompts for missing information. -n strips debugging information from modules before adding them to the library. -oprefix specifies a prefix for the filenames to be created by the x command. If the prefix includes a directory name, you must include the forward slash (/) at the end of the name. -s includes, in the listing produced by the l command, a list of the public symbols defined in the module. -tpathname specifies a path for the temporary library. -v tells oml to display messages as it adds or deletes modules to and from the library. -x generates a cross reference for variables and functions used in a library. oml produces warning messages if either of the following are true: [] A module that you want to delete or extract is not in the library. [] Any module in the library includes a second definition for a public symbol. 254 Chapter 10 oml Manages libraries (continued) Examples Since a single object file is essentially a library of one module, you can use oml to find out what module name is included in the object file, as follows: oml name.o l To build a new library, you can create a list of the filenames of the object modules that you want to include in the library and then create the library using the following command: oml new.lib r @name.lst The following command extracts all of the modules in the library cfuncs.lib and creates a file for each module in the directory :object/: oml -o:object/cfuncs.lib x * Note: This command will succeed only if the module names in the library do not contain pathnames. The following command deletes the module tribe.o from the library cfuncs.lib: oml cfuncs.lib d tribe.o The following command lists the modules and symbols in the library test.lib: oml -s test.lib l You can save this listing in a file named test.lst by adding the greater than (>) sign followed by the filename: oml >test.lst -s test.lib l 255 Utility Reference scmsg Searches for and corrects errors and warnings Synopsis scmsg [options] Description The semsg utility helps you find and fix errors and warnings in your code. It acts as a filter between you and the compiler, allowing you to invoke the editor of your choice and go to the line causing the error or warning quickly and easily. You can use semsg with the editor of your choice, using AREXX as a communication medium. AREXX is a standard part of AmigaDOS 2.0 and can be purchased as a third-party product for use under AmigaDOS 1.3. If you do not have AREXX, you still can use semsg to control the se editor provided as part of the SAS/C Development System, but you will not be able to program the editor keys to control scmsg. If you invoke the compiler from the Shell or by using the Build icon on the Workbench, semsg is automatically invoked for you. You can specify the following options in the semsg command: autoedit specifies that you want semsg to invoke your editor automatically, open the source file, and display the line producing the message. The default value is noautoedit. config=filename specifies the name of a configuration file. Typically, the configuration file contains the command necessary to invoke your editor, open a source file, and display the appropriate line. For more information about configuration files, see "Using AREXX to Invoke Your Editor," later in this section. hidden specifies that you do not want semsg to display the message browser window until the compiler returns a message. The default value is noh i dden. To redisplay the message browser window, you can enter semsg nohidden at the Shell prompt or send the AREXX show command to the sC_ SCMSG AREXX port. For example, you can use the following AREXX script to send the show command: /* AREXX script to send the SHOW command */ ADDRESS 'SC_SCMSG' 'SHOW' quit terminates scmsg. 256 Chapter 10 scmsg Searches for and corrects errors and warnings (continued) rexxonly specifies that scmsg should not open a window. Use this option if you intend to query scmsg for the messages from your editor or some other AREXX-supporting program, and you do not want to see the scmsg window. Unless you specify hidden or rexxonly, scmsg opens a window on the Workbench screen. This window contains the first error or warning message from the compilation. As additional messages are produced, they are appended to the end of the list. These additional messages may be produced in the same or a different source file. The current message is always highlighted. You can move from message to message by clicking on the message or by using the arrow keys. The scroll bar on the right side of the window allows you to move around in the list. Double-clicking on a message invokes the editor at the file and line number specified in the message. The scmsg window lists all messages in the following format: primary: class msgno in secondary line lineno: text where: primary is the C source file being compiled. class is either Error or Warning. msgno is the message number. secondary is the name of the file in which the error or warning occurred. This file may be the same file as the primary file, or it may be a header file included by the primary file using the #include statement. lineno is the line number in the secondary file. text is the message text. The message text may specify an alternate file for a message. If a message describes a conflict between two different places in your code, the alternate file gives the location of one of them. The secondary file gives the location of the other. If an 257 Utility Reference scmsg Searches for and corrects errors and warnings (continued) alternate file is available for the message, the text contains the words See line num file filename. Every time a C source file is compiled, all old messages listing that file as the primary file are deleted from the scmsg window. The following sections describe the options available from the Project and Edit menus on the scmsg screen. Many of these menu items have menu acce1erator keys that allow you to perform the specified action without selecting the menu item. To use a menu accelerator key, hold down the right Amiga key (just to the right of the spacebar) and press the specified key. The Project Menu The Project menu allows you to control your message session. The following list describes each option on the Project menu and, where applicable, gives the menu accelerator key equivalent. Set Options sets scmsg options that specify which editor you want to use and any options for that editor. These options are typically saved in the file ENV: sc/scmsg. The options available are as follows: editcommand is the Shell command necessary to start your editor. Use the % f sequence to indicate where the filename should be in the command. If this option is left blank, scmsg does not attempt to invoke your editor, and all the other options are ignored. If this option is left blank but a portname is specified, scmsg sends AREXX commands to the port, if it exists. gotofile specifies the AREXX commaIld template needed to open a file. Use the %f sequence to indicate where the filename should be in the command. Once the filenaIlle has been substituted, this command is sent to your editor's AREXX port when a new file needs to be opened. If this option is left blank, scmsg always uses the editcommand to invoke your editor each time there is an error. 258 Chapter 10 scmsg Searches for and corrects errors and warnings (continued) gotoline specifies the AREXX command template needed to go to a specific line. Use the %1 sequence to indicate where the line number should be in the command. Once the line number has been substituted, this command is sent to your editor's AREXX port when scmsg needs to go to a new line. If this option is left blank, scmsg does not attempt to move to the proper line number in the file. hidden specifies that scmsg should not open a window. Use this option if you intend to query scmsg for the messages from your editor or some other AREXX-supporting program and you do not want to see the scmsg window. This option does not take any arguments. portname specifies the name of your editor's AREXX port. If this option is left blank, but editcommand is specified, scmsg assumes that your editor does not support AREXX. The scmsg utility issues the editcommand option but does not attempt to send any AREXX commands to your editor. wait specifies that scmsg should not open a window until one or more new compiler messages are available. This option does not take any arguments. Use saves the current options to ENV:sc/scmsg. Save saves the current options in ENV:sc/scmsg and ENVARC:sc/scmsg. The left, top, width, and height options are set to the current window's values. Save As . . . allows you to save your current options to a specified filename. You will be prompted for the filename. Restore reads the option settings from ENV:sc/scmsg into memory. Restore from . . . reads the options settings from a specified filename. The scmsg utility prompts you to enter the filename. 259 Utility Reference scmsg Searches for and corrects errors and warnings (continued) Reset to SAS/C defaults resets all options to the default values provided by the SAS/C Development System. Refer to Chapter 8, ''Compiling and Linking Your Program," in SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor. These defaults are suitable for use with se. Hide Window closes the scmsg window until the compiler produces another message. To redisplay the message browser window, you can enter scmsg nohidden at the Shell prompt or send the AREXX show command to the SC_SCMSG AREXX port. For example, you can use the following AREXX script to send the show commalld: /* AREXX script to send the SHOW command */ ADDRESS 'SC_SCMSG' 'SHOW' Quit terminates scmsg. The Build Menu You can use the Build menu to terminate any current builds or start new builds. The following list describes each option on the Build menu and, where applicable, gives the menu accelerator key equivalent. Abort Build terminates any current builds that are active. You may want to select this option if, for example, an error in a common header file is producing too many warnings or errors. The menu accelerator key for this command is Right-Amiga-A. Build Project starts a new build. The smake utility is invoked from the directory specified in the ENV: sc/pro jdir environrnent variable. This variable is automatically set for you each time you submit a smake command or click on the Build icon from Workbench. If unset, the current directory is used. The menu accelerator key for this command is Right-Amiga-B. Any build that is currently running is aborted before the new build is submitted. 260 Chapter 10 scmsg Searches for and corrects errors and warnings (continued) The Edit Menu You can use the Edit menu to perform certain actions on the current (highlighted) message. The following list describes each option on the Edit menu and, where applicable, gives the menu accelerator key equivalent. Go to Error invokes the editor on the file and line number that produced the message. You can perform the same action by double-clicking on the message or by pressing the Return key. Go to Alternate invokes the editor on the alternate file and line. This option is valid for messages that have an alternate file and line number specified in the form See line num file filename. You also can edit the alternate file by holding down either Alt key and double-clicking on the message or by holding down either Alt key and pressing the Return key. Delete Message removes the highlighted message from the list. The menu accelerator key is Right-Amiga-D. Clear removes all messages from the list. The menu accelerator key is Right-Amiga-C. Delete by . . . displays a submenu that allows you to delete all messages that meet specific criteria. The options on the submenu are as follows: Message Number deletes all messages with the same message number as the current message. The menu accelerator key is Right-Amiga-N. File deletes all messages produced by the same secondary file, regardless of the primary file. The menu accelerator key is Right- Amiga-F. Compilation deletes all messages produced by the same primary file. The menu accelerator key is Right-Amiga-P. 261 Utility Reference scmsg Searches for and corrects errors and warnings (continued) Using AREXX to Invoke Your Editor When scmsg wants to communicate with your editor, it issues an AREXX command based on the templates you provide with the Set Options submenu and the information from the highlighted message. It uses the template in the appropriate option as a base and performs substitutions on it. All templates start with a percent (%) sign. The following substitutions are performed: Template Substitution %% percent (%) sign %n newline character %f filename %l line number %c column number %xhh hexadecimal character specified by hh %r carriage return scmsg ignores any other sequence of a percent (%) sign followed by a character. If scmsg finds the AREXX port described in your options file, it sends the openf ile AREXX sequence provided to the port to tell your editor to open the necessary file. If scmsg cannot locate the AREXX port described in your options file, it attempts to invoke your editor on the appropriate file using the specified editcommand Shell command. If successful, it goes to the appropriate line using the AREXX command template. The following values are typical of what might be found in a configuration file created for se by the Set Options submenu under the Project menu: editcommand SC:C/SE Shell command to invoke SE portname SC_SE Name of the editor's REXX port 262 Chapter 10 scmsg Searches for and corrects errors and warnings (continued) gotofile OW "%f"%r Open specified file gotoline LL "%1"%r Go to line number %1. Configuration files and example AREXX scripts for several popular editors have been included with the SAS/C Development System in the sc:extras/scmsg drawer. Check that drawer to see if support for your editor has been provided. Using ehe SC_SCMSG AREXX Port You can also use the built-in AREXX port iII scmsg to get information on the messages remotely from your editor or from any other program that supports AREXX. The port's name (for use with the AREXX address command) is SC_SCMSG. The following commands are supported: abort aborts any builds currently running. altfile returns the alternate filename (if any). An empty string indicates that there are no messages on the list or that the current message has no alternate file. altline returns the alternate line number (if any). An empty string indicates that there are no messages on the list or that the current message has no alternate file. bottom goes to the last message in the list. build submits a new build of the last project built. Any build that is currently running is aborted before the new build is submitted. class returns either error or warning, depending on the current message. clear deletes all messages. delcomp [filename] deletes all messages with the specified filename as their primary filename. If no filename is specified, the primary filename of the 263 Utility Reference scmsg Searches for and corrects errors and warnings (continued) current message is used. If the current message is deleted, the next non-deleted message becomes current. delete deletes the current message and goes to the next message in the list. delfile [filename] deletes all messages with the specified filename as their secondary filename. If no filename is specified, the secondary filename of the current message is used. If the current message is deleted, the next non-deleted message becomes current. delnum[msgno] deletes all messages with the specified message number. If no message number is specified, the number of the current message is used. If the current message is deleted, the next non-deleted message becomes current. errnum returns the error number. An empty string indicates that there are no messages on the list. file returns the filename for the current message. An empty string indicates there are no messages on the list. hide closes the scmsg window, but keeps scmsg running. If you specify wait, the scmsg window reappears when a new message is issued from the compiler. Otherwise, you must send a show command with REXX or reinvoke scmsg from the command line to redisplay the window. line returns the line number for the current message. An empty string indicates there are no messages on the list. next goes to the next message in the list. If the current message is the last in the list, scmsg goes to the first message in the list. prev goes to the previous message in the list. If the current message is the first in the list, scmsg goes to the last message in the list. quit terminates scmsg. 264 Chapter 10 scmsg Searches for and corrects errors and warnings (continued) rexxonly specifies that scmsg should close the message browser window and not reopen it unless you specify scmsg nohidden at the Shell prompt or send the ARGXX show command to the sc_ SCMSG ARGXX port. Use this command if you intend to query scmsg for the messages from your editor or some other AR~XX supporting program, and you do not want to see the scmsg window. select selects the current message for editing. Your editor is invoked and moved to the proper file and line number. This command is equivalent to pressing the Return key on the current message. show[activate] pops the scmsg window to the front or redisplays the window if it is hidden. If you specify activate, the scmsg window becomes the active window, and you can enter keyboard commands to scmsg. text returns the message text. An empty string indicates that there are no messages on the list. top goes to the first message in the list. Examples The following AREXX script, when invoked from se, opens the file containing the current message, moves to the appropriate line number, and displays the message on the editor message line: /* AREXX script to move to next error */ address 'SC_SCMSG' /* Set Up to talk to scmsg */ Idelete' /* Delete the current error, move to next */ options results /* Tell AREXX we want the return values */ /* of issued AREXX commands */ 'file' /* Get the new filename */ file = result 'line' /* Get the new line nUmber */ line = result 265 Utility Reference scmsg Searches for and corrects errors and warnings (continued) 'text' /* Get the new message text */ text = result options /* Don't care about results any more */ address 'SC_SE' /* Now talk to the editor */ if file = "" then 'DMNo more errors' /* Display Message "No more errors" */ else do 'OW UC' || file || "0d"x /* Open Window "file" */ 'LL UC' || line || "0d"x /* Go to line "line" */ 'DM' || text /* Display Message "text" */ end 266 Chapter 10 scopts Sets compiler options Synopsis scopts [options] Description The scopts utility allows you to set compiler options for a project by clicking on the gadget that corresponds to the option. The options you specify are used by the sc command whenever you compile and link your files. To run scopts, you can double-click on the SCoptions icon, or you can enter scopts on the Shell command line. scopts displays the SAS/C Compiler Options Index window. This window contains buttons that open additional windows. Each of these windows allows you to set different compiler options. In all, scopts can display nine windows: Compiler Options Index allows you to do the following: [] set certain options such as list, xref, link, and map [] specify the name of the final executable module [] display additional windows such as the Optimizer Options window and the Link Options windows [] save your option settings to a file named scoptions in the current directory [] save your option settings in ENV:sc/scoptions. Compiler Options contains gadgets for miscellaneous options such as debug, shortintegers, and stringmerge. Diagnostic Message Options contains gadgets for options, such as ansi, strict, and errorrexx, that affect which messages are generated by the compiler and linker and how those messages are handled. Code Generation Options contains gadgets for options, such as data, code, and cpu, that affect the code generated by the compiler. Listing/Cross-Reference Options contains gadgets for options, such as listnarrow, errorlisting, and xrefsystem, that affect the content and formatting of any listing or cross-reference files generated. Optimizer Options contains gadgets for options, such as optpeep, optsize, and optalias, that affect the performance of the optimizer. 267 Utility Reference scopts Sets compiler options (continued) Prototype Generation Options contains gadgets for options, such as genprotoexterns, genprotoparms, and genprototypedef s, that affect how prototypes are generated. Linker Options contains gadgets for options, such as smallcode, stripdebug, and batch, that are passed to the linker when the linker is invoked by sc. These options are not used by the compiler. Map Options contains gadgets for options, such as maphunk, mapxref, and mapoverlay, that affect the content of the map file. For a brief description of an option, move the cursor to the option gadget and press the Help key. For a complete description of any compiler option, refer to Chapter 8, "Compiling and Linking Your Program," in User's Guide, Volume I. These windows may contain one or more of the following basic types of gadgets: cycles appear as raised buttons with a cycle symbol on the left side. By clicking on the gadget with the left mouse button, you can cycle through the setting available for that option. To reverse the direction of the cycle, press the Shift key as you click the mouse button. actions appear as raised buttons. Selecting the button causes an immediate action to occur. For example, selecting the Compiler Options. . . gadget displays the Compiler Options window. strings appear as a raised ridge around a text area. You can enter data in the area by clicking within the text area and typing. When you have finished typing, press the Return key. lists appear as a set of control gadgets (a scroll bar, arrow gadgets, a string area, and ADD and DEL buttons) combined with a raised scrolling area. Use the scroll bar and arrow gadgets to position the scrolling area on specific items. To add new items to the list, select the ADD button, type the new item name, and press the Return key. To remove 268 Chapter 10 scopts Sets compiler options (continued) an item from the list, click on the item (to copy it to the string area), and select the DEL button. To modify an item, click on the item (to copy it), and enter any corrections. To specify an option for which the scopts utility does not have a gadget, enter the option and any parameters required by the option into the SPECIAL gadget. You can enter as many additional options as you like. If you use the SPECIAL gadget to specify an option for which scopts already has a gadget, the next time you invoke scopts, the gadget for that option is selected, and the option is no longer included in the SPECIAL gadget. The only options remaining in the SPECIAL gadget are those for which scopts does not have a gadget. For example, if you enter link into the SPECIAL gadget, the next time you invoke scopts, the link gadget is selected, and the SPECIAL gadget does not contain the link option. Any values you enter into the SPECIAL gadget are processed after all other gadgets are processed. Therefore, options you enter into the SPECIAL gadget may override other options. To specify the name of your final executable module, specify a filename in the ProgramName gadget. To save your option settings, select one of the following options from the Project menu: Save to SCOPTIONS saves the settings to the file scoptions in the current directory. You also can click on the Save button in the SAS/C Compiler Options Index window to save the settings in scoptions. Save as global defaults (ENV:) saves the settings to the file ENV:/sc/scoptions. You also can click on the Save Default button in the SAS/C Compiler Options Index window to save the settings in ENV:. The option settings are also saved to ENVARC:, if it exists. Save as . . . asks you for the name of the file in which you want to save the settings. To use the options saved in a file other than scoptions or ENV: sc/scoptions, you can specify the filename using the with compiler option in the sc command. The options in the with file are read as if they were specified in the sc command at the position occupied by the with option. 269 Utility Reference scopts Sets compiler options (continued) To exit scopts without saving any of your changes, click on the Cancel button. When you run the sc command, it first looks for an scoptions file in your current directory. If this file does not exist, the sc command looks for the ENV:sc/scoptions file. The scoptions file is an ASCII file that contains the list of sc options that you specify. You can edit this file with a text editor and add any options you want. To load a previously saved options file or to reset all options to their default values, select one of the following options from the Project menu: Restore from SCOPTIONS reads the contents of the scoptions in the current directory into memory. Restore from global defaults (ENV:) reads the contents of ENV: sc/scoptions into memory. Restore from . . . asks you for the name of the file from which you want to read option settings into memory. Reset to SAS/C defaults resets all options to the default values provided by the SAS/C Development System. Refer to Chapter 8, "Compiling and Linking Your Program," in SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor. You also can change option settings by specifying the option Oll the scopts command line. For example, to set the math=standard and link options, you can enter the scopts command as follows: scopts math=standard link If you enter the scopts command followed by option settings, scopts does not display any windows, and you cannot choose the file into which the options are saved. Specifically, scopts performs the following tasks: 1. reads the scoptions file in your current directory, if it exists. If this file does not exist, scopts reads ENV: sc/scoptions. 2. adds or changes the options you specified. 270 Chapter 10 scopts Sets compiler options (continued) 3. saves the new option settings in the file scoptions in the current directory. 271 Utility Reference scsetup Sets up a new project Synopsis sc:scsetup [directory]. . Description The scsetup utility sets up a directory that you can use for C development. You can run scsetup on existing directories or use it to create new directories. scsetup creates an icon for the directory and copies into the directory icons for the most commonly used SAS/C Development System tools, such as smake and CodeProbe. You can add icons for any file extensions or tools that you want scsetup to copy in addition to the standard icons. Specifically, scsetup performs the following actions: 1. Creates the directory, if necessary. 2. Creates an icon file for the directory being set up, if it does not already have one. scsetup uses the file sc: starter_project . info as a template for directory icons. 3. Creates icons for the files in the directory, if necessary. Default icons are supplied for . c, . h, . a, and . smk files. These icons are in the sc: icons drawer under the name def_c.info, def_h.info, def_a.info, and def_smk.info. You can add any default icons needed for other extensions by copying an icon into sc:icons with the appropriate name (def_extension. info). 4. Creates an icon file for any subdirectories of the directory being set up, if they do not already have one. 5. Creates icons for the files in each subdirectory, if necessary. 6. Copies the contents of the directory sc: starter_project, if present, to the directory being set up. This starter directory contains a Build icon, a Debug icon, an Edit icon, and an SCoptions icon. You can place any other icons or programs in this starter directory that you want copied to directories set up with scsetup. scsetup will not overwrite any existing files or icons. You can run scsetup from the CLI or from the Workbench. To run scsetup from the CLI, enter the following command: sc:scsetup [directory] . . . If you do not specify a directory name, scsetup sets up the current directory. If you specify a directory that does not exist, scsetup creates the directory. To run scsetup from the Workbench and create a new project, double-click on the SCsetup icon, and type the name of the drawer when prompted. 272 Chapter 10 scsetup Sets up a new project (continued) To run scsetup from the Workbench and set up an existing drawer, click on the drawer icon. (Click on the actual drawer icon, not the file icons in the drawer.) To select additional drawers, hold down the Shift key and click on their icons. After you have selected all the drawers, hold down the Shift key and double-click on the SCsetup icon. After you have set up a directory, you can run the editor by double- clicking on the Edit icon, and you can run CodeProbe by double- clicking on the Debug icon. You can run smake by double-clicking on the Build icon. smake looks for a smakefile or a makefile. If none are present, it compiles and links all.c files in the directory using the options specified through the scopts utility, described earlier in this chapter. 273 Utility Reference smake Maintains and updates records of file dependencies Synopsis smake [options] [macro-definitions] [targets] Description The smake utility is a tool that you can use to maintain projects that are composed of many files. A file can be C source code, a data file for a graphics or audio, or perhaps a spreadsheet file. For example, you may have a project that consists of 50 files, and several programmers may be responsible for different files. To manage this project, you need to keep track of which files have been changed and which files must be compiled before other files (that is, which files are dependent on other files). You can use smake to keep track of file dependencies, recompile and relink any files that have been updated, and produce new product files. In other words, smake determines if any of the source files have changed since the last version of the product file was generated and, if so, generates a new product file. To use smake, you create a smakefile that identifies dependent files and target fi1es and describes the actions required to produce a new product. A basic description of these terms follows: target file is any file that is created or updated by smake. Producing this file may require creating or updating several intermediate files. dependent file is a file that must be created or updated before a target file can be updated. A dependent file can be a source code file, header file, or object code file. In other words, if a dependent file is changed (for example, by editing), then the target file must be rebuilt. actions are the commands necessary to update each dependent and target file. Actions can be calls to the compiler or linker or basic housekeeping commands. smakefile is a file that identifies every dependent file required to create the target file and describes every action required to update or create the dependent and target files. When you run smake, it re-creates only the first target file specified in the smakefile (unless you specify an alternate target as described in "Using Alternate Targets," later in this section) and, if necessary, any 274 Chapter 10 smake Maintains and updates records of file dependencies (continued) dependent files needed to re-create the target file. Specifically, smake performs the following actions: 1. Locates and identifies the target file. By default, smake remakes the first target file specified in the smakefile. You can specify an alternate target as described under "Using Alternate Targets," later in this section. 2. ensures that any file on which the target file depends already exists and is up to date. To determine when dependent files were last modified, smake looks at the time stamp of the file. A file is considered current if it has a time stamp later than that of any of its dependent files. Note: Before using smake, make sure that your system clock is accurate, using the date command if appropriate. An example of the date command under AmigaDOS follows: date 12-Aug-92 16:34:57 You must enter the time using 24-hour clock notation. Enter the month as a three-character field. 3. Re-creates the target file if any of the dependent files have been modified more recently than the target file. Creating the smakefile A smakefile has the following basic format: # This is a comment. target-file1: dependent-file1 dependent-file2... actions target-file2: dependent-file1 dependent-file2... actions . . . You can include comments in a smakefile by entering a pound (#) sign in the first column. smake will ignore the remainder of that line. All target file names must [] start in the first column [] be followed by a colon (:) [] be followed by the name of any dependencies of the target. 275 Utility Reference smake Maintains and updates records of file dependencies (continued) If there are too many dependent filenames to fit on one line, repeat the target name and colon on the next line, and enter the remaining dependent filenames. Immediately after the target-dependency line are any actions required to generate the target. Each of the action lines, if any, must be indented a minimum of one tab or space. To continue an action line onto additional lines, end each continued line with a backslash (\). You can have as many action lines as necessary for each target-dependency line. You can call smake from within a smakefile. You cannot issue the cd (change directory) command from within a smakefile. For example, suppose you have an executable file named myfile that you created by linking two object files, file1.o and file2.o . These object files are created by compiling the source files file1.c and file2.c, and each of these source files includes the header stdio.h. Figure 10.1 shows the relationships among these files. ---------- Figure 10.1 Executable File | myfile | Example File (primaryTarget) ---------- Dependencies / \ / \ Object Files ----------- ----------- (Dependents of Primary and | file1.o | | file2.o | Targets of Source Files) ----------- ----------- / \ / \ / \ / \ ----------- ----------- ----------- Source Files | file1.c | | stdio.h | | file2.c | (Dependents) ----------- ----------- ----------- If any information in stdio.h changes, you would have to recompile both source files and relink both object files to produce a new executable file. However, you can create a smakefile that contains all of the information necessary to recompile and relink these files and then run smake to recompile and relink as necessary. 276 Chapter 10 smake Maintains and updates records of file dependencies (continued) Your smakefile could look like this: 1 # Primary target is myfile 2 myfile: file1.o file2.o 3 slink FROM LIB:c.o+file1.o+file2.o TO myfile LIB \ 4 LIB:sc.lib+LIB:amiga.lib 5 6 file1.o: df1:source/file1.c stdio.h 7 sc data=absolute code=far dfl:source/file1.c 8 9 file2.o: df1:source/file2.c stdio.h 10 sc data=absolute code=far df1:source/file2.c Note: Do not enter line numbers in your smakefiles. Line numbers are included here for use in the discussion that follows. The first line is a comment line. The second line identifies the two dependent object files of the target file myfile. That is, it identifies the files that must be current before myf ile can be generated: file1.o and file2.o. Lines three and four give the commands (actions) necessary to produce myfil e. In this example, the only command necessary to produce myf ile is a call to the linker, slink. The sixth line identifies the files required to produce the object file file1.o. The two files are df1:source/file1 .c and stdio.h. Line seven gives the command necessary to produce the object file: a call to the compiler, sc. Lines nine and ten identify the dependent files and actions required to produce file2.o. Target-dependency and action lines are the primary components of a smakefile. However, smake provides many special features that you can use to make your smakefiles more powerful. These features include macros, transformation rules, local input files, fake targets, and more. The following sections describe all of the special features you can use in your smakefile. 277 Utility Reference smake Maintains and updates records of file dependencies (continued) Using Special Symbols You can use special symbols to override some of the default actions of smake. These special characters are as follows: - Normally, when an action generates an error, smake stops processing. If you want smake to continue processing when it encounters an error caused by a specific action, begin the action line with a minus (--) sign. If you want smake to continue processing after all errors, specify the command line option -k. @ Normally, smake displays all commands and messages generated by those commands on the screen as each command is executed. If you do not want a command to be echoed to the screen, begin the action line with the at (@) symbol. smake will still display any generated messages. If you do not want any commands echoed to the screen, specify the command line option - s. $ The dollar ($) sign is an escape symbol for the dollar sign itself. In other words, to enter a dollar sign in a filename, enter two dollar signs ($$). If you enter only one dollar sign, smake thinks that the dollar sign indicates the beginning of a macro. \ The backslash (\) symbol is an escape symbol for the pound (#) sign. Pound signs normally indicate the beginning of a comment. To use a pound sign in a command line, enter a backslash before the pound sign (\#). & The ampersand (&) symbol is provided for compatibility with other implementations of smake. The ampersand is ignored under AmigaDOS. Using Macros You can use macros to represent any character string, including AmigaDOS commands, directory specifications, header files, compiler or assembler flags, and constant strings. Macros are especially useful where long character strings are required. Within a smakefile, you can define a macro using the equals (=) sign as follows: macro-name = definition Make sure you define a macro before you attempt to use it. If you reference a macro that has not yet been defined, that macro will be expanded to an empty. 278 Chapter 10 smake Maintains and updates records of file dependencies (continued) Note: You purposely can define a macro to be the empty string by entering only the macro name and the equals (=) sign: macro-name = To refer to a macro within a smakefile, use the following format: $(macro-name) For example, you can define the macros source and f lags to represent the pathname of your source file and the compiler options you want to use to compile that file. Using these two macros, our earlier example now looks like the following: # Define macros for soUrce pathname and compiler options SOURCE = df1:source/ FLAGS = data=absolute code=far # Primary target is myfile myfile: file1.o file2.o slink FROM LIB:c.o+file1.o+file2.o TO myfile LIB \ LIB:sc.lib+LIB:amiga.lib file1.o: S(SOURCE)file1.c stdio.h sc $(FLAGS) S(SOURCE)file1.c file2.o: $(SOURCE)file2.c stdio.h sc $(FLAGS) $(SOURCE)file2.c Overriding a Macro Definition You can override the definition of a macro from the command line of smake by specifying the new definition as follows: macro-name = new-definition If you specify a macro definition on the smake command line, do not include spaces around the equals (=) sign. For example, you can redefine the debug macro as follows: smake -f editor debug=yes 279 Utility Reference smake Maintains and updates records of file dependencies (continued) Using Default Macros smake provides five default macros that are defined after a target- dependency line is processed and before the next action line is processed. Macro Definition $@ target filename $? list of dependent files, including the full directory pathnames, that are not current (that is, they have time stamps later than the target time stamps) $* name of the first dependent file, including the full directory pathname but excluding the filename extension $< name of the dependent file that caused the action, excluding the directory pathname but including the filename extension $> name of the dependent file that caused the action, excluding directory pathnames and filename extension For example, your smakefile could contain the following target- dependency line: obj/new/test.o: src/new/test.c hdr/test.h This line defines the source file as test.c located in the directory src/new and the header file test.h located in the directory hdr. If the source file test.c has a time stamp later than the target file test.o, then the default macros will have the following values: Macro Value S@ obj/new/test.o $? src/new/test.c $* src/new/test $ test 280 Chapter 10 smake M aintains and updates records of file dependencies (continued) Note: The value of each ofthese default macros changes after each target-dependency line is processed. Defining Transformation Rules You can use transformation rules with macros to tell smake how to make a file with a given filename extension from another file with a different filename extension. Transformation rules are most useful when you have several files with which you want to perform the same action. smake uses transformation rules if you do not specify explicitly the action required to create a certain target. For example, you can have a transform ation rule that tells smake how to create object files with extensions of .o from source files with extensions of .c. Ifthe only action required to produce the object file from the source file is a callto the co mpiler, your smakefile can contain the following transformation rule: .c.o: sc $* 281 Utility Reference smake Maintains and updates records of file dependencies (continued) Then, smake would compile source files (os.c and strbpl.c) without an action line for each source file that explicitly specified the call to the compiler: .c.o: sc $* obj/os.o: os.c obj/strbpl.o: strbpl.c Using Fake Targets Fake targets are a set of predefined targets that allow you to control the behavior of smake. smake does not remake fake targets. Fake targets allow you to set logical names, specify actions to be taken for certain conditions, and suppress certain messages. smake provides five fake targets: .DEFAULT .IGNORE .ONERROR .SET .SILENT The following list describes these targets in detail .DEFAULT specifies an individual action or a set of actions to be executed if [] there are no actions specified for a given target-dependency line [] there is no default transformation rule for the given target- dependency pair. The command line syntax used for the .DEFAULT target is as follows: .DEFAULT: action- 1 action-2 . . . action-n 282 Chapter 10 smake Maintains and updates records of file dependencies (continued) You can use .DEFAULT actions to display messages to the screen as smake is running. For example, your smakefile can consist of the following lines: .DEFAULT: ; this target needs remaking $@ alpha.cpp: alpha.clp If alpha.clp has a later time stamp than alpha.cpp, smake will print the following message to your screen: this target needs remaking alpha.cpp .IGNORE tells smake to ignore any error caused by the action lines. Specifying . IGNORE is equivalent to calling smake with the -i option. To specify . IGNORE, include the following line in your smakefile: .IGNORE: .ONERROR specifies an action or set of actions to be performed when smake detects an error. For example, you may want to delete certain temporary files or transfer them to a different directory if an error occurs. Specify the actions to be taken after the . ONERROR target: .ONERROR action-l action-2 . . . action-n .SET allows you to set the values of logical name assignments (as created by the assign command) from within a smakefile. When the logical name is set from within a smakefile, the logical name retains 283 Utility Reference smake Maintains and updates records of file dependencies (continued) the specified value and will be in effect for any secondary processes spawned from the main process. To specify . SET, use the following format: .SET: logical-name = value The value may be any character, including a space. However, the leading and trailing space characters are ignored. For example, you can redefine the logical name INCLUDE as follows: .SET: INCLUDE: = df0:sc/examples .SILENT tells smake not to echo the action lines to the standard output device before they are executed. Specifying . SILENT is equivalent to calling smake with the -s option. To specify . SILENT, include the following line in your smakefile: .SILENT: Using Multiple Targets If you have several target files that are dependent on the same dependent files, you can specify the target files together on the same target-dependency line. For example, if prog.c, my file.c, and newcode.c all included the header file stdio.h, you can use the following lines in your smakefile: prog.c myfile.c newcode.c: stdio.h sc $@ Using Alternate Targets Unless you specify an alternate target, smake remakes only the first target file specified in the smakefile and, if necessary, any dependent files needed to re-create the target file. However, your smakefile can contain target-dependency and actions lines for several targets. To tell 284 Chapter 10 smake Maintains and updates records of file dependencies (continued) smake to remake a target other than the first one specified in the smakefile, enter the name of the target on the smake command line: smake target-name For example, you can have the following smakefile that specifies two targets, clean and backup: clean: delete S(OBJ)files.o.Ds delete $(OBJ)os.o delete $(OBJ)strbpl.o backup: copy files.c to df1: copy os.c to df1: copy strbpl.c to df1: If you enter the smake command without specifying a target, smake runs the commands listed under clean. To run the commands listed under backup, you must use this command line: smake backup Using Local Input Files From within a smakefile, you can create a temporary disk file containing instructions that is passed to AmigaDOS when you run smake. Local input files are useful when you need to enter command lines that are too long to fit on one line. Any macros defined in the smakefile can be used within a local input file. Local input files are automatically deleted before smake terminates. You can construct a local input file with action lines as follows: command <[preface] <[!] [(filename)] statement1 statement2 . . . statementn 285 Utility Reference smake Maintains and updates records of file dependencies (continued) where: command is the command to be handed to AmigaDOS. preface is any text or symbol to be passed to AmigaDOS before the temporary filename. The preface may contain spaces. tells smake to create a local input file containing the statements you specify but not to pass the filename as part of the generated command line. filename is the name of the local file. If you do not specify a name, smake uses the temporary filename temp _ smake . tmp. If you specify a filename, enclose the filename in parentheses, and do not enter spaces before or after the filename. statementl-n are the statements that you want included in the local input file. The following example shows a smakefile that uses macros and a local input file to create the target grep. grep is a utility that is composed of C source files and one assembly language module, the startup module c.a. 1 # Generate an Updated version of GREP 2 3 # Define macros 4 SCHDRS = grep.h pat.h 5 OBJ = obj/ 6 FLAGS = IDIR=INCLUDE: IDIR=INCLUDE:sc/ OUT=$(08J) 7 SC = SC:sc 8 9 # Specify file dependencies for GREP executable, generate link 10 # command to be passed to AmigaDOS, then specify contents of 11 # WITH file . 12 grep: $(oBJ)grep.o $OBJ)c.o $(OBJ)-main.o $(OBJ)re_gen.o 13 grep: $(OBJ)re_match,c S(OBJ)os.o 14 slink destination] [options] pattern string file . . Description splat replaces all occurrences of pattern with string in each file that you specify. splat does not overwrite the original version of the file unless you specify the -o option. If you do not redirect the output by specifying a greater than (>) sign followed by a destination, splat places the changed file in either a temporary file or, if you use the -d option, in the specified directory. splat uses the same root filename with an extension of .$$$. You must use the rules recognized by grep for specifying the pattern and string. For example, to specify a string that contains spaces, you must enclose the string in double quotes. For additional information, see the description of the grep utility earlier in this chapter. splat supports the following options: -ddirectory specifies the directory where you want splat to place the new files. Using this option leaves the original versions untouched. If the specified directory does not exist, splat attempts to create it. If the attempt fails, splat displays an error message. The -o and -d options are mutually exclusive. -o tells splat to overwrite the original version of the file with the new version. The -o and -d options are mutually exclusive. -s displays the name of the file on which splat is currently working. It also displays a message saying that no substitutions have been performed if it was unable to find the specified pattern in the file. If you do not specify -s, splat performs its task silently. -v displays all lines in which substitutions are made, but it does not create new versions of the files. You can use this option to determine the changes that splat will make to your files. Examples For example, suppose you want to substitute INT for int in every declaration of an integer identifier in your C source files. The following command replaces int with INT in all files with the .headers and .source extensions in your current directory. It writes the new versions of these files in the directory named /backup. splat -d/backup/ int INT N?.headers #?.source 292 Chapter 10 splat Searches for and replaces patterns that match regular expressions (continued) However, you do not want calls to printf to become prINTf. Because in these declarations, the string int is followed by a space character, you should use the following command instead: splat -d/backup/ "int 1" "INT " #?.headers #?.source Similarly, the following command performs the same substitutions, but it writes the new versions of the files in the subdirectory backup of the current directory: splat -dbackup/ "int " "INT " #?.headers #?.source To avoid errors such as replacing printf with prINTf, you can use the -v option to determine, without changing your source files or creating new files, if you have entered the correct command. The following command performs the same substitutions as the previous command and displays those changes on the screen, but it does not change the files: splat -v "int " INT " #?.headers #?.source The following command replaces all occurrences of the string un signed char with ehar within all files with the .c extension in the current directory: splat "unsigned char" char #?.c The following command appends the string -cc to the end of each line that contains the string sc1 in the file comp.bat: splat -dbak/ "sc1.*$" " -ccll comp.bat The pattern sc1.*$ matches any string beginning with sc1 followed by O or more of any character and ending with the end of the line. The string& -cc appends a space followed by -cc to the end of the line. 293 Utility Reference splat Searches for and replaces patterns that match regular expressions (continued) You can also use splat to insert lines in a file or to break single lines into multiple lines. For example, you can have a file named text.c that contains the following line: parms(s);usage();exit(l); Suppose you want the calls to usage and exit to be on separate lines and indented one tab stop; enter the following command (all on one line): splat parms(s);usage();exit(1); parms(s);\n\tusage(); \n\texit(1);\n\ttext.c 294 Chapter 10 tb Displays traceback information Synopsis tb [>destination] [options] [tbfile [program]] Description The tb utility processes the traceback file that is created when you link your program with catch.o and your program terminates abnormally. To get traceback information for your program, you must link your program with catch.o. If your program terminates abnormally, catch.o creates a standard IFF format file named Snapshot . TB in your current directory. This file contains up to six sections: [] symbol cross reference [] stack [] registers [] environment [] memory [] user data. Each section contains information about your program at the time it terminated. (Two sections, memory and user data, may not be available for your program.) tb displays the traceback information on the screen unless you redirect it by specifying a greater than (>) sign followed by a destination. If you do not specify any options, tb displays only the current stack frame, which indicates the location where the program terminated. By specifying options, you can print 211 of the sections in the traceback file. By default, tb looks for the traceback file Snapshot . TB in your current directory. If you want tb to use a different traceback file, specify the traceback file as the tbfile parameter. The program parameter specifies the program from which you want tb to read debugging information. If you do not specify program, this utility uses the program specified in the traceback file. Note: Specifying a program is useful when you have two executables of your program: one created with debugging information and another without debugging information. The version without debugging information loads faster, but you still have access to the traceback information if your program crashes. 295 Utility Reference tb Displays traceback information (continued) tb supports the following options: -l displays all sections present in the traceback file -x displays the location of all symbols encountered in the program -s displays the contents of the entire stack at the time your program terminated -r displays the current contents of registers at the time your program terminated -v displays the callback chain and the location where the program terminated -m displays the amount of memory available at the time your program terminated (if present in Snapshot.TB) -u displays any user data generated by your program (if present in Snapshot.TB). Examples Suppose you have a program named testit that you link with catch.o, and testit terminates abnormally when you run it. You can display information about where the program terminates by entering the tb command without any options, as follows: 1> tb Program Name: testit; run from CLl Program load map (addresses are APTRs, sizes are in bytes) 220f78 $1110 211268 $5b4 Terminated with GURU number 00000005, Divide by Zero Error Error occurred at address 221cde = _foo line 5 called from 22156a = main line 11 called from 221c60 = _main + 704 called from 2210ca = hunk 0 + $152 However, the file created by catch.o contains much more information. To display all of the information contained in Snapshot.TB, you can specify the -l option, as follows: 1> tb -1 TraceDump 0.88 Copyright (c) 1988 The Software Distillery 296 Chapter 10 tb Displays traceback information (continued) TraceDump Utility: catch.o; Version 1, Revision O Processor type: 68000 VBlankFreq 60, PowerSupFreq 60 Symbols for hunk O _foo = 22153c _main = 22155c Program Name: testit; run from CLI Program load map (addresses are APTRs, sizes are in bytes) 220f 78 S 1110 21 1268 $5b4 Terminated with GURU number 00000005, Divide by Zero Error Error occurred at address 221cde = _foo line 5 called from 22156a = main line 11 called from 221c60 = _main + 704 called from 2210ca = hunk 0 + S152 Registers: DO=00221cde D1=00000000 D2=00000001 D3=00002718 D4=00000001 D5=0000002b D6=0000003b D7=00000000 A0=00221f54 A1=00243fcc A2=0024460a A3=00225c68 A4=00211268 A5=002445be A6=002033c8 A7=002445ae PC 221cde C=0 V=0 Z=1 N=0 X=0 stack top: 244640, stack pointer: 2445ae, stack length: $94 entire stack, size = $94 bytes 2445AE: 000003ED 00221558 0000002B 00000000: ...m.".X...+.... 2445BE: 002445CA 0022156A 00225C68 002445F6: .$EJ.".j."h.$E. 2445CE: 00221C60 00000001 00211620 00225CC4: .".'.....!. ."D 2445DE: 00226030 00225C68 83D10000 00000021: ."'0."h.Q.....! 2445EE: 13230021 00211620 00244640 002210CA: .#.!.!..$F@.".J 2445FE: 00244602 74657374 6974000A 00000022: .$F.testit...." 24460E: 60300000 27100000 27180000 00010000: '0'..'...'..... 24461E: 002B0000 003B0022 60300022 61300020: .+...;."'0."a0. 24462E: 35300022 0F740024 464400FF 425800FF: 50.".t.$FD..BX.. 24463E: 424C0022 : BL." 297 Part3 Using the SAS/C Macro Assembler Chapter 11 Using Assembly Language with C Language 288 299 11 Using Assembly Language with C Language 299 Introduction 300 Writing Assembly Language Functions 300 Writing Assembler Statements 304 Using Assembler Directives 308 Defining and Using Macros 309 Defining Control Sections 314 Communicating between Assembly Language and C Language 314 Calling Assembler Functions from C Functions 322 Calling C Functions from Assembler Functions 322 Referencing Global Data 323 Running the Assembler Introduction The SAS/C Macro Assembler reads an assembly language source file and produces an object file in the Amiga object file format. You can use the assembler to generate assembly language modules for your C programs, or you can generate programs written entirely in assembly language. For example, some operations such as directly accessing CPU and I/O registers cannot be handled easily in the C language. Also, assembly language is sometimes necessary to get the best combination of code size and speed. The assembler supports the full set of 68xxx mnemonics, an extensive set of assembler directives, and a powerful macro facility. To use the assembler, you should understand thoroughly the Motorola 68xxx instruction set. The "Additional Documentation" section in "Using This Book" lists books that describe the Motorola 68xxx instruction set. If you are writing assembly language modules to be called from C functions, or if your assembly language modules call C functions, you should also understand the SAS/C function protocol. This chapter assumes that you have a knowledge of assembler, but not necessarily the SAS/C Macro Assembler. This chapter describes the directives supported by the assembler, discusses how to write and use macros, and describes how to call C functions and assembler modules. 300 Chapter 11 Writing Assembly Language Functions The following sections provide an overview of the syntax expected by the SAS/C Assembler. The topics covered include [] the format of assembler statements [] the directives supported by the Assembler [] how to create and use macros [] how to define control sections [] how to specify addresses in assembler statements [] how to specify floating-point data [] the offsets supported by branch instructions. Writing Assembler Statements Each assembly language source line has the following format: [label:] operation[.size] operand . . . [;comment] You can enter white space (spaces or tabs) before any field. You must enter white space between the operation and operand. The fields of the source line are described below: label can start in any column and end with a colon, or can start in column one and end with either a colon or white space. A label can be up to 31 characters long and can contain letters, digits, underscores (_), and dollar ($) signs. A label cannot start with a digit, and the case of letters is significant. For example, the assembler differentiates between xYz, xYZ, and xyz. operation is the name of an instruction, a directive, or a macro. Do not begin an operation in column one. If no label is present, precede the operation with white space. If a label is present, you must include a colon or white space between the label and operation. The case of this field is not significant. For example, MOVE is the same as move. size specifies either the size of the operands or the offset, depending on the type of instruction. See the following section, "Specifying Sizes," for additional information. operand may contain 0 or more expressions, depending on the specific operation. Expressions are composed of constants, variables, and operators. The information in the following section, "Specifying Expressions," describes constants and operators in more detail. 301 Using Assembly Language with C Language comment can be entered in your assembler source code by preceding the comment text with a semicolon. Specifying Sizes Support for size suffixes depends on the instruction that you enter and the processor that you use. Check the documentation for your processor to determine which size suffixes are valid. For most non- floating-point instructions, the following suffixes are valid: Suffix Meaning none defaults to word (two bytes) B byte L long S short (same as byte) W word For floating-point instructions, the following suffixes are valid: Suffix Meaning none defaults to word B byte D double L long P packed S single W word x extended 302 Chapter 11 For branch instructions BSR and BRA, the sizes supported by the assembler are as follows: Suffix Meaning none calculates the size offset needed. For externs, the assembler generates a 16-bit offset. s generates 8-bit offsets. B generates 8-bit offsets. w generates 16-bit offsets. L generates 32-bit offsets.BSR.L is supported only on the 68020 and higher processors, and you cannot use BSR.L to branch to externs. For example, the following instruction creates a 32-bit branch: BRA.L subpr Data are converted into single, double, or extended precision according to the type of instruction. For example, the following instruction converts 2.1 into single precision and stores it in floating- point register 1: fmove.s #2.1,fpl As an additional example, the fmove instructions for the decimal number 2.1 specifying the bit pattern in hexadecimal are as follows: fmove.s #$40066666,fpl fmove.d #$4000CCCCCCCCCCCD,fPl fmove.x #$400000008666666666666666,fpl Specifying Expressions As described earlier, an expression is composed of constants, variables, and operators. A variable is a label name or a name defined using an assembler directive. 303 Using Assembly Language with C Language A constant is a decimal, hexadecimal, octal, or binary mlmber, or an ASCII literal. Unless you specify otherwise, the assembler expects a decimal number. To specify an ASCII literal, enclose the literal in single quotes. To specify a hexadecimal number, precede the number with a dollar sign. To specify an octal number, begin the number with an at (@) sign. To specify a binary number, begin the number with a percent (%) sign. The following table shows how to enter different types of constants: Type or Base Prefix Example decimal none 1234 ASCII literal 'literal' 'AC9T' hexadecimal $ $89AB octal @ @743 binary % %1011 floating point none 2.1 scientific notation none 2.1E+10 hexadecimal floating point $ $4066666 Note: If you use hexadecimal notation to specify floating-point numbers, you must use either the IEEE or FFP bit pattern representation. For information about this representation, refer to a manual for the 6888x math coprocessor. The following table lists the operators recogni~ed by the assembler in the order in which they are processed. Order Operator Meaning 1 - unary minus 2 >> right shift << left shift (continued) 304 Chapter 11 Order Operator Meaning 3 * multiply / divide % modulus 4 + add - subtract 5 < less than <= less than or equal to > greater than >= greater than or equal to == equal to != not equal to 6 & bitwise AND ! bitwise OR For example, in the following expression, PDQ is first negated and then multiplied by DEF, and the result is added to ABC: ABC+DEF*-PDQ Each expression represents a 32-bit value. An absolute expression is one that contains only constants. A relocatable expression contains symbols whose values are determined during the linking and loading procedure. Using Assembler Directives With the exception of the DC, DCB, and DS directives, an assembler directive is an instruction to the assembler instead of an instruction to be translated into object code. Directives cannot begin in the first character of the input line. The assembler supports the following directives: [label] CNOP offset,alignment aligns any data structure or entry point to any boundary. alignment is the alignment required for the base, such as 4 for long word, and offset is the offset from that alignment. 305 Using Assembly Language with C Language CSECT name,type,align,rtype,rsize defines section type and alignment requirements. The section "Defining Control Sections," later in this chapter, discusses the CSECT macro. [label] DC[.size] expression[,expression] . . . defines a constant value in memory. [label] DCB[.size] n,expression defines a constant block in memory. Using the DCB directive is equivalent to using the DC directive n times. [label] DS[.size] n reserves (defines) n memory locations of the size indicated by .size. ELSE begins an alternative for the IF directive. [label] END defines the end of the program. ENDC defines the end of conditional assembly. This directive turns off each of the IFxx directives. ENDM ends a macro definition. label EQU expression assigns permanently the value of expression to label. label EQUR register equates an address or data register with label. EXITM exits the macro expansion. This directive is a synonym for MEXIT. FAIL generates an error for the next input line. FORMAT is included for compatibility only. IDNT name defines a program unit name. IF expression assemb]es the following statemeIIts to the next ELSE or ENDIF if the expression supplied as its argument is not 0. IF statements may be nested. IFC string, string assembles if the strings are identical. 306 Chapter 11 IFD symbol assembles if the symbol is defined. IFEQ expression assembles if the expression is 0. IFGE expression assembles if the expression is greater than or equal to 0. IFGT expression assembles if the expression is greater than 0. IFLE expression assembles if the expression is less than or equal to 0. IFLT expression assembles if the expression is less than 0. IFNC string,string assembles if the strings are not identical. IFND symbol assembles if the symbol is not defined. IFNE expression assembles if the expression is not equal to 0. INCLUDE "filename" includes external files into the source. You can nest INCLUDE directives up to a depth of 3. LIST tells the assembler to produce a listing file. LLEN n sets the number of characters per line in the listing file. n can be any value from 60 to 132. The default value is 132 characters. label MACRO begins a macro definition. The following section, "Defining and Using Macros," describes how to define and use macros. MASK2 is included for compatibility only. MEXIT exits the macro expansion. This directive is a synonym for EXITM. NARG is the reserved symbol to which the assembler assigns the index of the last argument passed to the macro in the parameter list. NOFORMAT is included for compatibility only. 307 Using Assembly Language with C Language NOLIST tells the assembler to stop producing a listing file. NOPAGE tells the assembler to stop inserting page breaks and title headers in the listing file. NOOBJ stops the production of the object file. OFFSET n defines offsets. To define a table of offsets using the DS directive, you use the OFFSET directive. To end an offset section, use a RORG, OFFSET, SECTION, or END directive. OPSYN oldname newname defines a synonym for opcodes. PAGE inserts a page break into the listing file. PLEN n sets the number of lines per page in the listing file. n can be any value from 24 to 100. The default is 60 lines. label REG R1[-R2][/R3 [-R4]] . . . assigns permanently the register list to label. You can specify individual registers by separating each register with a slash (R1/R2/R3), or you can specify a range of registers by specifying the first and last registers separated with a hyphen (R1-R3). You can also combine individual registers with a range of registers (R1/R3-R5/R7). The assembler translates this list into the register list mask format used by the MOVEM instruction. [label] RORG n sets the program counter to n bytes from the start of the current relocatable section. [label] SECTION name[,type] defines a program section. name is a character string, and type must be CODE, DATA, or BSS. The section "Defining Control Sections, later in this chapter, discusses the SECTION macro. label SET expression assigns temporarily the value of the expression to the symbol identified by label. SPC n skips n blank lines in the listing file. 308 Chapter 11 TTL title sets the title string that is printed in the page headers in the listing file. The title can be no longer than 40 characters. XDEF label[,label] . . . defines an internal label as an external entry. By using the XREF directive, you can then refer to the symbols generated by these labels from other modules and from routines written in the C language. XREF label[,label]. . . references an external symbol defined with the XDEF directive. Defining and Using Macros You can define a macro using the following sequence of directives and instructions: label MACRO . . . ENDM You must begin the definition with a MACRO directive on a line by itself. After the MACRO directive, enter the lines that constitute the macro procedure. End the macro definition with the ENDM directive on a line by itself. You can use the EXITM directive within the macro procedure to exit the macro before the ENDM directive. For example, you could define a macro called acopy as follows: acopy MACRO move.w 4(sp),\1 move.l 6(sp),\2 ENDM You can invoke this macro with the following statement: acopy d0,a5 The assembler expands the macro as follows: move.w 4(sp),d0 move.l 6(sp),a5 309 Using Assembly Language with C Language Defining Control Sections The SAS/C Macro Assembler does not assume any default control sections. You must use either the SECTION or CSECT directive before you define any code or data. A SECTION or CSECT directive defines the beginning of a relocatable control section. Pararneters on these directives allow you to name each control section. The assembler uses these named control sections to control the location of data and code during linking. Chapter 12, "How Does the Compiler Work?," in SAS/C Development User's Guide, Volume I, describes the sections produced by the compiler. Using the SECTION Directive The SECTION directive follows this format: [label] SECTION name[,type] The following list describes each of the parameters. name specifies the name of the control section. You can use the name __MERGED for near data. You can use a specific name only once in a given asm file. type specifies the type of section. The type can be BSS, DATA, or CODE. Specifying Addresses with the SECTION Directive You can define symbols to be in the data section by USillg XREF and XDEF after the SECTION directive. The following exarnple uses 16-bit addressing to reference both code and data: SECTION __MERGED,DATA XREF xdata data1 DC.W 10 data2 DC.L 20 . . . SECTION TEXT,CODE XREF cfunc XDEF afunc afunc JSR cfunc(PC) MOVE.W data1(A4),D0 MOVE.L data2(A4),D1 MOVE.L d1,xdata(A4) 310 Chapter 11 To use 32-bit addressing, remove references to the register A4 and to the Program Counter (PC). Using the CSECT Directive The CSECT directive follows this format: CSECT name[, type][, align][, rtype][, rsize] The name and type parameters describe the control section being defined. The rtype and rsize parameters define how to access the information in the section. The align parameter is ignored. The following list describes each of the parameters: name specifies the name of the control section. You can use the name __MERGED for near data. You can use a specific name only once in a given asm file. type specifies the type of section. A value of 0 indicates a code section, 1 indicates a data section, and 2 indicates an uninitialized data section (like the udata section used by the compiler). The default value is 0 (code). align specifies the alignment requirements of the control section as a power of 2. For example, an alignment of 1 means that the section will begin on an even address, and a value of 2 means that the section will begin at an address divisible by 4. Note: This parameter is not used on the Amiga. All sections are long-word aligned. rtype specifies whether the code or data in the section are addressed relative to register A4 or to the PC. The default value is 0. rsize specifies the size of the offset for the address. If you specify an rsize of 4, the assembler uses absolute addressing. If you specify an rsize of 2, the assembler uses the value of rtype to determine how to address code or data in the section. The default value is 4. 311 Using Assembly Language with C Language The following table summarizes the valid types and sizes of relocation information on the 68000: rtype rsize Description 0,1,2 4 32-bit absolute address 0 2 PC-relative address (code section) 1 2 A4-relative address (data section) 2 2 A4-relative address (BSS section) Specifying Addresses with the CSECT Directive By specifying parameters in the CSECT directive, you can generate assembler modules that are compatible with C programs compiled with the data=near (base-relative data) and code=near (program counter-relative addressing) compiler options. You can force address register-relative addressing of data in the BSS section by specifying an rtype of 2 and an rsize of 2. Any XREF statements for external data elements must appear after the CSECT statement, and all data must be addressed relative to register A4. For example, the following code moves data around: CSECT __MERGED,1,,2,2 XREF xdata datal DC.W 10 data2 DC.L 20 . . . CSECT TEXT,0 MOVE.W datal(A4),DO MOVE.L data2(A4),D1 MOVE.L d1,xdata(A4) Note: If the XREF statement for the external data precedes the CSECT statement, you can use a standard reference to a four byte external address. You can force program counter-relative addressing of data in the code section by specifying an rtype of 0 and an rsize of 2. The XREF statement for the external function must appear after the CSECT 312 Chapter 11 statement. and the function must be called relative to the program counter. For example, the following code calls the function cfunc relative to the PC: CSECT TEXT,0,,0,2 XREF cfunc XDEF afunc afunc JSR cfunc(PC) RTS Note: If the XREF statement for the external function precedes the CSECT statement, you can use a standard JSR instruction to a 4-byte external address. In addition to specifying addresses relative to address registers and to the program counter, you also can specify absolute addresses or enter immediate data. The following tables summarize the addressing modes supported by the SAS/C Assembler and provide examples of each mode. The notation used in these tables is as follows: Notation Meaning Anan address register (a0 a7) bda 32-bit byte displacemer1t data actual data you want loaded into the register Dn a data register (d0--d7) d8 an 8 bit displacement d16 a 16-bit displacement od the 32 bit outer displacement PC program counter Xn an index register (a0.w--a7.1) xxx any number in decimal, hexadecimal, octal, or binary format You can specify the displacements, data, and numbers in decimal, hexadecimal, octal, or binary format. The information on entering operands in the section "Writing Assembler Statements," earlier in this chapter, describes how to specify each type of constant. 313 Using Assembly Language with C Language Note: All fields of the operands on the addressing modes marked 68020 are optional. The following table shows examples of register-direct addressing modes: Mode Example Dn add.w d1 ,d0 An addq.w #1 ,a1 The following table shows examples of register-indirect addressing modes: Mode Example (An) add.w (a1) ,d0 (An)+ add.w (a1)+,d0 -(An) add.w -(a1),d0 d16(An) add.w 10(a1),d0 d8(An,Xn) add.w 10(a1,a2.l),d0 bd(An,Xn) add.w $10000(a1,a2.l),d0 (68020 only) ([bd,An],Xn,od) add.w ([10,a1],a2.l,20),d0 (68020 only) ([bd,An,Xn],od) add.w ([10,a1,a2.l],20),d0 (68020 only) The following table shows examples of absolute addressing modes: Mode Example (xxx).W add.w (100).w,d0 (xxx).L add.l (100).l,d0 314 Chapter 11 The following table shows how to specify immediate data: Mode Example #data add.1 #100,d0 The following table shows examples of program counter-relative addressing modes: Mode Example d16(PC) add.w 10(PC),d0 d8(PC,Xn) add.w 10(PC,a2.l), d0 bd(PC,Xn) add.w $10000(PC,a2.l) (68020 only) ([bd,PC],Xn,od) add.w ([10,PC],a2.l,20),d0 (680Z0 only) ([bd,PC,Xn],od) add.w ([10,PC,a2.l],20),d0 (68020 only) Communicating between Assembly Language and C Language The following sections describe how to call assembler functions from C functions and how to call C functions from assembler modules. Calling Assembler Functions from C Functions Assembler modules may be called from C functions in three ways: [] passing parameters by placing them on the stack. Unless you specify the parameters=register option or use the __asm keyword, C functlons pass parameters on the stack. [] compiling your program with the parameters=register option. This option tells the compiler to pass parameters in registers, but it allows the compiler to determine which registers to use. [] using the __asm keyword and specifying which registers parameters are placed in. Passing parameters in registers produces a faster, smaller executable module. 315 Using Assembly Language with C Language Passing Parameters on the Stack As previously stated, C functions pass parameters on the stack if you do not specify the parameters=register option or use the __asm keyword. For example, the following assembler module, func, adds or subtracts an integer argument and a double argument depending on whether a plus ( + ) sign or a minus (--) sign is passed in the character argument. ; NOTE: This code assumes that you have a math co-processor. ;If you do not, your machine will crash when you run ;this program. xdef _func section code _func: fmove.d 8(a7),fp0 ; middle cmpi.b #'+',7(a7) ; should I add? bne.b noadd ; no, check subtract fadd.l 16(a7),fpO ; add 'mrright' to 'middle' bra.b exitpoint ; ready to return noadd: cmpi.b #'-',7(a7) ; should I subtract? bne.b nosub ; no, exit with error fsub.l 16(a7),fp0 ; subtract 'mrright' bra.b exitpoint from 'middle' nosub: fmove.b #-1,fpO ; return -1 for error exitpoint: fmove.l fp0,d0 ; return 'int' in d0 rts end The func assembler module returns an integer. 316 Chapter 11 To call an assembler module from your C program, include the prototype for the assembler module in your C source file before calling the function. The prototype for the previous example is the following: int func (char lefty, double middle, int mrright); For example, you can write the following program to call the f unc module: #include int func(char lefty, double middle, int mrright); void main(void) { char lefty; double middle; int mrright; lefty = '+'; middle = 12345.; mrright = 99; printf("func(+) = %d\n", func(lefty, middle, mrright)); } If you save the assembler module func in a file named testa.a, you can assemble test.a with the following command: asm -m2 testa.a If you save the C source code in a file named test, you can compile and link test with the following commands: sc math=868881 test slink lib:c.o test.o testa.o lib lib:sc.lib The test program will pass parameters on the stack. When you run test, you should see the following output: func(+) = 12444 317 Using Assembly Language with C Language To use the parameters inside your assembler module, you must retrieve the parameters from the stack. The arguments are placed on the stack from right to left; that is, the leftmost argument is immediately above the 4-byte return address in the stack. For example, in the following function call, the compiler generates code to push the arguments mrright, middle, and then lefty onto the stack. char lefty; double middle, int mrright; func(lefty,middle,mrright); Next, the func module is called, and the return address is pushed onto the stack. Figure 11.1 shows the stack after the func module has been called. Figure 11.1 | Bottom of Stack | The Stack after the | | func Module Is High | mrright | Called Memory | | <-- A7+12+n | middle | | | <-- A7+8+n | lefty | | | <-- A7+4+n | return address | | | <-- A7+n Low | work area | Memory | of size n | | | | Top of Stack | The arguments mrright, middle, and lefty use 4 bytes, 8 bytes, and 4 bytes, respectively.* Register A7 is the stack pointer, and it points to the 4-byte return address. Note: If you specify the shortintegers option, integers will be 2 bytes instead of 4. Before retrieving arguments from the stack into non-scratch registers, you must first save the contents of those registers, so they -------------------------------------------------------------------------------- * The smallest item that can be pushed onto the stack is the size of an integer. The size depends on whether you specify the shortint compiler OptiOII. A char will be promoted to an int. 318 Chapter 11 may be restored when your function terminates. Scratch registers are registers D0, D1, A0, A1, FP0, and FP1. The following list describes the steps your assembler module should take to save register values and establish frame pointers. In these steps, n refers to the size of your work area in bytes. 1. Enter the SUBI instruction if you need local storage: SUBI n,A7 2. Save registers D2 through D7, A2 through A6 if they will be changed during execution of the module. 3. Save floating-point registers FP2 through FP7 if a 68881 math coprocessor is present and will be used by the module. You can address the arguments from A7 as follows: Location Size Contents (A7) + n 4 return address (A7)+4+n 4 argument lefty (A7)+8+n 8 argument middle (A7)+16+n 4 argument mrright Using the parameters=register Option Using the parameters=register option tells the compiler to pass some of the function arguments in registers instead of on the stack. Specifically, the first two pointer arguments are in A0 and A1, and the first two integral arguments are in D0 and D1. All other arguments are passed on the stack. The compiler identifies functions that expect arguments in registers by placing an @ in front of the function name. The @ replaces the underscore (_) that the compiler normally places at the beginning of function names. 319 Using Assembly Language with C Language Using the parameters=register option is similar to passing parameters using the stack. For example, make sure you: [] include a prototype of your assembler module in your C source program. [] retrieve any parameters that are passed on the stack before using them. [] use the same asm command to assemble your assembler code. [] use the same slink command to link your C code. However, you must specify the parameters=register option in the sc command as follows: sc parameters=register test Using the __asm Keyword Using the __asm keyword on a function prototype or definition tells the compiler to pass parameters in specific registers. When you use __asm, the calling C function places the parameters in the registers required by the assembler module, so no stack manipulation inside the assembler module is necessary. The following assembler code is the same f unc module that is described previously in the section "Passing Parameters on the Stack," but it is modified to use the __asm keyword. ; NOTE: This code assumes that you have a math co-processor. ;If you do not, your machine will crash when you run ;this program. xdef _func section code _func: cmpi.b #'+',d0 ; should I add? bne.b noadd ; no, check subtract fadd.l d1,fp0 ; add 'mrright' to 'middle' bra.b exitpoint ; ready to return noadd: cmpi.b #'-',d0 ; should I subtract? bne.b nosub ; no, exit with error 320 Chapter 11 fsub.l dl,fp0 ; subtract 'mrright' from 'mlddle' bra.b exitpoint nosub: fmove.b #-1,fp0 ; return -1 for error exitpoint: fmove.l fp0,d0 ; return 'int' in d0 rts end To use the __asm keyword, you must modify the prototype of the assembler module in your C source file. For each parameter that you want to pass in a register, precede the parameter with the register keyword, two underscores (__), and the register into which you want the parameter placed. The prototype for the previous example is the following: int __asm func(register __d0 char lefty, register __fp0 double middle, register __d1 int mrright); The lefty argument is placed into register d0, the middle argument is placed into register fp0, and the mrright argument is placed into register d1. The remainder of your C program is the same as that shown earlier in the section "Passing Parameters on the Stack." You also use the same asm, sc, and slink commands as shown in in the section "Passing Parameters on the Stack." Returning Values to the Calling Function Your assembler module should return values in one or more registers. The register(s) depend on the data type of the calling function. Function return values are passed back in one or more registers, 321 Using Assembly Language with C Language depending on the data type declared for the calling function. The conventions are as follows: Return Length Type (Bits) Syntax Meaning char 8 D0.B low byte of D0 short 16 D0.W low word of D0 long 32 D0.L all of D0 pointer 32 D0.L all of D0 float 32 D0.L all of D0 float (68881) 32 FP0. S single precision in FP0 double (IEEE) 64 D0.L,D1.L high bits in D0 double (FFP) 32 D0.L all of D0 double (68881) 96 FP0.X all of FP0 If the assembler module returns a structure or union, it must define a static work area (not on the stack) to hold the returned object and return a pointer to this object in the D0 register. The calling function should immediately move the data to the appropriate place. Note: This approach implies that functions returning structures or unions are not re-entrant, although they are serially reusable. Such a function can be recursive if it is designed carefully with this return technique in mind. After setting up the return value, the assembler module exits by reversing the steps described earlier: 1. restore registers that were saved. 2. advance the stack pointer in register A7 past the work area. 3. return to the caller using an RTS instruction. The calling function removes the arguments from the stack. 322 Chapter 11 Calling C Functions from Assembler Functions The steps you take to call a C function from an assembler program vary, depending on whether or not you compile your C function using the parameters=register option. If you are not using registerized parameters, follow these steps: 1. push the arguments on the stack in the correct order. 2. call the function using the JSR instruction. 3. after control returns from the called function, adjust the stack pointer to account for pushed arguments. For example, the following code calls the function cfunc with two parameters that are currently in registers D7 and D6 and stores the return code in the ret variable. XREF cfunc MOVE.L D7,-(A7) ;push argument HOVE.L D6,-(A7) JSR cfunc ;call function ADDQ #8,A7 ;restore stack ptr MOVE.L D0,ret ;save return value If you are using registerized parameters, follow these steps: 1. place the appropriate arguments in the correct registers. 2. push any remaining arguments onto the stack. 3. add an ~ to the front of the function name, and call the function using the JSR instruction. 4. after control returns from the called function, adjust the stack pointer to account for pushed arguments (if any). For example, the following code calls the function cfunc with two parameters that are currently in registers D7 and D6 and stores the return code in the ret variable. XREF @cfunc MOVE.L D7,D0 MOVE.L D6,D0 JSR @cfunc ;call function MOVE.L D0,ret ;save return value If your C function is declared using the __asm keyword, you should pass the parameters in the appropriate registers. Referencing Global Data Instead of passing parameters into and out of a function, you can use global data. 323 Using Assembly Language with C Language You can access data declared in an assembler module from a C function by placing the data declarations inside a data section and defining the data with an XDEF statement. The following code defines two variables in assembly language and shows how to declare them in a C function. In Assembly Language In C Language CSECT data extern long VAR1; XDEF VAR1,VAR2,VAR3 extern long VAR2; VAR1 DC.L $4000 VAR2 DC.L $8000 You can access data declared in a C function from an assembler module using the XREF statement, as follows: In C Language In Assembly Language long VAR1=0x4000; XREF VAR1,VAR2 long VAR1=0x4000; . . . MOVE.L VAR1,D0 Running the Assembler After you have created your modules or programs in assembly language, you can run the Assembler by entering the asm command as follows: asm [>listfile] [options] filename The filename is the name of the assembly language source file that you want to assemble. The assembler assumes a source filename extension of .a, and it produces an object file with the same filename but with the .o extension. You can then use the linker, slink, to 324 Chapter 11 combine these object modules into an executable file, called a load module. If you include >listfile, the assembler sends the source listing and error messages to that file. The assembler supports the following options: -cx specifies that the sections designated by x are to be loaded into memory addressable by the Amiga system's custom hardware. You should specify -c for screen image and audio data. The x can be one or more of the following: b bss or uninitialized data c code segment d data segment By default, the assembler loads the segments into memory not addressable by custom hardware, if it is available. This action avoids bus contention between the processor and the custom hardware. For example, the following command causes all segments to be loaded into chip-addressable memory, regard0ess of the system memory configuration: asm -ccdb prog.a -d activates the debugging mode. -dsymbol [ =valuel defines symbol as if your source file contained this statement: symbol EQU value If you do not specify a value, the assembler assigns a value of 1. -hx specifies that the sections designated by x are to be loaded into memory not addressable by the Amiga system's custom hardware. The x can be one or more of the following: b bss or uninitialized data c code segment d data segment By default, the assembler loads the segments into memory not addressable by custom hardware, if it is available. This action 325 Using ~ssembly Language with C Language prevents the specified segments from being loaded into chip- addressable memory even if no other memory is available. This action could also prevent programs from running if external high- speed memory is not available on the machine. For example, the following command loads all three sections into high-speed r~AM asm -hcdb prog . a -iprefix specifies a prefix that should be placed in front of filenames in INCLUDE directives. You can enter up to four -i options. The assembler will search for the files in the order in which you specify the prefixes. If you specify a directory name as a prefix, include the trailing slash (/). For example, you can assemble the file named testprog. a with the following command: asm -imyinc/ -iyourinc/ testprog.a If your program contains the statement include abc . i, the assembler searches for the file in the current directory. If that fails, it searches for myinc/abc . i and then yourinc/abc . i. -l[x][m][i] sends a listing of the source file to the standard output, usually the screen. The listing displays the appropriate location counter and code- or data-generated information beside the source line. The x, m, and i produce the following slightly different listings: x lists the expansion text for macros. m lists additional data generated for source lines that camlot be listed beside the original source line. This option allows multiple listing lines for each source line. i lists the source for text from INCLUDE files as well as the original source file. -m0 specifies that only 68000 instructions are allowed. This option issues warning messages if, for example, you use instructions that are only available on the 68020. This option is the default. -m2 turns off the warnings generated by the -mO option. Use this option if 68020 instructions are allowed. 326 Chapter 11 -m3 turns off the warnings generated by the -m0 option. Use this option if 68030 instructions are allowed. -m4 turns off the warnings generated by the -mO option. Use this option if 68040 instructions are allowed. -oprefix specifies a prefix that you want placed in front of the output filename. If you specify a directory name as a prefix, include the (/). Any drive or directory prefixes in the input filename are discarded before the new prefix is added. Do not include blanks in the prefix. -s includes the section name at the beginning of each hunk. -u specifies that you want the assembler to prefix external references with an underscore (_). Do not use this option if you entered all external names with leading underscores. You should specify this option when you assemble startup code. -w defines the symbol shortint to be 1. This option works as if you had specified -dshortint= 1. For example, the following command assembles the file named modn.a, produces an object file named modn.o, and generates a listing file named modn. 1st that lists the source code and any error messages: asm >modn.lst -l modn 327 Part 4 Using the SAS/C Optimizer Chapter 12 Optimizing Your Code 328 329 12 Optimizing Your Code 329 Introduction 329 The Global Optimizer 334 The Peephole Optimizer 334 Running the Optimizers 335 Global Optimization Compiler Options 336 Global Optimization and the Debugger Introduction Your SAS/C Development System provides the following two optimizers: global optimizer (GO) analyzes the intermediate code produced by the compiler, performs several types of optimizations, and produces output in the same form as the compiler. Because the global optimizer works on intermediate code, it has no knowledge of the target processor or its instructions. peephole optimizer analyzes the assembler instructions and replaces inefficient sequences of instructions with shorter, more efflcient sequences. The Global Optimizer The global optimizer optimizes the flow of control and data through an entire function. The global optimizer performs several types of optimizations: register assignment analyzes the function to determine which auto variables, formal variables, temporary values, and constant values should be assigned to registers at each point in the function. The optimizer assigns up to three address registers, four data registers, and, if a math coprocessor is present, four floating point registers for the use of register variables. Generally speaking, the variables that are most used at a given point are assigned to registers. For example, variables occurring in 330 Chapter12 loops are more likely to be assigned to registers. The global optimizer attempts to keep a variable assigned to a register for as long as possible. Using the ampersand (&) operator with a variable prevents the global optimizer from allocating that variable to a register because it cannot predict when the resultant pointer will be used to read or modify the variable's value in memory. The same condition applies to an external variable because it may appear in another function or the & operator may be used with it elsewhere. The effect of global optimization's register allocation is quite different from the use of the register storage class. In general, a variable declared using the register keyword is associated with a machine register throughout the entire block in which it is declared (usually the entire function). In most functions, the variable is heavily used in some places and not used in other places. Yet, if a machine register is assigned to the variable, then the same register cannot be reused even in those sections where the variable is not used. Therefore, global optimization changes a register's assigned variable during the evaluation of the expression to ensure that the most heavily used variables are always in machine registers. The global optimizer overrides the register keyword in the declarations of integer, double, and pointer variables. Because of the portability of the C language, it is difficult for a programmer to know the number of available registers provided by the target machine and the compiler. The concept of a register variable is based on the idea that the variable is kept in a register for the entirety of its scope. Such restrictions no longer apply when a compiler uses the more advanced registration allocation algorithms in SAS/C software. Even though the compiler does not have dynamic information about program execution that would indicate which statements are executed more heavily, it can use the loop nesting structure to make a reasonable approximation. dead store elimination eliminates the assignment of a value to a variable if the value is not used. The assignment can be eliminated as in this example: index = 23; . . . /* code that does not refer to index */ . . . index = 12; 331 Optimizing Your Code The first assignment to index can be removed. Since the global optimizer inspects all references to the variable throughout the entire function, even subtle dead stores are eliminated. dead code elimination eliminates code that never can be executed. common subexpression merging eliminates recalculation of values that have been computed previously within the same function. For example, the following code x = i / 3; y = i / 3 + 4; can be changed to temp = i / 3; x = temp; y = temp + 4; moving invariants out of loops moves a calculation in a loop, whose value is the same on each iteration, to the outside of the loop. For example, the loop for (i = O; i < j; i++) { a[i]= p->q.r[10]; } can be changed to temp = p->q.r[10]; for (i = 0; i < j; i++) { a[i]= temp; } Refer to the explanation for optloop later in this chapter for more information about this type of optimization. induction variable transformations changes to addition loops containing multiplications (usually those associated with array indexing). 332 Chapter 12 copy propagation eliminates definitions of the form leftvar = rightvar when all uses of leftvar have this definition as the single reaching definition and rightvar will not change before each use. This optimization supports other optimizations. constant propagation and folding replaces references to a variable with a constant when the variable is defined as that constant. If the variable is used only in expressions with a different type (for example, if an int variable is only used in a comparison with f loat variables), global optimization creates a constant of the correct type. If the variable is used only as a constant, global optimization eliminates the variable entirely. The following example demonstrates these optimizations: void f(double d) { i = 10; for (; d < i; ++d) { . . . } return; } The previous code can be changed to the following: void f(double d) { for (; d < 10.0; ++d) { . . . } return; } Constant propagation is often useful in programs that contain inline functions since one or more parameters to the inlined function actually may be constants. 333 Optimizing Your Code auto variable elimination and remapping eliminates unused auto variables and reassigns storage offsets. Often the variable is unused because of previous optimizations. very busy expression hoisting moves an expression that is computed along all paths from a point in the code to a single, common location. For example, the code if (expression x = i + j; else y = (i + j) * 2; can be changed to temp = i + j; if (expression x = temp; else y = temp * 2; various reductions in strength performs associative reordering of additive operations involving constants to reduce the operation count. Various arithmetic operations involving constants are reduced in strength. Conditional and logical expressions whose results are unused are converted into corresponding if code. For instance, putchar from stdio.h is implemented with a conditional expression. If the result (the original character or an error indication) is not used, GO converts it into if else code, eliminating a load into a register. various control flow transformations performs various transformations to eliminate unreachable code or useless control structures. reordering of operations to reduce value lifetimes moves expressions with a single use adjacent to the operation that uses them. This optimization helps reduce temporary lifetimes and supports optimizations that move code around. For example, in the following code, the computation of the address ~ p 1 i ] can be moved after the call: P[i] = f(); 334 Chapter 12 The Peephole Optimizer The code generator contains all of the knowledge about the target processor and its instructions and makes full use of the 680x0 instruction set. The code generator tries not to generate extra instructions, but the peephole optimizer can help catch the few places where this is not possible. As stated earlier, the peephole optimizer analyzes the assembler instructions and replaces inefficient sequences of instructions with shorter, more efficient sequences. For example, for the following set of instructions, the peephole optimizer deletes the TST.L instruction: MOVE.L D1,D2 TST. LD2 BNE LABEL The test instruction is not needed because the condition codes for the branch instruction are set by the move instruction. Currently, the peephole optimizer optimizes 22 patterns of assembler instructions. If you find additional patterns that the optimizer should recognize, contact the Technical Support Division at SAS Institute Inc. Running the Optimizers To run the optimizers, specify the appropriate compiler option: Option Effect optimize turns on both the global and peephole optimizers. optimize turns on only the global optimizer. nooptpeep In many cases, optimized code is more difflcult to debug than non- optimized code. You may want to use the optimizer only after the main program has been tested and most errors have been corrected. 335 Optimizing Your Code Global Optimization Compiler Options The compiler accepts the following options to modify the operation of the global optimizer: optalias disables typebased aliasing assumptions. If optalias is used, the global optimizer uses worst-case aliasing. Using this option can significantly reduce the amount of optimization that can be performed. The nooptalias option is the default. optcomplexity defines the complexity of functions considered small by optinline. For more information, refer to Chapter 8, "Compiling and Linking Your Program," of SAS/C Development System User's Guide, Volume I: Introduction, Compiler, Editor. optdepth defines the maximum depth of function calls to be inlined. The range is 0 to 6, and the default value is 3. optinline inlines small functions (as defined by optcomplexity) as well as those with the __inline keyword. The optinline option is the default when optimize is used. Refer to Chapter 11, "Using Amiga Specific Features of the SAS/C Language," in the SAS/C Development System User's Guide, Volume I, for information about the _\ts_inline keyword. optinlocal inlines single-call static (local) functions. optloop assumes that loops have multiple iterations when the number of iterations is variable. This assumption enables the movement of safe code out of loops. The optloop option is the default. For more information, see "moving invariants out of loops," earlier in this chapter. When a loop is not executed at all, the moved code is executed in cases where it previously would not have been. For example, the code for (i = 0; i < n; ++i) for (j = 0; j < m; ++j) p[i * m + j] += 1; 336 Chapter 12 can be changed to for (i = 0; i < n; ++i) { temp = i * m; for (j = 0; j < m; ++j) p[temp + j] += 1; } In the changed code, i*m can be calculated when m is less than or equal to 0. When optloop has been specified, there may be a small cost in time for every loop that is not executed. There is also a significant time saving for loops that are executed many times, as most are. Some types of code may cause an exception, for example, division by 0. For this reason, the global optimizer restricts moved code to safe operations, including integral and pointer arithmetic other than division by 0, but not including iloating-point operations. The global optimizer avoids incorrect exceptions regard0ess of the setting of optloop. optrdepth defines the maximum level of recursive function calls to be inlined. The range is 0 to 6, and the default is 1. optsize disables optimizations that might sacrifice code size to save time. Only some loop optimizations do this. The nooptsize option is the default. Specifying both opttime and optsize may result in code that is both slower and larger than most optimized code. opttime disables optimizations that might sacrifice time to save space. The noopttime option is the default. Global Optimization and the Debugger To use all the capabilities of the debugger, the lines in the source code file must correspond exactly with the lines in the object code file. Optimizing your code may change this correspondence. Also, the debugger may not know about variables that the optimizer moves or eliminates. If you use the debugger on optimized code, run the debugger in mixed mode by entering the following command on the debugger command line: opt source mixed 337 Optimizing Your Code In mixed mode, the debugger displays both assembly language instructions and C source lines in the source window. Use the assembly language code to determine if the variables you examine are actually located where the debugger thinks they are. 338 339 Part 5 Appendix Appendix diff File-Matching Algorithm 340 341 Appendix diff File-Matching Algorithm This appendix describes the file-matching algorithm used by the diff utility. The algorithm used by the diff utility is described in A Technique for Isolating Differences Between Files by P. Heckel.* The matching algorithm described by Heckel is simple, fast, and effective. Briefly, it works as follows: [] Identify those lines that occur only once in each file. Assume that these lines match one another. [] Sweep downward into the first file. Each time you come to a line L that is already matched to the line L1 in the second file, examine the next line. This second line is referred to as L+1. [] If L+1 is the same as the corresponding line L1+1 in the second file, then match those lines as well. [] After this downward sweep is completed, sweep upward in the first file attempting to match lines in the same way (except that you look at L-1 and L1-1 when finding a matched line L). The effect of the matching algorithm is to match blocks of text to each other in the two files. However, the algorithm frequently cross-matches single lines or two blocks of lines. That is, lines L and L+k may be matched to lines L1 and L1-j. Consequently, after the process described previously is completed, the matches must be untangled to generate a coherent report of the differences. Therefore, the diff utility cross-matches blocks and then unmatches the smaller of the blocks. This process is an attempt to satisfy the notion that the differences reported should be minimal. In addition, this algorithm must first seed itself by identifying lines that occur exactly once in each file. Therefore, this algorithm may fail to match any lines even when there is an obvious match. ---------------------------------------------------------------------------- * Heckel, P. (1978), "A Technique for Isolating Differences Between Files," Communications of the ACM (April), 264-8. 342 Appendix For example, you may have two files with the following contents: File 1 File 2 aaa bbb xxx xxx xxx xxx yyy zzz The algorithm will fail to match the blocks of xxx lines because it does not find any lines that occur exactly once in each file to seed the algorithm. 343 Index A nesting aliases 92 positional parameters 90 -a option, smake utility 289 referencing aliases commands with abort command, SC_SCMSG AREXX port back-tick character (`) 92 262, 262-264 syntax 89, 128 absolute addressing modes 313 aliases for dump command in previous absolute expressions 304 releases 146 147 accelerator keys 23-24, 29, 34 alternate targets, smake utility 283 284 actions, smake utility 273 altfile command, SC _ SCMSG AREXX port actions gadget 267 262 activate command 107, 111, 127 altline command, SC _ SCMSG AREXX Address field, tasks command 109 port 262 address parameter 118-119 ampersand operator (&) examples 118-119 identifying addresses 118 using with location parameter 40 using with global optimizer 330 addresses ampersand symbol (&) absolute addressing modes 313 special symbol in smake utility 277 addressing modes supported by SAS/C and operator (&) assembler 312 not used with register variables 58 dumping 62 append block, diff utility 221 forcing program counter-relative AREXX interface 101 addressing 311 invoking editors 261-262 register-direct addressing modes 313 AREXX macros 101-104 specifying with CSECT directive 311-314 command output 103-104 specifying with SECTION directive invoking macros 102-103 309-310 libraries.cpr 106 addsym option macros provided by CodeProbe 101-102 adding to slink automatically 8, 9 return codes 103 generating H_SYMBOL hunk 8 values returned from CodeProbe purpose 74 commands 103-104 AddTask function 114 AREXX port 262-264 after option args command 130 break command 49, 135 array-slice parameter 119-120 go command 40, 42, 156 arrays alias command 89-92, 128-129 displaying 31, 59-61 See also define command setting watches or watch breaks 71 See also expand command arrdim option, opt command 86 87, 165 compared with define command 92,93 ASCII option, dump command 65-66 displaying alias definitions 90 asm command 323-326 displaying current aliases 89-90 -c option 324 escape characters 19 -d option 324 examples 91, 128-129 -d symbol(=value) option 324 expanding alias names 90, 91 -h option 324-325 344 Index asm command (continued) used in array-slice parameter 119 -i option 325 wild card indicator 34 -m0 option 325 asynchronous tasks 108 -m2 option 325 at sign ((?) -m3 option 326 oml utility 251, 253 -m4 option 326 replacing underscore in function names -o option 326 for compiler 318 options supported 324 326 special symbol in smake utility 277 s option 326 specifying octal numbers in assembler syntax 323 statement expressions 303 u option 326 auto variable elimination and remapping w OptiOII 326 333 __asm keyword 319 320 autoedit option, scmsg utility 255 assembler directives 304-308 autoswap mode 29, 88 See also specific directives autoswap option, opt command 88, 165 assembly language 299 326 addresses, specifying with CSECT directive 311 314 B assembler directives 304-308 assembler statements, writing 300-304 -b option __asm keyword 319-320 diff utility 219 calling assembler functions from C oml utility 253 functiolls 314 321 smake utility 289 calling C functions from assembler back-tick character (`) fullctions 322 non-expansion of escaped macro communicating with C language 314-323 definitions 92 93, 141 control sections, defining 309-314 referencing aliased commands 92 CSECT directive 310 314 backslash character (\) expressions, specifying 302 304 continuing lines in aliases 90 fields in source line 300-301 Control-\ for terminating oml 251 format of source lines 300 escape character in grep searches 227, macros, defining and using 308 231, 232-233 options supported by assembler 324-326 escape character preceding semicolon 93 parameters=register option 318-319 extending commands across lines 18 passing parameters on the stack 315-318 interpretation in character strings 19, referencing global data 322-323 123 returning values to calling function special symbol in smake utility 277 320 321 badchar option, opt command 87, 165 rulming the assembler 323-326 bclear command 131 SECTION directive 309-310 definition 36, 48 size sumxes, specifying 301 302 examples 131 writing assembly language functions syntax 131 300 314 bdisable command 48, 132 assembly mode benable command 48, 133 ps command 47 blist command 36, 48, 134 setting 46, 83 bottom command, SC_SCMSG AREXX trace command 45 port 262 asterisk ( ) braces ({}) grep search pattern 225, 226, 230-231 defining aliases 90 removing all aliases 92 using in cmd_list parameters 50 345 Index brackets ([]) C enclosing characters in grep search 226, 228-230 C functions, calling See calling assembler functions from branch instructions C functions assembler statement size suffixes 302 See calling C functions from assembler break command 48-53, 135 136 functions See also bclear command C mode 83 See also bdisable command -c option See also benable command asm command 324 See also blist command diff utility 219 after option 49, 135 grep utility 225 cmd0ist parameter 50, 135 smake utility 289 call command 137-138 definition 39 call frame 6 examples 136 calling assembler functions from C go command as last command of cmd list functions 314-321 parameter 51 __asm keyword 319-320 quiet option 52 53, 135 calling an assembler module 316 syntax 48-49, 135 parameters=register option 318-319 temp option 52-53, 135 passing parameters on the stack 315 318 trace option 51, 52-53, 135 retrieving parameters from the stack when option 49, 135 317 returning values to calling function Break menu 21 22 320-321 breakpoints saving register contents 317-318 attaching actions to 50 53 stack, example 317 caution against placing in libraries 110 calling C functions from assembler conditional 49 50 functions 322 definition 5, 32, 47 Calls window l4 executing up to a breakpoint 32 caret (^) multitasking programs 108 grep search pattern 226 nesting 52 case option, opt command 85, 165 catch command 107, 112, 139 preventing debugger from stoppin 51 Catch New Devices option resident libraries 105, 106 See devices option, opt command setting 32, 47-48 catch option, opt command 89, 166 temporary, set by go command 40, 43 change block, diff utility 221 turning off 32 character classes, grep utility 226 using with detach command 111 112 specifying 228-230 -buffer command-line option 78 79 characters and strings, dumping 65 66 build command, SC_SCMSG AREXX port class command, SC _ SCMSG AREXX port 262 clear command SC SCMSG AREXX port Build menu, scmsg utility 259 262 built-in functions 202-203 -cli command-line option 11, 79 See also specific functions cmd_list parameter, break command 50, list of functions 203 135 parameters 202 CNOP assembler directive 304 purpose 202 Code Generation Options window 266 346 Index CodeProbe 3-24 command-line editing 16-19 See also debugging programs determining editing modes 17 basic features 4 editing function keys 17-18 changes and enhancements 5 escape characters in commands 19 command line 16-19 escape sequences in character compiling and linking programs 9 strings18 19 controlling 8 extending commands across lines cpr command 9-10 using backslash (\) 18 debugging procedure 7-8 command-line options 78-81 entering commands 16-24 adding as tool types 78 function and special keys 22-23 -buffer 78-79 introduction 3 4 -cli 11, 79 line mode 11 -command 79 menu accelerator keys 23-24 -device 97 multitasking features 4-5 -i 79 opening windows 15-16 -line 79 pull-down menus 20-22 -nok 98 quit command 10 -noprofile 79-80 requirements 7 -pipe 97 running 9-11 running on optimized code 336 337 -screen 80 starting 25 34 setting up in Workbench screen 11 terminology 5_7 -speed 97 windowing interface 12-16 -startup 26, 80 Workbench support 10-11 -symfile 98 CodeProbe sample session 25-34 -unit 97 activating autoswap mode 29 using with cpr command 10 breakpoints, setting 32 -w 80 clearing watches and watch breaks 34 -wb. 11, 80 compiling and linking 25 -wd0alog 81 continuing execution 30 -wregister 81 controlling debugging session 27-34 -wsource 81 displaying arrays and structures 30-32 -wwatch 81 displaying variable values and types 32 command output for AREXX macros executing breakpoints 32 103-104 executing until variable changes value command parameter, help command 27 33-34 commands go command 26 See also specific commands invoking the debugger 26 address parameter 118 119 online help 26-27 array-slice parameter 119 quitting the debugger 34 command-line editing 16-19 restart command 26 command-line equivalents for menu items source mode, setting 27-28 20-22 starting the debugger 25-26 customizing Dialog window commands stepping over code 29-30 89-94 watch and watch break commands 32-34 editing function keys 17-18 comma (,) editing modes 17 separating multiple arguments in display entering on command line 16-19 command 58 escape characters in strings 18-19 command command line option 79 expression parameter 120 347 Index extending across lines using backslash controlling program execution (\) 18 See program execution, controlling function and special keys 22-23 copy propagation 332 list of commands 116-118 cover utility 216-218 location parameter 120 121 dir= option 217 menu accelerator keys 23-24 example 217-218 number parameter 121 merge option 217 pull-down menus 20-22 nosource option 217 range parameter 121-122 options supported 217 register parameter 122-123 running 216 SC_SCMSG AREXX port 262-264 syntax and description 216 217 shortcuts for command names 16 cpr command 9-10 speclal parameterS 118-125 available command-line options 10 specifying in oml utility 252-253 changing the default environment 11 subrange parameter 123-124 -cli option 11 syntax 16 invoking the debugger 26 type parameter 124 syntax 9, 75 variable parameter 125 -wb option 11 >prompt 16 .cpr extension for macros 102 comment field, assembly language source cprinit file line 301 comment lines 82 comment lines, cprinit file 82 examples 81-82 communications parameters initializing CodeProbe 81-82 defining for cross debugging 97 suppresSing execution with -noprofile -device 97 option 79 80 -pipe 97 CPRK -speed 97 See also cross-development mode -unit 97 examples 99 comparing files options 98 See diH utility required on target machine 96 compiler running 96 See sc command starting before CPRX 97, 98 compiler options, setting starting the kernel 98 See scopts utility terminating 99-100 Compiler Options Index window 266 CPRX Compiler Options window 266 See also cross-development mode compiling examples 99 compiling and linking programs 7 -nok option 98 sample program (lines.c) 25 starting 98-99 condition control register (CCR) flags 110 stripping debug information with -x config= option, scmsg utility 255 option 96 constants -symfile option 98 assembler statement expressions 303 syntax 98 optimizing 332, 333 terminating 99-100 reductions in strength 333 -x option 99 context option, opt command 85, 166 cross-debugging 6 control flow transformations 333 cross-development mode 95-100 control sections See also CPRK See CSECT assembler directive See also CPRX See SECTION assembler directive debugging applications 99 348 Index cross-development mode (continued) data structures, displaying defining communications parameters 97 See structures, displaying examples 99 DC assembler directive 305 host machine 96 DCB assembler directive 305 Nl LL modem cable 96 deactivate command 107, 111, 140 preparing to use cross debugger 96 dead code elimination 331 procedure 96 99 dead store elimination 330 reasolls for cross-debugging 95-96 Debug field, tasks command 109 running cross debugger 96-100 DEBUG tool 11 starting the cross debugger (CPRX) debug= options 74-76 98 99 determining which option to use 76-77 starting the kernel (CPRK) 98 list of options 74 target machine 96 debug=full option 74 terminating CPRX and CPRK 99-100 using 76 CSECT assembler directive 310-314 when to use 76 77 addressing modes supported 312 debug=fullflush option 74 definition 304 using 76 forcing program counter-relative when to use 76-77 addressing 311 debug=line option 74 format 310 generating H DEBUG hunks 8 parameters 310 using 75 program counter-relative addressing debug=symbol option 74 modes, examples 314 generating H DEBUG hunks 8 register-direct addressing modes 313 using 75-76 specifying addresses 311-314 when to use 76-77 specifying immediate data 314 debug=symbolflush option 74 valid types and sizes of relocation adding to sc command 9 informatioll 311 displaying full debugging information 25 CTRL-C, terminating CPRK and CPRX 99 using 76 Ctrl-L key 23 when to use 76-77 Ctrl-W key 23 debugger curly braces See CodeProbe See braces ({}) debugging environment, setting up 73-94 cllrrellt task, displaying 89 alias command 89 92 cycles gadget 267 arrdim option 86-87 autoswap mode 88 badchar option 87 D case option 85 Catch New Devices option 88 d command catch option 89 oml utility 252 changing default environment short form of display command 30 with -cli and wb options 11 -d Option choosing command-line options 78-81 asm command 324 context option 85 smake utility 289 current task 89 splat utility 291 customizing Dialog window commands -d symbol(=value) option, asm command 89-94 324 debug= options 74-76 data, examining debug=full option 76 See dump command debug=fullflush option 76 349 Index debug=line option 75 restart command 26 debug=symbol option 75-76 running CodeProbe 9-11 debug=symbolflush option 76 sample program 1 37-38 define command 92-93 sample program 2 53-56 echo mode 84 setting breakpoints 32 ibytes option 84-85 setting source mode 27-28 ignorepath option 85 single stepping 44-47 initializing CodeProbe 81-82 starting the debugger 25-26 list option 86 stepping over code 29-30 radix option 86 steps for debugging 8 rangelen option 87 trace commands 45-46 search path 87 88 watch and wbreak commands 32-34, setting and showing options 82-89 70-72 source file location 77 78 watches and watch breaks 69-72 source modes 83 84 whatis command 68-69 Step Into ResLib option 88 89 decimal option, dump command 65 strlen option 86 .DEFAULT fake target 281-282 unalias command 92 default files, smake utility 287 288 unassemble option 86 #define capability, C preprocessor 93 undefine command 94 define command 141 when to use debug= options 76-77 compared with alias command 92, 93 debugging programs 25 34, 35 72 compared with C preprocessor #define See also multitasking programs, capability 93 debugging defining symbols to nothing 93 See also resident libraries, debugging displaying macro definitions 93 activating autoswap mode 29 examples 141 break command 48-53 syntax 93, 141 breakpoints 47-53 delcomp command, SC_SCMSG AREXX clearing watches and watch breaks 34 port 262 commands for running sample delete block, diff utility 220 programs 36 delete command, SC_SCMSG AREXX port compiling and linking programs 9, 25 263 continuing execution 30 delfile command, SC_SCMSG AREXX controlling program execution 27-34, port 263 39-53 delnum command, SC_SCMSG AREXX display command 57 61 port 263 displaying arrays and structures 30-32 dependent file, smake utility 273 displaying variable values and types 32 detach command 111-112, 142 dump command 61-66 definition 107 examining data and data structures examples 142 57-72 precautions 111-112 executing breakpoints 32 syntax 111, 142 executing until variable changes value device command-line option 97 33-34 devices option, opt command 88, 166 go command 26, 39-44 Diagnostic Message Options window 266 invoking the debugger 26 Dialog window online help 26-27 echo mode 84 proceed commands 46-47 functions 14 quitting the debugger 34 open by default 12, 26 register command 66-68 scrolling 31 350 Index Dialog window (continued) special symbol in smake utility 277 specifying start-up window coordinates specifying hexadecimal numbers in 81 assembler statement expressions zooming to full size 30 303 Dialog window commands -$ option, grep utility 225 alias 89-92 DS assembler directive 305 customizing 89-94 dump command 61-66, 145 147 wclear 34 addresses, dumping 62 diff file-matching algorithm 341-342 ASCII option 65-66 diff utility 219-223 characters and strings, dumping 65-66 append block 221 compared with register command 77 -b option 219 compatibility aliases 146-147 -c option 219 decimal option 65 change block 221 examples 147 delete block 220 float option 64 error messageS 222-223 floating-point numbers, dumping 64-65 examples 221-222 format parameter 145 -F option 219 integers, dumping 65 -L option 219 pointers, dumping 63-64 -I option 219 ranges, dumping 62-63 -o option 219 syntax 61, 145 options supported 219-220 variables, dumping 61-62, 75 -p Option 220 dzero command 148 -q Option 220 displaying ASCII text string 66 syntax and description 219-221 examples 31, 148 -w Option 220 syntax 148 dir= option, cover utility 217 disassembling object modules (omd utility) E 249 display command 57-61, 143-144 -e option, smake utility 289 compared with register command 77 echo command 149 examples 143-144 echo option, opt command 84, 166 expresslon parameter 57 Edit menu, scmsg utility 260 format parameter 57 AREXX for invoking editors 261-262 multiple arguments 58 examples 264-265 overriding default format 57 SC_SCMSG AREXX port 262-264 string parameter 58 editcommand option, scmsg Project menu structures and arrays 30-32, 59-61 257 syntax 57, 143 editing modes 17 value and type of variables 32 ELSE assembler directive 305 variable types 75 END assembler directive 305 dollar parameter ($) ENDC assembler directive 305 dump command 145 ENDM assembler directive 305, 307 line command 161 env command 150-151 set command 177 environment 6 dollar sign ($) See also debugging environment, setting grep search pattern 227, 229, 231 up indicating macros 277, 278 representing state of the machine 14 positional parameters in aliases 90, 128 run environment 6 prefixing register names 119 user environment 6 351 Index environment variable (sc/cprpath) 11 FAIL assembler directive 305 EQU assembler directive 305 fake targets, smake utility 281-283 equals sign (=) file command, SC _ SCMSG AREXX port defining macros in smake utility 277-278 263 EQUR assembler directive 305 file comparison errnum command, SC_SCMSG AREXX See diff utility port 263 file dependencies, tracking errors and warnings, searching for See smake utility See scmsg utility file-matching algorithm 341-342 escape characters 18-19 File menu alias command 19 Line and Find Current Line items 20 backslash (\) in character strings 19 menu items and command-line backslash (\) in grep searches 227 equivalents 20-22 character strings 18-19 finish command 100, 154 commands 19 flags, modifying double quotes (" ") around 18-19 See rflag command dumping with ASCII option 66 float option, dump command 64 single quotes (' ') around 19 floating-point instructions string parameter support 123 assembler statement size suffixes 301 exception hand0ing 113-114 floating-point numbers exclamation mark (!) dumping 64-65 marking watch breaks 33 hexadecimal notation in assembler negation character in grep search 226, statement expressions 303 230 FORMAT assembler directive 305 execute command 152 format parameter executing code display command 57 See program execution, controlling dump command 145 EXITM assembler directive 305, 307 fregister command 155 expand command 153 function keys expression parameter actions performed 22-23 display command 57 command-line editing 17-18 operators not accepted 120 function line parameter, location expressions parameter 41 absolute 304 function parameter, location parameter 41, optimizing subexpressions 331 42 reductions in strength 333 functions relocatable 304 See built-in functions reordering 333 specifying in assembler statements 302-304 G very busy expression hoisting 333 gadgets in scopts utility 267 268 global data, referencing 322-323 F global optimizer 329 333 auto variable elimination and -f option remapping 332 grep utility 225 common subexpression merging 331 Istat utility 244 constant propagation and folding 332 smake utility 289 control flow transformations 333 -F option, diff utility 219 copy propagation 332 352 Index global optimizer (continued) -f option 225 dead code elimination 331 -n option 225 dead store elimination 330-331 number of times characters may appear, induction variable transformations 331 specifying 230-231 moving invariants out of loops 331 options supported 225 optalias option 335 -p option 225 optcomplexity option 335 patterns at beginning or end of line, optdepth option 335 specifying 231 optinlille option 335 patterns containing special characters, optinlocal option 335 specifying 232 234 optloop option 335-336 -q option 225 optrdepth option 336 redirecting output 224 optsize option 336 -s option 225 opttime option 336 single character, specifying 228 reduction5 in strengtll 333 specifying patterns 225-227 register assignment 329-330 syntax 224 reordering of operations 333 -v option 225 runnirlg 333_337 -V option 225 running the debugger on optimized code -$ option 225 336 337 gst utility 237 239 very busy expression hoisting 333 error messages 239 global symbol information 8 examples 238 239 global symbol tables list optlon 237 238 See gst utility options supported 237 238 See hypergst utility syntax and description 237_238 go command 39-44, 156-157 unload option 238 after clause 42, 156 verbose option 238 completing execution before running other commands 30 H examples 44, l56 157 executing until breakpoint 30, 32 -h option last command of cmd list parameter 51 asm command 324-325 location parameter 156 smake utility 290 location parameter forms 40 42 H_DEBUG hunks 7, 8 parameters 40 help command 26 27, 158 starting execution of sample program 26 Help key 23 syntax 39 Help menu 16 syntax errors 43-44 Help window 14 when clause 42 44, 156 hidden option, scmsg Project menu 258 go main command 26, 80 hidden option, scmsg utility 255 gotofile option, scmsg Project menu 257 hide command, SC_SCMSG AREXX port gotoline option, scmsg Project menu 258 263 greater than sign (>) host machine 6, 96 See also redirecting output (>) hunks > prornpt for command line 16 H_DEBUG hunks 7, 8 grep utility 224 236 H_SYMBOL hunks 8 -c option 225 hunks command 159 description 224 227 hypergst utility 240-241 error messages 234 236 hyphen (-) examples 227 specifying range in grep search 226 353 Index I keys function key actions 22-23 -i command-line option 79 function keys for command-line editing -i option 17-18 asm command 325 menu accelerator keys 23 24, 29, 34 smake utility 290 special keys 23 ibytes option, opt command 84 85, 166 IDNT assembler directive 305 IF assembler directive 305 L IFC assembler directive 305 IFD assembler directive 306 l command, oml utility 252 IFEQ assembler directive 306 -l option IFGE assembler directive 306 diff utility 219 IFGT assembler directive 306 tb utility 295 IFLE assembler directive 306 -L option, diff utility 219 IFLT assembler directive 306 label field, assembly language source line IFNC assembler directive 306 300 IFND assembler directive 306 left-Amiga m keyboard shortcut 29, 34 IFNE assembler directive 306 less than sign (<) .IGNORE fake target 282 diff utility 220 ignorepath option, opt command 85, 166 oml utility 251 image 6 libraries image parameter, location parameter 42 See resident libraries, debugging INCLUDE assembler directive 306 libraries, managing infinite loops 112 See oml utility initializing CodeProbe libraries.cpr AREXX macro 106 See cprinit file line boundary 6 Input window 15 line command, SC_SCMSG AREXX port insert editing mode 17 263 instruction bytes -line command-line option 11, 79 See ibytes option, opt command line parameter, location parameter 41 integers, dumping 65 link library 250 interlace mode link option 9, 25 See -i command-line option linker invoking the debugger See slink See cpr command Linker Options window 267 linking programs 9, 25 LIST assembler directive 306 J list command 161 162 list option jump command 89, 160 gst utility 237 opt command 86, 166 Listing/Cross Reference Options window K 266 lists gadget 267 -k option, smake utility 290 LLEN assembler directive 306 kernel load module 324 See CPRK local input files, smake utility 284-286 354 Index location parameter 40 42, 123-124 Memory window 15 address parameter 40 memory, dumping definition 40, 120 See dump command forms 40 memset function 207 function line parameter 41 menu accelerator keys 23-24, 29, 34 function parameter 41, 42, 121 menus go command 40 42, 156 See pull-down menus image parameter 42, 120 merge option, cover utility 217 integer parameter 121 Message window 15 line parameter 41 See also wmsg command module parameter 42, 120 MEXIT assembler directive 306 syntax 120 minus sign (-) log command 163-164 special symbol in smake utility 229, 277 log file 6 mixed mode 83-84 loops opt source mixed command 46, 77 induction variable transformations 331 running the debugger on optimized code moving invariants out of loops 331 336-337 Iprof utility 242 243 setting 83-84 Istat utility 244 248 module 7 -f option 244 module parameter, location parameter 42 options supported 244 Modules window 15 syntax and description 244 multiple targets, smake utility 283 -t option 244 multitasking programs, debugging 107-114 z option 244 activate command 111 asynchronous tasks 108 breakpoints and task handling 108 M catch command 112 CodeProbe features 4-5 -m option, tb utility 295 commands for controlling tasks 107, MACRO assembler directive 306 109 113 macros deactivate command 111 See also AREXX macros design considerations 113-114 See also define command detach command 111-112 defining assembly language macros 308 exception hand0ing 113-114 escaped macros not expanded 92-93 opt task command 110 111 hiding in double quotes 92 symload command 112-113 macros, smake utility 277-281 synchronous tasks 108 default macros 279-280 task handling by CodeProbe 108 defining transformation rules 280-281 tasks command 109-110 defining with equals sign (=) 277-278 terminating tasks 108 overriding definitions 278 trap handling 113-114 referring to macros 278 types of tasks 108 Map Options window 267 -m0 option, asm command 325 MASK2 assembler directive 306 -m2 option, asm command 325 maximum bad characters -m3 option, asm command 326 See badchar option, opt command -m4 option, asm command 326 memcmp function 204 memcpy function 205 memmove function 206 Memory menu 22 355 Index N -n option 253 -o option 253 -n option options, specifying 253 grep utility 225 r command 252 oml utility 253 -s option 253 smake utility 290 syntax and description 250-251 Name field, tasks command 109 -t option 253 name= option, gst utility 238 terminating 251 NARG assembler directive 306 -v option 253 nested breakpoints 52 x command 252 networks -x option 253 using for cross debugging 97 @ command 253 next command, SC_SCMSG AREXX port .ONEERROR fake target 282 263 online help nodebug option 74 See help command NOFORMAT assembler directive 306 OpenDevice function 114 -nok option 98 OpenLibrary function 114 NOLIST assembler directive 307 operand field, assembly language source non-floating-point instructions line 300 assembler statement size suffixes 301 operation field, assembly language NOOB) assembler directive 307 source line 300 NOPAGE assembler directive 307 operators -noprofile command-line option 79-80 assembler statement expressions nosource option, cover utility 217 303-304 NULL modem cable for cross debugging 96 OPSYN assembler directive 307 number parameter 121 opt command 82-89, 165 167 numeric keypad modes 17 arrdim option 86-87, 165 autoswap option 88, 165 badchar option 87, 165 O case option 85, 165 catch option 89, 166 -o option context option 85, 166 asm command 326 devices option 88, 166 diff utility 219 displaying current task 89 oml utility 253 echo option 84, 166 splat utility 291 env option 112 Object Module Disassembler 249 examples 167 Object Module Librarian ibytes option 84-85, 166 See oml utility ignorepath option 85, 166 objects, determining type or configuration list option 86, 166 See whatis command radix option 86, 167 OFFSET assembler directive 307 rangelen option 87, 167 omd utility 249 reslib option 88 89, 167 oml utility 250-254 search option 87-88, 166 -b option 253 source option 46, 77, 83, 84, 166, 336 commands, specifying 252-253 strlen option 86, 167 d command 252 syntax 165 examples 254 task option 107, 110-111, 167 invoking 250 unassemble option 86, 167 I command 252 opt env command 112 356 Index opt source asm command 46 Output window 15 opt source mixed command 46, 77, 84, overwrite editing mode 17 336 opt task command 110 111 definition 107 P examples 111 task addresses 111 -p option task-lD argument 110 diff utility 2Z0 using 110 111 grep utility 225 optalias option, global optimizer 335 smake utility 290 optcomplexity option, global optimizer 335 PAGE assembler directive 307 optdepth option, global optimizer 335 parameters=register option 318 319 optimized code, rumling debugger on pass count 7, 40, 42 336-337 specifying 135 Optimizer Optiolls window 266 patterns, searching for optimizing code See grep utility See global optimizer pausing 179 See peephole Optimizer peephole optimizer 329 optinline option, global optimizer 335 functions 334 optinlocal option, global optimizer 335 running 334 option results command (AREXX) 103 beginning AREXX templates 261 options specifying binary numbers in assembler See also command-line options See also debug= options statement expressions 303 See also opt command Period (.) See also scopts utility grep wildcard character 225, 228, 230 -pipe command-line option 97 addsym 8, 9, 74 PLEN assembler directive 307 cover utility options 217 plus sign (+) default options, displaying 82 diff utility options 219 220 grep search pattern 226, 231 global optimizer compiler options portname option, scmsg Project menu 258 335-336 pound sign (#) grep utllity options 225 ANSI # and ## operators not supported lstat utility options 244 Indicating comments m smakefiles 274 oml utility options 253 inserting before undefine command 191 parameters=register option 318-319 prev command, SC_SCMSG AREXX port scmsg utility options 255-256 263 scmsg utility Project menu options Pri field, tasks command 109 257 258 printing expressions setting and showing within CodeProbe See grep utility 82-89 proceed command 46-47, 168 smake utility 289-290 See also ps command splat utility 291 assigned to Return key 29 tb utility 295 compared with trace command 44, Options menu 20 21 46 47 optloop option, global optimizer 335-336 definition 29, 39 optrdepth option, global optimizer 336 examples 47, 168 optsize option, global optimizer 336 integer parameter 47 opttime option, global optimizer 336 syntax 46, 168 357 Index profile scripts quit option, scmsg utility 255 See also cprinit file quotes, double (" ") suppressing execution with -noprofile defining aliases 90 option 79-80 hiding macros 92 program counter-relative addressing surrounding character strings 18 examples 314 using in grep patterns 227 forcing 31] quotes, single ('') program execution, controlling enclosing literals in assembler statement See also debugging programs expressions 303 break command 48-53 surrounding character strings 19 clearing watches and watch breaks 34 continuing execution 30 executing until variable changes value R 33 34 executing up to breakpoints 32 r command, oml utility 252 go command 26, 30, 32, 39-44 -r option proceed commands 29, 46-47 tb utility 295 setting breakpoints 32, 47-53 radix option, opt command 86, 167 single stepping 29, 44-47 range parameter 121 122 stepping into called functions 29 rangelen option, opt command 87, 167 stepping over code 29-30 ranges trace commands 45-46 caution when using variables for setting using watch and watch break commands watches 71 32-33 dumping 62-63 Project menu, scmsg utility 257-259 re-attaching tasks 112 Prototype Generation Options window 267 redirecting output (>) ps command 169 diff utility 219 assembly mode 47 grep utility 224 example 169 lprof utility 242 syntax 46, 169 lstat utility 244 public screen, specifying 80 omd utility 249 public symbol 250 oml utility 251 pull-down menus 20 22 splat utility 291 See also specific menus tb utility 294 list of pull-down menus and command-line REG assembler directive 307 equivalents 20-22 register command 66-68, 171 See also fregister command altering register contents 67-68 Q determining variable values 77 displaying register contents 67 q option examples 171 diffutility 220 syntax 66 67, 171 grep utility 225 register-direct addressing modes 313 smake utility 290 register parameter 122-123 quiet option, break command 52-53, 135 Register window 15, 81 quit command 170 registers quitting the debugger 10, 34 altering contents 67-68 SC_SCMSG AREXX port 263 displaying contents 67 syntax and description 170 effect of opt task command 110 terminating CPRX 100 modifying 110 358 Index registers (continued) splat utility 291 optimizing 329-330 tb utility 295 saving contents before retrieving sample CodeProbe session arguments from stack 317 See CodeProbe sample session scratch registers 318 sample programs relocatable expressions 304 commands for running sample RemTask function 114 programs 36 resident libraries, debugging 105-106 lines.c 25 cautions for setting breakpoints 106, sample program 1 37-39 110 sample program 2 53-56 example 106 sc.examples drawer 25 libraries.cpr AREXX macro 106 saving option settings in scopts utility limitations 106 268-269 setting breakpoints 105 sc command symload command 106 adding addsym option to slink reslib option, opt command 88-89, 167 automatically 8 restart command 172-173 debug=symbolflush option 9, 25 compared with start command 181 link option 9 crashes caused by improper use 26 parameters=register option 319 definition 26, 36 typical usage 9 examples 1 73 SC_CPR 101 running go command before using 30 See also AREXX macros syntax and description 172 SC_SCMSG AREXX port 262-264 restoring previously saved options in scopts scmsg utility 255-265 utility 269 autoedit option 255 results variable, AREXX 103 Build menu 259 return codes available to AREXX macros command options 255-256 103 config=option 255 return command 174 Edit menu 260 Return key for executing proceed format of messages 256-257 command 29 hidden option 255 REXX language Project menu 257-259 See AREXX interface quit option 255 rexxonly command, SC_SCMSG AREXX rexxonly option 256 port 264 syntax and description 255-257 rexxonly option, scmsg utility 256 scopts utility 266-270 rflag command 175 entering options on command line 269 right-Amiga key 23 exiting without saving changes 269 RORG assembler directive 307 gadgets 267-268 run environment 6 restoring previously saved options 269 Run menu 21 saving option settings 268-269 tasks performed by 269-270 windows for setting options 266-267 S scratch registers 318 -screen command-line option 80 -s option script files asm command 326 See cprinit file grep utility 225 See profile scripts oml utility 253 scsetup utility 9, 271-272 smake utility 290 search command 176 359 Index search option, opt command 87-88, 166 addsym option 8, 9 search path 87 88 generating H_SYMBOL hunk 8 searching for expressions stripdebug option 77 See grep utility smake utility 273 290 searching for patterns -a option 289 See splat utility actions performed by 274 SECTION assembler directive 309-310 alternate targets 283 284 definition 307 -b option 289 format 309 -c option 289 specifying addresses 309-310 comments in smakefiles 274 segment lists creating and using default files 288 assigning pointers 113 creating smakefiles 274-276 determining address 112 -d option 289 select command, SC_SCMSG AREXX port default (.def) files 287-288 264 default macros 279-280 semicolon (;) defining transformation rules 280-281 escaping with backslash (\) in echo -e option 289 command 149 -f option 289 expanding alias names 90 fake targets 281-283 preceding with escape character 93 file dependencies, example 275 using in cmd list parameters 50 -h option 290 serial ports -i option 290 using for cross debugging 97, 98 -k option 290 SET assembler direetive 307 local input files 284 286 set eommand 177 178 macros 277-281 .SET fake target 282-283 multiple targets 283 setenv command 11 -n option 290 SetFunction 114 options 289-290 setting up new projects overriding macro definitions 278 See scsetup utility -p option 290 Shell -q option 290 starting across serial line 11 running smake 288-290 shortcut keys 23-24, 29, 34 -s option 290 shortcuts for command names 16 smake.def file 287-288 show [activate] command, SC_SCMSG special symbols 277 AREXX port 264 syntax 273, 289 SigWait field, tasks command 109 -t option 290 .SILENT fake target 283 terminology 273 single stepping through programs 29, -u option 290 44-47 -x option 290 size field, assembly language source line smake.def file 287-288 300 smakefile 273 size suffixes, assembler statements 301-302 source command 78, 180 slash (/) source file second character in Dialog window's title specifying location 77-78 bar 17 source line fields, assembly language sleep command 179 300 301 slink comment 301 adding or stripping debugging label 300 information 7 operand 300 360 Index source line fields, assembly language strcpy function 210 (continued) string parameter 123 operation 300 display command 58 size 300 support for escape characters 123 source modes 83-84 strings, dumping 65 66 assembly mode 45, 46, 47, 83 strings gadget 267 C mode 83 stripdebug option 77 definition 27 strlen function 211 illustrations 26 strlen option, opt command 86, 167 mixed mode 46, 83-84, 336 structures setting 27-28, 83-84 displaying 30-31, 57, 59-60 syntax of opt source command 83 setting watches or watch breaks 71 source option, opt command 83 84, 166 subrange parameter 119, lZ3 124 Source window symbol 7 functions 15 See also debug=symbol option illustrations 26 global symbol information 8 open by default 12, 26 symbol command 183 specifying start-up window coordinates symbol= option, gst utility 238 81 symbol tables, global sourceis option 77-78 See gst utility SPC assembler directive 307 See hypergst utility special keys 23 -symfile option 98 -speed command-line option 97 symload command 112-113, 184 splat utility 291-293 debugging resident libraries 106 -d option 291 definition 107 description 291 examples 184 examples 291-293 syntax and description 112-113, 184 -o option 291 -s option 291 syntax 291 T -v option 291 stack, assembly language programs 317 -t option stack variables 110 oml utility 253 StackPtr field, tasks command 109 smake utility 290 start command 181-182 -t= option, lstat utility 244, 245-248 See also restart command target files, smake utility 273 starting the debugger 25-34 alternate targets 283 284 -startup command-line option 26, 80 fake targets 281-283 State field, tasks command 109 multiple targets 283 state of the machine target machine 7, 96 See environment files required 96 statistics utilities task addresses 111 Iprof utility 242-243 task ID 110 Istat utility 244 248 task option, opt command 107, 110 111, Step Into ResLib option 167 See reslib option, opt command tasks stepping through code See also multitasking programs, See program execution, controlling debugging strcat function 208 displaying current task 89 strcmp function 209 turning task catching on or off 89 361 Index tasks command 109 110, 185 transformation rules for macros, smake Address field 109 utility 280 281 all option 110, 112 trap handling 113 114 Debug field 109 ts command 45, 187 definition 107 TTL assembler directive 308 displaying tasks, example 109 Type field, tasks command 109 examples 185 type parameter 124 finding specific tasks 112 Name field 109 Pri field 109 U SigWait field 109 StackPtr field 109 -u option State field 109 asm command 326 syntax and description 185 smake utihty 290 tb utility 294-296 tb utility 295 description 294-295 unalias command 92, 188 examples 295-296 unassemble command 189 190 -l option 295 unassemble option, opt command 86, 167 -m optlon 295 undefine command 94, 191 -r option 295 underscore (_) -s option 295 replaced by @ sign for compiler 318 syntax 294 -unit command-line Option 97 u option 295 unload option, gst utility 238 -v option 295 user environment 6 -x option 295 utilities temp option, break command 52-53, 135 See specific utilities terminating programs and tasks See also quit command CodeProbe tasks 108 V CPRK and CPRX 99 oml utility 251 -v option scmsg utility 255 grep utility 225 text command, SC SCMSG AREXX port oml utility 253 264 tb utility 295 tool types, adding 78 -V option, grep utility 225 top command, SC _ SCMSG AREXX port variable parameter 125 264 variables trace command 45 46, 186, 187 assembler statement expressions 302 compared with proceed command 44, displaying value and type 32 46-47 dumping 61-62, 75 debugging programs 45-46 verbose option, gst utility 238 definition 39 View menu 21 examples 45 46, 186 integer parameter 45 stepping into a called function 29 W syntax and description 45, 186 trace option, break command 51, 52 53, -w command line option 80 135 -w option traceback information, displaying asm command 326 See tb utility diff utility 220 362 Index wait option, scmsg Project menu 258 where command 110, 198 watch breaks 32-34 window command 199 clearing 34 windowing interface 12-16 creating 33 See also specific windows example 34 functions of CodeProbe windows 14-16 function 70 opening windows 15 marked by exclamation mark (!) 33 screen layout 12-13 setting on structures or arrays 71 windows displayed in scopts utility setting ranges 71 266-267 slow execution while using 33, 72 wlist command 69, 71, 200 static by default 70 wmsg command 201 watch command 70-72, 192 Workbench process, invoking 80 See also wbreak command Workbench screen See also wclear command invoking CodeProbe 11 See also wdisable command running CodeProbe 10-11 See also wenable command specifying with -screen command-line See also wlist command option 80 creating watches 33 specifying with -w command-line option definibon 69 80 examples 192 -wregister command-line option 81 syntax and description 70, 192 -wsource command-line option 81 -watch command line option 81 -wwatch command-line option 81 Watch window displaying watches and watch breaks 69, 70 X functions 15 opening 335 x command, oml utility 252 specifying start-up window coordinates -x option 81 omd utility 249 watches 26, 69 oml utility 253 caution when using variables for ranges smake utility 290 71 stripping debug information 96 clearing 34 tb utility 295 creating 33 using with CPRX 99 dynamic by default 70 XDEF assembler directive 308 function 69-70 defining symbols in data section 309 setting on structures or arrays 71 referencing global data 322-323 -wb command-line option 11, 80 XREF assembler directive 308 wbreak command 70-72, 193 defining symbols in data section 309 wclear command 34, 194 referencing global data 322-323 -wdialog command-line option 81 using with CSECT directive 311-312 wdisable command 195 wenable command 196 whatis command 68-69, 197 Z displaying value and type of variables 32 examples 68-69, 197 -z option, Istat utility 244 syntax and description 68, 197 when option break command 49, 135 go command 40, 42-44, 156 363 Index Special Characters @ (at sign) See at sign (@) {} (braces) ' (single quotes) See braces ({}) See quotes, single ('') \ (backslash character) " (quotes) See backslash character (\) See quotes, double ("") / (slash) See slash (/) = (equals sign) See equals sign (=) [] (brackets) See brackets ([]) . (period) See period (.) < (less than sign) See less than sign (<) + (plus sign) See plus sign ( +) & (ampersand operator) See ampersand operator (&) & (ampersand symbol) See ampersand symbol (&) & (and operator) See and operator (&) ! (exclamation mark) See exclamation mark (!) $ (dollar sign) See dollar parameter ($) See dollar sign ($) (asterisk) See asterisk (*) ; (semicolon) See semicolon (;) ^ (caret) See caret (^) - (hyphen) See hyphen (-) - (minus sign) See minus sign (-) , (comma) See comma (,) % (percent sign) See percent sign (%) _ (underscore) See underscore (_) > (greater than sign) See greater than sign (>) (back-tick character) See back-tick character (') # (pound sign) See pound sign (#)