home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / vsoup128.zip / mts.cc < prev    next >
C/C++ Source or Header  |  1997-02-12  |  20KB  |  1,028 lines

  1. //  $Id: mts.cc 1.21 1997/02/12 08:49:45 hardy Exp $
  2. //
  3. //  This progam/module was written by Hardy Griech based on ideas and
  4. //  pieces of code from Chin Huang (cthuang@io.org).  Bug reports should
  5. //  be submitted to rgriech@ibm.net.
  6. //
  7. //  This file is part of soup++ for OS/2.  Soup++ including this file
  8. //  is freeware.  There is no warranty of any kind implied.  The terms
  9. //  of the GNU Gernal Public Licence are valid for this piece of software.
  10. //
  11. //  Problems
  12. //  --------
  13. //  -  the emx09c semaphores are likely to deadlock, because the signal handler
  14. //     is illegal (streams!)...
  15. //  -  sprintf/vsprintf are thread-safe functions and reentrant
  16. //  -  sometimes the functions in this module are calling directly library functions.
  17. //     Those functions are placed here to indicate that they are checked with respect
  18. //     to thread-safety
  19. //  -  all IO should be done without streams, see class TFile!  Although this class
  20. //     seems to be not so nice as e.g. streams, it is doing the job quite well.  Be
  21. //     cautious, if you want to use this class for other projects...
  22. //     E.g. simultaneous access to one TFile is not possible.  If there is a gets()
  23. //     active and the file will be closed at the same time, an access violation
  24. //     will happen (most likely...).  Anyway this type of operation is undefined!
  25. //
  26.  
  27.  
  28. #include <assert.h>
  29. #include <errno.h>
  30. #include <fcntl.h>
  31. #include <io.h>
  32. #include <share.h>
  33. #include <stdarg.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <unistd.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <unistd.h>
  41.  
  42. #include "mts.hh"
  43. #include "sema.hh"
  44.  
  45.  
  46.  
  47. //--------------------------------------------------------------------------------
  48.  
  49.  
  50.  
  51. TSemaphor sysSema;   // damit werden einige Systemaufrufe serialisiert...
  52.  
  53.  
  54.  
  55. size_t fwriteT( const void *buffer, size_t size, size_t count, FILE *out )
  56. {
  57.     size_t res;
  58.  
  59.     sysSema.Request();
  60.     res = fwrite( buffer,size,count,out );
  61.     sysSema.Release();
  62.     return res;
  63. }   // fwriteT
  64.  
  65.  
  66.  
  67. FILE *popenT( const char *command, const char *mode )
  68. {
  69.     FILE *res;
  70.  
  71. #ifdef TRACE_ALL
  72.     printfT( "popenT(%s,%s)\n", command,mode );
  73. #endif
  74.  
  75.     sysSema.Request();
  76.     res = popen( command,mode );
  77.     sysSema.Release();
  78.     return res;
  79. }   // popenT
  80.  
  81.  
  82.  
  83. int pcloseT( FILE *io )
  84. {
  85.     int res;
  86.  
  87. #ifdef TRACE_ALL
  88.     printfT( "pcloseT(%p)\n", io );
  89. #endif
  90.  
  91.     sysSema.Request();
  92.     res = pclose( io );
  93.     sysSema.Release();
  94.     return res;
  95. }   // pcloseT
  96.  
  97.  
  98.  
  99. int removeT( const char *fname )
  100. {
  101.     int res;
  102.  
  103. #ifdef TRACE_ALL
  104.     printfT( "removeT(%s)\n", fname );
  105. #endif
  106.  
  107.     sysSema.Request();
  108.     res = remove( fname );
  109.     sysSema.Release();
  110.     return res;
  111. }   // removeT
  112.  
  113.  
  114.  
  115. int renameT( const char *oldname, const char *newname )
  116. {
  117.     int res;
  118.  
  119. #ifdef TRACE_ALL
  120.     printfT( "renameT(%s,%s)\n",oldname,newname );
  121. #endif
  122.  
  123.     sysSema.Request();
  124.     res = rename( oldname,newname );
  125.     sysSema.Release();
  126.     return res;
  127. }   // renameT
  128.  
  129.  
  130.  
  131. static char *tempnamT( const char *dir, const char *prefix )
  132. {
  133.     char *res;
  134.  
  135. #ifdef TRACE_ALL
  136.     printfT( "tempnamT(%s,%s)\n",dir,prefix );
  137. #endif
  138.  
  139.     sysSema.Request();
  140.     res = tempnam( dir,prefix );
  141.     sysSema.Release();
  142.     return res;
  143. }   // tempNamT
  144.  
  145.  
  146.  
  147. static int openT( const char *name, int oflag )
  148. //
  149. //  open file with mode oflag.
  150. //  - shared write access is denied
  151. //  - if file will be created, it will permit read/write access
  152. //
  153. {
  154.     int res;
  155.  
  156. #ifdef TRACE_ALL
  157.     printfT( "openT(%s,%d)\n", name,oflag );
  158. #endif
  159.  
  160.     sysSema.Request();
  161.     res = sopen( name, oflag, SH_DENYWR, S_IREAD | S_IWRITE );
  162.     sysSema.Release();
  163.     return res;
  164. }   // openT
  165.  
  166.  
  167.  
  168. static int closeT( int handle )
  169. {
  170.     int res;
  171.  
  172. #ifdef TRACE_ALL
  173.     printfT( "closeT(%d)\n", handle );
  174. #endif
  175.  
  176.     sysSema.Request();
  177.     res = close( handle );
  178.     sysSema.Release();
  179.     return res;
  180. }   // closeT
  181.  
  182.  
  183.  
  184. static int readT( int handle, void *buffer, int len )
  185. {
  186.     int res;
  187.  
  188. #ifdef TRACE_ALL
  189.     printfT( "readT(%d,%p,%d)\n",handle,buffer,len );
  190. #endif
  191.  
  192.     sysSema.Request();
  193.     res = read( handle,buffer,len );
  194.     sysSema.Release();
  195.     return res;
  196. }   // readT
  197.  
  198.  
  199.  
  200. static int writeT( int handle, const void *buffer, int len )
  201. {
  202.     int res;
  203.  
  204. #ifdef TRACE_ALL
  205.     printfT( "writeT(%d,%p,%d)\n",handle,buffer,len );
  206. #endif
  207.  
  208.     sysSema.Request();
  209.     res = write( handle,buffer,len );
  210.     sysSema.Release();
  211.     return res;
  212. }   // writeT
  213.  
  214.  
  215.  
  216. static long lseekT( int handle, long offset, int origin )
  217. {
  218.     long res;
  219.  
  220. #ifdef TRACE_ALL
  221.     printfT( "lseekT(%d,%ld,%d)\n",handle,offset,origin );
  222. #endif
  223.  
  224.     sysSema.Request();
  225.     res = lseek( handle,offset,origin );
  226.     sysSema.Release();
  227.     return res;
  228. }   // lseekT
  229.  
  230.  
  231.  
  232. static int ftruncateT( int handle, long length )
  233. {
  234.     int res;
  235.  
  236. #ifdef TRACE_ALL
  237.     printfT( "ftruncateT(%d,%ld)\n",handle,length );
  238. #endif
  239.  
  240.     sysSema.Request();
  241.     res = ftruncate( handle,length );
  242.     sysSema.Release();
  243.     return res;
  244. }   // ftruncateT
  245.  
  246.  
  247.  
  248. //--------------------------------------------------------------------------------
  249.  
  250.  
  251.  
  252. int hprintfT( int handle, const char *fmt, ... )
  253. {
  254.     va_list ap;
  255.     char buf[BUFSIZ];
  256.     int  buflen;
  257.  
  258.     sysSema.Request();
  259.     va_start( ap, fmt );
  260.     buflen = vsprintf( buf, fmt, ap );
  261.     va_end( ap );
  262.     if (buflen > 0)
  263.     buflen = write( handle,buf,buflen );
  264.     sysSema.Release();
  265.     return buflen;
  266. }   // hprintfT
  267.  
  268.  
  269.  
  270. int hputsT( const char *s, int handle )
  271. {
  272.     int len, res;
  273.  
  274.     sysSema.Request();
  275.     len = strlen(s);
  276.     res = write( handle,s,len );
  277.     sysSema.Release();
  278.     return (res == len) ? len : EOF;
  279. }   // hputsT
  280.  
  281.  
  282.  
  283. int sprintfT( char *dst, const char *fmt, ... )
  284. {
  285.     va_list ap;
  286.     int  buflen;
  287.  
  288.     sysSema.Request();
  289.     *dst = '\0';
  290.     va_start( ap, fmt );
  291.     buflen = vsprintf( dst, fmt, ap );
  292.     va_end( ap );
  293.     sysSema.Release();
  294.     
  295.     return buflen;
  296. }   // sprintfT
  297.  
  298.  
  299.  
  300. int printfT( const char *fmt, ... )
  301. {
  302.     va_list ap;
  303.     char buf[BUFSIZ];
  304.     int  buflen;
  305.  
  306.     sysSema.Request();
  307.     va_start( ap, fmt );
  308.     buflen = vsprintf( buf, fmt, ap );
  309.     va_end( ap );
  310.     if (buflen > 0)
  311.     write( STDOUT_FILENO, buf,buflen );
  312.     sysSema.Release();
  313.     return buflen;
  314. }   // printfT
  315.  
  316.  
  317.  
  318. int vprintfT( const char *fmt, va_list arg_ptr )
  319. {
  320.     char buf[BUFSIZ];
  321.     int buflen;
  322.  
  323.     sysSema.Request();
  324.     buflen = vsprintf( buf,fmt,arg_ptr );
  325.     if (buflen > 0)
  326.     write( STDOUT_FILENO, buf,buflen );
  327.     sysSema.Release();
  328.     return buflen;
  329. }   // vprintfT
  330.  
  331.  
  332.  
  333. int vsprintfT( char *dst, const char *fmt, va_list arg_ptr )
  334. {
  335.     int buflen;
  336.  
  337.     sysSema.Request();
  338.     buflen = vsprintf( dst,fmt,arg_ptr );
  339.     sysSema.Release();
  340.     return buflen;
  341. }   // vsprintfT
  342.  
  343.  
  344.  
  345. int sscanfT( const char *src, const char *fmt, ... )
  346. {
  347.     va_list ap;
  348.     int fields;
  349.  
  350.     sysSema.Request();
  351.     va_start( ap, fmt );
  352.     fields = vsscanf( src, fmt, ap );
  353.     va_end( ap );
  354.     sysSema.Release();
  355.     return fields;
  356. }   // sscanfT
  357.  
  358.  
  359.  
  360. //--------------------------------------------------------------------------------
  361.  
  362.  
  363.  
  364. TFileTmp::TFileTmp( void )
  365. {
  366. #ifdef TRACE_ALL
  367.     printfT( "TFileTmp::TFileTmp()\n" );
  368. #endif
  369.     memBuff     = NULL;
  370.     memBuffSize = 0;
  371. }   // TFileTmp::TFileTmp
  372.  
  373.  
  374.  
  375. TFileTmp::~TFileTmp()
  376. {
  377. #ifdef TRACE_ALL
  378.     printfT( "TFileTmp::~TFileTmp()\n" );
  379. #endif
  380.     close();
  381. }   // TFileTmp::~TFileTmp
  382.  
  383.  
  384.  
  385. void TFileTmp::close( void )
  386. {
  387. #ifdef TRACE_ALL
  388.     printfT( "TFileTmp::close() %s\n",fname );
  389. #endif
  390.     TFile::close( 0,1 );
  391.     if (memBuff != NULL) {
  392.     memBuffSize = 0;
  393.     delete memBuff;
  394.     memBuff = NULL;
  395.     }
  396. }   // TFileTmp::close
  397.  
  398.  
  399.  
  400. int TFileTmp::open( const char *pattern, int buffSize )
  401. //
  402. //  ein temporärer File ist immer binär und wird immer erzeugt,
  403. //  und ist read/write!
  404. //
  405. {
  406.     char *tname;
  407.  
  408. #ifdef TRACE_ALL
  409.     printfT( "TFileTmp::open(%s,%d)\n", pattern,buffSize );
  410. #endif
  411.     for (;;) {
  412.     if ((tname = ::tempnamT(NULL,pattern)) == NULL)
  413.         return 0;
  414.     filePos = 0;
  415.     fileLen = 0;
  416.     if (TFile::open(tname,TFile::mreadwrite, obinary,1)) {
  417.         free( tname );
  418.         break;
  419.     }
  420. #ifdef DEBUG_ALL
  421.     printfT( "temp file %s rejected (already in use)\n",tname );
  422.     perror( tname );
  423. #endif
  424.     free( tname );
  425.     }
  426.     memBuff = new unsigned char[buffSize];
  427.     memBuffSize = buffSize;
  428.     return 1;
  429. }   // TFileTmp::open
  430.  
  431.  
  432.  
  433. int TFileTmp::iread( void *buff, int bufflen )
  434. {
  435.     int cbufflen;
  436.     
  437. #ifdef TRACE_ALL
  438.     printfT( "TFileTmp::read(%p,%d) %s\n",buff,bufflen,fname );
  439. #endif
  440.  
  441.     //
  442.     //  compare remaining file data to requested size bufflen
  443.     //
  444.     if (bufflen >= 0  &&  filePos + bufflen > fileLen)
  445.     bufflen = fileLen - filePos;
  446.     cbufflen = bufflen;
  447.  
  448.     //
  449.     //  read from memory part
  450.     //
  451.     if (filePos < memBuffSize  &&  cbufflen > 0) {
  452.     int toRead = cbufflen;
  453.     if (filePos + cbufflen > memBuffSize)
  454.         toRead = memBuffSize - filePos;
  455.     memcpy( buff, memBuff+filePos, toRead );
  456.     buff = (char *)buff + toRead;
  457.     cbufflen -= toRead;
  458.     }
  459.  
  460.     //
  461.     //  read from physical file
  462.     //
  463.     if (cbufflen > 0)
  464.     TFile::iread( buff,cbufflen );
  465.  
  466.     return bufflen;
  467. }   // TFileTmp::iread
  468.  
  469.  
  470.  
  471. int TFileTmp::iwrite( const void *buff, int bufflen )
  472. {
  473.     int cbufflen = bufflen;
  474.     
  475. #ifdef TRACE_ALL
  476.     printfT( "TFileTmp::iwrite(%p,%d) %s\n",buff,bufflen,fname );
  477. #endif
  478.     //
  479.     //  write to memory part
  480.     //
  481.     if (filePos < memBuffSize  &&  cbufflen > 0) {
  482.     int toWrite = cbufflen;
  483.     if (filePos + cbufflen > memBuffSize)
  484.         toWrite = memBuffSize - filePos;
  485.     memcpy( memBuff+filePos, buff, toWrite );
  486.     buff = (char *)buff + toWrite;
  487.     cbufflen -= toWrite;
  488.     }
  489.  
  490.     //
  491.     //  write to physical file
  492.     //
  493.     if (cbufflen > 0)
  494.     TFile::iwrite( buff,cbufflen );
  495.  
  496.     return bufflen;
  497. }   // TFileTmp::iwrite
  498.  
  499.  
  500.  
  501. int TFileTmp::truncate( long offset )
  502. //
  503. //  filePos is undefined after truncate()
  504. //
  505. {
  506. #ifdef TRACE_ALL
  507.     printfT( "TFileTmp::truncate(%ld)\n",offset );
  508. #endif
  509.     if (offset < fileLen)
  510.     fileLen = offset;
  511.  
  512.     //
  513.     //  set physical file
  514.     //
  515.     if (fileLen <= memBuffSize)
  516.     TFile::truncate( 0 );
  517.     else
  518.     TFile::truncate( fileLen-memBuffSize );
  519.     
  520.     return 0;
  521. }   // TFileTmp::truncate
  522.  
  523.  
  524.  
  525. long TFileTmp::seek( long offset, int origin )
  526. {
  527. #ifdef TRACE_ALL
  528.     printfT( "TFileTmp::seek(%ld,%d) %s\n",offset,origin,fname );
  529. #endif
  530.  
  531.     //
  532.     //  calculate new file position
  533.     //
  534.     if (origin == SEEK_SET)
  535.     filePos = offset;
  536.     else if (origin == SEEK_CUR)
  537.     filePos += offset;
  538.     else if (origin == SEEK_END)
  539.     filePos = fileLen + offset;
  540.     if (filePos < 0)
  541.     filePos = 0;
  542.     else if (filePos > fileLen)
  543.     filePos = fileLen;
  544.  
  545.     //
  546.     //  set physical file pointer
  547.     //
  548.     {
  549.     long tPos = filePos;
  550.     
  551.     if (filePos <= memBuffSize)
  552.         TFile::seek( 0, SEEK_SET );
  553.     else
  554.         TFile::seek( filePos-memBuffSize, SEEK_SET );
  555.     filePos = tPos;
  556.     }
  557.     
  558.     return filePos;
  559. }   // TFileTmp::seek
  560.  
  561.  
  562.  
  563. //--------------------------------------------------------------------------------
  564.  
  565.  
  566.  
  567. TFile::TFile( void )
  568. {
  569. #ifdef TRACE_ALL
  570.     printfT( "TFile::TFile()\n" );
  571. #endif
  572.     mode  = mnotopen;
  573.     fname = NULL;
  574.     filePos = 0;
  575.     fileLen = 0;
  576. }   // TFile::TFile
  577.  
  578.  
  579.  
  580. TFile::~TFile()
  581. {
  582. #ifdef TRACE_ALL
  583.     printfT( "TFile::~TFile()\n" );
  584. #endif
  585.     close();
  586. }   // TFile::~TFile
  587.  
  588.  
  589.  
  590. void TFile::close( int killif0, int forceKill )
  591. {
  592. #ifdef TRACE_ALL
  593.     printfT( "TFile::close(%d,%d) %s\n",killif0,forceKill,fname );
  594. #endif
  595.  
  596.     if (mode != mnotopen) {
  597.         int kill = (killif0  &&  (::tell(handle) == 0))  ||  forceKill;
  598.     ::closeT( handle );
  599.     if (kill)
  600.         ::removeT( fname );
  601.     }
  602.  
  603.     if (fname != NULL) {
  604.     delete fname;
  605.     fname = NULL;
  606.     }
  607.     if (mode == mread  ||  mode == mreadwrite) {
  608.     delete buffer;
  609.     buffer = NULL;
  610.     buffSize = 0;
  611.     invalidateBuffer();
  612.     }
  613.     mode   = mnotopen;
  614.     handle = -1;
  615. }   // TFile::close
  616.  
  617.  
  618.  
  619. void TFile::remove( void )
  620. {
  621.     close( 0,1 );
  622. }   // TFile::remove
  623.  
  624.  
  625.  
  626. int TFile::open( const char *name, TMode mode, OMode textmode, int create )
  627. //
  628. //  in case of mwrite, the file pointer is positioned at end of file
  629. //  returns 0, if not successful
  630. //
  631. {
  632.     int flag;
  633.  
  634. #ifdef TRACE_ALL
  635.     printfT( "TFile::open(%s,%d,%d,%d)\n",name,mode,textmode,create );
  636. #endif
  637.  
  638.     if (TFile::mode != mnotopen)
  639.     close(0);
  640.  
  641.     if (textmode == otext)
  642.     flag = O_TEXT;
  643.     else
  644.     flag = O_BINARY;
  645.  
  646.     if (mode == mread)
  647.     flag |= O_RDONLY;
  648.     else if (mode == mwrite)
  649.     flag |= O_WRONLY;
  650.     else if (mode == mreadwrite)
  651.     flag |= O_RDWR;
  652.     else {
  653.     errno = EPERM;
  654.     return 0;
  655.     }
  656.     
  657.     if (create)
  658.     flag |= O_CREAT | O_TRUNC;
  659.  
  660.     handle = ::openT( name, flag );
  661.     if (handle < 0)
  662.     return 0;
  663.  
  664.     seek( 0,SEEK_END );           // set fileLen
  665.     fileLen = filePos;
  666.     if (mode != mwrite)
  667.     seek( 0,SEEK_SET );       // sets also filePos
  668.     
  669.     TFile::mode = mode;
  670.     xstrdup( &fname, name );
  671.     buffSize = 0;
  672.     buffer = NULL;
  673.     if (mode == mread  ||  mode == mreadwrite) {
  674.     buffSize = 4096;
  675.     buffer = new unsigned char[buffSize+10];
  676.     }
  677.     invalidateBuffer();
  678.     return 1;
  679. }   // TFile::open
  680.  
  681.  
  682.  
  683. int TFile::truncate( long length )
  684. {
  685.     int res = ::ftruncateT( handle, length );
  686.     seek( 0, SEEK_END );
  687.     return res;
  688. }   // TFile::truncate
  689.  
  690.  
  691.  
  692. long TFile::seek( long offset, int origin )
  693. {
  694.     long pos;
  695.  
  696. #ifdef TRACE_ALL
  697.     printfT( "TFile::seek(%ld,%d)\n",offset,origin );
  698. #endif
  699.     invalidateBuffer();
  700.     pos = ::lseekT( handle,offset,origin );
  701.     if (pos >= 0)
  702.     filePos = pos;
  703.     return pos;
  704. }   // TFile::seek
  705.  
  706.  
  707.  
  708. long TFile::tell( void )
  709. {
  710.     return filePos;
  711. }   // TFile::tell
  712.  
  713.  
  714.  
  715. int TFile::write( const void *buff, int bufflen )
  716. {
  717.     int r;
  718.  
  719.     if (bufflen <= 0)
  720.     return 0;
  721.  
  722.     //
  723.     //  set the physical filePos correctly (fillBuff() problem)
  724.     //
  725.     if (buffNdx < buffEnd)
  726.     seek( filePos,SEEK_SET );   // also invalidates Buffer
  727.     
  728.     r = iwrite( buff,bufflen );
  729.     if (r > 0) {
  730.     filePos += r;
  731.     if (filePos > fileLen)
  732.         fileLen = filePos;
  733.     }
  734.     return r;
  735. }   // TFile::write
  736.  
  737.  
  738.  
  739. int TFile::iwrite( const void *buff, int bufflen )
  740. //
  741. //  must not change filePos!
  742. //
  743. {
  744.     return ::writeT( handle,buff,bufflen );
  745. }   // TFile::iwrite
  746.  
  747.  
  748.  
  749. int TFile::putcc( char c )
  750. {
  751.     return (write(&c,1) == 1) ? 1 : EOF;
  752. }   // TFile::putc
  753.  
  754.  
  755.  
  756. int TFile::fputs( const char *s )
  757. {
  758.     int len, res;
  759.  
  760.     len = strlen(s);
  761.     res = write( s,len );
  762.     return (res == len) ? len : EOF;
  763. }   // TFile::fputs
  764.  
  765.  
  766.  
  767. int TFile::printf( const char *fmt, ... )
  768. {
  769.     va_list ap;
  770.     char buf[BUFSIZ];
  771.     int  buflen;
  772.  
  773.     va_start( ap, fmt );
  774.     buflen = ::vsprintfT( buf, fmt, ap );
  775.     va_end( ap );
  776.     return write( buf,buflen );
  777. }   // TFile::printf
  778.  
  779.  
  780.  
  781. int TFile::vprintf( const char *fmt, va_list arg_ptr )
  782. {
  783.     char buf[BUFSIZ];
  784.     int buflen;
  785.  
  786.     buflen = ::vsprintfT( buf,fmt,arg_ptr );
  787.     return write( buf,buflen );
  788. }   // TFile::vprintf
  789.  
  790.  
  791.  
  792. int TFile::read( void *buff, int bufflen )
  793. {
  794.     int r;
  795.  
  796.     invalidateBuffer();
  797.     r = iread( buff,bufflen );
  798.     if (r > 0)
  799.     filePos += r;
  800.  
  801.     assert( filePos <= fileLen );
  802.     return r;
  803. }   // TFile::read
  804.  
  805.  
  806.  
  807. int TFile::iread( void *buff, int bufflen )
  808. //
  809. //  must not change filePos!
  810. //
  811. {
  812.     return ::readT( handle,buff,bufflen );
  813. }   // TFile::iread
  814.  
  815.  
  816.  
  817. int TFile::fillBuff( void )
  818. //
  819. //  must not change filePos!
  820. //
  821. {
  822.     int blk;
  823.     int toRead;
  824.  
  825. #ifdef TRACE_ALL
  826.     printfT( "TFile::fillBuff()\n" );
  827. #endif
  828.  
  829.     if (buffEof)
  830.     return buffNdx < buffEnd;
  831.  
  832.     if (buffEnd-buffNdx >= buffSize/2)
  833.     return 1;
  834.  
  835. #ifdef TRACE_ALL
  836.     printfT( "TFile::fillBuff() -- 2\n" );
  837. #endif
  838.  
  839.     memmove( buffer, buffer+buffNdx, buffEnd-buffNdx );
  840.     buffEnd = buffEnd - buffNdx;
  841.     buffNdx = 0;
  842.     toRead = (buffSize-buffEnd) & 0xfc00;
  843.     blk = iread( buffer+buffEnd, toRead );
  844.     if (blk > 0)
  845.     buffEnd += blk;
  846.     else
  847.     buffEof = 1;            // -> nothing left to read!
  848.     buffer[buffEnd] = '\0';
  849.  
  850. #ifdef DEBUG_ALL
  851.     printfT( "TFile::fillBuff() = %d,%d,%d\n",blk,buffNdx,buffEnd );
  852. #endif
  853.     return buffEnd > 0;
  854. }   // TFile::fillBuff
  855.  
  856.  
  857.  
  858. int TFile::getcc( void )
  859. {
  860.     if (buffNdx >= buffEnd) {
  861.     if ( !fillBuff())
  862.         return -1;
  863.     }
  864.     ++filePos;
  865.     return buffer[buffNdx++];
  866. }   // TFile::getcc
  867.  
  868.  
  869.  
  870. char *TFile::fgets( char *buff, int bufflen, int skipCrLf )
  871. //
  872. //  '\0' will always be skipped!
  873. //  If SkipCrLf, then also \r & \n are skipped
  874. //
  875. {
  876.     char *p;
  877.     int  n;
  878.     int  r;
  879.  
  880. #ifdef TRACE_ALL
  881.     printfT( "TFile::fgets(.,%d) %s\n",bufflen,fname );
  882. #endif
  883.  
  884.     p = buff;
  885.     n = 0;
  886.     for (;;) {
  887.     if (n >= bufflen-2) {     // if Buffer exhausted return (there is no \n at eob)
  888.         if (skipCrLf) {
  889.         do
  890.             r = getcc();
  891.         while (r > 0  &&  r != '\n');
  892.         }
  893.         break;
  894.     }
  895.  
  896.     r = getcc();
  897.     if (r < 0) {              // EOF!
  898.         if (n == 0) {
  899.         *p = '\0';
  900.         return( NULL );
  901.         }
  902.         else
  903.         break;
  904.     }
  905.     else if (r != 0) {
  906.         if ( ! (skipCrLf  &&  (r == '\r'  ||  r == '\n'))) {
  907.         *(p++) = (unsigned char)r;
  908.         ++n;
  909.         }
  910.         if (r == '\n')
  911.         break;
  912.     }
  913.     }
  914.     *p = '\0';
  915.     return buff;
  916. }   // TFile::fgets
  917.  
  918.  
  919.  
  920. int TFile::scanf( const char *fmt, void *a1 )
  921. //
  922. //  Scan one argument via sscanf.  Extension of this function to any number
  923. //  of arguments does not work, because "%n" must be added (and an argument...)
  924. //  Perhaps one argument is also ok, because what happened if one wants to
  925. //  scan two arguments, but the second failed (what will "%n" display?)
  926. //  -  sollen besondere Zeichen gescannt werden, so sollte das immer mit "%[...]"
  927. //     gemacht werden, da ein einzelnes Zeichen, daß nicht paßt die Zuweisung "%n"
  928. //     verhindert!
  929. //  trick:  the internal read buffer is always kept at least half full,
  930. //          therefor scanf can work just like sscanf!
  931. //
  932. {
  933.     int  fields;
  934.     int  cnt;
  935.     char fmt2[200];
  936.  
  937. #ifdef TRACE_ALL
  938.     printfT( "TFile::scanf1(%s,...) %d,%d\n",fmt,buffNdx,buffEnd );
  939. #endif
  940.  
  941.     if ( !fillBuff())
  942.     return EOF;
  943.  
  944.     strcpy( fmt2,fmt );
  945.     strcat( fmt2,"%n" );
  946.  
  947.     cnt = 0;
  948.     fields = ::sscanfT( (char *)buffer+buffNdx, fmt2, a1,&cnt );
  949. #ifdef DEBUG_ALL
  950.     printfT( "TFile::scanf1()='%.20s' %d,%d\n",buffer+buffNdx,cnt,fields );
  951. #endif
  952.     if (cnt == 0)
  953.     fields = 0;
  954.     else {
  955.     buffNdx += cnt;
  956.     filePos += cnt;
  957.     assert( filePos <= fileLen );
  958.     }
  959.     return fields;
  960. }   // TFile::scanf
  961.  
  962.  
  963.  
  964. //--------------------------------------------------------------------------------
  965.  
  966.  
  967.  
  968. static TSemaphor regSema;
  969.  
  970.  
  971.  
  972. regexp *regcompT( const char *exp )
  973. {
  974.     regexp *res;
  975.  
  976.     regSema.Request();
  977.     res = regcomp( exp );
  978.     regSema.Release();
  979.     return res;
  980. }   // regcompT
  981.  
  982.  
  983.  
  984. int regexecT( const regexp *cexp, const char *target )
  985. {
  986.     int res;
  987.  
  988.     regSema.Request();
  989.     res = regexec( cexp,target );
  990.     regSema.Release();
  991.     return res;
  992. }   // regexecT
  993.  
  994.  
  995.  
  996. //--------------------------------------------------------------------------------
  997.  
  998.  
  999.  
  1000. const char *xstrdup( const char *src )
  1001. {
  1002.     int len;
  1003.     char *dst;
  1004.  
  1005.     len = strlen(src)+1;
  1006.     dst = new char [len];
  1007.     if (dst != NULL)
  1008.     memcpy( dst,src,len );
  1009.     else {
  1010.     hprintfT( STDERR_FILENO,"\nxstrdup failed\nprogram aborted\n" );
  1011.     exit( 3 );
  1012.     }
  1013.     return dst;
  1014. }   // xstrdup
  1015.  
  1016.  
  1017.  
  1018. void xstrdup( const char **dst, const char *src )
  1019. {
  1020.     if (*dst != NULL)
  1021.     delete *dst;
  1022.  
  1023.     if (src != NULL)
  1024.     *dst = xstrdup( src );
  1025.     else
  1026.     *dst = NULL;
  1027. }   // xstrdup
  1028.