
Lesson 6

          Libraries, why we have them, and how to make and use them.

  In order to simplify the creation of programs for its customers,
software vendors make available one or more libraries of functions
which have general application.

        When you write a program in 'C' much, if not most, of the "hard work"
is done by explicitly called functions, which you call by simply writing
their names in your program script. Unfortunately there is a little bit
more to it than that. If the function returns a value which is other
than of type int, you have to tell the compiler the type of the returned
value. An example will, I hope make things clear.

        Lets's suppose that you have been given the task of, making things
stupidly simplistic for a book example, sorting a list of names into
alphabetical order. ( Yes, I do know this can, and should be done in just
one line of shell script! However that's another story for another day. )

        You look diligently through the Programmer Reference Manual, discover
that the prose is almost opaque, and find a couple of interesting looking
routines called strcmp, and qsort. You decide to use these library
functions. Now for just a moment lets consider the ins and outs of what,
in effect, you have just done. You have just asked a member of the team
of programmers who created the library to join you, by proxy as it were, in
creating your masterpiece. A useful concept, which has been in use
almost since the start of electronic computing.

        To re-focus the mind on the task at hand; let's look in the Reference
Manual
at the page for qsort(3C) - The 3C in parenthesis is the cryptic code which
is the unix apology for a reference to section 3C in the Manual! So find
section 3C and look up qsort. Now have a look at the SYNOPSIS, and notice
that there is no mention of a header file to #include, and also notice that
qsort returns a void, not an int. This means that there is no header file
/usr/include/qsort.h ( for my version of unix - system V Release 3.2.2 -
anyway ) and you have to declare qsort yourself as an external function.
Also turn to the page string(3C) in the fine manual. Notice that the
SYNOPSIS here includes the line #include <string.h> so you have to put
it in your program text. Once more an example to make it all clear.


/* ----------------------------------------- */

#ident "@(#) qsort-demo.c"

#include <stdio.h>
#include <string.h>
#include <assert.h>

extern void qsort ();
extern int strcmp();        /* Some compilers need this defined, most don't. */

char names[22][25] =                         /* Here are some names to sort. */
{
  "John Nagle", "Colin Douthwaite", "Ian Lance Taylor", "Brian J. Murrell",
  "Pete", "Geoff Mccaughan", "David Liebert", "Operator", "Bill Baucum",
  "Victor Volkman", "Chay R Harley", "Dan Romanchik", "Larry Kollar",
  "Gaston Ormazabal", "Arijit Chandra", "Kenneth Mark Hopkinson",
  "Kerr Hatrick", "Tim Love", "Robert M. Juranitch", "Jeffrey Micke",
  "Duong Quoc", "Jagadesh Vasudevamurthy"
        };

#define NUMBER_OF_NAMES sizeof ( names ) / sizeof ( names[0] )

main()
{
  int i;

        /*
        ** Print the unsorted names.
        */

        printf ( "The Unsorted Names.\n" );
  for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] );

        /*
        ** Print a prompt, and wait.
        */

        printf ( "Press RETURN to continue: " );
        fflush ( stdout );
        getchar();

        /*
        ** Now apply qsort to the arrary of character strings.
        */

        qsort (( char * ) names, NUMBER_OF_NAMES, sizeof ( *names ), strcmp );

        assert ( names[0][0] < names[1][0] );  /* Quick check to see it's done
it. */

        /*
        ** Print the sorted names.
        */

        printf ( "The Sorted Names.\n" );
  for ( i = 0; i < NUMBER_OF_NAMES; i++ ) printf ( "%s\n", names[i] );
  }

/* ----------------------------------------- */

  Note very well:-

        I wanted 22 short character strings for the data items
for the demo to sort. So grep, uniq, cut, tail, and finally a tiny bit of
vi fished eminently suitable strings out of "mail.received". If your name
is not on the list, well I'm sorry, but the world is not a fair place!

  So that's how you use library routines. I chose qsort because it is
simple to use, and shows off a feature of 'C' well, that's the ability
to use a name of a function as a pointer and then execute that function
from within the called function. It's strcmp in this case. A quick look
at the compiler output is instructive.

  As is the nature of the animal, a tin-pot little program, which should
have taken all of ten minutes to get going in fact took more like two
hours. I put it down to the fact that the Fine Manual did not make it
adequately obvious that the data array acted on by qsort was the data itself.
From reading the Fine Manual I got the impression that the array acted on
was an array of pointers. You live and learn. It would be a much faster
qsort if, in fact, the sorting function sorted pointers to data instead of
the data itself. You might like to make a function qsort_p which worked in
in this way. The qsort algorithm is well documented elsewhere.

        There is just one more point to notice about using function libraries.
The 'C' compilation system will load functions from the library /lib/libc.a
as a default. All others have to be indicated to the linking loader by a
switch on the shell interactive command line.

$ cc -o prog prog.c -L /usr/local/lib -lgdbm -lmalloc

        You might use this command line to compile and link a program which
uses both the GNU gdbm data-base manager library, which is installed in
the directory /usr/local/lib, and the enhanced malloc library. Now, there
hangs a tale! I remember having to compile a program suit off Usenet and
it just would not work properly. No error messages, no warnings, no
missing linking-loader symbols. It just "died" when I tried to run it.
After many, many hours of total frustration, I thought that I would try
linking in the enhanced malloc library. Presto! It worked.

        Note very well.

  A common misconception is the notion that having a #include <whatever.h>
line in the source text will automagically tell the linking loader to
get the functions from the appropriate library. Remove this erroroneous
notion from your mind. It won't. The -lwhatever flag on the shell command
line which initiates execution of "cc" or "ld" is the only way to tell the
loader where to look for the required library.


--
 +----------------------------------------------------------------------+
 | NAME   Christopher Sawtell                                           |
 | SMAIL  215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.|
 | EMAIL  chris@gerty.equinox.gen.nz                                    |
 | PHONE  +64-3-389-3200   ( gmt +13 - your discretion is requested )   |
 +----------------------------------------------------------------------+
