home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0010 - 0019 / ibm0010-0019 / ibm0010.tar / ibm0010 / CLIPB52.ZIP / SPENCE.ZIP / RICKC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-04  |  17.5 KB  |  730 lines

  1.     /***
  2.     * The source code provided herein remains the property of Rick
  3.     * Spence and Software Design Consultants. You are, however, free to
  4.     * use it, but please do not republish.
  5.     */
  6.  
  7.     /***
  8.     * rickc.c
  9.     *
  10.     * Rick Spence's C code from the Advanced C presentation, 1990 Devcon
  11.     */
  12.  
  13.     #include "nandef.h"
  14.     #include "extend.h"
  15.  
  16.     #include <dos.h>
  17.     #include <stdlib.h>
  18.  
  19.  
  20.     /***
  21.     *   Program 9 - 1 Getting and Setting File Attributes
  22.     */
  23.  
  24.     /***
  25.     * NUMERIC cdos_getfi(path, attribute)
  26.     *
  27.     * CHARACTER path            Full path 
  28.     * NUMERIC   *attributes     Numeric to store attributes in. Must be
  29.     *                           passed by reference
  30.     *
  31.     * Get a file or directory attributes. Return in attribute (must pass it
  32.     * by reference). Function returns 0 if ok, otherwise the error code.
  33.     */
  34.  
  35.     CLIPPER cdos_getfi()
  36.  
  37.     {
  38.         unsigned attributes, errcode;
  39.  
  40.         errcode = _dos_getfileattr(_parc(1), &attributes);
  41.         _storni(attributes, 2);
  42.         _retni(errcode);
  43.     }
  44.  
  45.  
  46.     /***
  47.     * NUMERIC cdos_setfi(path, attribute)
  48.     *
  49.     * CHARACTER path            Full path
  50.     * NUMERIC   attribute       New attributes
  51.     *
  52.     * Set a file or directory attribute. Function returns 0 if ok,
  53.     * otherwise the error code.
  54.     */
  55.  
  56.     CLIPPER cdos_setfi()
  57.  
  58.     {
  59.         _retni(_dos_setfileattr(_parc(1), _parni(2)));
  60.     }
  61.  
  62.  
  63.  
  64.     /***
  65.     *   Program 9 - 2  Making, Changing, and Removing Directories
  66.     */
  67.  
  68.  
  69.     /***
  70.     * NUMERIC cchdir(path)
  71.     *
  72.     * CHARACTER path            Path name of directory to change to
  73.     *
  74.     * Change current working directory to the directory
  75.     * specified by path. Function returns 0 if OK, otherwise
  76.     * the error code.
  77.     */
  78.  
  79.     CLIPPER cchdir()
  80.  
  81.     {
  82.         _retni(chdir(_parc(1)));
  83.     }
  84.  
  85.  
  86.     /***
  87.     * NUMERIC cmkdir(path)
  88.     *
  89.     * CHARACTER path
  90.     *
  91.     * Make a new directory with the specified path.
  92.     *
  93.     * RETURN: 0 if OK, error code otherwise
  94.     */
  95.  
  96.     CLIPPER cmkdir()
  97.  
  98.     {
  99.         _retni(mkdir(_parc(1)));
  100.     }
  101.  
  102.  
  103.     /***
  104.     * NUMERIC crmdir(path)
  105.     *
  106.     * CHARACTER path
  107.     *
  108.     * Delete the directory specified by path.
  109.     *
  110.     * RETURN: 0 if OK, -1 if error
  111.     */
  112.  
  113.     CLIPPER crmdir()
  114.  
  115.     {
  116.         _retni(rmdir(_parc(1)));
  117.     }
  118.  
  119.  
  120.  
  121.     /***
  122.     *   Program 9 - 3  Calling the Random Number Generator
  123.     */
  124.  
  125.     /***
  126.     * VOID csrand(seed)
  127.     *
  128.     * NUMERIC seed         - Any value to set the starting point for
  129.     *                        the generator. 1 reinitializes it.
  130.     *
  131.     * Initialize random number generator
  132.     */
  133.  
  134.     CLIPPER csrand()
  135.  
  136.     {
  137.         srand(_parni(1));
  138.         _ret();
  139.     }
  140.  
  141.  
  142.     /***
  143.     * NUMERIC crand()
  144.     *
  145.     * RETURN : A random number in the range 0 to 32767
  146.     */
  147.  
  148.     CLIPPER crand()
  149.  
  150.     {
  151.         _retni(rand());
  152.     }
  153.  
  154.  
  155.  
  156.     /***
  157.     *   Program 9 - 4  Splitting a File Name into its Constituent Parts
  158.     */
  159.  
  160.     /***
  161.     * VOID splitpath(path, drive, dir, fname, ext)
  162.     *
  163.     * CHARACTER path                   - The path to split
  164.     * CHARACTER *drive                 - The drive letter
  165.     * CHARACTER *dir                   - The directory path
  166.     * CHARACTER *fname                 - The file name
  167.     * CHARACTER *ext                   - The file extension
  168.     *
  169.     * The function splits the passed path name into its constituent
  170.     * parts. Each part is passed by reference, and must be defined
  171.     * to at least these sizes:
  172.     *
  173.     *     _MAX_DRIVE   3       max. length of drive component
  174.     *     MAX_DIR     13       max. length of path component
  175.     *     _MAX_FNAME   9       max. length of file name component
  176.     *     _MAX_EXT     5       max. length of extension component
  177.     */
  178.  
  179.     CLIPPER splitpath()
  180.  
  181.     {
  182.         char *drive, *dir, *fname, *ext;
  183.  
  184.         /* First allocate memory from Clipper's free pool */
  185.         drive = (char *) _exmgrab(_MAX_DRIVE);
  186.         dir = (char *) _exmgrab(_MAX_DIR);
  187.         fname = (char *) _exmgrab(_MAX_FNAME);
  188.         ext = (char *) _exmgrab(_MAX_EXT);
  189.  
  190.         _splitpath(_parc(1), drive, dir, fname, ext);
  191.  
  192.         /* set parameters (they were passed by reference) */
  193.         _storc(drive, 2);
  194.         _storc(dir, 3);
  195.         _storc(fname, 4);
  196.         _storc(ext, 5);
  197.  
  198.         /* Release memory */
  199.         _exmback(drive, _MAX_DRIVE);
  200.         _exmback(dir, _MAX_DIR);
  201.         _exmback(fname, _MAX_FNAME);
  202.         _exmback(ext, _MAX_EXT);
  203.  
  204.         _ret();
  205.     }
  206.  
  207.  
  208.  
  209.     /***
  210.     *   Program 9 - 5 Interfacing to Strcspn and Strspn
  211.     */
  212.  
  213.     /***
  214.     * NUMERIC cstrcspn(string1, string2)
  215.     *
  216.     * CHARACTER string1, string2
  217.     *
  218.     * RETURN : Index into string1 of the first character in the set of
  219.     *          characters specified by string2. This is the length of the
  220.     *          initial substring in string1 of characters not in string2.
  221.     */
  222.  
  223.     CLIPPER cstrcspn()
  224.  
  225.     {
  226.         /* Add one to strcspn's result to convert from
  227.            C's 0 based strings to Clipper's 1 based */
  228.         _retni(strcspn(_parc(1), _parc(2)) + 1);
  229.     }
  230.  
  231.  
  232.     /***
  233.     * NUMERIC cstrspn(string1, string2)
  234.     *
  235.     * CHARACTER string1, string2
  236.     *
  237.     * RETURN : Index into string1 of the first character NOT in the set of
  238.     *          characters specified by string2. This is the length of the
  239.     *          initial substring in string1 of characters in string2.
  240.     */
  241.  
  242.     CLIPPER cstrspn()
  243.  
  244.     {
  245.         /* Add one to strspn's result to convert from
  246.            C's 0 based strings to Clipper's 1 based */
  247.         _retni(strspn(_parc(1), _parc(2)) + 1);
  248.     }
  249.  
  250.  
  251.  
  252.     /***
  253.     *   Program 9 - 8  General Purpose Interrupt Caller
  254.     */
  255.  
  256.     /***
  257.     * VOID cint86(interrupt, in_regs, out_regs)
  258.     *
  259.     * NUMERIC interrupt                - The interrupt to call
  260.     * ARRAY NUMERIC in_regs            - Input Registers
  261.     * ARRAY NUMERIC out_regs           - Output Registers
  262.     *
  263.     * The function calls the specified interrupt with the passed
  264.     * input registers (in_regs). It places the output registers in
  265.     * the passed output registers (out_regs)
  266.     */
  267.  
  268.     #define NUM_REGS sizeof(union REGS)  / sizeof(int)
  269.  
  270.     CLIPPER cint86()
  271.  
  272.     {
  273.         union REGS regs;
  274.         int *ptr_reg;
  275.         int reg_no;
  276.  
  277.         /* First load regs from Clipper's input array */
  278.         ptr_reg = (int *) ®s;
  279.         for (reg_no = 0; reg_no < NUM_REGS; reg_no++)
  280.             ptr_reg[reg_no] = _parni(2, reg_no + 1);
  281.  
  282.         int86(_parni(1), ®s, ®s);
  283.  
  284.         /* Now put results into Clipper's output array */
  285.  
  286.         ptr_reg = (int *) ®s;
  287.         for (reg_no = 0; reg_no < NUM_REGS; reg_no++)
  288.             _storni(ptr_reg[reg_no], 3, reg_no + 1);
  289.  
  290.         _ret();
  291.     }
  292.  
  293.  
  294.  
  295.     /***
  296.     *   Programs 9 - 10, 9 -11, 9 - 12, 9 - 13, 9- 14 combined
  297.     */
  298.  
  299.     /***
  300.     * set.c
  301.     *
  302.     * SET handling functions
  303.     *
  304.     */
  305.  
  306.     /* The following should be in a separate header file really */
  307.  
  308.     /* This is the structure of a set descriptor */
  309.  
  310.     typedef struct
  311.     {
  312.         char *set;             /* Pointer to the set */
  313.         unsigned int set_len;  /* The length of this set */
  314.         unsigned int cur_bit;  /* Used when stepping through a set to
  315.                                   indicate next position */
  316.     } SET_DESC;
  317.  
  318.  
  319.     /* Forwards */
  320.     extern void _set_kill(int);
  321.     extern void _set_add(int, int);
  322.     extern int  _set_in(int, int);
  323.     extern void _set_del(int, int);
  324.  
  325.     #define MAX_SETS 7
  326.  
  327.     /* Declare static array of set descriptors */
  328.     static SET_DESC set_desc[MAX_SETS];
  329.     /* number of elements represented by one byte in the set */
  330.     #define BITS_ELEM 8 
  331.  
  332.  
  333.     /* Determine set byte number given element */
  334.     #define SET_BYTE_NUM(ELEM_NUM) ELEM_NUM / BITS_ELEM 
  335.  
  336.     /* Determine set bit number (within byte) given element */
  337.     #define SET_BIT_NUM(ELEM_NUM)  ELEM_NUM % BITS_ELEM
  338.  
  339.     /* Macro to return a set's size */
  340.     #define SET_SIZE(set_num) (set_desc[set_num].set_len)
  341.  
  342.     /* Macro to return the number of element's that can be represented
  343.        in a set */
  344.     #define SET_NUM_ELEMS(set_num) (SET_SIZE(set_num) * BITS_ELEM)
  345.  
  346.     /* Return value for sequential scan termination */
  347.     #define NO_MORE_ELEMS -1
  348.  
  349.     /***
  350.     * NUMERIC set_init(set_size)
  351.     *
  352.     * NUMERIC set_size          - The size of the set in bytes. Each byte
  353.     *                             can store 8 entries.
  354.     *
  355.     * RETURN : A handle for this set for future reference.
  356.     */
  357.  
  358.     CLIPPER set_init()
  359.  
  360.     {
  361.         _retni(_set_init(_parni(1)));
  362.     }
  363.  
  364.  
  365.     /***
  366.     * VOID set_kill(set_handle)
  367.     *
  368.     * NUMERIC set_handle          - The ahndle of the set to delete
  369.     *
  370.     * The function removes this set from its internal structure.
  371.     */
  372.  
  373.     CLIPPER set_kill()
  374.  
  375.     {
  376.         _set_kill(_parni(1));
  377.         _ret();
  378.     }
  379.  
  380.  
  381.     /***
  382.     * VOID set_add(set_handle, set_element, ...)
  383.     *
  384.     * NUMERIC set_handle          - The handle of the set to add to
  385.     * NUMERIC set_element         - The element to add to the set
  386.     *
  387.     * NOTE : you can pass any number of elements to set_add
  388.     *
  389.     * The function adds set_element to the set defined by set_handle.
  390.     */
  391.  
  392.  
  393.     CLIPPER set_add()
  394.  
  395.     {
  396.         int i;
  397.  
  398.         for (i = 2; i <= PCOUNT; i++)
  399.             _set_add(_parni(1), _parni(i));
  400.     }
  401.  
  402.  
  403.     /***
  404.     * VOID set_del(set_handle, set_element, ...)
  405.     *
  406.     * NUMERIC set_handle          - The handle of the set to delete from
  407.     * NUMERIC set_element         - The element to delete from the set
  408.     *
  409.     * NOTE : you can pass any number of elements to set_add
  410.     *
  411.     * The function deletes set_element from the set defined by set_handle.
  412.     */
  413.  
  414.     CLIPPER set_del()
  415.  
  416.     {
  417.         int i;
  418.  
  419.         for (i = 2; i <= PCOUNT; i++)
  420.             _set_del(_parni(1), _parni(i));
  421.     }
  422.  
  423.  
  424.     /***
  425.     * LOGICAL set_in(set_handle, set_element)
  426.     *
  427.     * NUMERIC set_handle          - The handle of the set to test
  428.     * NUMERIC set_element         - The element to test
  429.     *
  430.     *
  431.     * RETURN : The function returns whether set_element is contained in
  432.     *           the set defined by set_handle.
  433.     */
  434.  
  435.     CLIPPER set_in()
  436.  
  437.     {
  438.         _retl(_set_in(_parni(1), _parni(2)));
  439.     }
  440.  
  441.  
  442.     /***
  443.     * NUMERIC set_or(set1_handle, set2_handle)
  444.     *
  445.     * NUMERIC set1_handle, set2_handle       - Two set handles
  446.     *
  447.     * RETURN : - Set handle of new set constructed from the OR of
  448.     *            the two sets
  449.     */
  450.  
  451.     CLIPPER set_or()
  452.  
  453.     {
  454.         _retni(_set_or(_parni(1), _parni(2)));
  455.     }
  456.  
  457.  
  458.     /***
  459.     * NUMERIC set_and(set1_handle, set2_handle)
  460.     *
  461.     * NUMERIC set1_handle, set2_handle     - Two set handles
  462.     *
  463.     * RETURN : - Set handle of new set constructed from the AND of
  464.     *            the two sets
  465.     */
  466.  
  467.     CLIPPER set_and()
  468.  
  469.     {
  470.         _retni(_set_and(_parni(1), _parni(2)));
  471.     }
  472.  
  473.  
  474.     /***
  475.     * NUMERIC set_diff(set1_handle, set2_handle)
  476.     *
  477.     * NUMERIC set1_handle, set2_handle          - Two set handles
  478.     *
  479.     * RETURN : - Set handle of new set constructed from the DIFFERENCE of
  480.     *            the two sets (i.e. set1_handle - set2_handle)
  481.     */
  482.  
  483.     CLIPPER set_diff()
  484.  
  485.     {
  486.         _retni(_set_diff(_parni(1), _parni(2)));
  487.     }
  488.  
  489.  
  490.     /***
  491.     * NUMERIC set_first(set_handle)
  492.     *
  493.     * NUMERIC set_handle
  494.     *
  495.     * RETURN : - The first element of the set
  496.     */
  497.  
  498.     CLIPPER set_first()
  499.  
  500.     {
  501.         _retni(_set_first(_parni(1)));
  502.     }
  503.  
  504.  
  505.     /***
  506.     * NUMERIC set_next(set_handle)
  507.     *
  508.     * NUMERIC set_handle
  509.     *
  510.     * RETURN : - The next element of the set
  511.     */
  512.  
  513.     CLIPPER set_next()
  514.  
  515.     {
  516.         _retni(_set_next(_parni(1)));
  517.     }
  518.  
  519.     static int _set_init(set_size)
  520.  
  521.     int set_size;
  522.  
  523.     {
  524.         unsigned int set_handle;
  525.  
  526.         set_handle = get_set_handle();
  527.  
  528.         set_desc[set_handle].set_len = set_size;
  529.         set_desc[set_handle].cur_bit = 0;
  530.  
  531.         set_desc[set_handle].set = malloc(set_size);
  532.         memset(set_desc[set_handle].set, 0, set_size);
  533.  
  534.         return set_handle;
  535.     }
  536.  
  537.  
  538.     static int get_set_handle()
  539.  
  540.     {
  541.         int set_handle;
  542.  
  543.         for (set_handle = 0; set_handle < MAX_SETS &&
  544.                              set_desc[set_handle].set; set_handle++)
  545.             ;
  546.  
  547.         if (set_handle >= MAX_SETS)
  548.             /* Fatal error exit ... */
  549.             exit(1);
  550.     
  551.         return (set_handle);
  552.     }
  553.  
  554.  
  555.     static void _set_kill(set_handle)
  556.  
  557.     int set_handle;
  558.  
  559.     {
  560.         free(set_desc[set_handle].set);
  561.         set_desc[set_handle].set = NULL;
  562.     }
  563.  
  564.     static void _set_add(set_handle, set_element)
  565.  
  566.     int set_handle, set_element;
  567.  
  568.     {
  569.        /* OR in the appropriate bit ... */
  570.        if (set_element < SET_NUM_ELEMS(set_handle))
  571.            set_desc[set_handle].set[SET_BYTE_NUM(set_element)]
  572.                                     |= 1 << SET_BIT_NUM(set_element);
  573.  
  574.     }
  575.  
  576.  
  577.     static void _set_del(set_handle, set_element)
  578.  
  579.     int set_handle, set_element;
  580.  
  581.     {
  582.         /* AND out the appropriate bit ... */
  583.         if (set_element < SET_NUM_ELEMS(set_handle))
  584.             set_desc[set_handle].set[SET_BYTE_NUM(set_element)]
  585.                                     &= ~(1 << SET_BIT_NUM(set_element));
  586.     }
  587.  
  588.  
  589.     static int _set_in(set_handle, set_element)
  590.  
  591.     int set_handle, set_element;
  592.  
  593.     {
  594.         if (set_element < SET_NUM_ELEMS(set_handle))
  595.             return (set_desc[set_handle].set[SET_BYTE_NUM(set_element)] &
  596.                     1 << SET_BIT_NUM(set_element));
  597.     }
  598.  
  599.  
  600.     static int _set_first(set_handle)
  601.  
  602.     int set_handle;
  603.  
  604.     {
  605.         int cur_bit, set_ptr;
  606.  
  607.         cur_bit = 0;
  608.  
  609.         while (!_set_in(set_handle, cur_bit)
  610.                && cur_bit < SET_NUM_ELEMS(set_handle))
  611.             cur_bit++;
  612.  
  613.         if (cur_bit != SET_NUM_ELEMS(set_handle))
  614.         {
  615.             set_desc[set_handle].cur_bit = cur_bit;
  616.         }
  617.  
  618.         return ((cur_bit == SET_NUM_ELEMS(set_handle))
  619.                  ? NO_MORE_ELEMS : cur_bit);
  620.     }
  621.  
  622.  
  623.     static int _set_next(set_handle)
  624.  
  625.     int set_handle;
  626.  
  627.     {
  628.         int cur_bit;
  629.  
  630.         /* Start search from next element */
  631.         cur_bit = set_desc[set_handle].cur_bit + 1;
  632.  
  633.         while (!_set_in(set_handle, cur_bit) &&
  634.                cur_bit < SET_NUM_ELEMS(set_handle))
  635.             cur_bit++;
  636.  
  637.         if (cur_bit != SET_NUM_ELEMS(set_handle))
  638.         {
  639.             set_desc[set_handle].cur_bit = cur_bit;
  640.         }
  641.  
  642.         return ((cur_bit == SET_NUM_ELEMS(set_handle))
  643.                  ? NO_MORE_ELEMS : cur_bit);
  644.     }
  645.  
  646.     static int _set_or(set1_handle, set2_handle)
  647.  
  648.     int set1_handle, set2_handle;
  649.  
  650.     {
  651.         int new_set_handle, new_set_size, elem_num, smaller_set_size;
  652.  
  653.         new_set_size = max(SET_SIZE(set1_handle), SET_SIZE(set2_handle));
  654.         smaller_set_size = min(SET_SIZE(set1_handle),
  655.                                SET_SIZE(set2_handle));
  656.  
  657.         new_set_handle = _set_init(new_set_size);
  658.  
  659.         /* Add any from either set */
  660.         for (elem_num = 0; elem_num < smaller_set_size * BITS_ELEM;
  661.              elem_num++)
  662.             if (_set_in(set1_handle, elem_num) ||
  663.                 _set_in(set2_handle, elem_num))
  664.                 _set_add(new_set_handle, elem_num);
  665.  
  666.         /* Now add trailing from the longer set */
  667.         if (smaller_set_size == SET_SIZE(set1_handle))
  668.             for(; elem_num < new_set_size * BITS_ELEM; elem_num++)
  669.             {
  670.                 if (_set_in(set2_handle, elem_num))
  671.                     _set_add(new_set_handle, elem_num);
  672.             }
  673.         else
  674.             for(; elem_num < new_set_size * BITS_ELEM; elem_num++)
  675.             {
  676.                 if (_set_in(set1_handle, elem_num))
  677.                     _set_add(new_set_handle, elem_num);
  678.             }
  679.  
  680.         return (new_set_handle);
  681.     }
  682.  
  683.  
  684.     static int _set_and(set1_handle, set2_handle)
  685.  
  686.     int set1_handle, set2_handle;
  687.  
  688.     {
  689.         int new_set_handle, new_set_size, elem_num;
  690.  
  691.         new_set_size = min(SET_SIZE(set1_handle), SET_SIZE(set2_handle));
  692.         new_set_handle = _set_init(new_set_size);
  693.  
  694.         for (elem_num = 0; elem_num < new_set_size * BITS_ELEM; elem_num++)
  695.             if (_set_in(set1_handle, elem_num) &&
  696.                 _set_in(set2_handle, elem_num))
  697.                 _set_add(new_set_handle, elem_num);
  698.  
  699.         return (new_set_handle);
  700.     }
  701.  
  702.  
  703.     static int _set_diff(set1_handle, set2_handle)
  704.  
  705.     int set1_handle, set2_handle;
  706.  
  707.     {
  708.         int new_set_handle, new_set_size, elem_num, smaller_set_size;
  709.  
  710.         new_set_size = SET_SIZE(set1_handle);
  711.         new_set_handle = _set_init(new_set_size);
  712.  
  713.         smaller_set_size = min(SET_SIZE(set1_handle),
  714.                                SET_SIZE(set2_handle));
  715.  
  716.         for (elem_num = 0; elem_num < smaller_set_size * BITS_ELEM;
  717.              elem_num++)
  718.             if (_set_in(set1_handle, elem_num) &&
  719.                 !_set_in(set2_handle, elem_num))
  720.                 _set_add(new_set_handle, elem_num);
  721.   
  722.         /* Now add any trailing from the first set */
  723.         if (smaller_set_size == SET_SIZE(set2_handle))
  724.             for(; elem_num < new_set_size * BITS_ELEM; elem_num++)
  725.                 if (_set_in(set1_handle, elem_num))
  726.                     _set_add(new_set_handle, elem_num);
  727.  
  728.         return (new_set_handle);
  729.     }
  730.