C Client Program Passing Array to ALGOL Library

The following examples illustrate the C syntax for calling a library. The examples also illustrate the ability to pass arrays between C and ALGOL.

The following is a file named FOO, which is specified by a #include statement in the C client program. This file contains the import declaration for a procedure called LC.

extern “ALGOL” void LC (char*, char (&)[ ], int, int&, __heap_t,
                        __errno_t);

In the FOO file, the use of the string “ALGOL” has the following effects on the declaration:

  • The return type of void causes the declaration to be interpreted as an untyped procedure rather than an integer procedure.

  • Normally, C passes all parameters by value. The string “ALGOL” identifies LC as a non-C procedure, thereby allowing parameters to be passed by reference. Call-by-reference parameters are denoted by the ampersand (&) operator. For example, int& matches a call-by-reference integer, and char (&) [] matches a call-by-reference unbounded EBCDIC array.

  • The string “ALGOL” also allows some hidden parameter types to be included in the import procedure declaration. In FOO, the hidden parameters are __heap_t and __errno_t. These parameters are supplied by the compiler, and are not mentioned in the statement in the C program that invokes the imported procedure. The __heap_t parameter passes the C program's heap as an EBCDIC array with 0 lower bound. The __errno_t parameter passes the predeclared global variable errno as a call-by-name integer.

Notice that the import procedure name, LC, is given in all uppercase. This is because many languages, including ALGOL, do not allow library objects to be exported with names containing lowercase letters.

The following is the C client program FOO/C.

#include <stdio.h>
#include “foo” (bytitle=“OBJECT/FOO/A”, intname=“FOO”)

main (int argc, char *argv []) {
   char buf [10];
   int  i, len;

   for (i=1; i<argc; i++) {
      errno = 0;
      LC (argv [i], buf, sizeof (buf), len);
      if (errno!= 0) {
         printf (“string too long: %d > %d\n”, len-1, sizeof (buf)-1);
         errno = 0;
      } else {
         printf (“(%2d) \”%s\” -> \”%s\”\n”, len-1, argv [i], buf);
      }
   }
}

The #include “foo” line in this client program serves as the library declaration. This program calls the imported procedure LC to convert some text to lowercase letters. Notice that the invocation of LC has only four parameters supplied. The compiler automatically supplies parameters for __heap_t and __errno_t as described previously.

After invoking LC, the program uses the variable errno to read and update the error value returned by the library in the __errno_t parameter. Notice that the C program initializes errno to 0 before calling LC. The library functions responsible for assigning errno only modify the errno value if an error occurs. These functions do not automatically assign a value of 0 to errno when a valid result occurs, as the 0 would overwrite any value left to record a previous error.

The following is the ALGOL library FOO/A, which is used by the C program FOO/C.

BEGIN
   PROCEDURE LC (PTR, BUF, BUFSIZE, LEN, HEAP, ERRNO);
      VALUE PTR, BUFSIZE;
      INTEGER PTR, BUFSIZE;
      EBCDIC ARRAY BUF [*], HEAP[0];
      INTEGER LEN, ERRNO;
    BEGIN
      DEFINE MAX_LEN = 65536 #;
      POINTER P;
      INTEGER L;
      TRANSLATETABLE DOWNCASE(EBCDIC TO EBCDIC,
         “ABCDEFGHIJKLMNOPQRSTUVWXYZ” TO “abcdefghijklmnopqrstuvwxyz”);
      SCAN P:HEAP [PTR] FOR L:MAX_LEN UNTIL = 48”00”;
      LEN:= MAX_LEN - L + 1; % +1 for trailing null
      IF LEN > BUFSIZE THEN BEGIN
         ERRNO:= 1;
      END ELSE BEGIN
          REPLACE BUF [0] BY HEAP [PTR] FOR LEN WITH DOWNCASE;
      END IF;
    END;

    EXPORT LC;
    FREEZE(TEMPORARY);
END.

In this example, the BUF parameter is specified as unbounded in order to match the char (&) [] parameter in the FOO file. The HEAP parameter is specified with a lower bound of 0 because C passes the __heap_t parameter this way.

Note that the PTR parameter is declared as an integer. The program is able to use PTR as a pointer by including it in the pointer expression HEAP [PTR]. This technique works reliably only if the MEMORY_MODEL compiler control option in the C program specifies a one-dimensional memory model. If the C program had specified a two-dimensional memory model, this ALGOL program would have to use the HEAPTOPTR function to convert the integer value to a pointer.

The SCAN statement and the LEN assignment statement both rely on the fact that C terminates each string with a null character.

As noted in the description of the C program, this procedure assigns a value to ERRNO only if an error is encountered.