Posted by : ANIMESH SHAW Saturday, 17 September 2011


§15 Miscellaneous Library Routines

The C standard specifies that the following headers and their related library routines must be available:
 
                       
                          
                        
                        
                       
 
Obviously you should avoid using these names for your own header files. In addition, C++ also has and , so don't use these either. There are far too many routines in the standard libraries for me to describe them all, which is as good an excuse as any not to bother. I will, however, present a few program examples or program fragments for the more commonly used routines. You should refer to the DEC C Run Time Library Manual, using BookReader or MGBOOK to get the latest version, and familiarize yourself with what is available. VMS provides several Unix style functions in and . To be strictly accurate, these are nonportable, but they are available on many Unix systems. One such function is getenv, which, in Unix land, gets the string value of "environment variables", which roughly correspond to DCL symbols, or logicals names. On the VAX or Alpha, the getenv function first looks for a logical name match, and returns the translation if it finds one, else it looks for a local symbol with the same name and returns the definition, or, if that wasn't found it looks for a global symbol. Compile and run "symbols.c" and try defining MYSYM as a symbol, and as a logical name, and see what output you get.
 
/*---- Getting Symbols or Logical Names C Example ("symbols.c") --------------*/
 
/* ANSI C Headers */
#include 
#include 
 
/* Main Program starts here */
int main( int argc, char *argv[] )
{
    char *s_ptr;
/*  End of declarations ... */
 
    printf("MYSYM = \"%s\"\n", ( s_ptr = getenv("MYSYM")) ? s_ptr : "" );
 
    exit(EXIT_SUCCESS);
}
 
Getting the time is another commonly required function, and C provides a number of standard routines for this purpose. An example program demonstrates the use of various time routines, including strftime, which is very flexible in letting you form a formatted time string.
 
/*---- Getting the time ("time.c") -------------------------------------------*/
 
/* ANSI C Headers */
#include 
#include 
#include 
 
/* Main Program starts here */
int main( int argc, char *argv[] )
{
    time_t c_time;
    struct tm *c_time_rec;
    char string[80];
/*  End of declarations ... */
 
/*  Get the current time */
    time(&c_time); /* c_time now contains seconds since January 1, 1970 */
 
/*  Convert this to a string using the ctime() function */
    printf("%s\n", ctime( &c_time ) );
 
/*  Split the time into it's components - hours, minutes, seconds etc. */
    c_time_rec = localtime( &c_time );
 
/*  Selectively copy day of week into string */
    strftime( string, sizeof(string)-1, "Today is %A", c_time_rec );
 
/*  Print out the day of the week */
    printf("%s\n", string );
 
    exit(EXIT_SUCCESS);
}
 
It is important to use the standard defined types for time variables, like time_t, and not use, say, unsigned int because "you know that's what it is". I say this because some systems are going to have a 2038 bug, a bit like the millenium bug, caused by the number of seconds since January 1, 1970 exceeding the storage capacity of the type currently used for time_t. Compiler vendors might well change time_t to be something completely different in future, like a 64 bit quantity or perhaps a structure. If you have used time_t throughout your code, a simple recompilation and relink will be all that you need to do, and this will avoid your name being cursed by later generations of programmers, or your being ejected into space by HAL ;-)
String-to-number conversion is a topic that frequently crops up in the comp.lang.c Usenet news group. You have already met sprintf, which is the number-to-string converter. Other functions, like atoi and atof convert strings to ints and floats, and strtod and strtol convert strings to double and long respectively. Random integer numbers, seeded usingsrand, can be obtained using the rand function, and if you want floating point numbers, cast the result of rand to float and divide by the macro value RAND_MAX, also cast to float. Searching and sorting routines, bsearch and qsort are also provided. They expect you to pass a pointer to a function which is used to determine whether objects compare equal, greater than or less than, then they do the sorting or searching, using your function for the comparison.
The equivalent of LIB$SPAWN is the system() function. The argument is either a command shell command, or NULL to test whether a command shell is available.
 
     if ( system(NULL) )
     {
/*     Do VMS command */
       system("DIRECTORY")
     }
     else
     {
       fprintf(stderr,"Sorry - no command shell available !");
     }
 
The atexit function lets you register exit handlers in FILO order, which are called when the program exits. These are useful for tidying up resources, even if some deeply nested subroutine calls exit(). Handlers for other types of condition can be registered using the signal() function. In Unix, signals are a bit like AST notifications. They range from SIGALRM, which lets you know when an alarm set by the alarm function has gone off, to SIGINT which can be used to trap Ctrl C. A pair of functions, setjmp and longjmp provide one of the nearest thing I have seen to the mythical "comefrom" statement ! An example showing you how to trap Ctrl C will demonstrate. This program includes and , and stores the position to which we want to return in saved_position, which is of type jmp_buf. You should never actually "look" at this, because it is only meaningful as an argument to longjmp. The second parameter to longjmp is an non-zero integer, which will be returned as the value of setjmp when we come back to it from the longjmp. Called directly, setjmp returns zero. The example "signal.c" should make signal handling and longjmping clearer.
 
/*---- Signal and longjmp Example ("signal.c") -------------------------------*/
 
/* ANSI C Headers */
#include 
#include 
#include 
#include 
 
#if defined( _WIN32 )
# include "windows.h"
#endif
 
/* Defines and macros */
#define MAX_COUNT 5
 
/* Global variables */
jmp_buf saved_position;
 
/* Function prototypes */
void ctrl_c_handler( int scode );
 
/* Main Program starts here */
int main( int argc, char *argv[] )
{
    int icount = 0;
/*  End of declarations ... */
 
    signal( SIGINT, ctrl_c_handler );
 
    if ( !setjmp(saved_position) )
    {
      for ( ; icount < MAX_COUNT; ++icount )
      {
        printf("At main line - looping #%d - enter Ctrl/C\n", icount);
#if !defined( _WIN32 )
        sleep( 10 );
#else
        Sleep( 10000 );
#endif
      }
    }
    else
    {
      printf("Returned from Ctrl C handler - exiting early\n");
    }
 
    exit(EXIT_SUCCESS);
}
 
void ctrl_c_handler( int scode )
{
/*  End of declarations ... */
 
    if ( scode == SIGINT )
    {
      printf("Handling Ctrl C - return to position saved by setjmp()\n");
      longjmp( saved_position, 1 ); /* Use any non-zero number */
    }
    else
    {
      printf("Strange - Ctrl C handler called with wrong signal code !\n");
    }
}
 
To get "signal.c" to link properly, you must compile it with /PREFIX=ALL to properly prefix the nonstandard function call to sleep, a function. All the recognised RTL functions are actually prefixed with "DECC$" by the compiler, and this allows the linker to find them automatically at link time. It is a good idea to get into the habit of using /PREFIX=ALL because this will cause warnings to be issued at link time if you inadvertently name any of your own functions so as to clash with inbuilt ones. This example works slightly differently under Windows, because although the Ctrl C handler is called, the program then exits (this is the documented behaviour).
Finally, I will present an example of a function that can be called with variable arguments. The C syntax for variable arguments is to use three dots, ..., to represent the variable arguments. You must however, specify at least one argument at the start of the parameter list. In one way, routines are rather inferior to the nonstandard routines, available on Unix and VMS, because the latter can tell you how many arguments were passed, whereas the former makes you tell the function in some way, like the "%" conversion characters in a printf format string does. Y.R.L. programmers - for some examples of the nonstandard varargs mechanism (which you should avoid using if at all possible) see SRC$OLB:PRINTFILE.C and FIFO.C in GNRC. Here is an example program using the standard stdargs mechanism, called "vargs.c".
 
/*---- Variable Arguments C Example ("vargs.c") ------------------------------*/
 
/* ANSI C Headers */
#include 
#include 
#include 
 
/* Defines and macros */
#define END 0
 
/* Function prototypes */
int add_some_ints( int first, ...);
 
/* Main Program starts here */
int main( int argc, char *argv[] )
{
    int total;
/*  End of declarations ... */
 
    total = add_some_ints( 1, 2, 3, 4, END);
 
    printf("Total was %d\n", total );
 
    exit(EXIT_SUCCESS);
}
 
/*---- Rather pathetic function to add up some integers ----------------------*/
int add_some_ints( int first, ...)
{
    va_list ap; /* Use to point to each argument in turn */
    int inext, sum, icount;
/*  End of declarations ... */
 
    icount = 1;
    sum = first;
    va_start( ap, first ); /* Use last named argument - first in this case */
 
/*  End of args is marked by END, which is zero */
 
    while ( inext = va_arg( ap, int ) )  /* Second arg of va_arg is type */
    {
      sum += inext;
      ++icount;
    }
    va_end( ap ); /* Tidy up */
 
    printf("add_some_ints added %d integers\n", icount );
 
    return( sum );
}
 
The best way to find out about the run time library functions is to look them up in K&R, or with VMS HELP, then have a go at using them.


Popular Post

Blog Archive

Total Pageviews

Sign In

Follow by Email

Powered by Blogger.

Like Us on Facebook

Search This Blog

Loading...

Indian Coder

- Copyright © Programming Mania -Metrominimalist- Powered by Blogger - Designed by Johanes Djogan -