home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR8 / TDE32.ZIP / PORT.C < prev    next >
C/C++ Source or Header  |  1993-11-13  |  17KB  |  593 lines

  1. /*
  2.  * Now that I own both MSC 7.0 and BC 3.1 and have linux, lets rearrange stuff
  3.  * so many compilers can compile TDE.  Several implementation specific
  4.  * functions needed for several environments were gathered into this file.
  5.  *
  6.  * In version 3.2, these functions changed to support unix.
  7.  *
  8.  * Incidentally, there is difference between a NULL line pointer and
  9.  * a pointer to a line that contains no characters.  For example, calling
  10.  *
  11.  *       line = malloc( 0 );
  12.  *
  13.  *                   or, more precisely in TDE:
  14.  *
  15.  *       line = _fmalloc( 0 );
  16.  *       line = farmalloc( 0 );
  17.  *
  18.  * will return a valid pointer to an item of 0 length in some compilers
  19.  * and a NULL pointer in other compilers.  malloc( 0 ) will return a valid
  20.  * pointer to an object of zero length in MSC.  malloc( 0 ) will return a
  21.  * NULL pointer in BC.  The problem with returning a NULL pointer for
  22.  * malloc( 0 ) is that it's a little harder to tell if the heap is out of
  23.  * memory or if we have a valid NULL pointer.  On the other hand, the good
  24.  * part about returning a NULL pointer for malloc( 0 ) is that extra space
  25.  * is not wasted for an object of 0 length.  In TDE, we will test for 0
  26.  * before calling my_malloc( ) and set an ERROR code if out of memory.
  27.  *
  28.  * Although many PC C compilers have findfirst and findnext functions for
  29.  * finding files, let's write our own to keep a closer watch on
  30.  * critical errors.
  31.  *
  32.  *
  33.  * New editor name:  TDE, the Thomson-Davis Editor.
  34.  * Author:           Frank Davis
  35.  * Date:             June 5, 1991, version 1.0
  36.  * Date:             July 29, 1991, version 1.1
  37.  * Date:             October 5, 1991, version 1.2
  38.  * Date:             January 20, 1992, version 1.3
  39.  * Date:             February 17, 1992, version 1.4
  40.  * Date:             April 1, 1992, version 1.5
  41.  * Date:             June 5, 1992, version 2.0
  42.  * Date:             October 31, 1992, version 2.1
  43.  * Date:             April 1, 1993, version 2.2
  44.  * Date:             June 5, 1993, version 3.0
  45.  * Date:             August 29, 1993, version 3.1
  46.  * Date:             November 13, 1993, version 3.2
  47.  *
  48.  * This code is released into the public domain, Frank Davis.
  49.  * You may use and distribute it freely.
  50.  */
  51.  
  52. #include "tdestr.h"
  53. #include "common.h"
  54. #include "tdefunc.h"
  55. #include "define.h"
  56.  
  57. #if !defined( __UNIX__ )
  58.  #include <bios.h>       /* for REGS */
  59.  #include <dos.h>        /* for intdos */
  60. #endif
  61.  
  62. #if defined( __UNIX__ )
  63. /*
  64.  **********************************************************************
  65.  ******************************  PART 1  ******************************
  66.  **********************************************************************
  67.  *
  68.  * Let's try to make unix have the look and feel of a PC.
  69.  */
  70.  
  71. /*
  72.  * Name:    my_malloc
  73.  * Purpose: malloc from the far heap
  74.  * Date:    November 13, 1993
  75.  * Passed:  size:  memory needed heap
  76.  *          rc:   pointer to return code
  77.  * Notes:   set the return code only if an ERROR occured with malloc.
  78.  *           returning a NULL pointer is not neccessarily an ERROR.
  79.  */
  80. void *my_malloc( size_t size, int *rc )
  81. {
  82. void *mem;
  83.  
  84.    assert( size < MAX_LINE_LENGTH );
  85.  
  86.    if (size == 0)
  87.  
  88.       /*
  89.        * if 0 bytes are requested, return NULL
  90.        */
  91.       mem = NULL;
  92.    else {
  93.  
  94.       mem = malloc( size );
  95.  
  96.       /*
  97.        * if malloc failed, return NULL and an ERROR.
  98.        */
  99.       if (mem == NULL)
  100.          *rc = ERROR;
  101.    }
  102.    return( mem );
  103. }
  104.  
  105.  
  106. /*
  107.  * Name:    my_free
  108.  * Purpose: free memory from the far heap
  109.  * Date:    November 13, 1993
  110.  * Passed:  mem:  pointer to memory to free in far heap
  111.  */
  112. void my_free( void *mem )
  113. {
  114.    assert( mem != NULL );
  115.    free( mem );
  116. }
  117.  
  118.  
  119. /*
  120.  * Name:    my_heapavail
  121.  * Purpose: available free memory from the far heap
  122.  * Date:    November 13, 1993
  123.  * Notes:   mstats( ) is a gcc unix function that returns a structure.
  124.  *          (I haven't got this working, yet.)
  125.  */
  126. long my_heapavail( void )
  127. {
  128. /*
  129. struct mstats m;
  130.  
  131.  
  132.    m = mstats( );
  133.    return( (long)m.bytes_free );
  134. */
  135. return( 0 );
  136. }
  137.  
  138.  
  139. /*
  140.  * Name:    my_memcpy
  141.  * Purpose: copy memory
  142.  * Date:    November 13, 1993
  143.  * Passed:  dest: pointer to destination
  144.  *          src:  pointer to source
  145.  *          size: number of bytes to copy
  146.  */
  147. void my_memcpy( void *dest, void *src, size_t size )
  148. {
  149.    if (size > 0) {
  150.       assert( dest != NULL );
  151.       assert( src  != NULL );
  152.       memcpy( dest, src, size );
  153.    }
  154. }
  155.  
  156.  
  157. /*
  158.  * Name:    my_memmove
  159.  * Purpose: move memory
  160.  * Date:    November 13, 1993
  161.  * Passed:  dest: pointer to destination
  162.  *          src:  pointer to source
  163.  *          size: number of bytes to copy
  164.  */
  165. void my_memmove( void *dest, void *src, size_t size )
  166. {
  167.    if (size > 0) {
  168.       assert( dest != NULL );
  169.       assert( src  != NULL );
  170.       memmove( dest, src, size );
  171.    }
  172. }
  173.  
  174.  
  175. /*
  176.  * Name:    my_ltoa
  177.  * Purpose: ltoa is not ANSI - write our own
  178.  * Date:    November 13, 1993
  179.  * Passed:  lnum:   number to convert to ASCII.  in linux, an int is 32 bits.
  180.  *          s:      pointer to buffer
  181.  *          radix:  0 < radix <= 16
  182.  * Notes:   store the ascii string in a 20 character stack.
  183.  */
  184. char *my_ltoa( int lnum, char *s, int radix )
  185. {
  186. int  sign;
  187. char *digit = "0123456789abcdef";
  188. char stack[20];
  189. char *sp;
  190. char *p;
  191.  
  192.    if (radix < 0)
  193.       radix = -radix;
  194.  
  195.    /*
  196.     * default an empty string.
  197.     */
  198.    *s = '\0';
  199.    if (radix > 0 && radix <= 16) {
  200.       sign = 0;
  201.       if (lnum < 0) {
  202.          lnum = -lnum;
  203.          sign = -1;
  204.       }
  205.  
  206.       /*
  207.        * put a '\0' at the beginning of our stack.
  208.        *
  209.        * standard procedure: generate the digits in reverse order.
  210.        */
  211.       sp  = stack;
  212.       *sp = '\0';
  213.       do {
  214.          *++sp = digit[lnum % radix];
  215.          lnum = lnum / radix;
  216.       } while (lnum > 0);
  217.  
  218.       /*
  219.        * now, pop the ascii digits off the stack.  the '\0' that we stored
  220.        *  at the beginning of the stack terminates the string copy.
  221.        */
  222.       p = s;
  223.       if (sign == -1)
  224.          *p++ = '-';
  225.       while (*p++ = *sp--);
  226.    }
  227.    return( s );
  228. }
  229.  
  230.  
  231. /*
  232.  * Name:    my_findfirst
  233.  * Purpose: find the first file matching a pattern
  234.  * Date:    November 13, 1993
  235.  * Passed:  dta:    disk transfer address
  236.  *          path:   path to search for files
  237.  *          f_attr: attributes of files to search for
  238.  * Notes:   we don't use this function in a unix environment
  239.  */
  240. int  my_findfirst( DTA FAR *dta, char FAR *path, int f_attr )
  241. {
  242.    return( ERROR );
  243. }
  244.  
  245.  
  246. /*
  247.  * Name:    my_findnext
  248.  * Purpose: find the next file matching a pattern using POSIX readdir
  249.  * Date:    November 13, 1993
  250.  * Passed:  dp:  directory pointer (DIR is defined in <dirent.h>
  251.  *          unix_dta:  a pointer for TDE's dta
  252.  * Notes:   find directory elements.  the readdir( ) function gets the
  253.  *           next directory element.  it is up to TDE to figure the
  254.  *           directory element type, i.e. file, link, FIFO, subdirectory, etc...
  255.  */
  256. int  my_findnext( DIR *dp, UNIX_DTA *unix_dta )
  257. {
  258. struct dirent *dir;     /* dirent defined in <dirent.h> */
  259. int  rc;
  260.  
  261.    /*
  262.     * make sure our directory pointers aren't null
  263.     */
  264.    if (dp == NULL  ||  unix_dta == NULL)
  265.       rc = ERROR;
  266.    else if ((dir = readdir( dp )) == NULL)
  267.       rc = ERROR;
  268.    else {
  269.  
  270.       /*
  271.        * copy the directory element name and length to our unix_dta buffer.
  272.        * to figure the element, we will append the element name to the
  273.        *   directory stem and call stat( ).
  274.        */
  275.       strcpy( unix_dta->fname, dir->d_name );
  276.       unix_dta->name_len = strlen( unix_dta->fname );
  277.       rc = OK;
  278.    }
  279.    return( rc );
  280. }
  281.  
  282. #else
  283.  
  284. /*
  285.  **********************************************************************
  286.  ******************************  PART 2  ******************************
  287.  **********************************************************************
  288.  *
  289.  * DOS malloc and findfirst and findnext.
  290.  */
  291.  
  292. /*
  293.  * Name:    my_malloc
  294.  * Purpose: malloc from the far heap
  295.  * Date:    April 1, 1993
  296.  * Passed:  mem:  pointer to memory to free in far heap
  297.  *          rc:   pointer to return code
  298.  * Notes:   set the return code only if an ERROR occured with malloc.
  299.  *           returning a NULL pointer is not neccessarily an ERROR.
  300.  */
  301. void FAR * my_malloc( size_t size, int *rc )
  302. {
  303. void FAR *mem;
  304.  
  305.    assert( size < MAX_LINE_LENGTH );
  306.  
  307.    if (size == 0)
  308.  
  309.       /*
  310.        * if 0 bytes are requested, return NULL
  311.        */
  312.       mem = NULL;
  313.    else {
  314.  
  315. #if defined( __MSC__ )
  316.       mem = _fmalloc( size );
  317. #else
  318.       mem = farmalloc( size );
  319. #endif
  320.  
  321.       /*
  322.        * if malloc failed, return NULL and an ERROR.
  323.        */
  324.       if (mem == NULL)
  325.          *rc = ERROR;
  326.    }
  327.    return( mem );
  328. }
  329.  
  330.  
  331. /*
  332.  * Name:    my_free
  333.  * Purpose: free memory from the far heap
  334.  * Date:    April 1, 1993
  335.  * Passed:  mem:  pointer to memory to free in far heap
  336.  */
  337. void my_free( void FAR *mem )
  338. {
  339.    assert( mem != NULL );
  340.  
  341. #if defined( __MSC__ )
  342.    _ffree( mem );
  343. #else
  344.    farfree( mem );
  345. #endif
  346. }
  347.  
  348.  
  349. /*
  350.  * Name:    my_heapavail
  351.  * Purpose: available free memory from the far heap
  352.  * Date:    November 13, 1993
  353.  */
  354. long my_heapavail( void )
  355. {
  356. long avail_mem;
  357.  
  358. #if defined( __MSC__ )
  359. unsigned paragraphs;
  360.  
  361.    _dos_allocmem( 0xffff, ¶graphs );
  362.    /*
  363.     * A paragraph is 16 bytes.  Convert paragraphs to bytes by shifting left
  364.     * 4 bits.
  365.     */
  366.    avail_mem = (long)paragraphs << 4;
  367. #else
  368.  
  369.    /*
  370.     * use the Borland farcoreleft( ) function.
  371.     */
  372.    avail_mem = farcoreleft( );
  373. #endif
  374.    return( avail_mem );
  375. }
  376.  
  377.  
  378. /*
  379.  * Name:    my_memcpy
  380.  * Purpose: copy memory
  381.  * Date:    November 13, 1993
  382.  * Passed:  dest: pointer to destination
  383.  *          src:  pointer to source
  384.  *          size: number of bytes to copy
  385.  * Notes:   far memory copy in DOS real mode
  386.  */
  387. void my_memcpy( void FAR *dest, void FAR *src, size_t size )
  388. {
  389.    if (size > 0) {
  390.       assert( dest != NULL );
  391.       assert( src  != NULL );
  392.       _fmemcpy( dest, src, size );
  393.    }
  394. }
  395.  
  396.  
  397. /*
  398.  * Name:    my_memmove
  399.  * Purpose: move memory
  400.  * Date:    November 13, 1993
  401.  * Passed:  dest: pointer to destination
  402.  *          src:  pointer to source
  403.  *          size: number of bytes to copy
  404.  * Notes:   far memory move in DOS real mode - handles mem overlap
  405.  */
  406. void my_memmove( void FAR *dest, void FAR *src, size_t size )
  407. {
  408.    if (size > 0) {
  409.       assert( dest != NULL );
  410.       assert( src  != NULL );
  411.       _fmemmove( dest, src, size );
  412.    }
  413. }
  414.  
  415.  
  416. /*
  417.  * Name:    my_ltoa
  418.  * Purpose: ltoa is not ANSI
  419.  * Date:    June 5, 1991
  420.  * Passed:  lnum:   number to convert to ASCII
  421.  *          s:      pointer to buffer
  422.  *          radix:  0 < radix <= 16
  423.  * Notes:   If in insert mode, then this function adds the required
  424.  *           number of spaces in the file.
  425.  *          If not in insert mode, then tab simply moves the cursor right
  426.  *           the required distance.
  427.  */
  428. char *my_ltoa( long lnum, char *s, int radix )
  429. {
  430.    return( ltoa( lnum, s, radix ) );
  431. }
  432.  
  433.  
  434. /*
  435.  * Name:    my_findfirst
  436.  * Purpose: find the first file matching a pattern using DOS interrupt
  437.  * Date:    January 6, 1992
  438.  * Passed:  dta:    disk transfer address
  439.  *          path:   path to search for files
  440.  *          f_attr: attributes of files to search for
  441.  * Notes:   return codes for my_findfirst:
  442.  *             0  no error
  443.  *             2  file is invalid or does not exist
  444.  *             3  path is invalid or does not exist
  445.  *            18  no matching directory entry was found
  446.  *            -1  check the critical error flag for critical errors
  447.  */
  448. int  my_findfirst( DTA FAR *dta, char FAR *path, int f_attr )
  449. {
  450. void FAR *old_dta;
  451. void FAR *new_dta;
  452. int  rc;
  453.  
  454.    new_dta = (void FAR *)dta;
  455.  
  456.    ASSEMBLE {
  457.  
  458. /*
  459. ; save the old dta
  460. */
  461.         mov     ah, 0x2f                /* DOS get dta */
  462.         int     0x21                    /* DOS interrupt */
  463.         mov     WORD PTR old_dta, bx    /* save OFFSET of old DTA */
  464.         mov     ax, es
  465.         mov     WORD PTR old_dta+2, ax  /* save SEGMENT of old DTA */
  466.  
  467. /*
  468. ; set the new dta
  469. */
  470.         push    ds                      /* save ds */
  471.         mov     dx, WORD PTR new_dta    /* get OFFSET of new dta */
  472.         mov     ax, WORD PTR new_dta+2  /* get SEGMENT of new dta */
  473.         mov     ds, ax                  /* put it in ds */
  474.         mov     ah, 0x1a                /* DOS set dta */
  475.         int     0x21                    /* DOS interrupt */
  476.         pop     ds                      /* get back ds */
  477.  
  478. /*
  479. ; find first matching file
  480. */
  481.         push    ds                      /* save ds */
  482.         mov     cx, WORD PTR f_attr     /* file attributes to search for */
  483.         mov     dx, WORD PTR path       /* get OFFSET of path */
  484.         mov     ax, WORD PTR path+2     /* get SEGMENT of path */
  485.         mov     ds, ax                  /* put it in ds */
  486.         mov     ah, 0x4e                /* DOS find first file */
  487.         int     0x21                    /* DOS interrupt */
  488.         pop     ds                      /* get back ds */
  489.  
  490. /*
  491. ; save the return code
  492. */
  493.         jc      an_error                /* carry is set if an error occured */
  494.         xor     ax, ax                  /* zero out ax, return OK if no error */
  495.    }
  496. an_error:
  497.  
  498.    ASSEMBLE {
  499.         mov     WORD PTR rc, ax         /* save the return code */
  500.  
  501. /*
  502. ; get back old dta
  503. */
  504.         push    ds                      /* save ds */
  505.         mov     dx, WORD PTR old_dta    /* get OFFSET of old dta */
  506.         mov     ax, WORD PTR old_dta+2  /* get SEGMENT of old dta */
  507.         mov     ds, ax                  /* put it in ds */
  508.         mov     ah, 0x1a                /* DOS set dta */
  509.         int     0x21                    /* DOS interrupt */
  510.         pop     ds                      /* get back ds */
  511.    }
  512.    if (ceh.flag == ERROR)
  513.       rc = ERROR;
  514.    return( rc );
  515. }
  516.  
  517.  
  518. /*
  519.  * Name:    my_findnext
  520.  * Purpose: find the next file matching a pattern using DOS interrupt
  521.  * Date:    January 6, 1992
  522.  * Passed:  dta:  disk transfer address
  523.  * Notes:   my_findfirst() MUST be called before calling this function.
  524.  *          return codes for my_findnext (see DOS tech ref manuals):
  525.  *             0  no error
  526.  *             2  path is invalid or does not exist
  527.  *            18  no matching directory entry was found
  528.  *            -1  check the critical error flag for critical errors
  529.  */
  530. int  my_findnext( DTA FAR *dta )
  531. {
  532. void FAR *old_dta;
  533. void FAR *new_dta;
  534. int  rc;
  535.  
  536.    new_dta = (void FAR *)dta;
  537.  
  538.    ASSEMBLE {
  539.  
  540. /*
  541. ; save the old dta
  542. */
  543.         mov     ah, 0x2f                /* DOS get dta */
  544.         int     0x21                    /* DOS interrupt */
  545.         mov     WORD PTR old_dta, bx    /* save OFFSET of old DTA */
  546.         mov     ax, es
  547.         mov     WORD PTR old_dta+2, ax  /* save SEGMENT of old DTA */
  548.  
  549. /*
  550. ; set the new dta
  551. */
  552.         push    ds                      /* save ds */
  553.         mov     dx, WORD PTR new_dta    /* get OFFSET of new dta */
  554.         mov     ax, WORD PTR new_dta+2  /* get SEGMENT of new dta */
  555.         mov     ds, ax                  /* put it in ds */
  556.         mov     ah, 0x1a                /* DOS set dta */
  557.         int     0x21                    /* DOS interrupt */
  558.         pop     ds                      /* get back ds */
  559.  
  560. /*
  561. ; find next matching file
  562. */
  563.         mov     ah, 0x4f                /* DOS find first file */
  564.         int     0x21                    /* DOS interrupt */
  565.  
  566. /*
  567. ; save the return code
  568. */
  569.         jc      an_error                /* carry is set if an error occured */
  570.         xor     ax, ax                  /* zero out ax, return OK if no error */
  571.    }
  572. an_error:
  573.  
  574.    ASSEMBLE {
  575.         mov     WORD PTR rc, ax         /* save the return code */
  576.  
  577. /*
  578. ; get back old dta
  579. */
  580.         push    ds                      /* save ds */
  581.         mov     dx, WORD PTR old_dta    /* get OFFSET of old dta */
  582.         mov     ax, WORD PTR old_dta+2  /* get SEGMENT of old dta */
  583.         mov     ds, ax                  /* put it in ds */
  584.         mov     ah, 0x1a                /* DOS set dta */
  585.         int     0x21                    /* DOS interrupt */
  586.         pop     ds                      /* get back ds */
  587.    }
  588.    if (ceh.flag == ERROR)
  589.       rc = ERROR;
  590.    return( rc );
  591. }
  592. #endif
  593.