home *** CD-ROM | disk | FTP | other *** search
- /***
- * The source code provided herein remains the property of Rick
- * Spence and Software Design Consultants. You are, however, free to
- * use it, but please do not republish.
- */
-
- /***
- * rickc.c
- *
- * Rick Spence's C code from the Advanced C presentation, 1990 Devcon
- */
-
- #include "nandef.h"
- #include "extend.h"
-
- #include <dos.h>
- #include <stdlib.h>
-
-
- /***
- * Program 9 - 1 Getting and Setting File Attributes
- */
-
- /***
- * NUMERIC cdos_getfi(path, attribute)
- *
- * CHARACTER path Full path
- * NUMERIC *attributes Numeric to store attributes in. Must be
- * passed by reference
- *
- * Get a file or directory attributes. Return in attribute (must pass it
- * by reference). Function returns 0 if ok, otherwise the error code.
- */
-
- CLIPPER cdos_getfi()
-
- {
- unsigned attributes, errcode;
-
- errcode = _dos_getfileattr(_parc(1), &attributes);
- _storni(attributes, 2);
- _retni(errcode);
- }
-
-
- /***
- * NUMERIC cdos_setfi(path, attribute)
- *
- * CHARACTER path Full path
- * NUMERIC attribute New attributes
- *
- * Set a file or directory attribute. Function returns 0 if ok,
- * otherwise the error code.
- */
-
- CLIPPER cdos_setfi()
-
- {
- _retni(_dos_setfileattr(_parc(1), _parni(2)));
- }
-
-
-
- /***
- * Program 9 - 2 Making, Changing, and Removing Directories
- */
-
-
- /***
- * NUMERIC cchdir(path)
- *
- * CHARACTER path Path name of directory to change to
- *
- * Change current working directory to the directory
- * specified by path. Function returns 0 if OK, otherwise
- * the error code.
- */
-
- CLIPPER cchdir()
-
- {
- _retni(chdir(_parc(1)));
- }
-
-
- /***
- * NUMERIC cmkdir(path)
- *
- * CHARACTER path
- *
- * Make a new directory with the specified path.
- *
- * RETURN: 0 if OK, error code otherwise
- */
-
- CLIPPER cmkdir()
-
- {
- _retni(mkdir(_parc(1)));
- }
-
-
- /***
- * NUMERIC crmdir(path)
- *
- * CHARACTER path
- *
- * Delete the directory specified by path.
- *
- * RETURN: 0 if OK, -1 if error
- */
-
- CLIPPER crmdir()
-
- {
- _retni(rmdir(_parc(1)));
- }
-
-
-
- /***
- * Program 9 - 3 Calling the Random Number Generator
- */
-
- /***
- * VOID csrand(seed)
- *
- * NUMERIC seed - Any value to set the starting point for
- * the generator. 1 reinitializes it.
- *
- * Initialize random number generator
- */
-
- CLIPPER csrand()
-
- {
- srand(_parni(1));
- _ret();
- }
-
-
- /***
- * NUMERIC crand()
- *
- * RETURN : A random number in the range 0 to 32767
- */
-
- CLIPPER crand()
-
- {
- _retni(rand());
- }
-
-
-
- /***
- * Program 9 - 4 Splitting a File Name into its Constituent Parts
- */
-
- /***
- * VOID splitpath(path, drive, dir, fname, ext)
- *
- * CHARACTER path - The path to split
- * CHARACTER *drive - The drive letter
- * CHARACTER *dir - The directory path
- * CHARACTER *fname - The file name
- * CHARACTER *ext - The file extension
- *
- * The function splits the passed path name into its constituent
- * parts. Each part is passed by reference, and must be defined
- * to at least these sizes:
- *
- * _MAX_DRIVE 3 max. length of drive component
- * MAX_DIR 13 max. length of path component
- * _MAX_FNAME 9 max. length of file name component
- * _MAX_EXT 5 max. length of extension component
- */
-
- CLIPPER splitpath()
-
- {
- char *drive, *dir, *fname, *ext;
-
- /* First allocate memory from Clipper's free pool */
- drive = (char *) _exmgrab(_MAX_DRIVE);
- dir = (char *) _exmgrab(_MAX_DIR);
- fname = (char *) _exmgrab(_MAX_FNAME);
- ext = (char *) _exmgrab(_MAX_EXT);
-
- _splitpath(_parc(1), drive, dir, fname, ext);
-
- /* set parameters (they were passed by reference) */
- _storc(drive, 2);
- _storc(dir, 3);
- _storc(fname, 4);
- _storc(ext, 5);
-
- /* Release memory */
- _exmback(drive, _MAX_DRIVE);
- _exmback(dir, _MAX_DIR);
- _exmback(fname, _MAX_FNAME);
- _exmback(ext, _MAX_EXT);
-
- _ret();
- }
-
-
-
- /***
- * Program 9 - 5 Interfacing to Strcspn and Strspn
- */
-
- /***
- * NUMERIC cstrcspn(string1, string2)
- *
- * CHARACTER string1, string2
- *
- * RETURN : Index into string1 of the first character in the set of
- * characters specified by string2. This is the length of the
- * initial substring in string1 of characters not in string2.
- */
-
- CLIPPER cstrcspn()
-
- {
- /* Add one to strcspn's result to convert from
- C's 0 based strings to Clipper's 1 based */
- _retni(strcspn(_parc(1), _parc(2)) + 1);
- }
-
-
- /***
- * NUMERIC cstrspn(string1, string2)
- *
- * CHARACTER string1, string2
- *
- * RETURN : Index into string1 of the first character NOT in the set of
- * characters specified by string2. This is the length of the
- * initial substring in string1 of characters in string2.
- */
-
- CLIPPER cstrspn()
-
- {
- /* Add one to strspn's result to convert from
- C's 0 based strings to Clipper's 1 based */
- _retni(strspn(_parc(1), _parc(2)) + 1);
- }
-
-
-
- /***
- * Program 9 - 8 General Purpose Interrupt Caller
- */
-
- /***
- * VOID cint86(interrupt, in_regs, out_regs)
- *
- * NUMERIC interrupt - The interrupt to call
- * ARRAY NUMERIC in_regs - Input Registers
- * ARRAY NUMERIC out_regs - Output Registers
- *
- * The function calls the specified interrupt with the passed
- * input registers (in_regs). It places the output registers in
- * the passed output registers (out_regs)
- */
-
- #define NUM_REGS sizeof(union REGS) / sizeof(int)
-
- CLIPPER cint86()
-
- {
- union REGS regs;
- int *ptr_reg;
- int reg_no;
-
- /* First load regs from Clipper's input array */
- ptr_reg = (int *) ®s;
- for (reg_no = 0; reg_no < NUM_REGS; reg_no++)
- ptr_reg[reg_no] = _parni(2, reg_no + 1);
-
- int86(_parni(1), ®s, ®s);
-
- /* Now put results into Clipper's output array */
-
- ptr_reg = (int *) ®s;
- for (reg_no = 0; reg_no < NUM_REGS; reg_no++)
- _storni(ptr_reg[reg_no], 3, reg_no + 1);
-
- _ret();
- }
-
-
-
- /***
- * Programs 9 - 10, 9 -11, 9 - 12, 9 - 13, 9- 14 combined
- */
-
- /***
- * set.c
- *
- * SET handling functions
- *
- */
-
- /* The following should be in a separate header file really */
-
- /* This is the structure of a set descriptor */
-
- typedef struct
- {
- char *set; /* Pointer to the set */
- unsigned int set_len; /* The length of this set */
- unsigned int cur_bit; /* Used when stepping through a set to
- indicate next position */
- } SET_DESC;
-
-
- /* Forwards */
- extern void _set_kill(int);
- extern void _set_add(int, int);
- extern int _set_in(int, int);
- extern void _set_del(int, int);
-
- #define MAX_SETS 7
-
- /* Declare static array of set descriptors */
- static SET_DESC set_desc[MAX_SETS];
- /* number of elements represented by one byte in the set */
- #define BITS_ELEM 8
-
-
- /* Determine set byte number given element */
- #define SET_BYTE_NUM(ELEM_NUM) ELEM_NUM / BITS_ELEM
-
- /* Determine set bit number (within byte) given element */
- #define SET_BIT_NUM(ELEM_NUM) ELEM_NUM % BITS_ELEM
-
- /* Macro to return a set's size */
- #define SET_SIZE(set_num) (set_desc[set_num].set_len)
-
- /* Macro to return the number of element's that can be represented
- in a set */
- #define SET_NUM_ELEMS(set_num) (SET_SIZE(set_num) * BITS_ELEM)
-
- /* Return value for sequential scan termination */
- #define NO_MORE_ELEMS -1
-
- /***
- * NUMERIC set_init(set_size)
- *
- * NUMERIC set_size - The size of the set in bytes. Each byte
- * can store 8 entries.
- *
- * RETURN : A handle for this set for future reference.
- */
-
- CLIPPER set_init()
-
- {
- _retni(_set_init(_parni(1)));
- }
-
-
- /***
- * VOID set_kill(set_handle)
- *
- * NUMERIC set_handle - The ahndle of the set to delete
- *
- * The function removes this set from its internal structure.
- */
-
- CLIPPER set_kill()
-
- {
- _set_kill(_parni(1));
- _ret();
- }
-
-
- /***
- * VOID set_add(set_handle, set_element, ...)
- *
- * NUMERIC set_handle - The handle of the set to add to
- * NUMERIC set_element - The element to add to the set
- *
- * NOTE : you can pass any number of elements to set_add
- *
- * The function adds set_element to the set defined by set_handle.
- */
-
-
- CLIPPER set_add()
-
- {
- int i;
-
- for (i = 2; i <= PCOUNT; i++)
- _set_add(_parni(1), _parni(i));
- }
-
-
- /***
- * VOID set_del(set_handle, set_element, ...)
- *
- * NUMERIC set_handle - The handle of the set to delete from
- * NUMERIC set_element - The element to delete from the set
- *
- * NOTE : you can pass any number of elements to set_add
- *
- * The function deletes set_element from the set defined by set_handle.
- */
-
- CLIPPER set_del()
-
- {
- int i;
-
- for (i = 2; i <= PCOUNT; i++)
- _set_del(_parni(1), _parni(i));
- }
-
-
- /***
- * LOGICAL set_in(set_handle, set_element)
- *
- * NUMERIC set_handle - The handle of the set to test
- * NUMERIC set_element - The element to test
- *
- *
- * RETURN : The function returns whether set_element is contained in
- * the set defined by set_handle.
- */
-
- CLIPPER set_in()
-
- {
- _retl(_set_in(_parni(1), _parni(2)));
- }
-
-
- /***
- * NUMERIC set_or(set1_handle, set2_handle)
- *
- * NUMERIC set1_handle, set2_handle - Two set handles
- *
- * RETURN : - Set handle of new set constructed from the OR of
- * the two sets
- */
-
- CLIPPER set_or()
-
- {
- _retni(_set_or(_parni(1), _parni(2)));
- }
-
-
- /***
- * NUMERIC set_and(set1_handle, set2_handle)
- *
- * NUMERIC set1_handle, set2_handle - Two set handles
- *
- * RETURN : - Set handle of new set constructed from the AND of
- * the two sets
- */
-
- CLIPPER set_and()
-
- {
- _retni(_set_and(_parni(1), _parni(2)));
- }
-
-
- /***
- * NUMERIC set_diff(set1_handle, set2_handle)
- *
- * NUMERIC set1_handle, set2_handle - Two set handles
- *
- * RETURN : - Set handle of new set constructed from the DIFFERENCE of
- * the two sets (i.e. set1_handle - set2_handle)
- */
-
- CLIPPER set_diff()
-
- {
- _retni(_set_diff(_parni(1), _parni(2)));
- }
-
-
- /***
- * NUMERIC set_first(set_handle)
- *
- * NUMERIC set_handle
- *
- * RETURN : - The first element of the set
- */
-
- CLIPPER set_first()
-
- {
- _retni(_set_first(_parni(1)));
- }
-
-
- /***
- * NUMERIC set_next(set_handle)
- *
- * NUMERIC set_handle
- *
- * RETURN : - The next element of the set
- */
-
- CLIPPER set_next()
-
- {
- _retni(_set_next(_parni(1)));
- }
-
- static int _set_init(set_size)
-
- int set_size;
-
- {
- unsigned int set_handle;
-
- set_handle = get_set_handle();
-
- set_desc[set_handle].set_len = set_size;
- set_desc[set_handle].cur_bit = 0;
-
- set_desc[set_handle].set = malloc(set_size);
- memset(set_desc[set_handle].set, 0, set_size);
-
- return set_handle;
- }
-
-
- static int get_set_handle()
-
- {
- int set_handle;
-
- for (set_handle = 0; set_handle < MAX_SETS &&
- set_desc[set_handle].set; set_handle++)
- ;
-
- if (set_handle >= MAX_SETS)
- /* Fatal error exit ... */
- exit(1);
-
- return (set_handle);
- }
-
-
- static void _set_kill(set_handle)
-
- int set_handle;
-
- {
- free(set_desc[set_handle].set);
- set_desc[set_handle].set = NULL;
- }
-
- static void _set_add(set_handle, set_element)
-
- int set_handle, set_element;
-
- {
- /* OR in the appropriate bit ... */
- if (set_element < SET_NUM_ELEMS(set_handle))
- set_desc[set_handle].set[SET_BYTE_NUM(set_element)]
- |= 1 << SET_BIT_NUM(set_element);
-
- }
-
-
- static void _set_del(set_handle, set_element)
-
- int set_handle, set_element;
-
- {
- /* AND out the appropriate bit ... */
- if (set_element < SET_NUM_ELEMS(set_handle))
- set_desc[set_handle].set[SET_BYTE_NUM(set_element)]
- &= ~(1 << SET_BIT_NUM(set_element));
- }
-
-
- static int _set_in(set_handle, set_element)
-
- int set_handle, set_element;
-
- {
- if (set_element < SET_NUM_ELEMS(set_handle))
- return (set_desc[set_handle].set[SET_BYTE_NUM(set_element)] &
- 1 << SET_BIT_NUM(set_element));
- }
-
-
- static int _set_first(set_handle)
-
- int set_handle;
-
- {
- int cur_bit, set_ptr;
-
- cur_bit = 0;
-
- while (!_set_in(set_handle, cur_bit)
- && cur_bit < SET_NUM_ELEMS(set_handle))
- cur_bit++;
-
- if (cur_bit != SET_NUM_ELEMS(set_handle))
- {
- set_desc[set_handle].cur_bit = cur_bit;
- }
-
- return ((cur_bit == SET_NUM_ELEMS(set_handle))
- ? NO_MORE_ELEMS : cur_bit);
- }
-
-
- static int _set_next(set_handle)
-
- int set_handle;
-
- {
- int cur_bit;
-
- /* Start search from next element */
- cur_bit = set_desc[set_handle].cur_bit + 1;
-
- while (!_set_in(set_handle, cur_bit) &&
- cur_bit < SET_NUM_ELEMS(set_handle))
- cur_bit++;
-
- if (cur_bit != SET_NUM_ELEMS(set_handle))
- {
- set_desc[set_handle].cur_bit = cur_bit;
- }
-
- return ((cur_bit == SET_NUM_ELEMS(set_handle))
- ? NO_MORE_ELEMS : cur_bit);
- }
-
- static int _set_or(set1_handle, set2_handle)
-
- int set1_handle, set2_handle;
-
- {
- int new_set_handle, new_set_size, elem_num, smaller_set_size;
-
- new_set_size = max(SET_SIZE(set1_handle), SET_SIZE(set2_handle));
- smaller_set_size = min(SET_SIZE(set1_handle),
- SET_SIZE(set2_handle));
-
- new_set_handle = _set_init(new_set_size);
-
- /* Add any from either set */
- for (elem_num = 0; elem_num < smaller_set_size * BITS_ELEM;
- elem_num++)
- if (_set_in(set1_handle, elem_num) ||
- _set_in(set2_handle, elem_num))
- _set_add(new_set_handle, elem_num);
-
- /* Now add trailing from the longer set */
- if (smaller_set_size == SET_SIZE(set1_handle))
- for(; elem_num < new_set_size * BITS_ELEM; elem_num++)
- {
- if (_set_in(set2_handle, elem_num))
- _set_add(new_set_handle, elem_num);
- }
- else
- for(; elem_num < new_set_size * BITS_ELEM; elem_num++)
- {
- if (_set_in(set1_handle, elem_num))
- _set_add(new_set_handle, elem_num);
- }
-
- return (new_set_handle);
- }
-
-
- static int _set_and(set1_handle, set2_handle)
-
- int set1_handle, set2_handle;
-
- {
- int new_set_handle, new_set_size, elem_num;
-
- new_set_size = min(SET_SIZE(set1_handle), SET_SIZE(set2_handle));
- new_set_handle = _set_init(new_set_size);
-
- for (elem_num = 0; elem_num < new_set_size * BITS_ELEM; elem_num++)
- if (_set_in(set1_handle, elem_num) &&
- _set_in(set2_handle, elem_num))
- _set_add(new_set_handle, elem_num);
-
- return (new_set_handle);
- }
-
-
- static int _set_diff(set1_handle, set2_handle)
-
- int set1_handle, set2_handle;
-
- {
- int new_set_handle, new_set_size, elem_num, smaller_set_size;
-
- new_set_size = SET_SIZE(set1_handle);
- new_set_handle = _set_init(new_set_size);
-
- smaller_set_size = min(SET_SIZE(set1_handle),
- SET_SIZE(set2_handle));
-
- for (elem_num = 0; elem_num < smaller_set_size * BITS_ELEM;
- elem_num++)
- if (_set_in(set1_handle, elem_num) &&
- !_set_in(set2_handle, elem_num))
- _set_add(new_set_handle, elem_num);
-
- /* Now add any trailing from the first set */
- if (smaller_set_size == SET_SIZE(set2_handle))
- for(; elem_num < new_set_size * BITS_ELEM; elem_num++)
- if (_set_in(set1_handle, elem_num))
- _set_add(new_set_handle, elem_num);
-
- return (new_set_handle);
- }