0% found this document useful (0 votes)
371 views

Linux Ada Programming

Uploaded by

luislupe
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
371 views

Linux Ada Programming

Uploaded by

luislupe
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 360

The Big Book of Linux Ada Programming

The Big Online Book of Linux Ada Programming


An online documentation project over 27,000 lines long. Last Updated: July 20, 2001 Copyright 1999-2001, Ken O. Burtch. All Rights Reserved. Permission given to copy (including photocopying) this document for education purposes provided this notice is kept intact.

Do you want to develop Linux applications twice as fast as the C language? Read on!

Latest version: [ North America/Canada ] Download files: [ .zip HTML ] [ PDF ] Unofficial mirrors: [ Europe/Spain ] [ Asia/Japan ] [ OOP Web ]

Search the Big Book for a word or phrase Special Thanks To Jeff Creem (user stack and errno clarifications) Wilhelm Spickermann (CVS) Leonid A. Timochouk (Florist clarifications) Jrgen Pfeifer (Multithreading information) Bernhard Gubanka (Debugging Pools clarifications) Eric L. Schott, Warren W. Gay, Jean-Marc Bourguet (Adjust vs. C++ Copy Constructors) Jean-Marc Bourguet (C++ exceptions) Warren W. Gay (Ada Streams) Rush Kesler (PDF version) Duncan Sands (Fortran, Elaborate_All) Erik Sigra (Automake)

Search

Talk with the author at [email protected] (remove the "-nospam"). Hosted by PegaSoft Canada. Special thanks to the Ada Linux Team.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (1 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

Table of Contents
i. Preface 1 Introduction 1.1 A Brief History of Linux 1.2 1995: The Year of Ada and Gnat 1.3 Why use Ada? 1.4 Why Ada and Linux? 1.5 Linux Ada Resources 2 Installing Gnat on Linux 2.1 Installing the ALT RPMs 2.2 Installing the ACT Binaries 2.3 Compiling Gnat from its Sources 2.4 Case Study: Installing Gnat 3.11 on over an old Linux Distribution 3 The Integrated Development Environments 3.1 TIA: The Console IDE 3.1.1 Quick Start 3.1.2 TIA Keyboard Legend 3.1.3 The File Menu 3.1.4 The Edit Menu 3.1.5 The Find Menu 3.1.6 The Misc Menu 3.1.7 The Project Menu 3.1.8 The ? Menu 3.2 GRASP-the X windows IDE 3.2.1 Installation 3.2.2 QuickStart 3.2.3 The Project Window 3.2.4 The Source File Window 3.2.5 The Button Bar 3.3 Other Tools and IDEs 3.3.1 VAD 3.3.2 Jessie 3.3.3 RAPID 3.3.3 VIDE 3.3.5 GLIDE

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (2 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

4 From Source Code to Executable 4.1 Gnat Filename Conventions 4.2 Writing Your First Ada Program 4.2.1 Writing a Program with an IDE 4.2.2 Writing a Program without an IDE 4.2.3 After Building 4.3 The Three Step Process 4.4 Gnat Compiling Options 4.4.1 Run-time Error Checking 4.4.2 Checking without Compiling 4.4.3 When you have Too Many Errors 4.5 Gnat Binding Options 4.6 Gnat Linking Options 4.7 Gnatmake Options 4.7.1 So you changed the comments ?

5 Building Large Projects 5.1 Make: the Traditional Project Builder 5.1.1 A Simple Ada Makefile 5.2 Cook: A Parallel Make 5.2.1 Cooking in Parallel 5.2.2 A Simple Ada Cookbook 5.3 Automake and Autoconf: UNIX Portability

6 Development Utilities 6.1 Saving Time with Gnatstub 6.2 Crossreferencing with Gnatxref 6.3 Eliminating Dead Code with Gnatelim 6.4 Execution Stack & Memory Leak Detection 6.5 Conditional Compiling with Gnatprep 6.6 Profiling with gprof 6.7 Shared Libraries Using GnatDLL 6.8 Source as Web Pages Using GnatHTML 6.9 GnatFIND

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (3 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

7 Optimizing Your Project 7.1 Compiler Optimization Options 7.2 Gnat Source Optimization Options 7.3 CPU Optimization Options 7.4 What Differnece Does Optimization Make? 7.5 Working with the Assmebly Source

8 Debugging Your Project 8.1 Limit and the Heap Size 8.2 The Debugging Pragmas 8.3 Identifying Files 8.4 Compiler Info with -gnatG 8.5 Floating Point Numbers 8.6 Gdb: The GNU Debugger 8.7 Code Restrictions

9 Team Development 9.1 Change Logs 9.2 RCS: Revision Control System 9.3 CVS: Concurrent Versions System 9.4 Creating Transcripts with Script 9.5 Timing Execution with Time

10 An Introduction to Ada 10.1 Your Main Program 10.2 Text_IO 10.3 Fundamental Data Types 10.4 Type Attributes 10.5 Operatiors and Expressions 10.6 Variable Declarations 10.7 New Types 10.7.1 Modular Types 10.7.2 Text_IO and New Types 10.8 Aggregate Types
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (4 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

10.9 Enumerated Types 10.10 Procedures and Function 10.11 Flow of Control

11 Advanced Ada Programming 11.1 Packages 11.2 Controlling Elaboration 11.2.1 First line of defense: Pure, Preelaborate and No_Elaboration_Code 11.2.2 Second line of defense: Elaborate, Elaborate_Body, Elaborate_All 11.2.3 Other Elaboration Pragmas 11.3 Objects 11.4 Objects with Automatic Initialization/Finalization 11.5 Multiple Inheritance 11.6 Private Objects 11.7 Generics 11.8 Exceptions 11.9 Dynamic Allocation 11.10 Callbacks 11.10.1 Storage Pools 11.10.2 Access Parameters 11.11 Multithreading 11.11.1 FSU vs. Native Threads 11.11.2 Tasks 11.11.3 Task Types 11.11.4 Protected Items/Types 11.12 Ada Text Streams 11.13 Pragmas 11.14 Low-Level Ada

12 Standard Gnat Packages 12.1 Standard String and Character Packages 12.2 Advanced Input/Output 12.2.1 GNAT.IO 12.2.2 GNAT.IO_Aux 12.3 Sequential_IO 12.4 Direct_IO 12.5 Formatted Output 12.6 Calendar Package

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (5 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

12.7 Tags Package 12.8 Tables 12.9 Hash Tables 12.10 Bubble and Heap Sorts 12.11 Regular Expressions 12.12 Advanced String Processing 12.13 GLADE Distributed Processing [not finished] 12.14 Basic Math Packages 12.15 Exception Handling and Traceback Packages

13 Linux Introduction 13.1 Introduction to Processes 13.1.1 Parents, Children and Families 13.1.2 Ownership and Permissions 13.2 Using System and OsLib.Spawn 13.3 The Linux Environment 13.4 Standard C Libraries 13.5 The Linux Kernel 13.5.1 Kernel Calls 13.5.2 Devices 13.5.3 Proc File System 13.5.4 AudioCD: An Example Program 13.6 Standard Input/Output/Error 13.8 Linux Binary Formats 13.9 Linux Libraries 13.10 Libc5, Libc6 and Upward Compatibility 13.11 Linux Basics

14 Linux Programming 14.1 Gnat OS Library 14.2 Installing Binding Packages 14.3 Catching Linux Signals 14.4 Working with the Command Line 14.4 Linux Environment Variables 14.6 GNAT.Directory_Operations Package 14.7 GNAT.Lock_Files Package

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (6 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

15 Free Ada Bindings 15.1 Using Florist, a POSIX binding 15.2 Using Texttools 15.2.1 Installation 15.2.2 Introduction 15.2.3 Package Overview 15.2.4 Window Overview 15.2.5 Other Useful Window Manager Subprograms 15.2.6 Alerts 15.2.7 Other Predefined Windows 15.2.8 Control Overview 15.2.9 OS Package 15.2.10 UserIO Overview 15.2.11 Appearance and Keys 15.3 Using Ncurses [not finished] 15.4 Using GTK+ Widgets [not finished] 15.5 Using Motif Widgets [not finished] 15.6 Using the TASH TCL Binding [not finished 15.7 Using the Mesa/OpenGL Binding [not finished] 15.8 Engine_3D [not finished]

16 Advanced Linux Programming 16.1 Writing Your Own Bindings 16.2 Linux Errors and Errno 16.3 The Linux Clock 16.3.1 Basic time functions 16.3.2 Timeval Calls - Microsecond Accuracy 16.3.3 Functions Using the tm Record 16.3.4 Time as a String 16.3.5 Timer Functions 16.4 Process Information 16.4.1 Ownership 16.4.2 Other Functions 16.5 Environment Variables 16.6 Multitasking 16.7 Linux File Operations 16.8 Opening and Closing Files 16.9 Directories

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (7 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

16.10 Stdio Files 16.11 Stdio Pipes 16.12 Memory Management 16.13 The Virtual Consoles 16.14 Making Database Queries 16.14.1 mySQL [not finished] 16.14.2 PostgreSQL [not finished] 16.15 Dynamic Loading [not finished] 16.16 A Word on Device Drivers 16.17 Linux Sound 16.17.1 Detecting a Sound Card 16.17.2 Playing Sound Samples 16.17.3 Using the Mixer 16.17.4 Recording Sound Samples [not finished] 16.18 Audio CDs 16.19 Kernel Pipes [not finished] 16.20 Shared Memory [not finished] 16.21 Message Queues [not finished] 16.22 Semaphores [not finished] 16.23 Sockets 16.24 Memory Management 16.25 Exit Procedures

17 Moving C Programs To Ada 17.1 c2ada: Translating Your Programs 17.2 Interfaces.C package 17.3 Interfaces.C.Pointers package 17.4 Interfaces.C_Streams package 17.5 Ada and C Files 17.6 A Word on Interfaces.Fortran

18 Data Structures 18.1 Using the Booch Components 18.1.1 Containers 18.1.2 Iterators 18.1.3 Single linked Lists 18.1.4 Double linked Lists 18.1.5 Bags
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (8 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

18.1.6 Sets 18.1.7 Collections 18.1.8 Queues 18.1.9 Stacks 18.1.10 Deques 18.1.11 Rings 18.1.12 Maps 18.1.13 Binary Trees 18.1.14 AVL Trees 18.1.15 Multiway Trees 18.1.16 Graphs 18.1.17 Smart Pointers 18.1.18 Booch Multithreading

19 Specialized Topics 19.1 Ada Meets Java 19.1.1 The Java Virtual Machine [unfinished] 19.1.2 JGNAT [unfinished] 19.2 ASIS [unfinished]

20 Developing Your Project 20.1 The Project Proposal 20.2 The Design Phase 20.3 The Development Phase 20.4 The Alpha/Beta Release 20.5 Releasing Your Software 20.5.1 A Third Party Library 20.6 Distribution Formats 20.6.1 RPM: Red Hat Package Manager [not finished] 20.6.2 TGZ Packages 20.6.3 TAR.BZ2 Packages 20.6.4 Other Formats 20.7 Man Pages 20.8 Linux Software Map Entry 20.9 Licensing Options

Appendices
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (9 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

Appendix A: The Linux Shell Appendix B: Linux Error Codes Appendix C: Linux Kernel Calls Appendix D: Signals Appendix E: Ioctl parameters Appendix F: Overview of Gnat Packages Glossary

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/book.html (10 of 10) [7/20/2001 11:22:56 AM]

The Big Book of Linux Ada Programming

i. Preface
I've been working with Linux since kernel 0.97 and with Gnat since version 2.00. In the past five years or so, I've been frustrated by the lack of documentation on Linux Ada programming. Gnat is one of the most powerful development environments for Linux, certainly superior to C or C++, and yet most people have never heard of it. Those that have often ignore it because they can't find enough documentation to install Gnat, let alone to evaluate it. After my article "Gnat: C++ and Java under Fire", published in the October 1998 edition of Linux Journal, I decided to collect my knowledge of Linux Ada programming and set down what I've learned: from installing Gnat to interfacing with the Linux kernel. I wanted to create a book that had everything I needed in one place to write professional Linux applications. After publishers declined to put it in print because Ada developers are a small (though growing) niche in the Linux market, I decided to publish it online so that the facts about Linux Ada programming would be understood. This document covers basic software development on Linux, a review of the core Ada 95 language, and an introduction to designing programs that work with the Linux kernel and standard C libraries. It also covers some of the Ada bindings that exist for packages like Motif, TCL and GTK+. This book tries to describe Linux specifics whenever possible. This is not another UNIX book recycled with the word "Linux" substituted in. Although many Ada basics are covered, this document assumes the reader is familiar with a high-level programming language such as BASIC, C, C++, Java . Borland Delphi programmers will notice similarities between Delphi and Ada. Because C is the dominant language in the Linux world, the differences between C and Ada are hilighed throughout the text. The document is designed to be used as a reference after it's been read, with many tables and examples covering common Linux programming problems. Although this book covers a lot of material, it is not intended as an exhaustive survey of Linux Ada programming.Linux is in a constant state of development. Refer to your Linux documentation for the latest information and newest features. Also, Ada 95 has several application specific and portability features which are not covered since they are not related to general Linux Ada programming. Because of the fast pace of Linux development, information in this document may be obsolete, or (to paraphrase Douglas Adams) apocryphal or wildly inaccurate. However, most of the facts have been verified against Gnat 3.11 (or a later version), and most of the examples in this document have been compiled under Gnat. Ken O. Burtch, September 1999

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/0-ii-pref.html [7/20/2001 11:28:01 AM]

Big Online Book of Linux Ada Programming - 1 Introduction

1 Introduction
Table of Contents Next Chapter-->

[Rewrite & Expand] Ada 95 is arguably the most powerful development language available for Linux, with features comparable to Java and execution speeds similar to, and sometimes exceeding, C. gnat, the main [perhaps only'check at HBAP?--KB] Ada 95 compiler for Linux, is also absolutely free. This makes a combination that's hard for Linux programmers to ignore.

1.1 A Brief History of Linux


The Linux operating system that was created as a hobby by a young student, Linus Torvalds, at the University of Helsinki in Finland. Linus, interested in the UNIX clone operating system Minix, wanted to create an expanded version of Minix with more capabilities. He began his work in 1991 when he released version 0.02 and invited programmers to participate in his project. Version 1.0 was released in 1994. The latest version is 2.4 and development continues. Linux uses GNU General Public License (GPL) and its source code is freely available to everyone. Linux distributions, CD-ROMs with the Linux kernel and various other software ready for installation, do not have to be free, but the Linux source code must remain available. Making source code available is known as 'open source'. The word "Linux" is properly pronounced using a Swedish accent, making it difficult to pronounce in North America. It is most often pronounced with a short "i" and with the first syllable stressed, as in LIH-nicks, but it is sometimes pronounced LYE-nicks (the anglicized "Linus' UNIX") or LEE-nucks. Strickly speaking, Linux refers to the operating system kernel that starts and manages other programs and provides access to system resources. The various open source shells, compilers, standard libraries and commands are a part of another project called GNU. The GNU project was started by the Free Software Foundation (FSF) as an an attempt to create a free version of UNIX. The main Linux C compiler, gcc, is a part of the GNU project. There is also a GNU kernel project, but this has been largely superseded by the Linux kernel. X Windows is also not strictly a part of Linux. Xfree86, the free version of X Windows, was adapted to the Linux operating system.

1.2 1995: The Year of Ada and Gnat


In 1974, the US Department of Defense realized it was spending too much on software. They wanted a new computer language that could handle all of their needs, from controlling the hardware in a missile guidance system to doing artificial intelligence. In 1983, they created the language Ada (now known as Ada 83), a heavily modified version of the Pascal language. "Ada", a proper name, refers to Countess Ada Lovelace
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/1.html (1 of 5) [7/20/2001 11:28:29 AM]

Big Online Book of Linux Ada Programming - 1 Introduction

(1815-1852), considered by some to be the world's first programmer. The original Ada had several shortcomings in the areas of software engineering: Ada programs tended to be big and awkward to maintain over time. In 1990, ANSI began a project to revise Ada, to include object oriented features, hierarchical program libraries, support for other languages, and add-ons for specialized applications like systems programming, real-time systems, distributed information (client/server) systems and scientific programming. The updated language is known as Ada 95. GNAT is a GPL Ada compiler, available for Linux, Windows NT, and many other platforms. It was originally created at New York University. GNAT is owned by Ada Core Technologies (ACT, http://www.gnat.com): although gnat is free, companies who want support can purchase it for a fee. The Linux version of GNAT supports the entire Ada 95 standard, including all optional features. It includes many extensions, like cross-compiling and support for the C++ language. ACT also provides GLADE, a free RPC-based TCP/IP networking implementation Ada 95's distributed systems annex. The GNAT manual describes their compiler as "an industrial-quality Ada 95 compiler, integrated into the GCC retargetable compiler system. GNAT is a complete compiler, validated on several platforms, that includes support for all the Ada 95 annexes specified in the Ada Reference manual. Because of its integration into the GCC system, GNAT is available on a large number of hardware/operating system platforms, and can be used as a cross-compiler from any of its targets to any other one. Because of the common code-generator technology of GCC, GNAT has excellent support for multi-language programming: Ada, C, C++, Fortran, etc. GNAT also represents a substantial improvement in Ada compilation technology. It's [sic] open-system philosophy stands in contrast with the opaque approach of older Ada compilers. There are no hidden and complex central libraries whose use requires a totally new set of commands, and no rigid development environments that often force needless recompilations. While preserving all of Ada's safety, GNAT's source-based model provides the flexibility and efficiency typically encountered in C development environments. Furthermore, GNAT's flexibility greatly facilitates its integration within third-party development environments and CASE tools. A number of standard editors, debuggers, profilers, memory analyzers, test coverage or configuration-management tools, etc. can be used with GNAT, which coexists comfortably with familiar programming tools (unlike older Ada compilation systems)." Fun Fact: When Gnat 3.11p was released, Robert Dewar said that Linux would never be a billion dollar platform and deserved no special consideration by ACT. By the time Gnat 3.12p was released just over a year later, the Red Hat company was worth more than 18 billion dollars, or 40% of the server market. The first platform supported by Gnat 3.12p was Linux.

1.3 Why Use Ada?


C and C++ represent the de facto standard for Linux programming. After all, the kernel itself is written in C. However, C++ is not suitable for all kinds of projects because different computer languages have different strengths and weaknesses. Ada was designed for team development and embedded systems, leading to advantages over C in development time and debugging. An in-depth 1995 study by Stephen F. Zeigler (http://www.adaic.com/docs/reports/cada/cada_art.html) showed that development in Ada costs about half that of C++. It also suggests that Ada produces "almost 90% fewer bugs for the final

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/1.html (2 of 5) [7/20/2001 11:28:29 AM]

Big Online Book of Linux Ada Programming - 1 Introduction

customer". GNAT was developed closely with gcc, the native C compiler for Linux. Unlike some compilers that translate a program into C and then feed the C program into gcc, gcc has built-in support for the Ada language. Like g++, the GNU C++ compiler, gnat works with gcc, allowing it to produce fast, quality executables without any intermediate steps. This integration gives a lot of flexibility to programmers who want or need to support multiple languages. GNAT has an extensive set of features for trading variables and function calls between Ada and C/C++. It can import C/C++ items into Ada, export Ada items to C/C++. You can also link Ada functions indirectly into Java, using Java's ability to import C++ functions. GNAT comes with over 140 standard libraries. These include numeric and string libraries, file operations, hash tables and sorts. If you would rather work directly with Linux C libraries, a variety of "binding" libraries exist, available for download from the Public Ada Library or The Home of the Brave Ada Programmers. These include bindings for POSIX (that is, the Linux kernel), X Windows, Motif, TCL and WWW CGI applications. The Ada Linux Team prepackage many bindings for use with their version of the Gnat compiler. More and more Linux libraries feature Ada bindings, including ncurses (a standard text screen drawing library) and GTK (the Gimp Toolkit, a graphics package). Although gnat is distributed under the GPL license, gnat and its libraries may be used in commercial applications. The GtkAda mailing list is at http://gtkada.eu.org. The Gnat mailing list is at http://www.diax.ch/users/gdm/gnatlist.htm. The Gnat Glade chat mailing list is at [email protected].

1.4 Why Ada and Linux?


Ada provides a number of important features for Linux programmers: q Fast Executables - the GNAT compiler produces executables using the same code generator as gcc. q User Friendly - Ada is easy to learn and use, making it a popular choice for introductory computer science courses. Its source code is much easier to read that C, C++ or Java. q Standardized - Ada compilers adhere to a strict standard making Ada programs reliable and portable. Even Java hasn't been standardized. q Flexibility - Ada has many specialized design features that address issues usually ignored by other languages, such as real-time applications, safety-critical software, and low-level hardware access. q Faster, Cheaper Development - As the previously mentioned Zeigler study shows, Ada programs tend to have fewer errors that C++ programs. This means you can get your work done faster with less time and money spent on debugging. q Scalability - Ada is designed for embedded systems and team projects, making it an ideal choice for large projects. This same scalability, and the object oriented features of the language, make the
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/1.html (3 of 5) [7/20/2001 11:28:29 AM]

Big Online Book of Linux Ada Programming - 1 Introduction

source code prone to a longer lifespan. Ample Libraries - The GNAT compiler comes with many general purpose libraries, and bindings exist for most of the key Linux libraries. Open Source Friendly - Ada's readability and scalability make it an ideal language for open source development. Child packages, for example, make it easy to extend someone else's work without affecting the original source code.

1.5 Linux Ada Resources


There are a variety of resouces on the Internet for Linux Ada development. One important resource is the comp.lang.ada newsgroup, which is frequented by many Ada celebrities, including Robert Dewar of Ada Core Technologies and Tucker Taft, the principle designer of Ada 95. If you have questions about the inner workings of Ada 95, this is the place to go. Ada Linux Team (ALT) is a group of programmers dedicated to Linux programming specifically using Ada. This site is located at www.gnuada.org/alt.html . They provide the latest versions of software and libraries for Linux, including bug fixes for Gnat, prepackaged and ready for installation. The GNU Ada site, www.gnuada.org, is a site for all things related to Gnat, not only Linux Gnat development. The Ada Source Code Treasury at www.adapower.com provides examples of both Linux and Windows Ada applications. Included are examples of sockets, MD5 encryption and packages to work with Windows servers from a Linux computer.It also has a free, unsupported binding to Motif by Itermetric/Avestar. If you are looking for general algorithms and source code examples, PAL (the Public Ada Library), is a large source code repository located at www.monmouth.edu/faculty/conn/webproj/ppt2/ . It includes thousdands of source code examples, bindings, compilers and the official Ada 95 documentation. The Ada Software Engineering Library has over 1 Gig of files. It's available at http://unicoi.kennesaw.edu/ase/index.htm. The Home for Brave Ada Programmers at www.adahome.com provides a lot of general reference material and bindings. The Ada Information Clearinghouse (AIC) at www.adaic.com contains statistics, studies and other general information. http://www.skinner.demon.co.uk/aidan/programming/libra has a tool called Libra (Library of Reusable Ada Code) for many common data structures such as lists, queues, and Internet sockets such as HTTP and POP3. http://www.ainslie-software.com has a tool called AdaJNI (Java Native Interface) that lets you call java methods from Ada 95. Table of Contents
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/1.html (4 of 5) [7/20/2001 11:28:29 AM]

Next Chapter-->

Big Online Book of Linux Ada Programming - 1 Introduction

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/1.html (5 of 5) [7/20/2001 11:28:29 AM]

Big Online Book of Linux Ada Programming - 2 Installing Gnat on Linux

2 Installating Gnat on Linux


<--Last Chapter Table of Contents Next Chapter-->

Gnat is a part of the gcc project. The gcc command itself isn't a compiler: it's a program that determines the kind of source file you have and runs the appropriate compiler for you. For example, the Ada compiler is called gnat1, and the C compiler is called cc1. When gcc detects an Ada source file, it runs gnat1 to compile it. Because gcc and Gnat must work as a team, specific versions of Gnat are created for specific versions of gcc. Gnat 3.10p is compiled against the gcc for kernel 2.0.29 (for example, the version of gcc used in the Slackware 3.2 distribution). Gnat 3.11p, 3.12p and 3.13p are compiled against gcc 2.8.1.

To find out which version of gcc you have, run gcc with the -v switch. The standard Gnat distribution from ACT comes with its copy of the correct version of gcc and can install Gnat and its gcc in a separate directory. The binary versions from ACT's web site have C++ support removed, so if you want gcc to support C++ and Ada simultaneously, you'll have to recompile gcc and Gnat from their sources.

It is possible to install one version of gcc overtop of another and to select one version or the other using the gcc -V switch, but gcc must again be recompiled from its (newest) sources to make it aware of the other version. There are patches available via the ALT web site for compiling gnat from the sources for the egcs compiler instead of gcc. egcs (pronounced "eggs") is a variation of gcc designed specifically for Pentium computers. Egcs is based on gcc 2.8.0. Slackware 3.6, for example, used egcs. The egcs optimizations are being merged with gcc for the upcoming release of gcc 3.0. ACT has announced plans to fold Gnat into the Gcc project for Gcc 3.1 and have moved some of their discussions to the gcc mailing list.

2.1 Installing the ALT RPMs


The Ada Linux Team version of Gnat is available from their web site. Versions exist for the Red Hat, S.u.S.E. and Debian distributions. They may also work on the Mandrake and Caldera distributions. The ALT versions include support for ASIS, GLADE and native Linux threads. The package includes gnatgcc, a version of gcc with Gnat and C++ support, and gnatgdb, a version of gdb that supports Ada source code, plus gnatprep and the other Gnat utilities.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/2.html (1 of 4) [7/20/2001 11:30:05 AM]

Big Online Book of Linux Ada Programming - 2 Installing Gnat on Linux

The rpm files are built for Red Hat and S.u.S.E. distributions. If you try installing it on another distribution, use --nodep to ignore any package dependency warnings. 1. Download and read the readme file. 2. Download the gnat-3.xxp-runtime* rpm file (where xx is the current version of Gnat and * is the rest of the filename). For older RPMs, this is gnat-3.xxp*. 3. Download the gnat-3.xxp rpm file. For older RPMs, this is gnat-3.xxp-devel*. 4. rpm -i gnat-3.xxp-runtime* 5. rpm -i gnat-3.xxp* 6. Download and install any of the additional Gnat packages you need The rpm files on the ALT site are configured to work with the ALT version of gnat. To install them, simply download them and run rpm with the -i switch. The ALT GNAT build system is available for those wanting to know more about how the RPMs are constructed. Using CVS, you can check our the source code. export CVSROOT=":pserver:[email protected]:/var/cvs" cd $HOME cvs login # (use empty password) cvs -z9 co -d ALT gnuada/alt-build

2.2 Installing the ACT Binaries


The latest version of the Gnat compiler is available from the ACT FTP site. These binaries do not have the extra features available with the ALT RPMs, but they include extra installation information, including how to install Gnat's various add-ons. There are also versions for other operating systems besides Linux.

Gnat 3.12 and older have an additional install option to overwrite you're existing copy of gcc, provided it is right version. Since it is rare that a distribution has the exact same version of gcc, this option is no longer provided. ACT will sometimes release several versions of Gnat for different C libraries. When downloading the binaries, make sure that you download the version compiled against the appropriate C library. This is due to the constantly evolving nature of Linux.

To find out which libc library your distribution uses, examine the /lib/libc.so link to find out which file it points to. For example, if /lib/libc.so points to a libc5 library, then you'll need the libc5 version.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/2.html (2 of 4) [7/20/2001 11:30:05 AM]

Big Online Book of Linux Ada Programming - 2 Installing Gnat on Linux

The latest public version from ACT is 3.13p, which has been compiled for gcc 2.8.1. By default, Gnat is installed in a /usr/gnat subdirectory. If you don't have gcc 2.8.1, you can specify a separate directory where gnat will install itself and its own personal copy of gcc 2.8.1. Using this method, you need to perform an additional step. The installation program (doconfig) creates a shell script containing environment variables that you can copy to your shell startup script (under bash, this is usually the .profile file in your home directory). Gcc uses these variables to locate the gnat files. You will need to include the gnat directory in the front of your PATH variable to prevent gnat from using the gcc that came with your Linux distribution. For example, use the shell command: export PATH="/usr/gnat/bin:$PATH" Only use this command when you want to use Gnat since it effectively hides the copy of gcc that came with your distribution. If you don't want gnat to be enabled by default, you can write a short shell script that assigns the environment variables, sets the path, and starts a new shell.

2.3 Compiling Gnat from its Sources


Occasionally you may want to compile Gnat yourself from its sources. For example, q you may want to learn more about computer language design q you may want to enable support for other languages (e.g. C++) q you may want to make libgnat a shared library q you may want to upgrade gnat for the newest C libraries q you may want to change the multithreading model In order to recompile Gnat, you'll need the following: 1. A copy of the gcc sources in order to build a copy of gcc that's compatible with Gnat. The required version is listed in the Gnat documentation. 2. A copy of the gnat sources. The sources are available for download from the gnat download site and its mirrors. [I should compile gnat and make notes and flush out the details more--KB] First, you need to recompile the gcc compiler. Make sure you follow gcc's instructions for activating Ada support. make CFLAGS="-g -fsigned-char" LANGUAGES="c c++ ada" make stage1 make CC="stage1/xgcc -Bstage1/" CC="-g -O2 -fsigned-char" STAGE_PREFIX="stage1/" LANGUAGES="c c++ ada" <build tools and lib with CC="./xgcc -B./"> There are two problems that can arise: 1. The standard C library may have changed. 2. The souce code for the gcc compiler itself may have changed. Changes to the C library rare unless the library is several generations out of date. Even so, by consulting the man pages you can usually find out the new parameters the various C functions expect. Upgrading gcc to a new version of gcc, however, can be difficult. Gnat's gcc patches are designed for a specific version of gcc. It is usually a good idea to get a copy of the source code for the version of gcc Gnat was designed for and
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/2.html (3 of 4) [7/20/2001 11:30:05 AM]

Big Online Book of Linux Ada Programming - 2 Installing Gnat on Linux

compile a second gcc compiler just for use with Gnat. For gnat 3.13, you'll need the gcc 2.8.1 source code. You should be able to compile an older version of gcc to work with newer C libraries, provided the compiler is only a few months out of date. Now follow the directions to compile Gnat. Make sure libgnat.a is accessible to the linker. If it isn't, copy it to /usr/lib and run ldconfig to update Linux's shared library tables. [More here - KB]

2.4 Case Study: Installing Gnat 3.11 on over an old Linux Distribution
We installed Gnat 3.11p on a Pentium running a Slackware distribution with egcs and lib6. We wanted to replace egcs with gcc 2.8.1 and install the Gnat binaries (compiled for 2.8.1) over top. We first went to the Sunsite mirror which provides Linux compiled binaries of gcc, ready to be unpacked and installed Unfortunately, the readme file reported they had trouble compiling gcc and supplied egcs instead. egcs is based on gcc 2.8.0 which meant that we couldn't use it with gnat 3.11. Instead we downloaded the gcc 2.8.1 source code from a GNU FTP mirror site and prepared to build the compiler from scratch. 1. We ran Gnat doconfig program and select option 1. The gcc path that it's expecting is displayed as i686-pc-linux-gnu. This was going to be our configuration host setting for gcc. 2. We followed the instructions in the gcc INSTALL file. configure --with-gnu-as --with-gnu-ld --enable-threads=posix --host i686-pc-linux-gnu 3. We checked the gcc makefile to make sure i686-pc-linux-gnu was reasonable. It required lib6 and lib6 was installed. The Makefile also showed that the i686 setting is compatible with our Pentium (i586). 4. Before running make, we changed the Makefile's OLDCC variable from cc to /usr/bin/gcc. There was a cpp syntax error while building libgcc1.a, probably the error the Slackware people encountered. We tracked down the line causing the problem in the Makefile and discovered they were calling cc to do the compiling, which doesn't handle the C preprocessor (cpp) properly. Typing in the line at the shell prompt showed that /usr/bin/gcc worked fine while /usr/bin/cc would not. The note in the Makefile said we shouldn't use gcc to avoid circular references in some of the functions (that is, that it might inadvertantly call the 2.8.1 compiler instead of the old 2.7.2.3 compiler), so we made sure we included the full path. 5. make LANGUAGES="c c++" 6. mkdir stage1; make stage1 make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O2 -fsigned-char" 7. mkdir stage2; make stage2 make CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O2 -fsigned-char" 8. make compare reported no errors. 9. make install CC="stage2/xgcc" -Bstage2/" CFLAGS="-g -O2" LANGUAGES="c c++" 10. gcc -v and gcc -dumpversion reported the correct version. We deleted the old /usr/lib/gcc-lib/i486-linux directory to save some space. 11. We installed gnat by running doinstall If we were doing C++ programming, we would need to install the standard C++ library, libstdc++, as well. In this case, we enabled C++ support to avoid recompiling gcc for C++ in the future. <--Last Chapter Table of Contents Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/2.html (4 of 4) [7/20/2001 11:30:05 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

3 Introduction to the IDE's


<--Last Chapter Table of Contents Next Chapter-->

There are two IDE's, or Integrated Development Environments, available for gnat and Linux. PegaSoft's TIA (Tiny IDE for Ada) is a text-based IDE, while GRASP is an X-Windows IDE. Both have similar basic features. On the other hand, if you are looking just for text editors with Ada syntax hilighting, many exist for Linux including elvis, emacs/xemacs and nedit.

3.1 TIA: The Console IDE


TIA, Tiny IDE for Ada, is a console IDE for Gnat. Besides being my own program, it was written using Gnat runs using the GPL texttools packages described later in this document. The screen layout is similar to pico's, with the menu options displayed along the bottom of the screen. If you are running on the Linux console or a xterm window, you can choose the menu items with alt key combinations or using your mouse.

This IDE is designed for rapid Ada development.To meet this goal, it uses a number of interesting features: q a ddd style debugger q automatic saving - whenever you open a new source file, tia saves your old file q quiet updates - each time a file is saved, TIA will attempt to recompile the file, to reduce the project rebuilding time.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (1 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

q q

TIA will only update one file at a time to avoid slowing down your machine. automatic spelling correction - When you press return/enter while editing your source file, TIA automatically corrects common spelling mistakes for any of the following words or phrases: procedure, function, package, exception, subtype, "end if;", "end loop;" , "end record;". error hilighting - you can move between compiler errors with a single keypress, and the cursor is automatically positioned at the exact location of the error and the message displayed at the bottom of the window. quick open - you can open recently opened files with a single keypress tight integration with gnat - for example, you can load a package spec and create a body using gnatstub by simply selecting Stub in the File menu. support for keyboard macros

If you are interested in an X Windows IDE, you should read the next section on GRASP.

3.1.1 Quick Start


Before you compile a program, you have to set up the project parameters under Proj. For simple, single file programs, put the name of the program in the main line and select your CPU type. TIA will save this information when you quit in a ".adp" file (Ada Project). You can check the current file with Check. If there are errors, use Err to move to the place where an error occurred and the error message will appear on the bottom of the screen. Repeatedly use Err to fix all errors. Note that as you edit the program, such as adding or deleting lines, Err may not take you to the exact line because the lines have moved. Build your project with Build and you're ready to run your program.

3.1.2 TIA Keyboard Legend:


These are the key functions in TIA. If you are running TIA under X Windows, the X window manager may use some of these key combinations for its own purposes. Control Keys Control-6 - Mark/Unmark Control-A - Execute macro (follow with the key for the macro) Control-B - Copy (single line or to the mark) Control-E - End Control-L - Redraw screen Control-N - Page Down Control-P - Page Up Control-T - Backtab, back one item on screen Control-V - Paste Control-X - Cut (single line or to the mark) Control-Y - Home Navigating The TIA Screen End - last line of text Home - first line of text Page Up - Up One Page Page Down - Down One Page Esc/F1 - TextTools' Accessories Menu Tab - Next Item On Screen Backtab - Previous Item On Screen (note: Linux console doesn't support the back tab key--use control-t) Alt-Char - Jump to the item with hot key Char (Linux Console/xterm) Scroll Bars Keys

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (2 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

Down Arrow - 10% Forward in Document End - Bottom of Document Home - Top of Document Left Arrow - Back one line Right Arrow- Forward one line Up Arrow - 10% Back in Document In TIA, the width of the text is limited to size of the edit area. Any lines that are longer that the edit area are denoted with an ellipsis at the end. The edit area does not scroll left or right as it does in pico.

3.1.3 The File Menu


New Source Start a new source file. Open Source Open a new source code window, or an existing one. Type in the name of the source file and choose open to open it. (.adb is assumed if you don't specify an ending.) Choose browse to walk through the directories using a open dialog box. Or you can chose one of the recently opened files that appear at the bottom. On the Linux console, use alt-# to open these files. Chose new and TIA will create an empty package body for you to fill in--just delete what you don't want. Save Saves the file. TIA automatically saves whenever you check or build. Save As Save As. Save the file under a different name. Revert Reloads the current file, discarding any changes that haven't been saved by you or TIA. (TIA automatically saves a file when a new one is loaded.) Diff Displays the differences between the current file and when it was last saved using the diff command. Print Pipes the file, with a header, to the lpr command, printing it on the default line printer. Stats Display information about the current file and memory usage. Stub Creates an empty package body for the current file. The current file must be a package spec. Check Checks the current file for syntax errors. Xref Displays a crossreference of all identifiers in the current file. Quit Stops the program.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (3 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

3.1.4 The Edit Menu


Cut Deletes the selected text and puts it in the clipboard. Same as ctrl-x. Copy Copies the selected text to the clipboard without deleting it. Same as ctrl-b. Paste Inserts the text on the clipboard. Same as ctrl-v. Append Moves the cursor to the right end of the current line. This is useful for adding comments at the ends of lines.

3.1.5 The Find Menu


Find/Replace Find brings up the find dialog to search for text. Fill in the top line and select find to find the next occurrence of the text in your document. Select backwards to search towards the top of the document instead of towards the bottom. Fill in the replace line and select replace to replace the text you are searching for with new text. Select cancel to erase the find text. Next Next finds (or finds and replaces) the next occurrence of the text in the source code. If the text is not found, TIA beeps. Next Err Moves the cursor to the location of the next error and displays the error message at the bottom of the screen. Goto Moves the cursor to a specific line.

3.1.6 The Misc Menu


Edit Macros Brings up the macro edit screen. Macros are keyboard short cuts you define. Each macro must fit on a line.The first character on the line is the trigger, and the remaining characters are the keyboard keys the trigger represents. For example, a line "pprocedure" defines a macro "p" that represents the keystrokes "p","r","o","c","e","d","u","r" and "e". To use a macro in TIA, press control-A and then the letter of the macro. Options Opens the options window. The first option is to allow background updates. Turn this option off on slow machines. The second option sets the background colour to blue or black on colour displays. Debugger Runs TIA's ddd-style debugger. [Expand--KB] GDB This item runs the gdb debugger.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (4 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

3.1.7 The Project Menu


Project Params The project parameters window. Choose the debugging level, CPU type and optimization level and TIA will pass the information to gnat accordingly. You can specify additional gnatmake options (like -n for no main program in Ada when you want to call Ada subprograms from another language), linking options (such as Linux libraries you need to link to), and the name of the main program. Static binding turns static binding on and off. CPU Options: 486, Pentium, Pentium II, Other Optimize Options: None, Basic, Size, Speed Debugging Options: q Prelease (assert/debug pragma's on, basic and elaboration checks on) q Alpha/Beta (assert/debug pragma's on, basic checks on, no elaboration checks) q Release (assert/debug pragma's off, all non-essential checks off) Project Type: q Program (compile and link project as an executable program q Package (compile, but don't link project since there's no main program) q Static Library ((unfinished) compile and generate a static library file named lib<project>.a) q Shared Library ((unfinished) compile and link a shared library file named lib<project>.so.a) Builder: Specify the name of the program to build the project with, usually gnatmake: q Gnatmake (Gnat's project builder) q Make (Linux's standard project builder) q Cook (an enhanced project builder based on make). Static Linking: select this to link in all the libraries used into a self-contained executable Egcs: select this to run egcs instead of gcc [untested] ALT: select this to compile on a system using the ALT version of gnat Build TIA attempts to build the project and create a working executable file. People To be finished

3.1.8 The ? Menu


This is the About window. It shows information about the current version of TIA, including the version and copyright notice.

3.2 GRASP: The X Windows IDE


GRASP is a free X-Windows IDE that supports Ada 95. It's based on Motif and provides similar basic features to TIA. The main difference is that GRASP is a multi-language IDE and that it supports source code analysis, annotating your source code with Control Structure Diagrams (CSD's) and showing code complexity with graphs called CGP's.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (5 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

Besides Ada 95, GRASP supports C, C++, Java and VHML source files. It supports operating systems other than Linux and can also work with Ada compilers other than gnat. GRASP is available for download from that GRASP home page at http://www.eng.auburn.edu/grasp.

3.2.1 Installation
1. Download a version of GRASP from the GRASP web site. GRASP uses the Motif widget library. The static version has a copy of Motif included with it: download this version of you don't have a Motif compatible library (such as LessTif). If you have a Motif compatible library, download the dynamic version to save disk space. If you are using LessTif, make sure that the libXm and related files are properly linked in /lib and run ldconfig to ensure Linux sees the changes. 2. Move the tar archive to the location you want to install GRASP in. For example, "/usr/local" would be a good choice. 3. Unpack the grasp archive with "tar xfvz". 4. GRASP requires an environment variable called "GRASP_HOME" to be set so GRASP knows where it was installed. To define GRASP_HOME every time for any user, add the following line to the end of your /etc/profile file: export GRASP_HOME=graspdir/graspada export PATH="$PATH:$GRASP_HOME/bin" where graspdir is the directory where you installed grasp (eg./usr/local").
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (6 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

Login in again to make the changes take effect and type "grasp&" to start GRASP. GRASP provides online help. Extensive documentation is provided in HTML format, but it's not lynx browser friendly. You'll have to use a GUI browser like Netscape.

3.2.2 Quick Start


1. 2. 3. 4. 5. Open a new source window using "File / Ada 95...". Type in your program. Save the source file as "test1.adb". Add "test1.adb" to your project by chosing "File / Add to Project" If you are using ALT gnat, change the compiler configuration under "Compiler / Command Setup": 6. 1. Select Compiler / Command Setup. You'll see the list of commands Grasp uses to invoke gnat. 2. Change the Compile and Check commands from "gcc" to "gnatgcc", the name used by ALT. 7. Compile the program by chosing "Compiler / Compile and Link". If there were no errors, the message window will appear with the message "Grasp: operation completed" and no error messages above it.

3.2.3 The Project Window


The first window that appears is the GRASP project window. It contains the word "GRASP", but as you add source files to your project, they will be added to this window. The File Menu Ada 95 et al. - opens a new source file window. Choose a language: Ada 95, C, C++, Java or VHDL. Save all files - saves all open files. Exit GRASP - quits GRASP, closes all open windows. The Project Menu New - start a new project Open - open an exisiting project Close - close current project Save - save current project Create / Save as - save current project under a new name, creating a new project. Open Selected File- opens hilighted source file in the project window Remove Selected Files - deletes these files from the project window Add Files to Project - add source files to the project window The Search Menu - search for files to add to the project The Preferences Menu Colour/Font - change the appearance of the source code window Tab Size - change the number of spaces to indent when the tab key is pressed Generate .gml files - NQS--KB The Window Menu Message Window - opens the GRASP error message window.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (7 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

Search Window - opens the file searching window

3.2.4 Source File Window


This is the window where you type up your Ada programs and packages. The File Menu Clear - erase the entire source file Open - open a new source file Save - save the source file Save as - save the source file under a new name Print - prints the source file to a postscript printer, or to a file to be printed with ghostscript Language - change the source file language. This doesn't translate the file to a new language, but tells GRASP how the file should be hilighted. Exit- closes the source file window The Edit Menu Undo - undoes last edit change Cut, Copy, Paste - standard cut, copy and pasting text Paste Primary - NQS--KB Search / Replace - standard search /replace Comment - turns hilighted text into a comment Uncomment - removes comment marks from hilighted text Convert Keywords to Upper/Lowercase - changes the case of all keywords in the document. Goto Line - goto a particular line Insert File - insert a source file into this one. The View Menu Show Unit Symbols - toggles module symbols in CSD diagram Show Data Symbols - toggles data symbols in CSD diagram Show Boxes - toggles boxes around multiline statements in CSD diagram Intrastatement Align - If on, for statements longer than one line, the second line and onward will be indented to the position of the first open paranthesis. Force Newlines - If on, divides up statements so they will be on separate lines. Auto Line Numbers - toggles line number display in CSD diagram Auto Indent - toggles indentation in CSD diagram Line Numbers - adds line number to CSD diagram corresponding to lines in source code Generate CSD - creates a Control Structure Diagram for source code Remove CSD - removes CSD diagram from source code

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (8 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

Show Controls - toggles button bar at top of edit area Show message Bar - toggles message bar at bottom of window The Templates Menu - insert source code for typical Ada multiline statements. The source code must be edited to fit the current program. The Window Menu - opens various grasp windows The Compiler Menu Make - builds the project using the make command defined in command setup (typically make) Compile and Link - builds the project using gnatmake Compile - compiles the source file without building the project Semantic Check - checks the source code for errors Flag Setup - configures the switches for compiling, linking, etc. Command Setup - configures the commands to compile, link, etc. The Run Menu Run - runs the program using popen Run Previous - runs the last file that was run Run File - runs a particular file Cleanup Session - kills any hung processes.Doesn't affect daemons. The CPG Menu Generate CPG - create a Compilexity Profile Graph Weights - configure the CPG weights

3.2.5 The Button Bar


Auto - automatically rebuild the CSD whenever a major change occurs, such as inserting a template or loading a new file. Generate CSD - same as choosing View/ Generate CSD Font Size - changes the font size

3.3 Other Tools and IDEs 3.3.1 VAD-Visual Ada Developer


VAD is an Ada code generator written in the TCL/TK graphics scripting language. Besides gnat, there are about 10 additional packages you must install before VAD will run. You type in a TCL/TK description of a VAD widget in a text file and VAD will produce all the necessary source code to use the widget. Most graphics formats are supported. VAD is available from http://ada95.freeservers.com/index.html.

3.3.2 Jessie
Jessie is an X Windows IDE for building large projects and designing multiple executables at once. It's an open source project of Silicon Graphics (http://www.sgi.com) and works with multiple languages. ACT has announced that Gnat will provide Jessie support in the future. Jessie is downloadable from http://oss.sgi.com.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (9 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 3 Introduction to the IDE's

3.3.3 Rapid
RAPID is an X Windows GUI Builder that works with TASH (the Ada TCL/TK package). You can draw TCL/TK windows containing Labels, Text Buttons, Radio Buttons, Check Boxes, and other widgets. When you select "Compile", RAPID saves the Ada source code necessary to display using TASH the window you drew. RAPID is available from ALT.

3.3.4 VIDE
VIDE is a C/C++/Java IDE, but it will work with Gnat if configured correctly. However, it doesn't support Ada keyword hilighting.

3.3.5 GLIDE 3.3.6

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/3.html (10 of 10) [7/20/2001 11:30:22 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

4 From Source Code to Executable


<--Last Chapter Table of Contents Next Chapter-->

This section is an overview of creating new programs on Linux.

4.1 Gnat Filename Conventions


Unlike Microsoft Windows, Linux filenames do not require a suffix to indicate the filetype. Nevertheless, Linux files often have suffixes to make it easier to identify the type of files by their names. gnat makes extensive use of suffixes. Here are some filename conventions: q .ads - Ada package specification q .adb - Ada package body or program q .adc - Gnat configuration file (for dead code elimination) q .adt - Gnat tree file (for dead code elimination) q .adj - Defaults for [NQS-KB] q .adp - TIA project file or Gnat gnatxref/gnatfind project file q .cfg - GLADE distributed program configuration file q .ali - debugging and linking information produced by gnat q .xrb - cross-reference file generated by gnatf q GRASP_defaults... - GRASP defaults file, holds your preferences q .gpj - a grasp project file q .gui - a VAD TCL/TK widget description For example, demo.adb would be an Ada program named demo.

You can change the colour used by ls to display these filenames by changing the /etc/DIR_COLORS file. Directions on how to do this are included in the file.

4.2 Writing Your First Ada Program

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (1 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

4.2.1 Writing a program with an IDE:


Start a new project. For example, with TIA type tia hello to create a new project called "hello.adp". Type in the following Ada program. with text_io; use text_io; procedure hello is begin put_line( "Hello World!" ); end hello; This Ada program will print a short message on the screen. Save the file and build the project. If there is a problem with your program, TIA will show you the line number, the position on the line, and an error message describing the problem. If you typed in the program correctly, you should now have an executable file called hello in your directory. TIA will ask you if you want to run your program. Your program should display the message Hello World! before TIA's window reappears.

4.2.2 Writing a Program without an IDE


With a standard UNIX editor such as pico or vi, create the following file called "hello.adb". For example, pico hello.adb Type in the following Ada program. with text_io; use text_io; procedure hello is begin put_line( "Hello World!" ); end hello; This Ada program will print a short message on the screen. When the file is saved, the gnatmake command to build the project: gnatmake hello.adb

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (2 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

If there is a problem with your program, gnatmake will show you the line number, the position on the line, and an error message describing the problem. If you typed in the program correctly, you should now have an executable file called hello. Run the file by typing hello (or ./hello on some distributions) and Linux will respond by displaying the message Hello World!

4.2.3 After Building


After building your project, there should be several files in your directory: q hello.adb - this is the Ada program you typed in. The is called a source file. q hello.o - this is the binary code created by the compiler. This is called an object file. q hello.ali - this is additional information about the program created by gnat. q hello - this is the executable program If you want to clean up your directory, the hello.o and hello.ali are information files and can be safely erased. However, on large project with multiple files, leaving them will speed up the building process.

4.3 The Three Step Process


When you build a project using gnatmake, or when you use an IDE to run gnatmake for you, gnatmake performs three operations: 1. Compiling: gnatmake checks your file for errors. If there are no errors, it creates an object file containing the binary version of your program. If there are any errors in your file, gnatmake stops. 2. Binding: gnatmake verifies that all the files in the project are up to date. If there are files that need to be compiled, gnatmake will compile them as well. 3. Linking: gnatmake combines all the object files to create an executable program. On simple projects, these steps can all be done automatically. However, on some projects with particular requirements, you may need to take special actions during one of these steps. You can perform these separate steps yourself. For example, using the hello.adb program: 1. Compile the program with: gcc -c hello.adb 2. Bind the program with: gnatbind hello.ali 3. Link the program with: gnatlink hello.ali Once again, you have an executable program called "hello".

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (3 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

4.4 Gnat Compiling Options


The version of gcc for gnat has all of the normally document gcc switches, plus some new switches for gnat. You can run gcc by itself, or have gnatmake run gcc for you. Unless otherwise noted, these switches can be applied to both gcc and gnatmake. q -b - For crosscompiling, compile for a target machine q -Bdir Multiple gnats, load the gnat compiler from directory dir instead of the default one q -c - gcc only, tells gcc to compile only and not to try to link with the C linker q -g - create an executable that can be used with the gdb debugger q -Idir - Beside the directory with the first file, check directory dir for more source files q -I- - Do not look for source files in the directory where the first file resides q -On -On Optimize, from 0 (none) to 3 (maximum, automatic internal inlining). See below. q -s - gcc only, create an assembly language source file instead of an object file q -Wuninitialized - warnings on uninitialized variables q -v - show what steps the gcc compiler is performing q -gnata - turn on debugging pragmas. See below. q -gnatb - keep messages brief q -gnatc - check the program, but don't compile it q -gnatdx - activate ACT internal debugging switch 'x', where x is a character q -gnatD - with -gnatG, save debugging info to files ending in .dx q -gnate - display error message immediately instead of waiting until end of compile q -gnatE - turn on dynamic elaboration checks q -gnatf - give more information about errors q -gnatg - turn on gnat style checks q -gnatG - show pseudo-code of how Gnat interprets your source code q -gnatic - use character set c q -gnatkn- constrain file names to n characters q -gnatl - include source code with error messages q -gnatL - C++ exception handling (setjmp/longjmp) q -gnatmn - show no more than n errors q -gnatn - allow inline subprograms across source code in different files q -gnatN - inline as much as possible, even subprograms not marked for inlining q -gnato - turn on checks normally turned off (such as numeric overflow checking) q -gnatp - turn all checks off q -gnatq - don't quit because of errors--compile entire source file q -gnatr - check for reference manual source code layout q -gnatR - listing with alignment info

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (4 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

q q q q

q q q q q q q q q q

-gnats - synatx check only -gnatt - create tree output file -gnatu - list units being compiled -gnatwm - warning mode(s) m. These include r -gnatwa - show all optional warnings r -gnatwA - show no optional warnings r -gnatwc - warnings for always true/false expressions in statements r -gnatwe - treat warnings as errors r -gnatws - suppress warnings r -gnatwl - warnings on elaboration errors r -gnatwu - warnings on unused variables, uninitialized parameters, unused packages r -gnatyk - check indentifier case -gnatx - suppress cross-reference information -gnaty - Impose line length limit, etc. [? - KB] -gnatzm - generate distribution stubs for m -gnatZ - zero-cost exceptions (default) -gnat83 - enforce old Ada 83 conventions -gnat95 - enforce Ada 95 conventions (default) -mno-486 - create an executable that can run on a Intel 386 or newer -m486 - create an executable that can run on a Intel 486 or newer -mcpu=model - compile an executable for the given cpu model -fstack-check - check for stack overflows

The -gnat switches can be combined together, such as -gnatbcs for -gnatb, -gnatc, and -gnats. Many of the GCC switches listed in 4.5 can be used as well. 4.4.1 Run-time Error Checking Ada has extensive checking for run-time errors. By default, gnat turns off some of these checks to improve the speed of the programs. To turn on all error checking, you need to use -gnato -gnatE switches. To turn off all error checking, you need to use -gnatp. IDE: TIA sets these switches for you based on your choices in the project parameters window. 4.4.2 Checking without Compiling In gnat 3.10, if you want to check a source file without actually compiling it, use the gnatf utility. In gnat 3.11 or later, you can use gcc with the -gnatc option to check a source file. IDE: TIA uses -gnatc when you chose File/Check.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (5 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

4.4.2 When you have Too Many Errors When you have so many compiling errors that they run off the top of the screen, you can redirect the errors to a file and list them with the less command by adding the following to the end of your compiling command: "2> temp.out; less temp.out".

4.5 Gnat Binding Options


gnatbind checks the integrity of a project before the linking phase. You can run gnatbind by itself, or have gnatmake run it for you. q -A - (default) generate binder program in Ada. See -C, -x. q -aIdir - besides the directory of the file, search for source files in directory dir q -aOdir - besides the directory of the file, search for .ali files in directory dir q -b - brief messages q -C - generate binder program (in C, not Ada). See -A, -x. q -c - check only q -e - list elaboration dependancies q -E - exception stack traceback (when compiling with -funwind-tables) q -f - use full reference manual semantics in an attempt to find a legal elaboration order q -h - help q -Idir -combination of -aI and -aO q -I- - don't look for source and .ali files in regular places q -l - list the chosen elaboration order q -mn - show no more than m binding errors q -Mn - main program to be called n, not the default name q -n - no main program, for when the main program is written in another language q -nostdinc - (no standard includes) ignore default directory when looking for sources q -nostdlib - (no standard libraries) ignore default directory when looking for libraries q -o file - output to a file name file q -O - list objects q -p - pessimistic - try worst case elaboration order q -r - renames the main program from main to gnat_main q -s - require all source files to be present q -shared - link in Gnat run-time library as a shared library (if available--for example, ALT version) q -static - link in Gnat run-time library statically q -t - ignore time stamp errors q -Tn - tasking time slices are n milliseconds long. n=0 means no time slicing, as per Annex D. q -we - treat warnings as errors

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (6 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

q q q q

-ws - suppress all binder warnings -v - verbose messages -x - check only, ignore source files. Don't generate a binder program. See -s. -z - same as -n [?-KB]

4.6 Gnat Linking Options


gnatlink combines object files together to form a finished executable program. You can run it by itself, or gnatmake can run it for you. q -o file - name of executable file to create q -v - verbose messages q -gnatlink n instead of gcc, use linker named n q -l lib in the specified library

When linking in libraries, the order of the libraries is important. When libraries depend on each other, libraries must be listed before the libraries that they use.

4.7 Gnatmake Options


To compile any Ada program, use the gnatmake command. gnatmake checks all the packages a program relies upon and automatically compiles any packages that need compiling. For example, gnatmake main.adb will compile the file main.adb, automatically compiling all Ada files referenced by main.adb, if necessary. This is unlike other building tools like make and cook because the dependancy of source files is listed in every Ada file by the with statement. make and cook are designed to work with C which has no equivalent statement and requires the programmer to list the dependencies in a separate file. When gnatmake is finished compiling, it will automatically bind and link the program, producing an executable file called main. There are times when you want gnatmake to compile the project, but not to bind or link it. You can tell gnatmake not to link by using the -n option: gnatmake -n main.adb Here is a summary of the gnatmake switches: q -a - consider all files, even read-only source files and standard system files like ada.text_io q -c - compile only q -f - recompile entire project
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (7 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 4 From Source Code to Executable

q q q q

q q q q q q q q q q q q q q q

-jn - on multiprocessor machiens, compile using n processes at once -k - ignore errors, and compile as much as possible -M - create a list of dependences suitable for make's Makefile -i - instead of the current directory, keep intermediate files in directories where their sources are found -m - update dependancies without compiling -n - check dependencies, but don't do anything -o name - save the executable as name -q - quiet - no status messages -s - switch change - recompile if the switches have changed -v - verbose - explain why files are compiled -aIdir - besides the directory of the first file, search directory dir for source files -aOdir - besides the directory of the first file, search directory dir for object and .ali files -Adir - same as -aIdir and -aLdir -Idir - same as -aodir -aIdir -I- - don't look for source files in the directory of the first file -Ldir - besides directory of the first file, look for libraries in directory dir -cargs s - pass switches s to compiler -bargs s - pass switches s to binder -largs s - span>pass switches s to linker (e.g. -largs somefile.o to link in the somefile object file)

4.7.1 So you changed the comments...


Use gnatmake with the -m option, which updates gnat's files without producing a new object code file. Use this to avoid pointless recompilations when all you changed were the comments in a source file. <--Last Chapter Table of Contents Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/4.html (8 of 8) [7/20/2001 11:31:15 AM]

Big Online Book of Linux Ada Programming - 5 Building Large Projects

5 Building Large Projects


<--Last Chapter Table of Contents Next Chapter-->

5.1 Make: The Traditional Project Builder


IDE: TIA supports make. To use make, select it in the project parameters window. Gnatmake is the best tool for building small projects. However, if you have a lot of C functions, you may want to use Linux's traditional project building command, make. The make command interprets a series of rules saved in a file called "Makefile". These rules describe which files are dependent on which other files. Each rule is followed by the command needed to update the files, such as the command to compile them. For example, if you had a Ada program called dbase and it relied on the source files common.adb, scanner.adb and parser.adb, a Makefile might include the rule: dbase: common.o scanner.o parser.o gnatlink o dbase This rule says that the dbase executable file depends on the object files for the 3 Ada source files, and to update dbase make has to link the object files with the gnatlink command. If you are writing an Ada program with C source files, the basic strategy for using make with gnat is to make rules than ensure the C files are compiled properly, and then to finish the project using Gnatmake. Makefiles can have comments and variables and rules that refer to parameters to the make command as opposed to files. The many options can't be covered here.

5.1.1 A Simple Ada Makefile


The following Makefile will compile an Ada program called main.adb, plus any packages used by main. This should work for most small projects. Edit the OBJS variable to include the object files for every package used by your program. To use this make file, type "make" to build your Ada project, or "make clean" to remove any intermediate files produced by the compiler.

The ALT version of Gnat uses uses the name gnatgcc, not gcc, for the GCC compiler.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/5.html (1 of 6) [7/20/2001 11:31:40 AM]

Big Online Book of Linux Ada Programming - 5 Building Large Projects

# Sample Ada makefile # # Assumes main program is named main.adb # # by Ken O. Burtch OBJS = main.o somepackage.o # How to compile Ada files .adb.o: gcc -c $< .SUFFIXES: .adb .o # How to link the main program main: $(OBJS) gnatbind -xf main.ali; gnatlink main.ali clean: rm *.o *.ali core

5.2 Cook: A Parallel Make


IDE: TIA supports cook. To use cook, select it in the project parameters window. cook is a program for building projects. Unlike make, cook has additional features such as the ability to define true variables and functions, and the ability to build a project using multiple machines in parallel. This can be a useful tool for large Ada projects. cook also comes with a tool to convert Makefiles to cook Howto.cook files. If you need to install cook, there are four basic steps are:
q q q q

configure make make sure make install

# # # #

run GNU configure build cook verify cook by running tests install cook on your computer

When you type "cook", cook looks for a file called Howto.cook. This file, called a "cookbook", contains rules, or "recipes", for building a project. Each rule has three parts:
q

targets - the files built with this rule (e.g. the object file names)

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/5.html (2 of 6) [7/20/2001 11:31:40 AM]

Big Online Book of Linux Ada Programming - 5 Building Large Projects

ingredients - the files need to do the building (e.g. source code fields) q body - the commands to do the work. these can include other rules. Here is an example Howto.cook file with one rule:
q

main: main.adb { gnatmake main.adb; } The target is "main". To create main, cook must examine main.adb. If main.adb is newer than main, cook creates a new main by running the Gnatmake command. Cook comes with some predefined rules for compiling certain kinds of files. These predefined cookbooks can be attached to your Howto.cook file by using "#include". For example, #include "c" includes basic rules describing the relationships of C files to each other.

5.2.1 Cooking in Parallel


Cook can use the rsh command to build several parts of a program at once, either on a computer with multiple CPU's or over a network. If rsh hasn't been configured, you'll need to do this before you can run cook. For example, all the computers should have the source directory mounted via NFS under the same mount directory. Also, the clocks on all the computers should be set identically or cook may be confused by the age of the files. To cook in parallel, run cook with the -par switch. This option indicates the number of computers cook can use, the default being 4. You can indicate fewer computers. For example, -par=2 will run cook using 2 computers. To indicate which machines to use, assign the hosts to the parallel_hosts variable. parallel_hosts = first_computer second_computer third_computer Simple Howto.cook files will compile in parallel without any modification.

5.2.2 A Simple Ada Cookbook


The following Howto.cook file will compile an Ada program called main.adb, plus any packages used by main. This should work for most small projects. Edit the OBJS variable to include all the object files from the packages you are using. To use this make file, type "cook" to build your Ada project, or "cook clean" to remove any intermediate files produced by the compiler.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/5.html (3 of 6) [7/20/2001 11:31:40 AM]

Big Online Book of Linux Ada Programming - 5 Building Large Projects

The ALT version of Gnat uses uses the name gnatgcc, not gcc, for the GCC compiler. /* /* /* /* /* /* /* /* ---------------------------------------- */ This is a simple Ada Howto.cook cookbook */ */ it assumes the main program is named */ main.adb */ */ by Ken O. Burtch */ ---------------------------------------- */

OBJS = main.o somepackage.o; /* How to compile individual Ada files */ %.o: %.adb { gcc -c %.adb; } /* How to compile individual C files */ /* ( Just in case we want to mix C and Ada ) */ %.o: %.c { gcc -c %.c; } /* How to bind and link the main program */ main: [OBJS] { gnatbind -xf main.ali; gnatlink main.ali; } /* How to clean up intermediate files */ clean: { rm *.o *.ali core; } There are many other features in cook not covered here. More information about cook can be found in the Cook User Manual and the Cook Reference Manual.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/5.html (4 of 6) [7/20/2001 11:31:40 AM]

Big Online Book of Linux Ada Programming - 5 Building Large Projects

5.3 Automake and Autoconf: UNIX Portability


If you want to create projects that run on a variety of UNIX platforms, not just Linux, you'll want to look at GNU autoconf and automake. The GNU tools use these programs extensively. Included with Linux, autoconf creates a shell script called "configure". Customized for your project, when this script is executed, it scans the features of the particular UNIX that it is running on and tailors all Makefiles accordingly. It optionally produces a C file called "config.h" which contains information about the features it found. automake, the other half of autoconf, creates a Makefile.in using templates called "Makefile.am". Once automake is finished, all you have to do is run "configure" to make your final makefile and type "make" to build the project on any version of UNIX. It is possible to use autoconf and automake on Ada Makefiles, but this topic is beyond the scope of this book. More information on automake and autoconf can be found using "info autoconf" and "info automake". The following is an example of what happens when you run an autoconf configure script, as run for the FreeAmp program. checking checking checking checking checking checking checking checking checking checking checking checking checking checking checking checking checking checking checking checking host system type... i686-pc-linux for a BSD compatible install... (cached) /usr/bin/install -c whether build environment is sane... yes whether make sets ${MAKE}... (cached) yes for working aclocal... found for working autoconf... found for working automake... found for working autoheader... found for working makeinfo... found whether make sets ${MAKE}... yes for gcc... gcc whether the C compiler (gcc) works... yes whether the C compiler (gcc) is a cross-compiler... no whether we are using GNU C... yes whether gcc accepts -g... yes for c++... c++ whether the C++ compiler (c++) works... yes whether the C++ compiler (c++) is a cross-compiler... no whether we are using GNU C++... yes whether c++ accepts -g... yes

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/5.html (5 of 6) [7/20/2001 11:31:40 AM]

Big Online Book of Linux Ada Programming - 5 Building Large Projects

checking checking ... checking checking checking checking checking checking creating creating ... creating

for POSIXized ISC... no for ranlib... ranlib for libc5... no for dlopen in -ldl... yes for MIT PThreads... no for Base LinuxThreads... yes for LinuxThreads w/ErrorCheck Mutex... yes for sys/asoundlib.h... no ./config.status Makefile config/config.h

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/5.html (6 of 6) [7/20/2001 11:31:40 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

6 Development Utilities
<--Last Chapter Table of Contents Next Chapter-->

6.1 Saving Time with Gnatstub Starting with gnat 3.11p, gnat provides a prototyping tool called Gnatstub.Gnatstub takes an Ada package specification and creates a corresponding body, ready to have the details outlined in the spec filled in. These empty subprograms are sometimes called "stubs". This is especially useful on a large project where programmers write a series of package specs to test their design. Once the package design is set, Gnatstub can create a basic body and save the programmers the work of copying and modifying the specification by hand. IDE: TIA will run gnatstub on the current file using Stub in the File menu. For example, suppose you have the following package specification in a file called tiny.ads: package tiny is procedure simple_procedure; function simple_function return boolean; end tiny; You can create a stub body for this package using gnatstub tiny.ads Gnatstub produces the following tiny.adb file: package body tiny is ---------------------- simple_function ---------------------function simple_function return boolean is begin return simple_function; end simple_function; ----------------------

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (1 of 14) [7/20/2001 11:31:53 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

-- simple_procedure ----------------------procedure simple_procedure is begin null; end simple_procedure; end tiny; This package body is in proper Ada format, ready to be compiled. Of course, it doesn't actually do anything useful. It's up to the programmer fill in the implementation details.

6.2 Cross-referencing with Gnatxref


Gnatxref (or gnatf in gnat 3.10) is a utility that produces an index of every occurrence of an identifier in a program, including all identifiers used by packages that the program depends upon. The -v option produces a listing in the format for a vi editor tags file. IDE: TIA will run gnatxref on the current file by chosing Xref in the File menu. For our hello.adb program, Gnatxref produces the following: Text_IO U a-textio.ads:51:13 {} {hello.adb:1:10 4:7 } Put_Line U a-textio.ads:260:14 {} {hello.adb:4:15 } Ada U ada.ads:18:9 {} {hello.adb:1:6 4:3 } hello U hello.adb:2:11 {} {} Each line begins with the identifier being indexed. The "U" means [not sure-KB]. The next segment is the file that defines the identifier, and the position in the file. The {} means [not sure-KB]. The final bracketed section lists all occurrences of the identifier in the program. In this example, identifier text_io appears in the first line (the with) and the fourth line (the put_line).

6.3 Eliminating Dead Code with Gnatelim


gnatelim is a utility that searches for unused parts of your program in the object files and removes them from the final executable. It works by creating a list of subprograms that the compiler shouldn't compile. If you save this list as gnat.adc, gnatmake will automatically read this file and will skip these subprograms when compiling. To use gnatelim, you need to generate tree files using the -gnatt switch. The Gnat manual recommends these steps when using gnatelim (assuming that your main program is main.adb): 1. gnatmake -c main 2. gnatbind main 3. gnatmake -f -c -gnatc -gnatt main

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (2 of 14) [7/20/2001 11:31:53 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

4. gnatelim main > gnat.adc 5. gnatmake -f main These commands will generate a complete set of tree files for your project, strip out all unused subprograms, and will then recompile the project as a finished executable. gnatelim is is based on ASIS. [gnatelim doesn't work under gnat 3.11.--KB]

6.4 Execution Stack & Memory Leak Detection


Gnat 3.11 does not display the execution stack in the event of of an exception. Gnat 3.12 provides additional information about the source of an exception. You can get additional information about the execution stack using the gnat.traceback package (12.15). The gnatmem utility monitors a running programming using the Gnat gdb debugger. When the program is finished running, gnatmem displays a summary of dynamically allocated memory. You can use this information to find "memory leaks", places in your program where allocated memory was not deallocated. Because gnatmem uses gdb, the program should be compiled with gdb support turned on (the -g switch). Note: gnatmem doesn't work with Gnat 3.11. To run gnatmem, type gnatmem program The gnatmem switches are: -q - quiet - hides statistics and shows only potential memory leaks n - a number between 1 and 10 indicating the depth of the backtrace information -o file - save the gdb output to the indicated file. The gdb script is saved as gnatmem.tmp -i file - processing using the file previously saved with -o. Use this to test a program that crashed while gnatmem was running.

6.5 Conditional Compiling with Gnatprep


Although the Ada 95 design team decided against including preprocessing compiler directives like C does, gnat provides a preprocessor so you can use conditional compiling directives in your Ada programs. Gnatprep, the Gnat PREProcessor, takes a source file with conditional directives, a file with variable assignments for the conditional directives, and produces a source file with all statements not satisfying the conditional directives removed. C: The conditional directives do not allow expressions. There must only be a variable, and that variable must be true or false. IDE: No IDE's currently support gnatprep.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (3 of 14) [7/20/2001 11:31:53 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

Suppose you create a file called "prepvalues" with the following Gnatprep definitions: ALPHAVERSION := true BETAVERSION := false RELEASEVERSION := false TRANSLATION := English Suppose also that you had a short program with Gnatprep statements in it: with text_io; use text_io; procedure preptest is -- only include the relevant parts for this version #if ALPHAVERSION s_version : string := "alpha"; #elsif BETAVERSION s_version : string := "beta"; #elsif RELEASEVERSION s_version : string := "release"; #else s_version : string := "unknown"; #end if; -- string is the value of the gnatprep variable named translation s_translation : string := "$TRANSLATION"; begin Put_Line( "This is the " & s_version & " edition" ); Put_Line( "This is the " & s_translation & " translation" ); end preptest; Running gnatprep on the above program with the prepvalues file gives you the following program: with text_io; use text_io; procedure preptest is -- only include the relevant parts for this version s_version : string := "beta"; -- string is the value of the gnatprep variable named translation s_translation : string := "English";

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (4 of 14) [7/20/2001 11:31:53 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

begin Put_Line( "This is the " & s_version & " edition" ); Put_Line( "This is the " & s_translation & " translation" ); end preptest; The Gnatprep command switches are: -Dsymbol=value - define values on the command line instead of a prep values file, same as -D in C. For example, -DMacintosh=FALSE -b - replace gnatprep commands with blank lines (instead of -c) -c - comment out gnatprep commands (instead of -b) -r - generate a Source_Reference pragma -s - print a sorted list of symbols and values -u - treat undefined symbols as if they were FALSE C: There is no gnatprep equivalent of __FILE__ (name of current source file) or __LINE__ (number of current line).

6.6 Profiling with Gprof


Gprof in the GNU profiler. It shows which subprograms in a program are being executed the most. You can use this information to find the parts of a program with the greatest need for CPU efficiency and hand optimize those parts accordingly. To use Gprof, you must rebuild your project using the -pg switch at both the compiling and linking stages. With Gnatmake, you must include -pg with both -cargs and -largs switches. IDE: TIA will profile your project with gprof if you select Profile in the Project menu. It automatically rebuilds your project with the necessary gprof switches, starts your main program, and then displays the gprof results. For example, we can use Gprof on the following factorial program: package fact is function factorial( param : integer ) return integer; end fact; package body fact is function factorial( param : integer ) return integer is begin if param < 2 then return 1; end if;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (5 of 14) [7/20/2001 11:31:53 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

return param * factorial( param - 1 ); end factorial; end fact; with fact; use fact; procedure bench2 is maxFactorials : constant integer := 1000; type factorialArray is array( 1..maxFactorials ) of integer; list : factorialArray; begin for i in 1..maxFactorials loop list( i ) := factorial( i ); end loop; end bench2; After compiling and linking the program with the -pg switch, run the program. The program produces a gmon.out file containing profile information about the program. Now we can use Gprof to get an analysis of the program. Running gprof -c bench2 returns the following information. Note that Ada subprograms are labeled with the package name, a double underscore, and the subprogram name. [Need to clean this up--KB] Flat profile: Each sample counts as 0.01 seconds. %cumulative self self total

time seconds seconds callsus/callus/callname

62.500.050.05__mcount_internal 25.000.070.02mcount

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (6 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

12.500.080.01100010.0010.00fact__factorial 0.000.080.0010.00 10000.00_ada_bench2

0.000.080.0010.000.00fact___elabb

%the percentage of the total running time of the time program used by this function. cumulative a running sum of the number of seconds accounted seconds for by this function and those listed above it. self the number of seconds accounted for by this seconds function alone.This is the major sort for this listing. calls the number of times this function was invoked, if this function is profiled, else blank. self the average number of milliseconds spent in this ms/call function per call, if this function is profiled, else blank. total the average number of milliseconds spent in this ms/callfunction and its descendents per call, if this function is profiled, else blank. name the name of the function. This is the minor sort for this listing. The index shows the location of the function in the gprof listing. If the index is in parenthesis it shows where it would appear in the gprof listing if it were to be printed. Call graph (explanation follows) granularity: each sample hit covers 4 byte(s) for 100.00% of 0.01 seconds index % time self children called name 499500fact__factorial [1] 0.010.001000/1000_ada_bench2 [3]

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (7 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

[1]100.00.010.001000+499500fact__factorial [1] 0.000.000/0mcount (177) 499500fact__factorial [1]

----------------------------------------------0.000.000/0_start [473] [2]100.00.000.01main [2] 0.000.011/1_ada_bench2 [3] 0.000.000/0__gnat_initialize [399] 0.000.000/0adainit [61] 0.000.000/0__gnat_break_start [395] 0.000.000/0adafinal [60] 0.000.000/0__gnat_finalize [397] 0.000.000/0exit [95]

----------------------------------------------0.000.011/1main [2] [3]100.00.000.011_ada_bench2 [3] 0.010.00 1000/1000fact__factorial [1] 0.000.000/0mcount (177)

-----------------------------------------------

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (8 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

0.000.001/1adainit [61] [6]0.00.000.001fact___elabb [6] 0.000.000/0mcount (177)

-----------------------------------------------

This table describes the call tree of the program, and was sorted by the total amount of time spent in each function and its children. Each entry in this table consists of several lines.The line with the index number at the left hand margin lists the current function. The lines above it list the functions that called this function, and the lines below it list the functions this one called. This line lists: index A unique number given to each element of the table. Index numbers are sorted numerically. The index number is printed next to every function name so it is easier to look up where the function in the table. % time This is the percentage of the `total' time that was spent in this function and its children.Note that due to different viewpoints, functions excluded by options, etc, these numbers will NOT add up to 100%. self This is the total amount of time spent in this function. children This is the total amount of time propagated into this function by its children. called This is the number of times the function was called. If the function called itself recursively, the number only includes non-recursive calls, and is followed by a `+' and the number of recursive calls. name The name of the current function. The index number is printed after it. If the function is a member of a cycle, the cycle number is printed between the

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (9 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

function's name and the index number. For the function's parents, the fields have the following meanings: self This is the amount of time that was propagated directly from the function into this parent. children This is the amount of time that was propagated from the function's children into this parent. called This is the number of times this parent called the function `/' the total number of times the function was called. Recursive calls to the function are not included in the number after the `/'. name This is the name of the parent.The parent's index number is printed after it.If the parent is a member of a cycle, the cycle number is printed between the name and the index number. If the parents of the function cannot be determined, the word `<spontaneous>' is printed in the `name' field, and all the other fields are blank. For the function's children, the fields have the following meanings: self This is the amount of time that was propagated directly from the child into the function. children This is the amount of time that was propagated from the child's children to the function. called This is the number of times the function called this child `/' the total number of times the child was called. Recursive calls by the child are not listed in the number after the `/'. name This is the name of the child.The child's index number is printed after it.If the child is a member of a cycle, the cycle number is printed between the name and the index number. If there are any cycles (circles) in the call graph, there is an entry for the cycle-as-a-whole. This entry shows who called the cycle (as parents) and the members of the cycle (as children.) The `+' recursive calls entry shows the number of function calls that

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (10 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

were internal to the cycle, and the calls entry for each member shows, for that member, how many times it was called from other members of the cycle. Index by function name (418) __mcount_internal[1] fact__factorial[5] <cycle 2> [3] _ada_bench2(177) mcount [6] fact___elabb[4] <cycle 1> If factorial is a function internal to program bench2, the function name won't show up in Gprof. For example: procedure bench2 is function factorial( param : integer ) return integer is begin if param > 1 then return param * factorial( param - 1 ); end if; return 1; end factorial; maxFactorials : constant integer := 100; type factorialArray is array( 1..maxFactorials ) of integer; list : factorialArray; begin for i in 1..maxFactorials loop list( i ) := factorial( i ); end loop; end bench2; gprof -c bench2 returns the following information: Flat profile: Each sample counts as 0.01 seconds.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (11 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

no time accumulated %cumulativeselfselftotal

time seconds seconds callsTs/callTs/callname 0.000.000.00990.000.00main

0.000.000.0010.000.00_ada_bench2 etc.

Note: gnatmem doesn't work with Gnat 3.11.

6.7 Shared Libraries Using GnatDLL


[To be written--KB]

6.8 Source as Web Pages Using GnatHTML


This utility converts an Ada source file into a series of indexed, coloured HTML web pages. By default, the web pages are stored under a subdirectory called HTML. By posting your source code on a network or the Internet, developers can examine your work with a web browser. The gnathtml switches are: q -83 - look for Ada 83 keywords only q -cc color - comment colour q -d - convert files which depend on this file as well q -D - like -d, but also convert standard library files q -f - crossreference local entries q -ln - display line numbers every n lines q -Idir - file search path q -odir - specify the output directory (default html/) q -pfile - use this Gnat project file q -sc color - symbol colour q -Tfile - read the files to convert from this file Example using gnathtml with the following program: with Ada.Text_IO; use Ada.Text_IO;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (12 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

procedure htmltest is -- a demonstration of gnathtml function factorial( n : natural ) return natural is -- compute the factorial of n begin if n < 2 then return 1; else return n * factorial( n-1 ); end if; end factorial; -- main program begin put_line( "Browse this source!" ); new_line; put_line( "The factorial of 5 is" & natural'image( factorial( 5 ) ) ); end htmltest;

This creates an index file like this:

Files
q

htmltest.adb

Functions/Procedures
q q

factorial htmltest

The first link would show you your entire file:

File : htmltest.adb
with Ada.Text_IO; use Ada.Text_IO; procedure htmltest is -- a demonstration of gnathtml

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (13 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 6 Development Utilties

function factorial( n : natural ) return natural is -- compute the factorial of n begin if n &lt; 2 then return 1; else return n * factorial( n-1 ); end if; end factorial; -- main program begin put_line( "Browse this source!" ); new_line; put_line( "The factorial of 5 is" & natural'image( factorial( 5 ) ) ); end htmltest; The links use the .htm (not .html) extension for portability.

6.9 GnatFind
[To be written--KB] <--Last Chapter Table of Contents Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/6.html (14 of 14) [7/20/2001 11:31:54 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

7 Optimizing Your Project


<--Last Chapter Table of Contents Next Chapter-->

Optimization is the customization of a program to run as small and/or as fast as possible on a particular type of computer. If you program is running slower than you expected, or is using more memory or disk space than you expected, you should first examine the approach you used in your Ada source code. Can you use better data structures, or implement faster algorithms? For example, a bubble sort is an easy way to sort relatively small amounts of data, but a quick sort is faster on thousands or millions of pieces of data. In large programs, the subprogram causing the biggest bottlenecks may not be obvious. Experimenting with different test data and timing the results can often narrow down the problem areas. You could also try the gprof profiling tool, which will give you statistics on your program performance and will show that you are on the right track. Why spend hours or days improving a section of your program that isn't causing the problem? This is especially important in a business environment: focus your time on the sections that will give the greatest improvements. Some optimizations can be done automatically by the Gnat compiler. There are both compiler switches and language pragmas for fine tuning your programs.

7.1 Compiler Optimization Options


There are several compiling switches used to optimize programs. The -O switch tells the compiler how much time it should spend optimizing the program: q No -O - fastest compiling, but gives you gnat warnings for optimization pragmas. Use only when fast compiling is essential. q -O/-O1 - slower compiling, cleaner executable, and no pragma optimize warnings from gnat. You should normally include this. q -O2 - more optimization. Use this for the smallest executable. q -O3 - full optimization, automatic code inlining for small subprograms and loop unraveling. Use this for the fastest executable. When using floating point numbers, you may experience rounding errors if you don't use the -ffloat-store switch as discussed in 8.5. Inlining is also affected by two other switches: q -gnatn - allow inlining between packages where pragma inline is used in a package specifications. q -gnatN - allow automatic inlining between packages (this is very memory intensive) q No -gnatn/N - no inlining between packages, even if a pragma inline is used in a package

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (1 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

specification. These switches both require a -O switch for inlining to take effect. The -gnatp switch turns off all non-essential error checking such as constraint and range checks. This is the same as using pragma Suppress( All_Checks ) on every file in the entire program, making the program smaller and faster. There are some other gcc optimization switches which can sometimes be used: -ffast-math - gcc will ignore certain ANSI & IEEE math rules. For example, it will not check for negative numbers before invoking the sqrt function. This improves math performance but can cause sideeffects for libraries expecting the ANSI/IEEE rules to be honoured. -fomit-frame-pointer - gcc will free the register usually dedicated to hold the stack frame pointer. This improves performance, but makes debugging difficult--many debugging utilities require the frame pointer. IDE: TIA sets the proper switches for you based on your selections in the project parameters window.

7.2 Gnat Source Optimization Options


Ada Package pragma Pack( Aggregate ); pragma Optimize( Space / Time / Off ); pragma Inline( Subprogram ); pragma Inline_Always( Subprogram ); pragma Discard_Names( type ); Description Use minimum space for the aggregate. How you want your statements optimized. Inline the subprogram Inline the subprogram Don't include ASCII identifiers in executable. C Equivalent inline -

There are six pragmas available to change the size and execution speed of your program. Pragma Pack compresses an array, record or tagged record so that it uses the minimum space possible. For example, a packed boolean array takes up one bit for each boolean. Pack only packs the aggregate, not any aggregate items that might make up the aggregate: if you have an array of records, you'll need to both pack the array and the records to use the minimum space possible. Packing aggregates usually slows down the execution of your program. type CustomerProfile is record Preferred : boolean; PreordersAllowed : boolean; SalesToDate : float; end record; pragma Pack( CustomerProfile );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (2 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

Gnat can perform close packing, that is, packing right down to individual bits, for array elements or records of 64 bits or smaller. Pragma Optimize specifies how you want your statements to be optimized: to run as fast as possible (time), to be as small as possible (space), or no optimization at all. Optimize does not affect data structures. pragma Optimize ( space ); package body AccountsPayable is Pragma Inline makes Ada inline the subprogram whenever possible. That is, it physically inserts the subprogram whenever it's named instead of calling it in order the make your program run faster. This uses up a lot of space and is only practical for small procedures and functions. procedure Increment( x : integer ) is begin x := x + 1; end Increment; pragma Inline( Increment ); Compiling switch -O3 must be used or pragma inline is ignored. -O3 will also automatically inline short subprograms for you. Pragma Inline_Always forces inlining between packages (like -gnatn) regardless of whether or not -gnatn or -gnatN has been used. Pragma Discard_Names frees up space by discarding the ASCII images (names) of identifiers. For example, if you have a big enumerated type, Ada normally maintains strings for the names of each of the enumerated items in case you want to use the 'img attribute. You can discard these names if you never intend to use 'img. type aDogBreed is (Unknown, Boxer, Shepherd, MixedBreed ); pragma Discard_Names( aDogBreed ); When you discard names, the 'img is still available. Instead of returning the enumerated value's image, 'img returns the position of the enumerated type (for example, 0, 1, 2 and so forth). Fun Fact: The ASCII images of your variable names are stored as C strings at the end of your executable file. You can view them using the less (or strings) shell command.

7.3 CPU Optimization Options


There are two main CPU optimization switches in GCC 2.x, as listed in the GCC manual: -mno-486 - optimize for 80386. -m486 - optimize for 80486. These programs will still run on a 80386.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (3 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

q q q

Future versions of Gnat built for GCC 3.x or later will probably support: -mpentium - optimize for Pentium / Intel 586 -mcpu=i686 - optimize for Pentium II/ Intel 686 -mcpu=k6 - optimize for AMD K6

There are currently no switches newer CPUs such as Pentiums. Under GCC 2.8.1 (and Gnat), the GCC FAQ recommends the following switches for reasonable Pentium performance: "-m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -fno-strength-reduce". There are other switches that may or may not be helpful, depending on your program: read the gcc FAQ for full details. IDE: TIA sets the proper switches for you based on your selections in the project parameters window. Let's put all these flags together. Suppose you are trying to develop a program for the Intel Pentium CPU with an emphasis on speed. During development, the Gnatmake switches would be "-O1" since this setting suppresses pragma optimize warnings. For the final release, the Gnatmake switches should be "-m486 -O3 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -fno-strength-reduce -gnatp" for maximum performance on a Pentium processor.

7.4 What Difference Does Optimization Make?


In the previous sections, we saw GCC compiler switches and and Ada pragmas that affect the speed and size of your finished application. But how much of a difference does optimization make? And are there any problems caused by optimization? The optimization switches and pragmas affect different applications differently. Some will give better results to certain kinds of applications, while others may actually have a negative effect. The following table summarizes the results of optimizing on the Hartstone Ada benchmark program. Hartstone is a multithreading mathematics test available freely on the Internet http://ftp.sunet.se/pub4/benchmark/hartstone/. Table: Hartstone 1.1 Benchmark Summary Gnat switches -gnatE -gnato -g -gnatE -gnato -gnatE no switches -O Ada pragmas CPU Time 0.13s 0.13s 0.10s 0.10s 0.07s File Size 294265 147433 138679 138679 113076 Task Set Util 0.41% 0.41% 0.32% 0.29% 0.22%

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (4 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

-O2 -O3 -O3 -gnatp -O3 -gnatp Pent Max Max Max Max

Optimize( Space ) Optimize( Time ) Pack arrays

0.07s 0.07s 0.08s 0.08s 0.05s 0.05s 0.05s 0.11s

113324 118790 104290 105042 105714 105714 105714 105712

0.22% 0.20% 0.37% 0.15% 0.15% 0.15% 0.15% 0.15%

Pent - GCC Pentium optimization switches Max - Pent + -ffast-math + -fomit-frame-pointer This test was conducted with a Pentium II 350, 64 Megs RAM and ALT Gnat 3.12p-9. As they say, your milage many vary (and probably will). By optimizing the application, Hartstone can be reduced to half its size and run about 2/3 faster than using no optimization. However, if we pack the arrays in Hartstone, we save two bytes but lose all the improvements in speed. Sometimes smaller programs are not faster. Let's try optimizing a convoluted program that uses integers, arrays, functions and mathematics and see what effect the optimization techniques have. procedure bench is --Simple benchmark program to test optimization pragma optimize( time ); type bench_integer is new long_integer range long_integer'range; type small_integer is new long_integer range 0..9; function p( param : bench_integer ) return bench_integer is divideby : constant bench_integer := 4; begin return param / divideby; end p; pragma inline( p ); j : bench_integer := bench_integer'last; -- deliberate error in main program for j * 2 type atype is array(0..9) of small_integer; --pragma pack( atype);

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (5 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

a : atype; begin for i in 1..100_000_000 loop j := abs( p( bench_integer( i ) ) - (j * 2) ); a( integer( j mod 10 ) ) := small_integer( j mod bench_integer( small_integer'last) ); end loop; end bench; Notice that j is assigned the largest bench_integer possible. This will force an overflow error the first time around the for loop, when j is multiplied by two. The following chart shows the effect of the different switches and pragmas, and indicates when gnat caught the overflow error. The test was conducted on a Pentium II 350 with 64 Megs of RAM using the gnat 3.11 NYU binaries and was timed with the time command. Gnatmake Switches gnatmake -gnato -gnatE gnatmake -gnato gnatmake -gnatE gnatmake gnatmake -O gnatmake -O2 gnatmake -O3 gnatmake -O3 -gnatp gnatmake -O3 -gnatp Pent gnatmake -O3 -gnatp Pent gnatmake -O3 -gnatp Pent gnatmake -O3 -gnatp Pent Pragmas Optimize( Space ) Optimize( Time ) Pack atype CPU Time 40.3 s 40.3 s 10.8 s 10.8 s 10.8 s 9.6 s 9.6 s 9.6 s 9.6 s 4.4 s Size 118162 118162 118162 117634 117426 117426 117426 117410 117410 117410 117410 117326 Error Caught? YES YES No No No No No No No No No No

Although the proper optimization can make this program run faster, but with overflow checking was turned on with -gnato, the overflow error is caught. The lesson here is that error checking only works when it's turned on. We can compare the results to the equivalent C program: int p( int param ) { return param / 4;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (6 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

} int i; int j = 2147483647; int a[10]; int main() { for (i=1; i<=100000000; i++) { j = abs( p(i)-(j*2)); a[ j%10 ] = j%10; } return 0; } GCC Switches gcc -Wall gcc -O3 Pent Pragmas CPU Time 12.8 s 8.6 s Size 24541 24541 Error Caught? No No

In this case, notice that C never detected the overflow error. Secondly, notice that the Ada program ran twice as fast as the C program. In theory, an Ada compiler can take advantage of the typing information and the optimization hints provided by the pragmas. The C compiler has less information and this can hinders the optimization process. (I've never investigated whether or not Gnat does this or how much of an effect it has.) The optimization techniques will affect different programs differently. You need to chose the best approach for your particular project.

7.5 Working with the Assembly Source


Assembly language is the low-level programming language for working with the hardware of a particular computer. Using assembly language, you can access the processor registers, use unusual features of the processor, and dictate exactly which operations the processor performs. Assembly language programs are usually several times smaller and faster than programs written in high-level languages, but they are also several times harder to build, maintain and debug. The Linux assembler is called gas (the GNU assembler). Like GNAT and C++, gas works through gcc. To assemble an assembly language source file, simply run gcc. The compiler will recognize the assembly language file and will assemble it using gas. If you want to view the assembly source code of your Ada program, use the "-c -S -fverbose-asm" options when compiling. GNAT will create a file with a ".s" suffix containing the assembly source. You can view it, or even edit it and assemble afterwards. Improving the instructions produced by the compiler and then assembling afterwards is known as hand optimizing. This technique is typically used for high performance applications such as games, where the programmer needs to get the maximum performance from the hardware.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (7 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

The following is the stderr.s file for the stderr.adb program described elsewhere in this document. .file"stderr.adb" .version"01.01" / GNU Ada version 2.8.1 (i686-pc-linux-gnu) compiled by GNU C version 2.8.1. / options passed:-I../texttools/ -mcpu=i486 -march=i486 -gnatp -gnatf -O3 / -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 / -fno-strength-reduce -fverbose-asm / options enabled:-fdefer-pop -fcse-follow-jumps -fcse-skip-blocks / -fexpensive-optimizations -fthread-jumps -fpeephole -fforce-mem / -ffunction-cse -finline-functions -finline -fkeep-static-consts / -fcaller-saves -fpcc-struct-return -frerun-cse-after-loop / -fschedule-insns2 -fcommon -fverbose-asm -fgnu-linker -m80387 / -mhard-float -mno-soft-float -mieee-fp -mfp-ret-in-387 / -mschedule-prologue -mcpu=i486 -march=i486 -malign-loops=2 / -malign-jumps=2 -malign-functions=2 gcc2_compiled.: .section.rodata .LC0: .string"This is an example of writing error messages to stderr" .align 4 .LC1: .long 1 .long 54 .LC2: .string"This message is on standard error" .align 4 .LC3: .long 1 .long 33 .LC4: .string"This message is on standard output" .align 4 .LC5: .long 1 .long 34
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (8 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

.LC6: .string"This is also on standard error" .align 4 .LC7: .long 1 .long 30 .LC8: .string"But this is on standard output" .text .align 4 .globl _ada_stderr .type_ada_stderr,@function _ada_stderr: pushl %ebp movl %esp,%ebp movl $.LC0,%eax movl $.LC1,%edx pushl %edx pushl %eax call ada__text_io__put_line__2 pushl $1 call ada__text_io__new_line__2 movl $.LC2,%eax movl $.LC3,%edx pushl %edx pushl %eax call ada__text_io__standard_error pushl %eax call ada__text_io__put_line movl $.LC4,%eax movl $.LC5,%edx pushl %edx pushl %eax call ada__text_io__put_line__2 addl $32,%esp pushl $1 call ada__text_io__new_line__2
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (9 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 7 Optimizing Your Project

call ada__text_io__standard_error pushl %eax call ada__text_io__set_output movl $.LC6,%eax movl $.LC7,%edx pushl %edx pushl %eax call ada__text_io__put_line__2 call ada__text_io__standard_output pushl %eax call ada__text_io__set_output movl $.LC8,%eax movl $.LC7,%edx pushl %edx pushl %eax call ada__text_io__put_line__2 movl %ebp,%esp popl %ebp ret .Lfe1: .size_ada_stderr,.Lfe1-_ada_stderr .ident"GCC: (GNU) 2.8.1"

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/7.html (10 of 10) [7/20/2001 11:32:11 AM]

Big Online Book of Linux Ada Programming - 8 Debugging Your Project

8 Debugging Your Project


<--Last Chapter Table of Contents Next Chapter-->

8.1 Limit and the Heap Size


The default storage pool (or the "heap") is kept on the user's stack. Unusually large variables in subprograms (including the main program) can cause out of memory errors. Variables in packages are not affected by the stack size. You can increase the stack space using Linux's limit command (although using dynamic allocation is usually a better solution). limit stacksize 1024 kbytes # 1 Megabyte user stack To constrain the size of your stack, as far as Gnat is concerned, use the GNAT_STACK_LIMIT environment variable to indicate the number of kilobytes of stack space. In individual Ada tasks, the stack size can be set by pragma Storage_Size. Stack size checking is normally disabled by Gnat. Section 4.4 discusses this.

8.2 The Debugging Pragmas


Ada Feature pragma Assert( condition); pragma Debug( Procedure ); Description Assert a condition. C Equivalent

assert Debugging procedure call Disable pragma debug pragma Suppress_Debug_Info; #ifdef var...#endif Indicate a subprogram that pragma No_Return( subprogram ); never completes Initialize scalars to illegal pragma Normalize_Scalars; values GNAT provides two useful pragma for debugging programs. To use these pragmas, you need to use the -gnata option during compiling. Removing -gnata causes GNAT to ignore these pragmas, making it easy to compile a version of your program for public release without having to delete the debugging statements from your source code.Pragma Assert lets you test to make sure a certain condition is true. If it isn't, then an exception is raised. Use Assert to check for conditions which you assume are true during program development. This is especially useful when several programmers are working on a project and you don't know if a condition will change in the future. pragma Assert( ScreenHeight = 24 );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/8.html (1 of 6) [7/20/2001 11:32:24 AM]

Big Online Book of Linux Ada Programming - 8 Debugging Your Project

In this example, if the variable ScreenSize is not 24, an ASSERT_ERROR exception is raised. Pragma Debug lets you call a procedure for debugging purposes. For example, you can use this to print information about the program while it is running. Because this is a pragma, you can place it almost anywhere, even in the middle of variable declarations. x := 5; pragma Debug( PrintToLogFile( "X is now" & x'img ) ); If PrintToLogFile is a procedure that saves messages to a log file, this example saves the message "X is now 5" to the log file. Pragma debug can be disabled with pragma Suppress_Debug_Info. Pragma No_Return can be used to indicate subprograms that never complete. This suppresses the related compiler warnings. Pragma Normalize_Scalars initializes anything not an array, record or tagged record to illegal values wherever possible. This pragma helps expose variables used before they are initialized. Use this at the start of a program or package. Suppose you have a integer variable with a range between 1 and 100. Normally, Ada won't assign an initial value (unless you specify one). With Normalize_Scalars, your variable will be initialized to some value out of range, perhaps -1. If you attempt to use this variable, you'll probably raise a CONSTRAINT_ERROR exception.

8.3 Identifying Files


[Rewrite and Expand]From Usenet: > If you are using 2.2.x, you can use the /proc to find a process which is> using a directory or file. If is the case, try this: ls -lad `find> /proc` | grep home> The number after the /proc should be the process ID.>> Any way, it seems a little bit delicate umount your /home after the> boot... Couldn't you use a rescue disk and format your /home without> mount it in a boot?>> Are you sure your /home isn't only a part of your / (root directory)?> When you type "df", does it report a different device for the /home?> Sorry, if I'm asking a very basic question.>try fuser or lsof.

8.4 Compiler Info with -gnatG


The -gnatG compiler switch shows Gnat's interpretation of your source code after its initial analysis. If you specify -gnatD, Gnat will write this information to a file ending in .dg (for "debug"). The following is a listing of the "pointers" program used later in this book: with Ada.Text_IO, System.Address_To_Access_Conversions; use Ada.Text_IO; procedure pointers is
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/8.html (2 of 6) [7/20/2001 11:32:24 AM]

Big Online Book of Linux Ada Programming - 8 Debugging Your Project

package IntPtrs is new System.Address_To_Access_Conversions( integer ); -- Instantiate a package to convert access types to/from addresses. -- This creates an integer access type called Object_Pointer. five : aliased integer := 5; -- Five is aliased because we will be using access types on it int_pointer : IntPtrs.Object_Pointer; -- This is an Ada access all type int_address : System.Address; -- This is an address in memory, a C pointer begin int_pointer := five'unchecked_access; -- Unchecked_access needed because five is local to main program. -- If it was global, we could use 'access. int_address := five'address; -- Addresses can be found with the 'address attribute. -- This is the equivalent of a C pointer. int_pointer := IntPtrs.To_Pointer( int_address ); int_address := IntPtrs.To_Address( int_pointer ); -- Convert between Ada and C pointer types. end pointers; The -gnatG shows the compiler's analysis of your program. In this case, it displays the results of the instantiation of the generic package: with system; with ada; with ada.text_io; with system.address_to_access_conversions; use ada.text_io; with system; with system; with unchecked_conversion; procedure pointers is package intptrs is subtype object is integer;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/8.html (3 of 6) [7/20/2001 11:32:24 AM]

Big Online Book of Linux Ada Programming - 8 Debugging Your Project

package address_to_access_conversions renames intptrs; null; type object_pointer is access all object; for object_pointer'size use 32; function to_pointer (value : address) return object_pointer; function to_address (value : object_pointer) return address; pragma convention (intrinsic, to_pointer); pragma convention (intrinsic, to_address); freeze object_pointer [] freeze to_pointer [] freeze to_address [] end intptrs; package body intptrs is function to_address (value : object_pointer) return address is begin if value = null then return null_address; else return value.all'address; end if; end to_address; function to_pointer (value : address) return object_pointer is package a_to_pGP3183 is subtype source is address; subtype target is object_pointer; function a_to_pR (s : source) return target; end a_to_pGP3183; function a_to_p is new unchecked_conversion (address, object_pointer); begin return target!(source(value)); end to_pointer; end intptrs; package intptrs is new system.address_to_access_conversions (integer); five : aliased integer := 5; int_pointer : intptrs.object_pointer := null; int_address : system.address; freeze intptrs [] begin int_pointer := five'unchecked_access; int_address := five'address; int_pointer := intptrs.to_pointer (int_address);

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/8.html (4 of 6) [7/20/2001 11:32:24 AM]

Big Online Book of Linux Ada Programming - 8 Debugging Your Project

int_address := intptrs.to_address (int_pointer); return; end pointers;

8.5 Floating Point Numbers


The GCC FAQ reports that floating point rounding problems can occur with -O2 and -O3 unless you use -ffloat-store (keeps floating-point numbers out of CPU registers). Using this switch will slow your program.

8.6 Gdb: the GNU debugger


gnat 3.11 and later with a version of Gdb, the GNU command line debugger, that fully supports Ada data structures.You shouldn't have to use Gdb very often as most problems are solvable with a few well-placed put_line's. However, if the program produces are core file or is behaving unpredictably because of an obscure coding mistake or a compiler bug, Gdb is the best way to find out what is going wrong and where. In order to use Gdb, you must compile your program with debugging support enabled (with the -g option in gnat, or -ggdb in C). To start Gdb on a program called dbase, use gdb dbase (or gnatgdb with the ALT version) and Gdb responds with its command line prompt, "(gdb)". Type run to start the program normally to the point of the crash. You can print out the value of variables using the print command: (gdb) print ch This will print the character in the variable named ch at the time when the program was stopped. To look at a core file produced by a segmentation fault, use gdb dbase core You can examine the variables at the time the program crashed. Gdb contains many other commands. You can get online help at any time with the help command. GNAT has a hidden -gnatdg flag. If you compile your program using this flag, you'll get extra information for Gdb, such as making all temporary variables used by gnat visible to the debugger.

8.7 Code Restrictions


There are several pragmas for disabling certain language features. These restriction pragmas can be used to enforce a certain policy and warn a programmer when the policy is violated. For example, if you are writing a real-time program, you may want to disable Ada features that do not have a known response time so that your program will not have random delays. The restriction pragmas include:

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/8.html (5 of 6) [7/20/2001 11:32:24 AM]

Big Online Book of Linux Ada Programming - 8 Debugging Your Project

q q q

q q q

Ada_83 - do not allow Ada 95 language features Ada_95 - (default) allow Ada 95 language features Controlled - turn off garbage collection for a type. This has no effect with Gnat since it does not implement garbage collection. Ravanscar - enforce Ravanscar run-time restrictions Restricted_Run_Time - similar to Ravanscar Restrictions - disable particular language features

no_run_time also enforces restrictions because the Ada run-time library is not available. More information on the usage of these pragmas is available in the Gnat documentation.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/8.html (6 of 6) [7/20/2001 11:32:24 AM]

Big Online Book of Linux Ada Programming - 9 Team Development

9 Team Development
<--Last Chapter Table of Contents Next Chapter-->

9.1 Change Logs


The Change Log Creating a change log is the easiest method to document changes you've made in a project. A change log is a text file (usually called "CHANGES") containing an explaination of all recent changes in a project. For example, if you are working on an open source project and you add support for encrypted passwords, you might document this by writing Nov 1 - added password support to file passwords.adb If anyone was going to add password support to your project, they can quickly see that you've already done it. Or if somebody was adding additional features to the passwords.c file, they will know that they may have to change their work since you've already changed the same file. The change log is popular on open source projects involving few programmers because there's little chance of two programmers modifying the same source file simultaneously. The Formal Change Log Most businesses or professional institutions have a much more formal structure for their change logs. In an environment involving important data, a program problem means someone else will have to retrace your activities in order to find and correct a problem. Formal logs are kept in a binder since there's always the possibility that a major failure will make it impossible to sign onto the computer. Each change is documented with q the date q person who made the software change q what programs were affected q a description of the change Some companies have internal audits done to ensure that changes were properly made. The auditors will pick random pages from the change log and ask the programmer to verify the changes. In these cases, a formal change log may also include information such as the size, ownership and permissions of files affected. This serves both to quickly check a file as well as to force a programmer to verify the security of the files he or she installs. The most common security loopholes in UNIX are caused by people not checking the ownership and permissions of installed files.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/9.html (1 of 6) [7/20/2001 11:32:37 AM]

Big Online Book of Linux Ada Programming - 9 Team Development

9.2 RCS: Revision Control System


RCS (Revision Control System) is a tool that shares a document or program source code between multiple people. It also automatically numbers the file with a version number (eg. 1.1, 1.2) with each revision, and maintains a change log. CVS, an extension to RCS, is described below.Once you initialize RCS for a project, people in your project "check out" (with the co command) a copy of a file, and when they're done making changes they "check in" the file (with the ci command). RCS is also a good tool for maintaining documentation. Read the rcsintro man page for more information on getting started. The following is a transcript of a session using RCS. Assume that you have a source file called "f.c". To add the source file to RCS, you'd use ci. You are prompted for a general description of the file and RCS assigns version number 1.1 to the file. The file is deleted from your directory and moved into RCS's care. armitage:/home/ken/ada/rcs# ci f.c RCS/f.c,v <--f.c enter description, terminated with single '.' or end of file: NOTE: This is NOT the log message! >> Curreny Definitions >> . initial revision: 1.1 done armitage:/home/ken/ada/rcs# ls RCS To check out the file, read-only, use co. The file reappears. armitage:/home/ken/ada/rcs# co f.c RCS/f.c,v -->f.c revision 1.1 done armitage:/home/ken/ada/rcs# ls RCS f.c To check out a file to change it, use co -l (lock out others): armitage:/home/ken/ada/rcs# co -l f.c RCS/f.c,v --> f.c revision 1.1 (locked) done Suppose you add the line "--test line" to the file. Rcsdiff will report any changes you've made to the file since checking it out: armitage:/home/ken/ada/rcs# rcsdiff f.c =================================================================== RCS file: RCS/f.c,v retrieving revision 1.1
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/9.html (2 of 6) [7/20/2001 11:32:37 AM]

Big Online Book of Linux Ada Programming - 9 Team Development

diff -r1.1 f.c 0a1 > --test line Finally, you can check the file back in. RCS increments the version number and prompts you for a message for the change log. armitage:/home/ken/ada/rcs# ci f.c RCS/f.c,v <-- f.c new revision: 1.2; previous revision: 1.1 enter log message, terminated with single '.' or end of file: >> Added comments >> . done

9.3 CVS: Concurrent Versions System


CVS (Concurrent Versions System ) is a front end to RCS designed to work with groups of files in multiple directories. CVS can work with individual files, whole directories or you can organize large projects into groups of files (called a modules) that you want to work with. Like RCS, it timestamps files, maintains version numbers, and identifies possible problems when two programmers update the same section of a program simultaneously. CVS is very popular for open source development. CVS can be configured to allow programmers all over the world to work on your project without having to be logged into your computer. In order to use CVS, the project leader needs to create a directory for CVS to work in (called the repository) and a subdirectory called CVSROOT. Then you define an environment variable called CVSROOT so CVS knows where to find the CVS directory. For example, to make "/home/our-project-cvs" the repository for your team, set up the CVSROOT under bash as export CVSROOT=/home/our-project-cvs The repository holds copies of all the files, change logs, and other shared resources for your project. To add a new project to the CVS repository, use the import command. Import will take the files in the current directory and put them in the repository under the name you specify. Import also requires a short string to identify who is adding the project, and a string to describe the state of the project. This strings are comments and can be anything: your login and "init-rel" for initial release may be good choices. By convention, CVS begins numbering your project with "1.1" [root@redbase cvs]# cvs import project kburtch init-rel (CVS starts your default editor, typically vi) CVS: ---------------------------------------------------------------------CVS: Enter Log. Lines beginning with `CVS: ' are removed automatically
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/9.html (3 of 6) [7/20/2001 11:32:37 AM]

Big Online Book of Linux Ada Programming - 9 Team Development

CVS: CVS: ---------------------------------------------------------------------(make notes and exit vi) N project/currency.adb No conflicts created by this import The "N project/currency.adb" line indicates that CVS created a new project called "project" and added the Ada file currency.adb to it. currency.adb is now stored in the CVS repository, ready to be shared amongst the team members. To work with a project, you use co (or checkout). This CVS command will save a copy of the project in your directory. It will also create a CVS directory to save private data files used by CVS. To use co, move to your home directory and type: [root@redbase cvs]# cvs checkout currency.adb cvs checkout: Updating . U project/currency.adb The subdirectory project will contain your own, personal copies of project files to work on. CVS maintains the original copy of currency.adb. Another programmer can also checkout currency.adb while you are working on your copy. If you do a checkout right after an import, you may have to remove the original files: CVS will not overwrite any existing files. To add a file to CVS, use the add command. currency.adb, use [root@redbase cvs]# cvs add currency.adb To add a file called

Single files, directories or even CVS modules can also be added to your project using "add". As you work on your source code, you can check your work against the project using the update command. [root@redbase cvs]# cvs update cvs update: Updating . When updating, CVS checks the files in your copy of the project against its copies. If another team member made changes to one of the project Ada files, CVS will copy the new file to your directory. If another team member made changes to one of the Ada files you've been working on, CVS will attempt to update your copy without destroying your work.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/9.html (4 of 6) [7/20/2001 11:32:37 AM]

Big Online Book of Linux Ada Programming - 9 Team Development

Sometimes the changes involve the same part of the Ada file and CVS won't be able to combine the changes automatically. CVS calls this a conflict. For example, suppose your Ada file contained a function function ConvertCurrency( amount : integer ) return float; If you changed this function to use a float amount, and another team member has changed amount to a string, CVS will report a conflict. You will have to talk to the team member who made the change and make an agreement what amount should be. If there are no other problems after an update, you can continue working on your source code. To delete a file, remove it using "rm" and then "update". file is no longer in the project. CVS will see your

The CVS command release will permanently remove a file from a project (including the copy in CVSROOT), but it also prevents you from recovering the file from the CVSROOT directory in an emergency. Unless storage space is limited, consider using the rm/update method of removing files. While working on your source code, your changes are not distributed to the rest of your team until you are ready. When your source code is tested and ready to be made available, use ci (or commit). Before commiting your changes, delete non-essential files (such as .ali, .o or executable files) to save space in the repository. The log command gives information about a group of files: [root@redbase cvs]# cvs log -l project cvs log: Logging project RCS file: /usr/cvs/project/currency.adb,v Working file: project/currency.adb head: 1.1 branch: 1.1.1 locks: strict access list: symbolic names: p1: 1.1.1.1 keyword substitution: kv total revisions: 2; selected revisions: 2 description: ---------------------------revision 1.1 date: 1999/01/13 17:27:33; author: kburtch; state: Exp; branches: 1.1.1;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/9.html (5 of 6) [7/20/2001 11:32:37 AM]

Big Online Book of Linux Ada Programming - 9 Team Development

Initial revision ---------------------------revision 1.1.1.1 date: 1999/01/13 17:27:33; author: kburtch; state: Exp; lines: +0 -0 Project started ============================================================================= Status gives you an overview of a group of files: [root@redbase cvs]# cvs status project cvs status: Examining project =================================================================== File: currency.adb Status: Up-to-date Working revision: 1.1.1.1 Wed Jan 13 17:27:33 1999 Repository revision: 1.1.1.1 /usr/cvs/project/currency.adb,v Sticky Tag: (none) Sticky Date: (none) Sticky Options: (none)

9.4 Creating Transcripts with Script


So you did something wrong. How to you show what you did to your fellow programmers? The script command creates a file called "typescript" in the current directory. The typescript file is a text file that records a list of everything that appears on the screen. You can stop the recording process with the exit command.

9.5 Timing Execution with Time


The shell command time will tell you how long a program took to run, and reports general statistics such as how many page faults occurred. armitage:/home/ken/ada/sm# time myprog 3.09user 0.95system 0:05.84elapsed 69%CPU(0avgtext+0avgdata 0maxresident)k 0inputs+0outputs(4786major+4235minor)pagefaults 0swaps

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/9.html (6 of 6) [7/20/2001 11:32:37 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

10 An Introduction to Ada
<--Last Chapter Table of Contents Next Chapter-->

Ada is a full-featured language with many capabilities, rules, and nuances. Although the fundamentals are easy to learn (Ada somewhat resembles BASIC), it is several times larger that C, and to truly master the language requires considerable practice. To make understanding easier, the discussion is broken up into two chapters. This chapter outlines the basics of the language, and the next chapter discusses features for team development, large projects, and other specialized tasks. This in no way covers everything there is to know about Ada. I've chosen to cover those features that have been the most use to me over the years in my projects. For example, array slicing alone could take up several pages of discussion, but I've never had a need for it in recent years. Of course, you may be involved in a project in which array slicing is crutial. In these cases, I recommend you get a good Ada 95 reference such as Barnes' Programming in Ada 95. Likewise this is not a complete introduction to computer programming. Some background knowledge is assumed. Ada also has many specialized features for specific tasks such as scientific computing and real-time systems. Where I deliberately skip a subject, I usually make a note that I have done so. I've also hilighted useful information for C programmers who are learning Ada. Now, on to main programs.

10.1 Your Main Program


A main program in Ada is a procedure with no parameters that starts your program running. This is the set of instructions that the computer begins to follow when your program is first executed. The following program will print a message on the screen when you run it. with Ada.Text_IO; procedure firstProgram is -- my first Ada program begin Ada.Text_IO.Put_Line( "This is my first Ada program." ); end firstProgram; C: Ada is not case sensitive. "WITH" or "With" is the same as "with". An Ada program consists of sets of words and punctuation symbols. The words fall into two categories. First, the words in bold in bold are called keywords. These are words that have special meaning to Ada. Second, the words that aren't in bold are identifiers. These are the names of variables, procedures, packages and other items with names or titles in the language. IDE: Ada IDE's will hilight keywords in bold for you. Some editors such as emacs, elvis and nedit will also hilight keywords. This is a good way to check for spelling mistakes. In this program, begin is a keyword because Ada uses the word "begin" to denote where the program is to begin
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (1 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

executing instructions. On the other hand, "firstProgram" is an identifier because it is the name of our program. All keywords in Ada are also reserved words: this means that the keywords cannot be used as identifiers. The main program can have any name, as long as the name matches the filename. In gnat, the source code for a main program ends in .adb (Ada body). This program should be saved as firstprogram.adb. C: The main program doesn't have to be "main" unless you save the program as "main.adb".

If you call a program "test.adb", remember that test is a built-in shell command. To run a program named test, you'll have to type "./test" instead of "test" to avoid running the shell command by mistake.

Comments are denoted by two minus signs (--). This is a note to the reader; Ada will ignore it. Everything you type to the right of the symbol is treated as a remark to the reader. C: Ada has no equivalent to the block comment /* and */.

10.2 Text_IO
Ada put( s ); put( n'img ); put_line( s ); new_line; Description Display a string Display a number C Equivalent printf( "%s", s ); printf( "%d", n );

get( c ); get_line( s, len ); Read a line of text from the keyboard etc.

Display a line of text and start a new line printf( "%s\n", s ); Start a new line printf( "\n" ); Read a character from the keyboard c = getc(); gets(&s);

Like many modern computer languages, Ada doesn't have any built-in methods of reading the keyboard or writing messages on the screen. It doesn't assume you're writing a program for a PC (you could be doing embedded programming, for example)--but in general, you need to interpret what people type and display the results to the screen. You have to add this functionality specifically. The standard input/output package for Ada is Text_IO. This package prints characters and strings to the screen and reads characters and strings from the keyboard. It can also read and write simple sequential text files. (Packages will be discussed in detail starting at 11.1 in the next chapter.) Text_IO is only useful for simple programs. It doesn't have the ability to draw buttons, windows or menus. For X Windows programming, you'll require other packages/libraries to perform input and output.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (2 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

C: In C, printf and company can use an arbitrary number of parameters, where the parameters can be of different types. Text_IO's puts have one parameter, and the parameter must be a string or a character. Upcoming sections demonstrate how to print other types. The most commonly used operations are: q Put - write to the screen, but don't start a new line q Put_Line - write to the screen and start a new line q New_Line - start a new line q Get - read a character from the keyboard q Get_Line - read a string from the keyboard The following program is an example of Text_IO. with Ada.Text_IO; use Ada.Text_IO; procedure basicio is -- this program demonstrates basic input/output c : character; -- this is a letter begin Put_Line( "This program displays information on the screen" ); Put_Line( "and reads information from the keyboard"); New_Line; Put_Line( "Put_Line displays a line of text and advances to" ); Put_Line( "the next line." ); Put( "Put " ); Put_Line( "displays text, but it doesn't start a new line" ); Put_Line( "New_Line displays a blank line"); New_Line; Put_Line( "Get waits for a character to be typed."); Put_Line( "Type a key and the Enter key to continue." ); Get( c ); Put_Line( "The character you typed was '" & c & "'" ); end basicio;

This program displays information on the screen and reads information from the keyboard

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (3 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Put_Line displays a line of text and advances to the next line. Put displays text, but it doesn't start a new line New_Line displays a blank line Get waits for a character to be typed. Type a key and the Enter key to continue. c The character you typed was 'c' Besides letters and numbers, there are special characters called control characters which, instead of displaying a character, change the Linux display. To print controls characters, you need to use one of Ada's built-in character sets. For example, ASCII is a predefined list of all the ASCII characters. To send an explicit form feed character, use Put( ASCII.FF ); Some common control characters are: q ASCII.NUL - C end of string character q ASCII.CR - carriage return - move to beginning of line q ASCII.HT - horizontal tab q ASCII.LF - line feed - start a new line q ASCII.FF - form feed - start a new page on a printer C: Put doesn't recognize C string escape codes like "\n" or "\r". Besides ASCII, Ada has a number of other character sets defined in the Ada.Characters packages.

The ASCII set is officially made obsolete in Ada 95 by Ada.Characters.Latin_1, but it's still often used because it's easier to type.

10.3 Fundamental Data Types


Ada Type Character Integer Natural Positive Long_Integer Description A single character An integer (32-bit) number Zero or positive integer Positive integer C Equivalent char int -

A big integer (same as long in Gcc) long (same as int in Gcc) A really big (64-bit) integer Long_Long_Integer long long A small (16-bit) integer Short_Integer short Short_Short_Integer A really small (8-bit) integer char A real number Float float
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (4 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Long_Float Long_Long_Float Short_Float Fixed String

A big real number A really big real number A smaller real number A fixed-point real number An Ada fixed-length string

double long double ? char array

C: There are no built-in equivalents of unsigned types. Natural and Positive are integer values that aren't allowed to be negative, effectively requiring the sign bit to be zero. Characters cannot be used for small integer values--characters variables can only represent character values. Generally speaking, programs take data, process it in different ways, and create new information. Data is categorized into different data types. Data that is typed into a program is known as literals. Ada has several kinds of literals: q 'c' is a character. Character literals are enclosed in single quotes. q -5 is an integer q 45.5 is a float or a fixed with one decimal place q "This is a string" is a fixed string. Strings literals are enclosed in double quotes. C: Ada doesn't have long numerical literals, like "45L". Numeric literals are a special type called universal integer and adapt to fit the requirements of an expression. C: Ada strings do not end with an ASCII 0 character: they end with the upper bound of the array that encloses them. To change an Ada string into a C string, concatenate a null character like this: "This is my string" & ASCII.NUL; There are three kinds of real numbers. A fixed, or fixed point, number is a number that has a fixed number of decimal points. For example, U.S. dollars are often represented using fixed numbers because there are two decimal places. A float, or floating-point, number is a number that doesn't have a fixed number of decimal places. Decimal numbers are a variation of fixed numbers commonly used for currency. Some Ada programmers recommend that floats are used whenever possible because float calculations are usually faster than fixed calculations. This is because most computers today have floating point support in their hardware. Floating point numbers are very important for business and scientific applications. When floating point numbers are converted to integers, do the numbers round to the nearest integer or is the decimal part simply discarded? In C, this is system dependent: System V-based UNIX's usually round to the nearest integer, while some other systems discard the decimal part. (Others, like HP-UX, the number rounds towards the nearest even integer providing the floating point number is exactly half way between two integers.) On Linux, C truncates the decimal part. In Ada, the way numbers round are strictly defined by the language: you can be sure that, no matter what operating system you are using, floating point numbers converted to integers will always round to the nearest integer. If the floating point number is half way between two integers, it will round "up". The following program demonstrates floating point rounding:
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (5 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

with ada.text_io, ada.float_text_io; use ada.text_io, ada.float_text_io; procedure rounding is -- rounding example procedure ShowRounding( f : float ) is -- show the floating point value, and show the value -- after it's converted to an integer int_value : integer; begin Put( " Float number " ); Put( f, fore => 5, aft => 3 ); int_value := integer( f ); Put_Line( " rounds to " & int_value'img ); end ShowRounding; begin Put_Line( "This is a demonstration of how Ada 95 rounds" ); New_Line; ShowRounding( ShowRounding( ShowRounding( ShowRounding( ShowRounding( end rounding; 253.0 ); 253.2 ); 253.5 ); 253.8 ); -253.8 );

This is a demonstration of how Ada 95 rounds Float Float Float Float Float number number number number number 2.530E+02 2.532E+02 2.535E+02 2.538E+02 -2.538E+02 rounds rounds rounds rounds rounds to 253 to 253 to 254 to 254 to -254

You can compare the results with the following C program: #include <stdio.h> static void show_rounding( float f ) { int i; i = f; printf( " Float number %g", f ); printf( " rounds to %d\n", i );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (6 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

} /* show rounding */ int main () { show_rounding( show_rounding( show_rounding( show_rounding( return 0; } 253.0 253.2 253.5 253.8 ); ); ); );

Float Float Float Float

number number number number

253 rounds to 253 253.2 rounds to 253 253.5 rounds to 253 253.8 rounds to 253

Rounding to integers is a common way in C business applications to round money to the nearest dollar or cent. This is accomplished by multiplying the floating point value by 100.0, adding .5, and then taking the integer value and converting it once more into a floating point value. In Ada, there's a built-in type attribute to round floating point numbers: this makes conversion to an integer unnecessary. C: The fundamental integer types don't "wrap around" the way C data types do. Values that grow too large produce overflow errors. However, gnat turns off integer overflow exceptions by default to improve performance. Ada provides properly behaved C types and conversion functions in the Interfaces.C package. Interfaces.C includes the following types: type int is new Integer; type short is new Short_Integer; type long is range -(2 ** lbits1) .. +(2 ** lbits1) - 1; type signed_char is range SCHAR_MIN .. SCHAR_MAX; for signed_char'Size use CHAR_BIT; type unsigned is mod 2 ** int'Size; type unsigned_short is mod 2 ** short'Size; type unsigned_long is mod 2 ** long'Size; type unsigned_char is mod (UCHAR_MAX + 1); for unsigned_char'Size use CHAR_BIT; GNAT has a second package, Interfaces.C.Extensions, that includes additional types, such as unsigned_long_long. As it's name suggests, the Text_IO package only performs I/O with text, not numbers or other types of information. If you want to print, say, and integer value using Text_IO, you must first convert the integer to a string using the 'img attribute (or 'image). (Attributes are discussed in the next section.) with Ada.Text_IO; use Ada.Text_IO; procedure basicio2 is
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (7 of 29) [7/20/2001 11:33:05 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

-- this program demonstrates more advanced input/output i : integer := 5; -- this variable contains an integer number -- i initially has the value of 5 s : string(1..20); -- this variable contains a 20 character string len : natural; begin Put_Line( "This program displays information on the screen" ); Put_Line( "and reads information from the keyboard"); New_Line; Put_Line( "'img returns the string representation of a variable's" ); Put_Line( "value. The value i is" & i'img); New_Line; s := "...................."; -- set s to 20 periods Put_Line( Put_Line( Put_Line( Get_Line( "The variable s is " & s); "Get_Line reads a string from the keyboard" ); "Type in a message up to 20 characters and press Enter:" ); s, len );

Put_Line( "After Get_Line copies your message to s, s is now '" & s & "'" ); Put_Line( "The message is" & len'img & " characters long." ); Put_Line( "The characters after your message remain unchanged." ); end basicio2;

This program displays information on the screen and reads information from the keyboard 'img returns the string representation of a variable's value. The value i is 5 The variable s is .................... Get_Line reads a string from the keyboard Type in a message up to 20 characters and press Enter: jingle bells After Get_Line copies your message to s, s is now 'jingle bells........' The message is 12 characters long. The characters after your message remain unchanged.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (8 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

with Ada.Text_IO; use Ada.Text_IO; procedure basicio3 is -- this program demonstrates more even advanced input/output i : integer := 5; -- this variable contains an integer number -- i initially has the value of 5 s : string(1..5); -- this variable contains a 5 character string len : natural; begin Put_Line( "This program displays information on the screen" ); Put_Line( "and reads information from the keyboard"); New_Line; Put_Line( "The value i is" & i'img); New_Line; Put_Line( Put_Line( Put_Line( Get_Line( "integer'value changes a string into an integer value" ); "Type in a 4 character integer characters with a leading" ); "space or negative sign and press Enter:"); s, len ); -- length of string

i := integer'value( s ); Put_Line( "The value of i is " & i'img); New_Line; end basicio3;

This program displays information on the screen and reads information from the keyboard The value i is 5 integer'value changes a string into an integer value Type in a 4 character integer characters with a leading space or negative sign and press Enter: 2345 The value of i is 2345

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (9 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Besides Text_IO, Ada provides additional "Text_IO" packages for the basic Ada data types. Using these packages, you don't need to use 'img to convert the variable to a string. For example, the package Ada.Integer_Text_IO can put and get integers, and Ada.Float_Text_IO can put and get floating point numbers. You can use these packages simultaneously with Text_IO. These additional packages do not have Put_Line or Get_Line because these are specifically for strings. The Put command has two additional capabilities: to space information to fit into specified field widths, and to display numbers in formats other than base 10. with Ada.Text_IO, Ada.Integer_Text_IO; use Ada.Text_IO, Ada.Integer_Text_IO; procedure basicio4 is -- this program demonstrates integer input/output i : integer := 5; -- this variable contains an integer number -- i initially has the value of 5 begin Put_Line( "This program displays information on the screen" ); Put_Line( "and reads information from the keyboard" ); New_Line; Put( "The value i is" ); Put( i ); New_Line; New_Line; Put_Line( "Type in an integer number." ); Get( i ); New_Line; Put( "The value i is" ); Put( i ); New_Line; New_Line; Put_Line( "'width =>' specifies the amount of room to display the number in." ); Put_Line( "This can be used to display columns of numbers." ); Put( "Using a width of 5, the value i is '" ); Put( i, width => 5 ); Put_Line( "'" ); New_Line; Put_Line( "'base =>' specifies a number system besides the normal base 10" ); Put( "Using binary notation, the value i is " ); Put( i, base => 2 ); New_Line; New_Line; Put_Line( "Set the variable Default_Width or Default_Base to avoid using" ); Put_Line( "'width =>' and 'base =>'." ); Put( "The Default_Width was " ); Put( Default_Width ); New_Line; Default_Width := 20; Put( "The Default_Width is now " ); Put( Default_Width ); New_Line;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (10 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Put( "The value i is '" ); Put( i ); Put_Line( "'" ); New_Line; end basicio4; This program displays information on the screen and reads information from the keyboard The value i is 5 Type in an integer number. 432 The value i is 432 'width =>' specifies the amount of room to display the number in. This can be used to display columns of numbers. Using a width of 5, the value i is ' 32' 'base =>' specifies a number system besides the normal base 10 Using binary notation, the value i is 2#110110000# Set the variable Default_Width or Default_Base to avoid using 'width =>' and 'base =>'. The Default_Width was 11 The Default_Width is now 20 The value i is ' 432'

Table: Predefined Text_IO packages for Numeric Types

Type Short_Short_Integer Short_Short Integer (wide) Short_Float Short_Float (wide text) Short_Integer Short_Integer (wide text) Integer Integer (wide text) Float Float (wide text) Long_Float Long_Float (wide text) Long_Integer

Text_IO Package Ada.Short_Short_Integer_Text_IO Ada.Short_Short_Integer_Wide_Text_IO Ada.Short_Float_Text_IO Ada.Short_Float_Wide_Text_IO Ada.Short_Integer_Text_IO Ada.Short_Integer_Wide_Text_IO Ada.Integer_Text_IO Ada.Integer_Wide_Text_IO Ada.Float_Text_IO Ada.Float_Wide_Text_IO Ada.Long_Float_Text_IO Ada.Long_Float_Wide_Text_IO Ada.Long_Integer_Text_IO

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (11 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Long_Integer (wide text) Long_Long_Float Long_Long_Float (wide) Long_Long_Integer Long_Long_Integer (wide) Unbounded (String) Wide_Unbounded (String) Calender.Time

Ada.Long_Integer_Wide_Text_IO Ada.Long_Long_Float_Text_IO Ada.Long_Long_Float_Wide_Text_IO Ada.Long_Long_Integer_Text_IO Ada.Long_Long_Integer_Wide_Text_IO Ada.Unbounded_IO Ada.Wide_Unbounded_IO Gnat.Time_IO

10.4 Type Attributes


Ada has a selection of attributes, or built-in functions, that can be applied to types and variables. Attributes are attached to the end of a type or variable name using a single quote. The most useful attribute, the 'img attribute, returns the ASCII image of what it's attached to, which is handy for printing values on the screen using only Ada's Text_IO package. (5)'img, for example, is the string "5". false'image, the image of the boolean value false, is the string "FALSE" in capital letters. One quirk of 'img is that if the value is a positive number, 'img adds a leading blank. 'img is a GNAT shorthand for the Ada attribute 'image. 'image requires you to specify the type of the parameter. integer'image( 5 ) is the string "5". This attribute is useful on complicated expressions where 'img won't work because of the lack of parentheses. Here's a list of Ada 95 attributes: [To Be Completed] Access - access value for an identifier Address - address value for an identifier Adjacent - the floating point value adjacent to the given value Aft - for fixed types, number of decimal digits after decimal to accommodate a subtype Alignment - storage value of an identifier Base - unconstrained subtype of a type Bit_Order - whether or not bits are high order first Body_Version [NQS] Callable - true if task can be called Ceiling - round up a floating point value Class - classwide type of an identifier Component_Size - size of array components in bits Compose Constrained Copy_Sign Count Definite Delta Denorm

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (12 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Digits Exponent External_Tag First - first index in an array First_Bit Floor - round down a floating-point value Fore Fraction Identity Image Input - convert value to a string Last - last index in an array Last_Bit Leading_Part Length - number of elements in an array Machine Machine_Emax - maximum real type exponent on your hardware Machine_Emin - minimum real type exponent on your hardware Machine_Mantissa - size of mantissa on your hardware in bits Machine_Overflows - true of your machine overflows real types [NQS] Machine_Radix Machine_Rounds Max - maximum value Max_Size_In_Storage_Elements Min - minimum value Model Modulus Output Partition_ID - for distributed processing Pos - position in a discrete type (such as an enumerated) opposite of val Position Pred - previous value in a discrete type Range - range of values for a type Read Remainder Round Rounding Safe_First Safe_Last Scale

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (13 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Scaling Signed_Zeros Size - size of storage in bytes Small Stoarge_Pool - used to set the storage pool for a pointer Storage_Size Succ - next value in a discrete type Tag - tag for a tagged record Terminated - true if task has terminated Truncation Unbiased_Rounding Unchecked_Access - return access type, but ignore scope checks Val - value of a discrete type at a certain position opposite of pos Valid - determine if the expression evaluates to a legal result Value - convert string to a value opposite of image Version Wide_Image - same as image, but for a 16-bit string Wide_Value - same as value, but for a 16-bit string Wide_Width Write Here's a list of additional gnat-specific attributes: [should fold these in above] Abort_Signal - task abort exception Address_Size - number of bits in an address Bit - offset to first bit in object Default_Bit_Order - whether or not CPU uses high order first Elab_Body - the procedure that elaborates a package body Elab_Spec - the procedure that elaborates a package spec Enum_Rep - the numerical value of an enumerated identifier Fixed_Value - unchecked conversion of integer to a fixed type Img - shorthand for image Integer_Value - the reverse of Fixed_Value Machine_Bits - for compatibility with other Ada compilers Max_Interrupt_Priority - the maximum interrupt priority Max_Priority - the maximum task priority Maximum_Alignment - determine the bit alignment of an external object Mechanism_Code - how a parameter is passed to a subprogram Null_Parameter - for passing null pointer for a composite object Object_Size - for fixed and discrete types, default allocation size Passed_By_Reference - true if type is normally passed by reference

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (14 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Range_Length - number of values in a discrete type Storage_Unit - same as System.Storage_Unit Tick - same as System.Tick Type_Class - return type basic class of an identifier (such an enumerated or array) Universal_Literal_String - return a string literal for a number Unrestricted_Access - like access, but has no accessibility or aliased view checks Value_Size - number of bits to represent a value of a given subtype Word_Size - same as System.Word_Size The following program demonstrates some of the basic Ada attributes. with text_io; procedure attrib is type enum is ( dog, mica, megabyte ); begin Text_IO.Put_Line( "Some Basic Ada Attributes:" ); Text_IO.New_Line; Text_IO.Put_Line( "Boolean bits is " & boolean'size'img ); Text_IO.Put_Line( "Short short integer bits is" & short_short_integer'size'img ); Text_IO.Put_Line( "Short integer bits is " & short_integer'size'img ); Text_IO.Put_Line( "Integer bits is " & integer'size'img ); Text_IO.Put_Line( "Long integer bits is " & long_integer'size'img ); Text_IO.Put_Line( "Long long integer bits is " & long_long_integer'size'img ); Text_IO.Put_Line( "Natural bits is " & natural'size'img ); Text_IO.Put_Line( "Positive bits is " & positive'size'img ); Text_IO.Put_Line( "Short float bits is " & short_float'size'img ); Text_IO.Put_Line( "Float bits is " & float'size'img ); Text_IO.Put_Line( "Long float bits is " & long_float'size'img ); Text_IO.Put_Line( "Long long float bits is " & long_long_float'size'img ); Text_IO.Put_Line( "Our 3 item enumerated bits is " & enum'size'img ); Text_IO.New_Line; Text_IO.Put_Line( "First integer is " & integer'first'img ); Text_IO.Put_Line( "Last integer is " & integer'last'img ); Text_IO.New_Line; Text_IO.Put_Line( "First enumerated is " & enum'first'img ); Text_IO.Put_Line( "Last enumerated is " & enum'last'img ); Text_IO.Put_Line( "Mica is in position" & enum'pos( mica )'img ); Text_IO.Put_Line( "The third enumerated is " & enum'val(2)'img );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (15 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Text_IO.New_Line; Text_IO.Put_Line( "The smallest float is" & float'small'img ); Text_IO.Put_Line( "The largest float is" & float'large'img ); Text_IO.Put_Line( "The number of digits in float is" & integer'image(float'digits) ); Text_IO.Put_Line( "The size of the mantissa in bits is" & float'mantissa'img ); Text_IO.Put_Line( "However, the CPU's mantissa is" & float'machine_mantissa'img ); end attrib;

Here are the results of the program on a Pentium II with gnat 3.11: Some Basic Ada Attributes: Boolean bits is 1 Short short integer bits is 8 Short integer bits is 16 Integer bits is 32 Long integer bits is 32 Long long integer bits is 64 Natural bits is 31 Positive bits is 31 Short float bits is 32 Float bits is 32 Long float bits is 64 Long long float bits is 9 Our 3 item enumerated bits is 2 First integer is -2147483648 Last integer is 2147483647 First enumerated is DOG Last enumerated is MEGABYTE Mica is in position 1 The third enumerated is MEGABYTE The smallest float is 1.17549435082228751E-38 The largest float is 1.93428038904620299E+25 The number of digits in float is 6 The size of the mantissa in bits is 21 However, the CPU's mantissa is 24

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (16 of 29) [7/20/2001 11:33:06 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

10.5 Operations and Expressions


Ada Operator and or xor not = /= abs mod rem and then or else in not in Description Boolean and Boolean or Boolean xor Boolean not Equals Not equals Absolute Value Integer modulus Float remainder Short circuited and Short circuited else Value in range Short for not( ...in...) C Equivalent && || ? ~ == != ? % -

Boolean operations: and, or, not, xor Comparisons: >, >=, <, <=, =, /= Unary operations: +, -, abs Binary Operations: +, -, *, /, mod, rem, &, ** C: C boolean operators always short circuit. In Ada, there are both short circuiting operations and operations that do not short circuit.

Short circuiting operations are not considered true operators, and as such, can't be overloaded (see below).

Membership Tests (in and not in) are not considered true operators and can't be overloaded. if dog in aDogBreed then Put_Line( "The dog is a breed in the enumerated aDogBreed" ); end if; if i in 1..10 then Put_Line( "I is between 1 and 10" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (17 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

end if; 1..10 is called a range. The range attribute returns the range of values for a type. if salary not in MiddleManagementSalary'range then Put_Line( "The salary is not in the middle management type's range" ); end if; C: Assignment is considered a statement, not an operator.

10.6 Variable Declarations


You define a variable as the variable name, colon, the type of information the variable will hold, and a semicolon. totalSales : float; This creates a new variable called totalSales that contains a real number. Some variations: runningTotal : integer := 0; -- this variable starts out at 0 companyName : constant string := "Bob's Widgets Inc."; --companyName is set to Bob's Widgets Inc. and it can't be changed while --the program is running char1, char2 : character; Complex variables references can be assigned a shorthand with a rename declaration. sb : float renames EmployeeList( CurrentEmployee ).SalaryInfo.Bonus; ... sb := 5.0; -- same as EmployeeList( CurrentEmployee ).SalaryInfo.Bonus := 5.0

C: There are no self-referential operators, such as C's +=.

10.7 New Types


Ada Statement type subtype Description Create a new type. Create a variation of an existing type C Equivalent typedef -

New types are defined with the type statement. type aSalary isnew float; type aSmallSalary isnew Salary range 0.0 .. 35_000.0;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (18 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

When you create a new type, the type is considered to be incompatible with the type it is derived from. If you want to add a small salary to a salary, you'll have to use type casting, even though they are both floats. totalSalary, BigSalary : aSalary; aSmallSalary : aSmallSalary; totalSalary := bigSalary + aSalary( smallSalary ); To type cast one type into another, use the type name and the value to convert in parantheses after it.

C: "(type) value" style of type casting doesn't work in Ada. C: "Ada has stronger restrictions on typecasting. In C, for example, you can cast a character pointer as an integer pointer. Although this is considered a bad programming practice, it is allowed. Ada will not allow this kind of type casting. Use subtype to create a type aSmallSalary that is compatible with aSalary. subtype aSmallSalary is aSalary range 0..35_000.0; Subtype can also be used to rename types. subtype sb is aSalaryBonusForEmployeesNamedBobStevens; In this example, sb is a short form for aSalaryBonusForEmployeesNamedBobStevens. "sb" is techncially called a "subtype mark", a term which sometimes appears in Gnat error messages. One common error, "subtype mark required in this context", indicates that there are several different types that could be used and you have to indicate to the compiler which should used.

10.7.1 Modular Types


Normally, if a calculation produces an answer too large for the variable type being assigned to, it creates an error. This is called a numeric overflow. For example, if int is an integer, int := integer'max +1; -- check (KB) will result in a constraint error because the answer is bigger than the biggest number an integer variable can contain. Ada provides another type of integer called a modular type. The word "modular" comes from the mathematical modulus operation. Modular types never overflow. Instead, if a number becomes bigger than the largest possible number the variable can contain, the value of the modular type "wraps around" to the lowest value and continues to grow from there. If the int variable in the above example was a modular called int modular, then int := intmodular'max + 1; would result in int being assigned intmodular'min. C: C integer types are all modular because C doesn't catch overflow errors. There are no built-in modular types. All modular types are new types created by a type statement. type mod10 is mod 10; -- value ranges from 0 to 9
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (19 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

10.7.2 Text_IO and New Types


To perform Text_IO input and output on new types, you have to create your own version of Text_IO for the new type. This process is called "instantiation", and is covered later in the section on generics. The format is package MyNewTextIOPackage isnew PredefinedGenericIOPackage( mytype ); For example, to create a Text_IO package for the aSalary type, package aSalary_Text_IO is new Ada.Text_IO.Float_IO( aSalary ); Ada creates a new package called aSalaray_Text_IO customized for the aSalary type. You can use your package just like one of the standard Ada numeric Text_IO packages. Salary := 50_000.00 aSalary_Text_IO.Put( Salary ); The following table lists all the Text_IO packages that can be instantiated for a particular type.

Table : Predefined generic Text_IO packages for performing Input/Output Base Type Complex Numbers Complex Numbers (wide text) Decimals (NQS) Decimal Numbers (wide text) Enumerateds Enumerateds (wide text) Fixed Points Fixed Points (wide text) Floating Points Floating Points (wide text) Integers Integers (wide text) Modulars Modulars (wide text) Package Ada.Text_IO.Complex_IO Ada.Wide_Text_IO.Complex_IO Ada.Text_IO.Decimal_IO Ada.Wide_Text_IO.Decimal_IO Ada.Text_IO.Enumeration_IO Ada.Wide_Text_IO.Enumeration_IO Ada.Text_IO.Fixed_IO Ada.Wide_Text_IO.Fixed_IO Ada.Text_IO.Float_IO Ada.Wide_Text_IO.Float_IO Ada.Text_IO.Integer_IO Ada.Wide_Text_IO.Integer_IO Ada.Text_IO.Modular_IO Ada.Wide_Text_IO.Modular_IO

10.8 Aggregate Types


Arrays are tables of values with specific bounds. For example, to declare a table of 10 people type peopleHeightList is array( 1..10 ) of integer; The bounds can be specified as a type.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (20 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

type peopleHeight is new integer range 1..10; type peopleHeightList is array( peopleHeight ) of integer; This creates an array from 1 to 10, the range of possible values for the type peopleHeight. This is the same as using array( peopleHeight'range ). You can create a multidimensional array by using more than one index to the table. type peopleStats is array( peopleHeight, peopleAge ) of integer; You can assign default values to an array using :=, the assignment operator. The list of values is enclosed in brackets. You can specify a specific value using =>, or specify a default with others =>. PeopleHeights1 : peopleHeightList := (others => 0); -- looks strange, but assigns 0 to all the heights in the entire list peopleHeights2 : peopleheightList := ( 10, others => 0 ); -- first height is 10, others are 0 peopleHeights3 : peopleHeightList := (5 => 15, others => 0 ); -- fifth height is 15, others are 0 Arrays are accessed by specifying values for the indices. To get the height for the fifth element in the PeopleHeights1 array, you'd type: Put_Line( PeopleHeights1( 5 )'img ); Records are collections of related information. Each subsection is referred to as a field. type employeeProfile is record name : string( 1..80 ); salary : aSalary; age : anAge; end record; You can assign default values to the fields in a record using :=, the assignment operator. type employeeProfile isrecord name: string( 1..80 ) := (others => ' '); salary : aSalary := 30_000.0; age: anAge := 30; end record; Default values for whole records can be specified when record variables are declared. Bob : employeeProfile := ("Bob Smith", 35_000.0, 37 ); Denise : employeeProfile := ( name => "Denise Jones", salary => 39_000.0, age => 42 ); In the above examples, we are creating a temporary record and then assigning that record to the variable. You can use this in the executable part of your program, not just in declarations. Ada will require a "subtype mark", an indication of what type of record you are making. NewRec := employeeProfile'("Bob Smith", 35_000.0, 37 ); employeeProfile' indicates that the record we've built should be treated as an employeeProfile record.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (21 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

Although this looks almost exactly the same as type casting, it isn't type casting. Consider the following: J := long_integer'( 5 ); J := long_integer( 5 ); The first statement clarifies that 5 is a long_integer: this is a hint to the compiler that 5 should be treated as an long_integer. The second converts 5 from an integer to a long_integer. Record fields are accessed using a period and the field name. Bob.age := 37; A variant record is a record that contains different sets of mutually exclusive information. type employeeProfile( sex : aSex ) is record name : string( 1..80 ); salary : aSalary; age : anAge; case sex is when male => BeardLength : integer; when female => null; end record; (check syntax) In this example, a male employee has an additional field called BeardLength. (when you create a variant record, you must specify the descriminant).

10.9 Enumerated Types


Enumerated types (lists of identifiers) are created using a type statement. type aDogBreed is ( Unknown, Boxer, Retriever, Shepherd, MixedBreed ); Different enumerated types may have the same values, but they are considered different from each other. For example, type aCatBreed is ( Unknown, Siamese, MixedBreed ); shares two values with aDogBreed, but an unknown cat breed is considered different from an unknown dog breed. If Ada is confused by the ambiguity, you can clarify values with a subtype mark, e.g. aCatBreed'(MixedBreed). Many of the common attributes work with enumerated types, including 'first, 'last, and 'range. Especially useful are 'pred (get a previous enumerated identifier) and 'succ (get the next enumerated identifer). Specific values can be assigned (using a for clause) so the enumerated type can reflect an external integer value (such as error codes). with ada.text_io, unchecked_conversion; use ada.text_io;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (22 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

procedure enumeration_fun is -- a demonstration of Ada 95 enumerated types type vowels is ( 'a', 'e', 'i', 'o', 'u', none ); -- characters may be used as well as identifiers. -- character sets are implemented this way.

The standard

type aDogBreed is ( Jack_Russel, Labrador, German_Shepherd, Other ); type aCanadianRegion is ( West_Coast, Arctic, Labrador, Other ); subtype coldPlaces is aCanadianRegion range Arctic..Other; -- names may overlap between enumerated types type anErrorCode is ( None, IOerror ); for anErrorCode use ( None => 0, IOerror => 7 ); -- specific values may be assigned to enumerated identifiers function toInteger is new unchecked_conversion( anErrorCode, integer ); begin -- Basic enumerated type operations put( "The vowel 'u' has a position of" ); put( integer'image( vowels'pos( 'u' ) ) ); put_line( " in the list." ); put( "The vowel after 'a' is" ); put( vowels'image( vowels'succ( 'a' ) ) ); put_line( "." ); -- Using a regular enumerated. Where an identifer belongs to -- two enumerated types, we have to apply a type qualifier when -- ambiguity comes up. put( "The item before German_Shepherd is " ); put( aDogBreed'image( aDogBreed'pred( German_Shepherd ) ) ); put_line( "." ); put( "The item after Labrador (the region) is " ); put( aCanadianRegion'image( aCanadianRegion'succ( Labrador ) ) ); put_line( "." ); put_line( "Listing of cold regions between 'Labrador' and 'Other':" ); for cr in coldPlaces'(Labrador)..other loop put_line( aCanadianRegion'image( cr ) ); end loop; -- Using an enumerated with assigned numbers. -- we assigned, we need unchecked_conversion. To get the number

put( "Error code " & anErrorCode'image( IOerror ) ); put( " is in position" & integer'image(anErrorCode'pos( IOerror ) ) );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (23 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

put_line( "." ); put( "IOerror has a value of" & integer'image( toInteger( IOerror ) ) ); put_line( "." ); put( "The code before IOerror is " ); put( anErrorCode'image( anErrorCode'pred( IOerror ) ) ); put_line( "." ); put( "The code after NONE is " ); put( anErrorCode'image( anErrorCode'succ( None ) ) ); put_line( "." ); end enumeration_fun;

The vowel 'u' has a position of 4 in the list. The vowel after 'a' is'e'. The item before German_Shepherd is LABRADOR. The item after Labrador (the region) is OTHER. Listing of cold regions between 'Labrador' and 'Other': LABRADOR OTHER Error code IOERROR is in position 1. IOerror has a value of 7. The code before IOerror is NONE. The code after NONE is IOERROR. The boolean type is implemented as an enumerated with two values, true and false. False is always the predecessor of true. C: Ada enumerated types have more features than C's. You can use 'pred and 'succ to move through the list without casting the enumerated as an integer and using arithmetic. The position of an enumerated identifer is independent of its assigned value.

10.10 Procedures and Functions


Ada Statement procedure function declare/begin Description A subprogram that returns no value for expressions. A subprogram that returns a value for expressions.. A nested block C Equivalent void f(...); sometype f(...); {...}

There are several ways to break up an Ada program. First, a procedure, such as the main program, is a subprogram which returns no value. procedure print_test is begin Text_IO.Put_Line( "This is a test" ); end print_test;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (24 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

C: a procedure is a void function. The second is a function. A function is a procedure that can be used in a expressions because it returns a value. The value is returned with a return statement. function AddOne( X : integer ) return integer is begin return X+1; end AddOne; AddOne adds one to whatever is in the brackets. To add one to a variable called subtotal, you'd use it like this: Total := AddOne( SubTotal ); The value in the brackets is the parameter to the function. Parameters have modes: in, out or in out. In, which is the default if you specify a mode, means that the variable is treated as a constant. Out means the value is returned when the subprogram is finished. In out means the value goes into the subprogram, is changed, and is returned again when the subprogram is finished. In Ada, functions can only have in parameters, but procedures can have all three. procedure AddOne( x : in out integer ) is begin X := x + 1 end AddOne; ... AddOne( Subtotal );

C: There is no equivalent of pass-by-copy or pass-by-reference. See the section on interfacing C and Ada. There is also a special access mode, which means that the parameter must be an access variable. This is especially useful with tagged records. You can also get around the in out restriction on functions with the access mode. It is discussed in 11.10.2. C: An access variable is basically a pointer. These are described later. An example of multiple parameters: procedure DisplayCurrency( c : aCurrency; fieldWidth : integer; useDollarSign : boolean := true ) is useDollarSign, the third parameter, has a default value of true. Here's now you can call this procedure: DisplayCurrency( 1.97, 8 );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (25 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

DisplayCurrency( 1.97, 8, false ); DisplayCurrency( 1.97, 8, useDollarSign => false ); DisplayCurrency( c => 1.97, fieldWidth => 8, useDollarSign => false ); If you really wanted to, you can also change the order of the parameters using the => convention. DisplayCurrency( fieldWidth => 8, useDollarSign => false, c => 1.97 ); You can also declare arbitrary blocks in Ada. These let you declare variables in the middle of a procedure or function or set apart the designated source code in it's own block. The form of a block is an optional declare section, and the block denoted by a begin and end. procedure nested is Date : integer; begin Date := 0; declare DaysInYear : constant integer := 365; begin Date := Date + DaysInYear; end; end nested; Here, DaysInYear only exists for the assignment statement that follows it. The main reason for blocks is to add an exception hander to a particular line without having to write a one line procedure. begin Total := Total / Average; exception when numeric_error => Text_IO.Put_Line( "Division by zero!" ); Total := 0; end; Here, if there's a numeric error during the division statement, it's caught and handled. Operators are in-fix functions, ones that take parameters on their left and right. For example, "+" is an operator. Ada lets you redefine most of the standard operators so they work with types of your choosing. You enclose the operators' symbol in double quotes. function "+"( e : employeeRecord, s : aSalary ) returns aSalary is begin return e.salary + s; end function; The above function will let you add a salary to an employee record, which assumes you are referring to the salary field in the employee record. Ada subprograms can have the same name as long as their parameters or return values are different. This is called overloading. If Ada can't determine which subprogram you are referring to, you'll receive an error when compiling. In the above example, "+" is overloaded since there's integer addition, floating addition, and the other built-in
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (26 of 29) [7/20/2001 11:33:07 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

meanings for "+", and our special salary addition we just defined. C: Assignment is not an operator in Ada. Assignment overloading can be simulated with controlled tagged records and the Adjust procedure.

10.11 Control of Flow


Ada Statement if for while loop exit case goto Description Conditional execution Interative loop Pretest loop Indefinite loop Loop exit Multiple case conditional execution Unconditional jump C Equivalent if for while break switch goto

The if statement is, well, a standard if statement which you can find in many languages. Here's an example: if x > 0 then Text_IO.Put_Line( "X is positive" ); elsif x < 0 then Text_IO_Put_Line( X is negative ); else Text_IO.Put_Line( "X is zero" ); end if; Ada provides two expression short-circuiting operators: "or else" and "and then". Short-circuiting means that the expression will not be evaluated if the left side doesn't satisfy the condition. if x > 0 or else y > 0 then In this case, y > 0 is only checked if x is not greater than zero. There is a general purpose loop statement, loop. Loops are exited with an exit statement. Ada provides a shorthand, exit when, to exit on a condition. loop X := X / 2.5; exit when X < 4.0; X := X + 1.0; end loop;

C: There is no general purpose loop in C.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (27 of 29) [7/20/2001 11:33:08 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

C: There's no equivalent of the C continue statement. There is a pretest loop, while, which determines whether or not the loop should be entered or reentered based on an expression at the top of the loop; while X >= 4.0 loop x := ( x / 2.5 ) + 1.0; end loop;

C: This is the equivalent of a C while loop. There is no post-test loop, like C's do loop. There is the standard for loop as well, to loop through a range of numbers. For loops in Ada may only loop by discrete numbers one unit at a time: no real numbers and no arbitrary stepping values. To go backwards through a range, use the word reverse. for I in 1..10 loop Total := Total + 1; end loop; To loop through an entire range of a type, use the 'range attribute. To loop through all the dogs in an enumerated type called aDogBreed, for dog in aDogBreed'range loop Also note that dog is implicitly defined. You don't have to declare it. Ada understands the type from the loop and the loop variable exists for the duration of the loop.

C: For is much more structured than C's for. Any loop can be exited with exit (or exit when). Ada allows you to label loops in order to exit out of several loops at once. In the following example, exit will exit the current loop and all loops up to and including OuterLoop. In this case, that's both loops. OuterLoop: while y > 0 loop while x > 0 loop x := x - y; if x = 37 then exit OuterLoop; end if; end loop; y := y * 2; end loop; There is a case statement as well, for testing a lot of different individual values. Ada requires a when others case to
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (28 of 29) [7/20/2001 11:33:08 AM]

Big Online Book of Linux Ada Programming - 10 An Introduction to Ada

make sure that all possible cases are handed. case DogBreed is when Unknown => Text_IO.Put_Line( "I don't know the breed" ); when Shepherd => Text_IO.Put_Line( "It's a shepherd" ); when others => Text_IO.Put_Line( "It's something else" ); end case; Ada also as a null statement, which is a placeholder to use when a statement is expected but none is needed. For example, you can't have an empty if statement--there must be at least a "null;". Multiple cases can be included with the vertical bar, or a range can be specified with an ellipsis. case TaxType is when local_tax => Tax := Tax + LocalTax; when federal_tax | govt_taxable => Tax := Tax + FederalTax; when others => null; -- perhaps a warning would be better here instead end case;

C: case is like switch, but the cases don't fall through. Cases can also use ranges, such as 1..10 or TaxSubtype'range. I really like goto's, and through a stroke of good luck, Ada includes a goto. Goto labels are denoted with double angle brackets (unlike loop labels that use a colon). for I in 0..10 loop -- some computations here if emergency then goto Help; end if; end loop; -- stuff that must not be executed in an emergency <<Help>> Text_IO.Put_Line( "We are now down here" );

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/10.html (29 of 29) [7/20/2001 11:33:08 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

11 Advanced Ada Programming


<--Last Chapter Table of Contents Next Chapter-->

11.1 Packages
Ada package Description Define a package C Equivalent -

C:In C++, classes serve two purposes. First, they hide declarations. Second, they implement objects. In Ada, declaration hiding is done separately with packages: you do not need to use tagged records to use packages. Large Ada programs are divided up into packages. These are collections of procedures, functions, variables and other declarations that serve a similar purpose. You can have packages to draw text on the screen, or packages to do accounts payable, or package to work with complex numbers. To make it easier for different people to work on different packages, and to make packages self-documenting, Ada packages are divided into two parts. The package specification (or package spec) contains everything that other programs need to use your package. It contains all variables they can access, all the subprograms they can call, etc. For subprograms, you only use the subprogram header, the procedure or function line, to let the programmers know the name of the subprogram and what the parameters are. C: Subprograms declared in package specs are similar to C (non-static) function prototypes in header files. Unlike prototypes, which are optional, declarations in the package specs are required for subprograms to be exported outside of the package.

package Currency is -- This package defines US and Canadian dollars, and converts money between -- these two countries. subtype aMoney is float; type USDollars is new aMoney; type CanadianDollars is new aMoney; -- aMoney is separate so we can change the base type, if necessary, for -- US and Canadian dollars. USDollars and Canadian dollars deliberately -- incompatible because it could be messy if we mix them up procedure SetExchangeRates( USToCanadian, CanadianToUS : float ); function ToCanada( money : USDollars ) return CanadianDollars; function ToUS( money : CanadianDollars ) return USDollars;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (1 of 39) [7/20/2001 11:33:44 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

-- Set the exchange rate between US and Canada, and two functions to -- convert between currencies. end Currency; In GNAT, you must save this package under the filename "currency.ads" (.ads for Ada Spec ). Here we create different money values two functions to convert between the different rates and a procedure to set the exchange rates to use in the functions. Notice there is no main program. With the spec complete, you can compile it to check for errors. To complete the package, we create a package body with the rest of the details, including the completed subprograms. With the implementation details hidden in the package body, other programmers don't have to worry about how currency is actually handled. package body Currency is

-- This package defines US and Canadian dollars, and converts money between -- these two countries. USToCanadaExchangeRate : float; CanadaToUSExchangeRate : float; procedure SetExchangeRates( USToCanadian, CanadianToUS : float ) is begin USTOCanadaExchangeRate := USToCanadian; CanadaToUSExchangeRate := CanadianToUS; end SetExchangeRates; function ToCanada( money : USDollars ) return CanadianDollars is begin return CanadianDollars( money * USToCanadaExchangeRate ); end ToCanada; function ToUS( money : CanadianDollars ) return USDollars is begin return USDollars( money * CanadaToUSExchangeRate ); end ToUS; -- Set the exchange rate between US and Canada, and two functions to -- convert between currencies. end Currency; Notice we have access to everything we defined in the package spec--we don't need to repeat anything in the body. Because the two exchange rate variables are defined inside the package body, they are invisible to other programmers. Save this package body as "currency.adb" (.adb for AdaBody). Make sure all pragma Stubbed's are removed for the finished subprograms. Compile both and you have a working package. To use your package in a program, use the with statement. with text_io, currency; procedure currencyTest is begin Currency.SetExchangeRate( 1.5, 0.7 );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (2 of 39) [7/20/2001 11:33:44 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Text_IO.Put_Line( "1 Canadian dollar is " & Currency.ToUS( 1.0 )'img ); end currencyTest; To have Ada check which package a subprogram belongs to, and avoid typing the package name constantly, use the use statement. with currency; use currency; ... SetExchangeRate( 1.5, 0.7 ); If the use statement creates an ambiguity, Ada will warn you that it can't determine which package SetExchangeRate is in. Package bodies may have main programs, a block at the end of all declarations marked with begin. This allows you to setup your package before it's actually used. In this case, we don't need one. Package specs may have private sections at the end of the spec. There will be times when you will have to provide information so that Ada can compile your spec, but you don't want the application programmer to be able use this information. For example, you might create a package to maintain a customer list, but you don't want the programmer to access the internal fields of a customer list since you might change them at some point. Just about anything in a package spec can be marked private, and the compiler expects the details to be specified in the private section. Declarations can also be limited private, meaning that besides having the details inaccessible to the programmer, the programmer can't assign between variables of the type. For example, use limited private if you think you may include pointers in the type at some time in the future. package CustomerList is

type aCustomerNumber is new positive range 1..1000; type aCustomerList is limited private; private type aCustomerArray is array( aCustomerNumber ) of string(1..120); type aCustomerList is record CurrentCustomer : aCustomerNumber; Customers : aCustomerArray; end record; -- no pointers yet, but we may some day, so it's limited private end CustomerList; In this example, a programmer can declare customer lists, but he cannot access the fields CurrentCustomer or Customers (because it's private), nor can he copy lists with assignment statements (because it's limited private). C: In C++, privacy is limited to classes. In Ada, virtually anything can be private. Packages can have children. A child package is a package that extends the capabilities of the parent package. You can use child packages to add features to existing packages, such as the standard Ada libraries, or to break up large packages into groups of related functions. Suppose you had a package called accounting that contains tools to handle accounting in general. You can create a child package for accounts payable begins like this: package Accouting.Accounts_Payable is In GNAT, save this package spec as "accounting-accounts_payable.ads", with a minus sign instead of a period.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (3 of 39) [7/20/2001 11:33:44 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

A child package inherits the package spec from it's parent package. You can access anything in the accounting package, including anything private to which access is normally denied. When a program uses the statement with Accouting.Accounts_Payable; the parent package, accounting, is automatically with'ed as well (although you still have to use separate use's).

11.2 Controlling Elaboration


Ada Pragma pragma pragma pragma pragma pragma pragma pragma Description The simplest kind of package. Pure; When an entire package isn't Pure_Function( function_name); pure... A package with simple Preelaborate; elaboration. Similar to Preelaborate. No_Elaboration_Code; Force "package" to be elaborated Elaborate( package ); first, if possible. Elaborate the body before the Elaborate_Body( package ); specification. Short for Elaborate() for each Elaborate_All; package. C Equivalent -

Elaboration is the initialization of a package that's done before the main program of the package is executed. Assigning values to constants, for example, is elaboration. C: Since C is a has no packages, the order of elaboration between files is determined strictly by the compilation order. For most projects, gnat will work out a good elaboration order on its own. However, large projects with packages referring to each other in complicated ways may require complex elaboration orders. gnat searches every possible elaboration order until it finds one that solves any ambiguities. To speed up projects with slow elaboration times, Ada and gnat provide a number of pragmas to give the compiler hints on the best compilation order and to solve any potential ambiguities.

11.2.1 First line of defense: Pure, Preelaborate and No_Elaboration_Code


Pragma Pure and Preelaborate are elaboration restrictions. They are hints to the Ada compiler to cut down the compiler's work when trying to solve elaboration order. Pragma Pure tells Ada that the package requires no elaboration and contains no executables. For example, a package of nothing but type declarations (with no default values) is pure. package money_types is pragma pure; -- a simple package, nothing to elaborate subtype aCurrency is float; type aSalary is new aCurrency;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (4 of 39) [7/20/2001 11:33:44 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

end money_types; Pragma Preelaborate tells Ada that the package requires minimal elaboration. You should try pragma pure, and if it fails, try pragma preelaborate. gnat 3.11 introduced the gnat specific pragma No_Elaboration_Code. Sometimes this will work when Preelaborate will not. Sometimes you can declare a function as pure using pragma Pure_Funciton. A pure function is one with no side effects and one that's value doesn't change when executed with the same parameters each time. If the only thing standing in your way to using pure or preelaborate are some functions used to assign initial values, try declaring them as pure functions. If your package or program fails to meet the elaboration restriction requirements, the compiler will issue an error.

11.2.2 Second line of defense: Elaborate, Elaborate_Body, Elaborate_All


Sometimes the hints are not enough. For example, a package that assigns a value to constant using a function like Sin45 : float := Ada.Numerics.Elementary_Functions.Sin( 45, 360 ); is neither pure nor preelaborate because a function must be called when the package is initialized. In these cases, you can tell Ada specifically which package should be elaborated first. Pragma Elaborate( package ) tells Ada the specified package should be elaborated first. For example, all generics must be elaborated before they are used, so it's a good idea to use pragma elaborate on every generic package. with generic_linked_list; pragma Elaborate( generic_linked_list ); Pragma Elaborate_All indicates that a particular package and all the packages used by that package must be elaborate before the current package. For example, if package userio uses package common, with userio; pragma Elaborate_All( userio ); will elaborate both userio and common prior to this package Because Elaborate_All will affect multiple packages, it can cause unnecessary binding errors when used indiscriminately. This pragma, when used everywhere, effectively requires all packages to be arranged in a strict hierarchy. Make sure this is the effect you want.

11.2.3 Other Elaboration Pragmas


Another pragma, pragma Elaborate_Body, forces the package body to be elaborated before the package specification. This is especially useful in generic packages. Pragma Elaborate and Elaborate_All can also be used to resolve ambiguous elaborations.

11.3 Objects
Ada type...tagged record type...new parenttype with record type...access all sometype Description Define an object Extend an object Define a pointer to a class C Equivalent class class ...: parenttype sometype *

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (5 of 39) [7/20/2001 11:33:44 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

'class abstract

Class-wide type virtual Abstract types/subprograms function...=0

C: Ada developed its own object oriented terminology because C's terminology can be ambiguous and confusing. Ada differentiates between a class and the structure that defines that class. An object in Ada is known as a tagged record. That is, it is a normal Ada record that has an invisible tag attached to it. The record type anEmployeeProfile is record name : string(1..80); age : anAge; end record; can be changed to a tagged record by adding the keyword tagged: type anEmployeeProfile is tagged record name : string(1..80); age : anAge; end record; Although these two records look the same, if we use the 'size attribute to see how much memory the records take up, we'll see that the tagged record is bigger. The extra space is used to store the invisible tag. Unlike normal records, fields can be added tagged record and a new tagged record can be created. This is called extending the record. To create a related record with additional fields, we use the keyword new: type anHourlyEmployee is new anEmployeeProfile with record hourlyRate : float; end record; A tagged record extended in this way has all the fields of anEmployeeProfile, but has the additional field of hourlyRate. anEmployeeProfile and anHourlyEmployee are said to be in the anEmployeeProfile class: the class is the collection of anEmployeeProfile and all record extended from it. Now we can create a access type (commonly called a pointer, though technically it isn't a pointer) to any record in the class: type anEmployeeProfilePtr is access all anEmployeeProfile'class; This pointer can be assigned either anEmployeeProfile record or anHourlyEmployee record. This is the purpose of the tagged record's invisible tag. The tag indicates the type of tagged record a pointer points to since these kinds of pointers can refer to more than one type of tagged record. This is sometimes called late binding. ptr1 : anEmployeeProfilePtr := new anEmployeeProfile( "Bob Smith", 45 ); ptr2 : anEmployeeProfilePtr := new anHourlyEmployee( "Denise Jones", 37, 17.50 ); Access variables are null until assigned a different value. They are the only variables in Ada to have a default value. There may be cases where you want to extend a type without adding new fields. Ada provides a shorthand phrase for this. For example, if you want to distinguish hourly employees that work at night as being separate from other hourly employees, use type aNightHourlyEmployee is new anHourlyEmployee with null record; In complex classes, there will be times when you'll want to define a record that you never intend to assign variables to. For example, anEmployeeProfile doesn't contain enough fields to completely describe any employee: only the tagged records

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (6 of 39) [7/20/2001 11:33:44 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

derived from anEmployeeProfile are usable. When particular record exists only to be extended it called an abstract record. You declare abstract records with the keyword abstract: type anEmployeeProfile is abstract tagged record name : string(1..80); age : anAge; end record; If you try to create anEmployeeProfile record, Ada will report an error since you said that this record can only be extended into other records. Ada requires that subprograms that work with tagged records be declared immediately after the type declaration. Each procedure or function can only take one tagged record as a parameter. C: Methods are normal subprograms with an object being referred to as a parameter. myobj.method( x ) would be method (myobj, x) or method( x, myobj) in Ada. type aSalaryEmployee is new anEmployeeProfile with record salaryRate : float; end record; procedure SetSalaryRate( s : in out aSalaryEmployee'class; rate : float ) is begin s.salaryRate := rate; end SetSalaryRate; function GetSalaryRate( s : aSalaryEmployee'class ) return float is begin return s.salaryRate; end GetSalaryRate; We've declared two one line subprograms that will work on any tagged record derived from aSalaryEmployee. C: Ada does not require constructors or destructors. Creating objects with these are discussed below. Subprograms can be marked as unusable in the same way as abstract tagged records. An abstract procedure or function is a placeholder. Declaring one requires that all types extended from this type must have this subprogram defined. If any do not have this subprogram, Ada will report an error. For example, if anEmployeeProfile had a procedure like procedure WriteEmployeeName( e : anEmployeeProfile ) is abstract; all employee profile records would be required to have a procedure called WriteEmployeeName. ASalaryEmployee will have a compilation error unless we add such a function: procedure WriteEmployeeName( e : aSalaryEmployee )is begin Text_IO.Put_Line( "Employee Name: " & e.Name ); end WriteEmployeename; WriteEmployeeName could also use aSalaryEmployee'class to refer aSalaryEmployee or any records we extend from it. To avoid ambiguity, only one tagged record subprogram can refer to any one type. This is different from some other object oriented languages where you can override a classwide subprogram with one that refers to a specific type. The advantage of no overriding is that someone reading your class knows exactly which subprogram will be used for a particular tagged record type--they don't need to read the entire class to make sure the subprogram isn't overridden later on. The disadvantage is that if
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (7 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

you can't use a classwide type, you'll have to write subprograms for each and every type in that class. In these cases, typecasting is useful. Tagged record types can be typecast as other tagged record types (in the same class) using typecasting. You need to do this if you want a dispatching call inside of a dispatching call. For example, if anEmployeeProfile has a GetSalaryRate function, we could call it by: procedure WriteEmployeeSalary( e : aSalaryEmployee'class ) is begin Text_IO.Put_Line( "The salary is" & GetSalaryRate( anEmployeeProfile( e ) ) ); end WriteEmployeeSalary;

11.4 Objects with Automatic Initialization/Finalizaton


Ada Controlled Object Call Initialize Adjust Finalize Description Initialize an object Fix object after assignment Clean up an object C Equivalent constructor copy constructor destructor

Basic Ada tagged records don't do anything special when they are created or destroyed. If you want special actions to be executed automatically when a tagged record is created or destroyed, you can use the Ada.Finalization package. In this package is defined a special tagged record called Controlled. When you extend this tagged record, you can overload special procedures that Ada will automatically execute when necessary. This saves you from having to explicitly call such procedures yourself. type businessDepartment is new Finalization.Controlled with record departmentHead : aEmployeeProfilePtr := new aSalaryEmployee ( "Bob Smith", age => 45, rate => 42_000.0); end record; In this example, every time you allocate a businessDepartment variable, DepartmentHead is initialized with a dynamic allocation. We could write a procedure to free up this memory, but then we would have to remember to call it every time a variable is about to be discarded. A better way to handle this is to let Ada do the discarding for us. Finalize is the name of the procedure Ada calls when cleaning up a controlled tagged record. We create our own Finalize for our businessDepartment tagged record: procedure Finalize(bd : in out businessDepartment) is begin -- Finalize Free( bd.departmentHead ); end Finalize; Now Ada will automatically run this procedure before any businessDepartment variable is destroyed and we never have to worry about forgetting to free up the memory used by departmentHead. C: Finalize is the destructor. There are two other such automatic procedure we can use with controlled tagged records. Procedure Initialize is used when an object is first created, and procedure Adjust is used after an object is assigned in an assignment statement.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (8 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Adjust is very smart. Temporary storage is used for self-assignment. If Adjust fails because of an exception, Finalize is not executed. C:Adjust is like a C++ copy constructor, except that Ada will copy the object before calling Adjust. With a copy constructor, you must copy the object yourself in the body of the constructor. Unlike a copy constructor, Adjust only executes during assignment. with text_io, sample; use text_io, sample; procedure controlledtest is srp1, srp2 : SampleRecPtr; sr3 : SampleRec; begin Put_Line( "(This is the first line of the program)"); New_Line; Put_Line( "This is an example of controlled tagged records:" ); New_Line; Put_Line( "Executing 'srp1 := new SampleRec'"); srp1 := new SampleRec; New_Line; Put_Line( "Executing 'srp2 := srp1' (copying a pointer)" ); srp2 := srp1; New_Line; Put_Line( "Executing 'sr3 := srp1.all' (copying a record pointed to)" ); sr3 := srp1.all; New_Line; Put_Line( "(This is the last line of the program)"); end controlledtest;

with ada.finalization; use ada.finalization; package sample is type SampleRec is new Controlled with null record; type SampleRecPtr is access all SampleRec; -- sample controlled tagged record (and a pointer to same) procedure Initialize( sr : in out SampleRec ); procedure Finalize( sr : in out SampleRec ); procedure Adjust( sr : in out SampleRec ); -- these are required for controlled tagged records end sample;

with Ada.text_io; use Ada.text_io;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (9 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

package body sample is -- just print messages to show that these are working procedure Initialize( sr : in out SampleRec ) is begin Put_Line( "Initialize: Initialized tagged record" ); end Initialize; procedure Finalize( sr : in out SampleRec ) is begin Put_Line( "Finalize: Finalized tagged record " ); end Finalize; procedure Adjust( sr : in out SampleRec ) is begin Put_Line( "Adjust: Adjusted tagged record " ); end Adjust; end sample; Here is the output. The records being affected are noted in bold. Initialize: Initialized tagged record [sr3] (This is the first line of the program) This is an example of controlled tagged records: Executing 'srp1 := new SampleRec' Initialize: Initialized tagged record [srp1.all] Executing 'srp2 := srp1' (copying a pointer) Executing 'sr3 := srp1.all' (copying a record pointed to) Finalize: Finalized tagged record [sr3 (before record is copied)] Adjust: Adjusted tagged record [sr3 (after record is copied)] (This is the last line of the program) Finalize: Finalized tagged record [srp1.all] Finalize: Finalized tagged record [sr3] Ada also provides a second tagged record, Limited_Controlled, which is a controlled record that can't be assigned. Consequently, it has no adjust procedure.

11.5 Multiple Inheritance


Like a tree, tagged records can only be extended from a single parent. Extending from multiple parents is called multiple inheritance, and Ada doesn't allow multiple inheritance. The Ada designers considered multiple inheritance a feature that adds ambiguity to a language: for example, if an employee tagged record has two different parents, each with a salary field, do you merge the salary fields into one or do you have two copies of the field in your record? Because there is no consistent solution to this kind of problem, the Ada designers decided to not to support multiple inheritance. However, you can add tagged records as nested fields, just like you would a normal record. This workaround guarantees that each object will only have one parent it can extend from.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (10 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

type aClass is tagged record F1 : integer; end record; type anUnrelatedClass is tagged record U1 : integer; end record; type anMIExample is new aClass with UC : anUnrelatedClass; -- a field, not an extension end record; anMIExample is a tagged record belonging to aClass, not to anUnrelatedClass. If you extend anMIExample, it will inhert F1 from its parent class. Since anUnrelatedClass UC is nested, you can still access it as a field using the prefix "UC.". [ BETTER EXAMPLE -- KB ]

11.6 Private Objects


Unless a tagged record class is very small, it's kept in it's own package. When you put a class in a package, you can use the package to hide the details of the class and to make parts of the class inaccessible to the outside world. package customers is type AbstractCustomer is abstract tagged private; type BasicCustomer is new AbstractCustomer with private; private type AbstractCustomer is new abstract tagged record name : string( 1..80 ); end record; type BasicCustomer is new AbstractCustomer with SalesCategory : integer; end record; end customers; By declaring a tagged record as private, we eliminate all access to the fields in the record. Anybody who wants to change the value of the fields must do it through any subprograms we provide. In object oriented programming, it's a good idea to make as many tagged records private as possible, the same as other private types. That way, if you want to change the contents of the tagged record, programs that use your class will not have to be changed. C: Ada does not have protected objects, but protected objects can be simulated using Ada packages.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (11 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

11.7 Generics
Ada allows you to create source code templates, called generics. With generics, you can specify a routine with only general information about the kinds of types the routine can work on. Later a programmer instantiates the generic by giving a type. Generics are useful for things like sort routines, which work basically the same way on different data types. C: Generics are similar to C++ templates. Ada contains several standard generic procedures. The most important one is unchecked_deallocation. This long winded procedure deallocates memory allocated with new. In order to free up memory, you must instantiate an unchecked_deallocation for each access type you are going to use new on. You have to specify both the access type and type of data that is being pointed to. with unchecked_deallocation; type booleanPtr is access all boolean; procedure Free is new unchecked_deallocation( boolean, booleanPtr ); Free is a new version of unchecked_deallocation compiled for booleanPtr's to a boolean type. Ada was designed for the possibility automatic storage recovery, that everything that was allocated in a subprogram would be deallocated automatically when the subprogram is left. Unfortunately, gnat was implemented without this feature and all memory has to be explicitly deallocated. Another standard generic you'll run into is unchecked_conversion. This converts a variable of one type to another by physically copying to data from one to the other, such as an array of 8 bits to a short_short_integer. Although you can write generic subprograms, most of the time you use generics will be for creating generic packages. Generic packages have a spec and body like normal Ada packages, but they begin with a list of parameters to the package that must be filled in when the generic is instantiated. generic -- these are the parameters for the generic type ListElement is <>; -- unspecified list element procedure ">="( left, right : ListElement); -- a procedure to sort by package SimpleList is type List procedure procedure procedure is array( 1..100) of ListElement; Add( l : list; e : ListElement); Sort( l : list ); Display( l : list );

end SimpleList; (check--KB) In this example, SimpleList takes some kind of data type called a ListElement, the items that compose the lists. Besides <>, Ada offers a number of other non-specific type descriptors to give the compiler an idea of what kind of types are acceptable.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (12 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Since the ListElement could be an aggregate and we can't assume we can do simple comparisons, the programmer must also specify a procedure to sort the elements by. Once you write the package body (no generic section in the package body, just a regular package body), you can instantiate the generic package in a program. After instantiation, use the package like any other package. with SimpleList; procedure ListTest is package BooleanList is new SimpleList( boolean, ">=" ) -- in this case, the normal ">=" will sort booleans begin BooleanList.Add( mylist, true ); BooleanList.Add( mylist. False ); end ListTest; Now you'll notice that generics and tagged records share a lot of capabilities. You can use both to write subprograms that work on a variety of types. Tagged records are referred to as dynamic polymorphism, because which subprogram to call gets determined while the program is running. Generics are referred to as static polymorphism, because the subprograms are generated when the generic is instantiated by the compiler and which subprogram to call is known when the program is compiled. The better approach depends on what you are doing. In general, generics run faster but take up more space because the compiler generates separate subprograms for each type. Tagged records take up less space but tend to run slower. Variant records and tagged records, likewise, share much in common. Although variant records can be simulated with tagged records, you'll need to decide which is the best choice depending on what you are trying to accomplish. Variant records tend to be smaller and faster, but are harder to extend than tagged records. Since tagged records are naturally used to create variables that are similar to one another, you might wonder if you'd ever create a single variable of a tagged record type. These are called singletons, and are used in frequently in languages like C++. They are popular because they have a specific elaboration order and provide access to features only available in objects (such as private members). Programmers doing this have no need to create a class of several objects. However, Ada has an easily controlled elaboration process and features such as privacy are not specific to tagged records. As a result, there is rarely a need for singletons in Ada programs.

11.8 Exceptions
Ada e : exception raise e exception clause Description Declare an exception Raise/throw an exception Handle/catch an exception C Equivalent throw type try...catch

C:In C++, exceptions are performed by throwing types (typically objects). In Ada, an exception is a separate type. Only exceptions can be thrown--you can't throw types. Exceptions aren't related to objects in any way. When you throw in C++, you do so in a try block. In Ada, you can throw an exception in any block. The exception clause (equivalent to catch) at the end of the block is optional.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (13 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

What do you do when something unexpected error occurs? Unexpected errors are called exceptions in Ada. For example, running out of memory is an exception. Ada has a number of predefined exceptions, and examples of when they occur: q CONSTRAINT_ERROR - number out of range, like assigning -1 to a positive variable q NUMERIC_ERROR - dividing by zero q SELECT_ERROR - caused by task select statement with no else part q STORAGE_ERROR - running out of memory q TASKING_ERROR - failure of a task to handle an entry call q PROGRAM_ERROR - hitting the end of a function without returning anything q ASSERT_ERROR - a pragma assert failed You can turn off checking for most of these errors using pragmas, but they are usually a sign that something if fundamentally wrong with your program. Gnat provides a compiler option to turn these checks off for the release version of a program. The standard libraries have additional exceptions defined. To handle an exception, you need an exception part at the end of a subprogram. When the exception is raised (occurs), execution immediately jumps down to the exception part. The exception part contains a list of exceptions to check for, plus an others part, similar to a case statement. procedure exceptional( Total : out integer) is begin -- do some stuff exception when constraint_error => Total := 0; when storage_error => Total := -1; when others => raise; end exceptional; Raise causes the exception to be reraised to the calling subprogram. If one subprogram doesn't handle the exception, it's raised in the subprogram that called it. This continues until the exception is handled by an exception part, or the main program is it. In the worst case, if the main program has no exception part, the program terminates and the exception name is printed on the screen. One use for exception parts to deallocate access types so the memory isn't lost when unexpected errors occur. You can define and raise your own exceptions. procedure exceptional2 is Accounting_Error : exception; C: Ada exceptions do not carry any additional information when raised. You can simulate error messages and other information with global variables. Pragma Assert provides an exception for debugging programs. Assert is described in 8.2. For more advanced manipulation of exceptions, you'll need to use Ada.Exceptions and its related packages. These are described in 12.15.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (14 of 39) [7/20/2001 11:33:45 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

11.9 Dynamic Allocation


Ada new unchecked_deallocation Description Allocate new memory Deallocate memory C Equivalent malloc/mallopt free

Dynamic allocation is reserving memory for variables while the program is running. The memory is allocated from a region called the default storage pool. GNAT sometimes refers to this as the unbounded no reclaim pool because the only limit on the amount of memory you can allocate is the physical limit of the machine, and memory is not reclaimed through garbage collection. C: The default storage pool is effectively the "heap". Ada uses access types to create a handle to dynamically declared variables. type IntegerPtr is access all Integer; ip : integerPtr := new Integer; In this example, IP access a dynamically declared integer. IP is only large enough to hold the address of where the integer is located. To access the integer, we have to add the suffix .all to IP. This is called dereferencing. ip.all := 5; If you are dereferencing multiple pointers, the all is only required at the end to indicate that the final pointer is to be dereferenced ( for example,. ptr1.ptr2.ptr3.all). The word all in access all is not strictly required. If all is included, the IntegerPtr type will be compatible on any other integer pointer. Without all, Ada imposes certain restrictions on what the access type can point to, but in general always use access all. Memory allocated with new is freed with unchecked_allocation (see the section on generics). You can assign initial values when you create a new dynamic variable. In the following example, we declare, allocate memory and assign an initial value all at once. ip : integerPtr := new Integer( 5 ); To create a record with a pointer to itself, have an empty type statement with the record first: type LinkedListRecord; type LinkedListPtr is access LinkedListRecord; type LinkedListRecord is record info : string(1..80); next : LinkedListPtr; end record; To point to variables you've declared, you must declare those variables as aliased to indicate they can be pointed to. To get the address of something, use the 'access attribute. type CustomerArray is array(1..100) of CustomerRecord; type CustomerArrayPtr is access all CustomerArray; ca : aliased CustomerArray; cp : CustomerArrayPtr := ca'access; cp now points to ca. Individual array elements can also be aliased.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (15 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

type CustomerArray is array(1..100) of aliased CustomerRecord; type CustomerArrayPtr is access all CustomerArray; ca : CustomerArray; c15p : CustomerArrayPtr := ca(15)'access; Ada will give you an error when you try to use 'access when the object pointing to may disappear after the pointer does. If you're absolutely certain that this won't happen, you can circumvent the error by using 'unchecked_access. An access type is necessarily just the address of a dynamic object. To get the address of an access type, it's best to use gnat's generic package System.Address_To_Access_Conversions. type intacc is access all integer; package strConvert is new System.Address_To_Access_Conversions(intacc); ... string_address := strConvert.To_Address( SomeIntAccVar ); Ada 83: The original use of .all created too many ambiguities. Ada 95 requires greater use of .all.

11.10 Callbacks
A callback is a pointer to a subprogram. They are called callbacks because you usually give the pointer to another subprogram that calls the procedure pointed to whenever it needs to. You can declare callbacks using type. type UpdateWindow is access procedure; type DisplayNewValue is access procedure( newval : integer ); One important restriction is that Ada requires that callbacks to refer to global subprograms. This is done to ensure that the access variable always points to an existing subprogram. You cannot create a callback to a local procedure or function, even if it's perfectly safe to do so. If you try, you'll get an obscure error message about one level being deeper than another. The gnat equivalent for 'unchecked_access for callbacks is 'unrestricted_access, which you can use if you're absolutely sure the subprogram you're using will not save the access when it's finished running. You can get the address of a procedure using 'access. Suppose MyUpdateProcedure is a procedure fitting the description of UpdateWindow, a procedure with no parameters. updatePtr : UpdateWindow := MyUpdateProcedure'access; procedure DoComplexSlowComputation( updatePtr); To call a callback, use the dereference operator .all. UpdatePtr.all;

11.10.1 Storage Pools


Unlike languages like C that have only one storage pool, Ada allows you to define your own storage pools. Authors of real-time applications, for example, can create a pool with a maximum size limit or a fixed access time. Use a for clause to make an access type use a pool other than the default storage pool. type AccountingRecPtr is access all AccountingRec;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (16 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

for AccountingRecPtr'storage_pool use my_pool; Gnat defines several storage pools besides the default storage pool. Perhaps the most useful is the debug pool. This storage pool, available in version of Gnat before 3.12, works the same as the default storage pool except that it performs run-time checks for several different pointer related problems. If a check fails, an exception is raised. The following program illustrates the errors caught by debug pool access types. with Ada.Text_IO, System.Pool_Local, System.Debug_Pools; use Ada.Text_IO; with unchecked_deallocation; -- This is an example of using the GNAT-specific debug_pool -- storage pool. procedure debpools is type sales_record is record salesman_code : integer; sales_amount : float; end record; -- just a typical record type salesptr_normal is access all sales_record; --- This is a normal access type. It is allocated -- in the default storage pool (aka "the heap"). -- The default storage pool is called -- Unbounded_No_Reclaimed_Pool. That is, there's -- no size limit, and memory is not reclaimed by -- garbage collection. -- A debug pool ----------------------------------------sales_debug_pool : System.Debug_Pools.Debug_Pool; -- declare a new debug pool --- Debug_Pool is a GNAT-specific pool. type salesptr_debug is access all Sales_Record; for salesptr_debug'storage_pool use Sales_Debug_Pool; ----This access type has no garbage collection but raises exceptions on allocation or deallocation errors, useful for tracking down storage leaks. All 4 possible exceptions are

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (17 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

-- shown in this program. procedure Free is new Unchecked_Deallocation( sales_record, salesptr_debug ); -- procedure to deallocate salesptr_debug access types sr : aliased Sales_Record; spd, spd2, spd3 : salesptr_debug; begin Put_Line( "Fun with debug storage pools!"); New_Line; -- Debug Pool Exception #1 begin Put_Line( "Accessing a non-allocated access type is an exception:" ); Put_Line( "spd.salesman_code := 1"); spd.salesman_code := 1; -- error: not allocated exception when System.Debug_Pools.Accessing_Not_Allocated_Storage => Put_Line( "***Accessing_Not_Allocated_Storage raised" ); when others => Put_Line( "***Unexpected exception" ); raise; end; New_Line; -- Debug Pool Exception #2 begin Put_Line( "Freeing a non-allocated access type is an exception:" ); Put_Line( "spd2 := sr'access --not allocated in pool" ); Put_Line( "Free( spd2 )" ); spd2 := sr'access; Free( spd2 ); exception when System.Debug_Pools.Freeing_Not_Allocated_Storage => Put_Line( "***Freeing_Not_Allocated_Storage raised" ); when others => Put_Line( "***Unexpected exception" ); raise; end; New_Line; spd := new Sales_Record'( salesman_code => 1, sales_amount => 55.50 ); -- Debug Pool Exception #3 begin Put_Line( "Accessing deallocated access type is an exception:" ); Put_Line( "spd := new Sales_Record..."); Put_Line( "Free( spd )" ); Put_Line( "spd.salesman_code := 1"); Free( spd ); spd.salesman_code := 1; -- error: not allocated
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (18 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

exception when System.Debug_Pools.Accessing_Not_Allocated_Storage => Put_Line( "***Accessing_Deallocated_Storage raised" ); when others => Put_Line( "***Unexpected exception" ); raise; end; New_Line; spd := new Sales_Record'( salesman_code => 1, sales_amount => 55.50 ); -- Debug Pool Exception #4 begin Put_Line( "Freeing deallocated access type is an exception:" ); Put_Line( "spd := new Sales_Record..."); Put_Line( "spd2 := spd" ); Put_Line( "Free( spd )" ); Put_Line( "Free( spd2 )" ); spd2 := spd; Free( spd ); Free( spd2 ); exception when System.Debug_Pools.Freeing_Deallocated_Storage => Put_Line( "***Freeing_Deallocated_Storage raised" ); when others => Put_Line( "***Unexpected exception" ); raise; end; New_Line; end debpools; Program Result: Fun with debug storage pools! Accessing a non-allocated access type is an exception: spd.salesman_code := 1 ***Accessing_Not_Allocated_Storage raised Freeing a non-allocated access type is an exception: spd2 := sr'access --not allocated in pool Free( spd2 ) ***Freeing_Not_Allocated_Storage raised Accessing deallocated access type is an exception: spd := new Sales_Record... Free( spd ) spd.salesman_code := 1 ***Accessing_Deallocated_Storage raised Freeing deallocated access type is an exception: spd := new Sales_Record... spd2 := spd Free( spd ) Free( spd2 ) ***Freeing_Deallocated_Storage raised

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (19 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

To create your own storage pools, you need to extend the Root_Storage_Pool tagged record found in the System.Storage_Pools package. [give example--KB]

11.10.2 Access Parameters


Because pointers are offen passed as parameters, Ada provides a special parameter type just for access types. access parameters are access types behave the same as an in parameter: you cannot assign a new value to the parameter. However, because it is an access type, you can change what the access parameter points to. Access parameters offer some advantages over in parameters with an access type: q Ada will verify that the parameter isn't null q Access parameters can be used in functions where in out parameters are not allowed q They avoid access type accessibility errors (without resorting to 'unchecked_access) Access parameters can't be compared or assigned, but you can typecast an access parameter into a normal access type and then compare values or assign it. with Ada.Text_IO; use Ada.Text_IO; procedure accparm is -- An example of access parameters -- Create a customer account record type money is new float; type aPercent is new float; type aCustomerAccount is record moneyOwing : money := 0.0; -- money on the account interest : aPercent := 0.15; -- 15% interest end record; type aCustomerPtr is access all aCustomerAccount;

procedure chargeInterest( cp : access aCustomerAccount ) is -- update the customer record by charging the interest begin cp.moneyOwing := cp.moneyOwing * money(1.0 + cp.interest ); end chargeInterest; procedure chargeInterest2( c : in out aCustomerAccount ) is -- update the customer record by charging the interest begin c.moneyOwing := c.moneyOwing * money(1.0 + c.interest ); end chargeInterest2; function chargeInterest3( cp : access aCustomerAccount ) return boolean is -- update the customer record by charging the interest -- if under 1000, don't charge interest and return false begin if cp.moneyOwing < 1000.0 then

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (20 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

return false; end if; cp.moneyOwing := cp.moneyOwing * money(1.0 + cp.interest ); return true; end chargeInterest3; cp : aCustomerPtr; begin Put_Line( "An Example of Access Parameters" ); New_Line; cp := new aCustomerAccount; Put_Line( "chargeInterest uses an access parameter" ); cp.moneyOwing := 1500.0; Put_Line( "Charging interest on" & cp.moneyOwing'img ); chargeInterest( cp ); Put_Line( "After interest, money owing is" & cp.moneyOwing'img ); New_Line; Put_Line( "chargeInterest2 uses an in out parameter" ); cp.moneyOwing := 1700.0; Put_Line( "Charging interest on" & cp.moneyOwing'img ); chargeInterest2( cp.all ); Put_Line( "After interest, money owing is" & cp.moneyOwing'img ); New_Line; Put_Line( "chargeInterest3 is a function with an access parameter" ); cp.moneyOwing := 1900.0; Put_Line( "Charging interest on" & cp.moneyOwing'img ); if chargeInterest3( cp ) then Put_Line( "After interest, money owing is" & cp.moneyOwing'img ); else Put_Line( "No interest was charged" ); end if; New_Line; Put_Line( "A null pointer for an access parameter causes an exception" ); cp := null; Put_Line( "Charging interest on a null pointer" ); if chargeInterest3( cp ) then Put_Line( "After interest, money owing is" & cp.moneyOwing'img ); else Put_Line( "No interest was charged" ); end if; New_Line; exception when constraint_error => Put_Line( Standard_Error, "Constraint error exception raised" ); when others => Put_Line( Standard_Error, "Unexpected exception raised" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (21 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

end accparm;

An Example of Access Parameters chargeInterest uses an access parameter Charging interest on 1.50000E+03 After interest, money owing is 1.72500E+03 chargeInterest2 uses an in out parameter Charging interest on 1.70000E+03 After interest, money owing is 1.95500E+03 chargeInterest3 is a function with an access parameter Charging interest on 1.90000E+03 After interest, money owing is 2.18500E+03 A null pointer for an access parameter causes an exception Charging interest on a null pointer Constraint error exception raised

11.11 Multithreading
Gnat comes with two alternative libraries for multithreading support. It can either use the native Linux pthreads (built into libc6), or it can use FSU (Florida State University) threads that are included with gnat. By default, the Linux version of gnat is compiled for Linux native threads.

11.11.1 FSU verses Native Threads


The FSU threads provide better concurrency at very small time slices, but are incompatible with Linux's pthreads library. This means you can't use the FSU version of gnat with the standard Linux libraries unless you recompile the libraries for FSU threads as well. FSU threads also force blocking on system calls and can cause blocking problems multiprocessors, and as a result most people don't use them. One exception is Florist, a POSIX (that is, Linux O/S calls) binding using FSU threads. The main benefit of FSU threads is that they are Ada Annex C & D compliant. To use FSU threads, you need to compile gnat from its sources.

11.11.2 Tasks
In Ada, a thread is referred to ask a task. It has nothing to do with multitasking, as its name might imply. A task runs independently of the main program, either by true parallelism on a multiprocessor computer, or as a separate job on a single processor computer. There is no way to specify which processor will receive a task: Linux takes care of this automatically.

Multithreaded programs have limits on the stack size for each thread--this is true for all Linux computer languages. Gnat 3.13 has an 8 Meg stack size limit per thread. Older versions had limits as low as 1 Meg per thread because of limits imposed by the Linuxthreads library. A task can take on several forms. In its simplest form, a task is structured like a package, with a specification and a body. The following is an example of a simple thread that waits 5 seconds after a program is started and displays a message.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (22 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

task SimpleTask; task body SimpleTask is begin delay 5.0; Put_Line( "The simple task is finished"); end SimpleTask; The specification, like a package, indicates what identifiers are available to the outside world. The SimpleTask thread doesn't communicate with the main program: it's specification is only one line long. Communicating with the rest of the program can be difficult. For example, with the tasks and main program running in parallel, sharing variables can be difficult. How does one task know when another task or the main program is finished changing the value of a variable? If a task works with a variable that's only partially been udpated, the data will be corrupt. Ada provides two ways for a thread to communicate with the rest of the program. The first communication method is called a rendezvous. One task communicates with another by sending a request. A task may send a request to another task to update a certain variable, or to perform a certain action, that would otherwise risk data corruption. Because this communication happens "on the fly", it's declared in two parts. First, in the task specification, a list of all requests the task is prepared to accept. These are called entry statements and look much like procedure declarations. Suppose we write a task to keep a running total, to be shared between several other tasks. We use a separate task to keep the total from being corrupted. task CountingTask is entry add( amount : integer ); end CountingTask; In the task body, a task indicates when it's ready to accept messages using the accept statement. This statement checks for outstanding requests from the rest of the program. task body CountingTask is runningTotal : integer := 0; begin loop accept add( amount : integer ) do runningTotal := runningTotal + amount; end add; end loop; end CountingTask; When this thread runs, accept statement will check for an add request. If there are no outstanding add requests, the thread suspends itself until a request is sent, waiting indefinitely for a new request. Suspending for a request is known as blocking. An accept statement with do part will cause your task to wait for that request and then do nothing. You can do this to synchronize two tasks. accept WaitUntilITellYouToGo; Suppose we add another entry statement to read the current value of the running total. task CountingTask is entry add( amount : integer ); entry currentTotal( total : out integer);

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (23 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

end CountingTask; In this case, we want the task to check for two different requests. The Ada select statement keeps a task from blocking and instead checks for multiple messages. task body CountingTask is runningTotal : integer := 0; begin loop select accept add( amount : integer ) do runningTotal := runningTotal + amount; end add; or accept currentTotal( total : out integer ) do total := runningTotal; end currentTotal; end select; end loop; end CountingTask; In this example, the task will repeatedly check for an add request or a currentTotal request. To communicate with the task, we make calls to the task as if it were a package. For example, to send a message to add 5 to the running total, we'd use CountingTask.Add( 5); Because accept is a statement that executes at run-time, you can create any kind of message policy you want. Some messages can block. Some messages can be checked. You can force certain message to be handled before others. The final "or" part of a select can contain instructions to execute when none of the accepts statements are executed. For example, a task can end itself with the terminate command. If you want a task to terminate when there are no more requests, add a or terminate at the end of your select statement. If select statement doesn't give you enough control over blocking, select can include when clauses. The clauses work like an if statement, executing the accept statement only if a condition is true. If time2accept is a boolean variable, you could write select when time2accept => accept add( amount : integer ) do A when clause is referred to as a "guard" because, like a crossing guard, the accept will not execute unless the guard gives permission. Ada also has a delay statement. Delay forces a task (or a program) to suspend itself for a number of seconds. To wait for three-and-a-half seconds, use delay 3.5; You can place a delay statement in the last "or" part of a select statement to force the task to suspend itself for a few seconds if no requests were found.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (24 of 39) [7/20/2001 11:33:46 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Delay can also wait for a particular time. The time is expressed using the Ada.Calendar time format. If Tomorrow is a variable with the time of midnight tomorrow in the Ada.Calendar time format, you can delay the start of a task with delay until Tomorrow; In an emergency, one task can terminate another with the abort statement. abort CounterTask; Ada provides a variation of the select statement for tasks that timeout when they cannot complete their work in time. This version has two parts: the first part consists of what to do if the task isn't completed in time, and the second consists of the task to complete. For example, if BigCalculation is a slow process that we wish to timeout after 30 seconds, select delay 30.0; Put_Line( "Timeout!" ); then abort BigCalculation; end select; In this example, BigCalculation will continue for up to 30 seconds. If it doesn't finish, "Timeout!" is displayed and BigCalculation is aborted.

11.11.3 Task Types


Often multithreaded programs will need a set of identical tasks. For example, you many want to sort a customer's records for several different customers using different threads. You can't do this with the simple tasking examples shown so far. To create a set of identical tasks, you must create a template of the tasks to run. Ada calls these templates a task type: they look just like a regular task except the specification begins with "task type" instead of "task" by itself. The following is a task template using the CountingTask example. task type CountingTask is entry add( amount : integer ); entry currentTotal( total : out integer ); end CountingTask; This template will not run by itself. If we want to create a CountingTask task, we create one by declaring it. Task1, Task2 : CountingTask; Task1 and Task2 are two copies of CountingTask. This is equivalent to creating two separate tasks: task Task1 is entry add( amount : integer ); entry currentTotal( total : out integer); end Task2; task Task2 is entry add( amount : integer ); entry currentTotal( total : out integer); end Task2; Because task types can be declared, we can create 20 tasks at once by declaring an array of 20 CountingTask's. CountingTasks : array(1..20) of CountingTask;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (25 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Tasks can also be declared in records as well, or allocated dynamically using the new operator. type aTaskPtr is access CountingTask; tp : aTaskPtr; ... tp := new CountingTask; Using new, you can create as many copies of a particular task as you need.

11.11.4 Protected Items/Types


Ada tasks are useful for many kinds of multithreading. However, Ada provides a second method of multithreading called protected objects. These are similar to the "monitors" used by Java. In an Ada task, you specify when and how different tasks communicate. When items are declared protected, Ada controls the interaction for you. Protected objects are declared the same was as a package, using a specification and a body. They act like a package that allows only one task access to its contents at a time. While one task is using the contents, any other task wanting access is blocked until the first task is finished. Here is our CountingTask rewritten as a protected item. protected CountingType is procedure add( amount : integer); procedure currentTotal( total : out integer ); private runningTotal : integer := 0; end CountingType; protected body CountingType is procedure add( amount : integer ) is begin runningTotal := runningTotal + amount; end add; procedure currentTotal( total : out integer ) is begin total := runningTotal; end currentTotal; end CountingType; In this case, any task may execute the add or currentTotal procedures, but only one task may execute them at a time. This ensures that runningTotal will not be corrupted. Unlike a package, you can't declare variables in the spec or body unless you put them in a "private" part in the spec. Protected items can include entry declarations. Since there is no "main program" to the protected body, the protected body contains no accept statements. Instead, the entry declarations are filled in as if they were a subprogram. Any guarding conditions are attached to the end of the entry header. For example, to create an a version of our add procedure that blocks if the total is higher than 100, we could write protected CountingType is

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (26 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

entry add( amount : integer ); ... protected body CountingType is entry add( amount : integer ) when runningTotal<100 is begin runningTotal := runningTotal + amount; end add; ... Like tasks, you can create protected types by declaring the specification with "protected type" instead of "protected". You can then create arrays of protected items, or declare protected items dynamically. This covers the basics of Ada's multithreading capabilities. There's much more that Ada can do. If you are writing complicated multithreading programs, you're encouraged to investigate the Ada Reference Manual for more information.

11.12 Ada Text Streams


A stream is a sequential transmission of different types of data. When data is written to a stream, the stream converts the data to a form suitable for transmission. When the data is read, it's converted from the stream's format back to its original form. A practical example is saving tagged records belonging to the same class to a file. Ada's syntax for using streams is a bit cumbersome. Like tagged records, some of the features are implemented using attributes, and others are found in standard packages. The Ada.Streams.Stream_IO can write heterogeneous data to a text file, and then read it back again. This package contains a number of subprograms similar to Ada.Text_IO, including, Open, Close, Reset, Delete, Is_Open and End_Of_File. However, there are no Get or Put procedures. Instead, there are stream subprograms for working with the data in the file. q Stream - returns a stream to the file q Read - read data from the stream q Write - write data to the stream Read and Write are not used directly. Instead, the attributes 'read and 'write will read and write an item to the stream. That is, Gnat does the necessary conversion to stream data for you. For classes of tagged records, 'input and 'output read and write any child of the class. These attributes are implicitly defined for all class-wide types (that are not also limited). As a result, you usually combine 'class with the stream attributes for 'class'input and 'class'output. If you don't supply 'class, nothing will be written and no exception will be raised. with ada.text_io, ada.streams.stream_io; use ada.text_io, ada.streams.stream_io; with ada.unchecked_deallocation; procedure class_stream is -- Contact_Info: A simple class -- the base class must not be abstract when using 'input and 'output type contact_info is tagged null record; type contact_ptr is access all contact_info'class; type phone_number is new contact_info with record phone : string(1..14); end record;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (27 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

type office_number is new contact_info with record office : integer; end record; procedure free is new ada.unchecked_deallocation( contact_info'class, contact_ptr); -- A Stream File and Its Stream stream_file : Ada.Streams.Stream_IO.File_Type; the_stream : Ada.Streams.Stream_IO.Stream_Access; contact : contact_ptr; begin Put_Line( "An example of Ada.Streams.Stream_IO and a Class" ); Put_Line( "-----------------------------------------------" ); New_Line; Create( stream_file, out_file, "contact_list.stream" ); Put_Line( "Created a stream file" ); -- open the stream file the_stream := stream( stream_file ); -- get a stream representing the file's contents contact := new phone_number'( phone => "1-905-555-1023" ); contact_info'class'output( the_stream, contact.all ); free( contact ); Put_Line( "Wrote a phone number" ); -- write a record contact := new office_number'( office => 8023 ); contact_info'class'output( the_stream, contact.all ); free( contact ); Put_Line( "Wrote an office number" ); -- write a record Close( stream_file ); New_Line; -- close the stream file -- Read Them Open( stream_file, in_file, "contact_list.stream" ); Put_Line( "Opened a stream file" ); -- open the stream file the_stream := stream( stream_file ); -- get a stream representing the file's contents while not End_of_File( stream_file ) loop declare contact : contact_info'class := contact_info'class'input( the_stream );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (28 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

begin -- if this were more sophisticated, we could write a Put procedure -- for each tagged record and use dynamic dispatching if contact in phone_number then Put_Line( "read a phone number" ); elsif contact in office_number then Put_Line( "read an office number" ); else Put_Line( "read something else" ); end if; end; end loop; Close( stream_file ); -- close the stream file end class_stream;

An example of Ada.Streams.Stream_IO and a Class ----------------------------------------------Created a stream file Wrote a phone number Wrote an office number Opened a stream file read a phone number read an office number Files of items of the same time are more easily created with Ada.Sequential_IO or Ada.Direct_IO. Custom streams can be created to save or trasmit data in other ways such as in memory or through a network connection. Custom streams are created as tagged records extended from a root class, Ada.Streams.Root_Stream_Type'class. type My_Stream is new Root_Stream_Type with record ... Your stream type must override the abstract Red and Write subprograms to add and remove data from the stream. The following is an in-memory stream creating by Warren Gay. This stream can share data between programs, buffering the data as text in memory. If a buffer overflow occurs, an END_ERROR is raised. -- $Id: memory_stream.ads,v 1.1 2000/11/26 05:00:18 wwg Exp $ -- (c) Warren W. Gay VE3WWG [email protected], [email protected] --- Protected under the GNU GPL License with Ada.Finalization, Ada.Streams; use Ada.Finalization, Ada.Streams; package Memory_Stream is type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; type Memory_Buffer(Max_Elem: Stream_Element_Offset) is new Controlled with private;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (29 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

--------------------------------------------------- The new Stream Type, which must be derived from -- Root_Stream_Type. Note that Root_Stream_Type is -- NOT derived from Controlled, so if -- controlled attributes are necessary, they must -- be defined separately, and embedded into this -- object, as is done with Memory_Buffer here. -------------------------------------------------type Memory_Buffer_Stream(Max_Elem: Stream_Element_Offset) is new Root_Stream_Type with record Mem_Buf: Memory_Buffer(Max_Elem); -- Object with Finalization end record; type Memory_Buffer_Stream_Ptr is access all Memory_Buffer_Stream; -- The overloaded abstract for Read procedure Read(Stream: in out Memory_Buffer_Stream; Item: out Stream_Element_Array; Last: out Stream_Element_Offset); -- The overloaded abstract for Write procedure Write(Stream: in out Memory_Buffer_Stream; Item: in Stream_Element_Array); -- Rewind the Read Memory Buffer Index procedure Rewind_Read(Stream: Stream_Access); -- Rewind the Write Memory Buffer Index procedure Rewind_Write(Stream: Stream_Access); -- To permit easy destruction of this stream procedure Free(Stream: Stream_Access); private --------------------------------------------------- To create a Memory_Buffer stream with an -- Initialize procedure, it must be derived from -- a Controlled type. Unfortunately, the type -- Root_Stream_Type is not derived from the -- Controlled type, so it is done privately here. -------------------------------------------------type Memory_Buffer(Max_Elem: Stream_Element_Offset) is new Controlled with record Read_Offset: Stream_Element_Offset; Write_Offset: Stream_Element_Offset; Buffer: Stream_Element_Array(1..Max_Elem); end record; procedure procedure procedure Item: Last: procedure procedure Initialize(Buf: in out Memory_Buffer); Write(Buf: in out Memory_Buffer; Item: in Stream_Element_Array); Read(Buf: in out Memory_Buffer; out Stream_Element_Array; out Stream_Element_Offset); Rewind_Read(Buf: in out Memory_Buffer); Rewind_Write(Buf: in out Memory_Buffer);

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (30 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

end Memory_Stream;

-- $Id: memory_stream.adb,v 1.1 2000/11/26 05:00:18 wwg Exp $ -- (c) Warren W. Gay VE3WWG [email protected], [email protected] --- Protected under the GNU GPL License with Ada.Text_IO; use Ada.Text_IO; with Ada.Finalization; use Ada.Finalization; with Ada.IO_Exceptions; use Ada.IO_Exceptions; with Ada.Unchecked_Deallocation; package body Memory_Stream is --------------------------------------------------- Read from a Memory Buffer Stream : -------------------------------------------------procedure Read(Stream: in out Memory_Buffer_Stream; Item: out Stream_Element_Array; Last: out Stream_Element_Offset) is begin Read(Stream.Mem_Buf,Item,Last); end Read; --------------------------------------------------- Write to a Memory Buffer Stream : -------------------------------------------------procedure Write(Stream: in out Memory_Buffer_Stream; Item: in Stream_Element_Array) is begin Write(Stream.Mem_Buf,Item); end Write; --------------------------------------------------- Rewind the Read Memory Buffer Index -------------------------------------------------procedure Rewind_Read(Stream: Stream_Access) is Mem_Str: Memory_Buffer_Stream_Ptr := Memory_Buffer_Stream_Ptr(Stream); begin Rewind_Read(Mem_Str.Mem_Buf); end Rewind_Read; --------------------------------------------------- Rewind the Write Memory Buffer Index -------------------------------------------------procedure Rewind_Write(Stream: Stream_Access) is Mem_Str: Memory_Buffer_Stream_Ptr := Memory_Buffer_Stream_Ptr(Stream); begin Rewind_Write(Mem_Str.Mem_Buf); end Rewind_Write;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (31 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

--------------------------------------------------- Free a Memory Buffer Stream : -------------------------------------------------procedure Free(Stream: Stream_Access) is type Memory_Buffer_Stream_Ptr is access all Memory_Buffer_Stream; procedure Free_Stream is new Ada.Unchecked_Deallocation(Memory_Buffer_Stream,Memory_Buffer_Stream_Ptr); Str_Ptr: Memory_Buffer_Stream_Ptr := Memory_Buffer_Stream_Ptr(Stream); begin Free_Stream(Str_Ptr); end Free; --------------------------------------------------- Private Implementation : ---------------------------------------------------------------------------------------------------- Initialize a Memory_Buffer Object : -------------------------------------------------procedure Initialize(Buf: in out Memory_Buffer) is begin Buf.Read_Offset := Buf.Buffer'First; Buf.Write_Offset := Buf.Buffer'First; end Initialize; --------------------------------------------------- Write to a Memory Buffer Object : -------------------------------------------------procedure Write(Buf: in out Memory_Buffer; Item: Stream_Element_Array) is Count: Stream_Element_Offset := Item'Last + 1 - Item'First; Last: Stream_Element_Offset := Buf.Write_Offset + Count - 1; begin if Last > Buf.Buffer'Last then raise Ada.IO_Exceptions.End_Error; end if; Buf.Buffer(Buf.Write_Offset..Last) := Item; Buf.Write_Offset := Buf.Write_Offset + Count; end Write; --------------------------------------------------- Read from a Memory Buffer Object : -------------------------------------------------procedure Read(Buf: in out Memory_Buffer; Item: out Stream_Element_Array; Last: out Stream_Element_Offset) is Xfer_Count: Stream_Element_Offset := Item'Last + 1 - Item'First; Data_Count: Stream_Element_Offset := Buf.Write_Offset - Buf.Read_Offset; begin if Xfer_Count > Data_Count then Xfer_Count := Data_Count; end if; Item(1..Xfer_Count) :=
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (32 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Buf.Buffer(Buf.Read_Offset..Buf.Read_Offset+Xfer_Count-1); Buf.Read_Offset := Buf.Read_Offset + Xfer_Count; Last := Item'First + Xfer_Count - 1; end Read; --------------------------------------------------- Rewind the Read offset in the Memory Buffer -------------------------------------------------procedure Rewind_Read(Buf: in out Memory_Buffer) is begin Buf.Read_Offset := Buf.Buffer'First; end Rewind_Read; --------------------------------------------------- Rewind the Write offset in the Memory Buffer -------------------------------------------------procedure Rewind_Write(Buf: in out Memory_Buffer) is begin Buf.Read_Offset := Buf.Buffer'First; -- Implies a Read offset rewind Buf.Write_Offset := Buf.Buffer'First; -- Rewind the write offset end Rewind_Write; end Memory_Stream;

-- $Id: main.adb,v 1.1 2000/11/26 05:00:18 wwg Exp $ -- (c) Warren W. Gay VE3WWG [email protected], [email protected] --- Protected under the GNU GPL License with Ada.Text_IO; use Ada.Text_IO; with Memory_Stream; use Memory_Stream; --------------------------------------------------- This is a demo main program, that makes use of -- our home-brewed Memory_Buffer_Stream. --- To demonstrate, a record of type my_rec is -- written to the stream with known values, and -- then is read back twice, into records T and U. --- Then the write offset is rewound, and a new -- float variable F is written, and then read -- back into float variable G. -------------------------------------------------procedure Main is type my_rec is record -- A demonstration record A: natural; B: integer; S: string(1..8); Z: float;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (33 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

end record; Str: R: T: U: F: G: begin put_line("Demonstration has begun:"); Str := new Memory_Buffer_Stream(4096); -- Create in-memory buffer stream (4096 bytes) my_rec'write(Str,R); my_rec'read(Str,T); put_line("T.A put_line("T.B put_line("T.S put_line("T.Z :=" & natural'image(T.A)); :=" & integer'image(T.B)); := '" & T.S & "'"); := " & float'image(T.Z)); -- Write record R to stream -- Read stream back to record T -- Dump out T Stream_Access := null; my_rec := ( 23, -95, "oink my_rec := ( 0, 0, " my_rec := T; float := 29.99; float := 0.0; -- A Stream ", 1.414 ); -- An initialized record ", 0.0 ); -- For 1st read -- For 2nd read -- An initialized float -- For 3rd read

Rewind_Read(Str); my_rec'read(Str,U); put_line("U.A put_line("U.B put_line("U.S put_line("U.Z :=" & natural'image(U.A)); :=" & integer'image(U.B)); := '" & U.S & "'"); := " & float'image(U.Z));

-- Rewind the read pointer -- Now read into record U -- Dump out U

Rewind_Write(Str); float'write(Str,F); float'read(Str,G); put_line("G :=" & float'image(G)); Free(Str); put_line("Demonstration complete."); end Main;

-- Implies a read rewind also -- Write F to stream -- Read stream into G -- Report G for verification -- Delete stream

Demonstration has begun: T.A := 23 T.B :=-95 T.S := 'oink '


file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (34 of 39) [7/20/2001 11:33:47 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

T.Z := 1.41400E+00 U.A := 23 U.B :=-95 U.S := 'oink ' U.Z := 1.41400E+00 G := 2.99900E+01 Demonstration complete.

11.13 Pragmas
Pragmas, sometimes called compiler directives, are statements that provide additional information to the compiler build a better executable. Pragmas never change the meaning of a program. The following are the predefined Ada 95 pragmas: Abort_Defer Ada_83 Ada_95 All_Calls_Remote Annotate Assert Asynchronous Atomic Attach_Handler C_Pass_By_Copy Comment Common_Object Complex_Representation Component_Alignment Controlled Convention CPP_Class CPP_Constructor CPP_Destructor CPP_Virtual CPP_Vtable Debug Discard_Names Elaborate Elaborate_All Elaborate_Body Eliminate Error_Monitoring Export Export_Function defer abouts over a block of statements* enforce Ada 83 conventions, even if compiler switches say otherwise* enforce Ada 95 conventions, even if compiler switches say otherwise* All subprograms in a RPC package spec are RPC callable add information for external tools* create an assertion* call to remote subprogram can complete before subprogram is done identifier must be read/written without interruption install a signal handler procedure when calling C functions, use pass by copy (not by reference) when able* same as Ident * for Fortran, create variables that share storage space* use gcc's complex number format (for speed)* indicate how record components should be stored* turn off garbage collection for a type (no effect in gnat) apply a convention to an identifier treat a record or tagged record as a C++ class* treat imported function as a C++ class constructor* treat imported function as a C++ class destructor* import a C++ virtual function* specify a virtual function table* specify a debugging procedure call* discard ASCII representation of identifiers, as used by 'img elaborate a certain package before this one elaborate all with'ed packages before this one elaborate a package's body immediate after it's spec indicate an identifier that is not used in a program, created by gnatelim * treat errors as warnings during a compile* export an identifier from your program so it can be used by other languages export an Ada function with additional information over pragma Export*

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (35 of 39) [7/20/2001 11:33:48 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

export an Ada tagged record with additional information over pragma Export* Export_Procedure export an Ada procedure with additional information over pragma Export* export an Ada side effect function with additional information over pragma Export_Valued_Procedure Export* Extend_System obsolete* Finalize_Storage_Only no finalize on library-level objects, primarily for gnat's internal use * Ident object file identification string (no effect with Linux) * Export_Object Import Import_Function Import_Object import an identifer from another language so it can be used in your program import a non-Ada function with additional information over pragma Import* import a non-Ada object with additional information over pragma Import* import a non-Ada procedure with additional information over pragma Import_Procedure Import* import a non-Ada side effect function with additional information over Import_Valued_Procedure pragma Import* Inline the indicated subprogram may be inlined. Inline_Always forces inter-unit inlining, regardless of compiler switches* Inline_Generic for compatibility with other Ada compilers* specify that an identifier's value must readable at the given point in the Inspection_Point program (for code validation) Interface_Name for compatibility with other Ada compilers* Interrupt_Handler declare a signal handler procedure Interrupt_Priority Linker_Alias Linker_Options Linker_Section List Locking_Policy Machine_Attribute No_Return No_Runtime Normalize_Scalars Optimize Pack Page Passive Polling Priority Preelaborate Propagate_Exceptions Psect_Object Specify the task/protected object's priority where blocking occurs select an alternative linker[?] for a package (or other llinkable unit)* pass a string of options to the linker the gcc linker section to use * list source code while being compiled Spcify how protected objects are locked and when blocking occurs specify GCC machine attributes* specify a procedure that is deliberately never returned from, to avoid compiler warnings* ensures no gnat run-time routines are use (e.g. for creating device drivers)* set scalars variables to illegal values whenever possible indicates how statements should be optimzed indicates that the type should be compressed as much as possible start a new page in a program listing for compatibility with other Ada compilers* if on, enables exception polling* Specify the priority of a task preelaborate the specified package specify imported subprogram that can handle Ada exceptions; used with zero cost handling * Same as common_object*

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (36 of 39) [7/20/2001 11:33:48 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Pure Pure_Function Queuing_Policy Ravenscar Remote_Call_Interface Remote_Types Restricted_Run_Time Restrictions Reviewable Share_Generic Shared_Passive Source_File_Name Source_Reference Storage_Size Stream_Convert Subtitle Suppress Suppress_All Suppress_Initialization Task_Dispatching Task_Info Task_Storage Time_Slice Title Unchecked_Union Unimplemented_Unit Unsuppress Use_VADS_Size Volatile Volatile_Components Warnings Weak_External * - GNAT specific

specifies the package is pure specify a function without side-effects* How task/protected objects are sorted when queued enforce the Ravenscar real-time policies* Ensure a package can be callable by remote procedure calls used for communication between RPC partitions like Ravenscar, turns on a number of restrictions for real-time programming * Disable certain language features Provide a run-time profiling (like gprof) for compatibility with other Ada compilers* used for sharing global data with separate RPC partitions overrides normal Gnat file naming conventions* for use with gnatchop* amount of storage space for a task simplified way of creating streams I/O subprograms for a given type* for compatibility with other Ada compilers* turn off specific checks for common exceptions for compatibility with other Ada compilers* disable initialization of variables of a given type* specify how tasks sort dispatches (e.g. FIFO_Within_Priorities) specify information about a task* specify the guard area for a task* specify tasking time slice for main program [in Linux?]* for compatibility with other Ada compilers* treat a record as a C union type* for unfinished units, produces a compiler error if they are compiled* opposite of suppress* for older Ada code, 'size is equivalent to 'vads_size * value of variable may change unexpectedly array components may change unexpectedly turn compiler warnings on or off* specify an identifier that doesn't have to be resolved by the linker *

Unreserve_All_Interrupts allow reassigning of signals normally handled by gnat, eg. SIGINT*

The use of these pragmas are covered in detail in the GNAT and Ada 95 reference manuals.

11.14 Low-Level Ada


Ada Description C Equivalent

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (37 of 39) [7/20/2001 11:33:48 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Variable is influnced outside of program Specify an absolute address for a for x'address use a pointer Position the identifier x on b byte for x'alignment use b boundaries for x'bit_order use o; Store record using bit order o Specify a octal numeric literal 8#value# Specify a hexadecimal numeric 16#value# literal Assemble an instruction asm( inst, in, out) pragma volatile

volatile declaration p = (typecast) integer; ? ? 0Value 0xValue asm( inst : in : out )

Ada contains a number of low-level features and libraries, such as the ability to add machine code to a program or to access a hardware register in memory. I'll mention a few of these features here. If you need to specify a specific number of bits, say to access a hardware register, use the for statement. type Reg is new integer; for Reg'size use 4; -- register is 4 bits type RegPtr is access all Reg; You can refer an access type to a particular address using for var'address clause. Together with 'size , you can theoretically refer to an bit in the computer's memory. However, on Linux the address refers to a location in your address space and doesn't refer to a real physical location. var'alignment will align storage to a particular byte boundary. var'bit_order can specify a different bit order for a record than the default for your machine. The bit orders are defined in the System package. (Gnat 3.12 doesn't fully support bit orders.) for Reg'address use 16#2EF#; -- hex address 2EF in your memory space for Reg'alignment use 2; -- align to 16-bit boundaries for myRecord'bit_order use system.low_order_first; -- low bits to high machine If the register value can change independently of the Ada program (usually true), we need to mark the pointer with pragma volatile to make sure the compiler will make no assumptions while optimizing. pragma volatile( RegPtr); Ada will do bit-wise logic operations, but it will only do them on packed arrays of booleans or modular types. You can't do bit-wise operations on integers, for example. The bit-wise operators are and, or, xor and not. type byte is array(1..8) of boolean; pragma pack( byte ); b1, b2, b3 : byte; ... b3 := b1 and b2; If you need octal or hexadecimal numbers, Ada denotes these by using a leading base designation between 2 and 16, with the value delimited by number signs. Hex := 16#0FE9#; Bin := 2#01101010#; The System.Machine_Code package can embed assembly language instructions in an Ada program. Since Gnat is based on

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (38 of 39) [7/20/2001 11:33:48 AM]

Big Online Book of Linux Ada Programming - 11 Advanced Ada Programming

Gcc, it uses Gcc's inlining features. If you've inlined assembly code in a C program, you'll find Gnat's capabilities virtually identical. Assembly code is embedded using the Asm. Asm( "nop" ); -- do nothing A tutorial by Jerry van Dijk is available from AdaPower.com. Large sections of assembly code should be linked in separately.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/11.html (39 of 39) [7/20/2001 11:33:48 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

12 Standard Gnat Packages


<--Last Chapter Table of Contents Next Chapter-->

This section summarizes some of the more than 100 packages that come with the Gnat compiler. These include string handling, operating system binding, and sorts.

12.1 Standard String and Character Packages

Ada Package Ada.Character.Handling Ada.Strings.Fixed Ada.Strings.Bounded Ada.Strings.Unbounded Gnat.Case_Util Ada.Strings.Unbounded.Text_IO

Description Character operations Ada string operations Bounded strings and operations Unbounded strings and operations Just case conversions Text_IO for Unbounded Strings

C Equivalent Strings.h? Strings.h -

Ada's built-in strings, or "fixed" strings, are made of array of characters. The length of the array determines the bounds of the string. A string that's too short for an array is padded with blanks. Although these strings are fast, they are cumbersome to use and not practical for string-intensive applications. One problems is, although the string type is an array with an undefined upper bound, sooner or later you have to specify an upper bound and run the risk of constraint errors working with arrays of different sizes. Ada operator "&" concatenates fixed strings: this is the only built-in operator for fixed strings. There are two alternative strings in Ada. Bounded strings are arrays of strings with a definite maximum size, separate from the length, which eliminates to constraint errors. These strings are still relatively fast, but waste a lot of storage on small strings and you run the risk of overflowing the string. I use 255 character bounded strings as general purpose strings in my programs. The standard Ada library Ada.Strings.Bounded contains the definition of bounded strings and similar operations to Ada.Strings.Fixed. Because bounded strings have a definite upper bound, the package is generic and has to be instantiated for the maximum length. The library also includes a function to convert a bounded string to a fixed string. Unbounded strings are strings that can be of any size. They are typically implemented by dynamic allocation, which makes them slow, but they don't waste memory the way bounded strings do and there's no risk over a string overflow. The standard Ada library Ada.Strings.Unbounded contains the definition of unbounded strings and operations on them, including a function to convert an unbounded string to a fixed string.

C: Unbounded strings are not exactly the same as C strings. For one thing, unbounded strings don't end in null characters. C String support is in the packages Interfaces.C. with Ada.Text_IO, Ada.Strings.Unbounded.Text_IO; use Ada.Text_IO, Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO; procedure unbio is
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (1 of 35) [7/20/2001 11:34:25 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

-- this program demonstrates basic input/output with -- unbounded strings. These routines are more efficient -- because they avoid conversion into standard Ada -- strings us : Unbounded_String; begin Put_Line( "This program displays information on the screen" ); Put_Line( "and reads information from the keyboard" ); New_Line; Put_Line( "Type in a string" ); us := Get_Line; New_Line; Put_Line( "Put_Line displays a line of text and advances to" ); Put_Line( "the next line." ); Put( "The string you typed was " ); Put_Line( us ); New_Line; end unbio;

This program displays information on the screen and reads information from the keyboard Type in a string Uptown Girl, she been looking for a downtown man... Put_Line displays a line of text and advances to the next line. The string you typed was Uptown Girl, she been looking for a downtown man... For characters, the standard Ada library Ada.Character.Handling provides basic operations such as conversions between case, tests for types of characters, and conversions two and from 16-bit wide characters. Text_IO.Put_Line( Ada.Character.Handling.To_Upper( 'r' ) ); This example prints 'R' on the screen. For string handling capabilities, you need to use a package. The standard Ada library Ada.Strings.Fixed contains operations for fixed strings, including extracting substrings, mapping characters from one set to another (for example, upper to lower case), and string searching. There is also an Ada.Strings.Unbounded package containing the same subprograms for unbounded strings, and likewise an Ada.Strings.Bounded for bounded strings. Figure: Standard String Subprograms Append / & concatenate one string to another Element return the character at a particular index Replace_Element replace a character at a particular index Slice return a substring Replace_Slice / Overwrite replace a substring Insert add a string in the midst of the original string Delete remove a string in the midst of the original string

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (2 of 35) [7/20/2001 11:34:25 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

Count return the number of occurrences of a substring Index locate a string in the original string Index_Non_Blank locate the first non-blank character Head return the first character(s) of a string Tail return the last character(s) of a string Trim remove leading or trailing spaces * - duplicate the string a specific number of times Tokenize Translate convert a string to a new set of characters using a mapping function The following program demonstrates many of the standard Ada string subprograms using unbounded strings. with Ada.Text_IO, Ada.Strings.Unbounded.Text_IO; use Ada.Text_IO, Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO; procedure strdemo is -- demonstrate some of the Ada strings subprograms teststr : string := "The rich get richer"; us : Unbounded_String; begin Put_Line( "This program shows some Ada string capabilities" ); New_Line; Put( "Our test string is " ); Put_Line( teststr ); New_Line; Put_Line( "To_Unbounded_String converts a string to an unbounded string" ); us := To_Unbounded_String( teststr ); Put_Line( us ); New_Line; Put_Line( "The length of the string is " & length( us )'img ); Put_Line( "If we append, ' but not happier', the string is" ); Append( us, " but not happier" ); Put_Line( us ); New_Line; Put_Line( "The ampersand will work as well: " & us ); New_Line; Put_Line( "The fifth character is " & Element( us, 5 ) ); New_Line; Put_Line( "Replacing the 20th character, we get" ); Replace_Element( us, 20, ',' ); Put_Line( us ); New_Line; Put_Line( "The 5th to 8th charcaters is " & Slice( us, 5, 8 ) ); New_Line; Put_Line( "The first occurence of 'ch' is at " & Index( us, "ch" )'img );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (3 of 35) [7/20/2001 11:34:25 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

New_Line; Put_Line( "The first non-blank character is at " & Index_Non_Blank( us )'img ); New_Line; Put_Line( "Replacing the first 'rich' with 'RICH' we get" ); Replace_Slice( us, 5, 8, "RICH" ); Put_Line( us ); New_Line; Put_Line( "Inserting 'really ' at the 5th character, we get" ); Insert( us, 5, "really " ); Put_Line( us ); New_Line; Put_Line( "Overwriting characters 5 to 8, we get" ); Overwrite( us, 5, "most" ); Put_Line( us ); New_Line; Put_Line( "Deleting characters 5 through 11, we get" ); Delete( us, 5, 11 ); Put_Line( us ); New_Line; Put_Line( "The first 8 characters at the head of the string are" ); Put_Line( Head( us, 8 ) ); New_Line; Put_Line( "The last 8 characters at the tail of the string are" ); Put_Line( Tail( us, 8 ) ); New_Line; -- Count is ambiguous because of the use clauses Put_Line( "The count of 'er' is " & Ada.Strings.Unbounded.Count( us, "er" )'img ); New_Line;

end strdemo; This program shows some Ada string capabilities Our test string is The rich get richer To_Unbounded_String converts a string to an unbounded string The rich get richer The length of the string is 19 If we append, ' but not happier', the string is The rich get richer but not happier The ampersand will work as well: The rich get richer but not happier

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (4 of 35) [7/20/2001 11:34:25 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

The fifth character is r Replacing the 20th character, we get The rich get richer,but not happier The 5th to 8th charcaters is rich The first occurence of 'ch' is at 7 The first non-blank character is at 1 Replacing the first 'rich' with 'RICH' we get The RICH get richer,but not happier Inserting 'really ' at the 5th character, we get The really RICH get richer,but not happier Overwriting characters 5 to 8, we get The mostly RICH get richer,but not happier Deleting characters 5 through 11, we get The RICH get richer,but not happier The first 8 characters at the head of the string are The RICH The last 8 characters at the tail of the string are happier The count of 'er' is 2 There are also a number of libraries dealing with wide strings, strings with 16-bit characters. If you are only interested in doing case conversions, gnat provides a small package called case_util that does case conversions (and only case conversions) on characters and strings. Use case_util to avoid loading the entire Ada.Character.Handling library. The following sample program demonstrates the uses of case_util: with text_io, gnat.case_util; use text_io; procedure casetest is teststr : constant string := "This is a TEST_string"; tempstr : string := "....................."; begin Put_Line( "This is an example of the Gnat string case conversion tools:" ); New_Line; Put_Line( "The original string is '" & teststr & "'" ); New_Line; TempStr := TestStr; Gnat.Case_Util.To_Upper( TempStr ); Put_Line( "Upper case is '" & TempStr & "'" ); tempstr := teststr; Gnat.Case_Util.To_Lower( TempStr ); Put_Line( "Lower case is '" & TempStr & "'" ); tempstr := teststr; Gnat.Case_Util.To_Mixed( TempStr ); Put_Line( "Mixed case is '" & TempStr & "'" );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (5 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

end casetest; This is an example of the Gnat string case conversion tools: The original string is 'This is a TEST_string' Upper case is 'THIS IS A TEST_STRING' Lower case is 'this is a test_string' Mixed case is 'This is a test_String' Ada defines a number of character sets. ASCII is the standard ASCII character set. To put an "" character on displays that support the Latin character set, use Put( Ada.Characters.Latin_1.LC_AE_Dipthong );

12.2 Advanced Input/Output 12.2.1 GNAT.IO


For small programs that don't need the full capabilities of Text_IO, GNAT provides a package called GNAT.IO. This package can get and put integers, characters and strings. Unlike Text_IO, it's also preelaborated. with GNAT.IO; use GNAT.IO; procedure giodemo is -- this program demonstrates basic input/output using the -- GNAT.IO package, a stripped down version of Text_IO c : character; -- this is a letter begin Put_Line( "This program displays information on the screen" ); Put_Line( "and reads information from the keyboard" ); New_Line; Put_Line( "Put_Line displays a line of text and advances to" ); Put_Line( "the next line." ); Put( "Put " ); Put_Line( "displays text, but it doesn't start a new line" ); Put_Line( "New_Line displays a blank line" ); New_Line; Put_Line( "Get waits for a character to be typed." ); Put_Line( "Type a key and the Enter key to continue." ); Get( c ); Put_Line( "The character you typed was '" & c & "'" ); end giodemo; This program displays information on the screen and reads information from the keyboard Put_Line displays a line of text and advances to the next line. Put displays text, but it doesn't start a new line
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (6 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

New_Line displays a blank line Get waits for a character to be typed. Type a key and the Enter key to continue. g The character you typed was 'g' [Not complete] These packages are only useful for simple programs. Usually you will rely on packages/libraries provided for your project. Text_IO file operations are very limited and are only intended for quick and dirty programs. There are other libraries for more extensive file operations, such as Ada.Sequential_IO and Ada.Direct_IO. There is also a subpackage for displaying formatted text, such as columns of numbers.

12.2.2 IO_Aux
GNAT's IO_Aux package provides three commonly used functions to Text_IO programs: testing for a file's existence, and reading an unlimited length strings from a text file or a console. with Ada.Text_IO, GNAT.IO_Aux; use Ada.Text_IO, GNAT.IO_Aux; procedure ioaux is -- this program demonstrates the features of the IO_Aux -- package TestFile : string := "/etc/passwd"; procedure ScanString( s : string ) is begin Put_Line( "The string you typed was " & s ); Put_Line( "It is" & s'length'img & " characters long" ); end ScanString; begin Put_Line( "This program demonstrates the features of the" ); Put_Line( "IO_Aux package. This package adds three functions" ); Put_Line( "to simple Text_IO programs." ); New_Line; Put_Line( "File_Exists tests for a file's existence." ); if File_Exists( TestFile ) then Put_Line( TestFile & " exists" ); else Put_Line( TestFile & " doesn't exist" ); end if; New_Line; Put_Line( "Get_Line is the same as Ada.Text_IO's Get_Line" ); Put_Line( "except that reads a string of unlimited length" ); Put_Line( "and doesn't return an explicit length value." ); New_Line; Put_Line( "Please type in a string of any length" ); ScanString( GNAT.IO_Aux.Get_Line );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (7 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

New_Line; Put_Line( "The third function is a version of Get_Line" ); Put_Line( "that reads any string from a Text_IO files." ); New_Line; end ioaux;

This program demonstrates the features of the IO_Aux package. This package adds three functions to simple Text_IO programs. File_Exists tests for a file's existence. /etc/passwd exists Get_Line is the same as Ada.Text_IO's Get_Line except that reads a string of unlimited length and doesn't return an explicit length value. Please type in a string of any length Mary had a little lamb The string you typed was Mary had a little lamb It is 22 characters long The third function is a version of Get_Line that reads any string from a Text_IO files.

12.3 Sequential_IO
A sequential file is a list of similar items saved on a disk (or other long-term storage media). They are similar to a one dimensional array except there is no upper bound, and each item must be processed in sequence (hence the name "sequential"). You can create sequential files of same-length strings, or integer, but most commonly records are used. You can open an existing sequential IO file, or you can create a new one. When you open or create a file, you have to indicate what file mode you'll be using. "In" mode files can only be read. "Out" mode files can only be written to. "Append" is like out mode except that records are added to the end of an existing file. The reset procedure changes to a new mode and repositions your program accordingly to the end or beginning of the file. When you are finished with a sequential file, you can either close it or delete it if you don't need it again. Because there is no way of knowing how many records are remaining in the file, there is a function called End_of_File that you can check after each read to see if the last item has been read. You can only use End_of_File in In mode--it makes no sense to use it in Out or Append modes since you always write at the end of the file. The following program writes a couple of customer records to a sequential file and reads them back again: with Ada.Text_IO, Ada.Sequential_IO, Ada.IO_Exceptions; use Ada.Text_IO; procedure sequentio is -- Ada.Sequential_IO example type aCustomer is record

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (8 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

name : string(1..40); amountOwing : float := 0.0; end record; -- a customer record with two fields package aCustomerFile is new Ada.Sequential_IO( aCustomer ); use aCustomerFile; -- instantiate a new package for sequential IO on a file of -- customer records CustomerFile : aCustomerFile.File_Type; -- our customer file -- use "aCustomerFile" because Text_IO and Sequential_IO have File_Type cr : aCustomer; begin Put_Line( "This is a Ada.Sequential_IO example" ); New_Line; -- create the file Create( CustomerFile, Mode => Out_File, Name => "customer.seq" ); -- display some statistics Put_Line( "We created the file " & Name( CustomerFile ) ); Put_Line( "We're currently using " & Mode( CustomerFile )'img & " mode" ); if Is_Open( CustomerFile ) then Put_Line( "The file is open" ); else Put_Line( "The file isn't open" ); end if; New_Line; -- write the first record cr.name := "Tokyo Book Distributors Write( CustomerFile, cr ); Put_Line( "Writing " & cr.name ); -- write another record cr.name := "General Pizza Inc. "; Write( CustomerFile, cr ); Put_Line( "Writing " & cr.name ); Put_Line( "End_of_File not allowed on Out files" ); begin if End_Of_File( CustomerFile ) then Put_Line( "We are at the end of the file" ); else ";

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (9 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

Put_Line( "We aren't at the end of the file" ); end if; exception when Ada.IO_Exceptions.Mode_Error => Put_Line( Standard_Error, "End_of_File caused Ada.IO.Exceptions.Mode_Error" ); when others => Put_Line( Standard_Error, "Unexpected exception occurred" ); end; New_Line; -- change modes using Reset Put_Line( "Reset can change the file mode" ); Put_Line( "Changing to In_File mode" ); Reset( CustomerFile, In_File ); -- read first record Put_Line( "Reading the next customer" ); Read( CustomerFile, cr ); Put_Line( "Read " & cr.name ); New_Line; -- read second record Put_Line( "Reading the next customer" ); Read( CustomerFile, cr ); Put_Line( "Read " & cr.name ); New_Line; -- check the end of the file Put_Line( "End_of_File works on In files" ); if End_Of_File( CustomerFile ) then Put_Line( "We are at the end of the file" ); else Put_Line( "We aren't at the end of the file" ); end if; New_Line; Put_Line( "Closing file" ); Close( CustomerFile ); end sequentio;

This is a Ada.Sequential_IO example We created the file /home/ken/ada/trials/customer.seq We're currently using OUT_FILE mode The file is open Writing Tokyo Book Distributors Writing General Pizza Inc. End_of_File not allowed on Out files

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (10 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

End_of_File caused Ada.IO.Exceptions.Mode_Error Reset can change the file mode Changing to In_File mode Reading the next customer Read Tokyo Book Distributors Reading the next customer Read General Pizza Inc. End_of_File works on In files We are at the end of the file Closing file [Form not covered--KB]

12.4 Direct_IO
In relational database programming, you create tables of information. The tables act like arrays that are limited in length by the amount of disk space you have. Each table consists of a series of rows, and each row is divided up into subcategories called columns. A telephone book, for example, can be considered one large table. Each row contains information about a different person. Each row is subdivided into columns of names, addresses and phone numbers. Although you could represent a database table using a sequential IO file, it would be very difficult to use. To look up the 1000th entry in the file, you would have to read through the first 999 entries. The Ada equivalent to a database table is called a direct IO file. Some languages refer to this kind of file as a "random access" file. A direct IO file is called "direct" because you can move directly to any row in the file without having to read any other rows. The rows in a direct IO file are typically represented by records (athough they can be any data of a known length) and the columns are the fields in the records. Direct IO files can also use variant records--Ada will ensure there is enough space in each entry for the largest variation. You can open an existing direct IO file, or you can create a new one. When you open or create a file, you have to indicate what file mode you'll be using. "In" mode files can only be read. "Out" mode files can only be rewritten. Unlike sequential IO files, there is also an "In Out" mode which allows you to both read and write records. This is the most common mode for accessing direct IO files. If you move to a position beyond the end of the file, such as trying to write to row 100 when there are only 50 rows, the other unused rows will be created and filled with zero bytes--ASCII.NUL in characters or strings, 0 in integers and long_integers, and so forth. The only way to shorten a direct IO file is to create a new one, delete the original and copy the new one in place of the original. There are several useful functions for direct IO files: q Is_Open is true if the file has been opened q End_Of_File is true if you have read the last record in the file. (This is unavailable in out mode.) q Name is the path of the file q Mode is the current file mode q Size is the number of rows in the file q Index is the number of the current row The following example program reads and writes customer information using the Ada.Direct_IO package.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (11 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

with Ada.Text_IO, Ada.Direct_IO, Ada.IO_Exceptions; use Ada.Text_IO; procedure dirio is -- Ada.Direct_IO example type aCustomer is record name : string(1..40); amountOwing : float; end record; -- a customer record with two fields package aCustomerFile is new Ada.Direct_IO( aCustomer ); use aCustomerFile; -- instantiate a new package for direct IO on a file of -- customer records CustomerFile : aCustomerFile.File_Type; -- our customer file -- use "aCustomerFile" because Text_IO and Direct_IO have File_Type cr : aCustomer; begin Put_Line( "This is a Ada.Direct_IO example" ); New_Line; -- create the file Create( CustomerFile, Mode => Out_File, Name => "customer.dir" ); -- display some statistics Put_Line( "We created the file " & Name( CustomerFile ) ); Put_Line( "We're currently using " & Mode( CustomerFile )'img & " mode" ); Put_Line( "There are" & Size( CustomerFile )'img & " records" ); Put_Line( "We are on row " & Index( CustomerFile )'img ); if Is_Open( CustomerFile ) then Put_Line( "The file is open" ); else Put_Line( "The file isn't open" ); end if; New_Line; -- write the first record cr.name := "Midville Electric "; Write( CustomerFile, cr ); Put_Line( "Writing " & cr.name ); Put_Line( "There are" & Size( CustomerFile )'img & " records" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (12 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

Put_Line( "We are on row " & Index( CustomerFile )'img ); New_Line; -- write the next record on row 7 cr.name := "New York Distributors "; Write( CustomerFile, cr, To => 7 ); Put_Line( "Writing " & cr.name & " to row 7" ); Put_Line( "There are" & Size( CustomerFile )'img & " records" ); Put_Line( "We are on row " & Index( CustomerFile )'img ); Put_Line( "End_of_File not allowed on In files" ); begin if End_Of_File( CustomerFile ) then Put_Line( "We are at the end of the file" ); else Put_Line( "We aren't at the end of the file" ); end if; exception when Ada.IO_Exceptions.Mode_Error => Put_Line( Standard_Error, "End_of_File caused Ada.IO_Exceptions.Mode_Error" ); when others => Put_Line( Standard_Error, "Unexpected exception occurred" ); end; New_Line; -- change modes using Reset Put_Line( "Reset can change the file mode" ); Put_Line( "Changing to InOut_File mode" ); Reset( CustomerFile, InOut_File ); -- read first record Put_Line( "Reading the next customer" ); Read( CustomerFile, cr ); Put_Line( "Read " & cr.name ); New_Line; -- read second (undefined record) Put_Line( "Reading from row 2" ); Read( CustomerFile, cr ); Put_Line( "Read " & cr.name ); New_Line; -- read 7th row Put_Line( "Reading from row 7" ); Read( CustomerFile, cr, From => 7 ); Put_Line( "Read " & cr.name ); New_Line; -- check the end of the file Put_Line( "End_of_File works on InOut files" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (13 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

if End_Of_File( CustomerFile ) then Put_Line( "We are at the end of the file" ); else Put_Line( "We aren't at the end of the file" ); end if; New_Line; Put_Line( "Closing file" ); Close( CustomerFile ); end dirio;

This is a Ada.Direct_IO example We created the file /home/ada/customer.dir We're currently using OUT_FILE mode There are 0 records We are on row 1 The file is open Writing Midville Electric There are 1 records We are on row 2 Writing New York Distributors There are 7 records We are on row 8 End_of_File not allowed on In files End_of_File caused Ada.IO_Exceptions.Mode_Error Reset can change the file mode Changing to InOut_File mode Reading the next customer Read Midville Electric Reading from row 2 Read Reading from row 7 Read New York Distributors End_of_File works on InOut files We are at the end of the file Closing file Note: In this example, reading from the unassigned second record put a row of 40 ASCII.NUL characters on the screen. Because these are non-printable characters, nothing is visible in the results. [What about objects? How are tags treated? --KB] Direct_IO files are suitable for small database tables. If you need to work with large amounts of data, you should consider installing one of the free Linux databases (such as PostgreSQL or mySQL) and using them to store and retrieve your data. This is discussed in upcoming chapters. to row 7

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (14 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

Alternately, you can write your own database package using a the Linux kernel. seqio, a sequential IO package, is developed in chapter 16.

12.5 Formatted Output


Formatted output refers to displaying a value based on a template showing, in general, how the output should look. Because the template is a string, it's easy to visualize the results. This idea is used in languages like COBOL and BASIC (with its PRINT USING command). The Ada.Text_IO.Editing provides formatted output. The string template is called a picture. The picture can contain the following symbols. q '+' - the number will be printed with a leading + or q '-' - a negative numbers will be printed with a leading q '<' and '>' - a negative number will be printed with (..) q "CR" - a negative number will be printed with a leading "CR" (credit) q "DB" - a negative number will be printed with a leading "DB" (debit) q '$' - the currency symbol will be printed, or a floating dollar sign if multiple instances q '.' - marks the actual position for a decimal point q 'V' - marks the assumed position for a decimal point q '9' - space for a number with leading zeros q '#' - same as '$', except only the leading character is shown q 'Z' - space for a numbers with leading blanks q '_', 'B', '0', '/' - inserted. 'B' is a blank q '*' - space for a number with leading asterisks A PICTURE_ERROR is raised if there is a mistake in the layout. A LAYOUT_ERROR is raised if the layout can't be used with a particular value. Using a negative number without specifying a format symbol that allows negative numbers causes a LAYOUT_ERROR. Before using Text_IO.Editing, the internal generaic package Decimal_Output must be instantiated for a particular numeric type. Only decimal types are allowed. type money is delta 0.01 digits 18; package formatted_io is new ada.text_io.editing.decimal_output( money ); To_Picture converts a string to a picture type. Pic_String returns the string of the picture type. p : picture := To_Picture( "###9.99" ); s : string := Pic_String( p ); Valid returns true if a string is a valid picture. When Blank_When_Zero parameter is true, a zero represented as an empty string is allowed. By default, the picture string must show something for a zero. Blank_When_Zero can also be used with To_Picture. if not Valid( "####9.99" ) then Put_Line( Standard_Error, "This is a bad picture string" ); end if; Put displays the formatted decimal value. There is also an Image function that returns the results as a string instead of displaying it on the screen. Length returns the length of the formatted output. There is no Put_Line.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (15 of 35) [7/20/2001 11:34:26 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

Put( 455.32, pic ); str := Image( 455.32, pic ); Put( str, 455.32, pic ); Here is an larger example: with ada.text_io.editing; use ada.text_io; use ada.text_io.editing; procedure formatted is type money is delta 0.001 digits 18; package formatted_io is new ada.text_io.editing.decimal_output( money ); use formatted_io; procedure ShowValues( s : string ) is begin put( " 0.0 and " &s & " => " ); put( 0.0, To_Picture( s ) ); new_line; put( " 75.12 and " &s & " => " ); put( 75.12, To_Picture( s ) ); new_line; put( "-75.12 and " &s & " => " ); begin put( -75.12, To_Picture( s ) ); exception when others => put( "LAYOUT_ERROR" ); end; new_line; end ShowValues; begin put_line( "This is an example of Formatted Output" ); put_line( "--------------------------------------" ); new_line; put_line( put_line( put_line( put_line( new_line; "Default "Default "Default "Default currency symbol is " & Default_Currency ); fill character is '" & Default_Fill & "'" ); separator character is '" & Default_Separator & "'" ); radix mark is '" & Default_Radix_Mark & "'" );

ShowValues( "99999.99" ); New_Line; ShowValues( "ZZZZ9.99" ); New_Line; ShowValues( "****9.99" ); New_Line; ShowValues( "-$$$9.99" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (16 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

New_Line; ShowValues( "+###9.99" ); New_Line; ShowValues( "<###9.99>" ); New_Line; end formatted;

This is an example of Formatted Output -------------------------------------Default Default Default Default currency symbol is $ fill character is ' ' separator character is ',' radix mark is '.'

0.0 and ZZZZ9.99 => 0.00 75.12 and ZZZZ9.99 => 75.12 -75.12 and ZZZZ9.99 => LAYOUT_ERROR 0.0 and -9999.99 => 0000.00 75.12 and -9999.99 => 0075.12 -75.12 and -9999.99 => -0075.12 0.0 and ****9.99 => ****0.00 75.12 and ****9.99 => ***75.12 -75.12 and ****9.99 => LAYOUT_ERROR 0.0 and -$$$9.99 => $0.00 75.12 and -$$$9.99 => $75.12 -75.12 and -$$$9.99 => - $75.12 0.0 and +###9.99 => + $0.00 75.12 and +###9.99 => + $75.12 -75.12 and +###9.99 => - $75.12 0.0 and <###9.99> => $0.00 75.12 and <###9.99> => $75.12 -75.12 and <###9.99> => ( $75.12) Put has many parameters used to override default values. q Currency - the currency string to use q Fill - the fill character to use q Separator - the separator character to use q Radix_Mark - the radix mark to use There is also a Wide_Text_IO.Editing for wide string.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (17 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

12.6 Calendar Package


Calendar is the standard Ada package for telling time. You can get the current time, compare time values, do time arithmetic and comparisons. There is also a GNAT.Calendar package which extends the Ada.Caledar package with days of the week, second duration, and other features. Table: North American Federal Holidays and Celebrations Work schedules (not including small retail stores) often affected by these holidays. q New Year's Day, January 1st. q Birthday of Martin Luther King (U.S.), third Monday in January. q Inauguration Day (U.S.), January 20th every four years, starting in 1937. q Washington's Birthday (U.S.), third Monday in Febrauary. q Inauguration Day (U.S.), March 4th every four years, pre-1937. q Good Friday and Easter Sunday (see below). q Armed Forces Day (U.S.), third Saturday in May. q Memorial Day (U.S.), last Monday in May. q Flag Day (U.S.), June 14th. q Canada Day (Canada), July 1. q United States of America's Independence Day (U.S.), July 4. q Labor Day, first Monday in September. q Columbus Day, second Monday in October. q Thanksgiving Day (Canada), second Monday in October. q Election Day (U.S.), Tuesday on or after November 2. q Veterans Day (U.S.), November 11th. q Remembrance Day (Canada), November 11th. q Thanksgiving Day (U.S.), fourth Thursday in November. q Christmas Day, December 25th. North American Banking (and postal) Holidays include Easter Monday and Victoria Day (Canada). Daylight Savings Time Daylight Savings time begins, first Sunday in April (but not in Arizona, Hawaii, and parts of southern Indiana). Daylight Savings Time ends, last Sunday in October (but not in Arizona, Hawaii, and parts of southern Indiana). Table:Other Widely Celebrated North American Observances q Groundhog Day, February 2. q Lincoln's Birthday (U.S.), February 12. q Valentine's Day, February 14. q Washington's Birthday (U.S.), February 22. q St. Patrick's Day, March 17. q April Fools's Day, April 1. q Mothers' Day, second Sunday in May (36 USC Sec. 142). q Victoria Day (Canada), second last Monday in May [KB?] q Fathers' Day, third Sunday in June (36 USC Sec. 142a).

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (18 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages


q q q q q q q

St. Jean Baptiste Day (Quebec/Canada), last Saturday in June [KB?]. Parents' Day, fourth Sunday in July (36 USC Sec. 142c). Grandparents' Day, Sunday after Labor Day (36 USC Sec. 142b). Columbus Day (U.S., traditional), October 12. United Nations Day (U.S.), October 24. Halloween, October 31. Boxing Day, December 26.

The following program demonstrates the basic operations of the calender package. with text_io, calender; use calender; procedure caldemo is Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration; Christmas94 : time; begin Text_IO.Put_Line( "A simple calendar example" ); Text_IO.New_Line; Split( Clock, Year, Month, Day, Seconds ); Text_IO.Put_Line( "The current date is" & Year'img & "/" & Month'img & "/" & Day'img ); Text_IO.Put_Line( "It's" & seconds'img & " seconds into the day" ); Text_IO.New_Line; Christmas94 := Time_Of( 1994, 12, 25 ); if Christmas94 < Clock then Text_IO.Put_Line( "It's after Christmas 1994" ); else Text_IO.Put_Line( "It's before Christmas 1994" ); end if; Text_IO.New_Line; Split( Clock+12.5, Year, Month, Day, Seconds ); Text_IO.Put_Line( "In 12.5 seconds it will be " & Year'img & "/" & Month'img & "/" & Day'img ); Text_IO.Put_Line( "And" & seconds'img & " seconds into the day" ); end caldemo;

A simple calendar example


file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (19 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

The current date is 1998/ 12/ 17 It's 59775.185023000 seconds into the day It's after Christmas 1994 In 12.5 seconds it will be 1998/ 12/ 17 And 59787.686581000 seconds into the day The GNAT.Calendar.Time_IO package will write a time value according to a format string, similar to the Linux strftime function. Easter is one of the hardest holidays to calculate. The following is a program to calculate the date of Easter Sunday: [This should be rewritten for Ada.Calender -- KB]

with Ada.Text_IO; use Ada.Text_IO; procedure easter is procedure findEaster( year : integer; easter_month, easter_day : out integer ) is -- based on the public domain algorithm -- by Ed Bernal a,b,c,e,g,h,i,k,u,x,z : integer; begin ----"Gauss' famous algorithm (I don't know how or why it works, so there's no commenting)" -- Ed Bernal

a := year mod 19; b := year / 100; c := year rem 100; z := b / 4; e := b rem 4; g := (8*b + 13) / 25; h := (19*a + b - z - g + 15) rem 30; u := (a + 11*h) / 319; i := c / 4; k := c rem 4; x := (2*e + 2*i - k - h + u + 32) rem 7; easter_month := (h-u+x+90) / 25; easter_day := (h-u+x + easter_month +19) rem 32; end findEaster; month, day : integer; begin findEaster( 2000, month, day ); Put( "Easter Sunday 2000 is month " & month'img );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (20 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

Put_Line( " and day " & day'img ); end easter;

Easter Sunday 2000 is month

4 and day

23

12.7 Tags Package


Ada.Tags contains some utility procedures to for the invisible tags that accompany tagged records, including converting tags to and from strings. The following program shows what the tags package can do and shows tag comparison with the in operator. with text_io, ada.tags; procedure t is type ParentRec is tagged record i : integer; end record; type ChildRec is new ParentRec with record j : integer; end record; child : ChildRec; begin Text_IO.Put_Line( "Working with Tagged Record Tags:" ); Text_IO.New_Line; Text_IO.Put_Line( "ParentRec has an expanded name of " & Ada.Tags.Expanded_Name( ParentRec'Tag ) ); Text_IO.Put_Line( "ChildRec has an expanded name of " & Ada.Tags.Expanded_Name( ChildRec'Tag ) ); Text_IO.New_Line; Text_IO.Put_Line( "ParentRec has an external tag of " & Ada.Tags.External_Tag( ParentRec'Tag ) ); Text_IO.Put_Line( "ChildRec has an external tag of " & Ada.Tags.External_Tag( ChildRec'Tag ) ); Text_IO.New_Line; if child in ParentRec'class then Text_IO.Put_Line( "child (a child rec) is in ParentRec'class" ); else Text_IO.Put_Line( "This should not happen" ); end if; if child in ChildRec'class then Text_IO.Put_Line( "child (a child rec) is in ChildRec'class" ); else Text_IO.Put_Line( "This should not happen" );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (21 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

end if; end t;

Working with Tagged Record Tags: ParentRec has an expanded name of T.PARENTREC ChildRec has an expanded name of T.CHILDREC ParentRec has an external tag of T.PARENTREC ChildRec has an external tag of T.CHILDREC child (a child rec) is in ParentRec'class child (a child rec) is in ChildRec'class

12.8 Tables
Gnat 3.11 introduces gnat.table, a gnat package for creating an aribrary length array (or, for that matter, a link list). [expand and give example program]

12.9 Hash Tables


Gnat provides a generic package for hash tables called gnat.htable. You provide gnat's package with information on the size of the tables, the elements it contains, and a hash function and the instantiation provides Get and Set procedures to put values in and take values out of your hash table.

Gnat 3.11: This version of gnat adds remove and iterator subprograms for hash tables. The following is an example using a hash table of integers. with text_io, gnat.htable; use text_io; procedure hashtest is -- First, define the items required by gnat.htable type HashTableIndex is newinteger range 1..200; subtype HashElement is integer; EmptyPosition : constant HashElement := 9999; function HashOf( he : HashElement ) return HashTableIndex is begin return HashTableIndex( ( ( he * 91 ) mod integer( HashTableIndex'last ) ) + 1 ); end HashOf; -- OK, instantiate the package -file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (22 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

------

IntTable is a simple HashTable of integer. Since we're using simple integers, the hash key is the integer itself and we can compare integers with equals without having to write a function to compare the values.

package IntTable is new gnat.htable.simple_htable( Header_Num => HashTableIndex, -- how big the table is Element => HashElement,-- what's in the table No_Element => EmptyPosition,-- what's in empty positions Key => HashElement, -- what the key is Hash => HashOf,-- function to generate the hash Equal => "=" ); -- how to compare things in table begin Put_Line( "This is an example of a hash table of integers" ); New_Line; IntTable.Set( 1, 1 ); IntTable.Set( 27, 27 ); Put_Line( "Added 1 and 27 to the hash table" ); Put_Line( "Empty positions are" & EmptyPosition'img ); New_Line; Put_Line( "Pulling 1 from the hash table =" & IntTable.Get( 1 )'img ); Put_Line( "Pulling 27 from the hash table =" & IntTable.Get( 27 )'img ); Put_Line( "Pulling 99 from the hash table =" & IntTable.Get( 99 )'img ); end HashTest;

This is an example of a hash table of integers Added 1 and 27 to the hash table Empty positions are 9999 Pulling 1 from the hash table = 1 Pulling 27 from the hash table = 27 Pulling 99 from the hash table = 9999 [Could use more realistic example--KB]

12.10 Bubble and Heap Sorts


Gnat provides two packages for bubble sorting. Both assume that your information is in an array with a lower bound of zero. The zero element is used as temporary space for the sort. The first, gnat.bubble_sort_g, is a generic. You provide the package with a procedure to move data in the array and a function to check for one value being less than another. The instantiation provides a sort procedure. with text_io, gnat.bubble_sort_g;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (23 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

use text_io; procedure bubble1 is -- Our table to sort type IntegerTable is array( 0..5 ) of integer; it : IntegerTable := ( 0, 13, 4, 5, 16, 8 ); -- Define the items required by a generic gnat bubble sort procedure MoveIntegers( From, To : natural ) is begin it( To ) := it( From ); end MoveIntegers; function CompareIntegers( left, right : natural ) return boolean is begin return it( left ) < it( right ); end CompareIntegers; -- OK, instantiate the package -package IntSort is new gnat.bubble_sort_g( Move => MoveIntegers, -- how to move two things Lt => CompareIntegers ); -- how to compare to things procedure ShowTable is begin for i in IntegerTable'range loop Put_Line( i'img & " = " & it( i )'img ); end loop; end ShowTable; begin Put_Line( "This is an example of New_Line; Put_Line( "The table begins as:" ShowTable; IntSort.Sort( it'last ); -- sort New_Line; Put_Line( "The sorted table is:" ShowTable; end bubble1; bubble sorting an integer table" ); ); elements 1 to top of it array );

This is an example of bubble sorting an integer table The table begins as:

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (24 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

0 1 2 3 4 5

= = = = = =

0 13 4 5 16 8

The sorted table is: 0 1 2 3 4 5 = = = = = = 13 4 5 8 13 16

The second, gnat.bubble_sort_a uses callbacks instead of a generic package. Use this package if you want to conserve memory by avoiding a lot of instantiations of the generic bubble_sort_g. Remember that callbacks must be global, so we can't simple pass the local subprograms we created in bubble1. This time we must store the array and subprograms in a separate package. with text_io, gnat.bubble_sort_a, inttable; use text_io, inttable; procedure bubble2 is begin Put_Line( "This is an example of bubble sorting an integer table" ); New_Line; Put_Line( "The table begins as:" ); ShowTable; gnat.bubble_sort_a.Sort( n => it'last, Move => MoveIntegers'access, Lt => CompareIntegers'access ); -- sort elements 1 to top of it array New_Line; Put_Line( "The sorted table is:" ); ShowTable; end bubble2; package inttable is -- Our table to sort type IntegerTable is array( 0..5 ) of integer; it : IntegerTable := ( 0, 13, 4, 5, 16, 8 ); -- Define the items required by a callback gnat bubble sort -- these must be global to work procedure MoveIntegers( From, To : natural ); -- move one item in the table from From position to To position

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (25 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

function CompareIntegers( left, right : natural ) return boolean; -- compare two items in the table and determine if left is less than -- than right procedure ShowTable; end inttable; with text_io; use text_io; package body inttable is procedure MoveIntegers( From, To : natural ) is begin it( To ) := it( From ); end MoveIntegers; function CompareIntegers( left, right : natural ) return boolean is begin return it( left ) < it( right ); end CompareIntegers; procedure ShowTable is begin for i in IntegerTable'range loop Put_Line( i'img & " = " & it( i )'img ); end loop; end ShowTable; end inttable;

This is an example of bubble sorting an integer table The table begins as: 0 1 2 3 4 5 = = = = = = 0 13 4 5 16 8

The sorted table is: 0 = 13 1 = 4 2 = 5

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (26 of 35) [7/20/2001 11:34:27 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

3 = 8 4 = 13 5 = 16 The heap sort package works identically, with both generic (heap_sort_g) and callback (heap_sort_a) versions as well. Heap sorts are better suited to large amounts of data. Here's the callback version using the same inttable package we used above. with text_io, gnat.heap_sort_a, p; use text_io, p; procedure heaptest is begin Put_Line( "This is an example of heap sorting an integer table" ); New_Line; Put_Line( "The table begins as:" ); ShowTable; gnat.heap_sort_a.Sort( n => it'last, Move => MoveIntegers'access, Lt => CompareIntegers'access ); -- sort elements 1 to top of it array New_Line; Put_Line( "The sorted table is:" ); ShowTable; end heaptest;

This is an example of heap sorting an integer table The table begins as: [this wasn't corrupted beforeMS Word bug?]

12.11 Regular Expressions


"Regular Expressions" refers to pattern matching for strings: identifying all strings that adhere to a certain pattern. For example, listing all files that end with .ads using the shell command "ls *.ads" is an example of a regular expression. GNAT has two built-in packages for dealing with regular expressions. The first, called "Regexp", performs pattern matching using two different standards. First, it supports standard UNIX shell "file globbing" expressions as described by "man bash". Second, it supports BNF patterns as described in the Ada Reference Manual. Using the package is a two step process. First, you must compile the expression using the Compile function. Then, you check for a string that matches the expression using the Match function. The following program demonstrates the Regexp package. with Ada.Text_IO, GNAT.Regexp;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (27 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

use Ada.Text_IO, GNAT.Regexp; procedure regex is procedure TestMatch( re : Regexp; s : string ) is begin if Match( s, re ) then Put_Line( s & " matches the expression" ); else Put_Line( s & " doesn't match the expression" ); end if; end TestMatch; Criteria : Regexp; begin Put_Line( "This program demonstrates GNAT's regular expression" ); Put_Line( "capabilities. These are used to find text that match" ); Put_Line( "a certain pattern." ); New_Line; -- UNIX Regular Expressions Put_Line( "A 'globbing pattern' is a UNIX shell-style pattern matching" ); Put_Line( "The pattern 'a*' matches anything starting with the letter 'a'" ); Criteria := Compile( "a*", Glob => true, Case_Sensitive => true ); New_Line; TestMatch( Criteria, "accounting" ); TestMatch( Criteria, "President" ); TestMatch( Criteria, "sundries" ); New_Line; -- BNF Expressions Put_Line( "A non-globbing pattern is a BNF pattern, as used in the Ada" ); Put_Line( "Reference Manual. For example, 'a[a-z]*' means characters" ); Put_Line( "beginning with 'a' and with any number of letters following." ); Criteria := Compile( "a[a-z]*", false, true ); New_Line; TestMatch( Criteria, "accounting" ); TestMatch( Criteria, "sales" ); New_Line; end regex;

This program demonstrates GNAT's regular expression capabilities. These are used to find text that match a certain pattern.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (28 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

A 'globbing pattern' is a UNIX shell-style pattern matching The pattern 'a*' matches anything starting with the letter 'a' accounting matches the expression President doesn't match the expression sundries doesn't match the expression A non-globbing pattern is a BNF pattern, as used in the Ada Reference Manual. For example, 'a[a-z]*' means characters beginning with 'a' and with any number of letters following. accounting matches the expression sales doesn't match the expression The second Gnat pattern matching package is "Regpat" which interprets full UNIX V7 regular expressions as defined in the "man regexp" Linux man page. Don't be confused by the naming conventions: the Regexp package does not do Linux regular expressions.

12.12 Advanced String Processing


[spitbol-style string processing not finished]

12.13 GLADE Distributed Processing


GLADE is the free distributed processing package for TCP/IP and gnat. It is distributed separately from the gnat compiler. This should not be confused with the GTK's Glade, the GUI builder for the Gimp Toolkit widgets, which has bindings for Ada (http://glade.pn.org/). GLADE is built into the ALT version of GNAT. To install GLADE, unpack it and type "configure" and "make install". GLADE works on partitions, programs designed to run on other computers. Each partition has a channel between itself and another partition. Of course, the partitions can also run concurrently on one computer. You describe the partitions and channels using an Ada-like language called Garlic. GLADE uses rsh to start partitions, so make sure you don't run the programs under the root login since root is not allowed to run programs via rsh. [KB: I could install and compile programs with glade, but the communication wasn't workingerror in my networking setup or did I not install it properly?]

12.14 Basic Math Packages


Type Generic Ada Package Description basic math for Ada.Numerics.Generic_Elementary_Functions floating point numbers

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (29 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

basic math for short_float type basic math for Float Ada.Numerics.Elementary_Functions float type basic math for Long_Float Ada.Numerics.Long_Elementary_Functions long_float type basic math for Long_Long_Float Ada.Numerics.Long_Log_Elementary_Functions long_long_float type Short_Float Ada.Numerics.Short_Elementary_Functions Sooner or later, you will ask the question, "So, how do I compute the cosine of a number?" The answer found is the Ada.Numerics.Generic_Elementary_Functions package. This package with the unusually long name is the basic floating point math package. This is a generic package that you instantiate for a particular floating point type. For example, to set up the package for a custom floating point type called "percent", with Ada.Numerics.Generic_Elementary_Functions; type percent is new float range 0.0..1.0; package percentMath is new Ada.Numerics.Generic_Elementary_Functions( percent ); use percentMath; The "use percentMath" statement saves us from typing "percentMath." before every function we use. With percentMath instantiated, we can now perform basic floating point math functions such as Put_Line( "20% to the power of 3 is" & percent'image( 0.2**3.0 ) ); As shown in the table at the start of this section, elementary function packages for the basic floating point types are included with Gnat. The elementary package includes: Function Sqrt( x ) Log( x ) Log( x, b ) Exp( x ) ** Sin( x ) Sin( x, c ) Cos( x ) Cos( x, c ) Tan( x ) Tan( x, c ) Description Square Root Natural Logarithm (ln in some other languages) Logarithm to base b Raise e by power x Power operator Sine for x radians Sine for x where cycle range is c (eg. 360 for degrees) Cosine for x radians Cosine for x where cycle range is c Tangent for x radians Tangent for x where cycle range is c

There are corresponding functions for arctan, arccot, sinh, cosh, tanh, coth, arccosh, arctanh, artcoth. Here's an example using the built-in functions for the float type, and creating our own functions for our own percent type: with Ada.Text_IO, Ada.Numerics.Elementary_Functions, Ada.Numerics.Generic_Elementary_Functions; use Ada.Text_IO, Ada.Numerics.Elementary_Functions;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (30 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

procedure floatmath is type percent is new float range 0.0..1.0; package percentMath is new Ada.Numerics.Generic_Elementary_Functions( percent ); use percentMath; half : percent := 0.5; begin Put_Line( "Here's some floating point math!" ); New_Line; Put_Line( "4.0 to the power 3.0 is" & float'image( 4.0 ** 3.0 ) ); Put_Line( "The sine of 0.4 radians is" & float'image( sin( 0.4 ) ) ); Put_Line( "The cosine of 180 degrees is" & float'image( sin( 180.0, 360.0 ) ) ); Put_Line( "The square root of 81 is" & float'image( sqrt( 81.0 ) ) ); Put_Line( "50% squared is" & percent'image( half ** 2.0 ) ); end floatmath;

Here's some floating point math! 4.0 The The The 50% to the power 3.0 is 6.40000E+01 sine of 0.4 radians is 3.89418E-01 cosine of 180 degrees is 0.00000E+00 square root of 81 is 9.00000E+00 squared is 2.50000E-01

When you work with floating point subprograms in libraries outside of Ada, there's a chance that the library will change the floating point arithmetic settings for your CPU. When this happens, use the GNAT.Float_Control package to change your CPU back to GNAT's preferred defaults. There is only one subprogram in this package: reset. If you are interested in integer operations not covered by the built-in Ada features, the Interfaces package (the package used to interface Ada to other languages) defines several bit-shifting functions. In order to use these functions, you'll need to convert (or derrive) your integer values to one of Interfaces' integer types: Function Rotate_Left Rotate_Right Shift_Left Shift_Right Shift_Right_Arithmetic Description Rotate bits in integer types leftward Rotate bits in integer types rightward Shift bits in integer types leftward Shift bits in integer types rightward Arithmetic shift bits in integer types rightward

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (31 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

C: Shift_Left is the equivalent of the C << operator. Shift_Right is the equivalent of the >> operator. In Gnat, bit-shifting operations are intrinsic. That is, they act as built-in functions and execute quickly. Here is an example of shifting integer values. with Ada.Text_IO, Interfaces; use Ada.Text_IO, Interfaces; procedure shiftMath is six : unsigned_64 := 6; begin Put_Line( "Time to do a little bit shifting" ); New_Line; Put_Line( "Our integer is" & six'img ); Put_Line( "In binary, this is" & six'img ); Put_Line( "Shifted left once is" & Shift_Left( six, 1 )'img ); Put_Line( "Shifted left twice is" & Shift_Left( six, 2 )'img ); Put_Line( "Shifted right once is" & Shift_Right( six, 1 )'img ); Put_Line( "Arithmetic Shifted right once is" & Shift_Right_Arithmetic( six, 1 )'img ); end shiftMath;

Time to do a little bit shifting Our integer is 6 In binary, this is 6 Shifted left once is 12 Shifted left twice is 24 Shifted right once is 3 Arithmetic Shifted right once is 3

12.15 Exception Handling and Traceback Packages


Gnat includes packages for working with exceptions. Using these packages, you can add a message to your exceptions, save exceptions, and examine an exception occurences when they are raised. Traceback is a technique to examine the run-time stack and identify where an exception occurred. Gnat can identify the specific source file and line where an exception occurred. To use tracebacks in Linux, you must compile your program with the -funwind-tables switch and bind with the -E switch. [Zero-cost exceptions not covered yet--KB] with Ada.Text_IO,Ada.Exceptions,Gnat.Current_Exception,Gnat.Traceback.Symbolic; use Ada.Text_IO,Ada.Exceptions,Gnat.Current_Exception,Gnat.Traceback.Symbolic;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (32 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

procedure exc is e : exception; saved_exception : Exception_Occurrence; procedure CrashMe is begin Raise_Exception( e'identity, "call exec development team" ); end CrashMe; begin Put_Line( "This is an example of the Ada.Exceptions package" ); New_Line; -- Information about an exception that is not in progress Put_Line( "Exception_Name returns a unique name for an exception" ); Put_Line( "The unique name our exception is " & Exception_Name( e'identity ) ); New_Line; -- Raising an exception with a message Put_Line( "raise will raise an exception with no message" ); New_Line; Put_Line( "Raise_Exception will raise an exception with a message" ); Put_Line( "Raising " & Exception_Name( e'identity ) & " with the message 'call exc development team'" ); Put_Line( "in the subprogram 'CrashMe'." ); New_Line; CrashMe; exception when occurrence: others => -- Information about an exception that is is in progress Put_Line( "-------------------------------------------------------" ); Put_Line( "An exception has been raised! Now in exception handler" ); Put_Line( "The name of the exception is " & Exception_Name( occurrence ) ); New_Line; Put_Line( "Exception_Message returns the message for this exception" ); Put_Line( "The message for this exception is '" & Exception_Message( occurrence ) & "'" ); New_Line; Put_Line( "Exception_Information provides the name, message and any traceback information:" ); Put_Line( Exception_Information( occurrence ) ); New_Line; Put_Line( "The Gnat.Current_Exception package contains short-hand" ); Put_Line( "versions of Exception_Name, Exception_Message, Exception_Information." ); Put_Line( "These functions assume you're referring to the current exception" ); Put_Line( "Gnat.Current_Exception.Exception_Name is " & Exception_Name ); Put_Line( "Gnat.Current_Exception.Exception_Message is '" & Exception_Message &

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (33 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

"'"); New_Line; Put_Line( "The Gnat.Traceback.Symbolic package returns the contents of the" ); Put_Line( "runtime stack. That is, it shows which subprograms were being" ); Put_Line( "executed when the exception occurred." ); Put_Line( "The symbolic traceback is" ); Put_Line( Symbolic_Traceback( occurrence ) ); New_Line; Put_Line( "Ada.Exceptions can also save and re-raise in-progress exceptions" ); New_Line; Put_Line( "Save_Occurence can save the in-progress exception" ); Save_Occurrence( saved_exception, occurrence ); Put_Line( "Exception now saved." ); New_Line; Put_Line( "Reraise_Occurrence will raise an in-progress exception" ); Put_Line( "Reraising the one we just saved..." ); Reraise_Occurrence( saved_exception ); --Allocate/DeallocateMachineState not covered--for zero-cost exceptions end exc;

This is an example of the Ada.Exceptions package Exception_Name returns a unique name for an exception The unique name our exception is EXC.E raise will raise an exception with no message Raise_Exception will raise an exception with a message Raising EXC.E with the message 'call exc development team' in the subprogram 'CrashMe'. ------------------------------------------------------An exception has been raised! Now in exception handler The name of the exception is EXC.E Exception_Message returns the message for this exception The message for this exception is 'call exec development team' Exception_Information provides the name, message and any traceback information: Exception name: EXC.E Message: call exec development team

The Gnat.Current_Exception package contains short-hand versions of Exception_Name, Exception_Message, Exception_Information. These functions assume you're referring to the current exception Gnat.Current_Exception.Exception_Name is E Gnat.Current_Exception.Exception_Message is 'call exec development team' The Gnat.Traceback.Symbolic package returns the contents of the

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (34 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 12 Standard Gnat Packages

runtime stack. That is, it shows which subprograms were being executed when the exception occurred. The symbolic traceback is 0x8049cb3 in exc at exc.adb:10

Ada.Exceptions can also save and re-raise in-progress exceptions Save_Occurence can save the in-progress exception Exception now saved. Reraise_Occurrence will raise an in-progress exception Reraising the one we just saved... raised EXC.E : call exec development team Call stack traceback locations: 0x80497eb Because the reraised exception propogated all the way to the main program and caused it to fail, the final line was actually written to Standard_Error.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/12.html (35 of 35) [7/20/2001 11:34:28 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

13 Linux Introduction
<--Last Chapter Table of Contents Next Chapter-->

This section is an introduction to Linux programming.

13.1 Introduction to Processes


Linux is an operating system. It controls the execution of programs and access to system resources. Linux can run multiple programs at one. Each running program is referred to as a process. The operating system switches to a new process every 100 milliseconds by default--like everything else in Linux, this value can be customized by changing the kernel source code. Even on a Linux computer with only one user, there are usually several programs running in the background. The one process that is always running is "init": this is the root process, the first process Linux starts when the system is started.

13.1.1 Parents, Children and Families


Processes are grouped together into families. Each time a program starts another process, the new process is called a child and the original process is called a parent. When the parent unexpectedly stops running, Linux knows enough to stop all the related processes as well. A multitasking program is a program that starts other processes to run simultaneously and assist it with its work. When a child process starts, Linux makes a copy of the parent's resources for the child. For example, all the files that where open to the parent are also open to the child process. A multithreading program refers to independent streams of execution within a single process. Linux refers to each stream as a thread. Ada tasks and protected types, for example, are threads--they do not create entirely new programs they way multitasking works. Instead, they are miniature programs that run inside the parent task, sharing that parent's resources instead of getting their own copy. Don't confuse Ada tasks with multitasking--the term "task" was chosen before the term "multithreading" became popular. PID's The ps command shows a list of all processes that are running. Each process has its own identifying number, called the PID (for Process Identification). Here's a typical output from the ps command: $ ps PID 579 589 617 PPID's Processes also have a PPID (Parent Process ID) for identifying its parent process. The ps command l option (for "long") shows additional information about a process, including its PPID: $ ps l F S 100 S

TTY tty1 tty1 tty1

TIME 00:00:00 00:00:00 00:00:00

CMD login bash ps

UID 0

PID 579

PPID 1

C PRI 0 60

NI ADDR 0 -

SZ WCHAN 549 wait4

TTY tty1

TIME CMD 00:00:00 login

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (1 of 15) [7/20/2001 11:35:51 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

100 S 0 589 579 0 69 0 457 wait4 tty1 00:00:00 bash 100 R 0 624 589 0 70 0 634 tty1 00:00:00 ps In this case, there are three processes in one family. The ps process (PPID 589) has a bash shell as its parent (PID 589). Likewise, the parent of the bash shell is the login command. Process Groups For complex programs with many processes, Linux can organize processes into process groups. The ps lfw options (long, full, wide) will show the PID, the PPID and a simulated graph of groups of related processes. $ ps lfw F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND 100 0 579 1 0 0 2196 1148 wait4 S tty1 0:00 login -- root 100 0 589 579 15 0 1828 1060 wait4 S tty1 0:00 -bash 100 0 689 589 17 0 2484 824 R tty1 0:00 \_ ps lfw Here, it shows that "ps lfw" is a related to the bash shell process, but the bash shell is not related to the login command. The PPID number shows you which process started another, but not which group it belongs to. Because the bash shell process and the ps command are both members of the same group, if you were to kill the bash process, Linux would automatically kill the ps command as well because they are in the same group. With this arrangment, if the bash shell crashed, Linux can return control to the login program and allow you to log in again. In the same way, if you have many processes in your program, you can group your processes so if they crash unexpectedly, the main program can continue running and take emergency actions. Process groups also provides an easy way to stop several processes at once. For example, a web server could put all the child processes into one group to make it easy to stop them when the server is being shut down. Stopping Processes Normally, a process stops when it reaches the end of the instructions it needs to execute. You can stop a runaway program (or process) with the kill command, giving the command the PID number returned by the ps command. kill 624 #killing ps Below we'll discuss stopping processes from inside a program. A process that runs continually, performing some kind of regular system functions, is called a daemon (pronounced "day-mon", a variation on the word "demon" ). It's referred to as a daemon as if a little evil creature was running around doing work on its own. If you have a web server running, for example, you could refer to it's process as the web daemon.

13.1.2 Ownership and Permissions


For the sake of security, all programs belong to an owner and one or more groups. In the same way that all users have a login name (the "owner") and a list of groups they belong to, every program acts as if it's running on behalf of a particular user and their groups. If you're login is "bob", for example, any program you run will be owned by the "bob" login and whatever groups the "bob" login belongs to--your program can only access files that the "bob" login can access. If a program is owned by the superuser login, it doesn't automatically run with the full authority of the superuser. This can be circumnavigated by the setuid and setgid permissions. When a program is marked with the setuid or setgid active, the program is owned by whatever owner and group owns the file. This is used for system programs that have to schedule events between multiple people, like the printer daemon.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (2 of 15) [7/20/2001 11:35:51 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

13.2 Using System and OsLib.Spawn


Often, the first question new Linux programmers ask is, "How to do you run a shell command like ls from a program?" The easiest, though not necessarily most practical, way to do Linux programming is to use the standard C library's system call. System starts a new process, starts a shell running and gives the shell whatever command to execute that you specify. The command executes just as if you typed it in at the command prompt. For example, to list the files in the current directory on the screen, you'd type: function system( cmd : string ) returns integer; pragma Import( C, system ); ... Result := system( "ls" & ASCII.NUL ); The result is the exit status returned by the command, usually zero if it executed successfully or non-zero if there was an error. To capture the output of the system command, you can redirect the results to a file using the shell's output redirect, ">". This creates a text file for you to open with Ada.Text_IO.Open. Result := system( "ls > /tmp/ls.out" & ASCII.NUL); Ada.Text_IO.Open( fd, in_file, "/tmp/ls.out" ); ... The following is a simple program to print to the printer with the Text_IO library. It creates a text file and then uses system to run lpr to print it. with Ada.Text_IO; use Ada.Text_IO; procedure printer is -- a program for simple printing function System( s : string) return integer; pragma import( C, System, "system"); -- starts a shell and runs a Linux command procedure PrintFile( s : string) is -- run the lpr command Result : integer; begin Result := System( "lpr " & s & ASCII.NUL ); Put_Line( "Queuing " & s & "..." ); if Result /= 0 then Put_Line( "system() call for lpr failed" ); else Put_Line( "Printing is queued" ); end if; end PrintFile; procedure CreateFile( s : string) is -- run the touch command Result : integer; begin Put_Line( "Creatinig " & s & "..." ); Result := System( "touch " & s & ASCII.NUL ); if Result /= 0 then Put_Line( "system() call for touch failed" ); else
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (3 of 15) [7/20/2001 11:35:51 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

Put_Line( "Spool file initialized" ); end if; end CreateFile; -- the text file to print SpoolPath : constant string := "/tmp/spool.txt"; SpoolFile : File_Type; begin -- To open an out_file in text_io, it must exist. -- Create file will create a new spool file. -- Set_Output will redirect all output to the -- spool file. CreateFile( SpoolPath ); Open( SpoolFile, out_file, SpoolPath); Set_Output( SpoolFile ); -- write the report to printer -- Linux normally will not eject a page when -- printing is done, so we'll use New_Page. Put_Line( "Sales Report" ); Put_Line( "------------" ); New_Line; Put_Line( "Sales were good" ); New_Page; -- Now, restore output to the screen, close -- the file and queue the file for printing -- using lpr. Set_Output( Standard_Output ); Close( SpoolFile ); PrintFile( SpoolPath ); Put_Line( "Program done...check the printer" ); end printer; Although this program will work for simple applications, another improved program to print using pipes is discussed below. The system function is convenient but it has a couple of important drawback: q It's slow: it always opens a shell even if you're only using the shell execute some other program q It's a security risk: the shell could have aliases defined and what you thought you were running may not be what actually runs. GNAT's OsLib provides a subprogram like system called spawn. It executes a Linux program without starting a shell first. Spawn requires a bit of setup to use. You have to define an array of access type arguments for the command. Once you invoke spawn, it returns a boolean value indicating whether the spawn succeeded or failed. The following excerpt is from an example program in the OSLib section covered below.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (4 of 15) [7/20/2001 11:35:51 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

Arguments : Argument_List( 1..1 ); -- an argument list for 1 argument Ls : constant string := "/bin/ls"; -- the program we want to run WasSpawned: boolean; RootDir : aliased string := "/"; begin Arguments(1) := RootDir'unchecked_access; -- unchecked to avoid useless (in this case) accessibility warning Spawn( Ls, Arguments, WasSpawned ); if WasSpawned then New_Line; Put_Line( "End of ls output -- Spawned worked" ); else Put_Line( "Spawn failed"); end if; This fragment runs the ls command, prints the results on the screen, and then displays the success of the command on the screen. Notice there are differences between spawn and system: q spawn only gives you a boolean result q spawn does not start a shell, so it is more secure q because there is no shell, you can't run built-in shell commands nor can you redirect output using ">" If spawn is too limited, many UNIX and Linux programming books tell you how to create your own spawn style subprograms using fork, wait and the exec family of standard C commands. Here is an example of a short C function that executes a program and puts the results (standard output and standard error) to a text file of your choosing, allowing up to three parameters for the command. int CRunIt( char * path, char * outfile, char * param1, char * param2, char * param3 ) { pid_t child; int fd0, fd1, fd2; int status; int i; if ( !(child = fork()) ) { /* Redirect stdin, out, err */ for (i=0; i< FOPEN_MAX; ++i ) close( i ); fd0 = open( "/dev/null", O_RDONLY ); if (fd0 < 0) exit( 110 ); fd1 = open( outfile, O_WRONLY | O_CREAT | O_TRUNC ); if (fd1 < 0) exit( 111 ); fd2 = dup( 1 ); if (param1[0]=='\0') { execlp( path, path, NULL ); } else if (param2[0]=='\0') { execlp( path, path, param1, NULL ); } else if (param3[0]=='\0') {

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (5 of 15) [7/20/2001 11:35:51 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

execlp( path, path, param1, param2, NULL ); } else { execlp( path, path, param1, param2, param3, NULL ); } /* if we got here, file probably wasn't found */ exit( errno ); } wait( &status ); if ( WIFEXITED( status ) != 0 ) status = WEXITSTATUS( status ); return status; }

It is possible to rewrite this subprogram into Ada, but it's easier in C because of the constants, macros and execlp takes a variable number of parameters. This function returns some special exit status values: 110 if /dev/null couldn't be opened for standard input, and 111 if the output file you specified couldn't be opened. function CRunIt( cmd, outfile, parm1, parm2, parm3 : string ) return integer; pragma Import( C, CrunIt, "CRunIt" ); .. Result := CrunIt( "/bin/ls" & ASCII.NUL, -- executable to run "/tmp/ls.out" & ASCII.NUL, -- where output should go "" & ASCII.NUL, -- parameter 1 (none) "" & ASCII.NUL, -- parameter 2 (none) "" & ASCII.NUL ); -- parameter 3 (none) An important part of running commands like this is deciding on temp file names that won't be used if two copies of the program are run at the same time. There's two ways to do this: q Use the standard C function tmpfile (discussed below) q Find the process number of your program with the standard C function getpid and add it to your filename If you are interested in accessing Linux more directly, read the next section.

13.3 The Linux Environment


Because Linux is based on decades old UNIX, the Linux development environment is like an onion. Originally, all UNIX programs accessed the operating system through kernel calls. As time went on, new ways of accessing the kernel were added, and new libraries were made to encapsulate common problems. Finally, Ada itself comes with many standard packages and features to work with the operating system. For the Ada programmer, it's not difficult to work with the operating system. Gnat comes with many standard libraries. These are built using the standard C libraries. The C libraries, in turn, work by accessing the kernel. The problem is to decide which of the many ways to access Linux is the best suited for your program. For simple tasks, using the standard Ada packages is the most straightforward way of working with Linux. However, the standard Ada packages were designed for portability: they only allow access to the most basic Linux features, and they aren't particularly fast when doing it. Working with the standard C libraries is a compromise between speed and convenience: the C libraries give you more features, but require you to import C function calls and convert between Ada and C data types. For maximum speed and flexibility, you can only work with kernel, but then you risk extra work by rewriting subprograms that already exist in the standard libraries.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (6 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

To understand the differences between these layers, consider the problem of allocating dynamic memory. Usually you allocate memory with the Ada new statement. Where does new get its memory? It uses the standard C library's malloc function. But where does malloc get its memory? It gets it from the Linux kernel call mmap (memory map). The most direct way to get memory, and the method that gives you the most control, is mmap. On the other hand, the easiest way would be to use new and to let Ada allocate the memory and manage the details for you. It's the same with multithreading and sequential files. Multitasking is based on LinuxThreads, a part of the standard C library, which in turn is based on the kernel's clone function. Sequential files are based on the standard C library's stream functions, which in turn are implemented using the kernel's file handling functions. Figure: Ways of Doing the Same Thing

Standard Ada: Standard C libraries: Linux Kernel:

Memory Allocation new malloc mmap

Multithreading task / protected LinuxThreads functions clone function

Sequential Files Ada.Sequential_IO package C stream functions kernel file functions

As you move down the list from the standard Ada libraries to the Linux kernel, your program becomes more platform specific. A program that uses new will run on any operating system that can run Ada 95. If you use malloc, your program will run on any operating system that uses has the standard UNIX C libraries available. If you use mmap, your program will run on any Linux computernot just Intel-based Linux, but any flavour of Linux, include Sun UltraLinux or Apple Mklinux. Remember that Linux is a portable operating system: all versions of Linux will have mmap available.

13.4 Standard C Libraries


We've already covered many of the standard Ada libraries and language features in the above sections. The standard C libraries define standardized subprograms that exist across most version of UNIX. They are "wrappers": that is, they do not work directly with the kernel. For example, the standard C libraries are not a part of the kernel, but they use the kernel to implement standard C functions that you'd find across many UNIX'sThe main C library, called libc, is automatically loaded by Gnat and you can import subprograms from it directly. Other standard C libraries, such as C's math library, libm, or the password encryption library, libcrypt, need to be linked in at the linking stage. The standard C library calls are defined in the online manual pages.

13.5 The Linux Kernel


There are three basic ways to work with the Linux kernel: kernel calls, devices and the proc file system. Because Linux is organized around files, the last two ways let you operate devices and get system information simply by opening and working with files using standard Linux file operations. This is makes it easier to work with Linux, but it also can make some tasks hard to visualize because you have to do them through a sequence of abstract file operations. In a few cases, standard libraries and kernel calls have names that overlap, which can be confusing. In addition, Linux sometimes provides alternative versions of system calls based on different flavours of UNIX. For example, there are two different system calls to assign an environment variable, one based on BSD UNIX (setenv) and another based on the POSIX standard (putenv). Both do exactly the same thing, but their parameters are slightly different. Linux provides both to make it easier to move programs written for other versions of UNIX to Linux. But for the Ada programmer, you have to choose the one that's easiest to use in your program.

13.5.1 Kernel Calls


Kernel calls (sometimes called system calls or syscalls) are basic operations that are implemented directly in the kernel. There are C libraries which supply some thin wrappers on the calls which do some of the setup and cleanup for your. Most kernel calls are in described in the C header file unistd.h. The appendices contain a list of the Linux kernel calls.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (7 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

The kernel calls are documented in the online manual pages, but these are sometimes out of date due to the ever-changing nature of Linux.

13.5.2 Devices
The /dev directory defines device files. These files let you work with devices connected to your computer by using standard file operations. Devices can include hard drives, sound cards and the system console (the text display). Devices are recognized by their names: q /dev/hd devices: IDE hard drives, CD-ROMs, etc. q /dev/sd devices: SCSI hard drives, CD-ROMs, etc. q /dev/fd devices: floppy drives q /dev/console device: the text display q /dev/tty devices: the pseudo terminals. /dev/tty is an alias for the current tty terminal or ttyS serial port q /dev/ttyS devices: the serial ports q /dev/lp devices: the parallel ports (lp stands for line printer) In addition, most distributions define the following links: q dev/cdrom: an alias for the main CD-ROM device q /dev/modem: an alias for the the port/device the modem is connected to q dev/mouse: an alias for the port/device the mouse is connected to q /dev/fd0: an alias for the first floppy drive There are more device files than there are devices on a computer. For example, there may be 32 serial port device files defined, but that doesn't mean that there are actually 32 serial port on the computer. You will have to open the device and check for an error if it does not exist. For example, opening /dev/lp1 and writing a file to it writes the file as raw data to the first parallel port printer. Information on how these devices work is usually found in the How-To's and other system documentation. Special functions specific to a device are programmed with the ioctl() function. For example, you'd use ioctl() on /dev/dsp to set the sound volume on your sound card. The documentation for device files are often difficult to find. Sometimes documentation is contained in the kernel documentation (the /usr/doc/kernel.. directory) or in the kernel C header files (the /usr/src/linux/include/... directories). A list of some of the ioctl operations are listed in an appendix.

13.5.3 Proc File System


The /proc directory isn't really a directory at all. That is, it's a fake directory that's not physically on the hard disk, but you can still look into it and open the files it contains. The proc file system contains system information that you can access by opening the files and reading them. Some proc files may be written to in order to change system settings. For example, there are files that give you the information on how busy the CPU is, how much free memory you have, and the environment variables for the current process. The contents of these files are described in the proc man page.

13.5.4 AudioCD: An Example Program


The following CD-ROM audio CD player illustrates kernel calls, a standard C library function, and using a device file. with Ada.Text_IO, System; use Ada.Text_IO; procedure audiocd is -- Sample program for playing audio CD's

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (8 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

-- DEVICES --- This section deals with device files, in particular, -- the cdrom device DevCDROM : constant string := "/dev/cdrom"; -- path to the CDROM device, usually /dev/cdrom type ioctlID is type aFileID is -- Define these -- A ioctlID is new integer; new integer; as separate types for error checking. never the same as a FileID.

type byte is new integer range 0..255; for byte'size use 8; CDROMPLAYTRKIND : constant ioctlID := 16#5304#; CDROMSTOP : constant ioctlID := 16#5307#; CDROMSTART : constant ioctlID := 16#5308#; -- various CDROM ioctl functions as mentioned in the -- CDROM documentation in /usr/doc/kernel... type aDummyParam is new integer; -- define this as a separate type to make sure nothing -- important is used as a third parameter to ioctl_noparam -- a version of ioctl for functions that don't -- use a third parameter procedure ioctl_noparam( result : out integer; fid : aFileID; id : ioctlID; ignored : in out aDummyParam ); pragma import( C, ioctl_noparam, "ioctl" ); pragma import_valued_procedure( ioctl_noparam ); type cdrom_ti is record start_track, start_index : byte; end_track, end_index : byte; end record; -- from /usr/src/linux/include/linux/cdrom.h -- PLAYTRKIND ioctl function uses cdrom_ti record procedure ioctl_playtrkind( result : out integer; fid : aFileID; id : ioctlID; info : in out cdrom_ti ); pragma import( C, ioctl_playtrkind, "ioctl" ); pragma import_valued_procedure( ioctl_playtrkind ); -- KERNEL CALLS --- Calls to the Linux kernel (besides ioctl).

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (9 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

procedure open( id : out aFileID; path : string; flags : integer ); pragma import( C, open, "open"); pragma import_valued_procedure( open ); -- open is a kernel call to open a file procedure close( result : out integer; id : aFileID ); pragma import( C, close, "close"); pragma import_valued_procedure( close ); -- close is a kernel call to close a file -- C LIBRARY CALLS --- Calls to the standard Linux C libraries procedure perror( prefixstr : string ); pragma import( C, perror, "perror"); -- perror is a standard C library call to print -- the last error message from a kernel call or the -- standard C libraries on the screen cd : aFileID; playinfo : cdrom_ti; dummy : ADummyParam; ioctl_result : integer; close_result : integer; ch : character; begin Put_Line( "This program plays an audio CD in your CDROM drive" ); New_Line; -- open the /dev/cdrom file so we can control the CDROM drive -- using ioctl Put_Line( "Openning " & DevCDROM & "..." ); Open( cd, DevCDROM, 0 ); if cd < 0 then perror( "Error openning CDROM drive" ); end if; -- start the CDROM drive Put_Line( "Spinning up cdrom..." ); ioctl_noparam( ioctl_result, cd, CDROMSTART, dummy ); if ioctl_result < 0 then perror( "Error spinning up the CDROM drive" ); end if; -- display menu New_Line; Put_Line( "1 = Play, 2 = Quit" ); New_Line;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (10 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

-- Main loop. Repeat until 2 is selected. loop Put( Get( case when

"Select a function (1-2): " ); ch ); ch is '1' => playinfo.start_track := 1; -- first track playinfo.start_index := 0; -- no effect playinfo.end_track := 9; -- final track (inclusive) playinfo.end_index := 0; -- no effect ioctl_playtrkind( ioctl_result, cd, CDROMPLAYTRKIND, playinfo ); when '2' => ioctl_noparam( ioctl_result, cd, CDROMSTOP, dummy ); exit; when others => Put_Line( "Pardon?" ); end case;

if ioctl_result < 0 then perror( "Error controlling CDROM drive" ); end if; end loop; -- Close the CDROM device Close( close_result, cd ); if close_result < 0 then perror( "Error controlling CDROM drive" ); end if; end audiocd;

13.6 Standard Input/Output/Error


Linux defines three default I/O streams. Standard input (Linux file id 0) is the file form which all keyboard input normally comes to your program. Standard output (Linux file id 1) is the default where the output of your program is written. Standard error (Linux file id 2) is the file to which error messages are written. Usually, standard input is from the keyboard, and standard output and error are directed to the screen. There are two output streams so that if you redirect the results of a command to a file, such as "ls > temp.out", any errors that occur will still appear on the screen. The following program writes messages to standard output and standard error using Text_IO: with ada.text_io; use ada.text_io; procedure stderr is -- an example of writing messages to standard error begin Put_Line( "This is an example of writing error messages to stderr" ); New_Line; -- Text_IO defines a file called Standard_Error, always open, -- that you can write error messages to.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (11 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

Put_Line( Standard_Error, "This message is on standard error" ); Put_Line( "This message is on standard output" ); New_Line; -- you can use Set_Output to send all Put_Line's to Standard_Error Set_Output( Standard_Error ); Put_Line( "This is also on standard error"); Set_Output( Standard_Output ); Put_Line( "But this is on standard output"); end stderr;

This is an example of writing error messages to stderr This message is on standard error This message is on standard output This is also on standard error But this is on standard output Everything looks normal until you redirect the output of the program. This is the result when the standard output is redirected to a file called "out.txt". The error messages aren't redirected. [root@armitage trials]# stderr > out.txt This message is on standard error This is also on standard error

13.7 Linux Binary Formats


Many people do not think of binary files as having a format because they contain machine code instructions. However, binary files are more than just raw microprocessor instructions. They contain information such as the type of the binary file and a list of all DLL's needed by the program to run. Linux binary files come in two formats: ELF (Executable and Linking Format) and "a.out". They both have different characteristics and neither is better than the other. Most distributions let you install ELF or a.out compilers. The version of gnat for Linux is compiled for ELF. ELF is current Linux standard primarily because it provides better support for shared libraries. Fun Fact: "a.out" is an abbreviation for "assember output". Since the kernel has to do the loading and execution of programs, support for ELF, a.out or both must be selected when the kernel is compiled. Otherwise, the kernel will not recognize the format and will be unable to run the binary file.

13.9 Linux Libraries


A library is a set of object files that have been combined into a single file. You create a Linux library using the ar (archive), which takes ".o" object files can compiles them into or out of .a archive file. A Linux library files all start with "lib" and end with ".a". The command parameters for ar are a bit odd: check the man page for more details. The ar comamand has many options. Two useful variations are ar cr (create a new archive and add object files to it) and ar t (show a list of all object files in the archive file). See the example below for how these work. A library which is directly linked into a program, so that it is added to the executable, is called a static library. To link in a
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (12 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

static library, just include it's name with the gnatlink command (or gnatmake on simple projects). By default, gnat's own libgnat library is always static, because of concerns over multithreading. For example, if you install and compile the official JPEG library sources, a static library file is created named libjpeg.a. To link this library into your program, you'd include -ljpeg when linking. Note that you don't use the entire name of the file: gnat assumes there is a beginning "lib" and ending ".a". One use for static libraries is to create a library for others to use. As a small example, suppose you have a package p and you want to create a static library to link into a program t. You have to put the library's object file (p.o) into a static library (eg. libp.a) and change p.ali to read-only so gnat knows there is no object file included with p. Then include -lp when making or linking. armitage:/home/ken/ada/test# ls p.ads p.adb p.ali p.o t.adb armitage:/home/ken/ada/test# ar cr libp.a p.o armitage:/home/ken/ada/test# rm p.o armitage:/home/ken/ada/test# chmod -w p.ali armitage:/home/ken/ada/test# ls libp.a p.ads p.adb p.ali t.adb armitage:/home/ken/ada/test# ar t libp.a p.o armitage:/home/ken/ada/test# gnatmake t -lp (Strickly speaking, -lp should use gnatmake's linker options option, but this works.) If the library is in a place other than your current directory, you'll need to use the -L option to indicate the directory to check. A shared library ( or DLL, dynamic link library) is a library that is loaded into memory and shared between programs. It's not actually saved as part of the executable. All Linux shared libraries end in .so.a ("shared object archive??"). They are loaded when a program is executed. [UNTESTED!] To create a shared library, compile the source code with the -fPIC (position independent code) option and link using -shared. You also need to include -W1,-soname,nameofobject -- is this necessary under gnat if you use gnatlink? I think it probably is. [see Linux Application programming, pg 72]

if you forget the fPIC switch, your shared library will still load, but you won't be able to share the code between applications that use the library.

-fpic will also work on Intel processors because there is no maximum imposed for the global offset table, but it may not work on other processors: the fPIC switch is the preferred method. The shared libraries are usually stored in standard Linux directories, like /lib or /usr/lib. Once you copy a shared library into one of these directories, you have to run ldconfig to register the new shared library, otherwise Linux will not load it.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (13 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

To load a shared library from the current directory instead of the standard Linux directories, use -L. (where period is the current directory). Shared libraries have the advantage of making executable's smaller, but they are slower to load and execute and use up more memory than static libraries. The also have the advantage of being able to be ugraded separately from your program, provided you don't change the format of any of the subprograms. Too many shared libraries mean that you have small files scattered throughout the lib directories, making your program harder to maintain. Generally speaking, only subprograms that will be shared between programs should be shared libraries, and you should combine small, related libraries into one shared library. For example, all the standard C libraries are compiled into one shared library on Linux: libc.so.a. [from usenet] makedll.bat gcc -c beep.adb gnatbind -n beep.ali gnatlink beep.ali -o beep.jnk -mdll -Wl,--base-file,beep.base dlltool --dllname beep.dll --def beep.def --base-file beep.base --output-exp beep.exp --output-lib libbeep.a gnatbind -n beep.ali gnatlink beep.ali -o beep.jnk beep.exp -mdll -Wl,--base-file,beep.base dlltool --dllname beep.dll --def beep.def --base-file beep.base --output-exp beep.exp --output-lib libbeep.a gnatbind -n beep.ali gnatlink beep.ali beep.exp -o beep.dll -mdll This is a def file I am using. beep.def EXPORTS DllGetClassObject=DllGetClassObject@12 @2 DllCanUnloadNow=DllCanUnloadNow@0@3 DllRegisterServer=DllRegisterServer@0@4 DllUnregisterServer=DllUnregisterServer@0@5

NOTE: Since the exported functions or STDCALL, I need to provide the number of bytes used for parameters. If you were using standard pragma C stuff it would be: MYFunction@XXXX where XXXX is what ordinal in the DLL - BTW you can leave this out all together if you don't need it and just put the name of the function on the line. [end] Gnat has an option called -static which will link all shared libraries into your executable as if they were static libraries. This makes your executable completely self-contained, but may violate GPL licensing restrictions on certain libraries. Gnat comes with one shared library, libgnat.a. If you link a gnat program without the -static option, you have to copy this file into a standard library directory (e.g. /lib) and run ldconfig so that Linux will be able to find the gnat library when executing your programs. Gnat always automatically links in the library: you never have to type "-lgnat" explicitly when linking.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (14 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 13 Linux Introduction

13.10 Libc5, Libc6 and Upward Compatibility


One of the difficulties with Linux programming is that the standard libraries are seldom upwardly compatible. For example, the ncurses 3 console drawing package is completely incompatible with ncurses 4. Likewise, ncurses 4 is completely incompatible with ncurses 5. In an open source enviroment, subprogram parameters can appear and disappear with each new release. The Gnat compiler always links the standard C library into your programs. As a result, you have to be aware of the problems with Linux's standard C library, even if your Gnat program doesn't call its subprograms explicitly. Your Gnat executable always connected to the C library it was compiled against. Like most open source libraries, the standard C library isn't upwardly compatible. Inspite of the fact libc version 5 and libc version 6 (now called glibc 2.0) share the same name, many functions and names have been changed between the two versions. Multithreading under libc5 is done with the linuxthreads library, an implementation of "pthreads". LinuxThreads is based the Posix 1003.1c thread model, with a few extensions. Linuxthreads is a built in part of libc6. In the Linux world, even minor changes between libraries will create problems. There is very little upward compatibility. For example, a program may run on libc 6.0.x but won't run on libc 6.0.y because some symbol names have changed. Because of this dependency, your programs should be compiled against a specific Linux distribution. Don't assume that if a Red Hat disk and a Slackware disk are published in the same month that they are using exactly the same versions of the C library. By the same token, don't assume you can simply include libc 6.0.y with your program and update the user's version of libc by installing yours overtop. This can cause many programs to crash if they can't find the particular version of libc that they need. The same is true of the gnat library, libgnat.a. ACT does not guarantee that a program compiled for gnat 3.11's gnat library will run with gnat 3.12's gnat library. In fact, it probably won't.

13.11 Linux Basics


[To be filled in -- KB] <--Last Chapter Table of Contents Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/13.html (15 of 15) [7/20/2001 11:35:52 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

14 Linux Programming
<--Last Chapter Table of Contents Next Chapter-->

Fun Fact:The original Apple Macintosh operating system was written in Pascal, the ancestor language of Ada.

14.1 Gnat OS Library


Ada create_file delete_file etc. Description Create a Linux file Delete a Linux file C Equivalent creat unlink

The gnat OS library, gnat.os_lib, provides common UNIX operations independent of what flavour of UNIX gnat is running on. It provides an extensive set of file utilities as well as the ability to run blocked and non-blocked child processes.The price for this low-level OS support is the need to use a lot of addresses, 'access and C strings.

there is also a thin binding available for basic C stream functions, described below. with text_io, gnat.os_lib; use text_io, gnat.os_lib; procedure ostest is fd : File_Descriptor; FilePath : constant string := "testfile.xxx" & ASCII.NUL; -- for write test FirstLine : constant string := "This is the first line in the file"; AmountWritten : integer; -- for time stamp test ts : OS_Time; Year : Year_Type; Month : Month_Type;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (1 of 15) [7/20/2001 11:36:18 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Day : Day_Type; Hour : Hour_Type; Minute : Minute_Type; Second : Second_Type; -- for location test sp : String_Access; -- for delete test WasDeleted : boolean; -- for spawn test Arguments : Argument_List( 1..1 ); Ls : constant string := "/bin/ls"; WasSpawned: boolean; RootDir : aliased string := "/"; begin Put_Line( "This is an example of the Gnat's OS library:" ); New_Line; Put_Line( "Creating a new file..." ); fd := create_file( FilePath'address, Binary ); if fd = invalid_fd then Put_Line( "Unable to create " & FilePath ); else Put_Line( "Created " & FilePath ); end if; New_Line; Put_Line( "Getting the timestamp on the file..." ); ts := File_Time_Stamp( fd ); GM_Split( ts, Year, Month, Day, Hour, Minute, Second ); Put_Line( "The time stamp is" & Year'img & "/" & Month'img & "/" & Day'img & Hour'img & ":" & Minute'img & ":" & Second'img ); New_Line; Put_Line( "Writing to the file..." ); Put_Line( FirstLine ); AmountWritten := Write( fd, FirstLine'Address, FirstLine'Length ); Put_Line( "Wrote" & AmountWritten'img & " bytes" ); Put_Line( "The file length is" & File_Length( fd )'img ); New_Line; Close( fd );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (2 of 15) [7/20/2001 11:36:18 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Put_Line( "Closed the file" ); New_Line; Put_Line( "Locating the file we just made..." ); sp := Locate_Regular_File( File_Name => FilePath, Path => GetEnv( "PATH" ).all ); Put_Line( "The file is '" & sp.all & "'" ); New_Line; Put_Line( "Deleting the file..." ); Delete_File( FilePath'address, WasDeleted ); if WasDeleted then Put_Line( "File was deleted" ); else Put_Line( "File was not deleted" ); end if; New_Line; Put_Line( "Running ls / ..." ); New_Line; Arguments(1) := RootDir'unchecked_access; -- unchecked to avoid unless accessibility warning Spawn( Ls, Arguments, WasSpawned ); if WasSpawned then New_Line; Put_Line( "End of ls output - Spawned worked" ); else Put_Line( "Spawn failed" ); end if; New_Line;

end ostest;

This is an example of the Gnat's OS library: Creating a new file... Created testfile.xxx Getting the timestamp on the file... The time stamp is 1998/ 12/ 18 23: 42: 24 Writing to the file...

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (3 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

This is the first line in the file Wrote 34 bytes The file length is 34 Closed the file Locating the file we just made... The file is './testfile.xxx' Deleting the file... File was deleted Running ls / ... STARTUP System.map System.old bin boot cdrom dev dosc etc fd home lib lost+found mnt opt proc root sbin tmp usr var vmlinuz vmlinuz.old End of ls output - Spawned worked

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (4 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

14.2 Installing Binding Packages


A variety of Ada packages exist to allow you to call C libraries from Ada. These packages are called bindings. For example, there are Ada bindings to Motif, TCL, WWW CGI and Posix (that is, the kernel). A thin binding gives you direct access to library calls. A thick binding provides indirect access, where the package does some setup before invoking the library calls. The gnat.os_lib library is an example of a thick binding to basic Linux file operations. When installing binding libraries:
q

q q q

Make sure that the filename endings are the right ones for gnat. Different compilers use different conventions. Compile the binding package(s). Install the library the binding is for (if necessary) Include -lname on the link line, where name is the library. Remember that the order of the -l's is important.

14.3 Catching Linux Signals


A programs has to be able to respond to unexpected events. What do you do when somebody types control-C? How do you gracefully stop the program when somebody kills it with the kill command? These unexpected events are referred to a signals in Linux, and Gnat provides libraries for you to "catch" these signals and respond to them gracefully. The standard Ada 95 package Ada.Interrupts and its children handle unexpected operating system events. Under Linux, these packages provide support for signal handling.

A complete list of Linux signals is listed in an appendix. The package Ada.Interrupt.Names defines the names of these signals for you. Signal Handlers are protected type procedures with no parameters. The body of the procedure performs whatever actions you want to do when you receive a signal. For example, to catch the SIGTERM signal, the signal that indicates that the program has been killed with the "kill" shell command, you can write a handler like this: protectedbodySignalHandler is procedure HandleSIGTERM is -- normal kill signal handler begin Put_Line( "Ouch! I've been killed!" ); -- perform any other cleanup here end HandleSIGTERM; end SignalHandler;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (5 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

To put the handler in place permanently, use pragma Attach_Handler. pragma Attach_Handler( HandleSIGTERM, SIGTERM ); Now whenever your program receives a SIGTERM signal, your handler will automatically run. If you don't want to install a permanent handler, a handler can be installed or changed while the program is running. To indicate that a procedure is an interrupt handler that can be installed at a later time, use pragma Interrupt_Handler. pragma Interrupt_Handler( HandleSIGTERM ); Gnat automatically handles one signal for you: SIGINT, the interrupt signal. This is the signal that is sent to your program when control-c is pressed. If you want to handle control-c presses yourself, you have to use pragma Unreserve_All_Interrupts. Despite it's long name, this pragma simply tells Gnat to ignore SIGINT's. Certain signals can never be caught. SIGUNUSED, the unused signal, can't be caught for obvious reasons. Some signals are used by the multithreading software and are not available for use in applications. In particular, if you are running native Linux threads, you can't catch SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGTRAP, SIGABRT, SIGINT, SIGVTALRM, SIGUNUSED, SIGSTOP, or SIGKILL. On 2.0 kernels or older, native Linux threads use SIGUSR1 and SIGSUR2 and are not available. If you're running FSU threads, then SIGALRM is also not available. Ada.Interrupts also contains several subprograms for signal handling. Is_Reserved is true if a particular signal is uncatchable. q Is_Attached is true if a particular signal has a handler attached. q Current_Handler returns a pointer to the handler for a particular interrupt. q Exchange_Handler will put a new handler in place and return a pointer to the previous handler. q Detach_Handler will uninstall a handler The following package sets up three signal handlers, which display a message at set the EMERGENCY_SHUTDOWN variable to true. The demo program demonstrates some of the Ada.Interrupts subprograms and enters into a slow loop. The main program was killed with the "kill SIGPWR" shell command, simulating a power failure signal.
q

with Ada.Interrupts.Names; use Ada.Interrupts, Ada.Interrupts.Names; package SigHand is -- Package to handle basic Linux signals pragma Unreserve_All_Interrupts; -- Gnat will no longer handle SIGINT for us EMERGENCY_SHUTDOWN : boolean := false; -- set in the event of a signal to shut down the program -- SignalHandler will handle the signals independently -- from the main program using multithreading protected SignalHandler is

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (6 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

procedure HandleControlC; pragma Attach_Handler( HandleControlC, SIGINT ); -- SIGINT (Control-C) signals will be intercepted by -- HandleControlC procedure HandleKill; pragma Attach_Handler( HandleKill, SIGTERM ); -- SIGTERM (kill command) signals will be intercepted by -- HandleKill procedure HandlePowerFailure; pragma Attach_Handler( HandlePowerFailure, SIGPWR ); -- SIGPWR (power failure signal) intercepted by -- HandlePowerFailure end SignalHandler; end SigHand; with Ada.Text_IO; use Ada.Text_IO; package body SigHand is -- Package to handle basic Linux signals protected body SignalHandler is -- This protected type contains all our signal handlers procedure HandleControlC is -- Control-C signal handler begin if EMERGENCY_SHUTDOWN then Put_Line( "HandleControlC: The program is already shutting down" ); else Put_Line( "HandleControlC: Control-C was pressed, shutting down" ); end if; EMERGENCY_SHUTDOWN := true; end HandleControlC; procedure HandleKill is -- normal kill signal handler begin if EMERGENCY_SHUTDOWN then Put_Line( "HandleKill: The program is already shutting down" ); else

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (7 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Put_Line( "HandleKill: Program is shutting down" ); end if; EMERGENCY_SHUTDOWN := TRUE; end HandleKill; procedure HandlePowerFailure is -- power failure handler begin if EMERGENCY_SHUTDOWN then Put_Line( "HandlePowerFailure: The program is already shutting down" ); else Put_Line( "HandlePowerFailure: Program is shutting down" ); end if; EMERGENCY_SHUTDOWN := TRUE; end HandlePowerFailure; end SignalHandler; end SigHand; with Ada.Text_IO, SigHand, Ada.Interrupts.Names; use Ada.Text_IO, SigHand, Ada.Interrupts, Ada.Interrupts.Names; procedure SigDemo is Handler : Parameterless_Handler; Counter : integer := 2; begin Put_Line( "This program demonstrates signal handling." ); Put_Line( "To stop this program, type Control-C or " ); Put_Line( "kill it with the shell kill command." ); New_Line; -- Is_Reserved example if Is_Reserved( SIGTERM ) then Put_Line( "The SIGTERM handler is reserved" ); else Put_Line( "The SIGTERM handler isn't reserved" ); end if; -- Is_Reserved example if Is_Attached( SIGINT ) then Put_Line( "There is a SIGINT handler installed" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (8 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

else Put_Line( "There is no SIGINT handler installed" ); end if; -- Current_Handler example Put_Line( "Testing SIGTERM handler..." ); Handler := Current_Handler( SIGTERM ); -- Current_Handler gives a callback to the handler Handler.all; -- run the handler callback if EMERGENCY_SHUTDOWN then Put_Line( "Handler works" ); else Put_Line( "Handler doesn't work" ); end if; -- test complete: reset emergency shutdown flag EMERGENCY_SHUTDOWN := false; -- a long loop New_Line; Put_Line( "The number is " & Counter'img ); loop exit when EMERGENCY_SHUTDOWN; Counter := Counter * 2; Put_Line( "Doubling, the number is " & Counter'img ); delay 1.0; end loop; Put_Line( "The program has shut down" ); end SigDemo; This program demonstrates signal handling. To stop this program, type Control-C or kill it with the shell kill command. The SIGTERM handler isn't reserved There is a SIGINT handler installed Testing SIGTERM handler... HandleKill: Program is shutting down Handler works The number is 2 Doubling, the number is 4

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (9 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Doubling, the number is 8 Doubling, the number is 16 Doubling, the number is 32 Doubling, the number is 64 Doubling, the number is 128 Doubling, the number is 256 Doubling, the number is 512 HandlePowerFailure: Program is shutting down The program has shut down

14.4 Working with the Command Line


Ada Function Command_Name return string; Function ArgumentCount return natural; Function Argument( n : natural ) return string; Procedure Set_Exit_Status( e : Exit_Status ); Description The name of this command (path?). The number of arguments. The n'th argument. The exit status to return. C Equivalent argv[0] argn argv[n] exit( e )

Ada interacts with the outside world through the standard Ada package Ada.Command_Line. Suppose you have an Ada program called "myprog" and a user types in the following command: "myprog -v sally.com".

"myprog" is the name of the command. q "-v" and "sally.com" are arguments to the command. Command_Name returns the name of the command. If the program was run from a shell, it returns the name as typed in by the user. In the above example, Command_Name returns "myprog". ArgumentCount returns the number of arguments, not including the name of the program. The shell determines how arguments are grouped together, but typically each argument is separated by a space. In the above example, there are two arguments, "-v" and "sally".
q

Argument returns an argument. In the above example, argument( 1 ) returns "-v". Set_Exit_Status gives Ada the error code you want to return when the program is finished running. Ada defines two Exit_Status values, Success and Failure . Since Exit_Status is just an integer, you can return other values. Zero indicates that the program ran without error, non-zero values indicate an error. The predefined values of Success and Failure are 0 and 1. Properly flagging errors is important for shell programming. For example, you have to return the proper exit status for "myprog && echo 'all is well'" to work properly. You can retrieve the exit status of the last command using "$?". For example: #!/bin/bash
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (10 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

myprog -v sally if [ $? -eq 0 ] ; then echo "There were no errors" else echo "The program returned error code = $?" fi See the example program in the next section for an example using this package.

14.5 Linux Environment Variables


Ada.Command_Line.Environment is a gnat package for accessing Linux environment variables.

Ada Function Environment_Count return natural; Function Environment_Value(n) return string;

Description The number of environment variables The name value of the nth variable

C Equivalent ? getenv(n)

The Environment_Count function returns the number of environment variables. The Environment_Value function returns the name and value of a variable, separated by an equals sign. For example, Environment_Value( 5 ) returns the name and value of the fifth environment variable. The following program is an example of Ada.Command_Line and Ada.Command_Line.Environment. The results assume that you started the program by typing "cmdtest -v". with text_io, Ada.Command_Line.Environment; use text_io, Ada.Command_Line, Ada.Command_Line.Environment; procedure cmdtest is begin Put_Line( "This is an example of Ada.Command_Line" ); New_Line; Put_Line( "The command to invoke this example was '" & Command_Name & "'" ); Put_Line( "There is/are" & Argument_Count'img & " command line arguments" ); if Argument_Count > 0 then Put_Line( "The first argument is '" & Argument(1) & "'" ); end if; New_Line;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (11 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Put_Line( "There is/are" & Environment_Count'img & " environment variables." ); Put_Line( "The first environment variable is '" & Environment_Value( 1 ) & "'" ); Set_Exit_Status( Success ); end cmdtest;

This is an example of Ada.Command_Line The command to invoke this example was 'cmdtest' There is/are 1 command line arguments The first argument is '-v' There is/are 24 environment variables. The first environment variable is 'LESSOPEN=|lesspipe.sh %s' Environment variables can be removed using the Gnat Ada.Command_Line.Remove package.

14.6 GNAT.Directory_Operations Package


This Gnat package allows you to create and explore directories. Although the package is portable to all operating systems, the format of the directory depends on the particular operating system. For this package, a directory name string (Dir_Name_Str) is a pathname in the standard Linux format. The trailing '/' character is optional when using this package, but directory names returned will always have a trailing '/'. "." is the current directory. ".." is the parent directory of the current directory. Get_Current_Dir returns the name of the current directory. Change_Dir changes the current directory to a new location. with ada.text_io, gnat.directory_operations; use ada.text_io, gnat.directory_operations; procedure gdir is dir : string(1..80); len : natural; begin Put( "The current working directory is " ); Put_Line( Get_Current_Dir ); Change_Dir( ".." ); Put( "Moving up, the current working directory is " ); Put_Line( Get_Current_Dir );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (12 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Change_Dir( "work" ); Get_Current_Dir( dir, len ); Put( "Moving down to 'work', the current working directory is " ); Put_Line( dir(1..len) ); end dir;

The current working directory is /home/kburtch/work/ Moving up, the current working directory is /home/kburtch/ Moving down to 'work', the current working directory is /home/kburtch/work/ For viewing directories, the package opens directories like a Text_IO file. Dir_Type is a limited private directory type corresponds to a file_type in Text_IO. Directories can only be read. q Open - Open a directory for reading q Close - Close a directory q Read - Read a directory entry. When a null string is returned, there are no more entries q Is_Open - True if the directory is open q Read_Is_Thread_Safe - True if the directory can be read by separate tasks (threads). That is, if there is a readdir_r kernel call Any error will raise a DIRECTORY_ERROR exception with ada.text_io, gnat.directory_operations; use ada.text_io, gnat.directory_operations; procedure gdir2 is dir : Dir_Type; dirname : string( 1..80 ); len : natural; begin if Read_Is_Thread_Safe then put_line( "Tasks may read the same directory" ); else put_line( "Tasks may not read the same directory" ); end if; New_Line; Open( dir, "." ); if Is_Open( dir ) then put_Line( "The directory was opened" ); else put_Line( "The directory was not opened" ); end if; loop Read( dir, dirname, len ); exit when len = 0; Put_Line( dirname( 1..len ) ); end loop;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (13 of 15) [7/20/2001 11:36:19 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Put_Line( "End of directory" ); Close( dir ); end gdir2;

Tasks may not read the same directory The directory was opened . .. gdir.ads gdir.ali gdir.adb gdir.o gdir gdir2.adb gdir2.ali gdir2.o gdir2 End of directory The directories "." and ".." are always returned. New directories can be made with Make_Dir. Make_Dir( "logs" ); -- make a new "logs" directory If you need more features that these, the Linux kernel calls for directories are described in 16.9. The section includes a command to remove directories which cannot be done with Gnat.Directory_Operations.

14.7 GNAT.Lock_Files Package


This Gnat package contains subprograms for obtaining exclusive access to a particular file or directory. When a file is locked, only your program may use the file until the file is unlocked. Locks are implemented using lock files. When a file is locked, Gnat checks for the presence of a separate file. If the file exists, the file has been locked by another application. If a file cannot be locked, a LOCK_ERROR is raised. The programmer supplies the lock file name. Linux programs usually place lock files in the /var/lock/ directory. The Lock_File procedure locks a particular file. By default, if the procedure will continue trying to relock the file every second forever (actually, for Natural'Last seconds, a very long time). The delay and the number of retries can be changed. Lock_File( "/var/lock/", "customers.txt" ); Lock_File( "/var/lock/customers.txt" );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (14 of 15) [7/20/2001 11:36:20 AM]

Big Online Book of Linux Ada Programming - 14 Linux Programming

Lock_File( "/var/lock/customers.txt", Wait => 5.0, Retries => 10 ); Files are unlocked using Unlock_File. This procedure deletes the lock file. Unlock_File( LockDir, "customers.txt" ); Unlock_File( "/var/lock/customers.txt" ); The lock file approach is a voluntary convention. Programs that honour the convention can share the file in an orderly way. A program that doesn't use the package will not be denied access. For true file locking, use the Linux kernel calls described in 16.7.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/14.html (15 of 15) [7/20/2001 11:36:20 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

15 Free Ada Bindings


<--Last Chapter Table of Contents Next Chapter-->

15.1 Using Florist, the POSIX binding


Florist (Florida Statue University/Forest) is a GPL binding of the POSIX (IEEE Standard 1003.5b-1996) standard operating system functions. These include file operations, date and time functions, and multitaskingthe same kinds of function provided by the standard C libraries and the Linux kernel. If you are writing an application that will run on several different operating systems, Florist provides a level of operating system independence. Once you install gnat and Florist on your new platform, you should be able to recompile a Florist application without having to worry about variations in system calls. Florist is designed for gnat and runs on Linux as well as Solaris, OFS1, AIX, IRIX and HP-UNIX. Florist works closely with the gnat run-time system: you must compile Florist against a particular gnat installation. If you change your gnat installation, you will need to recompile Florist.

Older versions of Florist for Gnat 3.11 work best with a version of Gnat compiled for FSU threads. Native threads require some patching to work, and not all Florist features are supported--see the Florist documentation for details. For more information on FSU threads, read the multitasking section above. Newer versions of Florist, such as the ALT RPM, works with the normal (native threads) version of Gnat. Commercial support for Florist is available form ACT. Because the Linux kernel largely adheres to the POSIX standard, many of Florist functions have the same parameters as their Linux counterparts. Florist divides the POSIX functions into a set of 73 Ada packages, all prefixed with the name "posix". The main package is called "posix.ads" and contains the definition of data types and many of the basic POSIX functions. To write Florist applications, you'll need to link in the Florist library with "-lposix" (check?) and, if necessary, use "-I" to indicate where you've installed the package specifications.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (1 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

15.2 Using Texttools


The Texttools packages are a GPL, ncurses-based library for the Linux console. Texttools contain more than 600 procedures and functions to create windows, draw scroll bars, handle the mouse and keyboard events, play sounds, and much more. The Texttools package also provides a thick binding to Linux kernel calls. You can create a wide variety of application programs using Texttools alone. This is the same package used to implement TIA. [to be rewrittenKB]

15.2.1 Installation
1. In the C_code directory, type "gcc -O -c *.c" to compile the C files. 2. The Ada files should compile when you build your project with Gnatmake. If TextTools are installed in a different directory than your project, you will need to use the gnatmake -I switch. When linking, you'll need to include the "-lm" and "-lcurses" switches as well as the object files from C_code. TextTools uses the C math library and ncurses 4.0. For example, gnatlink -lm -lncurses C_code/*.o ...

15.2.2 Introduction
Although there are over 600 procedures and functions in TextTools, to open window is fairly uncomplicated. Everything in TextTools is drawn in a window. Everything in a window is a control (sometimes called a "widget"). To display a window, you must create a window, fill in the window with controls to display, and run the window manager's DoDialog command. The following program opens a simple window. ------------------------------------------------------------------with common, os, userio, controls, windows; use common, os, userio, controls, windows; procedure ttdemo is -- Define Window Controls OKButton : aliased ASimpleButton; MessageLine : aliased AStaticLine; -- The Dialog Record

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (2 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

DT : ADialogTaskRecord; begin -- Start TextTools StartupCommon( "demo", "demo" ); StartupOS; StartupUserIO; StartupControls; StartupWindows; -- Create a new window. The window will not appear until the -- DoDialog procedure is used. OpenWindow( To255( "Demo Window" ), -- title at top of window 0, 0, 78, 23, -- the coordinates of the window Style => normal, -- type of window, usually "normal" HasInfoBar => true ); -- true if control information is -- displayed at the bottom of the -- window -- Setup the controls in the window -- OK Button located near bottom of window Init( OKButton, 36, 20, 44, 20, -- coordinates in window 'o' ); -- hot key for OK button SetText( OKButton, "OK" ); -- button will have "OK" SetInfo( OKButton, To255( "Select me to quit" ) ); AddControl( SimpleButton, OKButton'unchecked_access, IsGlobal => false ); -- Message at top of window in bright red Init( MessageLine, 1, 1, 78, 1 ); SetText( MessageLine, "Welcome to TextTools" ); SetStyle( MessageLine, Bold ); SetColour( MessageLine, Red ); AddControl( SimpleButton, MessageLine'unchecked_access, IsGlobal => false ); -- Display the window and handle any input events. When dialog
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (3 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

-- is finished, return control which completed the dialog. loop DoDialog( DT ); exit when DT.Control = 1; -- first control is the OK button end loop; -- close the window CloseWindow; -- Shutdown TextTools ShutdownWindows; ShutdownControls; ShutdownUserIO; ShutdownOS; ShutdownCommon; end ttdemo; ------------------------------------------------------------------Package Overview TextTools is broken into 5 main packages, based on what they do. Common - this package contains all the basic data types used by TextTools, plus subprograms that work with those types. In particular, two important types are defined: Str255 - most TextTools subprograms use this bounded, 255 character string type instead of the standard Ada fixed strings. The function To255 converts an Ada string to a Str255. ToString converts in the other direction. q Str255List - some list controls display a block of text. These controls use the Str255List.List type, a linked list of Str255 strings. The subprograms for this type are defined the generic package gen_list. Most TextTools calls do not return errors. There are some exceptions, such in the OS package. Error numbers are returned in the LastError variable. LastError is 0 if there is no error.
q

OS - this package contains subprograms for working with the Linux operating system: that is, for reading the current time, deleting files, and the like. Texttools pathnames are defined in this package. A path is a Str255 string. The OS package can define path prefixes, beginning with a "$". For example, "$HOME" is predefined as the user's home directory. To delete a file called "temp.txt" from the user's home directory, you can use the OS erase command: Erase( To255( "$HOME/temp.txt" ) );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (4 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

$SYS is another predefined prefix. This refers to a directory in the user's home directory named with the "short name" you specify in the StartupCommon procedure. Sounds, keyboard macros and the session_log file are located here. UserIO - this package contains all the input/output routines for TextTools: it handles mouse clicks, draws text, and so forth. Normally, only people writing controls will need access to this package. However, the pen colours, beep sounds and text styles, are also defined here. Controls - this package contains all the window controls and related subprograms. Currently defined controls are: Thermometer q ScrollBar q StaticLine q EditLine (and family) q CheckBox q RadioButton q WindowButton q Rectangle q Line q HorizontalSep q VerticalSep q StaticList q CheckList q RadioList q EditList q SourceCodeList (used by TIA) Windows - this is the window manager. It creates and draws windows, and DoDialog procedure lets a user interact with the window. It also handles the "Accessories" window that appears when ESC is pressed.
q

Each package is started with a "Startup" procedure, and shutdown with a "Shutdown" procedure. The only procedure to take parameters is StartupCommon: you need to specify a program name and a short name to use for temporary files.

15.2.4 Window Overview


The Window Manager draws all the windows on the screen. For simple programs, you will need to use only four Window Manager procedures. OpenWindow - this procedure creates a new window. Each window has a title, coordinates on the screen, a "style", and an optional info bar.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (5 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

AddControl - adds a control to the current window. If IsGlobal is false, the coordinates you specified in the control's Init call will be treated as relative to the top-left corner of the window, as opposed to the top left corner of the screen. CloseWindow - closes the last window you created DoDialog - this procedure displays the window and handles all interaction between the user and the window. It has one parameter, ADialogTaskRecord, which lets you set up callbacks (if necessary) and returns the number of the control which terminated the dialog.

5.2.5 Other Useful Window Manager Subprograms


Windows can be saved using the SaveWindow command, and loaded again using LoadWindow. When a window is loaded with LoadWindow, you don't need to open the window or set up the controls--the Window Manager does this automatically for you. ShellOut will close the windows, run a shell command, and reopen the windows. RefreshDesktop will redraw all the windows on the screen. SetWindowTimeout will set a default control to be selected if there is no response after a certain amount of time.

15.2.6 Alerts
Alerts are small windows that show a short message. NoteAlert - displays a message with an "OK" button. The status sound is played, if installed. CautionAlert - displays a message with an "OK" button. The text is drawn to emphasize the message. The warning sound is played, if installed. StopAlert - displays a message with an "OK" button. The text is drawn to emphasize the message. The warning sound is played, if installed. YesAlert - display a message with "yes" (default) and "no" buttons. Plays an optional sound. NoAlert - display a message with "yes" and "no" (default) buttons. Plays an optional sound. CancelAlert - display a message with cancel button and a customized button (default). Plays an optional sound. YesCancelAlert - display a message with "yes", "no", and "cancel" buttons and returns the number of the button selected. Plays an optional sound. Example: NoteAlert( "The database has been updated" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (6 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

15.2.7 Other Predefined Windows


SelectOpenFile - displays a dialog for opening files. It has parameter, ASelectOpenFileRec. You have to fill in certain before displaying this window. SelectSaveFile - displays a dialog for saving files. It has one parameter, ASelectSaveFileRec. You have to fill in certain details before displaying this window. ShowListInfo - displays a Str255List list in a window EditListInfo - displays a Str255List list in a window and let's the user edit the list. Example: sof : ASelectOpenFileRec; ... sof.prompt := To255( "Select a file to open" ); sof.direct := false; -- can't select directories SelectOpenFile( sof ); if sof.replied then FilePath := sof.path & "/" & sof.fname; else -- user cancelled end if; Control Overview Every control must be initialized with the Init procedure. Init positions the control in the window and assigns a "hot key", a short cut key for moving to the control. You can turn a control off (make it unselectable) using SetStatus. Setting the control's status to Standby will make it selectable. Some controls are automatically turned off, such as the static line control. The following controls can be used in a TextTools window: Thermometer This is a thermometer bar graph. It shows the percentage between the maximum value and the current value, and is filled based on the percentage ScrollBar This is a scroll bar. A thumb is drawn at the relative location of the thumb value to the maximum value of the bar. The bar will be horizontal or vertical depending on the shape specified in the Init procedure. StaticLine

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (7 of 13) [7/20/2001 11:36:37 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

This is an unchanging line of text. EditLine (and family) This is an editable line of text. AdvanceMode - if set, the cursor will move to the next control when the edit field is full. This is useful in business applications where fixed-length product numbers are typed in. BlindMode - if set, hides the characters typed. This is useful for typing in passwords. SimpleButton This is a button that, when selected, terminates the dialog. Instant - if set, the button acts like a menu item. Pressing the hot key will immediately select the button and terminate the dialog. Otherwise, pressing the hot key only moves the cursor to the button. CheckBox A check box is an option which may be turned on or off. RadioButton A radio button is one of a set of options which may be turned on or off. Every radio button has a family number defined in the Init procedure. When a radio button is turned on, all other buttons in the family are turned off. WindowButton Loads a window from disk and displays it. The window must have been saved with the Window Manager's SaveWindow procedure. Rectangle A box which can be drawn around controls. Line A line--what else would it be--drawn between two corners of the enclosing rectangle defined by the Init procedure. HorizontalSep A horizontal line, often used to separate controls into groups. VerticalSep A vertical line, often used to separate controls into groups. StaticList A scrollable box of unchanging text.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (8 of 13) [7/20/2001 11:36:38 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

CheckList A scrollable box of check boxes. RadioList A scrollable box of radio buttons. EditList A scrollable box of editable text. SourceCodeList (used by PegaSoft's TIA) A scrollable box containing source code. OS Package This package contains various calls for working with the operating system. All calls support path prefixes as described above. Here are some of the subprograms:
q q q q q q q q q q q q

UNIX - run a UNIX shell command. The function variations return the result of the command. RunIt - runs a UNIX program. ValidateFilename - check for a syntactically correct filename. NotEmpty - true if a file is not empty IsDirectory - true if file is a directory IsFile - true if file is a "regular" file MakeTempFileName - creates a random file name for a temporary file Erase - deletes a file LoadList - load a Str255List list from a file SaveList - save a Str255List list to a file MyID - return the PID for your program SessionLog - write to the session log. If a $SYS directory exists, SessionLog creates a file called "session_log" in that directory. All SessionLog calls write to this file.

15.2.10 UserIO Overview


The UserIO package handles all the input and output for TextTools. Unless you are writing a game or new controls, you'll probably won't need to use UserIO at all. However, there are a few useful subprograms to be aware of:

Beep - play a .wav file. Requires Warren Gay's wavplay program. These files must be saved in the $SYS directory, with the name of the beep sound in upper case.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (9 of 13) [7/20/2001 11:36:38 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

Keypress - get a keypress q DrawErr - draw an error message. DrawErr draws the text on the left-side screen in white. Use only for emergencies. q GetDisplayInfo - retrieve information about the current screen, such as whether it supports colour, and it's dimensions. Use this information to resize your windows for different screens. Example:
q

Beep( Startup ); -- play startup sound Keyboard Macros UserIO will load a set of keyboard macros at startup. These must be saved in the $SYS directory, in a file called macro_file. The first letter of each line is the key for the macro, and the rest of the line is the expanded macro. For example, if a line in macro_file contained pPegaSoft then typing control-A followed by "p" would put the word "PegaSoft" in the input queue as if the person had typed "PegaSoft".

15.2.11 Appearance and Keys


Most of the objects on the screen should be easily understood, the majority designed after their GUI counterparts. Here is a list:

< > Text - A button. Press Return to activate. Type the hilighted letter to go immediately to this button. q | > Text - An menu button. Enter Return to activate. Type the hilighted letter to immediately activate. q ( ) Text - A radio button. Press Return to select this item and deselect the previous item in the group. q [ ] Text - A check box. Press Return to switch on or off. q -----#------- - A scroll bar. q -----50%----- - A thermometer graph. Buttons with hyphens in them are not selectable.
q

Basic Keyboard Shortcuts: Movement Keys Up/Down Arrow - move up or down to the next menu item * in lists - move up or down one line in the list
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (10 of 13) [7/20/2001 11:36:38 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

* in scroll bars - adjust up or down by 10% Left/Right Arrows - move left or right to the next menu item * in lists - move up or down one line in the list * in scroll bars - adjust up or down by 1 Page Up (or Control-P) - move up one page in a list * in scroll bars - same as up and down arrows Page Down (or Control-N) - move down one page in a list * in scroll bars - same as up and down arrows Home Key (or Control-Y) - move to the top of a list * in scroll bars - go to the top End Key (or Control-E) - move to the bottom of a list * in scroll bars - go to the bottom Tab Key - move to the next item in the window Control-T - move to the previous item in the window Return Key (or Spacebar) - activate a button When inside of a list box, the movement keys move you around the list. If you are on the Linux console, pressing alt and the hilighted letter will always jump to the appropriate object, even if you're inside a list box or the notepad. Editing Keys Control-6 - mark text * only works in edit lists Control-X - clear text * in lists, clear the current line (or lines, if control-6 used) Control-B - copy text * in lists, copy the current line (or lines, if control-6 used) Control-V - paste text * in notepad, paste the last line copied

Misc. Keys ESC Key (or F1) - bring up the accessories menu Control-L - redraw the screen

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (11 of 13) [7/20/2001 11:36:38 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

Control-A (or F2) - execute a keyboard macro

15.3 Using NCurses


Ncurses is a free toolset for drawing on text screens, such as the Linux console. [not finished]

15.4 Using GTK+ Widgets


GTK+, the Gimp ToolKit, is a widget set (or sometimes called a control set). These are the same widgets used by the Gimp drawing program. Unlike Motif and QT widgets, GTK+ uses an LGPL license, making it very popular for new Linux software, include the GNOME desktop project. GTK+ also contains 2D drawing operations. GTK+ is available for download from the GTK web site at http://www.gtk.org. GtkAda can be downloaded from the ALT web site, or from its home page at http://ada.eu.org/gtkada/. GtkAda is an Ada95 binding of Gtk+ version 1.2.0. It allows you to develop graphical applications in Ada95 using Gtk+. General GTK+ documentation and a tutorial written with examples in C are available from the GTK web site. [not finished]

15.5 Using Motif Widgets


Motif (pronounced "Moe-Teef") is an X Windows widget standard created by the Open Software Foundation (OSF), a group of several UNIX companies. Motif is built for the stanadard X Windows library Xt. With Motif, you can create windows and dialog boxes menus, buttons, scrolling lists and the like. Motif is a registered trademark of OSF. LessTif (pronounced "Less-Teef") is an open source compatible version of Motif 1.2 with some extensions, licenced under LGPL. It is available for download from the LessTif web site at http://www.lesstif.org. This site also includes documentation on compiling and installing LessTif. There are no Ada bindings for LessTif, but there are Ada bindings for Motif which should work equally well for Lesstif. The bindings are available from the Home for Brave Ada Programmers, http://www.adahome.com. Motif (and LessTif) have not proven to be very popular. Motif programs tend to be very large, with widgets layouts that are difficult to design, and have a heavy reliance on Motif's cumbersome resource files. Even small Motif programs typically require contain several hundred lines of source code to set up

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (12 of 13) [7/20/2001 11:36:38 AM]

Big Online Book of Linux Ada Programming - 15 Free Ada Bindings

their initial window. Toolsets such as Qt (used in KDE) and GTK+ (used in GNOME) have larger followings, and Motif support is primarily for older applications being ported to Linux. However, Motif, as a standard, is continuing to evolve.

15.6 Using the TCL Binding


TASH (Tcl Ada SHell) is a binding to TCL/TK. It includes both a thin binding to the basic TCL/TK functions (as found in the C header file tcl.h), as well as versions of the functions made for easier calling from Ada. The binding supports TCL 8.0 http://tash.calspan.com/ TASH also comes with its own TCL shell interpreter which functions like tclsh but is written in Ada.

15.7 Using the OpenGL/Mesa Binding


Mesa is an OpenGL library for 3D graphics. It can create 3D objects, transform them, and supports accelerated drivers. You can use Mesa under GTK+ by using a GTK+ "GL Area" widget and draw graphics inside using Mesa.

15.8 Engine_3D
Engine_3D is a real-time 3D drawing package written entirely in Ada. The Linux port is by Duncan Sands. The Engine_3D package is at http://members.nbci.com/gdemont/e3d.htm. <--Last Chapter Table of Contents Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/15.html (13 of 13) [7/20/2001 11:36:38 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

16 Advanced Linux Programming


<--Last Chapter Table of Contents Next Chapter-->

16.1 Writing Your Own Bindings


Ada Package pragma pragma pragma pragma import export import_function import_procedure Description Import identifier from another language Export identifier to another language Like import, but extra options C Equivalent extern? extern?

Like import, but extra options Import a function that returns values as pragma import_valued_procedure parameters Like export, but extra options pragma export_function Like export, but extra options pragma export_procedure

extern?

Because gnat is tightly integrated with gcc, we can make certain assumptions that would otherwise be impossible. q the basic Ada data types are equivalent to their C counterparts: an Ada integer array is a C integer array q in parameters are the same as pass by copy parameters in C q in out parameters are the same as passing a pointer as a parameter in C q Ada string parameters ending in ASCII.NUL are the same as a C string q Ada procedures are the same as C void functions There are rare cases when these assumptions don't hold (e.g. certain cases when null pointer parameters are not allowed by Ada), but, generally speaking, these assumptions are valid under Linux. Gnat has general purpose interfacing pragmas and support for C types in the Interfaces.C package. Use these if you want maximum portability. Because of these assumptions, most C library calls are easily represented in Ada. For example, we check the man page for gettime and discover it returns the current time as a long integer. To call this from Ada, we use function gettime return long_integer; pragma Import( C, gettime ); Since there is no Ada body for the gettime function, we use pragma import to let gnat know gettime is a C function. When we link, we need to specify the C library that function is in. In the case for the GNU C library, this is unnecessary since it's automatically linked. We can now call the C function gettime as if we wrote it ourselves.In C, it's possible to call a function and discard the result by not assigning it to anything. You can call C functions from Ada this way by declaring them a procedure. For example: procedure gettime; pragma Import( C, gettime ); In this case, it's not particularly useful to call gettime and throw away the time it gives you. In general, you should avoid discarding the result because you may find it useful at some time in the future. However, there are certain C function where the result is provided only for flexibility, such as functions that return a pointer in a parameter and return the same pointer as the function result as well. These can safely be discarded by treating the function as a procedure.If we wanted to export an integer variable called TotalTimeEstimate to C, we'd use TotalTimeEstimate : integer; pragma Export( C, TotalTimeEstimate );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (1 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

A C function that returns void corresponds to an Ada procedure. When importing or exporting to C, gnat converts the variable to lower case because C is a case-sensitive language. TotalTimeEstimate would be called totaltimeestimate in a C program. You can override this by providing a specific C name to link to. For example, pragma Export( C, TotalTimeEstimate, "TotalTimeEstimate" ); Import and Export don't require the name be the same at all. However, using entirely different names in C and Ada will make your program hard to understand. If you want to import functions from libraries other than the standard C library, you will have to explicitly link them in. For example, to use the C math library, libm.a, would have to be explicitly linked using -lm. In C, functions can have parameters that change value, while in Ada this kind of function is not allowed because functions can only have "in" parameters. To get around this problem, gnat defines an import_valued_procedure pragma. Suppose you have a C function like this: int SomeCFunction( char * param ) Normally, there is no way to represent this kind of function in an Ada program. However, we can import it by treating it as a procedure using the import_valued_procedure pragma: procedure SomeCFunction ( result : out integer; param : in out integer ); pragma import( C, SomeCFunction); pragma import_valued_procedure( SomeCFunction ); The import_valued_procedure pragma tells gnat that this procedure corresponds to a C function: the first parameter is the result of the C function, and the remaining parameters correspond to the parameters of the C function. The first import pragma is not strictly required, but ACT recommends using it. You can't import identifiers created by the #define statement since they only exist before a C program is compiled. You also can't import types (except for C++ classes) since types have no address in memory. [KB-true?] There is one case where these tricks fail: when the C function returns a pointer to a C variable that it declared. In this case, the function is returning a new C pointer. Luckily, Ada provides a package called Address_To_Access_Conversions to convert between C pointers and Ada access types. You instantiate the package with the type you want to convert between, and the package creates an access type that can be converted to and from an address (which is a C pointer).The following program demonstrates conversions to and from C pointer types. with Ada.Text_IO, System.Address_To_Access_Conversions; use Ada.Text_IO; procedure pointers is package IntPtrs is new System.Address_To_Access_Conversions( integer ); -- Instantiate a package to convert access types to/from addresses. -- This creates an integer access type called Object_Pointer. five : aliased integer := 5; -- Five is aliased because we will be using access types on it int_pointer : IntPtrs.Object_Pointer; -- This is an Ada access all type int_address : System.Address; -- This is an address in memory, a C pointer begin int_pointer := five'unchecked_access; -- Unchecked_access needed because five is local to main program.
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (2 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

-- If it was global, we could use 'access. int_address := five'address; -- Addresses can be found with the 'address attribute. -- This is the equivalent of a C pointer. int_pointer := IntPtrs.To_Pointer( int_address ); int_address := IntPtrs.To_Address( int_pointer); -- Convert between Ada and C pointer types. end pointers; For example, the standard C library function get_current_dir_name returns a pointer to a C string which it declares. To use get_current_dir_name, we have to instantiate Address_To_Access_Conversions for an array of characters (a C string), and convert the address to an access type using something like CharArray_pointer := CharArrayPtrs.To_Pointer( get_current_dir_name ); There is no other way in Ada to access the array that get_current_dir_name points to. KB-If your main program is a C program, you need to call adainit before any Ada code.

16.2 Linux Errors and Errno


Most standard C library errors are returned in an integer variable called "errno". You can examine errno in your Ada programs by importing it. errno : integer; pragma import( C, errno); Errno contains a number for the error returned by the last library function.

In Multithreading programs, be aware errno may not be not "thread safe" because it can be shared between threads. [KB: document how to do it with threads]

Linux provides two functions for working with errno error numbers. type string255is new string(1..255); type strptr is access string255; -- error messages are no longer than 255 characters procedure perror( message : string); pragma import( C, perror ); Perror prints a standard error description with a leading message to standard error. function strerror( error_number : integer ) return strptr; pragma import( C, strerror); Retuns a C string standard error description. The following example program makes a deliberate error with the link function and prints the error message using perror and stderror.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (3 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

with ada.text_io, ada.strings.fixed; use ada.text_io, ada.strings.fixed; procedure perr is -- an example of perror and strerror error messages procedure perror( message : string ); pragma import( C, perror ); -- print a standard error description with a leading message type string255 is new string(1..255); type strptr is access string255; -- error messages are no longer than 255 characters function strerror( error_number : integer ) pragma import( C, strerror); -- get a standard error description errno : integer; pragma import( C, errno ); -- last error number function link( path1, path2 : string ) return integer; pragma import( C, link); -- we'll use the link function to create an error LinkResult : integer; -- value returned by link ErrorMessagePtr : strptr; -- pointer to stderror message NullLocation : integer; -- location of NUL in stderror message begin Put_Line( "This is an example of perror and strerror"); New_Line; -- make a deliberate error and print it with perror Put_Line( "Trying to link a non-existent file to itself.." ); LinkResult := Link( "blahblah", "blahblah" ); if LinkResult = -1 then perror( "Link failed" ); end if; New_Line; -- Retrieve the last error message with strerror. -- Because strerror returns a C string, only print the -- string up to the first NUL character. ErrorMessagePtr := StrError( Errno ); NullLocation := Index( string( ErrorMessagePtr.all ), "" & ASCII.NUL ); Put( "The last error message was '" ); Put( Head( string( ErrorMessagePtr.all ), NullLocation-1 ) ); Put_Line( "'." ); end perr; return strptr;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (4 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

This is an example of perror and strerror Trying to link a non-existent file to itself. Link failed: No such file or directory The last error message was 'No such file or directory'. A table of error numbers is in the appendix.

16.3 The Linux Clock


The Ada.Calendar package is the standard method of working with time in Ada programs. If you need to interface with C programs, you may need to use Linux's time features. The Linux clock functions are either kernel calls or are a part of the standard C library, and they don't need to be linked in with the -lc option.

16.3.1 Basic time functions


The basic Linux time functions work with the number of seconds since January 1, 1970. This is referred to as the epoch in the Linux man pages. Because of the limits of a long integer value, the Linux clock will stop working properly around the year 2038. The basic functions use a long_integer for the time: type time_t is new long_integer; procedure time ( time : in out time_t); pragma import( C, time ); Returns the current time. function difftime( time1, time2 : time_t ) return long_float; pragma import( C, difftime ); Returns the number of seconds between two times (as a long_float).

16.3.2 Timeval Calls - Microsecond Accuracy


The timeval kernel calls return (or set) the current time with microsecond accuracy using a timeval record. type timeval is record tv_sec : time_t; -- number of seconds (since epoch) tv_usec : long_integer; -- number of microseconds end record; type timezone is record tz_minuteswest : integer; -- minutes west of Greenwich tz_dsttime : integer -- unsupported in Linux end record; procedure gettimeofday( result : out integer; tv : in out timeval, tz : in out timezone ); pragma import(C, gettimeofday ); pragma import_valued_procedure( gettimeofday ); Get the current time as the number of microseconds since January 1, 1970. Returns 0 for success. ftime() is an obsolete version of this function

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (5 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

procedure settimeofday( result : out integer; tv : in out timeval; tz : in out timezone ); pragma import( C, settimeofday ); pragma import_valued_procedure( settimeofday ); Set the current time as the number of microseconds since January 1, 1970. Returns 0 for success. procedure tzset; pragma import( C, tzset ); Create the TZ environment variable, if it doesn't exist, and sets it to the current timezone as specified in /etc/localtime or /usr/lib/zoneinfo/localtime. This is automatically invoked by the standard C library time functions whenever necessary. procedure adjtimex( result : out integer; buf : inout timex ); pragma import( C, adjtimex ); Tunes the kernel's clock for specific time parameters

16.3.3 Functions using the tm record


Besides the number of seconds elapsed since 1970, Linux can also work with records containing the time broken down into common measurements. These functions use a tm record. These functions are all a part of the standard C library. type tm is record sec : integer; min : integer; hour : integer; mday : integer; mon : integer; year : integer; wday : integer; yday : integer; isdst : integer; end record;

----------

seconds on the clock (0-59) minutes on the clock (0-59) hour on the clock (0-23) day of the month (1-31) month (0-11) year day of the week (0-6) day of the year (0-365) >0 is daylight savings time, 0=not, <0 unknown

You will also need the Address_To_Access_Conversions package to convert C pointers to tm record into Ada access type pointers. package TmPtrs is new System.Address_To_Access_Conversions( tm ); function localtime( time : in out time_t ) return system.address; pragma import( C, localtime ); Change the time into a tm record, making changes for the current time zone. time is the C pointer to the seconds since 1970. function gmtime( time : in out time_t ) return system.address; pragma import( C, gmtime ); Change the time into a tm record for UTC (Coordinated Universal Time). time is the C pointer to the seconds since 1970. function mktime( tm : system.address ) return time_t; pragma import( C, mktime ); Convert a tm record into the seconds since 1970. To get the current time in tm format, seconds_since_1970 : long_integer;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (6 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

tm_rec : tm; ... time( seconds_since_1970 ); tm = TmPtrs.To_Pointer( localtime( seconds_since_1970'address ) ).all;

16.3.4 Time as a String


function asctime( tm : system.address ) return string; pragma import( C, asctime ); Convert the tm into a standard UNIX time C string, such as you see with the ls -l shell command. function ctime( time : in out time_t) return long_integer; pragma import( C, ctime ); Get the current time as a standard UNIX time C string. It's equivalent to using asctime() on the localtime() of the current time(). procedure strftime( result: size_t; datestr : in out stringtype; max : size_t; format : string; tm : in out tmrec ); pragma import( C, strftime ); Like asctime(), converts a tm time into text. strftime() uses formatting codes to determine the appearance of the text, similar to the shell date command. Returns the length of the date string (including the ending ASCII.NUL). See the man page for complete details. Example: datestring : string(1..80); ... statftime( datestringsize, datestring, datestring'size/8, "%I:%M" & ASCII.NUL, tm ); Ada.Text_IO.Put_Line( "The time is " & datestring( 1..datestringsize-1 ) );

16.3.5 Timer Functions


Timer functions use the timeval structure function timerclear( tv : timeval ); function timerisset( tv : timeval ); function timercmp( t0, t1 : timeval; operator : ? );

16.4 Process Information


The Linux process functions are part of the standard C library, and do not need to be linked in with -lc. function getpid return integer; Returns the Process Identification Number (PID) for your program.

16.4.1 Ownership
The owner of a program is referred to as the UID (user identification number). Under Linux, there are actually three owners to any given program: the effective UID, the real UID and the saved UID. Normally, these three are all the same login. The real and saved uids are provided for programs that must temporarily pretend to be somebody else, like a daemon that needs special login for a short period of time, or setuid/setgid programs that must temporarily switch between owners. These special
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (7 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

functions are not covered here. function getuid return integer; pragma import( C, getuid ); Get the (real) UID of a process. Example: Put_Line( "My UID is " & getuid'img ); function setuid (uid : integer ) return integer; pragma import( C, setuid ); Change the effective (and saved and real) UID of a process to a new owner. The GID (group identification number) is the group the program belongs to. In Linux, there's a main, effective group number, and any number of secondary groups that a program can belong to. There is also real and saved GIDs, just like UIDs. procedure getgroups( result : out integer; num : integer; gidlist ); pragma import( C, getgroups); pragma import_valued_procedure( getgroups ); Return a list of group numbers that a process belongs to. Gidlist is the address of a list of C strings. function getgid return integer; pragma import( C, getgid ); Get the (real) UID of the process. Example: Put_Line( "My GID is " & getgid'img ); function setguid( gid : integer ) return integer; pragma import( C, setgid ); Change the effective GID (and saved and real) of a process to a new group. Linux also allows you to arrange processes into groups for easier management of multiple processes at once. Each process group as a, no surprise, a process group identification number (PGID). function setpgid( pid, pgid : integer ) return integer; pragma import( C, setpgid ); Place a process into a new process group. PID 0 is the current process. PGID 0 creates a new process group. function getpgid( pid : intger ) return integer; pragma import( C, getpgid ); Example: Put_Line( "My PGID is " & getpgid'img ); Returns the process group number for a process. PID 0 is the current process. Every program and process group also belongs to a session (as in a login session). When you log off the computer, Linux automatically stops all programs that were running in your session. The session leader is the top process in a session, such as your login shell. However, if you want to create a new session for some reason, you can use the following function: function setsid return integer; pragma import( C, setsid ); Start a new session and return a new session identification number (SID). Example: NewSID := etsid; 16.4.2 Other Functions function kill( uid, signal : integer ) return integer; pragma import( C, kill ); Stop a child process that your process has started, the same as using the kill command at the shell prompt. (More accuately, send a signal to a child processsome signals won't stop the child process.) Example: Result := kill( MyRunawayChildUID, 15 ); -- send SIGTERM (terminate) signal

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (8 of 47) [7/20/2001 11:37:13 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Signal handling, in general, is easier through Ada.Interrupts than through Linux kernel calls because of their heavy reliance on C macros.--KB function alarm( seconds : Interfaces.C.unsigned ) return Interfaces.C.unsigned; pragma import( C, alarm ); After the specified number of seconds, cause a SIGALRM interrupt in the current process.

16.5 Environment Variables


Environment variables can easily be set and read with Ada.Command_Line.Environment package. You can also set them directly through the standard C library. function putenv( str : string ) return integer; pragma import( C, putenv ); Define a Linux environment variable. putenv literally saves a pointer to the string; therefore the string must be global (or a literal). Example: Result := putenv( "TERM=vt102" & ASCII.NUL ); function getenv( str : string ) return string; pragma import( C, putenv ); Read the value of an environment value. Remember the string returned is a C string with an ending ASCII.NUL.

16.6 Multitasking
Multitasking creates child processes to do tasks for your main program. On multiprocessor machines, different processes can be assigned to different processors allowing work to be done simultaneously. On single processor machines, the processor switches several times a second between processes and does a little work on each. The function to create a new child process is called fork. When Linux creates a new process, it doesn't start by creating a blank process. Instead, it makes a copy of the original process so there are effectively two copies of your program running. The fork function returns a value to tells your program if it is the original program or the new copy. If you want to run a different program, you'll have to use one of the exec family of functions to load and run the new program. The exec functions destroy the old program and run a new program in its place. The above section, Using System and OSLib.Spawn, has an example C function called CrunIt that uses fork to start a new process and run a new program. type pid_t is new integer; function fork return pid_t; pragma import( C, fork ); Create a new child process identical to the original process and return 0 if the program is running as the child process or the PID of the parent if the program is running as the original parent process. Example: myPID := fork; procedure wait( pid : out pid_t; status : in out integer ); pragma import( C, wait); pragma import_valued_procedure( wait ); Wait until a child process have finished running. Pid is the PID of the child. status is an integer code indicating whether the child finished normally, and if it was stopped by a signal, which signal terminated the program. Status can be a null pointer if you don't want status information. Example: wait( wait_pid, wait_status ); procedure waitpid( pid : out pid_t, pid_or_gid : in out pid_t; status : in out integer; options : integer ); pragma import( C, waitpid); pragma import_valued_procedure( waitpid); Wait for a specific child. If pid_or_gid is less than -1, waitpid waits for any child in the specified group id. If pid_or_gid is -1,
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (9 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

it waits for any child (the same as wait). If pid_or_gid is 0, it waits for any child in the same group id as the parent. If pid_or_gid is greater than zero, waits for the child with the specified pid. Status can be a null pointer if you don't want status information. Options can determine whether waitpid returns immediately or blocks indefintely. Example: waitpid( child_pid, -children_gid, wait_status, 0 ); Wait3 and Wait4 are BSD UNIX variations which perform the same functions as wait and waitpid but with slightly different parameters. When multitasking, if a child process stops, it's retained in memory so that the parent can use wait to find out the reason it stopped running. These children are called "zombies". If the parent process doesn't use wait, the zombies will remain indefinitely, using up system resources. For any large multitasking program, make sure you handle SIGCHLD signals: these are created when a child stops running. The SIGCHLD handler only needs to call wait and Linux will then remove the child process from memory. The following is a simple multitasking example that multitasks two Put_Line statements. -- a simple example of multitasking that multitasks -- two put_line statements with ada.text_io; use ada.text_io; procedure multitask is type pid_t is new integer; function fork return pid_t; pragma import( C, fork); -- create a new process errno : integer; pragma import( C, errno); -- the last error code procedure wait( pid : out pid_t; status : in out integer); pragma import( C, wait); pragma import_valued_procedure( wait); -- wait until all child processes are finished myPID : pid_t; wait_pid : pid_t; wait_status : integer; begin Put_Line( "Welcome to this multitasking example" ); Put_Line( "This is the original process." ); New_Line; -- the fork function duplicates this program into -- two identical processes. Put_Line( "Splitting into two identical processes..." ); Put_Line( "-----------------------------------------" ); myPID := fork; -- split in two! -- This program is now the original process or the
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (10 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

-- new child process. myPID tells you which process -- you are. if myPID < 0 then Put_Line( Standard_Error, "Fork has failed. Error code " & errno'img ); elsif myPID = 0 then Put_Line( "This is the child process" ); else Put_Line( "This is the original process." ); -- wait until child is finished wait( wait_pid, wait_status); if wait_pid < 0 then Put_Line( Standard_Error, "Wait error: wait returned PID " & wait_pid'img & " and error number " & errno'img); end if; end if; end multitask;

Welcome to this multitasking example This is the original process. Splitting into two identical processes... ----------------------------------------This is the original process. This is the child process

16.7 Linux File Operations


The Linux file operations are part of the standard C library, and don't need to be linked in with the -lc option. The C calls are defined in the "fcntl.h" header file. [Explain Linux files here]

Linux never shortens files. If your file gets smaller, you must shorten it yourself using truncate.

The following bindings assume these types have been defined. type file_id is new integer; -- file ID number are discussed below type mode_t is new integer; type gid_t is new integer; type uid_t is new integer; type size_t is new long_integer; function unlink( pathname : string ) return integer; pragma import( C, unlink );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (11 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Delete a file. Example: Result := unlink( "/tmp/temp.txt" & ASCII.NUL ); function link( oldpath, newpath : string) return integer; pragma import( C, link ); Make a shortcut (hard link) to a file. Example: Result := link( "/tmp/temp.txt" & ASCII.NUL, "/tmp/newtemp.txt" & ASCII.NUL ); procedure getcwd( buf1 : out StringPtr; buf2 : in out stringptr; size : integer ); pragma import( C, getcwd ); pragma import_valued_procedure( getcwd) Return the current working directory. function mkdir( pathname : stringPtr; mode : mode_t ) return integer; pragma import( C, mkdir ); Create a new directory and set default permissions. function rmdir( pathname : string ) return integer; pragma import( C, rmdir ); Delete a directory. Example: Result := rmdir( "/tmp/tempdir" & ASCII.NUL ); function umask( mask : integer ) return integer; pragma import( c, umask ); Sets the default file permissions. function stat( filename : stringPtr; buf : stat_struct ) return integer; pragma import( C, stat ); Get information about a file, such as size and when it was last opened. function lstat( filename : stringPtr; buf : stat_struct ) return integer pragma import( C, lstat ); Same as stat function, but doesn't follow symbolic links. function tmpnam( s : stringPtr ) return stringPtr; pragma import( C, tmpnam ); Create a random name for a temporary file. function chown( path : string; owner : uid_t; group : gid_t) return integer; pragma import( C, chown ); function fchown( file : file_id; owner : uid_t; group : gid_t return integer; pragma import( C, fchown ); Change the ownership of a file to the specified owner and group. Example: Result := chown( "root.txt" & ASCII.NUL, 0, 0 ); function chmod( path : string; mode : mode_t ) return integer; pragma import( C, chmod ); function fchmod( file : file_id; mode : mode_t ) return integer; pragma import( C, fchmod ); Change the read/write/execute permissions on a file. Example: Result := chmod( "secure.txt" & ASCII.NUL, #8#640 ); Other low-level file operations are all done with the fcntl (file control) function. There are three variations to fcntl: it may have an operation code, an operation code and a long integer argument, or an operation code and a locking record argument. The operation numbers are defined in /usr/src/linux/asm-i386/fnctl.h:
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (12 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

F_DUPFD : constant integer := 0; F_GETFD : constant integer := 1; F_SETFD : constant integer := 2; F_GETFL : constant integer := 3; F_SETFL : constant integer := 4; F_GETLK : constant integer := 5; F_SETLK : constant integer := 6; F_SETLKW : constant integer := 7; F_SETOWN : constant integer := 8; F_GETOWN : constant integer := 9; F_SETSIG : constant integer := 10; F_GETSIG : constant integer := 11; function fcntl( fd : file_id; operation => F_DUPFD ) pragma import( C, fcntl ); Duplicates a file descriptor (same as dup2, but different errors returned). New descriptor shares everything except close-on-exec. New descriptor is returned. function fcntl( fd : file_id; operation => F_GETFD ) pragma import( C, fcntl ); Get close-on-exec flag; low bit is zero, file will close on exec kernel call. function fcntl( fd : file_id; operation => F_SETFD; arg : long_integer ) pragma import( C, fcntl ); Set the close-on-exec flag; low bit is 1 to make file close on exec kernel call. function fcntl( fd : file_id; operation => F_GETFL ) pragma import( C, fcntl ); Get flags used on open kernel call used to open the file function fcntl( fd : file_id; operation => F_SETFL; arg : long_integer ) pragma import( C, fcntl ); Set flags for open kernel call. Only async, nonblock and appending can be changed. procedure fcntl( result : out integer; fd : file_id; operation => F_GETLK; lock : in out lockstruct ) return integer pragma import( C, fcntl ); pragma import_valued_procedure( fcntl ); Return a copy of the lock that prevents the program from accessing the file, or else if there is nothing blocking, the type of lock procedure fcntl( result : out integer; fd : file_id; operation => F_SETLK; lock : in out lockstruct ) return integer pragma import( C, fcntl ); pragma import_valued_procedure( fcntl ); Place a lock on the file. If someone else has locked the file already, -1 is returned and errno contains the locking error. procedure fcntl( result : out integer; fd : file_id; operation => F_SETLKW; lock : in out lockstruct ) return integer pragma import( C, fcntl ); pragma import_valued_procedure( fcntl ); Place a read or write lock on the file, or to unlock it. If someone else has locked the file already, wait until the lock can be

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (13 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

placed. Additional information about locks are found in /usr/src/linux/Documentation/locks.txt type aLock is new short_integer; F_RDLCK : constant aLock := 0; -F_WRLCK : constant aLock := 1; -F_UNLCK : constant aLock := 2; -F_EXLCK : constant aLock := 3; -F_SHLCK : constant aLock := 4; -type aWhenceMode is SEEK_SET : constant SEEK_CUR : constant SEEK_END : constant

read lock write lock unlock (remove a lock) exclusive lock shared lock

new short_integer; aWhenceMode := 0; -- absolute position aWhenceMode := 1; -- offset from current position aWhenceMode := 2; -- offset from end of file

type lockstruct is record l_type : aLock; l_whence : short_integer; l_start : integer; l_len : integer; l_pid : integer; end record;

------

type of lock how to interpret l_start offset or position number of bytes to lock (0 for all) with GETLK, process ID owning lock

To lock a file, create a lockstruct record and fill in the details about the kind of lock you want. A read lock (F_RDLCK) makes the part of the file you specify read-only. No one can write to that part of the file. A write lock prevents any other program from reading or writing to the part of the file you specify. Your program may change that part of the file without being concerned that another process will try to read it before you're finished. If your program stops prematurely, the locks will be released. Example: Get exclusive right to write to the file, waiting until it's possible: -- lock file myLockStruct : lockStruct; result : integer; ... myLockStruct.l_type := F_WRLCK; myLockStruct.l_whence := 0; myLockStruct.l_start := 0; myLockStruct.l_end := 0; fcntl( result, fd, F_SETLKW, myLockStruct ); if result = -1 then put_line( standard_error, "fcntl failed" ); end if; -- file is now locked ... -- unlock file myLockStruct.l_type := F_UNLCK; myLockStruct.l_whence := 0; fcntl( result, fd, F_SETLKW, myLockStruct ); if result = -1 then put_line( standard_error, "fcntl failed" ); end if;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (14 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

[Double check off_t size for l_start, l_len--KB] function fcntl( fd : file_id; operation => F_GETOWN ) pragma import( C, fcntl ); Get the process (or process group) id of owner of file. The owner is the process that handles SIGIO and SIGURG signals for that file. function fcntl( fd : file_id; operation => F_SETOWN, arg : long_integer ) pragma import( C, fcntl ); Set the process (or process group) id of owner of file. The owner is the process that handles SIGIO and SIGURG signals for that file. This affects async files and sockets. function fcntl( fd : file_id; operation => F_GETSIG ) pragma import( C, fcntl ); Get the signal number of the signal sent when input or output becomes possible on a file (usually SIGIO or zero). (This is a Linux-specific function.) function fcntl( fd : file_id; operation => F_SETSIG, arg : long_integer ) pragma import( C, fcntl ); Set the signal number of the signal sent when input or output becomes possible on a file (zero being the default SIGIO). Use this to set up a signal handler alternative to the kernel calls select and poll. See the man page for more information. (This is a Linux-specifc function.)

16.8 Opening and Closing Files


The standard Ada packages Text_IO, Sequential_IO and Direct_IO are suitable for simple projects, but they were never intended as a complete solution for large-scale applications. If you want to do efficient file manipulation, you'll have to write your own routines based on kernel calls or the standard C library. gnat's OSLIB package contains low-level commands to work with UNIX files. However, you can always create your own. The following bindings assume these types have been defined. type file_id is new integer; type mode_t is new integer; type off_t is new long_integer; type size_t is new long_integer; subype ssize_t is size_t; function open( path : string; flags : integer; mode : mode_t ) return file_id; pragma import( c, open ); Open a file and return and file identification number. flags indicates how the file should be opened and what kind of access the file should allow (defined in /usr/include/fcntlbits.h). Mode defines the access permissions you want on the file. The flags are a set of bits with different meanings: O_RDONLY O_WRONLY O_RDWR O_CREAT O_EXCL O_NOCTTY : : : : : : constant constant constant constant constant constant integer integer integer integer integer integer := := := := := := 8#00#; 8#01#; 8#02#; 8#0100#; 8#0200#; 8#0400#; ------open for reading only open for writing only open for reading and writing no file? create it lock file (see below) if tty, don't acquire it

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (15 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

O_TRUNC : constant integer := 8#01000#; -- file exists? truncate it O_APPEND : constant integer := 8#02000#; -- file exists? move to end O_NONBLOCK : constant integer := 8#04000#; -- if pipe, don't wait for data O_SYNC : constant integer := 8#010000#; -- don't cache writes O_ASYNC : constant integer := 8#020000#; -- async. IO via SIGIO O_DIRECT : constant integer := 8#040000#; -- direct disk access O_LARGEFILE: constant integer := 8#0100000#; -- not implemented in Linux (yet) O_DIRECTORY: constant integer := 8#0200000#; -- error if file isn't a dir O_NOFOLLOW : constant integer := 8#0400000#; -- if sym link, open link itself Flags may be added together. O_EXCL is somewhat obsolete and has limitations on certain file systems. Use fcntl to lock files instead. O_SYNC only works on the ext2 file system or on block devices. function creat( path : string, mode : mode_t ) return file_id; pragma import( c, creat ); Creat is a short form for open( path, create + writeonly + truncate, mode ) function close( file : file_id ) return integer; pragma import( C, close ); Closes a file. function truncate( path : string; length : size_t ) return integer; pragma import( C, truncate ); function ftruncate( file : file_id; length : size_t ) return integer; pragma import( C, ftruncate); Shorten a file to a specific length. Despite its name, ftruncate is a kernel call, not a standard C library call like fopen. function read( file : file_id; b : in out buffer; length : size_t ) return ssize_t; pragma import( C, read ); Read bytes from the specified file into a buffer. Buffer is any type of destination for the bytes read, with length being the size of the buffer in bytes. The number of bytes read is returned, or -1 on an error. function write( file : file_id; b : in out buffer; length : size_t ) return ssize_t; pragma import( C, write ); Write bytes from a buffer into the specified file. Buffer is any type of destination for the bytes read, with length being the size of the buffer in bytes. The number of bytes written is returned, or -1 on an error. function lseek( file : file_id; offset : off_t; whence : integer ) return integer; pragma import( C, lseek ); Move to a particular position in the specified file. Whence is a code representing where your starting position is. Offset is how many bytes to move. There are three possible "whence" values: SEEK_SET : constant integer := 0; -- from start of file SEEK_CUR : constant integer := 1; -- offset from current position SEEK_END : constant integer := 2; -- from end of file File input/output is naturally suited to generic packages. You can use the generic package to hide the low-level details of the standard C library. In following example, SeqIO is a generic package for reading and writing a sequential file of some type, using the kernel calls mentioned above. -- SeqIO --- A simple sequential IO package using standard C functions
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (16 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

generic type AFileElement is private; package SeqIO is type AFileID is new short_integer; seqio_error : exception; function Open( path : string; read : boolean := true ) return AFileID; -- open a new file for read or write procedure Close( fid : AFileID ); -- close a file procedure Read( fid : AFileID; data : in out AFileElement); -- read one data item from the file. seqio_error is raised -- if the data couldn't be read procedure Write( fid : AFileID; data : AFileElement ); -- write one data item to the file. seqio_error is raised -- if the data couldn't be written end SeqIO; package body SeqIO is pragma optimize( space); -- Import C file handling functions type mode_t is new integer; -- C mode_t type type size_t is new integer; -- C size_t type subtype ssize_t is size_t; -- C ssize_t type -- The C file functions we'll be using -- (denoted with a C_ prefix for clarity ) function C_Open( path : string; flags : integer; mode : mode_t) return AFileID; pragma import( C, C_Open, "open"); function C_Close( file : AFileID ) return integer; pragma import( C, C_Close, "close" ); procedure C_Read( size : out ssize_t; file : AFileID; data : in out AFileElement; count: size_t); pragma import( C, C_Read, "read"); pragma import_valued_procedure( C_Read); -- Using an "in out" parameter is the easiest way to pass -- the address of the data element. Because Ada doesn't -- allow in out parameters in functions, we'll use gnat's -- valued procedure pragma to pretend read is a procedure procedure C_Write( size : out ssize_t;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (17 of 47) [7/20/2001 11:37:14 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

file : AFileID; data : in out AFileElement; count: size_t); pragma import( C, C_Write, "write"); pragma import_valued_procedure( C_Write); -- Using an "in out" parameter is the easiest way to pass -- the address of the data element. Because Ada doesn't -- allow in out parameters in functions, we'll use gnat's -- valued procedure pragma to pretend write is a procedure -- Our Ada subprograms function Open( path : string; read : boolean := true ) return AFileID -- open a new file for read or write flags : integer; begin -- the flag values are listed in fcntlbits.h and man 2 open if read then flags := 0; -- read only, existing file else flags := 1000 + 100 + 1; -- write only, create or truncate end if; -- octal 640 => usr=read/write, group=read, others=no access return C_Open( path & ASCII.NUL, flags, 8#640# ); end Open; procedure Close( fid : AFileID ) is -- close a file Result : integer; -- we'll ignore it begin Result := C_Close( fid); end Close; procedure Read( fid : AFileID; data : in out AFileElement ) is -- read one data item from the file BytesRead : ssize_t; begin -- 'size returns the size of the type in bits, so we -- divide by 8 for number of bytes to read C_Read( BytesRead, fid, data, AFileElement'size / 8 ); if BytesRead /= AFileElement'size / 8 then raise seqio_error; end if; end Read; procedure Write( fid : AFileID; data : AFileElement ) is -- write one data item to the file BytesWritten : ssize_t; data2write : AFileElement; begin -- can't use data directly because it's an "in" parameter data2write := data; -- 'size returns the size of the type in bits, so we -- divide by 8 for number of bytes to write
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (18 of 47) [7/20/2001 11:37:14 AM]

is

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

C_Write( BytesWritten, fid, data2write, AFileElement'size / 8); if BytesWritten /= AFileElement'size / 8 then raise seqio_error; end if; end Write; end SeqIO; You can test SeqIO with the following program: with SeqIO; with Ada.Text_IO; use Ada.Text_IO; procedure SeqIOtest is -- program to test SeqIO package IntIO is new SeqIO( integer); -- IntIO is a SeqIO for integer numbers id : IntIO.AFileID; int2read : integer; begin Put_Line( "Testing SeqIO package..." ); New_Line; -- Part #1: Write numbers to a file Put_Line( "Writing numbers 1 to 10 to a file..."); id := IntIO.Open( "int_list.txt", read => false ); for i in 1..10 loop IntIO.Write( id, i) end loop; IntIO.Close( id); -- Part #2: Read the numbers back from the same file Put_Line( "Reading numbers back..." ); id := IntIO.Open( "int_list.txt", read => true); for i in 1..10 loop IntIO.Read( id, int2read); Put_Line( "Number" & i'img & " =" & int2read'img ); end loop; IntIO.Close( id ); exception when IntIO.seqio_error => Put_Line( "Oh, oh! seqio_error!"); end SeqIOtest; Note: This should be rewritten because a failure to write all the bytes is not necessarily an error--Linux has a buffer limit on how much it writes at one time--KB

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (19 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Writing numbers 1 to 10 to a file... Reading numbers back... Number 1 = 1 Number 2 = 2 Number 3 = 3 Number 4 = 4 Number 5 = 5 Number 6 = 6 Number 7 = 7 Number 8 = 8 Number 9 = 9 Number 10 = 10 File Multiplexing Operations These kernel calls help programs that have to monitor several file descriptors at once for activity. procedure select( result : out integer; topplusone : integer; readset : in out fdset; writeset : in out fd_set; errorset : in out fd_set; timeout : in out timeval ); pragma import( C, select ); pragma import_valued_procedure( select ); Select checks one or more file descriptors to see if they are ready for reading, writing, or if there is an error. It will wait up to timeout microseconds before timing out (0 wll return immediately). topplusone is the numerically highest file descriptor to wait on, plue one. The result is 0 for a timeout, -1 for failure, or the number of file discriptors that are ready and the file discriptor sets indicate which ones. Unlike most UNIX's, Linux leaves the time remaining in the timeout record so that you can use select in a timing loop--to repeatedly select file descriptors until the timeout counts down to zero. Other UNIX's leave the timeout unchanged.

type pollfd is record fd : integer; events : short_integer; revents : short_integer; end record; Poll Events POLLIN := 16#1#; POLLPRI := 16#2#; POLLOUT := 16#4#; POLLERR := 16#8#; POLLHUP := 16#10#; POLLNVAL := 16#20#; These are defined in asm/poll.h. procedure poll( result : out integer; ufds : in out pollfd; nfds : integer; timeout_milliseconds : integer ); pragma import( C, poll ); pragma import_valued_procedure( poll ); The name of this kernel call is misleading: poll is a form of select(). timeout_milliseconds is a timeout in milliseconds, -1 for no timeout. ufds is an array of pollfd records for files that poll() should monitor. Poll returns the number of pollfd array elements that have something to report, 0 in a timeout, or -1 for an error. Each bit in events, when set, indicates a particular event that the program is waiting for. Revents represents the events which occurred.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (20 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

16.9 Directories
Directories are "folders" containing collections of files and other directories. In Linux, a directory is a special kind of file. Some of the standard file operations work on directories and some other file operations are specific to directories. The top-most directory is /, or the root directory. All files on a system are located under the root directory. Disk drives do not have separate designations as in MS-DOS. A period (.) represents the current directory, and a double period (..) represents the parent directory of the current directory. All directories have . and .. defined. The root directory, of course, doesn't have a parent: it's .. entry points to itself. Many of the kernel calls and standard C library functions dealing with directories use functions that return C pointers. As mentioned in the bindings section, the only way to convert these kind of functions to Ada is by declaring the C pointers as a System.Address type and changing the C pointers to Ada access types using the Address_To_Access_Conversions package. procedure getcwd( buffer : out string; maxsize : size_t ); pragma import( C, getcwd ); Returns the name of the current working directory as a C string in buffer. Maxsize is the size of the buffer. All symbolic links are dereferenced. function get_current_dir_name return System.Address; pragma import( C, get_current_dir_name ); Like getcwd, returns the current working directory name as a pointer to a C string. Unlike getcwd, symbolic links aren't dereferenced. Use this function to show the current directory to a user. procedure chdir( path : string); pragma import( C, chdir ); Change the current working directory to the specified path. Example: chdir( "/home/bob/stuff" & ASCII.NUL ); function mkdir( path : string; mode : size_t ) return integer; pragma import( C, mkdir ); Create a new directory with permission bits as specified by mode. function rmdir( path : string ) return integer; pragma import( C, rmdir ); Remove a directory. function opendir( path : string ) return System.Address; pragma import( C, opendir); Open a directory in order to read its contents with readdir. function closedir( info : System.Address) return integer; pragma import( C, closedir); Close a directory openned with opendir. Info is the C pointer returned by opendir. function readdir( info : System.Address ) return DirEntCPtr; pragma import( C, readdir); Read the next entry in the directory. A null C pointer is returned if there is no more entries. Info is the C pointer returned by opendir. function rewinddir( info : System.Address ) return integer; pragma import( C, rewinddir); Begin reading from the top of the directory. Info is the C pointer returned by opendir. function telldir( info : System.Address) return integer; pragma import( C, telldir); Mark the current position in the directory, to return to it later using the seekdir function. Info is the C pointer returned by
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (21 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

opendir. function seekdir( info : System.Address; position : integer ) return integer; pragma import( C, seekdir ); Return to a position in the directory marked by telldir. Info is the C pointer returned by opendir. function chroot( newroot : string ) return int; pragma import( C, chroot ); Make Linux think that a different directory is the root directory (for your program). This is used by programs such as FTP servers to prevent uses from trying to access files outside of a designated FTP directory. Example: Result := chroot( "/home/server/stay-in-this-directory" & ASCII.NUL); There is also a scandir function that reads a directory and sorts the entries, but this is difficult to use directly from Ada. The following program demonstrates some of the directory subprograms in Linux. with Ada.Text_IO, Interfaces.C, Ada.Strings.Fixed; use Ada.Text_IO, Interfaces.C, Ada.Strings.Fixed; with System.Address_To_Access_Conversions; procedure direct is -- Working with directories subtype size_t is Interfaces.C.size_t; -- renaming size_t to save some typing package CStringPtrs is new System.Address_To_Access_Conversions( string ); use CStringPtrs; -- Convert between C and Ada pointers to a string subtype DirInfoCPtr is System.Address; subtype DirEntCPtr is System.Address; -- two C pointers (System.Address types), renamed for -- clarity below type DirEnt is record inode : long_integer; -- inode number offset : integer; -- system dependent offset2: unsigned_char; -- system dependent reclen : unsigned_short; -- system dependent name : string( 1..257 ); -- name of file end record; pragma pack( dirent); -- dirent is defined in /usr/src/linux../linux/dirent.h package DirEntPtrs is new System.Address_To_Access_Conversions( DirEnt ); use DirEntPtrs; -- Convert between C and Ada pointers to a directory entry procedure getcwd( buffer : out string; maxsize : size_t ); pragma import( C, getcwd );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (22 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

function get_current_dir_name return System.Address; pragma import( C, get_current_dir_name); function mkdir( path : string; mode : size_t ) return integer; pragma import( C, mkdir ); function rmdir( path : string ) return integer; pragma import( C, rmdir ); function opendir( path : string ) return DirInfoCPtr; pragma import( C, opendir ); function closedir( info : DirInfoCPtr ) return integer; pragma import( C, closedir ); function readdir( info : DirInfoCPtr ) return DirEntCPtr; pragma import( C, readdir ); function rewinddir( info : DirInfoCPtr ) return integer; pragma import( C, rewinddir ); function telldir( info : DirInfoCPtr ) return integer; pragma import( C, telldir ); function seekdir( info : DirInfoCPtr; position : integer ) return integer; pragma import( C, seekdir ); -- scandir hard to use from Ada s: string(1..80); csop: CStringPtrs.Object_Pointer; Result: integer; DirInfo: DirInfoCPtr; direntop : DirEntPtrs.Object_Pointer; Position : integer; LastPosition : integer; begin Put_Line( "This program demonstrates Linux's directory functions" ); New_Line; -- getcwd example getcwd( s, s'length ); Put( "The current path (simplified) is " ); Put_Line( Head( s, Index( s, ASCII.NUL & "" )-1 )); -- Index for fixed strings takes a string as the second parameter -- We'll make a string containing an ASCII.NUL with & -- get_current_dir_name example csop := To_Pointer( get_current_dir_name );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (23 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Put( "The current path is " ); Put_Line( Head( csop.all, Index( csop.all, ASCII.NUL & "" )-1 ) ); -- mkdir example: create a directory named "temp" Result := mkdir( "temp" & ASCII.NUL, 755 ); if Result /= 0 then Put_Line( "mkdir error" ); else Put_Line( "temp directory created" ); end if; -- rmdir example: remove the directory we just made Result := rmdir( "temp" & ASCII.NUL ); if Result /= 0 then Put_Line( "rmdir error" ); else Put_Line( "temp directory removed" ); end if; New_Line; -- directory reading DirInfo := OpenDir( "/home/ken/ada" & ASCII.NUL); Put_Line( "Directory /home/ken/ada contains these files:"); loop direntop := To_Pointer( ReadDir( DirInfo ) ); exit when direntop = null; -- TellDir returns the position in the directory -- LastPosition will hold the position of the last entry read LastPosition := Position; Position := TellDir( DirInfo ); Put_Line( Head( Direntop.name, Index( Direntop.name, ASCII.NUL & "" )-1 ) ); end loop; New_Line; -- SeekDir: move to last position in directory Result := SeekDir( DirInfo, LastPosition ); Put( "The last position is " ); direntop := To_Pointer( ReadDir( DirInfo ) ); Put_Line( Head( Direntop.name, Index( Direntop.name, ASCII.NUL & "" )-1 ) ); New_Line; -- RewindDir: Start reading again Result := RewindDir( DirInfo ); Put( "The first position is " ); direntop := To_Pointer( ReadDir( DirInfo ) ); Put_Line( Head( Direntop.name, Index( Direntop.name, ASCII.NUL & "" )-1 ) ); New_Line; -- close the directory
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (24 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Result := CloseDir( DirInfo ); end direct;

This program demonstrates Linux's directory functions The current path (simplified) is /home/ken/ada/trials The current path is /home/ken/ada/trial temp directory created temp directory removed Directory /home/ken/ada contains these files: . .. temp all.zip README posix.zip sm posix cgi tia x rcsinfo.txt text_only original lintel texttools smbeta2.zip trials plugins texttools.zip The last position is texttools.zip The first position is .

16.10 Stdio Files


C has a library called stdio, or STanDard IO, which contains standard operations for text files. Loosely, stdio is the C equivalent of Ada's Text_IO package.The standard gnat package cstreams(?) provides a thin binding to many of the stdio functions. In this section, we'll looking at using stdio directly. Some of the stdio functions can't be used from Ada because of differences in the languages. For example, printf, the standard command for writing to the screen, has a variable number of parameters. Because there's no way to express a variable number of parameters in Ada, printf can't be imported into Ada. with System; type AStdioFileID is new System.Address; function fputc( c : integer; fid : AStdioFileID ) return integer; pragma import( C, fputc, "fputc" ); Part of standard C library. Writes one charcter to a file. function fputs( s : string; fid : AStdioFileID ) return integer;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (25 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

pragma import( C, fputs, "fputs" ); Writes a C string to a file. function ferror( fid : AStdioFileID ) return integer; pragma import( C, ferror); Return error from last file operation, if any. procedure clearerr( fid : AStdioFileID ); pragma import( C, clearerr); Clear the error and end of file information. function feof( fid : AStdioFileID ) return integer; pragma import( C, feof); Return non-zero if you are at the end of the file. function fileno( fid : AStdioFileID ) return integer; pragma import( C, fileno); Return the file number for use with Linux file kernel calls. function flock( fd, operation : integer ) return integer; pragma import( C, flock ); Locks or unlocks a file (or a portion of a file). This is for compatibility with other UNIXes--use fcntl instead. Operation: LOCK_SH LOCK_EX LOCK_NB LOCK_UN (1) (2) (4) (8) shared lock exclusive lock no block flag (may be added to others) unlock

16.11 Stdio Pipes


Pipes are the equivalent of shell command pipes formed by the '|' character. You can open a pipe to or from a shell command, depending if the pipe is for writing or reading respectively. These single direction pipe commands are a part of the standard C library. function popen( command, mode : string ) return AStdioFileID; pragma import( C, popen, "popen" ); Opens a pipe to a Linux shell command.Mode can be "w" for write or "r" for read. procedure pclose( result : out integer; fid : AStdioFileID); pragma import( C, pclose, "pclose" ); pragma import_valued_procedure( pclose ); Closes a pipe. The following program prints to a printer by opening a pipe to the lpr command. with Ada.Text_IO, System, SeqIO; use Ada.Text_IO; procedure printer2 is -- a program for simple printing ---> Pipe Stuff -------------------------------------

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (26 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

type AStdioFileID is new System.Address; -- a pointer to a C standard IO (stdio) file id function popen( command, mode : string ) pragma import( C, popen, "popen" ); -- opens a pipe to command return AStdioFileID;

procedure pclose( result : out integer; fid : AStdioFileID ); pragma import( C, pclose, "pclose" ); pragma import_valued_procedure( pclose); -- closes a pipe function fputc( c : integer; fid : AStdioFileID ) return integer; pragma import( C, fputc, "fputc" ); -- part of standard C library.Writes one charctera to a file. function fputs( s : string; fid : AStdioFileID ) return integer; pragma import( C, fputs, "fputs" ); -- part of standard C library.Writes a string to a file. PipeID : AStdioFileID; -- File ID for lpr pipe procedure BeginPrinting is -- open a pipe to lpr begin Put_Line( "Opening pipe to lpr ..." ); PipeID := popen( "lpr" & ASCII.NUL, "w"& ASCII.NUL); end BeginPrinting; procedure EndPrinting is -- close the pipe.Result doesn't matter. -- Linux normally will not eject a page when -- printing is done, so we'll use a form feed. Result : integer; begin Result := fputc( character'pos( ASCII.FF ), PipeID); pclose( Result, PipeID ); end EndPrinting; --> Input/Output Stuff -------------------------------procedure Print( s : string ) is -- print a string to the pipe, with a carriage -- return and line feed. Result : integer; begin Result := fputs( s & ASCII.CR & ASCII.LF & ASCII.NUL, PipeID ); end Print; begin -- Open the pipe to the lpr command Put_Line( "Starting to print..." ); BeginPrinting; Print( "Sales Report" ); Print( "------------" ); Print( "" ); Print( "Sales were good" ); -- Now, close the pipe. EndPrinting; Put_Line( "Program done...check the printer" ); end printer2;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (27 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

16.12 Memory Management


The amount of virtual memory for a process depends on the processor. For Intel x86 processors, your program and data must be 3 Gigabytes or less. (An additional 1 Gigabyte per process is reserved for the kernel, accounting for the full 32-bits of addressing space.) [not finished--KB]

16.13 The Virtual Consoles


The virtual consoles are controlled by the ioctl() function. [not finished--KB] The following example catches SIGWINCH signals and reports the new window size. with Ada.Interrupts.Names; useAda.Interrupts; package sigwinch is protected SignalHandler is procedure SizeChangeHandler; pragma Attach_Handler( SizeChangeHandler, Names.SIGWINCH ); -- this handler will catch SIGWINCH signals, a window size -- change end SignalHandler; end sigwinch;

with Ada.Text_IO; useAda.Text_IO; package body sigwinch is

-- imported C functions TIOGWINSIZ : constant integer := 16#5413#; -- get window size ioctl request type WindowSizeInfo is record row, column, unused1, unused2 : short_integer; end record; pragma pack( WindowSizeInfo ); -- the window size information returned by ioctl type AFileID is new integer; -- a file descriptor, a new integer for safety procedure ioctl_winsz( Result : out integer; fid : AFileID; request : integer; info : in out WindowSizeInfo ); pragma import( C, ioctl_winsz, "ioctl");
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (28 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

pragma import_valued_procedure( ioctl_winsz, "ioctl" ); -- get the size of the window function open( path : string; flags : integer ) return AFileID; pragma import( C, open, "open" ); -- open a file (in this case, the tty) procedure close( fid : AFileID ); pragma import( C, close, "close" ); -- close a file -- The Signal Handler protected body SignalHandler is procedure SizeChangeHandler is -- handle a window size change, SIGWINCH fid: AFileID;-- open's file ID Result : integer; -- function result of ioctl Info: WindowSizeInfo; -- window size returned by ioctl begin fid := Open( "/dev/tty" & ASCII.NUL, 0 ); ioctl_winsz( Result, fid, TIOGWINSIZ, Info ); if Result = 0 then Put_Line( "Window is now " & info.column'img & " x " & info.row'img); else Put_Line( "ioctl reports an error" ); end if; Close( fid ); end SizeChangeHandler; end SignalHandler; end sigwinch;

with Ada.Text_IO, sigwinch; useAda.Text_IO, sigwinch; procedure winch is begin Put_Line( "This program catches SIGWINCH signals"); New_Line; Put_Line( "It will stop running is 60 seconds. If you are using" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (29 of 47) [7/20/2001 11:37:15 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Put_Line( "X Windows, move the window to send signals."); New_Line; delay 60.0; -- run for 60 seconds end winch;

16.14. Making Database Queries 16.14.1 mySQL


mySQL (pronounced "my ess que ell" ) is a free, high-performance database from T.c.X. It's available for a number of platform, including Linux. The mySQL home page is http://www.mysql.org. mySQL comes with a C library called "mysqlclient". If an Ada program links in this library with "-lmysqlclient", it can access mySQL databases. You issue commands to the database called queries using the database language SQL (pronounced "sequel"). Connecting to a mySQL database is a six step process: 1. Open a new connect using mysql_init. 2. Login using mysql_real_connect. 3. Perform database queries with mysql_query or mysql_real_query. real_query allows binary data in the query. 4. Retrieve the results using mysql_store_result or mysql_use_result. 5. Free any memory using mysql_free_result. 6. Close your connection with mysql_close. Usually, a null point or non-zero integer result indicates an error. mysql_errono returns the error. Complete documentation is available from the mySQL web site.

16.14.2 PostgreSQL
Not finished--KB

16.15 Dynamic Loading


Not finished--KB

16.16 A Word on Device Drivers


The details of writing kernel device drivers in Ada is beyond the scope of this book. However, you'll have to use "GNORT" (pragma no_run_time).

with Ada.Text_IO; use Ada.Text_IO; procedure nrt2 is -- Simple Program begin


file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (30 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

put_line( "Hello World" ); end nrt2;

pragma no_run_time; procedure nrt is -- Same as nrt2 but using no run time type file_id is new integer; -- No Ada.Text_IO possible, so we'll write our own -- that talks directly to the Linux kernel procedure write_char( amount_written : out long_integer; id : file_id; buffer : in out character; amount2write : long_integer ); pragma import( C, write_char, "write" ); pragma import_valued_procedure( write_char, "write" ); procedure put( c : character ) is result : long_integer; buf : character := c; begin write_char( result, 1, buf, 1 ); end put; procedure new_line is begin put( character'val( 10 ) ); end new_line; procedure put_line( s : string ) is pragma suppress( index_check, s ); -- s(i) won't throw a range error, but Gnat checks for it -- by default. Exceptions are a part of the run time. begin for i in s'range loop put( s(i) ); end loop; new_line; end put_line; begin put_line( "Hello World" ); end nrt;

16.17 Linux Sound


The Linux sound capabilities, called OSS, were developed by 4front technologies.You can find more advanced documentation at their website http://www.opensound.com. This section describes only the basic functions. The newest Linux sound standard is ALSA.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (31 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Most distributions have OSS in the kernel by default, but there's no reason that OSS must be present--it can always be turned off for computers without a sound card.

16.17.1 Detecting a Sound Card


Open the file /dev/sndstatus. If there is no error, the computer has a sound card.

16.17.2 Playing Sound Samples


There are no C libraries or kernel calls to play sound samples. Instead, there is a device file called /dev/dsp which plays sound samples in the .au sound format. The .au sound format consists of a header describing the sound followed by the actual sound data. The header looks like this: type AAUHeader is record Magic : integer;

---dataLocation : integer; -dataSize: integer; -dataFormat: integer; -samplingRate : integer; -channelCount : integer; -info1, info2, info3, info4 end record;

a unique number denoting a .au file, as used with the magic file, SND_MAGIC Hex 646E732E (bytes 2E, 73, 6E, 64) offset or pointer to the sound data number of bytes of sound data the data format code the sampling rate the number of channels : character;-- name of sound

dataLocation is an offset to the first byte of the sound data. If there's no sound name, it's 28, the size of the header. It can a pointer to the data, depending on the dataFormat code, but that doesn't apply if you're playing a .au file. dataSize is the size of the sound data in bytes, not including the header. dataFormat describes how the sound data is to be interpreted. Here is a table of some common values. Value 0 1 2 3 4 5 6 7 8 10 11 12 13 14 16 18 19 Code SND_FORMAT_UNSPECIFIED SND_FORMAT_MULAW_8 SND_FORMAT_LINEAR_8 SND_FORMAT_LINEAR_16 SND_FORMAT_LINEAR_24 SND_FORMAT_LINEAR_32 SND_FORMAT_FLOAT SND_FORMAT_DOUBLE SND_FORMAT_INDIRECT SND_FORMAT_DSP_CORE SND_FORMAT_DSP_DATA_8 SND_FORMAT_DSP_DATA_16 SND_FORMAT_DSP_DATA_24 SND_FORMAT_DSP_DATA_32 SND_FORMAT_DISPLAY SND_FORMAT_EMPHASIZED SND_FORMAT_COMPRESSED Format unspecified format 8-bit mu-law samples 8-bit linear samples 16-bit linear samples 24-bit linear samples 32-bit linear samples floating-point samples double-precision float samples fragmented sampled data DSP program 8-bit fixed-point samples 16-bit fixed-point samples 24-bit fixed-point samples 32-bit fixed-point samples non-audio display data 16-bit linear with emphasis 16-bit linear with compression

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (32 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

20 21

SND_FORMAT_COMPRESSED_EMPHASIZED SND_FORMAT_DSP_COMMANDS

Combo of the two above Music Kit DSP commands

SamplingRate is the playback rate in hertz.CD quality samples are 44100. channelCount is 1 for mono, 2 for stereo. The info characters are a C null-terminated string giving a name for the sound. It's always at least 4 characters long, even if unused. In order to play a sound, treat /dev/dsp as if it were a device attached to your computer for playing .au sounds.Write a program to open /dev/dsp for writing and write the .au sound to it. Playing sounds is a natural candidate for multithreading because you don't want your entire program to stop while a sound is being played. The following program uses the seqio generic package we developed above to play an .au sound through /dev/dsp. with seqio; with Ada.Text_IO; use Ada.Text_IO; procedure playsnd is -- simple program to play an .au sound file package byteio is new seqio( short_short_integer ); -- sequential files of bytes au_filename : constant string := "beep.au"; -- sound file to play. supply the name of the .au file to play au_file: byteio.AFileID; -- the sound file dev_dsp: byteio.AFileID; -- /dev/dsp device soundbyte : short_short_integer; begin Put_Line( "Playing " & au_filename & "..."); -- open the files au_file := byteio.Open( au_filename, read => true); dev_dsp := byteio.Open( "/dev/dsp", read => false); -- read until we run out of bytes, send all bytes to -- /dev/dsp.The end of file will cause a seqio_error begin -- nested block to catch the exception loop byteio.Read( au_file, soundbyte ); byteio.Write( dev_dsp, soundbyte ); end loop;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (33 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

exception when byteio.seqio_error => null; -- just leave block end; -- close files byteio.Close( au_file ); byteio.Close( dev_dsp ); Put_Line( "All done" ); exception when others => Put_Line( "Oh, oh!An exception occurred!" ); byteio.Close( au_file ); byteio.Close( dev_dsp ); raise; end playsnd;

16.17.3 Using the Mixer


You control the mixer chip, if your sound card has one, by using the ioctl() kernel call. If there is no mixer, the ioctl() function returns -1. Mixer Functions Table SOUND_MIXER_NRDEVICES SOUND_MIXER_VOLUME SOUND_MIXER_BASS SOUND_MIXER_TREBLE SOUND_MIXER_SYNTH SOUND_MIXER_PCM SOUND_MIXER_SPEAKER SOUND_MIXER_LINE SOUND_MIXER_MIC SOUND_MIXER_CD SOUND_MIXER_IMIX SOUND_MIXER_ALTPCM SOUND_MIXER_RECLEV SOUND_MIXER_IGAIN SOUND_MIXER_OGAIN SOUND_MIXER_LINE1 SOUND_MIXER_LINE2 SOUND_MIXER_LINE3 17 Number of mixer functions on this computer 0 The master volume setting 1 Bass setting 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Treble setting FM synthesizer volume /dev/dsp volume internal speaker volume, if attached to sound card "line in" jack volume microphone jack volume CD input volume Recording monitor volume volume of alternate codec, on some cards Recording level volume Input gain Output gain Input source 1 (aux1) Input source 2 (aux2) Input source 3 (line)

Reading or writing values have a special bit set [Ken check using soundcard.h]. Ioctl calls return an integer value. Volume levels can be 0 to 100, but many sound cards do not offer 100 levels of volume. /dev/mixer will set the volume to setting nearest to your requested volume. [Not complete--KB]

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (34 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Sound_mixer_volume : constant integer := 0; Sound_Mixer_Read : constant integer := ?; Sound_Mixer_Write : constant integer := ?; oldVolume : integer; ioctlResult := Ioctl( mixer_file_id, sound_mixer_read + sound_mixer_volume, oldVolume ); -- master volume now in oldVolume if ioctlResult = -1 then Put_Line( "No mixer installed " ); end if; newVolume := 75; ioctlResult := ioctl( mixer_file_id, sound_mixer_write + sound_mixer_volume, newVolume ); -- master volume is 75%

16.17.4 Recording Sound Samples


Recording sounds works is the reverse process of playing sounds. Open /dev/dsp for reading, and it returns sound data. However, before you can begin recording from /dev/dsp, you need to describe how you want the recording done. You need to select the input source, sample format (sometimes called as number of bits), number of channels (mono/stereo) , and the sampling rate (speed). These are set by using the ioctl function on the /dev/dsp file. To select the input source, you'll need to use /dev/mixer. [Not finished--KB Sound_Mixer_Recsrc : constant integer := ?; Sound_Mixer_Read : constant integer := ?; Sound_Mixer_Write : constant integer := ?; newInputSource := Sound_Mixer_Mic; ioctlResult := ioctl( mixer_file_id, sound_mixer_write + sound_mixer_recsrc, newInputSource ); Common formats /* Audio data formats (Note! U8=8 and S16_LE=16 for compatibility) */ AFMT_QUERY AFMT_IMA_ADPCM AFMT_U8 AFMT_S16_LE AFMT_S16_BE AFMT_S8 AFMT_U16_LE 16#00000000# 16#00000004# 16#00000008# 16#00000010# 16#00000020# 16#00000040# 16#00000080# Returns current format ADPCM compressed data Unsigned bytes Little endian signed 16 bits Big endian signed 16 bits Signed bytes Little endian U16 bits

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (35 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

AFMT_U16_BE AFMT_MPEG

16#00000100# 16#00000200#

Big endian U16 bits MPEG (2) audio

sndctl_dsp_setfmt : constant integer := ?; newFormat : integer; newFormat := 16#0000010#; ioctlResult := ioctl( dsp_id, sndctl_dsp_setfmt, newFormat ); -- recording format now 16 bit signed little endian if newFormat /= 16#00000010 then Put_Line( "Sound card doesn't support recording format" ); end if; Selecting mono or stereo recording is a matter of 0 or 1 respectively. sndctl_dsp_stereo : constant integer := ?; stereo : integer; stereo := 1; ... ioctlResult := ioctl( dsp_id, sndctl_dsp_stereo, stereo ); -- recording format now stereo if stereo /= 1 then Put_Line( "Sound card doesn't support stereo" ); end if; Finally, select a sampling rate. sndctl_dsp_speed : constant integer := ?; newSpeed : integer; newSpeed:= 44100; ioctlResult := ioctl( dsp_id, sndctl_dsp_speed, newFormat ); -- recording now CD quality sampling speed if newSpeed /= 44100 then Put_Line( "Sound card doesn't support sampling speed" ); end if; Now read /dev/dsp for the raw sound data. If you want to save the sound as an .au file, you'll have to create the .au header information to attach to the sound data.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (36 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

16.18 Audio CDs 16.19 Kernel Pipes 16.20 Shared Memory


Shared Memory Flags IPC_CREAT IPC_EXCL Create new shared memory block plus read, write and execute bits.

IPC_PRIVATE indicates no key is supplied. function shmget( key : key_t; bytes : integer; shmflag : integer ) return integer; pragma import( C, shmget ); Key is an id you supply to identify the memory (or IPC_PRIVATE for no key). bytes is the minimum amount of memory that you need. shmflag indicates options for this call. Returns -1 on error, or an id for the memory. Example: shmid := shmget( mykey, 4096, IPC_CREAT+IPC_EXCL+8#0660#); function shmat( result : out system.address; shmid : integer; shmaddr : system.address; shmflag : integer ) return system.address; pragma import( C, shmat ); Shared memory attach. Makes shared memory accessible by returning a pointer to it. shmid is the id returned by shmget. if shmaddr isn't zero, the kernel will the address you give instead of chosing one itself. shmflags are additional options. Returns the address of the shared memory, or an address of -1 for an error. Example: shmat( ShmCPtr, myID, To_Address( null ), 0 ); ShmPtr := To_Address( ShmCPtr ); SHM_RDONLY - this memory is read-only (that is, as if it was constant ). SHM_RND - allows your shmaddr to be truncated to a virtual memory page boundary. function shmdt( shmaddr : system.address ) return integer; pragma import( C, shmdt ); Shared memory detach. Removes the association of the shared memory to the pointer. Returns 0 if the memory was detached, -1 for failure. Example: Result := shmdt( To_Address( ShmPtr ) ); function shmctl( shmid : integer; cmd : integer; info : system.address) return integer; pragma import( C, shmctl ); Performs miscellaneous shared memory functions, including deallocating shared memory allocated with shmget. Returns 0 if the function was successful, or -1 for a failure. Example: Result := shmctl( myID, IPC_RMID, To_Address( null) ); IPC_RMID - deallocate shared memory

16.21 Message Queues 16.22 Semaphores

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (37 of 47) [7/20/2001 11:37:16 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

16.23 Sockets
Send (sentto and sendmsg) are supersets of write. When you use write on a socket, it's actually implemented using the send family. Write will not work on UDP because it's connectionless. Use send to specify an address everytime. Protocol Families PF_INET Internet (IPv4) PF_INET6 Internet (IPv6) PF_IPX Novell PF_NETLINK Kernel user interface device PF_X25 ITU-T X.25 / ISO-8208 PF_AX25 Amateur radio AX.25 PF_ATMPVC Access to raw ATM PVCs PF_APPLETALK Appletalk PF_PACKET Low-level packet interface Socket Types SOCK_STREAM Two-way reliable connection, with possible out-of-band transmission (eg. TCP/IP) SOCK_DGRAM (Datagram) Connectionless, unreliable messages (eg. UDP/IP) SOCK_SEQPACKET Sequenced, reliable datagram connection. SOCK_RAQ Raw network protocol access. SOCK_RDM Reliable, unordered datagrams. function socket( domain, soctype, protocol : integer ) return integer; pragma import( C, socket ); Creates a network socket for protocol family domain, connection type soctype, and a protocol (0 uses the default protocol). Returns -1 on an error, or else a kernel file descriptor for the socket. Example: mySocket := socket( PF_INET, SOCK_STREAM, 0 ); -- open a standard Internet socket procedure connect( result : out integer; socket : integer; addr : in out socketaddr; addrlen : integer ); pragma import( C, connect ); pragma import_valued_procedure( connect ); Connects to a server on the network. socket is the socket to use; addr is the machine and service to connect to; addrlen is the length of the addr record. Returns -1 on an error, 0 for success. Example: connect( result, webserver, webserver'size/8 ); -- connect to the web server described by the webserver record function shutdown( socket, how : integer ) return integer; pragma import( C, shutdown ); Shuts down one or both directions of a socket. This is used, for example, by web browsers to let the server know there are no more HTTP requests being sent. Returns 0 on sucess, -1 on failure. Example: result := shutdown( mysocket, 1 ); procedure bind( result : out integer; myaddr : in out sockaddr, addrlen : integer ); pragma import( C, bind ); pragma import_valued_procedure( bind ); Registers your server on a particular port number with the Linux kernel. addrlen is the length of myaddr. Returns 0 on success, -1 on failure. Example: bind( result, myservice, myservice'size/8 ); function listen( socket : integer; backlog : integer ) return integer; pragma import( C, listen ); pragma import_valued_procedure( listen ); Prepares a socket for your server to listen for incoming connections. Backlog is the maximum number of established

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (38 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

connections that can be queued. Returns 0 on success, -1 on failure. Example: result := listen( mysocket, 10 ); procedure accept( result : out integer; socket : integer; clientaddr : in out sockaddr; addrlen : in out addrlen ); pragma import( C, accept ); pragma import_valued_procuedre( accept ); Returns the next connection to your server. If there are no connections, it waits for a new connection (unless you disabled blocking on the socket.) myaddr is the address of the incoming connection, and addrlen is the size of the address is bytes. addrlen should be initialized to the size of your sockaddr record. You must use listen before accept. Returns -1 on failure, or a new socket with the connection on success. You have to close the new socket when you are finished handling the connection. Example: len := clientaddr'size/8; accept( newsocket, listensocket, clientaddr, len ); This section ends with a demonstration of how to get a web page off the Internet. with Ada.Text_IO, Interfaces.C, System.Address_To_Access_Conversions; use Ada.Text_IO, Interfaces.C; procedure websocket is -- A program to fetch a web page from a server

-- Socket related definitions --- These are the kernel calls and types we need to create -- and use a basic Internet socket. type aSocketFD is new int; -- a socket file descriptor is an integer -- man socket -- make this a new integer for strong typing purposes type aProtocolFamily is new unsigned_short; AF_INET : constant aProtocolFamily := 2; -- Internet protocol PF_Net defined as 2 in -- /usr/src/linux/include/linux/socket.h -- Make this a new integer for strong typing purposes type aSocketType is new int; SOCK_STREAM : constant aSocketType := 1; -- this is for a steady connection. Defined as 1 in -- /usr/src/linux/include/linux/socket.h -- Make this a new integer for strong typing purposes type aNetProtocol is new int; IPPROTO_TCP : constant aNetProtocol := 6; ----The number of the TCP/IP protocol TCP protocol defined as 6 in /etc/protocols See man 5 protocols Make this a new integer for strong typing purposes

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (39 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

type aNetDomain is new integer; PF_INET : constant aNetDomain := 2; -- The number of the Internet domain -- Make this a new integer for strong typing purposes type aInAddr is record addr : unsigned := 0; end record; for aInAddr'size use 96; -- A sockaddr_in record is defined as 16 bytes long (or 96 bits) -- Request Ada to use 16 bytes to represent this record type aSocketAddr is record family : aProtocolFamily := AF_INET; -- protocol (AF_INET for TCP/IP) port : unsigned_short := 0; -- the port number (eg 80 for web) ip : aInAddr; -- IP number end record; -- an Internet socket address -- defined in /usr/src/linux/include/linux/socket.h -- and /usr/src/linux/include/linux/in.h function socket( domain : aNetDomain; stype : aSocketType; protocol : aNetProtocol ) return aSocketFD; pragma import( C, socket ); -- initialize a communication socket. -1 if error procedure bind( result : out int; sockfd : aSocketFD; sa : in out aSocketAddr; addrlen : int ); pragma import( C, bind ); pragma import_valued_procedure( bind ); -- give socket a name. 0 if successful procedure Connect( result : out int; socket : aSocketFD; sa : in out aSocketAddr; addrlen : int ); pragma import( C, connect ); pragma import_valued_procedure( connect ); -- connect to a (Internet) server. 0 if successful procedure Close( fd : aSocketFD ); pragma import( C, close ); -- close the socket, discard the integer result procedure Read( result : out integer; from : aSocketFD; buffer : in out string; buffersize : integer ); pragma import( C, read ); pragma import_valued_procedure( read ); -- read from a socket procedure Write( result : out integer; from : aSocketFD; buffer : system.address; buffersize : integer ); pragma import( C, write );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (40 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

pragma import_valued_procedure( write ); -- write to a socket package addrListPtrs is new System.Address_To_Access_Conversions( System.Address ); -- We need to use C pointers with the address list because this is -- a pointer to a pointer in C. This will allow us to dereference -- the C pointers in Ada. subtype addrListPtr is System.Address; -- easier to read than System.Address type aHostEnt is h_name h_aliases h_addrtype h_length h_addr_list record : System.Address; : System.Address; : int := 0; : int := 0; : addrListPtr;

-------

pointer to offical name of host pointer to alias list host address type (PF_INET) length of address pointer to list IP addresses we only want first one

end record; -- defined in man gethostbyname package HEptrs is new System.Address_To_Access_Conversions( aHostEnt ); -- Again, we need to work with C pointers here subtype aHEptr is System.Address; -- and this is easier to read use HEptrs; -- use makes = (equals) visible function getHostByName( cname : string ) return aHEptr; pragma import( C, getHostByName ); -- look up a host by it's name, returning the IP number function htons( s : unsigned_short ) return unsigned_short; pragma import( C, htons ); -- acronym: host to network short -- on Intel x86 platforms, -- switches the byte order on a short integer to the network -- Most Significant Byte first standard of the Internet procedure memcpy( dest, src : System.Address; numbytes : int ); pragma import( C, memcpy); -- Copies bytes from one C pointer to another. We could probably -- use unchecked_conversion, but the C examples use this. errno : int; pragma import( C, errno ); -- last error number procedure perror( s : string ); pragma import( C, perror ); -- print the last kernel error and a leading C string procedure PutIPNum( ia : aInAddr ) is -- divide an IP number into bytes and display it IP : unsigned := ia.addr; Byte1, Byte2, Byte3, Byte4 : unsigned;
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (41 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

begin Byte4 := IP mod 256; IP := IP / 256; Byte3 := IP mod 256; IP := IP / 256; Byte2 := IP mod 256; Byte1 := IP / 256; Put( Byte4'img ); Put( "." ); Put( Byte3'img ); Put( "." ); Put( Byte2'img ); Put( "." ); Put( Byte1'img ); end PutIPNum; procedure SendHTTPCommand( soc : aSocketFD; cmd : string ) is -- Write a HTTP command string to the socket amountWritten : integer := 0; totalWritten : integer := 0; position : integer := cmd'first; begin loop Write( amountWritten, soc, cmd( position )'address, cmd'length - integer( totalWritten ) ); if amountWritten < 0 then Put_Line( Standard_Error, "Write to socket failed" ); return; end if; Put_Line( "Sent" & amountWritten'img & " bytes" ); totalWritten := totalWritten + amountWritten; position := position + amountWritten; exit when totalWritten = cmd'length; end loop; end SendHTTPCommand; procedure ShowWebPage( soc : aSocketFD ) is -- Read the web server's response and display it to the screen amountRead : integer := 1; buffer : string( 1..80 ); begin -- continue reading until an error or no more data read -- up to 80 bytes at a time while amountRead > 0 loop Read( amountRead, soc, buffer, buffer'length ); if amountRead > 0 then Put( buffer( 1..amountRead ) ); end if; end loop; end ShowWebPage; ServerName: string := "www.adapower.com"; mySocket myAddress : aSocketFD; : aSocketAddr; -- the socket -- where it goes

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (42 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

myServer myServerPtr addrList Result begin

: : : :

aHEptr; -- IP number of server HEptrs.Object_Pointer; addrListPtrs.Object_Pointer; int;

Put_Line( "Socket Demonstration" ); New_Line; Put_Line( "This program opens a socket to a web server" ); Put_Line( "and retrieves the server's home page" ); New_Line; -- initialize a new TCP/IP socket -- 0 for the third param lets the kernel decide Put_Line( "Initializing a TCP/IP socket" ); Put_Line( "Socket( " & PF_INET'img & ',' & SOCK_STREAM'img & ", 0 );" ); mySocket := Socket( PF_INET, SOCK_STREAM, 0 ); if mySocket = -1 then perror( "Error making socket" & ASCII.NUL ); return; end if; New_Line; -- Lookup the IP number for the server Put_Line( "Looking for information on " & ServerName ); Put_Line( "GetHostByName( " & ServerName & ");" ); myServer := GetHostByName( ServerName & ASCII.NUL ); myServerPtr := HEptrs.To_Pointer( myServer ); if myServerPtr = null then Put_Line( Standard_Error, "Error looking up server" ); return; end if; Put_Line( "IP number is" & myServerPtr.h_length'img & " bytes long" ); addrList := addrlistPtrs.To_Pointer( myServerPtr.h_addr_list ); New_Line; -- Create the IP, port and protocol information Put_Line( "Preparing connection destination information" ); myAddress.family := AF_INET; myAddress.port := htons( 80 ); memcpy( myAddress.ip'address, addrlist.all, myServerPtr.h_length ); New_Line; -- Open a connection to the server Put_Line( "Connect( Result, Socket, Family/Address rec, F/A rec size )" );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (43 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Connect( Result, mySocket, myAddress, myAddress'size/8 ); Put( "Connect( " & Result'img & "," ); Put( myAddress.family'img & "/" ); PutIPNum( myAddress.ip ); Put( "," & integer'image( myAddress'size / 8 ) & ")" ); if Result /= 0 then perror( "Error connecting to server" & ASCII.NUL ); return; end if; New_Line; -----Write the request "GET" returns a web page from a web server Also send minimal HTTP header using User-Agent Followed with a blank line to indicate end of command

Put_Line( "Transmitting HTTP command..." ); SendHTTPCommand( mySocket, "GET /index.html HTTP/1.0" & ASCII.CR & ASCII.LF & "User-Agent: WebSocket/1.0 (BigBookLinuxAda Example)" & ASCII.CR & ASCII.LF & ASCII.CR & ASCII.LF ); New_Line; -- read web page back Put_Line( "---Web Page / Server Results-------------------------" ); ShowWebPage( mySocket ); Put_Line( "-----------------------------------------------------" ); -- close the connection Put_Line( "Closing the connection" ); close( mySocket ); Put_Line( "Demonstration finished - have a nice day" ); end websocket;

Socket Demonstration This program opens a socket to a web server and retrieves the server's home page Initializing a TCP/IP socket Socket( 2, 1, 0 ); Looking for information on www.adapower.com GetHostByName( www.adapower.com); IP number is 4 bytes long Preparing connection destination information

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (44 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Connect( Result, Socket, Family/Address rec, F/A rec size ) Connect( 0, 2/ 216. 92. 66. 46, 16) Transmitting HTTP command... Sent 81 bytes ---Web Page / Server Results------------------------HTTP/1.0 200 OK Date: Wed, 29 Mar 2000 02:32:56 GMT Server: Apache/1.3.3 Last-Modified: Thu, 11 Nov 1999 02:03:14 GMT Etag: "1f31-406-382a23e2" Accept-Ranges: Bytes Content-Length: 1030 Content-Type: text/html Age: 39 Via: HTTP/1.0 csmc2 (Traffic-Server/3.0.3 [uScHs f p eN:t cCHi p s ]) <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <HTML> <HEAD> <META NAME="author" CONTENT="David Botton">> <META NAME="keywords" CONTENT="Ada AdaPower power source code free treasury repository"> <META NAME="description" CONTENT="The Ada Source Code Treasurey contains components, procedures, algorithms and articles for Ada developers."> <META http-equiv="Page-Enter" CONTENT="revealtrans(duration=2.0, transition=3)"> <TITLE>AdaPower.com</TITLE> <LINK href="mailto:[email protected]" rev="made"> </HEAD> <FRAMESET COLS="120,*" FRAMEBORDER=0 FRAMESPACING=0 BORDER=0> <FRAME SRC="buttons.html" name="menu" frameborder=0 marginheight=0 marginwidth=0 noresize scrolling=auto border=0> <FRAME SRC="http://www.adapower.com/body.html" name="body" frameborder=0 marginheight=5 marginwidth=0 noresize scrolling=auto border=0> <NOFRAMES> <meta HTTP-EQUIV="REFRESH" CONTENT="0; URL="body.html"> <body bgcolor="#ffffff" text="#000000"> <a href="body.html">Click here</a> </BODY> </BODY> </NOFRAMES> </FRAMESET> </HTML> ----------------------------------------------------Closing the connection Demonstration finished - have a nice day

16.24 Memory Management


type aProtection is new integer; type aMapFlag is new integer; function getpagesize return long_integer; pragma import( C, getpagesize );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (45 of 47) [7/20/2001 11:37:17 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

Return the size of a Linux memory page (that is, the size of the memory blocks that your program and data are broken up into when loaded into memory). function mmap( start : system.address; size : long_integer; prot : aProtection; flags : aMapFlag; fd : integer; offset : long_integer ) return system.address; pragma import( C, mmap ); Allocates size bytes of memory and returns a C pointer. If it failed, -1 is returned. If MAP_FIXED and start are used, the memory will be at the specified address. The protection flags indicate how the memory will be accessed: a signal will be raised on an illegal access. If MAP_ANON is used, fd should be -1 and no file will be associated with the memory, otherwise fd is a file that will be copied into the block of memory and offset indicates how many bytes into the file the copying should take place. function munmap( start : system.address; size : long_integer ) return integer; pramga import( C, munmap ); Deallocate memory allocated by mmap. Returns -1 on an error. function mremap( old_start : system.address; old_size : long_integer; new_size : long_integer; flags : aMapFlag) return system.address; pragma import( C, mremap ); Changes the size of a block of memory allocated by mmap, possibly moving it. function mprotect( start : system.address; size : long_integer; new_prot : aProtection ) return integer; pragma import( C, mprotect ); Change the protection settings on a block of memory allocated by mmap. Returns -1 on an error. Other mmap flags: PROT_NONE PROT_READ PROT_WRITE PROT_EXEC MAP_SHARED processes any) MAP_PRIVATE : : : : constant constant constant constant aProtection aProtection aProtection aProtection := := := := 0; 1; 2; 4; ----shorthand for no access read access allowed write access allowed execute access allowed

: constant aMapFlag := 16#01#;

-- share changes with child -- (write changes to the file, if

: constant aMapFlag := 16#02#; constant aMapFlag := 16#10#; constant aMapFlag := 16#20#; constant constant constant constant constant constant aMapFlag aMapFlag aMapFlag aMapFlag aMapFlag aMapFlag := := := := := := MAP_ANON; 16#0100#; 16#0800#; 16#1000#; 16#2000#; 16#4000#;

MAP_FIXED : MAP_ANON : file MAP_ANONYMOUS : MAP_GROWSDOWN : MAP_DENYWRITE : MAP_EXECUTABLE: MAP_LOCKED : MAP_NORESERVE :

-----------

separate copy for child processes (changes kept in memory, if any) use specified address just alloc memory, no related another name for MAP_ANON stack-line usage write lock the file mark as executable don't swap out memory don't check for reservations

function msync( start : system.address; size : length; flags : aMSyncFlag ) return integer; pragma import( C, msync ); Updates the file associated with the memory allocated by mmap. Returns -1 on an error.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (46 of 47) [7/20/2001 11:37:18 AM]

Big Online Book of Linux Ada Programming - 16 Advanced Linux Programming

MS_ASYNC : constant aSyncFlag := 1; MS_INVALIDATE: constant aSyncFlag := 2; MS_SYNC : constant aSyncFlag := 4;

-- request memory to be saved soon -- mark cache as needing updating -- save memory to file immediately

function mlock( start : system.address; size : long_integer ) return integer; pragma import( C, mlock ); Deny page swapping on this block of memory allocated by mmap. Only a superuser process may lock pages. Returns -1 on an error. function munlock( start : system.address; size : long_integer) return integer; pragma import( C, munlock ); Allow page swapping on this block of memory allocated by mmap. Returns -1 on an error. function mlockall( flags : aLockFlag ) return integer; pragma import( C, mlockall ); Deny swapping on all memory for this process. Only a superuser process can lock memory. Returns -1 on an error. function munlockall return integer; pragma import( C, mlockall ); Allow swapping on all memory for this process. Returns -1 on an error. MCL_CURRENT : constant aLockFlag := 1; -- lock current blocks MCL_FUTURE : constant aLockFlag := 2; -- lock subsequent blocks function brk( end_data_segment : system.address ) return integer; pragma import( C, brk ); Resize the (Intel) data segment to the specified ending address. Returns -1 on an error. procedure sbrk( increment : long_integer ); pragma import( C, sbrk ); Increase the (Intel) data segment by the specified number of bytes.

16.25 Exit Procedures


procedure C_exit; pragma import( C, C_exit, "exit" ); pragma import_valued_procedure( C_exit ); exit is a C a standard C library function that closes all your standard C library files and stops your program. This procedure is meant to be used by C. It is not recommended in an Ada program. procedure K_exit; pragma import( C, K_exit, "_exit" ); pragma import_valued_procedure( K_exit ); _exit is a kernel call to stop your program. It leaves any open file open. Not recommended in an Ada program: there are more effective ways to stop your program.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/16.html (47 of 47) [7/20/2001 11:37:18 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

17 Moving C Programs To Ada


<--Last Chapter Table of Contents Next Chapter-->

17.1 c2ada: Translating Your Programs c2ada is available from http://www.skinner.demon.co.uk/aidan/programming/ 17.2 Interfaces.C package

Ada Package Description int unsigned long_long etc

C Equivalent

C integer int C unsigned integer unsigned char [n] long long C long long

char_array(n) C character array

The Interfaces.C and Interfaces.C.Extensions packages provide basic type definitions and conversions functions for C programs. Gnat 3.12 introduces a new boolean type, C_bool, which behaves as a proper C boolean value: 0 is false and any other value is true. One thing to remember about this package is that C strings are defined as an array of characters, and Ada will raise a CONSTRANT_ERROR exception if two arrays of characters are not exactly equal length, even if a smaller array is being assigned to a larger one. For example, s : char_array( 1..80 ) := To_C( "Fred Smith" ); -- bad This example will raise the exception because the string is 11 characters long (10 characters plus a null character), but the array being assigned to is 80 characters. You can get around these kind of errors with dynamic allocation. The following program demonstrates some of the types and functions in the Interfaces.C packages. with text_io, unchecked_deallocation, Interfaces.C.Extensions;

use text_io, Interfaces.C, interfaces.C.Extensions; procedure ctest is -- my types --- pointer to C string and deallocation procedure for same

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (1 of 11) [7/20/2001 11:37:38 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

type stringptr is access all char_array; procedure free is new unchecked_deallocation( char_array, stringptr ); -- types from standard Ada package Interfaces.C i u l ul c sp f d wc : : : : : : : : : int; unsigned; long; unsigned_long; char; stringptr; C_float; double; wchar_t; ---------integer unsigned integer long unsigned long a character ptr to a string (array of characters) a float a double 16-bit wide character

-- additional types from Gnat package Interfaces.C.Extensions ll : long_long; -- long long ull: unsigned_long_long; -- unsigned long long vp : void_ptr; -- void pointer begin Put_Line( "This is an example of Interfaces.C" ); New_Line; sp := new char_array'( To_C( "This is a string" ) ); Put_Line( "The C string s is '" & To_Ada( sp.all ) & "'." ); Free( sp ); end ctest;

This is an example of Interfaces.C The C string s is 'This is a string'.

17.3 Interfaces.C.Pointers Package


One C feature that Ada programs lack is pointer arithmetic. In C, you can move pointers forward and backwards through an array by using simple arithmetic operations. For example, adding two to an character pointer move the pointer two characters forward in a string. Decrementing an integer pointer moves the pointer back one index position in an integer array. Since pointer arithmetic is important in many C programs, especially sorts, Ada 95 provides a standard generic package called Interfaces.C.Pointers which implements access types that can use pointer arithmetic. To instantiate the package, you need to specify the elements that will be in your arrays, an unbounded array that will contain the elements, the range of index values, and a default terminator value used by some of the package's subprograms. For example, to create C-style pointers for the unbounded Char_Array (C string) type in Interfaces.C, you could instantiate the package with

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (2 of 11) [7/20/2001 11:37:38 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

package StringPtrs is new Interfaces.C.Pointers( Index => size_t, -- the index range is size_t Element => char, -- the array contains chars Element_Array => char_array, -- the unbounded type Default_Terminator => char'val( 0 ) -- the terminator value, ASCII.NUL ); use StringPtrs; -- need this to make + and - visible strptr : StringPtrs.Pointer; The use clause is very important. Without it, the arithmetic operators would not be directly available because they would be hidden inside the StringPtrs package. Pointers created using Interfaces.C.Pointers are access types, and can be used like any other access type. Put_Line( "strptr is pointing to the character " & strptr.all ); However, unlike other access types, they have new pointer arithmetic features. Addition and subtraction is performed the same way as in C by specifying how many positions in the array to move. To move strptr ahead 2 index positions in a string, add 2 to it: strptr := strptr + 2; Since Ada has no increment or decrement operators, two procedures are provided to move a pointer forward or backward by one array position: Increment( strptr ); -- forward one position Decrement( strptr ); -- back one position The package also makes four additional subprograms available: The Virtual_Length function returns the length of an array, up to end of the array or until a terminator is found. [If no terminator, do you get a storage error?--KB] The Value function returns a slice from the array, from the position of the pointer to the end of the array or until a terminator is found. It can also slice a specific number of elements from an array. Copy_Array copies a slice of a specific number of elements from one pointer to another. Copy_Terminated Array copies a slice from the pointer position until a terminator is found. The following program demonstrates C pointers to integer arrays. with Ada.Text_IO, Interfaces.C.Pointers; use Ada.Text_IO; procedure point is -------To use Interfaces.C.Pointers, you need to define an unbounded array type. In this case, we'll create an unbounded array called IntegerArrays with a maximum index range of 1 to 9. BiggestArray is the largest IntegerArrays array possible, with an index range of 1 to 9. IntegerArrays must have aliased elements because we will be accessing them with an access type.

subtype PointerRange is integer range 1..9; type IntegerArrays is array PointerRange range <> ) of aliased integer;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (3 of 11) [7/20/2001 11:37:38 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

type BiggestArray is new IntegerArrays( PointerRange ); package IntPtrs is new Interfaces.C.Pointers( Index => PointerRange, -- the index range Element => Integer, -- what the array contains Element_Array => IntegerArrays, -- the unbounded type Default_Terminator => 0 ); -- the terminator value use IntPtrs; -- need this to make + and - visible procedure ShowArray( ia : IntegerArrays ) is -- show the contents of any IntegerArrays array begin for i in ia'first..ia'last-1 loop Put( i'img ); Put( " =>" ); Put( ia( i )'img ); Put( "," ); end loop; Put( ia'last'img ); Put( " => " ); Put_Line( ia( ia'last )'img ); end ShowArray; ia, ia2 : BiggestArray; -- two integer arrays ip, ip2 : IntPtrs.Pointer; -- two pointers to integer arrays begin Put_Line( "This program demonstrates C-style pointers provided" ); Put_Line( "by Interfaces.C.Pointers" ); New_Line; -- initialize and display the contents of the array for i in PointerRange'first..PointerRange'last-1 loop ia( i ) := i*2; end loop; ia( PointerRange'last ) := 0; Put_Line( "The array is: " ); ShowArray( IntegerArrays( ia ) ); -- must typecast ia because ShowArray is expecting an IntegerArrays Put_Line( "Zero is our terminator in this example" ); New_Line; -- set the pointers to the first elements in the arrays

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (4 of 11) [7/20/2001 11:37:38 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

ip := ia( ia'first )'access; ip2 := ia2( ia'first )'access; -- ip works like a normal access type Put_Line( "Our pointer is set to first position in the array"); Put_Line( "The element is " & ip.all'img ); New_Line; -- increment example Increment( ip ); Put_Line( "Incrementing the pointer, it now points at " & ip.all'img ); New_Line; -- decrement example Decrement( ip ); Put_Line( "Decrementing the pointer, it now points at" & ip.all'img ); New_Line; -- addition example ip := ip + 3; Put_Line( "Addition moves the pointer forward." ); Put_Line( "Moving forward three elements, it now points at" & ip.all'img ); New_Line; -- subtraction example ip := ip - 2; Put_Line( "Subtraction moves the pointer backwards." ); Put_Line( "Moving backwards two elements, it now points at" & ip.all'img ); New_Line; -- Virtual_Length examples Put_Line( "Virtual_Length gives the length from the pointer to the" ); Put_Line( "default terminator. The length from this position is" & Virtual_Length( ip )'img & " positions" ); Put_Line( "Virtual_Length can also use an arbitrary terminator." ); Put_Line( "The length from the pointer to the first 14 is" & Virtual_Length( ip, 14 )'img & " positions" ); New_Line; -- Value examples Put_Line( "Value returns the array slice from the pointer position to" ); Put_Line( "the terminator. The array value from this position is" ); ShowArray( Value( ip ) );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (5 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

Put_Line( "Value can also return a slice of a specific length." ); Put_Line( "The next four elements are" ); ShowArray( Value( ip, Length => 4 ) ); New_Line; -- Copy_Terminated_Array example Put_Line( "Our second array contains" ); ShowArray( IntegerArrays( ia2 ) ); -- must typecast here New_Line; Put_Line( "Copy_Terminated_Array copies elements from one pointer to" ); Put_Line( "another, up to and including the terminator. Copying to" ); Put_Line( "the second array " ); Copy_Terminated_Array( ip, ip2 ); ShowArray( IntegerArrays ( ia2 ) ); -- must typecast here New_Line; -- Copy_Array example Put_Line( "Copy_Array copies a specific number of elements."); Put_Line( "Copying 4 elements from 3 positions ahead, the new"); Put_Line( "array contains" ); Copy_Array( ip+3, ip2, 4 ); ShowArray( IntegerArrays( ia2 ) ); -- must typecast here New_Line; end point;

This program demonstrates C-style pointers provided by Interfaces.C.Pointers The array is: 1 => 2, 2 => 4, 3 => 6, 4 => 8, 5 => 10, 6 => 12, 7 => 14, 8 => 16, 9 => 0 Zero is our terminator in this example Our pointer is set to first position in the array The element is 2 Incrementing the pointer, it now points at 4 Decrementing the pointer, it now points at 2 Addition moves the pointer forward. Moving forward three elements, it now points at 8 Subtraction moves the pointer backwards. Moving backwards two elements, it now points at 4

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (6 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

Virtual_Length gives the length from the pointer to the default terminator. The length from this position is 7 positions Virtual_Length can also use an arbitrary terminator. The length from the pointer to the first 14 is 5 positions Value returns the array slice from the pointer position to the terminator. The array value from this position is 1 => 4, 2 => 6, 3 => 8, 4 => 10, 5 => 12, 6 => 14, 7 => 16, 8 => 0 Value can also return a slice of a specific length. The next four elements are 1 => 4, 2 => 6, 3 => 8, 4 => 10 Our second array contains 1 => 12, 2 => 134531961, 3 => 12, 4 => 1, 5 => 134560412, 6 => 134891560, 7 => 134575980, 8 => 0, 9 => 134560432 Copy_Terminated_Array copies elements from one pointer to another, up to and including the terminator. Copying to the second array 1 => 4, 2 => 6, 3 => 8, 4 => 10, 5 => 12, 6 => 14, 7 => 16, 8 => 0, 9 => 134560432 Copy_Array copies a specific number of elements. Copying 4 elements from 3 positions ahead, the new array contains 1 => 10, 2 => 12, 3 => 14, 4 => 16, 5 => 12, 6 => 14, 7 => 16, 8 => 0, 9 => 134560432

17.4 Interfaces.C_Streams package


Ada Package fopen fclose fread etc. Description Open a text file (C stream) Close a text file (C stream) Read bytes from a text file (C stream) C Equivalent fopen fclose fread

Although the basic Ada types are identical to their C counterparts, the IO libraries are not guaranteed to write data in a format that is readable from other languages. Text files are fine, but to write binary files that can be accessed by C, you'll need to read and write the files using C file handing libraries. The Interfaces.C_Streams package provides a thin binding to the C stdio library. This is comparable to the gnat.os_lib library, but the binding is "thinner" and covers all C stream operations. Some stdio library functions aren't covered because they can't be represented by Ada. Gnat guarantees these functions will be available, no matter what platform gnat is running under, even if it isn't UNIX-based. It is also possible to call stdio directly. See the discussion above. c_streams uses "stream" to refer to a Linux text file. procedure clearerr(stream : FILEs); Clear any error associated with the stream.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (7 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

function fclose(stream : FILEs) return int; Close a stream. function fdopen(handle : int; mode : chars) return FILEs; Open a stream by a handle (UNIX file descriptor). function feof(stream : FILEs) return int; Check for the end of stream. function ferror(stream : FILEs) return int; Return any error associated with the last stream operation. functionfflush(stream : FILEs) return int; Finish writing any outstanding data to the stream. function fgetc(stream : FILEs) return int; Read one character from the stream. Characters will be ASCII values between 0 and 255, and can be converted to a character with character'val. function fgets(strng : chars; n : int; stream : FILEs) return chars; Read a string from the stream. Note this is not an Ada string. function fileno(stream : FILEs) return int; Return the fine number associated with a stream for use with standard Linux file operations. function fopen( filename : chars; Mode : chars) return FILEs; Open a stream. function fputc(C : int; stream : FILEs) return int; Write one character to a stream. Convert the character to an integer using character'val. function fputs(Strng : chars; Stream : FILEs) return int; Write a string of characters to the stream. function fread( buffer : voids; size : size_t; count : size_t; stream : FILEs) return size_t; Read count bytes into a buffer of length size and return number of bytes actually read. function freopen( filename : chars; mode : chars; stream : FILEs) return FILEs; Reopen the stream with a new mode. function fseek( stream : FILEs; offset : long; origin : int) return int; Move offset bytes from the specified origin point. function ftell(stream : FILEs) return long; Get stream offset for fseek. function fwrite( buffer : voids; size : size_t; count : size_t; stream : FILEs) return size_t; Write count bytes from a buffer of count length and return the number of bytes actually written. function isatty(handle : int) return int; [NQS--determine if stream is a TTY device?--KB] procedure mktemp(template : chars); Create a random name for a temporary file. procedure rewind(stream : FILEs); Move to the start of the stream. function setvbuf(stream : FILEs; buffer : chars; mode : int; size : size_t) return int;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (8 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

[NQS--used to know what this did--KB] procedure tmpnam(string : chars); [Difference with tmpnam?--KB] The parameter must be a pointer to a string buffer of at least L_tmpnam bytes (the call with a null parameter is not supported). function tmpfile return FILEs; [NQS--KB] function ungetc(c : int; stream : FILEs) return int; Back up one character in the stream. function unlink(filename : chars) return int; Delete a stream file. The following are related utility functions added by ACT. They are not standard UNIX functions like the above. function file_exists(name : chars) return int; Returns 0 if a file doesn't exist, 1 if it does. function is_regular_file(handle : int) return int; Return 1 if given handle is for a regular file, or 0 for some other kind of file. procedure set_binary_mode( handle : int); Read text without translation. Only works if compiled with text_translation_required. procedure set_text_mode( handle : int); Translate text. Only works if compiled with text_translation_required. procedure full_name(nam : chars; buffer : chars); Return the full path of a file as a C string. The following program demonstrates some of the c_stream functions. with text_io, unchecked_deallocation, Interfaces.C_Streams; use text_io, Interfaces.C_Streams; procedure cstreamtest is fd : FILEs; line2write : constant string := "This is a test"; cline2write: constant string := "This is a test" & ASCII.NUL; path : constant string := "testfile.xxx"; cpath : constant string := path & ASCII.NUL; fileMode : constant string := "w"; amountWritten : size_t; result : int; begin Put_Line( "This is an example of Interfaces.C_Streams" ); New_Line; fd := fopen( cpath'address, fileMode'address ); if ferror( fd ) = 0 then Put_Line( "Opened " & path & " with fopen"); Put_Line( "Writing '" & line2write & "' with fwrite" );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (9 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

amountWritten := fwrite( line2write'address, -- what to write 1, -- size of elements line2write'length, -- how many to write fd ); -- to which file Put_Line( New_Line; Put_Line( result := Put_Line( New_Line; "Wrote" & amountWritten'img & " characters" ); "Writing with fputs" ); fputs( cline2write'address, fd ); "Result was" & result'img );

result := fclose( fd ); Put_Line( "Closed " & path & " with fclose"); Put_Line( "Result was" & result'img ); New_Line; result := unlink( cpath'address ); Put_Line( "Deleted " & path & " with unlink"); Put_Line( "Result was" & result'img ); end if; end cstreamtest;

This is an example of Interfaces.C_Streams Opened testfile.xxx with fopen Writing 'This is a test' with fwrite Wrote 14 characters Writing with fputs Result was 1 Closed testfile.xxx with fclose Result was 0 Deleted testfile.xxx with unlink Result was 0

17.5 Ada and C Files


Gnat provides several interfacing packages to allow Ada to read and write C files. These are a "thicker binding" than Interfaces.C_Streams. q Ada.Direct_IO.C_Streams - a variation of Ada.Direct_IO of reading and writing C direct files. q Ada.Sequential_IO.C_Streams - a variation of Ada.Sequential_IO for reading and writing C sequential files q Ada.Streams_Stream_IO.C_Streams - a package for reading and writing C streams q Ada.Text_IO.C_Streams - a package for reading and writing C text files q Ada.Wide_Text_IO.C_Streams - a package for reading and writing 16-bit character C text files

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (10 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 17 Moving C Programs To Ada

17.6 A Word on Interfaces.Fortran


Gnat provides interfacing packages for languages besides C. Interfaces.Fortran contains types and subprograms to link Fortran language programs to your Ada programs. The GCC Fortran 77 compiler is g77. As with gcc, most of the A Fortran real variable, precision variable is an portability is an issue, Fortran data types correspond identically with an Ada type. for example, is the same as an Ada float, and a double Ada long_float. Other Ada compilers may not do this: if always use the types of Interfaces.Fortran.

Gnat 3.12 introduces a proper Fortran logical type that behaves according to Fortran semantics. Fortran subprograms may be imported into Ada using pragma import: procedure MyFortranSubroutine; pragma import( Fortran, MyFortranSubroutine ); Variables may be likewise imported. RealVar : float; pragma import( Fortran, RealVar ); g77 adds an undescore to subroutine names, so ifyou are importing from g77 you'll need to include the name of the subroutine with a trailing underscore in pragma import. pragma import (Fortran, MyFortranSubroutine, "MyFortranSubroutine_");

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/17.html (11 of 11) [7/20/2001 11:37:39 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

18 Data Structures
<--Last Chapter Table of Contents Next Chapter-->

Good programmers write good programs. Great programmers write good programs and good data structures. Organizing your data is as important as the program that crunches the data and produces a result. Unfortunately, my experiences in the corporate world have taught me that that the only data structure used is the single dimensional array. When results are the only goal and more processing power is the cure for bad software design, arrays are easy to implement (they are built into Ada). Even the worst programmer knows how to use an array. And arrays are easy to understand. Try to use a linked list, and a programmer can get into trouble with his boss for using risky, "advanced" technology. Alternatively, programmers will sometimes rely on the complexity and overhead of databases when a simplier solution using the correct data structure would be faster and easier to implement. If you are lucky enough to work for a company that uses more than arrays, this chapter will discuss how to use other kinds of data structures in Ada.

18.1 Using the Booch Components


Like Ada, C++ has no advanced data structures built into the language. To provide a standard set of data structures, what is now called the Standard Template Library was developed to provide the tools necessary to organize most types of data. Perhaps because of an oversight, Ada 95 with all its annexes has no equivalent to the C++ Standard Template Library. There are no standard packages providing common data structures. The Gnat compiler fills part of this void with packages for creating simple tables and hash tables. The Booch components are a set of C++ objects created by Grady Booch. These were later ported to Ada 95. The components contain sets of general purpose data structures. The Booch components are available from AdaPower.Net or in RPM format from the Ada Linux Team. This is one popular choice for Ada's unofficial "Standard Template Library". The components are organized into three main categories: tools, support and structs. The tools cover many items already implemented in the standard Ada or Gnat packages, such as searching, sorting and pattern recognition. Support refers to components that implement the tools and structs. The structs (data structures) are the primary interest of Ada programmers. These are further subcategorized by the user's requirements: bounded (where the size is known at compile-time or there's no heap allocation), unbounded (using dynamic allocation and item caching), or the dynamic (a compromize between bounded and unbounded). The default if no others are available is unbounded. Dynamic and unbounded types can specify a storage manager to use. The storage manager is a program that allocates memory. Use Global_Heap package if you have no preference. Unbounded structures allocate memory whenever a new item is added to the structure. Dynamic structures allocate memory in fixed-sized chunks. Each chunk is large enough for several items. The chunk size is set when the dynamic data structure is first created, but it can be altered at any time. When a chunk is full, the structure is grows by the size of another chunk. This reduces the number of memory allocations to improve performance. Each dynamic structure includes these subprograms: q Create - Change the chunk size for the collection q Set_Chunk_Size - Change the chunk size for the collection
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (1 of 26) [7/20/2001 11:38:16 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures


q q

Preallocate - Increase the size of the collection immediately Chunk_Size - Returns the current chunk size

The Booch components are organzied in a hierarchy of packages. The BC package is the top-most package. BC defines the basic execptions that can be raised by the various components: Container_Error : exception; Duplicate : exception; Illegal_Pattern : exception; Is_Null : exception; Lexical_Error : exception; Math_Error : exception; Not_Found : exception; Not_Null : exception; Not_Root : exception; Overflow : exception; Range_Error : exception; Storage_Error : exception; Synchronization_Error : exception; Underflow : exception; Should_Have_Been_Overridden : exception; Not_Yet_Implemented : exception; The data structure components are: Data Structure Booch Packages Description Unordered collection of items. Duplicates are counted but not actually stored. Ordered collection of items. Duplicates are allowed and stored. Double-ended queues A sequence of 0 or more items with a head and a pointer to each successive item. A sequence of 0 or more items with a head and a pointer to both successive and previous items.

Bags

bc-containers-bags-bounded bc-containers-bags-dynamic bc-containers-bags-unbounded

Collections

bc-containers-collections-bounded bc-containers-collections-dynamic bc-containers-collections-unbounded bc-containers-deques-bounded bc-containers-deques-dynamic bc-containers-deques-unbounded

Deques

Single linked bc-containers-lists-single Lists

Double linked Lists

bc-containers-lists-double

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (2 of 26) [7/20/2001 11:38:16 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

Maps

bc-containers-maps-bounded bc-containers-maps-dynamic bc-containers-maps-unbounded bc-containers-queues-bounded bc-containers-queues-dynamic bc-containers-queues-unbounded bc-containers-queues-ordered-bounded bc-containers-queues-ordered-dynamic bc-containers-queues-ordered-unbounded bc-containers-rings-bounded bc-containers-rings-dynamic bc-containers-rings-unbounded bc-containers-sets-bounded bc-containers-sets-dynamic bc-containers-sets-unbounded bc-containers-stacks-bounded bc-containers-stacks-dynamic bc-containers-stacks-unbounded bc-containers-trees-avl

A set with relationships between pairs of items. First in, first out list. A sorted list, items removed from the front. A deque with only one endpoint. Unordered collection of items. Duplicates are not allowed. Last in, first out list. Balanced binary trees A list with two successors per item. Tree with an arbitrary number of children. Groups of items with one-way relationships Groups of items with two-way relationships Access types that automatically deallocate themselves

Queues Ordered (Priority) Queues Rings

Sets

Stacks AVL Trees

bc-containers-trees-binary-in_order Binary Trees bc-containers-trees-binary-post_order bc-containers-trees-binary-pre_order Multiway Trees Directed Graphs Undirected Graphs bc-containers-trees-multiway-post_order bc-containers-trees-multiway-pre_order bc-graphs-directed

bc-graphs-undirected

Smart Pointers

bc-smart

A definition of common data structures can be found at the National Institute of Standards and Technology. The components are generic packages and must be instantiated for a particular type. They are arranged in hierarchies of generic packages. Each parent package must be instantiated before its child. For example, to use single linked lists (bc.containers.lists.single), bc.containers, bc.containers.lists, and bc.containers.lists.single must all be be created for the item type. As with many component libraries, the Booch components represent all structures in memory, not in long-term storage. They cannot be used to create disk files, although the data could be saved to disk and reloaded later. 18.1.1 Containers

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (3 of 26) [7/20/2001 11:38:16 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

Containers form the cornerstone of the Booch components. Containers are a controlled tagged record that encloses an item. The Booch components are composed of items stored in containers that are arranged in different ways. To use any of the Booch components, a container must be instantiated to hold your item. For example, to create a new package to manage character in containers, use package charContainers is new BC.Containers (Item => Character); 18.1.2 Iterators The Container package also manages the iterators used by the Booch components. An iterator is a variable that keeps track of the position in a data structure during a traversal. Iterators are created by New_Iterator in a data structure's package, but the subprograms that work with the iterator are defined in the Container package. q Reset - start a new traversal at the first item q Next - continue to another item in the component q Is_Done - True if there are no more items q Current_Item - return the current item The Is_Done function indicates when all items have been traversed. When Is_Done is true, Current_Item is undefined. In other words, the program must loop through all items in the list, plus 1, before Is_Done is true. Because an Iterator is a class-wide type, it must be assigned a new value when it is declared to avoid a compiler error. i : charContainers.Iterator'class := charList.New_Iterator( customers ); 18.1.3 Single linked Lists Creating a single linked list requires the instantiation of 3 separate generic packages: BC.Containers, BC.Containers.Lists, and BC.Containers.Lists.Single. To avoid problems with access types, these should be declared globally (that is, in a package spec). First, a container must be defined to hold the item you want to store in your linked list. package Containers is new BC.Containers (Item => Character); Second, basic operations on lists must be instantiated. package Lists is new Containers.Lists; Finally, the single linked list package must be instantiated. For an unbounded package, you chose a storage pool to use. Single linked lists are always unbounded. Use Global_Heap if you have no preference. package LS is new Lists.Single (Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage); The single linked list package provides the following subprograms: q Clear - destroy the list q Insert - add an item to the list q Append - add an item to the end of the list q Remove - remove an item from the list q Purge - remove consecutive items
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (4 of 26) [7/20/2001 11:38:16 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures


q q q q q q q q q q q q

Preserve - inverse of Purge, keep consecutive items, removing the rest Share/_Head/_Foot - make the list an alias for a sublist in another list Tail - discard everything but the last item in the list Length - return the number of items in the list Is_Null - true if the list has no items Is_Shared - true if there an alias to a sublist in the list Head - return the top-most item Foot - return the last item in the list Item_at - return an item at a given position New_Iterator - return an iterator for traversing the list Process_Head/Tail - generic procedure to return an item with processing Swap_Tail - NQS-KB

Notice that the term "Foot" refers to the last item in the list. The Ada string packages uses the term "Tail". Here's an example: with BC.Containers.Lists.Single; with Global_Heap; package customers is type aCustomer is record customerID : integer; accountBalance : float; end record; -- this is the item to put in the list package customerContainers is new BC.Containers (Item => aCustomer); -- create a new controlled tagged record container for customers package customerLists is new customerContainers.Lists; -- create a new list support package for our using container type package customerList is new customerLists.Single (Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage); -- create a single linked list package using the lists support -- customized for our container type end customers;

with ada.text_io, BC, customers; use ada.text_io, BC, customers; procedure list_demo is customers : customerList.Single_List; c : aCustomer; i : customerContainers.Iterator'class := customerList.New_Iterator( customers ); begin Put_Line( "This is a demo of the Booch components: single-linked lists" );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (5 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

New_Line; -- The Newly Declared List Put_Line( Put_Line( Put_Line( Put_Line( New_Line; "The "The "The "The list list list list is newly declared." ); is empty? " & customerList.Is_Null( customers )'img ); is shared? " & customerList.Is_Shared( customers )'img ); length is" & customerList.Length( customers )'img );

-- Inserting a customer c.customerID := 7456; c.accountBalance := 56.74; customerList.Insert( customers, c ); Put_Line( Put_Line( Put_Line( Put_Line( "Added customer" & c.customerID'img ); "The list is empty? " & customerList.Is_Null( customers )'img ); "The list is shared? " & customerList.Is_Shared( customers )'img ); "The list length is" & customerList.Length( customers )'img );

c := customerList.Head( customers ); Put_Line( "The head item is customer id" & c.customerID'img ); c := customerList.Foot( customers ); Put_Line( "The foot item is customer id" & c.customerID'img ); New_Line; -- Apending a customer c.customerID := 9362; c.accountBalance := 88.92; customerList.Append( customers, c ); Put_Line( "Appended customer" & c.customerID'img ); Put_Line( "The list length is" & customerList.Length( customers )'img ); c := customerList.Head( customers ); Put_Line( "The head item is customer id" & c.customerID'img ); c := customerList.Foot( customers ); Put_Line( "The foot item is customer id" & c.customerID'img ); New_Line; -- Iterator example Put_Line( "Resetting the iterator.." ); customerContainers.Reset( i ); c := customerContainers.Current_item ( i ); Put_Line( "The current item is customer id" & c.customerID'img ); Put_Line( "Are we done? " & customerContainers.Is_Done( i )'img ); Put_Line( "Advancing to the next item..." ); customerContainers.Next( i ); c := customerContainers.Current_item ( i ); Put_Line( "The current item is customer id" & c.customerID'img ); Put_Line( "Are we done? " & customerContainers.Is_Done( i )'img );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (6 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

Put_Line( "Advancing to the next item..." ); customerContainers.Next( i ); Put_Line( "Are we done? " & customerContainers.Is_Done( i )'img ); begin c := customerContainers.Current_item ( i ); exception when BC.NOT_FOUND => put_line( "BC.NOT_FOUND exception: no item at this position in the list" ); end; end list_demo;

This is a demo of the Booch components: single-linked lists The The The The list list list list is newly declared. is empty? TRUE is shared? FALSE length is 0

Added customer 7456 The list is empty? FALSE The list is shared? FALSE The list length is 1 The head item is customer id 7456 The foot item is customer id 7456 Appended The list The head The foot customer 9362 length is 2 item is customer id 7456 item is customer id 9362

Resetting the iterator.. The current item is customer id 7456 Are we done? FALSE Advancing to the next item... The current item is customer id 9362 Are we done? FALSE Advancing to the next item... Are we done? TRUE BC.NOT_FOUND exception: no item at this position in the list Single linked lists should not be Guarded. 18.1.4 Double linked Lists Double linked lists are implemented exactly the same as single-linked lists except that the word "Double" is substituted for the word "Single". Double linked lists are useful for lists that must be browsed backwards and forwards continuously. Double linked lists should not be Guarded. 18.1.5 Bags Bags, like linked lists, are collections of items. However, there is no attempt to order the items. Duplicate items can be stored, but the bag keeps a count of duplications to save memory instead of storing copies of the duplicates.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (7 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

The bags package provides the following subprograms: q Are_Equal - True if two bags have the same contents q Clear - Removes all items from the bag q Add - Adds an item to the bag q Remove - Removes an item from the bag q Union - Add one bag to another q Intersection - Remove all items not common between two bags. Where there are duplicates, keep the lower duplicate count q Difference - Remove all items not common between two bags. Where there are duplicates, subtract from the original and discard the item if the total is >= 0 q Extent - Return the number of distinct items q Total_Size - Return the total number of items (including duplicates) q Count - Return the number of occurences of an item in the bag q Is_Empty - True if the bag is empty q Is_Member - True if one or more copies of an item is in the bag q Is_Subset - True if the contents of one bag is completely contained in another q Is_Proper_Subset - Same as Is_Subset, but the bags must not be equal Bags can be bounded, dynamic or unbounded. Bags are implemented using a hash table. To declare a bag, a program must provide a hash function for storing items in the bag, and must indicate the size of the hash table. Here's an example. Notice that some of the subprograms are in the Bags instantiation, and some in the Bags.Unbounded instantiation. Also notice the iterator moves over the items, but not the duplications:

with BC.Containers.Bags.Unbounded; with Global_Heap; package customers is type aCustomerID is new integer range 1_000..9_999; function IDHash( id : aCustomerID ) return Positive; -- our hash function package customerContainers is new BC.Containers (Item => aCustomerID); -- create a new controlled tagged record container for customers package customerBags is new customerContainers.Bags; -- create a new bag support for our using container type package customerBag is new customerBags.Unbounded( Hash => IDHash, Buckets => 99, Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage); -- create an unbounded bag package holding customer numbers end customers;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (8 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

package body customers is function IDHash( id : aCustomerID ) return Positive is -- our hash function begin return Positive( id ); -- in this case, using the id is good enough end IDHash;

end customers;

with ada.text_io, BC, customers; use ada.text_io, BC, customers; procedure bag_demo is customers : customerBag.Unbounded_Bag; c : aCustomerID; i : customerContainers.Iterator'class := customerBag.New_Iterator( customers ); begin Put_Line( "This is a demo of the Booch components: bags" ); New_Line; -- The Newly Declared Bag Put_Line( Put_Line( Put_Line( Put_Line( New_Line; "The "The "The "The bag bag bag bag is newly declared." ); is empty? " & customerBag.Is_Empty( customers )'img ); extent is" & customerBag.Extent( customers )'img ); total size is" & customerBags.Total_Size( customers )'img );

-- Inserting a customer c := 7456; customerBags.Add( customers, c ); Put_Line( "Added customer" & c'img ); Put_Line( "The bag is empty? " & customerBag.Is_Empty( customers )'img ); Put_Line( "The bag extent is" & customerBag.Extent( customers )'img ); New_Line; -- Inserting another customer c := 9362; customerBags.Add( customers, c ); Put_Line( Put_Line( Put_Line( Put_Line( New_Line; "Added customer" & c'img ); "The bag is empty? " & customerBag.Is_Empty( customers )'img ); "The bag extent is" & customerBag.Extent( customers )'img ); "The bag total size is" & customerBags.Total_Size( customers )'img );

-- Inserting duplicate customer


file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (9 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

c := 9362; customerBags.Add( customers, c ); Put_Line( Put_Line( Put_Line( Put_Line( New_Line; "Added customer" & c'img ); "The bag is empty? " & customerBag.Is_Empty( customers )'img ); "The bag extent is" & customerBag.Extent( customers )'img ); "The bag total size is" & customerBags.Total_Size( customers )'img );

-- Iterator example Put_Line( "Resetting the iterator.." ); customerContainers.Reset( i ); c := customerContainers.Current_item ( i ); Put_Line( "The current item is customer id" & c'img ); Put_Line( "Are we done? " & customerContainers.Is_Done( i )'img ); Put_Line( "Advancing to the next item..." ); customerContainers.Next( i ); c := customerContainers.Current_item ( i ); Put_Line( "The current item is customer id" & c'img ); Put_Line( "Are we done? " & customerContainers.Is_Done( i )'img ); Put_Line( "Advancing to the next item..." ); customerContainers.Next( i ); Put_Line( "Are we done? " & customerContainers.Is_Done( i )'img ); begin c := customerContainers.Current_item ( i ); exception when BC.NOT_FOUND => put_line( "BC.NOT_FOUND exception: no item at this position in the bag" ); end; end bag_demo;

This is a demo of the Booch components: bags The The The The bag bag bag bag is newly declared. is empty? TRUE extent is 0 total size is 0

Added customer 7456 The bag is empty? FALSE The bag extent is 1 Added customer 9362 The bag is empty? FALSE The bag extent is 2 The bag total size is 2 Added customer 9362 The bag is empty? FALSE The bag extent is 2
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (10 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

The bag total size is 3 Resetting the iterator.. The current item is customer id 7456 Are we done? FALSE Advancing to the next item... The current item is customer id 9362 Are we done? FALSE Advancing to the next item... Are we done? TRUE BC.NOT_FOUND exception: no item at this position in the bag Bags are useful for counting the occurrences of an item in a large amount of data. 18.1.6 Sets Sets are essentially the same as bags but may not contain duplicates. The are useful for detecting the presence/absence of an item, or representing flags or conditions. with BC.Containers.Sets.Bounded; with Global_Heap; package fruit_sets is -- my grandfather owned one of the largest fruit companies in the world type aFruit is ( Apples, Grapes, Peaches, Cherries, Pears, Plums, Other );

function FruitHash( f : aFruit ) return Positive; -- our hash function for the set package fruitContainers is new BC.Containers( item=> aFruit ); -- basic fruit container package fruitSets is new fruitContainers.Sets; -- basic set support package fruitBoundedSets is new fruitSets.Bounded( fruitHash, Buckets => 10, Size => 20 ); -- our actual set is an unbounded set end fruit_sets;

package body fruit_sets is function FruitHash( f : aFruit ) return Positive is begin return aFruit'pos( f )+1; -- good enough for this example end FruitHash; end fruit_sets;

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (11 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

with ada.text_io, kb_sets; use ada.text_io, kb_sets; procedure set_demo is use fruitSets; use fruitBoundedSets; s1 : Bounded_Set; s2 : Bounded_Set; s3 : Bounded_Set; begin Put_Line( "This is a demo of the Booch components: sets" ); New_Line; Add( Add( Add( Add( Add( s1, s1, s2, s2, s2, apples ); peaches ); apples ); peaches ); pears ); "Set 1 has apples and peaches." ); "Set 2 has apples, peaches and pears." ); "Extent of set 1? " & Extent( s1 )'img ); "Extent of set 2? " & Extent( s2 )'img ); "Peaches in set 1? " & Is_Member( s1, peaches )'img ); "Pears in set 1? " & Is_Member( s1, pears )'img ); "Set 1 a subset of set 2? " & Is_Subset( s1, s2 )'img ); "Set 2 a subset of set 1? " & Is_Subset( s2, s1 )'img ); "Set 1 a subset of set 1? " & Is_Subset( s1, s1 )'img ); "Set 1 a proper subset of set 1? " & Is_Proper_Subset( s1, s1 )'img );

Put_Line( Put_Line( New_Line; Put_Line( Put_Line( Put_Line( Put_Line( Put_Line( Put_Line( Put_Line( Put_Line( New_Line;

s3 := s1; Union( s3, s2 ); Put_Line( "Set 3 is the union of set 1 and set 2" ); Put_Line( "Extent of set 3? " & Extent( s3 )'img ); end set_demo;

This is a demo of the Booch components: sets Set 1 has apples and peaches. Set 2 has apples, peaches and pears. Extent of set 1? 2 Extent of set 2? 3 Peaches in set 1? TRUE Pears in set 1? FALSE Set 1 a subset of set 2? Set 2 a subset of set 1? Set 1 a subset of set 1? Set 1 a proper subset of

TRUE FALSE TRUE set 1? FALSE

Set 3 is the union of set 1 and set 2 Extent of set 3? 3


file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (12 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

18.1.7 Collections Collections are a (conceptually) combination of lists and bags. Duplicates actually exist as copies in the collection, not simply counted. Collections are also indexed, like a list, so that items can be referenced in the collection. The Collections package provides the following subprograms: q Create - Create a new collection and its initial chunk q Clear - Remove all items from a collection q Insert - Add an item in front of another q Append - Add an item to the end of the collection q Remove - Remove an item at an index q Replace - Replace an item at an index q Length - Return the number of items in the collection q Is_Empty - True if there are no items in the collection q First - Return the item at the front of the collection q Last - Return the item at the end of the collection q Item_At - Return the item at a particular index q Location - Return the first index where an item is found (0 if Collections are implemented as dynamically allocated arrays. with BC.Containers.Collections.Dynamic; with Global_Heap; package products is type aProduct is record id : integer; weight : float; end record; package productContainers is new BC.Containers (Item => aProduct); -- this is the basic container package productCollections is new productContainers.Collections; -- create a new collection support for our using container type package productCollection is new productCollections.dynamic( Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage); -- create a dynamic collection holding products end products;

with ada.text_io, BC, products; use ada.text_io, BC, products; procedure collection_demo is products : productCollection.Dynamic_Collection; p : aProduct; i : productContainers.Iterator'class := productCollection.New_Iterator(
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (13 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

products ); begin Put_Line( "This is a demo of the Booch components: collections" ); New_Line; products := productCollection.Create( 100 ); -- The Newly Declared Collection Put_Line( "The collection is newly declared with a chunk size of 100..." ); Put_Line( "The collection is empty? " & productCollection.Is_Empty( products )'img ); Put_Line( "The collection length is" & productCollection.Length( products )'img ); Put_Line( "The collection chunk size is" & productCollection.Chunk_Size( products )'img ); New_Line; -- Adding an Item p.id := 8301; p.weight := 17.0; productCollection.Append( products, p ); Put_Line( "Product id" & p.id'img & " was added..." ); Put_Line( "The collection is empty? " & productCollection.Is_Empty( products )'img ); Put_Line( "The collection length is" & productCollection.Length( products )'img ); Put_Line( "The collection chunk size is" & productCollection.Chunk_Size( products )'img ); p := productCollection.First( products ); Put_Line( "The first item is" & p.id'img ); p := productCollection.Last( products ); Put_Line( "The last item is" & p.id'img ); New_Line; -- Adding another Item p.id := 1732; p.weight := 27.0; productCollection.Append( products, p ); Put_Line( "Product id" & p.id'img & " was added..." ); Put_Line( "The collection is empty? " & productCollection.Is_Empty( products )'img ); Put_Line( "The collection length is" & productCollection.Length( products )'img ); Put_Line( "The collection chunk size is" & productCollection.Chunk_Size( products )'img ); p := productCollection.First( products ); Put_Line( "The first item is" & p.id'img ); p := productCollection.Last( products ); Put_Line( "The last item is" & p.id'img ); New_Line; -- Changing the Chunk Size productCollection.Set_Chunk_Size( products, Size => 1 );
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (14 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

Put_Line( "The chunk size was reduced to only 1..." ); Put_Line( "The collection is empty? " & productCollection.Is_Empty( products )'img ); Put_Line( "The collection length is" & productCollection.Length( products )'img ); Put_Line( "The collection chunk size is" & productCollection.Chunk_Size( products )'img ); p := productCollection.First( products ); Put_Line( "The first item is" & p.id'img ); p := productCollection.Last( products ); Put_Line( "The last item is" & p.id'img ); New_Line; -- Iterator example Put_Line( "Resetting the iterator.." ); productContainers.Reset( i ); p := productContainers.Current_item ( i ); Put_Line( "The current item is customer id" & p.id'img ); Put_Line( "Are we done? " & productContainers.Is_Done( i )'img ); Put_Line( "Advancing to the next item..." ); productContainers.Next( i ); p := productContainers.Current_item ( i ); Put_Line( "The current item is customer id" & p.id'img ); Put_Line( "Are we done? " & productContainers.Is_Done( i )'img ); Put_Line( "Advancing to the next item..." ); productContainers.Next( i ); Put_Line( "Are we done? " & productContainers.Is_Done( i )'img ); begin p := productContainers.Current_item ( i ); exception when BC.NOT_FOUND => put_line( "BC.NOT_FOUND exception: no item at this position in the collection" ); end; Collections are suitable for small lists or lists where the upper bound is known or rarely exceeded.

This is a demo of the Booch components: collections The The The The collection collection collection collection is newly declared with a chunk size of 100... is empty? TRUE length is 0 chunk size is 100

Product id 8301 was added... The collection is empty? FALSE The collection length is 1 The collection chunk size is 100 The first item is 8301 The last item is 8301 Product id 1732 was added... The collection is empty? FALSE

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (15 of 26) [7/20/2001 11:38:17 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

The The The The The The The The The The

collection length is 2 collection chunk size is 100 first item is 8301 last item is 1732 chunk size was reduced to only 1... collection is empty? FALSE collection length is 2 collection chunk size is 1 first item is 8301 last item is 1732

Resetting the iterator.. The current item is customer id 8301 Are we done? FALSE Advancing to the next item... The current item is customer id 1732 Are we done? FALSE Advancing to the next item... Are we done? TRUE BC.NOT_FOUND exception: no item at this position in the collection 18.1.8 Queues Queues are a list in which items are removed in the same order they are added. Items are added at the end of the queue and removed at the front. An ordered (or "priority") queue is a queue in which added items are sorted. The queues package provides the following subprograms: q Clear - Remove all items from the queue q Append - Add an item to the back of the queue q Pop - Remove an item from the front of the queue and return it q Remove - Remove an item at a particular index q Length - Return the number of items in the queue q Is_Empty - True if there are no items in the queue q Front - Return the item at the front of the queue without removing it q Process - generic procedure to return an item with processing q Location - Return the first index where an item appears else 0 q Are_Equal - True if two queues have the same items and length q Copy - Copy one queue to another An ordered queue is identical except that append adds an item in sorted order. Queues can be bounded, dynamic or unbounded. Queues provide "fair" processing and reduce starvation. 18.1.9 Stacks Stacks are lists in which the last item placed in the list is the first item removed. The Stacks package provides the following subprograms: q Clear - Remove all items from the stack

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (16 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures


q q q q q q q q

Push - Add an item to the top of the queue Pop - Remove an item from the top of the stack and return it Depth - Return the number of items in the stack Is_Empty - True if there are no items in the stack Top - Return the item at the top of the stack without removing it Process_Top - generic procedure to return an item with processing Are_Equal - True if two stacks have the same items and length Copy - Copy one stack to another

Stacks can be bounded, dynamic or unbounded. Stacks are used for temporary storage, compact representation and fast data access. 18.1.10 Deques Deques (double-ended queues, pronounced "deck") are a combination of a stack and queue where items can be placed at the front or the back and removed from either the front or the back. The Deques package provides the following subprograms: q Clear - Remove all items from the deque q Append - Add an item to the deque q Pop - Remove an item from the deque and return it q Remove - Remove an item at a particular index q Length - Return the number of items in the deque q Is_Empty - True if there are no items in the deque q Front - Return the item at the front of the deque without removing q Back - Return the item at the back of the deque without removing it q Process_Front/_Back - generic procedure to return an item with processing q Location - Return the first index where an item appears else 0 q Are_Equal - True if two deques have the same items and length q Copy - Copy one deque to another Deques can be bounded, dynamic or unbounded. 18.1.11 Rings Rings are similar to deques, but rings have no "front" or "back", only a moving point of reference called "top". In addition to the deque subprograms, rings include "Mark" to mark a point in the ring, "Rotate_To_Mark" to move the ring to the marked position, and "At_Mark" to test to see if the top of the ring is at the mark. Rings can be bounded or dynamic. 18.1.12 Maps Maps are ordered pairs of related items. Each item is related to a "value" which may or may not be the same type. Maps relate items to values by "binding" them. The Maps package provides the following subprograms: q Clear - destroy a map q Bind - relate an item to a value q Rebind - relate an item to a different value q Unbind - remove the relationship between an item and its value
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (17 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures


q q q q q q

Extent - return the number of relationships Is_Empty - true if there are no relationships Is_Bound - true if the item is related to a value Value_Of - the value an item is related to Visit - a "read-only" procedure to traverse the map Modify - a procedure that traverses the map making changes

Maps are implemented with a hash table and caching. Maps can be bounded, dynamic, unbounded or synchronized. Maps are useful as translation tables. 18.1.13 Binary Trees Binary trees are lists with two successors instead of 1, named "left" and "right". The items in the tree are not sorted by the Booch component. The program has full control on how items are added to the tree. Programs "walk" the tree by moving the root of the tree up and down the links to the items. Left_Child follows the left child link. Right_Child follows the right child link. Parent follows the parent link. Each of these subprograms can be used as a procedure (to move the root of the tree) or as a function (to examine the item the link connects to). item := Item_At( Put( "Left child item := Item_At( Put_Line( " is " tree ); of " & item ) ; Left_Child( tree ) ); & item ) ;

When the root of the tree is moved, any items above the new root that aren't referenced anymore are destroyed. To move around the tree without destroying nodes (which is typically what you want to do), create an "alias" to the root of the tree with Create prior to moving. root := Create( tree ); -- create a reference to the root Left_Child( tree ); -- safe: old root is not destroyed Moving into an empty (null) position in the tree is allowed, but any attempt to look at the item there will raise an exception. The leaves and the parent of the root are empty. The Trees.Binary package provides the following subprograms: q Clear - Destroy the tree q Insert - Insert an item at the tree's root q Append - Add an item in the place of a particular item, moving the old item to a new position q Remove - Remove an item from the tree q Share - Create an alias to a subtree of the tree q Child/Left_Child/Right_Child - Move to a child item q Parent - Move towards the root q Set_Item - Make an item the root of the tree q Has_Children - True if the tree has any children items q Is_Null - True if the tree has no items q Is_Shared - True if any subtree has an alias to it q Is_Root - True if the tree is at the root of tree q Item_At - Return the item at the root of the tree In addition, the tree may have an in_order, pre_order or post_order generic procedure. This procedure traverses the tree and
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (18 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

executes processes each item. Pre_order processes an item before its children. Post_order processes an item after its children. In_order processes a node in the sort order of the tree--after all the left children but before all the right. with with with with BC.Containers.Trees.Binary.In_Order; BC.Containers.Trees.Binary.Pre_Order; BC.Containers.Trees.Binary.Post_Order; Global_Heap;

package shipment_binary is -- grandfather would be proud type aQuantity is ( Unknown, Basket_6Quart, Basket_11Quart, Bushel, Skid, Boxcar ); type aFruit is ( Apples, Grapes, Peaches, Cherries, Pears, Plums, Other ); type aShipment is record number : Positive; quantity : aQuantity; contents : aFruit; end record;

-- number of containers -- the containers -- type of fruit

procedure visitShipment( s : aShipment; OK : out boolean ); -- our tree traversal function package shipmentContainers is new BC.Containers( item=> aShipment ); -- basic fruit container package shipmentTrees is new shipmentContainers.Trees; -- basic tree support package shipmentBinaryTrees is new shipmentTrees.Binary( Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage ); -- our binary tree support procedure inOrdershipmentTraversal is new shipmentBinaryTrees.In_Order( visitShipment ); -- an in-order traversal procedure preOrdershipmentTraversal is new shipmentBinaryTrees.Pre_Order( visitShipment ); -- a pre-order traversal procedure postOrdershipmentTraversal is new shipmentBinaryTrees.Post_Order( visitShipment ); -- a post-order traversal end shipment_binary;

with ada.text_io; use ada.text_io; package body shipment_binary is


file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (19 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

procedure visitShipment( s : aShipment; OK : out boolean ) is -- our tree traversal function begin Put( "Shipment of" ); Put( s.number'img ); Put( " " ); Put( s.quantity'img ); Put( "(S) of " ); Put_Line( s.contents'img ); OK := true; end visitShipment; end shipment_binary;

with ada.text_io, shipment_binary; use ada.text_io, shipment_binary; procedure bintree_demo is use shipmentBinaryTrees; root : Binary_Tree; t : Binary_Tree; s : aShipment; OK : boolean; begin Put_Line( "This is a demo of the Booch components: binary trees" ); New_Line; -- this is the root item s.number := 5; s.quantity := basket_6quart; s.contents := cherries; Insert( t, s, Child => Left ); -- child doesn't really matter because there's no prior item at the root root := Create( t ); -- remember where the root is -- add to left of root s.number := 7; s.quantity := basket_11quart; s.contents := pears; Append( t, s, Child => Left, After => Left ); -- child doesn't really matter here -- add to right of root s.number := 12; s.quantity := bushel; s.contents := apples; Append( t, s, Child => Left, After => Right ); -- child doesn't really matter here

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (20 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

Left_Child( t );

-- move "t" down left branch

s.number := 3; s.quantity := skid; s.contents := peaches; Append( t, s, Child => Left, After => Right ); -- child doesn't really matter here Put_Line( Put_Line( Put_Line( Put_Line( Put_Line( Put_Line( ); Put_Line( " Put_Line( " Put_Line( " New_Line; |" ); +-------------------------------|" ); 3 skids of peaches" ); "Our tree is: "); " 5 6 qt baskets of cherries" ); " |" ); " +----------------------------------------------------+" ); " | |" ); "7 11 qt baskets of pears 12 bushels of apples"

Put_Line( "In-order traversal:" ); inOrderShipmentTraversal( root, OK ); if not OK then Put_Line( "The traversal was interrupted" ); end if; New_Line; Put_Line( "Pre-order traversal:" ); preOrderShipmentTraversal( root, OK ); if not OK then Put_Line( "The traversal was interrupted" ); end if; New_Line; Put_Line( "Post-order traversal:" ); postOrderShipmentTraversal( root, OK ); if not OK then Put_Line( "The traversal was interrupted" ); end if; end bintree_demo;

This is a demo of the Booch components: binary trees Our tree is: 5 6 qt baskets of cherries | +----------------------------------------------------+ | | 7 11 qt baskets of pears 12 bushels of apples | +-------------------------------| 3 skids of peaches

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (21 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

In-order Shipment Shipment Shipment Shipment

traversal: of 7 BASKET_11QUART(S) of PEARS of 3 SKID(S) of PEACHES of 5 BASKET_6QUART(S) of CHERRIES of 12 BUSHEL(S) of APPLES

Pre-order traversal: Shipment of 5 BASKET_6QUART(S) of CHERRIES Shipment of 7 BASKET_11QUART(S) of PEARS Shipment of 3 SKID(S) of PEACHES Shipment of 12 BUSHEL(S) of APPLES Post-order traversal: Shipment of 3 SKID(S) of PEACHES Shipment of 7 BASKET_11QUART(S) of PEARS Shipment of 12 BUSHEL(S) of APPLES Shipment of 5 BASKET_6QUART(S) of CHERRIES Binary trees should not be Guarded. 18.1.14 AVL Trees AVL trees are binary trees that are balanced. On every insert or delete, the tree is restructured to keep its symmetry. As a result, the trees must be sorted by the Booch component and the program using the AVL tree must provide a "<" function to sort the tree by. The AVL package provides fewer subprograms than the binary tree package: q Clear - destory the AVL tree q Insert - add an item into the AVL tree q Delete - remove an item form the AVL tree q Extent - return the number of items in the AVL tree q Is_Null - true if there are no items in the AVL tree q Is_Member - true if an item is in the AVL tree q Visit - traverse the tree in-order executing a "read only" procedure q Modify - traverse the tree in-order executing a procedure that can alter the items. There are no subprograms for walking the tree. Here is a sample declaration: with BC.Containers.Trees.AVL; with Global_Heap; package fruit_avl is -- more fun with fruit type aQuantity is ( Unknown, Basket_6Quart, Basket_11Quart, Bushel, Skid, Boxcar ); type aFruit is ( Apples, Grapes, Peaches, Cherries, Pears, Plums, Other ); type aShipment is record number : Positive; quantity : aQuantity; contents : aFruit;

-- number of containers -- the containers -- type of fruit

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (22 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

end record;

function sortCriteria( left, right : aShipment ) return boolean; -- for sorting the AVL tree package shipmentContainers is new BC.Containers( item=> aShipment ); -- basic fruit container package shipmentTrees is new shipmentContainers.Trees; -- basic tree support package shipmentAVLTrees is new shipmentTrees.AVL( sortCriteria, Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage ); -- our AVL tree support end fruit_avl;

package body fruit_avl is function sortCriteria( left, right : aShipment ) return boolean is begin return left.number < right.number; end sortCriteria; end fruit_avl; AVL trees have slower inserts and deletes than binary trees but are faster than a normal binary tree for searching. 18.1.15 Multiway Trees A multiway tree is a tree with any number of unsorted children (as opposed to a binary tree which always has no more than two chidren). The subprograms are similar to a binary tree. The append procedures add child items to an item. A new function called "Arity" returns the number children an item has. Multiway trees should not be Guarded. 18.1.16 Graphs Essentially, graphs are a generalization of maps where any number of items can be related to each other (as opposed to only two). A directed graph is a set of items (vertices) that are connected by relationships (edges or "arcs"). Like a single linked list, a program can only move forward along an arc. Items can also be linked to themselves. The graphs-directed package provides the following subprograms: q Create_Arc - add a relationship between two items q Number_Of_Incoming_Arcs - return the number of incoming arcs to an item q Number_Of_Outgoing_Arcs - return the number of outgoing arcs to an item q Set_From_Vertex - move an arch's source to a new item
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (23 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures


q q q

Set_To_Vertex - move an arc's destination to a new item From_Vertex - return the source item for an arc To_Vertex - return the destination item for an arc

There are four iterators: a graph iterator, and three iterators for visiting items (incoming, outgoing and both). An undirected graph is a directed graph with pointers to both the previous and next item along an arc. Like a double linked list, a program can move forwards or backwards along an arc. The graphs-undirected package provides the following subprograms: q Create_Arc - add a relationship between two items q Arity - return the number of arcs. Self-arcs are counted only once q Set_First_Vertex - move an arch's first item to a new item q Set_Second_Vertex - move an arc's second item to a new item q First_Vertex - return the first item for an arc q Second_Vertex - return the second item for an arc There are two iterators: a graph iterator and an item iterator. Graphs should not be Guarded. 18.1.17 Smart Pointers Smart pointers are an access type that counts the number of references to the item being pointed to. Your program allocates the item. The item is deallocated when no more pointers point to it. Smart pointers are a simplified form of garbage collection. The smart package provides the following subprograms: q Create - create a new smart pointer from an access variable q Value - return the item pointed to by the smart pointer with BC.smart; package depts is type departments is ( accounting, information_technology, shipping, human_resources ); type deptAccess is access all departments; package deptPtrs is new BC.smart( departments, deptAccess ); end depts;

with ada.text_io, depts; use ada.text_io, depts; procedure sp_demo is accountingPtr : deptPtrs.Pointer; accounting2Ptr : deptPtrs.Pointer; department : deptAccess; begin Put_Line( "This is a demo of the Booch components: smart pointers" ); New_Line; department := new departments'( accounting );

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (24 of 26) [7/20/2001 11:38:18 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

Put_Line( "Assigning dynamically allocate value to a smart pointer" ); accountingPtr := deptPtrs.Create( department ); Put_Line( "The accounting pointer points at " & deptPtrs.Value( accountingPtr ).all'img ); New_Line; Put_Line( "Assigning a smart pointer to a smart pointer" ); accounting2Ptr := accountingPtr; Put_Line( "The accounting pointer 2 points at " & deptPtrs.Value( accounting2Ptr ).all'img ); New_Line; Put_Line( "The memory is released when the program ends or no more pointers" ); Put_Line( "access the memory." ); end sp_demo;

This is a demo of the Booch components: smart pointers Assigning dynamically allocate value to a smart pointer The accounting pointer points at ACCOUNTING Assigning a smart pointer to a smart pointer The accounting pointer 2 points at ACCOUNTING The memory is released when the program ends or no more pointers access the memory. 18.1.18 Booch Multithreading Booch components can be guarded (manually "locking" the structure for exclusive access) or synchronized (implicit blocking) for multithreading purposes. Guarding is implemented by creating extending a container type to a Guarded_Container using the GC.Containers.Guarded package. Guarded containers contain two new subprograms, "Seize" and "Release", to lock and unlock a container. (This is implemented using a semaphore.) Any Booch data structure can be made guarded using guarded containers, but in some cases guarding will not work as expected and should not be used (for example, with lists). The basic semaphore locks individual objects (although it many not work as expected on certain structures such as lists, according to AdaPower.Net). The basic semaphore can be extended and customized by a programmer. Rewriting the Bags example with guards: with with with with BC.Containers.Bags.Unbounded; BC.Containers.Guarded; BC.Support.Synchronization; Global_Heap;

package guarded_customers is type aCustomerID is new integer range 1_000..9_999; function IDHash( id : aCustomerID ) return Positive; -- our hash function

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (25 of 26) [7/20/2001 11:38:19 AM]

Big Online Book of Linux Ada Programming - 18 Data Structures

package customerContainers is new BC.Containers (Item => aCustomerID); -- this is the basic container package customerBags is new customerContainers.Bags; -- create a new bag support for our using container type package customerBag is new customerBags.Unbounded( Hash => IDHash, Buckets => 99, Storage_Manager => Global_Heap.Pool, Storage => Global_Heap.Storage); -- create an unbounded bag holding customer numbers package customerGuardedBag is new customerContainers.Guarded ( Base_Container => customerBag.Unbounded_Bag, Semaphore => BC.Support.Synchronization.Semaphore ); -- create a new controlled tagged record container for customers end guarded_customers; A new guarded bag can now be declared: customers : customerGuardedBag.Guarded_Container; and the bag can be locked using customerGuardedBag.Seize( customers ); Synchronized access by threads is implemented in special versions of the data structure packages (for example, maps.synchronized). With synchronized packages, the implementation details are hidden from the user.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/18.html (26 of 26) [7/20/2001 11:38:19 AM]

Big Online Book of Linux Ada Programming - 19 Specialized Topics

19 Specialized Topics
<--Last Chapter Table of Contents Next Chapter-->

19.1 Ada Meets Java 19.1.1 The Java Virtual Machine


19.1.2 JGnat Most of the Gnat tools have a corresponding JGnat version, including gnatmake. To compile an Ada program into a Java byte-code program, use jgnatmake: jgnatmake hello Table: jgnatmake switches JGnatmake Switch -a -c -f -i -jnum -k -m -M -n -o name -q -s -v -z --GCC=command --GNATBIND=command --GNATLINK=command -aLdir -Adir Description Consider all files, even readonly ali files Compile only, do not bind and link Force recompilations of non predefined units In place. Replace existing ali file, or put it with source Use nnn processes to compile Keep going after compilation errors Minimal recompilation List object file dependences for Makefile Check objects up to date, output next file to compile if not Choose an alternate executable name Be quiet/terse Recompile if compiler switches have changed Display reasons for all (re)compilations No main subprogram (zero main) Use this jgnat command Use this gnatbind command Use this gnatlink command Skip missing library sources if ali in dir like -aLdir -aIdir

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/19.html (1 of 4) [7/20/2001 11:38:32 AM]

Big Online Book of Linux Ada Programming - 19 Specialized Topics

-aOdir -aIdir -Idir -I-Ldir -nostdinc -nostdlib -cargs opts -bargs opts -largs opts -g -Idir -I-O[0123] -gnata -gnatA -gnatb -gnatc -gnatd? -gnatD -gnate -gnatE -gnatf -gnatF -gnatg -gnatG -gnath -gnati? -gnatk -gnatl -gnatL -gnatmnnn -gnatn -gnato -gnatO nm

Specify library/object files search path Specify source files search path Like -aIdir -aOdir Don't look for sources & library files in the default directory Look for program libraries also in dir Don't look for sources in the system default directory Don't look for library files in the system default directory opts are passed to the compiler opts are passed to the binder opts are passed to the linker Generate debugging information Specify source files search path Do not look for sources in current directory Control the optimization level Assertions enabled. Pragma Assert/Debug to be activated Avoid processing gnat.adc, if present file will be ignored Generate brief messages to stderr even if verbose mode set Check syntax and semantics only (no code generation) Compiler debug option ? (a-z,A-Z,0-9), see debug.adb Debug expanded generated code rather than source code Error messages generated immediately, not saved up till end Dynamic elaboration checking mode enabled Full errors. Verbose details, all undefined references Force all import/export external names to all uppercase GNAT implementation mode (used for compiling GNAT units) Output generated expanded code in source form Output this usage (help) information Identifier char set (?=1/2/3/4/8/p/f/n/w) Limit file names to nnn characters (k = krunch) Output full source listing with embedded error messages Use longjmp/setjmp for exception handling Limit number of detected errors to nnn (1-999) Inlining of subprograms (apply pragma Inline across units) Enable overflow checking (off by default) Set name of output ali file (internal switch)

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/19.html (2 of 4) [7/20/2001 11:38:32 AM]

Big Online Book of Linux Ada Programming - 19 Specialized Topics

-gnatp -gnatP -gnatq -gnatR -gnats -gnatt -gnatTnnn -gnatu -gnatU -gnatv -gnatw? -gnatW -gnatx -gnatX -gnaty

Suppress all checks Generate periodic calls to System.Polling.Poll Don't quit, try semantics, even if parse errors List representation information Syntax check only Tree output file to be generated All compiler tables start at nnn times usual starting size List units for this compilation Enable unique tag for error messages Verbose mode. Full error output with source lines to stdout Warning mode. (?=s/e/l/u for suppress/error/elab/undefined) Wide character encoding method (h/u/s/e/8/b) Suppress output of cross-reference information Language extensions permitted Enable all style checks Enable selected style checks xxx = list of parameters: q 1-9 check indentation q b check no blanks at end of lines q c check comment format q e check end labels present q f check no form feeds/vertical tabs in source q h check no horizontal tabs in source q i check if-then layout q k check casing rules for keywords, identifiers q m check line length <= 79 characters q Mnnn check line length <= nnn characters q r check RM column layout q s check separate subprogram specs present q t check token separation rules Distribution stub generation (r/s for receiver/sender stubs) Use zero cost exception handling Enforce Ada 83 restrictions

-gnatyxxx

-gnatz -gnatZ -gnat83

jgnatmake will create two files: hello.class and ada_hello.class. To run the program under the Java interpreter, type

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/19.html (3 of 4) [7/20/2001 11:38:32 AM]

Big Online Book of Linux Ada Programming - 19 Specialized Topics

java hello Table: java switches Java Interpreter Switch -help -version -ss size -mx size -ms size -as size -classpath path -verify -verifyremote -noverify -Dproperty=value -verbosegc -noclassgc -v, -verbose -verbosejit -verbosemem -debug -noasyncgc -cs, -checksource -oss size -jar Description Print usage info Print version number Maximum native stack size Maximum heap size Initial heap size Heap increment Set classpath Verify all bytecode Verify bytecode loaded from network Do not verify any bytecode Set a property Print message during garbage collection Disable class garbage collection Be verbose Print message during JIT code generation Print detailed memory allocation statistics Trace method calls Do not garbage collect asynchronously Check source against class files Maximum java stack size Executable is a JAR

Limitations: Ada streams don't work with Jgnat. 19.2 ASIS Information on ASIS is available at http://info.acm.org/sigada/WG/asiswg/asiswg.html.

<--Last Chapter

Table of Contents

Next Chapter-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/19.html (4 of 4) [7/20/2001 11:38:32 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

20 Developing Your Project


<--Last Chapter Table of Contents Appendices-->

20.1 The Project Proposal Before you begin any project that will be released to the public, it's a good idea to draw up a proposal. The proposal should be about one page document describing the purpose of the project, who it's being made for, and how long it will take and what kind of investments (time, money or otherwise) you expect. This is especially important if there is anybody working with you. Don't assume your teammates see the project in exactly the same was as you do: write a proposal to avoid misunderstandings. For example, calling a project "a database" doesn't say much. Calling it a "fast, distributed database for businesses" tells your teammates where the database will be used, gives them an idea about the features required, and tells that the design emphasis is on execution speed. Once your proposal is finished, bounce the ideas of a few people you respect and trust, especially if they are potential users of your program. If none of them think the project is practical, you may want to change the target audience or features of your project, or chose another project altogether. You can later use your proposal as the basic text for an announcement of the release of your program. 20.2 The Design Phase When it comes time to begin designing the basic layout of a project, remember that Ada has features designed just for this task. Break up your project into a series of packages, and include basic type definitions and subprograms (using pragma stubbed). Remember that the design doesn't have to be perfect, but you need a starting place for you and your teammates to discuss the work. Use lots of comments to avoid continually explaining the purpose of each package and it's contents. When you have a basic layout, compile each of the specs to make sure the design is sound. 20.3 The Development Phase Check list: Did you use pragma pure, preelaborate or no_elaboration_code whenever possible? Did you use pragma Normalize_Scalars whenever possible? 20.4 The Alpha/Beta Release Check list for first alpha or beta release: Check your integers: did you use integer when short_integer or long_integer would have been better?
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (1 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

Do you have pragma Optimize set in all of your packages? Did you use pragma Pack all arrays and records that need packing? Do some need packing turned off? Did you assign your access types to a debug pool in order to check for run-time errors? 20.5 Releasing Your Software Check list: Did you remove all pragma Normalize_Scalars? Did you remove all access type references to debug pools? 20.5.1 A Third Party Library If you want to release a package as a third party library: Change your .ads files to read-only with chmod -w. Collect your executables into an archive with the ar command (see the section on libraries above). Include instructions for installing the archive and make sure you mention that those who use your library must use the -f option for gnatmake. This option treats all read-only files as third party libraries that cannot be recompiled because the package bodies were not included. 20.6 Distribution Formats 20.6.1 RPM: Red Hat Package Manager RPM (Red Hat Package Manager) is the most popular installation tool. It installs, uninstalls, and checksums packages. S.u.S.E.'s YaST (Yet Another Setup Tool) works using RPM. RPM files end in ".rpm". Full details on the RPM format are available from Red Hat's RPM site at http://www.rpm.org. The -q command checks for a package. -a shows all installed packages. [root@redbase /root]# rpm -q uucp uucp-1.06.1-14 [root@redbase /root]# rpm -q kernel kernel-2.0.32-2 [root@redbase /root]# rpm -q -a setup-1.9.1-1 filesystem-1.3.1-2 basesystem-4.9-1 AnotherLevel-0.5-2 ldconfig-1.9.5-2
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (2 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

XFree86-Mach64-3.3.1-14 Creating a new RPM archive is a cumbersome, multistep process. 20.6.2 TGZ Packages TGZ (tar-ed gzip packages) are created by collecting all the files into one file using tar (tape archiver) and compressing the file gzip (GNU zip) or tar's z (compress) option. The files are usually named with ".tgz" ending but sometimes have the ".tar.gz" longform ending. To create a new .tar archive, use the "cfv" options. tar cfv archivename file To add additional files to the archive, use "rfv". tar rfv archivename file When the tar file is finished, compress it with gzip gzip 9 archivename.tar And rename it to .tgz mv archivename.tar.gz archivename.tar.gz 20.6.3 TAR.BZ2 Packages TAR.BZ2 (tar-ed bzip packages) are another option. Like TGZ, these are tar files that are compressed, but instead use the new bzip2 command that compresses better than gzip. Other Formats TZ is an older format, these are tar files that are compressed with the old compression command, compress. ZIP packages are collected and compressed in the popular PC zip format using zip. ZOO packages use an older compression program, zoo. CPIO (Copy In-Out) is another archiving program similar to tar. It collects files but doesn't compress them. DEB is a package for the Debian distribution. There are a host of other tools and formats, including ones to create archives for other platforms. 20.7 Man Pages Linux man pages are special text files formatted for the groff program (GNU run off) is based on the older UNIX programs troff (for printers) and nroff (for terminals). Troff was originally created in 1973 by Joseph F. Ossanna.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (3 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

man pages are text files containing groff markup codes embedded in the text. These codes, much like HTML tags in a web page, control the fonts, layout and graphics used in the pages. You can also define your own groff codes (using groff macros). Here's an example of a man page with groff markup codes: .\"This is a comment .TH MAN 7 "25 July 1993" "Linux" "Linux Programmer's Manual" .SH NAME man \- macros to format man pages .SH SYNOPSIS .B groff \-Tascii \-man .I file Here, the ".B" groff code indicates that the text that follows should be bold (similar to &lt;b&gt;), and the ".SH" groff code incidcates the text that follows is a subheading (similar to &lt;hn&gt;). The groff predefined macros pretaining to manual pages are documented in the section 7 manual page on man ("man 7 man"). All the man pages are stored in subdirectories in /usr/man. The subdirectories are numbered, each number representing a different section number of the Linux manual. The manuals sections include: 1. Linux introduction 2. System Calls 3. C Library Calls 4. Summaries and Data Structures For example, the C library call manual pages are located in /usr/man/man3. The easiest way to create a simple man page for your program is to find a similar man page and make a copy. Use this copy as a basis for your new man page. You can perform a simple test on your new man page by groff mypage | less To convert your page to another format, use groff mypage > mypage.ps to create a PostScript version of your man page (or use the -Tdvi switch to create a TeX .dvi file). Use one of the free conversion programs available on the Internet to translate the PostScript file to another format.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (4 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

20.8 Linux Software Map Entry


The Linux Software Map (http://www.ExecPC.com/lsm/) is a web site devoted to tracking Linux software. Software registered with the map uses a LSM (Linux Software Map) file to describe programs. One important Linux site, Metalab (http://metalab.unc.edu), requires a LSM file for every program in its archive. A Linux Software Map entry is a text file ending with a ".lsm" suffix. It's formatted like an email message header. There are named fields that begin with a keyword and a colon, followed by the data for that field. Continue lines by pacing over beneath the previous line. Here is an example LSM entry: Begin3 Title: YAK - Bulletin Board System for Linux Version: 1.08b Entered-date: 09JUN97 Description: BBS software with sources for DOS, OS/2 and Linux. Includes also tosser and tick program without sources. Keywords: yak bbs tosser conference bulletin board Author: [email protected] (Timo Sirainen) Primary-site: Skyliner BBS +358-15-176242 Alternative-site: sunsite.unc.edu Platform: DOS, OS/2, Linux, ... Copying-policy: GPL End Here is the LSM entry for System Manager in a Box 0.9.1 (beta): Begin3 Title: Version: System Manager in a Box 0.9.1 (beta)

Entered-date: Wednesday, May 26, 1999 Description: Linux configuration and administration utility using AI techniques.

PegaSoft home page is http://www.vaxxine.com/pegasoft Keywords: system administration box ai pegasoft

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (5 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

Author:

[email protected] (PegaSoft Canada)

Maintained-by: [email protected] (PegaSoft Canada) Primary-site: metalab.unc.edu /pub/Linux/system/admin 700kB smiab-0.9.1.tgz Alternate-site: Original-site: Platforms: Copying-policy: freeware End [KB-platform or platforms?] Details about the format are available from the LSM web site. To register a program with the Linux Software Map, email your LSM entry to '[email protected]' with the subject 'add'. 20.9 Software Licensing Options The following is a very simplistic overview of the basic licensing options for Linux: Commercial sold for money, with warranty. Windows 95 is commercial, as are most programs that run on it. Free/Freeware free for all use, usually has no warranty. GPL (GNU Public License) free for use and no warranty. If it's a programming tool, you can only incorporate it into your programs to create more GPL software. In other words, GPL is free public software that can only be used to make more free public software. Imagine a free engine for cars. If any car is built to take that free engine, it must be sold for free as well. LGPL (Library GPL) same as GPL. Commercial programs may only use it if it's shared, not statically linked. A car can be sold with no engine in it, and the engine can be added separately by the dealer, but you can't sell the car with the free engine factory-installed. Shareware commercial software that's sold on the honor system: people who like the software and who use it are expected to send in a cheque to the author. There's a lot of shareware for Windows. Xfree86 uses a different licence that's compatible with GPL/LGPL. Virtually all the standard C libraries are LGPL, including libc, but you should check to documentation or C header files to make sure. Details on these and other licensing options, and how they interact, are described in the book Linux Application Development from Addision-Wesley-Longman.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (6 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - 20 Developing Your Project

<--Last Chapter

Table of Contents

Appendices-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/20.html (7 of 7) [7/20/2001 11:38:49 AM]

Big Online Book of Linux Ada Programming - Appendix A

<--Chapter 20

Table of Contents

Appendix B-->

Appendix A: The Linux Shell


The default Linux shell is bash. Here's a summary of common bash shell commands. ls lists the files in the current directory [root@armitage temp]# ls typescript touch create a new, blank file. If the file exists, changes the time it was last modified but otherwise leaves the file unchanged. [root@armitage temp]# touch temp.txt [root@armitage temp]# ls temp.txt typescript rm permanently remove a file [root@armitage temp]# rm temp.txt rm: remove `temp.txt'? y Note: Red Hat defines aliases for rm, mv and cp that prompt before they overwrite or erase a file. Most other distributions use the default behaviour, which is to take action without warning. You can disable Red Hat's aliases with the unalias command. mv change the name of a file, or move it to a new location [root@armitage temp]# touch temp.txt [root@armitage temp]# mv temp.txt temp2.txt [root@armitage temp]# ls temp2.txt typescript cp copy a file [root@armitage temp]# cp temp2.txt temp3.txt [root@armitage temp]# ls temp2.txt temp3.txt typescript grep search a file for a word or phrase

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99.html (1 of 3) [7/20/2001 11:39:10 AM]

Big Online Book of Linux Ada Programming - Appendix A

[root@armitage temp]# grep "procedure" /home/ken/ada/basicio2.adb procedure basicio2 is find search for a file [root@armitage temp]# find /home/ken -type f -name basicio3.adb /home/ken/ada/basicio3.adb lpr print a file [root@armitage temp]# lpr basicio3.adb lprm stop printing a file, if the file hasn't started printing yet [root@armitage temp]# lprm dfA017Aa01370 dequeued cfA017Aa01370 dequeued lpq list your files waiting to be printed [root@armitage temp]# lpq no entries cat display a file [root@armitage temp]# cat hello.adb with Ada.Text_IO; use Ada.Text_IO; procedure hello is begin Put_Line( "Hello world!" ); end hello; less display a file one screen at a time, allowing you to move around

[root@armitage temp]# less basicio.adb

tr translate characters. To translate a DOS text file to a Linux text file, use

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99.html (2 of 3) [7/20/2001 11:39:10 AM]

Big Online Book of Linux Ada Programming - Appendix A

tr d \r' < dos.txt > linux.txt

<--Chapter 20

Table of Contents

Appendix B-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99.html (3 of 3) [7/20/2001 11:39:10 AM]

Big Online Book of Linux Ada Programming - Appendix B

<--Appendix A

Table of Contents

Appendix C-->

Appendix B: Linux Error Codes


Linux numeric error codes as defined by the Linux kernel. C Name EPERM ENOENT ESRCH EINTR EIO ENXIO E2BIG ENOEXEC EBADF ECHILD EAGAIN ENOMEM EACCES EFAULT ENOTBLK EBUSY EEXIST EXDEV ENODEV ENOTDIR EISDIR EINVAL ENFILE EMFILE ENOTTY ETXTBSY Value 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Description Operation not permitted No such file or directory No such process Interrupted system call I/O error No such device or address Arg list too long Exec format error Bad file number No child processes Try again Out of memory Permission denied Bad address Block device required Device or resource busy File exists Cross-device link No such device Not a directory Is a directory Invalid argument File table overflow Too many open files Not a tty device Text file busy

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_b.html (1 of 4) [7/20/2001 11:39:27 AM]

Big Online Book of Linux Ada Programming - Appendix B

EFBIG ENOSPC ESPIPE EROFS EMLINK EPIPE EDOM ERANGE EDEADLK ENAMETOOLONG ENOLCK ENOSYS ENOTEMPTY ELOOP EWOULDBLOCK ENOMSG EIDRM ECHRNG EL2NSYNC EL3HLT EL3RST ELNRNG EUNATCH ENOCSI EL2HLT EBADE EBADR EXFULL ENOANO EBADRQC EBADSLT EDEADLOCK EBFONT ENOSTR ENODATA

27 28 29 30 31 32 33 34 35 36 37 38 39 40 same as EAGAIN 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 same as EDEADLK 59 60 61

File too large No space left on device Illegal seek Read-only file system Too many links Broken pipe Math argument out of domain of func Math result not representable Resource deadlock would occur File name too long No record locks available Function not implemented Directory not empty Too many symbolic links encountered Operation would block No message of desired type Identifier removed Channel number out of range Level 2 not synchronized Level 3 halted Level 3 reset Link number out of range Protocol driver not attached No CSI structure available Level 2 halted Invalid exchange Invalid request descriptor Exchange full No anode Invalid request code Invalid slot Bad font file format Device not a stream No data available

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_b.html (2 of 4) [7/20/2001 11:39:27 AM]

Big Online Book of Linux Ada Programming - Appendix B

ETIME ENOSR ENONET ENOPKG EREMOTE ENOLINK EADV ESRMNT ECOMM EPROTO EMULTIHOP EDOTDOT EBADMSG EOVERFLOW ENOTUNIQ EBADFD EREMCHG ELIBACC ELIBBAD ELIBSCN ELIBMAX ELIBEXEC EILSEQ ERESTART ESTRPIPE EUSERS ENOTSOCK EDESTADDRREQ EMSGSIZE EPROTOTYPE ENOPROTOOPT EPROTONOSUPPORT ESOCKTNOSUPPORT EOPNOTSUPP EPFNOSUPPORT

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96

Timer expired Out of streams resources Machine is not on the network Package not installed Object is remote Link has been severed Advertise error Srmount error Communication error on send Protocol error Multihop attempted RFS specific error Not a data message Value too large for defined data type Name not unique on network File descriptor in bad state Remote address changed Can not access a needed shared library Accessing a corrupted shared library .lib section in a.out corrupted Linking in too many shared libraries Cannot exec a shared library directly Illegal byte sequence Interrupted system call should be restarted Streams pipe error Too many users Socket operation on non-socket Destination address required Message too long Protocol wrong type for socket Protocol not available Protocol not supported Socket type not supported Operation not supported on transport endpoint Protocol family not supported

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_b.html (3 of 4) [7/20/2001 11:39:27 AM]

Big Online Book of Linux Ada Programming - Appendix B

EAFNOSUPPORT EADDRINUSE EADDRNOTAVAIL ENETDOWN ENETUNREACH ENETRESET ECONNABORTED ECONNRESET ENOBUFS EISCONN ENOTCONN ESHUTDOWN ETOOMANYREFS ETIMEDOUT ECONNREFUSED EHOSTDOWN EHOSTUNREACH EALREADY EINPROGRESS ESTALE EUCLEAN ENOTNAM ENAVAIL EISNAM EREMOTEIO EDQUOT ENOMEDIUM EMEDIUMTYPE

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

Address family not supported by protocol Address already in use Cannot assign requested address Network is down Network is unreachable Network dropped connection because of reset Software caused connection abort Connection reset by peer No buffer space available Transport endpoint is already connected Transport endpoint is not connected Cannot send after transport endpoint shutdown Too many references: cannot splice Connection timed out Connection refused Host is down No route to host Operation already in progress Operation now in progress Stale NFS file handle Structure needs cleaning Not a XENIX named type file No XENIX semaphores available Is a named type file Remote I/O error Quota exceeded No medium found Wrong medium type

<--Appendix A

Table of Contents

Appendix C-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_b.html (4 of 4) [7/20/2001 11:39:27 AM]

Big Online Book of Linux Ada Programming - Appendix C

<--Appendix B

Table of Contents

Appendix D-->

Appendix C: Linux Kernel Calls


This is a list of Linux kernel calls from section 2 of the manual.

_exit - terminate the current process _llseek - reposition read/write file offset _newselect - NQS sysctl - read/write system parameters accept - accept a connection on a socket access - check user's permissions for a file acct - switch process accounting on or off adjtimex - tune kernel clock afs_syscall - unimplemented alarm - set an alarm clock for delivery of a signal bdflush - start, flush, or tune buffer-dirty-flush daemon bind - bind a name to a socket break - unimplemented brk - change data segment size cacheflush - (MIPS) flush contents of instruction and/or data cache chdir - change working directory chmod - change permissions of a file chown - change ownership of a file chroot - change root directory __clone - create a child process for multithreading close - close a file descriptor connect - initiate a connection on a socket creat - open and possibly create a file or device create_module - create a loadable module entry delete_module - delete a loadable module entry dup - duplicate a file descriptor dup2 - duplicate a file descriptor execve - execute program exit - cause normal program termination fchdir - change working directory fchmod - change permissions of a file fchown - change ownership of a file fcntl - manipulate file descriptor fdatasync - synchronize a file's in-core data with that on disk flock - apply or remove an advisory lock on an open file fork - create a child process fstat - get file status fstatfs - get file system statistics
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_c.html (1 of 5) [7/20/2001 11:39:50 AM]

Big Online Book of Linux Ada Programming - Appendix C

fsync - synchronize a file's complete in-core state with that on disk ftruncate - truncate a file to a specified length get_kernel_syms - retrieve exported kernel and module symbols getdents - get directory entries getdomainname - get domain name getdtablesize - get descriptor table size getgid - get group identity geteuid - get user identity getgid - get group identity getgroups - get/set list of supplementary group gethostid - get the unique identifier of the current host gethostnamee - get host name getitimer - get value of an interval timer getpagesize - get system page size getpeername - get name of connected peer getpgid - get process group getpgrp - get process group getpid - get process identification getppid - get process identification getpriority - get/set program scheduling priority getresgid - get real, effective and saved group ID getresuid - get real, effective and saved user ID getrlimit - get resource limits getrusage - get resource limits getsid - get session ID getsockname - get socket name getsockopt - get options on sockets gettimeofday - get time getuid - get user identity gtty - unimplemented idle - make process 0 idle init_module - initialize a loadable module entry ioctl - control device ioperm - set port input/output permissions iopl - change I/O privilege level ipc - System V IPC system calls kill - send signal to a process killpg - send signal to a process group lchown - change ownership of a file link - make a new name for a file listen - listen for connections on a socket llseek - reposition read/write file offset lock - unimplemented lseek - reposition read/write file offset lstat - get file status mkdir - create a directory mknod - create a directory or special or ordinary file mlock - disable paging for some parts of memory mlockall - disable paging for calling process mmap - map files or devices into memory
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_c.html (2 of 5) [7/20/2001 11:39:50 AM]

Big Online Book of Linux Ada Programming - Appendix C

modify_ldt - get or set ldt mount - mount and unmount filesystems. mprotect - control allowable accesses to a region of memory mpx - unimplemented mremap - re-map a virtual memory address msgctl - message control operations msgget - get a message queue identifier msgrcv - receive a messsage msgsnd - send a message msync - synchronize a file with a memory map munlock - reenable paging for some parts of memory munlockall - reenable paging for calling process munmap - unmap files or devices into memory nanosleep - pause execution for a specified time nfsservctl - syscall interface to kernel nfs daemon nice - change process priority oldfstat - obsolete oldlstat - obsolete oldolduname - obsolete oldstat - obsolete olduname - obsolete open - open a file or device outb, outw, outl - port output macros pause - wait for signal personality - set the process execution domain pipe - create pipe poll - wait for some event on a file descriptor prctl - operations on a process prof - unimplemented ptrace - process trace query_module - query the kernel for various bits pertaining to modules quotactl - manipulate disk quotas read - read from a file descriptor readdir - read directory entry readlink - read value of a symbolic link readv - read a vector reboot - reboot or enable/disable Ctrl-Alt-Del recv - receive a message from a socket recvfrom - receive a message from a socket recvmsg - receive a message from a socket rename - change the name or location of a file rmdir - delete a directory sbrk - change data segment size sched_get_priority_max - get static priority range sched_get_priority_min - get static priority range sched_getparam - get scheduling parameters sched_setscheduler - get schedule algorithm/parameters sched_rr_get_interval - get the SCHED_RR interval for the named process sched_setparam - set scheduling parameters sched_setscheduler - set schedule algorithm/parameters
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_c.html (3 of 5) [7/20/2001 11:39:50 AM]

Big Online Book of Linux Ada Programming - Appendix C

sched_yield - yield the processor select - synchronous I/O multiplexing semctl - semaphore control operations semget - get a semaphore set identifier semop - semaphore operations send - send a message from a socket sendfile - transfer data between file descriptors sendmsg - send a message from a socket sendto - send a message from a socket setdomainname - set domain name setegid - set effective group ID seteuid - set effective user ID setfsgid - set group identity used for file system checks setfsuid - set user identity used for file system checks setgid - set group identity setgroups - set list of supplementary group sethostid - set the unique identifier of the current host sethostname - set host name setitimer - get or set value of an interval timer setpgid - set process group ID setpgrp - set process group setpriority - set program scheduling priority setregid - set real group ID setresgid - set real, effective and saved user setresuid - set real, effective and saved user setreuid - set real and / or effective user ID setrlimit - set resource limits setsid - creates a session and sets the process group ID setsockopt - set options on sockets settimeofday - get / set time setuid - set user identity setup - setup devices and file systems, mount root file (not available) sgetmask - ANSI C signal handling shmat - shared memory operations shmctl - shared memory control shmdt - shared memory operations shmget - allocates a shared memory segment shutdown - shut down part of a full-duplex connection sigaction - change signal action sigblock - change blocked signals siggetmask - get blocked signals sigmask - C macro to create signal masks signal - install signal handler sigpause - atomically release blocked signals and wait for interrupt sigpending - examine pending signals sigprocmask - change blocked signals sigreturn - return from signal handler and cleanup stack sigsetmask - set net group of blocked signals sigsuspend - replace signal mask and suspend process sigvec - obsolete
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_c.html (4 of 5) [7/20/2001 11:39:50 AM]

Big Online Book of Linux Ada Programming - Appendix C

socket - create an endpoint for communication socketcall - socket system calls entry point socketpair - create a pair of connected sockets ssetmask - NQS stat - get file status statfs - get file system statistics stime - set time stty - unimplemented swapoff - stop swapping to file/device swapon - start swapping to file/device symlink - make a new name for a file sync - commit buffer cache to disk sysctl - read/write system parameters sysfs - get file system type information sysinfo - returns information on overall system statistics syslog - read and/or clear kernel message ring buffer; set console_loglevel time - get time in seconds times - get process times truncate - truncate a file to a specified length umask - set file creation mask umount - unmount filesystems uname - get name and information about current kernel unlink - delete a name and possibly the file it refers to uselib - select shared library ustat - get file system statistics utime - change access and/or modification times of an inode utimes - change access and/or modification times of an inode vfork - alias for fork vhangup - virtually hangup the current tty vm86 - (Intel) enter virtual 8086 mode vm86old - obsolete wait - wait for process termination wait3 - wait for process termination, BSD style wait4 - wait for process termination, BSD style waitpid - wait for process termination write - write to a file descriptor writev - read or write a vector

<--Appendix B

Table of Contents

Appendix D-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_c.html (5 of 5) [7/20/2001 11:39:50 AM]

Big Online Book of Linux Ada Programming - Appendix D

<--Appendix C

Table of Contents

Appendix E-->

Appendix D: Signals
Be aware that the mapping of names to signals may be -to-one. There may be aliases. Also, for allsignal names that are not supported on the current systemthe value of the corresponding constant will be zero. SIGHUP -- hangup SIGINT -- interrupt (rubout) SIGQUIT -- quit (ASCD FS) SIGILL -- illegal instruction (not reset) SIGTRAP -- trace trap (not reset) SIGIOT -- IOT instruction SIGABRT used by abort, SIGIOT in the future SIGFPE -- floating point exception SIGKILL -- kill (cannot be caught or ignored) SIGBUS -- bus error SIGSEGV -- segmentation violation SIGPIPE -- write on a pipe with no one to read it SIGALRM -- alarm clock SIGTERM -- software termination signal from kill SIGUSR1 -- user defined signal 1 SIGUSR2 -- user defined signal 2 SIGCLD -- child status change SIGCHLD -- 4.3BSD's/POSIX name for SIGCLD SIGWINCH -- window size change SIGURG -- urgent condition on IO channel SIGPOLL -- pollable event occurred SIGIO -- input/output possible, SIGPOLL alias (Solaris) SIGSTOP -- stop (cannot be caught or ignored) SIGTSTP -- user stop requested from tty SIGCONT -- stopped process has been continued SIGTTIN -- background tty read attempted SIGTTOU -- background tty write attempted SIGVTALRM -- virtual timer expired SIGPROF -- profiling timer expired SIGXCPU -- CPU time limit exceeded SIGXFSZ -- filesize limit exceeded SIGUNUSED -- unused signal SIGSTKFLT -- stack fault on coprocessor SIGLOST -- Linux alias for SIGIO
file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_d.html (1 of 2) [7/20/2001 11:40:07 AM]

Big Online Book of Linux Ada Programming - Appendix D

SIGPWR -- Power failure

<--Appendix C

Table of Contents

Appendix E-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_d.html (2 of 2) [7/20/2001 11:40:07 AM]

Big Online Book of Linux Ada Programming - Appendix E

<--Appendix D

Table of Contents

Appendix F-->

Appendix E: Ioctl parameters


man ioctl_list gives a list of operations and parameters for ioctl. This is a copy of that man page. // Introduction This is Ioctl List 1.3.27, a list of ioctl calls in Linux/i386 kernel 1.3.27. It contains 421 ioctls from /usr/include/{asm,linux}/*.h. For each ioctl, I list its numerical value, its name, and its argument type. An argument type of 'const struct foo *' means the argument is input to the kernel. 'struct foo *' means the kernel outputs the argument. If the kernel uses the argument for both input and output, this is marked with // I-O. Some ioctls take more arguments or return more values than a single structure. These are marked // MORE and documented further in a separate section. This list is incomplete. It does not include:

-- Ioctls defined internal to the kernel ('scsi_ioctl.h'). -- Ioctls defined in modules distributed separately from the kernel. And, of course, it may have errors and omissions. // Main table. // <include/asm-i386/socket.h> 0x00008901 0x00008902 0x00008903 0x00008904 0x00008905 0x00008906 FIOSETOWN const int * SIOCSPGRP const int * FIOGETOWN int * SIOCGPGRP int * SIOCATMARK int * SIOCGSTAMP timeval *

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (1 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

// <include/asm-i386/termios.h> 0x00005401 0x00005402 0x00005403 0x00005404 0x00005405 0x00005406 0x00005407 0x00005408 0x00005409 0x0000540A 0x0000540B 0x0000540C 0x0000540D 0x0000540E 0x0000540F 0x00005410 0x00005411 0x00005412 0x00005413 0x00005414 0x00005415 0x00005416 0x00005417 0x00005418 0x00005419 0x0000541A 0x0000541B 0x0000541B 0x0000541C // MORE 0x0000541D 0x0000541E 0x0000541F 0x00005420 0x00005421 0x00005422 0x00005423 0x00005424 0x00005425 0x00005426 0x00005450 TIOCCONS void TIOCGSERIAL struct serial_struct * TIOCSSERIAL const struct serial_struct * TIOCPKT const int * FIONBIO const int * TIOCNOTTY void TIOCSETD const int * TIOCGETD int * TCSBRKP int TIOCTTYGSTRUCT struct tty_struct * FIONCLEX void TCGETS struct termios * TCSETS const struct termios * TCSETSW const struct termios * TCSETSF const struct termios * TCGETA struct termio * TCSETA const struct termio * TCSETAW const struct termio * TCSETAF const struct termio * TCSBRK int TCXONC int TCFLSH int TIOCEXCL void TIOCNXCL void TIOCSCTTY int TIOCGPGRP pid_t * TIOCSPGRP const pid_t * TIOCOUTQ int * TIOCSTI const char * TIOCGWINSZ const struct winsize * TIOCSWINSZ struct winsize * TIOCMGET int * TIOCMBIS const int * TIOCMBIC const int * TIOCMSET const int * TIOCGSOFTCAR int * TIOCSSOFTCAR const int * FIONREAD int * TIOCINQ int * TIOCLINUX const char *

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (2 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00005451 0x00005452 0x00005453 0x00005454 0x00005455 0x00005456 0x00005457 0x00005458 0x00005459 0x0000545A 0x0000545B

FIOCLEX void FIOASYNC const int * TIOCSERCONFIG void TIOCSERGWILD int * TIOCSERSWILD const int * TIOCGLCKTRMIOS struct termios * TIOCSLCKTRMIOS const struct temios * TIOCSERGSTRUCT struct async_struct * TIOCSERGETLSR int * TIOCSERGETMULTI struct serial_multiport_struct * TIOCSERSETMULTI const struct serial_multiport_struct *

// <include/linux/ax25.h> 0x000089E0 0x000089E1 0x000089E2 0x000089E3 0x000089E4 0x000089E5 0x000089E6 SIOCAX25GETUID const struct sockaddr_ax25 * SIOCAX25ADDUID const struct sockaddr_ax25 * SIOCAX25DELUID const struct sockaddr_ax25 * SIOCAX25NOUID const int * SIOCAX25DIGCTL const int * SIOCAX25GETPARMS struct ax25_parms_struct * // I-O SIOCAX25SETPARMS const struct ax25_parms-struct *

// <include/linux/cdk.h> 0x00007314 STL_BINTR void

0x00007315 STL_BSTART void

0x00007316 STL_BSTOP void 0x00007317 STL_BRESET void // <include/linux/cdrom.h> 0x00005301 0x00005302 0x00005303 0x00005304 0x00005305 0x00005306 CDROMPAUSE void CDROMRESUME void CDROMPLAYMSF const struct cdrom_msf * CDROMPLAYTRKIND const struct cdrom_ti * CDROMREADTOCHDR struct cdrom_tochdr * CDROMREADTOCENTRY struct cdrom_tocentry * // I-O

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (3 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00005307 0x00005308 0x00005309 0x0000530A 0x0000530B 0x0000530C 0x0000530D 0x0000530E 0x0000530F 0x00005310 0x00005311 0x00005312 0x00005313 0x00005314 0x00005315 0x00005316

CDROMSTOP void CDROMSTART void CDROMEJECT void CDROMVOLCTRL const struct cdrom_volctrl * CDROMSUBCHNL struct cdrom_subchnl * // I-O CDROMREADMODE2 const struct cdrom_msf * // MORE CDROMREADMODE1 const struct cdrom_msf * // MORE CDROMREADAUDIO const struct cdrom_read_audio * // MORE CDROMEJECT_SW int CDROMMULTISESSION struct cdrom_multisession * // I-O CDROM_GET_UPC struct { char [8]; } * CDROMRESET void CDROMVOLREAD struct cdrom_volctrl * CDROMREADRAW const struct cdrom_msf * // MORE CDROMREADCOOKED const struct cdrom_msf * // MORE CDROMSEEK const struct cdrom_msf *

// <include/linux/cm206.h> 0x00002000 CM206CTL_GET_STAT int 0x00002001 CM206CTL_GET_LAST_STAT int // <include/linux/cyclades.h> 0x00435901 0x00435902 0x00435903 0x00435904 0x00435905 0x00435906 0x00435907 0x00435908 0x00435909 CYGETMON struct cyclades_monitor * CYGETTHRESH int * CYSETTHRESH int CYGETDEFTHRESH int * CYSETDEFTHRESH int CYGETTIMEOUT int * CYSETTIMEOUT int CYGETDEFTIMEOUT int * CYSETDEFTIMEOUT int

// <include/linux/ext2_fs.h> 0x80046601 0x40046602 0x80047601 0x40047602 EXT2_IOC_GETFLAGS int * EXT2_IOC_SETFLAGS const int * EXT2_IOC_GETVERSION int * EXT2_IOC_SETVERSION const int *

// <include/linux/fd.h> 0x00000000 FDCLRPRM void 0x00000001 FDSETPRM const struct floppy_struct * 0x00000002 FDDEFPRM const struct floppy_struct *

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (4 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00000003 0x00000004 0x00000005 0x00000006 0x00000007 0x00000008 0x0000000A 0x0000000B 0x0000000C 0x0000000E 0x00000010 0x00000014 0x00000015 0x00000016 0x00000017 0x00000018 0x00000019 0x0000001B 0x0000001C 0x0000001E 0x00000028

FDGETPRM struct floppy_struct * FDMSGON void FDMSGOFF void FDFMTBEG void FDFMTTRK const struct format_descr * FDFMTEND void FDSETEMSGTRESH int FDFLUSH void FDSETMAXERRS const struct floppy_max_errors * FDGETMAXERRS struct floppy_max_errors * FDGETDRVTYP struct { char [16]; } * FDSETDRVPRM const struct floppy_drive_params * FDGETDRVPRM struct floppy_drive_params * FDGETDRVSTAT struct floppy_drive_struct * FDPOLLDRVSTAT struct floppy_drive_struct * FDRESET int FDGETFDCSTAT struct floppy_fdc_state * FDWERRORCLR void FDWERRORGET struct floppy_write_errors * FDRAWCMD struct floppy_raw_cmd * // MORE I-O FDTWADDLE void

// <include/linux/fs.h> 0x0000125D 0x0000125E 0x0000125F 0x00001260 0x00001261 0x00001262 0x00001263 0x00000001 0x00000002 BLKROSET const int * BLKROGET int * BLKRRPART void BLKGETSIZE int * BLKFLSBUF void BLKRASET int BLKRAGET int * FIBMAP int * // I-O FIGETBSZ int *

// <include/linux/hdreg.h> 0x00000301 0x00000302 0x00000304 0x00000307 0x00000308 0x00000309 0x0000030A 0x0000030B 0x0000031F 0x00000321 HDIO_GETGEO struct hd_geometry * HDIO_GET_UNMASKINTR int * HDIO_GET_MULTCOUNT int * HDIO_GET_IDENTITY struct hd_driveid * HDIO_GET_KEEPSETTINGS int * HDIO_GET_CHIPSET int * HDIO_GET_NOWERR int * HDIO_GET_DMA int * HDIO_DRIVE_CMD int * // I-O HDIO_SET_MULTCOUNT int

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (5 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00000322 0x00000323 0x00000324 0x00000325 0x00000326

HDIO_SET_UNMASKINTR int HDIO_SET_KEEPSETTINGS int HDIO_SET_CHIPSET int HDIO_SET_NOWERR int HDIO_SET_DMA int

// <include/linux/if_eql.h> 0x000089F0 0x000089F1 0x000089F2 0x000089F3 0x000089F4 0x000089F5 EQL_ENSLAVE struct ifreq * // MORE I-O EQL_EMANCIPATE struct ifreq * // MORE I-O EQL_GETSLAVECFG struct ifreq * // MORE I-O EQL_SETSLAVECFG struct ifreq * // MORE I-O EQL_GETMASTRCFG struct ifreq * // MORE I-O EQL_SETMASTRCFG struct ifreq * // MORE I-O

// <include/linux/if_plip.h> 0x000089F0 SIOCDEVPLIP struct ifreq * // I-O // <include/linux/if_ppp.h> 0x00005490 0x00005491 0x00005492 0x00005493 0x00005494 0x00005495 0x00005497 0x00005498 0x00005499 0x0000549A 0x0000549B 0x0000549C 0x0000549D 0x0000549E 0x0000549F PPPIOCGFLAGS int * PPPIOCSFLAGS const int * PPPIOCGASYNCMAP int * PPPIOCSASYNCMAP const int * PPPIOCGUNIT int * PPPIOCSINPSIG const int * PPPIOCSDEBUG const int * PPPIOCGDEBUG int * PPPIOCGSTAT struct ppp_stats * PPPIOCGTIME struct ppp_ddinfo * PPPIOCGXASYNCMAP struct { int [8]; } * PPPIOCSXASYNCMAP const struct { int [8]; } * PPPIOCSMRU const int * PPPIOCRASYNCMAP const int * PPPIOCSMAXCID const int *

// <include/linux/ipx.h> 0x000089E0 SIOCAIPXITFCRT const char * 0x000089E1 SIOCAIPXPRISLT const char * 0x000089E2 SIOCIPXCFGDATA struct ipx_config_data * // <include/linux/kd.h> 0x00004B60 GIO_FONT struct { char [8192]; } *

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (6 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00004B61 0x00004B6B 0x00004B6C 0x00004B70 0x00004B71 0x00004B2F 0x00004B30 0x00004B31 0x00004B32 0x00004B33 0x00004B34 0x00004B35 0x00004B36 0x00004B37 0x00004B3A 0x00004B3B 0x00004B3C 0x00004B3D 0x00004B40 0x00004B41 0x00004B69 0x00004B6A 0x00004B66 0x00004B67 0x00004B68 0x00004B44 0x00004B45 0x00004B62 0x00004B63 0x00004B64 0x00004B65 0x00004B46 0x00004B47 0x00004B48 0x00004B49 0x00004B4A 0x00004B4B 0x00004B4C 0x00004B4D 0x00004B4E

PIO_FONT const struct { char [8192]; } * GIO_FONTX struct console_font_desc * // MORE I-O PIO_FONTX const struct console_font_desc * //MORE GIO_CMAP struct { char [48]; } * PIO_CMAP const struct { char [48]; } KIOCSOUND int KDMKTONE int KDGETLED char * KDSETLED int KDGKBTYPE char * KDADDIO int // MORE KDDELIO int // MORE KDENABIO void // MORE KDDISABIO void // MORE KDSETMODE int KDGETMODE int * KDMAPDISP void // MORE KDUNMAPDISP void // MORE GIO_SCRNMAP struct { char [E_TABSZ]; } * PIO_SCRNMAP const struct { char [E_TABSZ]; } * GIO_UNISCRNMAP struct { short [E_TABSZ]; } * PIO_UNISCRNMAP const struct { short [E_TABSZ]; } * GIO_UNIMAP struct unimapdesc * // MORE I-O PIO_UNIMAP const struct unimapdesc * // MORE PIO_UNIMAPCLR const struct unimapinit * KDGKBMODE int * KDSKBMODE int KDGKBMETA int * KDSKBMETA int KDGKBLED int * KDSKBLED int KDGKBENT struct kbentry * // I-O KDSKBENT const struct kbentry * KDGKBSENT struct kbsentry * // I-O KDSKBSENT const struct kbsentry * KDGKBDIACR struct kbdiacrs * KDSKBDIACR const struct kbdiacrs * KDGETKEYCODE struct kbkeycode * // I-O KDSETKEYCODE const struct kbkeycode * KDSIGACCEPT int

// <include/linux/lp.h> 0x00000601 LPCHAR int 0x00000602 LPTIME int 0x00000604 LPABORT int

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (7 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00000605 0x00000606 0x00000608 0x00000609 0x0000060A 0x0000060B 0x0000060C 0x0000060D

LPSETIRQ int LPGETIRQ int * LPWAIT int LPCAREFUL int LPABORTOPEN int LPGETSTATUS int * LPRESET void LPGETSTATS struct lp_stats *

// <include/linux/mroute.h> 0x000089E0 SIOCGETVIFCNT struct sioc_vif_req * // I-O 0x000089E1 SIOCGETSGCNT struct sioc_sg_req * // I-O // <include/linux/mtio.h> 0x40086D01 0x801C6D02 0x80046D03 0x80206D04 0x40206D05 MTIOCTOP const struct mtop * MTIOCGET struct mtget * MTIOCPOS struct mtpos * MTIOCGETCONFIG struct mtconfiginfo * MTIOCSETCONFIG const struct mtconfiginfo *

// <include/linux/netrom.h> 0x000089E0 0x000089E1 0x000089E2 0x000089E3 SIOCNRGETPARMS struct nr_parms_struct * // I-O SIOCNRSETPARMS const struct nr_parms_struct * SIOCNRDECOBS void SIOCNRRTCTL const int *

// <include/linux/sbpcd.h> 0x00009000 DDIOCSDBG const int * 0x00005382 CDROMAUDIOBUFSIZ int // <include/linux/scc.h> 0x00005470 0x00005471 0x00005472 0x00005473 0x00005474 TIOCSCCINI void TIOCCHANINI const struct scc_modem * TIOCGKISS struct ioctl_command * // I-O TIOCSKISS const struct ioctl_command * TIOCSCCSTAT struct scc_stat *

// <include/linux/scsi.h> 0x00005382 SCSI_IOCTL_GET_IDLU struct { int [2]; } * 0x00005383 SCSI_IOCTL_TAGGED_ENABLE void

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (8 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00005384 SCSI_IOCTL_TAGGED_DISABLE void 0x00005385 SCSI_IOCTL_PROBE_HOST const int // MORE // <include/linux/smb_fs.h> 0x80027501 SMB_IOC_GETMOUNTUID uid_t * // <include/linux/sockios.h> 0x0000890B 0x0000890C 0x00008910 0x00008911 0x00008912 0x00008913 0x00008914 0x00008915 0x00008916 0x00008917 0x00008918 0x00008919 0x0000891A 0x0000891B 0x0000891C 0x0000891D 0x0000891E 0x0000891F 0x00008920 0x00008921 0x00008922 0x00008923 0x00008924 0x00008925 0x00008926 0x00008927 0x00008929 0x00008930 0x00008931 0x00008932 0x00008940 0x00008941 0x00008950 0x00008951 0x00008952 0x00008960 0x00008961 SIOCADDRT const struct rtentry * // MORE SIOCDELRT const struct rtentry * // MORE SIOCGIFNAME char [] SIOCSIFLINK void SIOCGIFCONF struct ifconf * // MORE I-O SIOCGIFFLAGS struct ifreq * // I-O SIOCSIFFLAGS const struct ifreq * SIOCGIFADDR struct ifreq * // I-O SIOCSIFADDR const struct ifreq * SIOCGIFDSTADDR struct ifreq * // I-O SIOCSIFDSTADDR const struct ifreq * SIOCGIFBRDADDR struct ifreq * // I-O SIOCSIFBRDADDR const struct ifreq * SIOCGIFNETMASK struct ifreq * // I-O SIOCSIFNETMASK const struct ifreq * SIOCGIFMETRIC struct ifreq * // I-O SIOCSIFMETRIC const struct ifreq * SIOCGIFMEM struct ifreq * // I-O SIOCSIFMEM const struct ifreq * SIOCGIFMTU struct ifreq * // I-O SIOCSIFMTU const struct ifreq * OLD_SIOCGIFHWADDR struct ifreq * // I-O SIOCSIFHWADDR const struct ifreq * // MORE SIOCGIFENCAP int * SIOCSIFENCAP const int * SIOCGIFHWADDR struct ifreq * // I-O SIOCGIFSLAVE void SIOCSIFSLAVE void SIOCADDMULTI const struct ifreq * SIOCDELMULTI const struct ifreq * SIOCADDRTOLD void SIOCDELRTOLD void SIOCDARP const struct arpreq * SIOCGARP struct arpreq * // I-O SIOCSARP const struct arpreq * SIOCDRARP const struct arpreq * SIOCGRARP struct arpreq * // I-O

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (9 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00008962 SIOCSRARP const struct arpreq * 0x00008970 SIOCGIFMAP struct ifreq * // I-O 0x00008971 SIOCSIFMAP const struct ifreq * // <include/linux/soundcard.h> 0x00005100 0x00005101 0xC08C5102 0xC0045103 0x80045104 0x80045105 0x40045106 0x40285107 0x40045108 0x40045109 0x8004510A 0x8004510B 0xC074510C 0x4004510D 0xC004510E 0x4004510F 0xCFB85110 0x00005111 0x40085112 0xC0045401 0x00005402 0x00005403 0x00005404 0xC0045405 0xC0045406 0x40045407 0x40045408 0xCFB85001 0xC0046D00 0xC0046D01 0xC0216D02 0x00005000 0x00005001 0xC0045002 0xC0045003 0xC0045004 0xC0045006 0xC0045007 0x00005008 0xC0045009 SNDCTL_SEQ_RESET void SNDCTL_SEQ_SYNC void SNDCTL_SYNTH_INFO struct synth_info * // I-O SNDCTL_SEQ_CTRLRATE int * // I-O SNDCTL_SEQ_GETOUTCOUNT int * SNDCTL_SEQ_GETINCOUNT int * SNDCTL_SEQ_PERCMODE void SNDCTL_FM_LOAD_INSTR const struct sbi_instrument * SNDCTL_SEQ_TESTMIDI const int * SNDCTL_SEQ_RESETSAMPLES const int * SNDCTL_SEQ_NRSYNTHS int * SNDCTL_SEQ_NRMIDIS int * SNDCTL_MIDI_INFO midi_info * // I-O SNDCTL_SEQ_THRESHOLD const int * SNDCTL_SYNTH_MEMAVL int * // I-O SNDCTL_FM_4OP_ENABLE const int * SNDCTL_PMGR_ACCESS struct patmgr_info * // I-O SNDCTL_SEQ_PANIC void SNDCTL_SEQ_OUTOFBAND const struct seq_event_rec * SNDCTL_TMR_TIMEBASE int * // I-O SNDCTL_TMR_START void SNDCTL_TMR_STOP void SNDCTL_TMR_CONTINUE void SNDCTL_TMR_TEMPO int * // I-O SNDCTL_TMR_SOURCE int * // I-O SNDCTL_TMR_METRONOME const int * SNDCTL_TMR_SELECT int * // I-O SNDCTL_PMGR_IFACE struct patmgr_info * // I-O SNDCTL_MIDI_PRETIME int * // I-O SNDCTL_MIDI_MPUMODE const int * SNDCTL_MIDI_MPUCMD struct mpu_command_rec * // I-O SNDCTL_DSP_RESET void SNDCTL_DSP_SYNC void SNDCTL_DSP_SPEED int * // I-O SNDCTL_DSP_STEREO int * // I-O SNDCTL_DSP_GETBLKSIZ int * // I-O SOUND_PCM_WRITE_CHANNELS int * // I-O SOUND_PCM_WRITE_FILTER int * // I-O SNDCTL_DSP_POST void SNDCTL_DSP_SUBDIVIDE int * // I-O

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (10 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0xC004500A 0x8004500B 0xC0045005 0x800C500C 0x800C500D 0x0000500E 0x80045002 0x80045006 0x80045005 0x80045007 0x00004300 0xCFB04301 0xC0144302 0xC0144303 0x40144304 0x40144305 0xC0144306 0xC0144307 0x4FA44308 0x8FA44309 0x80044D00 0x80044D01 0x80044D02 0x80044D03 0x80044D04 0x80044D05 0x80044D06 0x80044D07 0x80044D08 0x80044D09 0x80044D0A 0x80044D0B 0x80044D0C 0x80044D0D 0x80044D0E 0x80044D0F 0x80044D10 0x80044D1C 0x80044D1D 0x80044D1E 0x80044DFF 0x80044DFE 0x80044DFD 0x80044DFB 0x80044DFC

SNDCTL_DSP_SETFRAGMENT int * // I-O SNDCTL_DSP_GETFMTS int * SNDCTL_DSP_SETFMT int * // I-O SNDCTL_DSP_GETOSPACE struct audio_buf_info * SNDCTL_DSP_GETISPACE struct audio_buf_info * SNDCTL_DSP_NONBLOCK void SOUND_PCM_READ_RATE int * SOUND_PCM_READ_CHANNELS int * SOUND_PCM_READ_BITS int * SOUND_PCM_READ_FILTER int * SNDCTL_COPR_RESET void SNDCTL_COPR_LOAD const struct copr_buffer * SNDCTL_COPR_RDATA struct copr_debug_buf * // I-O SNDCTL_COPR_RCODE struct copr_debug_buf * // I-O SNDCTL_COPR_WDATA const struct copr_debug_buf * SNDCTL_COPR_WCODE const struct copr_debug_buf * SNDCTL_COPR_RUN struct copr_debug_buf * // I-O SNDCTL_COPR_HALT struct copr_debug_buf * // I-O SNDCTL_COPR_SENDMSG const struct copr_msg * SNDCTL_COPR_RCVMSG struct copr_msg * SOUND_MIXER_READ_VOLUME int * SOUND_MIXER_READ_BASS int * SOUND_MIXER_READ_TREBLE int * SOUND_MIXER_READ_SYNTH int * SOUND_MIXER_READ_PCM int * SOUND_MIXER_READ_SPEAKER int * SOUND_MIXER_READ_LINE int * SOUND_MIXER_READ_MIC int * SOUND_MIXER_READ_CD int * SOUND_MIXER_READ_IMIX int * SOUND_MIXER_READ_ALTPCM int * SOUND_MIXER_READ_RECLEV int * SOUND_MIXER_READ_IGAIN int * SOUND_MIXER_READ_OGAIN int * SOUND_MIXER_READ_LINE1 int * SOUND_MIXER_READ_LINE2 int * SOUND_MIXER_READ_LINE3 int * SOUND_MIXER_READ_MUTE int * SOUND_MIXER_READ_ENHANCE int * SOUND_MIXER_READ_LOUD int * SOUND_MIXER_READ_RECSRC int * SOUND_MIXER_READ_DEVMASK int * SOUND_MIXER_READ_RECMASK int * SOUND_MIXER_READ_STEREODEVS int * SOUND_MIXER_READ_CAPS int *

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (11 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0xC0044D00 0xC0044D01 0xC0044D02 0xC0044D03 0xC0044D04 0xC0044D05 0xC0044D06 0xC0044D07 0xC0044D08 0xC0044D09 0xC0044D0A 0xC0044D0B 0xC0044D0C 0xC0044D0D 0xC0044D0E 0xC0044D0F 0xC0044D10 0xC0044D1C 0xC0044D1D 0xC0044D1E 0xC0044DFF

SOUND_MIXER_WRITE_VOLUME int * // I-O SOUND_MIXER_WRITE_BASS int * // I-O SOUND_MIXER_WRITE_TREBLE int * // I-O SOUND_MIXER_WRITE_SYNTH int * // I-O SOUND_MIXER_WRITE_PCM int * // I-O SOUND_MIXER_WRITE_SPEAKER int * // I-O SOUND_MIXER_WRITE_LINE int * // I-O SOUND_MIXER_WRITE_MIC int * // I-O SOUND_MIXER_WRITE_CD int * // I-O SOUND_MIXER_WRITE_IMIX int * // I-O SOUND_MIXER_WRITE_ALTPCM int * // I-O SOUND_MIXER_WRITE_RECLEV int * // I-O SOUND_MIXER_WRITE_IGAIN int * // I-O SOUND_MIXER_WRITE_OGAIN int * // I-O SOUND_MIXER_WRITE_LINE1 int * // I-O SOUND_MIXER_WRITE_LINE2 int * // I-O SOUND_MIXER_WRITE_LINE3 int * // I-O SOUND_MIXER_WRITE_MUTE int * // I-O SOUND_MIXER_WRITE_ENHANCE int * // I-O SOUND_MIXER_WRITE_LOUD int * // I-O SOUND_MIXER_WRITE_RECSRC int * // I-O

// <include/linux/umsdos_fs.h> 0x000004D2 0x000004D3 0x000004D4 0x000004D5 0x000004D6 0x000004D7 0x000004D8 0x000004D9 0x000004DA 0x000004DB 0x000004DC UMSDOS_READDIR_DOS struct umsdos_ioctl * // I-O UMSDOS_UNLINK_DOS const struct umsdos_ioctl * UMSDOS_RMDIR_DOS const struct umsdos_ioctl * UMSDOS_STAT_DOS struct umsdos_ioctl * // I-O UMSDOS_CREAT_EMD const struct umsdos_ioctl * UMSDOS_UNLINK_EMD const struct umsdos_ioctl * UMSDOS_READDIR_EMD struct umsdos_ioctl * // I-O UMSDOS_GETVERSION struct umsdos_ioctl * UMSDOS_INIT_EMD void UMSDOS_DOS_SETUP const struct umsdos_ioctl * UMSDOS_RENAME_DOS const struct umsdos_ioctl *

// <include/linux/vt.h> 0x00005600 0x00005601 0x00005602 0x00005603 0x00005604 0x00005605 0x00005606 VT_OPENQRY int * VT_GETMODE struct vt_mode * VT_SETMODE const struct vt_mode * VT_GETSTATE struct vt_stat * VT_SENDSIG void VT_RELDISP int VT_ACTIVATE int

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (12 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00005607 0x00005608 0x00005609 0x0000560A

VT_WAITACTIVE int VT_DISALLOCATE int VT_RESIZE const struct vt_sizes * VT_RESIZEX const struct vt_consize *

// More arguments. Some ioctl's take a pointer to a structure which contains additional pointers. These are documented here in alphabetical order. CDROMREADAUDIO takes an input pointer 'const struct cdrom_read_audio *'. The 'buf' field points to an output buffer of length CDROMREADCOOKED, CDROMREADMODE1, CDROMREADMODE2, and CDROMREADRAW take an input pointer 'const struct cdrom_msf *'. They use the same pointer as an output pointer to 'char []'. The length varies by request. For CDROMREADMODE1, most drivers use 'CD_FRAMESIZE', but the Optics Storage driver uses 'OPT_BLOCKSIZE' instead (both have the numerical value 2048). CDROMREADCOOKED char [CD_FRAMESIZE] CDROMREADMODE1 char [CD_FRAMESIZE or OPT_BLOCKSIZE] CDROMREADMODE2 char [CD_FRAMESIZE_RAW0] CDROMREADRAW char [CD_FRAMESIZE_RAW] EQL_ENSLAVE, EQL_EMANCIPATE, EQL_GETSLAVECFG, EQL_SETSLAVECFG, EQL_GETMASTERCFG, and EQL_SETMASTERCFG take a 'struct ifreq *'. The 'ifr_data' field is a pointer to another structure as follows: EQL_ENSLAVE const struct slaving_request * EQL_EMANCIPATE const struct slaving_request * EQL_GETSLAVECFG struct slave_config * // I-O EQL_SETSLAVECFG const struct slave_config * EQL_GETMASTERCFG struct master_config * EQL_SETMASTERCFG const struct master_config * FDRAWCMD takes a 'struct floppy raw_cmd *'. If 'flags & FD_RAW_WRITE' is non-zero, then 'data' points to an input buffer of length 'length'. If 'flags & FD_RAW_READ' is non-zero, then 'data' points to an output buffer of length 'length'. GIO_FONTX and PIO_FONTX take a 'struct console_font_desc *' or a a buffer of 'char [charcount]'. This is an output buffer for GIO_FONTX and an input buffer for PIO_FONTX. GIO_UNIMAP and PIO_UNIMAP take a 'struct unimapdesc *' or a of 'struct unipair [entry_ct]'. This is an output buffer for GIO_UNIMAP and an input buffer for PIO_UNIMAP.

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (13 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

KDADDIO, KDDELIO, KDDISABIO, and KDENABIO enable or disable access to I/O ports. They are essentially alternate interfaces to 'ioperm'. KDMAPDISP and KDUNMAPDISP enable or disable memory mappings or I/O port access. They are not implemented in the kernel. SCSI_IOCTL_PROBE_HOST takes an input pointer 'const int *', which is a length. It uses the same pointer as an output pointer to a 'char []' buffer of this length. SIOCADDRT and SIOCDELRT take an input pointer whose type depends on the protocol: protocols const struct rtentry * AX.25 const struct ax25_route * NET/ROM const struct nr_route_struct * SIOCGIFCONF takes a 'struct ifconf *'. The 'ifc_buf' field points to a buffer of length 'ifc_len' bytes, into which the kernel writes a list of type 'struct ifreq []'. SIOCSIFHWADDR takes an input pointer whose type depends on the protocol: Most protocols; const struct ifreq * AX.25 const char [AX25_ADDR_LEN] TIOCLINUX takes a 'const char *'. It uses this to distinguish several independent sub-cases. In the table below, 'N + foo' means 'foo' after an N-byte pad. 'struct selection' is implicitly defined in TIOCLINUX-2 1 + const struct selection * TIOCLINUX-3 void TIOCLINUX-4 void TIOCLINUX-5 4 + const struct { long [8]; } * TIOCLINUX-6 char * TIOCLINUX-7 char * TIOCLINUX-10 1 + const char * // Duplicate ioctls This list does not include ioctls in the range SIOCDEVPRIVATE and SIOCPROTOPRIVATE. 0x00000001 FDSETPRM FIBMAP 0x00000002 FDDEFPRM FIGETBSZ 0x00005382 CDROMAUDIOBUFSIZ SCSI_IOCTL_GET_IDLUN

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (14 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix E

0x00005402 SNDCTL_TMR_START TCSETS 0x00005403 SNDCTL_TMR_STOP TCSETSW 0x00005404 SNDCTL_TMR_CONTINUE TCSETSF

<--Appendix D

Table of Contents

Appendix F-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_e.html (15 of 15) [7/20/2001 11:40:32 AM]

Big Online Book of Linux Ada Programming - Appendix F

<--Appendix E

Table of Contents

Glossary-->

Appendix F: Overview of GNAT Packages


This is an overview of some of the more useful packages included with Gnat 3.13p's more than 300 standard packages: File a-astaco a-caldel a-acalend a-chahan a-chlat1 a-coliea a-colire a-comlin a-cwila1 a-decima a-adiocs a-adireio a-dynpri a-except a-exctr a-filico Package Ada.Asynchronous_Task_Control Ada.Calendar.Delays Ada.Calendar Ada.Characters.Handling Ada.Characters.Latin_1 Ada.Command_Line.Environment Ada.Command_Line.Remove Ada.Command_Line Ada.Characters.Wide_Latin_1 Ada.Decimal Ada.Direct_IO.C_Streams Ada.Direct_IO Ada.Dynamic_Priorities Ada.Exceptions Ada.Exceptions.Traceback Ada.Finalization.List_Controller Description Unimplemented Sleeping using Calendar types Standard Ada Caledar package Standard Ada character handling package Standard Latin 1 Character set definition Standard Ada environment package Unset environment variables Standard Ada command arguments package Standard Ada Latin 1 Wide character set Limits and def'ns for Decimal types Generic package for reading/writing C direct files Standard Ada generic direct I/O package Changing task priorities on-the-fly Standard Ada exception handling package Support for exception tracebacks Support for controlled tagged records

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (1 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

a-finali a-flteio a-fwteio a-inteio a-interr a-intnam a-ioexce a-iwteio a-lfteio a-lfwtio a-liteio a-liwtio a-llftio a-llfwti a-llitio a-lliwti a-ncelfu a-ngcefu a-ngcoty a-ngelfu

Standard Ada controlled tagged record package Ada.Float_Text_IO Instantiated Text_IO for floats Instantiated Wide_Text_IO for Ada.Float_WideText_IO floats Instantiated Text_IO for Ada.Integer_Text_IO integers Standard Ada signal handling Ada.Interrupts package Ada.Interrupts.Names Linux signal names I/O exceptions used in std Ada.IO_Exceptions packages Instantiated Wide_Text_IO for Ada.Integer_Wide_Text_IO integers Instantiated Text_IO for long Ada.Long_Float_Text_IO floats Instantiated Wide_Text_IO for Ada.Long_Float_Wide_Text_IO long floats Instantiated Text_IO for long Ada.Long_Integer_Text_IO integers Instantiated Wide_Text_IO for Ada.Long_Integer_Wide_Text_IO long integers Instantiated Text_IO for long Ada.Long_Long_Float_Text_IO long floats Inst. Wide_Text_IO for long Ada.Long_Long_Float_Wide_Text_IO long floats Inst. Text_IO for long long Ada.Long_Long_Integer_Text_IO integers Inst. Wide_Text_IO for long Ada.Long_Long_Integer_Wide_Text_IO long integers Inst. of std ops for complex Ada.Numerics.Complex_Elementary_Function nbrs Generic package of std ops for Ada.Numerics.Generic_Complex_Elementary_Functions complex nbrs Generic complex numbers Ada.Numerics.Generic_Complex_Types package Generic std ops for complex Ada.Numerics.Generic_Elementary_Functions numbers Ada.Finalization

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (2 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

a-nlcefu a-nlcoty a-nlelfu a-nllcef a-nllcty a-nllefu a-nscefu a-nscoty a-nselfu a-nucoty a-nudira a-nuelfu a-nuflra a-numaux a-numeri a-reatim a-retide a-sequio a-sfteio a-sfwtio a-siocst

Ada.Numerics.Long_Complex_Elementary_Functions Ada.Numerics.Long_Complex_Types Ada.Numerics.Long_Elementary_Functions Ada.Numerics.Long_Long_ Complex_Elementary_Functions Ada.Numerics.Long_Long_ Complex_Types Ada.Numerics.Long_Long_ Elementary_Functions Ada.Numerics.Short_Complex_ Elementary_Functions Ada.Numerics.Generic_Complex_Types Ada.Numerics.Short_Elementary_Functions Ada.Numerics.Complex_Types Ada.Numerics.Discrete_Random Ada.Numerics.Elementary_Function Ada.Numerics.Float_Random Ada.Numerics.Aux Ada.Numerics Ada.Real_Time Ada.Real_Time.Delays Ada.Sequential_IO Ada.Short_Float_Text_IO Ada.Short_Float_Wide_Text_IO Ada.Sequential_IO.C_Streams

Inst. of std ops for long complex nbrs Instantiation of long float complex nbrs Instantiation of std ops for long floats Inst. of std ops for long long complex nbrs Instantiation of long long float complex nbrs Inst. of std ops for long long floats Inst. of std ops for short float complex nbrs Instantiation of short float complex nbrs Inst. of std ops for short floats Instantiation of float complex numbers Generic integer random number package Inst. of std ops for float complex nbrs Floating point random number package Internal use Defn's of Pi and epsilon Real-time timing declarations Sleeping using real-time types Standard Ada generic sequential I/O package Instantiated Text_IO package for short floats Instantiated Wide_Text_IO package for short floats Generic package for reading/writing sequential C files

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (3 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

a-siteio a-siwtio a-ssicst a-ssitio a-ssiwti a-stmaco a-storio a-strbou a-stream a-strfix a-string a-strmap a-strsea a-strunb a-ststio a-stunau a-stwibo a-stwifi a-stwima a-stwise a-stwiun a-suteio

Ada.Short_Integer_Text_IO Ada.Short_Integer_Wide_Text_IO Ada.Streams.Stream_IO.C_Streams Ada.Short_Short_Integer_Text_IO Ada.Short_Short_Integer_ Wide_Text_IO Ada.Strings.Maps.Constants Ada.Storage_IO Ada.Strings.Bounded Ada.Streams Ada.Strings.Fixed Ada.Strings Ada.Strings.Maps Ada.Strings.Search Ada.Strings.Unbounded Ada.Streams.Stream_IO Ada.Streams.Unbounded.Aux Ada.Strings.Wide_Bounded Ada.Strings.Wide_Fixed Ada.Strings.Wide_Maps Ada.Strings.Wide_Search Ada.Strings.Wide_Unbounded Ada.Strings.Unbounded.Text_IO

a-swmwco Ada.Strings.Wide_Maps.Wide_Constant

Instantiated Text_IO package for short integers Inst. Wide_Text_IO package for short integers Package for reading/writing C streams Inst. Text_IO package for short short integers Inst. Wide_Text_IO package for short short integers Upper_Set, Lower_Set and other char mappings Standard Ada bounded strings package Standard Ada streams package Standard Ada fixed strings package Standard Ada string defn's Standard Ada string mapping package Internal Use Standard Ada unbounded strings package Standard Ada streams I/O package Additional unbounded string subprograms Wide bounded strings package Wide fixed strings package Wide version of strings.maps Internal Use Wide unbounded strings package Unbounded strings package Upper_Set, Lower_Set and other wide char mappings

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (4 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

a-swuwti a-sytaco a-tags a-tasatt a-taside a-teioed a-textio a-ticoau a-ticoio a-tideau a-tideio a-tienau a-tienio a-tifiio a-tiflau a-tiflio a-tigeau a-tiinau a-tiinio a-timoau a-timoio a-tiocst a-titest a-unccon a-uncdea a-witeio

Ada.Strings.Wide_Unbounded.Wide_Text_IO Ada.Synchronous_Task_Control Ada.Tags Ada.Task_Attributes Ada.Task_Identification Ada.Text_IO.Editing Ada.Text_IO Ada.Text_IO.Complex_Aux Ada.Text_IO.Complex_IO Ada.Text_IO.Decimal_Aux Ada.Text_IO.Decimal_IO Ada.Text_IO.Enumeration_Aux Ada.Text_IO.Enumeration_IO Ada.Text_IO.Fixed_IO Ada.Text_IO.Float_Aux Ada.Text_IO.Float_IO Ada.Text_IO.Generic_Aux Ada.Text_IO.Integer_Aux Ada.Text_IO.Integer_IO Ada.Text_IO.Modular_Aux Ada.Text_IO.Modular_IO Ada.Text_IO.C_Streams Ada.Text_IO.Text_Streams Ada.Unchecked_Conversion Ada.Unchecked_Deallocation Ada.Wide_Text_IO

Wide unbounded strings package Subprograms to synchronize tasks Standard Ada tag package Set/get task attributes Task ID package Package for formatted Text_IO Standard generic Text_IO package Basic long long complex I/O package Generic Text_IO package for complex numbers Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Internal Use Text_IO for reading/writing C text files Text_IO stream definition Standard Ada unchecked conversions subprogram Standard Ada unchecked deallocation subprogram Text_IO package for wide characters

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (5 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

a-wtcoau a-wtcoio a-wtcstr a-wtdeau a-wtdeio a-wtedit a-wtenau a-wtenio a-wtfiio a-wtflau a-wtflio a-wtgeau a-wtinau a-wtinio a-wtmoau a-wtmoio a-wttest g-busora g-busorg g-calend g-casuti g-catiio g-comlin g-curexc

Ada.Wide_Text_IO.Complex_Aux Ada.Wide_Text_IO.Complex_IO Ada.Wide_Text_IO.C_Streams Ada.Wide_Text_IO.Decimal_Aux Ada.Wide_Text_IO.Decimal_IO Ada.Wide_Text_IO.Editing Ada.Wide_Text_IO.Enumeration_Aux Ada.Wide_Text_IO.Enumeration_IO Ada.Wide_Text_IO.Fixed_IO Ada.Wide_Text_IO.Float_Aux Ada.Wide_Text_IO.Float_IO Ada.Wide_Text_IO.Generic_Aux Ada.Wide_Text_IO.Integer_Aux Ada.Wide_Text_IO.Integer_IO Ada.Wide_Text_IO.Modular_Aux Ada.Wide_Text_IO.Modular_IO Ada.Wide_Text_IO.Text_Streams GNAT.Bubble_Sort_A GNAT.Bubble_Sort_G GNAT.Calendar GNAT.Case_Util GNAT.Calendar.Time_IO GNAT.Command_Line GNAT.Current_Exception

Basic Text_IO package for long long float complex numbers Generic Wide_Text_IO package for complex numbers Wide_Text_IO package for reading/writing wide C text files Internal Use Internal Use Package for formatted Wide_Text_IO Internal Use Internal Use Internal Use Internal Use Internal Use Used by wide character IO generic packages Internal Use Internal Use Internal Use Internal Use Definition of wide text I/O streams Bubblesort using access types Generic bubblesort package Ada.Calendar plus day of week, second duration, etc. Character case conversion without Characters.Handling Formatted I/O for time values, like Linux strftime() More powerful than Ada.Command_Line, like Linux getopts() DEC Ada 83 / VADS Ada style exception handling

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (6 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

g-debpoo g-debuti g-dirope g-except g-flocon g-hesora g-hesorg g-htable g-io g-io_aux g-locfil g-os_lib g-regexp

GNAT.Debug_Pools GNAT.Debug_Utilities GNAT.Directory_Operations GNAT.Exceptions GNAT.Float_Control GNAT.Heap_Sort_A GNAT.Heap_Sort_G GNAT.HTable GNAT.IO GNAT.IO_Aux GNAT.Lock_Files GNAT.OS_Lib GNAT.Regexp

Storage pool with allocation and dereference error checking Program debugging utilities: eg. system address output Linux directory changing, creating, walking Ada predefined exceptions for pure packages Set the floating point processor back to the Gnat defaults Heapsort package using access types Generic heapsort package Generic hash table package Text I/O for preelaborated packages Get_Line functions and file existence test for Text_IO Package for locking files/directories with retry capability Package for common Linux O/S operations Simple package for Linux globbing pattern matching and Ada BNF Package providing full UNIX regular expression pattern matching Check for a typo, similar to my Typo_Of in TextTools Package providing SPITBOL pattern matching SPITBOL string processing data structures Boolean type SPITBOL table Integer type SPITBOL table

g-regpat g-speche g-spipat g-spitbo g-sptabo g-sptain

GNAT.Regpat GNAT.Spell_Checker GNAT.Spitbol.Pattern GNAT.Spitbol GNAT.Spitbol.Table_Boolean GNAT.Spitbol.Table_Intege

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (7 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

g-sptavs g-table g-tasloc g-thread g-traceb g-trasym i-c i-cexten i-cobol i-cpoin i-cpp i-csthre i-cstrea i-cstrin i-fortra i-os2err i-os2lib i-os2syn i-os2th i-pacdec i-vxwork i-addimg s-arit64

GNAT.Spitbol.Table_VString GNAT.Table GNAT.Task_Lock GNAT.Threads GNAT.Traceback GNAT.Traceback.Symbolic Interfaces.C Interfaces.C.Extensions Interfaces.COBOL Interfaces.C.Pointers Interfaces.CPP Interfaces.C.Sthreads Interfaces.C_Streams Interfaces.C.Strings Interfaces.Fortran Interfaces.OS2Lib.Errors Interfaces.OS2Lib Interfaces.OS2Lib.Synchronization Interfaces.OS2Lib.Threads Interfaces.Packed_Decimal Interfaces.VxWorks System.Address_Image System.Arith_64

Unbounded string type SPITBOL table Dynamic one-dimensional arrays package Package for protecting critical regions in tasks Import C threads as Ada tasks Non-symbolic traceback support Symbolic tracebacks Standard Ada C interfacing package Additional C types not covered by Interfaces.C Standard Ada COBOL interfacing package C style pointer arithmetic GNAT C++ class interfacing package Dummy package Thin binding to C sequential files GNAT C string operations Standard Ada Fortran interfacing package OS/2 error codes OS/2 support OS/2 support OS/2 support Packed decimal fixed types support for Machine_Radix 10 computers VxWords API support Function returning a system.address image 64 bit arithmetic with support for intermediate results > 64 bits

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (8 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Appendix F

s-atacco

System.Address_To_Access_Conversions

s-bitops.ads System.Bit_Ops s-chepoo i-exngen s-pooglo s-pooloc s-powtab s-stoele System.Checked_Pools Exn_Float_Type System.Pool_Global System.Pool_Local System.Powten_Table System.Storage_Elements

Converting between simple pointers and access types Low-level bitwise operations for 1, 2 or 4 bytes Storage pool with a function called for any dereference Generic function for signed integer exponentiation normal heap for GNAT global access types normal heap for GNAT local access types table of powers of 10 Standard Ada package

<--Appendix E

Table of Contents

Glossary-->

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_f.html (9 of 9) [7/20/2001 11:40:56 AM]

Big Online Book of Linux Ada Programming - Glossary

<--Appendix F

Table of Contents

End of Book

Glossary
AARM The Annotated Ada Reference Manual contains the entire text of the Ada 95 standard (ISO/IEC 8652:1995(E)), plus various annotations. It is intended primarily for compiler writers, validation test writers, and other language lawyers. The annotations include detailed rationale for individual rules and explanations of some of the more arcane interactions among the rules. Ada 9X the working title of Ada 95 before the language was completed. ASIS The Ada Semantic Interface Specification is a layered vendor-independent open architecture. ASIS queries and services provide a consistent interface to information within the Ada compilation environment. Dynamic Polymorphism Polymorphism implemented at run-time using a "tag" to determine the type of item; tagged records, objects. Inheritance Creating new items containing an original item's features without changing the original item. LRM is the abbreviated name of the Language Reference Manual, sometimes called Ada Reference Manual. "LRM" was often used in the days of Ada 83; "RM" or "rm95" Multiple Inheritance Creating new items from two or more original item's features without changing the original item. Polymorphism A means of factoring out differences amongst a collection of items so that programs may be written in terms of the common features. RM see LRM. RM95 see LRM. Static Polymorphism Polymorphism implemented at compile-time; generics.

<--Appendix F

Table of Contents

End of Book

file:///G|/Linux/http-www.vaxxine.com-pegasoft-people-html/book/99_z.html [7/20/2001 11:41:10 AM]

You might also like