home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 318_01 / redsys.c < prev    next >
C/C++ Source or Header  |  1990-06-18  |  14KB  |  756 lines

  1. /*
  2.     RED operating system module -- Full C version
  3.  
  4.     Source:  redsys.c
  5.     Version: June 18, 1986; January 18, 1990.
  6.  
  7.     Written by
  8.     
  9.         Edward K. Ream
  10.         166 N. Prospect
  11.         Madison WI 53705
  12.         (608) 257-0802
  13.  
  14.  
  15.     PUBLIC DOMAIN SOFTWARE
  16.  
  17.     This software is in the public domain.
  18.  
  19.     See red.h for a disclaimer of warranties and other information.
  20. */
  21.  
  22. #include "red.h"
  23.  
  24. #ifdef MICRO_SOFT
  25. #include <bios.h>
  26. #include <fcntl.h>
  27. #include <io.h>
  28. #include <malloc.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <sys\types.h>
  33. #include <sys\stat.h>
  34. #endif
  35.  
  36. #ifdef TURBOC
  37. #include <alloc.h>
  38. #include <conio.h>
  39. #include <fcntl.h>
  40. #include <io.h>
  41. #include <mem.h>
  42. #include <sys\stat.h>
  43. #endif
  44.  
  45. static char sysinbuf[128];        /* file buffer        */
  46. static int  sysincnt;            /* index to sysinbuf[]    */
  47. static char syscbuf[MAXLEN];        /* typeahead buffer    */
  48. static int  sysccnt;            /* index for syscbuf[]    */
  49. static int  sysrcnt;            /* repeat count        */
  50. static int  syslastc;            /* last character    */
  51. static int  systopl,systopy,sysnl;    /* interrupt info    */
  52.  
  53. /*
  54.     NOTE:  This module should contain all routines that
  55.     might have to be changed for different compilers or
  56.     different operating systems.  
  57.  
  58.     Some routines in this module probably will probably
  59.     work regardless of operating system.  These I have
  60.     called PORTABLE routines.
  61. */
  62.  
  63. /*
  64.     Return a pointer to a block of n contiguous bytes.
  65.     Return NULL (i.e.,  0) if fewer than n bytes remain.
  66. */
  67. char *
  68. sysalloc(n)
  69. int n;
  70. {
  71.     char * p;
  72.     p = (char *) malloc(n);
  73.  
  74.     TRACEP("sysalloc",
  75.         sl_lpout(); sl_iout(n);
  76.         sl_sout(") returns "); sl_pout(p); sl_cout('\n'));
  77.  
  78.     return p;
  79. }
  80.  
  81. /*
  82.     o  Wait for next character from the console.
  83.     o  Do NOT echo the character.
  84.     o  Print any waiting lines if there is no input ready.
  85.         o  Swap out any dirty blocks if nothing else is happening.
  86.        (The SWAP constant enables this feature)
  87. */
  88. int
  89. syscin(void)
  90. {
  91.     int c;
  92.     int main_byte, aux_byte;
  93.  
  94.     SL_DISABLE();
  95.  
  96.     for(;;) {
  97.         c = syscstat();
  98.         if (c != -1) {
  99.             break;
  100.         }
  101.  
  102.         /* Output queued ? */
  103.         if (hasint && sysnl > 0) {
  104.             /* Print one line. */
  105.             bufout(systopl, systopy, sysnl);
  106.         }
  107.  
  108. #ifdef SWAP
  109.         /* Do not interrupt screen activity. */
  110.         if (sysnl == 0) {
  111.             /* Swap out one dirty buffer. */
  112.             swap_one();
  113.         }
  114. #endif
  115.  
  116.     }
  117.  
  118. #ifdef IBM
  119.  
  120.     main_byte = c & 0xff;
  121.     aux_byte  = (c & 0xff00) >> 8;
  122.  
  123.     TRACEP("syscin",
  124.         sl_sout(" main: "); sl_iout(main_byte);
  125.         sl_sout(" aux: ");  sl_iout(aux_byte);
  126.         sl_cout('\n'));
  127.  
  128.     /* Handle cursor keys and the numeric keypad. */
  129.     if (main_byte == 0) switch (aux_byte) {
  130.  
  131.         case 71: return HOME_KEY;     /* Home key.     */
  132.         case 79: return END_KEY;     /* End key.       */
  133.  
  134.         case 73: return PAGE_UP;    /* Page up key.   */
  135.         case 81: return PAGE_DN;    /* Page down key. */
  136.         case 82: return UP_INS;        /* Insert key     */
  137.         case 83: return DEL2;        /* Delete Key     */
  138.  
  139.         case 77:  return RIGHT;        /* Arrow keys.    */
  140.         case 75:  return LEFT;
  141.         case 72:  return UP;
  142.         case 80:  return DOWN;
  143.     }
  144.  
  145. #endif
  146.  
  147.     return c & 0x7f;
  148. }
  149.  
  150. /*
  151.     Close an unbuffered file.
  152.     Return OK (0) or ERROR (-1).
  153. */
  154. int
  155. sysclose(int fd)
  156. {
  157.     TRACEP("sysclose", sl_lpout(); sl_iout(fd); sl_rpout());
  158.  
  159.     close(fd);
  160. }
  161.  
  162. /*
  163.     Copy a file name from args to buffer.
  164.     This routine is SEMI-PORTABLE,  since it depends,
  165.     to a certain extent,  on what constitutes a file name.
  166. */
  167. void
  168. syscopfn(char *args, char *buffer)
  169. {
  170.     int n;
  171.  
  172.     TRACEP("syscopfn",       sl_lpout();
  173.         sl_sout(args);   sl_csout();
  174.         sl_pout(buffer); sl_rpout());
  175.  
  176.     for (n = 0;
  177.          n < SYSFNMAX -1 && args [n] != '\0' && args [n] != ' ';
  178.          n++) {
  179.  
  180.         buffer [n] = args [n];
  181.     }
  182.     buffer[n] = '\0';
  183. }
  184.  
  185. /*
  186.     Create an file for use by sysread and syswrite.
  187.     Erase it if it exists and leave it open for read/write access.
  188.     Return a small positive int or ERROR  (-1).
  189. */
  190. int
  191. syscreat(char * filename)
  192. {
  193.     int result;
  194.  
  195.     TRACEP("syscreat", sl_lpout(); sl_sout(filename));
  196.  
  197. #ifdef MICRO_SOFT
  198.     _fmode = O_BINARY;
  199.     result = creat(filename, S_IREAD | S_IWRITE);
  200.     _fmode = O_TEXT;
  201. #endif
  202.  
  203. #ifdef TURBOC
  204.     _fmode = O_BINARY;
  205.     result = creat(filename, S_IREAD | S_IWRITE);
  206.     _fmode = O_TEXT;
  207. #endif
  208.  
  209.     TRACE("syscreat",
  210.         sl_sout(") returns "); sl_iout(result); sl_cout('\n'));
  211.  
  212.     return result;
  213. }
  214.  
  215. /*
  216.     Return -1 if no character is ready from the keyboard.
  217.     Otherwise, return the character itself.
  218.  
  219.     This routine handles typeahead buffering.  It would
  220.     also handle the repeat key,  if that feature is used,
  221.     which it is NOT at present.  The code enclosed in
  222.     comments handles the repeat key.
  223. */
  224. int
  225. syscstat(void)
  226. {
  227.     int c;
  228.  
  229.     SL_DISABLE();
  230.  
  231.     /* Always look for another character. */
  232.  
  233. #ifdef MICRO_SOFT
  234.  
  235.     c = _bios_keybrd(_KEYBRD_READY);
  236.     if (c == 0) {
  237.         c = -1;
  238.     }
  239.     else {
  240.         _bios_keybrd(_KEYBRD_READ);
  241.     }
  242. #endif
  243.  
  244. #ifdef TURBOC
  245.  
  246.     c = bioskey(1);
  247.     if (c == 0) {
  248.         c = -1;
  249.     }
  250.     else {
  251.         bioskey(0);
  252.     }
  253. #endif
  254.  
  255.     return c;
  256. }
  257.  
  258.  
  259. /*
  260.     Execute args as if they were entered from the command line.
  261. */
  262. void
  263. sysexec(char *args)
  264. {
  265.  
  266.     SL_DISABLE();
  267.  
  268. #ifdef MICRO_SOFT
  269.     system(args);
  270.     puts("\nPress any key to resume editing: ");
  271.     syscin();
  272. #endif
  273.  
  274. #ifdef TURBOC
  275.     system(args);
  276.     puts("\nPress any key to resume editing: ");
  277.     syscin();
  278. #endif
  279.  
  280. }
  281.  
  282. /*
  283.     Return TRUE if the file exists and FALSE otherwise.
  284.     This routine is PORTABLE.
  285. */
  286. int
  287. sysexists(char * filename)
  288. {
  289.     int fd;
  290.  
  291.     TRACEPB("sysexists", sl_lpout(); sl_sout(filename); sl_rpout());
  292.  
  293.     if ((fd = sysopen(filename)) != ERROR) {
  294.         sysclose(fd);
  295.  
  296.         RETURN_BOOL("sysexists", TRUE);
  297.     }
  298.     else {
  299.         RETURN_BOOL("sysexists", FALSE);
  300.     }
  301. }
  302.  
  303. /*
  304.     Close and flush a file opened with sysfopen or sysfcreat.
  305.     Return OK (0) or ERROR (-1).
  306. */
  307. int
  308. sysfclose(FILE *fd)
  309. {
  310.     TRACEP("sysfclose", sl_lpout(); sl_pout(fd); sl_rpout());
  311.  
  312.     return fclose(fd);
  313. }
  314.  
  315. /*
  316.     Create a buffered output file for use with sysfputs.
  317.  
  318.     The file is cleared (erased) if it already exists.
  319.     A pointer to FILE is returned if all goes well.
  320.     NULL (0), is returned if the file can not be created.
  321. */
  322. FILE *
  323. sysfcreat(char *filename)
  324. {
  325.     FILE * f;
  326.  
  327.     TRACEP("sysfcreat", sl_lpout();    sl_sout(filename));
  328.  
  329. #ifdef MICRO_SOFT
  330.     f = fopen(filename, "w");
  331. #endif
  332.  
  333. #ifdef TURBOC
  334.     f = fopen(filename, "w");
  335. #endif
  336.  
  337.     TRACE("sysfcreat",
  338.         sl_sout(") returns "); sl_pout(f); sl_cout('\n'));
  339.  
  340.     return f;
  341. }
  342.  
  343. /*
  344.     Read the next line from buffered input file.
  345.     End the line with an '\n'.
  346.     Return the count of the characters read.
  347.     Return ERROR (-1) on end-of-file.
  348. */
  349. int
  350. sysfgets(FILE *fd, char *buffer, int maxlen)
  351. {
  352.     int c, count;
  353.  
  354.     TRACEP("sysfgets",      sl_lpout();
  355.         sl_pout(fd);     sl_csout();
  356.         sl_pout(buffer); sl_csout(); 
  357.         sl_iout(maxlen));
  358.  
  359.     count = 0;
  360.     while(1) {
  361.         c = sysgetc(fd);
  362.         if (c == '\r') {
  363.             /* Ignore pseudo newline. */
  364.             continue;
  365.         }
  366.         else if (c == EOF_MARK || c == ERROR) {
  367.             buffer [min(count, maxlen-2)] = '\n';
  368.             buffer [min(count, maxlen-1)] = '\0';
  369.  
  370.             TRACE("sysfgets", sl_sout(") returns ERROR\n"));
  371.             return ERROR;
  372.         }
  373.         else if (c == '\n') {
  374.             buffer [min(count, maxlen-2)] = '\n';
  375.             buffer [min(count, maxlen-1)] = '\0';
  376.             TRACE("sysfgets",
  377.                 sl_sout(") returns ");
  378.                 sl_iout(count);
  379.                 sl_cout('\n'));
  380.             return count;
  381.         }
  382.         else if (count < maxlen - 2) {
  383.             buffer [count++] = c;
  384.         }
  385.         else {
  386.             count++;
  387.         }
  388.     }
  389. }
  390.  
  391. /*
  392.     Write n BYTES from the buffer to the END of an unbuffered file.
  393.     Return ERROR (-1) or 1.
  394. */
  395. int
  396. sysflush(int fd, char * buffer, int n)
  397. {
  398.     int result;
  399.  
  400. #ifdef MICRO_SOFT
  401.     result = (write(fd, buffer, n) == -1) ? ERROR : 1;
  402. #endif
  403.  
  404. #ifdef TURBOC
  405.     result = (write(fd, buffer, n) == -1) ? ERROR : 1;
  406. #endif
  407.  
  408.     return result;
  409.  
  410. }
  411.  
  412. /*
  413.     Open a buffered input file for use by sysfgets and sysgetc.
  414.  
  415.     Return FILE or NULL if the file does not exist.
  416. */
  417. FILE *
  418. sysfopen(char *filename)
  419. {
  420.     FILE * f;
  421.  
  422. #ifdef MICRO_SOFT
  423.     f = fopen(filename, "r");
  424. #endif
  425.  
  426. #ifdef TURBOC
  427.     f = fopen(filename, "r");
  428. #endif
  429.  
  430.     return f;
  431. }
  432.  
  433. /*
  434.     Get the next characer from a file opened by sysfopen.
  435.     Mask off the high bit of the character.
  436.     return ERROR on end of file.
  437. */
  438. int
  439. sysgetc(FILE *fd)
  440. {
  441.     int c;
  442.  
  443.     SL_DISABLE();
  444.  
  445.     c = getc(fd);
  446.  
  447.     /* Be careful not to mask off bit on EOF. */
  448.     return ((c == ERROR) ? ERROR : c & 0x7f);
  449.  
  450. }
  451.  
  452. /*
  453.     Initialize the system module.
  454.  
  455.     The storage allocation routines are a real problem.
  456.     The AZTEC and DRI compilers completely botch it.
  457. */
  458. void
  459. sysinit(void)
  460. {
  461.     TICK("sysinit");
  462.  
  463.     /*
  464.         System dependent part.
  465.         This code sets the "moat" (in Unix terminology),
  466.         i.e., the amount of space that is guarenteed for
  467.         use by the stack by the memory allocation routines.
  468.         If you don't reserve enough space for the stack
  469.         the inject, extract, move and copy commands will crash.
  470.     */
  471.  
  472. #ifdef DESMET
  473.     scr_setup();
  474.     freeall(4000);
  475. #endif
  476.  
  477. #ifdef TURBOC
  478.     /* Use raw input. */
  479.     setcbrk(0);
  480. #endif
  481.  
  482.     /*
  483.         PORTABLE part.
  484.     */
  485.     sysnl    = 0;
  486.     sysccnt  = 0;
  487.     sysrcnt  = 0;
  488.     syslastc = 0;
  489. }
  490.  
  491. /*
  492.     Save info for interrupted screen update.
  493.     This routine is PORTABLE.
  494. */
  495. void
  496. sysintr(int systl, int systy, int sysn)
  497. {
  498.     SL_DISABLE();
  499.  
  500.     systopl = systl;
  501.     systopy = systy;
  502.     sysnl   = max(0,sysn);
  503. }
  504.  
  505. /*
  506.     Print character on the printer.
  507. */
  508. int
  509. syslout(char c)
  510. {
  511.     SL_DISABLE();
  512.  
  513. #ifdef DESMET
  514.     _os(5, c);    
  515. #endif
  516.  
  517.     return c;
  518. }
  519.  
  520. /*
  521.     Move a block of memory.
  522.  
  523.     This code MUST work regardless of whether the
  524.     source pointer is above or below the dest pointer.
  525.  
  526.     The for loop below is PORTABLE,  but this is time-
  527.     critical code;  it should work as fast as possible.
  528.     It may be worth your while to rewrite it in assembly
  529.     language.
  530. */
  531. void
  532. sysmove(char source [], char dest [], int count)
  533. {
  534.  
  535. #ifdef TURBOC
  536.     movmem(source, dest, count);
  537. #endif
  538.  
  539. #ifdef MICRO_SOFT
  540.     memmove(dest, source, (int) count);
  541. #endif
  542.  
  543. #ifndef MICRO_SOFT
  544. #ifndef TURBOC
  545.  
  546.     int i;
  547.  
  548.     TRACEP("sysmove",        sl_lpout();
  549.         sl_pout(source); sl_csout();
  550.         sl_pout(dest);     sl_csout(); 
  551.         sl_iout(count);     sl_rpout());
  552.  
  553.     if (count <= 0) {
  554.         return;
  555.     }
  556.     else if (source > dest) {
  557.         /* Copy head first. */
  558.         for (i = 0; i < count; i++) {
  559.             dest [i] = source [i];
  560.         }
  561.     }
  562.     else {
  563.         /* Copy tail first. */
  564.         for (i = count - 1; i >= 0; i--) {
  565.             dest [i] = source [i];
  566.         }
  567.     }
  568. #endif
  569. #endif
  570.  
  571. }
  572.  
  573. /*
  574.     Open an existing file for unbuffered i/o.
  575.     Return OK (0) or ERROR (-1).
  576. */
  577. int
  578. sysopen(char *name)
  579. {
  580.     int result;
  581.  
  582.     SL_DISABLE();
  583.  
  584. #ifdef MICRO_SOFT
  585.     result = open(name, O_RDWR | O_BINARY);
  586. #endif
  587.  
  588. #ifdef TURBOC
  589.     result = open(name, O_RDWR | O_BINARY);
  590. #endif
  591.  
  592.     return result;
  593. }
  594.  
  595. /*
  596.     Put one character to a buffered output file.
  597.     Returns the character itself,  or ERROR if the
  598.     disk becomes full.
  599. */
  600. int
  601. sysputc(char c, FILE *fd)
  602. {
  603.     SL_DISABLE();
  604.  
  605.     return putc(c, fd);
  606. }
  607.  
  608. /*
  609.     Read one block (DATA_SIZE bytes) from an unbuffered
  610.     file into the buffer of size DATA_SIZE.
  611.     Return the number of bytes read or -1 if an
  612.     end-of-file occurs immediately.
  613.     If less than a full block is read,  put an EOF_MARK mark
  614.     after the last byte.
  615. */
  616. int
  617. sysread(int fd, char * buffer)
  618. {
  619.     int n, result;
  620.  
  621.     TRACEP("sysread",        sl_lpout();
  622.         sl_iout(fd);     sl_csout();
  623.         sl_pout(buffer));
  624.  
  625. #ifdef MICRO_SOFT
  626.     n = read(fd, buffer, DATA_SIZE);
  627. #endif
  628.  
  629. #ifdef TURBOC
  630.     n = read(fd, buffer, DATA_SIZE);
  631. #endif
  632.  
  633.     if (n == ERROR) {
  634.         result = 0;
  635.     }
  636.     else if (n == DATA_SIZE) {
  637.         result = n;
  638.     }
  639.     else {
  640.         /* Force an end-of-file mark */
  641.         buffer [n] = EOF_MARK;
  642.         result = n;
  643.     }
  644.  
  645.     TRACE("sysread",
  646.         sl_sout(") returns "); sl_iout(result); sl_cout('\n'));
  647.  
  648.     return result;
  649. }
  650.  
  651. /*
  652.     Rename the old file to be the new file.
  653.     RED makes sure that the file is NOT open when
  654.     sysrename() is called.
  655. */
  656. void
  657. sysrename(char *oldname, char *newname)
  658. {
  659.     TRACEP("sysrename",       sl_lpout();
  660.         sl_sout(oldname); sl_csout(); 
  661.         sl_sout(newname); sl_rpout());
  662.  
  663.     rename(oldname, newname);
  664. }
  665.  
  666. /*
  667.     Seek to the specified block of an unbuffered file.
  668.     Return OK (0) or ERROR (-1).
  669. */
  670. int
  671. sysseek(int fd, int block)
  672. {
  673.     int result;
  674.     long lresult;
  675.     long temp;
  676.  
  677.     TRACEP("sysseek",
  678.         sl_lpout(); sl_iout(fd); sl_csout(); sl_iout(block));
  679.  
  680. #ifdef MICRO_SOFT
  681.     temp = ((long) block) * DATA_SIZE;
  682.     lresult = lseek(fd, temp, SEEK_SET);
  683.     result = (lresult == -1L) ? ERROR : OK;
  684. #endif
  685.  
  686. #ifdef TURBOC
  687.     /*
  688.         The following line is a workaround a bug in the compiler.
  689.         Without the cast, the code does not work if block == 32.
  690.     */
  691.     temp = ((long) block) * DATA_SIZE;
  692.     lresult = lseek(fd, temp, 0);
  693.     result = (lresult == -1L) ? ERROR : OK;
  694. #endif
  695.  
  696.     TRACE("sysseek",
  697.         sl_sout(") returns "); sl_lout(lresult); sl_cout('\n'));
  698.  
  699.     return result;
  700. }
  701.  
  702. /*
  703.     Write n bytes from the buffer to an unbuffered file.
  704.     Return the number of bytes written or ERROR (-1).
  705. */
  706. int
  707. syswrite(int fd, char * buffer, int n)
  708. {
  709.     int result;
  710.  
  711.     TRACEP("syswrite", sl_lpout();
  712.         sl_iout(fd);     sl_csout();
  713.         sl_pout(buffer); sl_csout(); 
  714.         sl_iout(n));
  715.  
  716. #ifdef MICRO_SOFT
  717.     result = write(fd, buffer, n);
  718. #endif
  719.  
  720. #ifdef TURBOC
  721.     result = write(fd, buffer, n);
  722. #endif
  723.  
  724.     TRACE("syswrite",
  725.         sl_sout(") returns "); sl_iout(result); sl_cout('\n'));
  726.  
  727.     return result;
  728. }
  729.  
  730. /*
  731.     Erase the file from the file system.
  732.     Return ERROR (-1) if the file does not exist or
  733.     can not be erased.
  734. */
  735. int
  736. sysunlink(char * filename)
  737. {
  738.     TRACEP("sysunlink", sl_lpout(); sl_sout(filename); sl_rpout());
  739.  
  740.     unlink(filename);
  741. }
  742.  
  743. /*
  744.     Wait for all console output to be finished.
  745.     This routine is PORTABLE.
  746. */
  747. void
  748. syswait(void)
  749. {
  750.     SL_DISABLE();
  751.  
  752.     while (hasint && sysnl > 0) {
  753.         bufout(systopl, systopy, sysnl);
  754.     }
  755. }
  756.