next up previous contents
Next: Prospering With Miranda Up: Appendices Previous: Appendices   Contents

Subsections

Compiling, Running and Debugging Programs

Dennis Cook, Scott Glenn Hopwood, Christopher Fraser,
Lab Assistant and Ex-President Leroy, who has retired
to surf, rob banks and jump out of aeroplanes

C

The C compiler works in a similar fashion to the Pascal compiler, and can be used to compile single or multiple files. The default C compiler compiles ``traditional'' C, the language defined in the first edition of The C Programming Language (1st Ed.) by Kernighan and Ritchie. See the section on the GNU C Compiler (gcc) for a description of how to compile programs written in ANSI C.

Compiling a Single File

The command for invoking the C compiler is

cc options files

where again, the executable is placed in a file in the current directory and called a.out.

For example, if you have a simple C program in a file called hello.c which looks like this

#include <stdio.h>

main()
{
    printf("Hello.\n");
}

...you would compile and run it like this...

sally% cc hello.c
sally% a.out
Hello.
sally% _

As usual, cc reports nothing if the compilation is successful. When it comes to reporting errors, the C compiler tends to be less helpful than the Pascal compiler, but still indicates line numbers, for example

sally% cat hello.c

#include <stdio.h>

main()
{
    printf(Hello.\n");
}
sally% cc hello.c
"hello.c", line 5: Hello undefined
"hello.c", line 5: illegal character: '\'
"hello.c", line 5: n undefined
"hello.c", line 5: newline in string or char constant
"hello.c", line 6: syntax error at or near string ");?
sally% _

Multiple Files

The C compiler works on multiple files in much the same way as the Pascal compiler. Like the Pascal compiler, you just specify the names of the files on the command line. For example, if your source code were in two files, called square.c and sqr.c, your compilation would look something like this:

sally% cat square.c
#include <stdio.h>

main()
{
        int i;
        char buf[80];

        extern int sqr();

        printf("Enter a number: ");
        i = atoi(fgets(buf, 80, stdin));

        printf("%d * %d = %d\n", i, i, sqr(i));
}
sally% cat sqr.c
int sqr(i)
        int i;
{
        return i * i;
}
sally% cc square.c sqr.c
square.c:
sqr.c:
Linking:
sally% a.out
Enter a number: 6
6 * 6 = 36
sally% _

Error messages for unresolved external linkages are the same as those generated by the Pascal compiler, as both compilers call ld to link the object files to form an executable.

The standard name of the executable, as you will have noticed, is ``a.out'' -- this can be changed by using the -o option. You might type cc square.c sqr.c -o Square in the above example to generate an executable which could be run with the command Square.

A utility called make exists which allows the user to maintain, update and regenerate object and executable files in a far more elaborate and time-saving fashion. See the manual entry or the Compiling Unix Software chapter for more information.

The GNU C Compiler (gcc)

The other C compiler available on the system is a public domain system provided by the Free Software Foundation, called gcc. This compiler will compile both traditional and ANSI C programs, is invoked by the command gcc, and behaves in a more or less similar fashion to cc. See Kernighan and Ritchie, 1988 for a description of ANSI C and the differences between it and traditional C.

Run-Time Errors

Executables produced by the C compiler have the same lack of run-time support as those produced by Pascal; most trivial errors, especially illegal subscripts will be ignored unless they interfere with the operating system, whereupon they produce core dumps.

A number of debuggers are available for work with C programs, including dbx, which functions in the same manner as it does for Pascal programs[*]. There is also an all-singing, all-dancing, X Windows based debugger called ups; for further information on this, see the comprehensive manual entry. Again, it helps if you compile your C programs with the -g flag, to produce debugging information.

C++ - A Note

The Free Software Foundation C++ compiler, g++, has been installed on the SoCS machines. Consult the manual entry. There's also Borland C++ 4.0 on the 386 PCs on level 2, as long as those dweebs playing DooM and Street Fighter haven't deleted it again.

COBOL

COBOL? Here's a nice picture instead:

Eiffel

This is what you're really looking in this section for, isn't it? It's a problem really, because Eiffel changes almost every year into something completely strange and unknown, making all manuals out of date, and all the writers of such manuals very rich, because everyone needs the new ones.

Let's see what we can do. In 1996, you could do the following things with Eiffel compilations[*]

eifstart
The first time you compile an Eiffel programme, you won't have all the supporting files which Eiffel generates to do all the linking and bounds checking and so on which it does without telling you[*].

This means you can't run thing quickly and easily, but will be in for a compile which takes an hour or so[*] ...To compile at this nascent stage of your life, you have to type eifstart when in the directory with your thing.e files and your Ace file. The Ace file acts much as a Makefile does[*].

After a bit of churning for a which, you'll get some response from the computer. Probably error messages. You'll have to fix those syntax errors and try again, but at least, after one success, you can use...

eif
Once you've gone through the torturous process of a clean compilation once, Eiffel will have created lots of temporary[*] files, and put them in a directory called EIFGEN. It will also have created a file called melted.eif.

You can now compile Eiffel programmes using eif. It's much faster than using eifstart, because it doesn't bother to regenerate the files in EIFGEN, it uses the files already there. It also uses the file called melted.eif. There's occassionally another file with the .eif extension generated. Don't delete this one either.

If eif doesn't work, you've probably deleted some necessary file, or Eiffel's corrupted them, you'll have to clean up your work and use eifstart again. You can do this by deleting the *.eif files and the EIFGEN directory[*].

An alternative way to clean up is to use...

eifclean
eif no longer works? You're getting al kinds of weird error messages? It's time to use eifclean!

This does everything I've mentioned above, but maybe cleaner. It may find little files you don't want that are lurking in corners. It works quite well, but it's slow. Deleting manually is faster if there's a big load on the system[*].

Use it. Or don't, if you think you know what you're doing. Just don't come running to us when you stuff it up.

The author claims a complete lack of knowledge about anything else to do with Eiffel, despite having fielded many queries from first-year students[*] in the course of 1996.

Ask your tutor.

Pascal

The Pascal compiler can be used to compile Pascal programs in single files, as well as large programs in multiple files. Before running the Pascal compiler, you will need to have the directory /usr/lang in your PATH environment variable.

Compiling a Single File

Assuming you have a program in a single file, the command to compile it is pc filename, which leaves an executable file called a.out, which you can run by typing a.out at the command line. For example, if you have a program in a file called hello.p, which looks like...

program hello(input,output);

begin
    writeln('Hello.')
end.

...you compile it and run it like this...

sally% pc hello.p
sally% a.out
Hello.
sally% 

No messages from the compiler indicate a clean compile. If your program were to contain an error, for example...

program hello_with_error(input,output);

begin
    writeln(Hello.')
end.

...the Pascal compiler will indicate with various abusive messages, along the lines of...

sally% pc hello.p
Fri Mar  5 14:52:56 1993  hello.p:
     4      writeln(Hello.')
     E ------------------------^--- Unmatched ' for string
     E ------------------^--- Undefined record
     E ------------------------^--- Expected identifier
     e ------------------------^--- Replaced character with a ')'
In program hello:
 E - Hello undefined on line 4
Compilation failed
sally% _

But what does this all mean? When the compiler finds an error, it prints out the line and its number, and then lists any errors below. Errors marked with a lower case e are minor errors, while errors marked with a capital E are Big Ones, from which your compilation Will Not Recover. In each case, the compiler will point at the position on the line where it thinks things went wrong.

You will note that the a.out file is quite large[*]; for the simple program presented here, it was around 112 blocks. To save disk space, you should always delete executable files as soon as you've finished with them.

Multiple Files

When you're dealing with very large programs, you may find it easier to split them across several files. In order to compile several files, just specify them all on the command line. For example if you have a file called square.p containing

(* File square.p *)
program square_a_number(input,output);

function square(var n: integer): integer; extern;

var i : integer;

begin
    write('Enter a number: ');
    readln(i);
    writeln(i, ' squared = ', square(i))
end.

...and the file containing the function square is called sqr.p and looks like this...

(* File sqr.p *)

function square(i : integer): integer;

begin
    square := i * i
end;

...you can compile like this...

sally% pc square.p sqr.p
square.p:
sqr.p:
Linking:
sally% _

If you declare a procedure or function to be external, but fail to actually define it, your compilation will fail. For example, if you were to try and compile the previous example by just compiling the file square.p you'll get this mess...

sally% pc square.p
ld: Undefined symbol 
   _square 
Compilation failed
sally% _

The message you get is from ld, the link driver which links together separately compiled files.

Run-Time Errors

Occasionally, program will contain errors serious enough to cause them to abort, or ``crash''. Unfortunately, the Pascal compiler does not generate particularly robust executable files; errors will not generally be detected until the program starts interfering with the operating system, typically by trying to access a memory location outside it's own segment[*]. When it does crash, it copies the area of memory it was working with into a file called core in the current directory; this is what the message Core Dumped means. The core file is dumped in the hope that the user can use it to carry out some form of autopsy and find out why it died[*].

Trouble is, while the core files produced by the executables from the various C compilers are useful, the ones produced from Pascal executables are generally about as much use as a sense of tact is for a drag queen. At this point a debugger becomes useful.

The dbx Debugger

dbx is a fairly simple debugger that will work on executables produced by just about any compiler. In order to use it effectively, compile your Pascal programs with the -g flag, i.e. pc -g thing.p This tells the compiler to generate a symbol table for use by dbx and any other debuggers; amongst other things it associates memory addresses with variable names, and with actual lines of code in the source files.

To run dbx, type dbx filename, where filename is the name of your executable file, usually a.out. It will then load the executable, and give you a (dbx) prompt. At this point, the easiest way to see where you program crashed is to type run. For example, assuming our program looked this...

program stuff_up(input,output);

var a : array [1..10] of integer;
    i : integer;

begin
    i := 10;
    repeat
        a[i] := 1;
        i := i - 1
    until i = 10
end.

...the session might look something like this...

sally% pc -g stuffup.p 
sally% a.out
Bus error (core dumped)
sally% dbx a.out
Reading symbolic information...
Read 259 symbols
program terminated by signal BUS (alignment error)
(dbx) run
Running: a.out 
signal SEGV (access to address exceeded protections)
  in program at line 9 in file "stuffup.p"
    9           a[i] := 1;
(dbx) print a[i]
subscript out of range
(dbx) print i
i = -1860
(dbx) print a[1]
`a[1] = 1
(dbx) quit
sally% _

A number of things are demonstrated here.


next up previous contents
Next: Prospering With Miranda Up: Appendices Previous: Appendices   Contents
root
1999-09-26