home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd6.lzh / SRC / io.c < prev    next >
Text File  |  1990-05-16  |  13KB  |  429 lines

  1. /*
  2.   C BASED FORTH-83 MULTI-TASKING IO MANAGEMENT
  3.  
  4.   Copyright (c) 1989 by Mikael Patel
  5.  
  6.   Computer Aided Design Laboratory (CADLAB)
  7.   Department of Computer and Information Science
  8.   Linkoping University
  9.   S-581 83 LINKOPING
  10.   SWEDEN
  11.  
  12.   Email: mip@ida.liu.se
  13.   
  14.   Started on: 30 June 1988
  15.  
  16.   Last updated on: 17 December 1989
  17.  
  18.   Dependencies:
  19.        (cc) fcntl.h, errno.h, kernel.h, error.h, memory.h and io.h
  20.  
  21.   Description:
  22.        Handles low level access to Operating System to allow asynchronous
  23.        input and multi-tasking of Forth level processes while waiting for
  24.        buffer filling. File names are saved so that files are not reloaded. 
  25.   
  26.   Copying:
  27.        This program is free software; you can redistribute it and/or modify
  28.        it under the terms of the GNU General Public License as published by
  29.        the Free Software Foundation; either version 1, or (at your option)
  30.        any later version.
  31.  
  32.        This program is distributed in the hope that it will be useful,
  33.        but WITHOUT ANY WARRANTY; without even the implied warranty of
  34.        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  35.        GNU General Public License for more details.
  36.  
  37.        You should have received a copy of the GNU General Public License
  38.        along with this program; see the file COPYING.  If not, write to
  39.        the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  40.  
  41. */
  42.  
  43. #ifndef OSK
  44. #  include <fcntl.h>
  45. #else
  46. #  include <modes.h>
  47. #endif
  48. #include <errno.h>
  49. #include "kernel.h"
  50. #include "memory.h"
  51. #include "error.h"
  52. #include "io.h"
  53.  
  54.  
  55. /* MAXIMUM FILE AND PATH NAME STRING SIZES */
  56.  
  57. #define FILENAMESIZE 128
  58. #define PATHNAMESIZE 128
  59.  
  60.  
  61. /* FILE BUFFERS STACK AND STACK POINTER */
  62.  
  63. #define FSTACKSIZE 32
  64.  
  65. FILE_BUFFER *io_fstack[FSTACKSIZE];
  66. int  io_fsp = -1;
  67.  
  68.  
  69. /* STACK OF LOADED FILE NAMES */
  70.  
  71. #define INFILESSIZE 64
  72.  
  73. static char *infiles[INFILESSIZE];
  74. static int  infsp = -1;
  75.  
  76.  
  77. /* STACK OF FILE SEARCH PATHS AND HOME ADDRESS */
  78.  
  79. #define PATHSSIZE 64
  80.  
  81. static char *paths[PATHSSIZE];
  82. static int  psp = -1;
  83.  
  84. static char *home;
  85.  
  86.  
  87. /* EXTERNAL DEFININED IO DISPATCH ROUTINE AND ENVIRONMENT ACCESS */
  88.  
  89. extern void io_dispatch();
  90. extern char *getenv();
  91.  
  92.  
  93. /* IO MANAGEMENT DEFINITONS */
  94.  
  95. int io_path(pname, pos)
  96.     char *pname;               /* Pointer to path name */
  97.     int  pos;                  /* Position to append */
  98. {
  99.     char pathname[PATHNAMESIZE];    
  100.     long plen = strlen(pname);
  101.     long i;
  102.  
  103.     /* Check for null path. Dont add these */
  104.     if (plen == 0) return IO_NO_ERROR;
  105.  
  106.     /* Check if the path name is an environment variable */
  107.     if (pname[0] == '$') {
  108.  
  109.        /* Fetch the environment variables value */
  110.        char *paths = (char *) getenv((char *) pname + 1);
  111.  
  112.        /* If paths are available recursivly add them to the path list */
  113.        if (paths) {
  114.            while (*paths) {
  115.                char *p = pathname;
  116.  
  117.                /* Parse list of paths; directories seperated by colon */
  118.                while (*paths && *paths != ':') *p++ = *paths++;
  119.                *p++ = '\0'; 
  120.  
  121.                /* Append recursively */
  122.                (void) io_path(pathname, pos);
  123.  
  124.                /* Access next path if available */
  125.                if (*paths) paths++;
  126.            }
  127.            return IO_NO_ERROR;
  128.        }
  129.        else
  130.            return IO_UNKNOWN_PATH;
  131.     }
  132.  
  133.     /* Check if the path contains a home directory character first */
  134.     if (pname[0] == '~' && pname[1] == '/') {
  135.        (void) strcpy(pathname, home);
  136.        (void) strcpy((char *) pathname + strlen(home), (char *) pname + 2);
  137.        pname = pathname;
  138.        plen = strlen(pathname);
  139.     }
  140.     
  141.     /* Check that the last character is a slash if not add it */
  142.     if (pname[plen - 1] != '/') {
  143.        pname[plen++] = '/';
  144.        pname[plen] = '\0';
  145.     }
  146.  
  147.     /* Check if the path has already been defined */
  148.     for (i = 0; i <= psp; i++)
  149.        if (STREQ(paths[i], pname)) return IO_PATH_DEFINED;
  150.     
  151.     /* Check if space is available on path stack */
  152.     if (psp + 1 == PATHSSIZE) return IO_TOO_MANY_PATHS;
  153.  
  154.     /* Make space for the new path */
  155.     psp = psp + 1;
  156.     
  157.     /* Check where the path should be appended */
  158.     if (pos == IO_PATH_FIRST) {
  159.        for (i = psp; i > 1; i--) paths[i] = paths[i - 1];
  160.        pos = 0;
  161.     }
  162.     else pos = psp;
  163.  
  164.     /* Add path string att position given */
  165.     paths[pos] = strcpy((char *) malloc((unsigned) plen), pname);
  166.  
  167.     return IO_NO_ERROR;
  168. }
  169.  
  170. void io_flush()
  171. {
  172.     /* Flush any waiting output */
  173.     (void) fflush(stdout);    
  174.  
  175.     /* Close all open files if not end of input stream */
  176.     if (io_not_eof()) {
  177.  
  178.        /* Close all files but lowest */
  179.        while (io_fsp > 0) (void) close(io_fstack[io_fsp--] -> fd);
  180.  
  181.        /* Close lowest file on file stack if not tty */
  182.        if (!isatty(io_fstack[io_fsp] -> fd))
  183.            (void) close(io_fstack[io_fsp--] -> fd);
  184.     }
  185. }
  186.  
  187. int io_infile(fname)
  188.     char *fname;               /* Pointer to file name to open as input */
  189. {
  190.     char filename[FILENAMESIZE];
  191.     long i, j;
  192.     long fd;
  193.     
  194.     /* Check for standard input as source */
  195.     if (fname == STDIN) {
  196.  
  197.        /* Check if space is available on file stack */
  198.        if (io_fsp + 1 == FSTACKSIZE) return IO_TOO_MANY_FILES;
  199.  
  200.        /* Push standard input as source onto the file buffer stack */
  201.        io_fsp = io_fsp + 1;
  202.        io_fstack[io_fsp] -> fd = STDIN;
  203.        io_fstack[io_fsp] -> bufp = 0;
  204.        io_fstack[io_fsp] -> cc = 0;
  205.        return IO_NO_ERROR;
  206.     }
  207.  
  208.     /* Check if the file name contains a home directory character first */
  209.     if (fname[0] == '~' && fname[1] == '/') fname += 2;
  210.  
  211.     /* Expand the file name using the path stack and try opening the file */
  212.     for (i = 0; i <= psp; i++) {
  213.  
  214.        /* Build the new file name using a path */
  215.        (void) strcpy(filename, paths[i]);
  216.        (void) strcpy(filename + strlen(paths[i]), fname);
  217.  
  218.        /* Check if this file has already been loaded */
  219.        for (j = 0; j <= infsp; j++)
  220.            if (STREQ(infiles[j], filename)) return IO_FILE_INCLUDED;
  221.  
  222.        /* Try opening the file */
  223.        fd = open(filename, S_IREAD);
  224.  
  225.        /* If no errors then save the file name and return file descriptor */
  226.        if (fd != -1) {
  227.  
  228.            /* Check if space is available on file stack */
  229.            if (io_fsp + 1 == FSTACKSIZE) return IO_TOO_MANY_FILES;
  230.  
  231.            /* Push file onto the file buffer stack and use it as source */
  232.            infsp = infsp + 1;
  233.            infiles[infsp] = strcpy((char *) malloc((unsigned) strlen(filename) + 1), filename);
  234.            io_fstack[++io_fsp] -> fd = fd;
  235.            io_fstack[io_fsp] -> bufp = 0;
  236.            io_fstack[io_fsp] -> cc = 0;
  237.            return fd;
  238.        }
  239.     }
  240.  
  241.     /* The file was not available so return error */
  242.     return IO_UNKNOWN_FILE;
  243. }
  244.  
  245.  
  246. int io_fillbuf()
  247. {
  248.     long nonblocking;
  249.  
  250.     /* Check io consistency and foreground task input only */
  251.     if (io_eof() || tp != foreground) error_fatal(0);
  252.     
  253.     /* Flush any waiting output if filling buffer from a terminal */
  254.     if (isatty(io_fstack[io_fsp] -> fd)) (void) fflush(stdout);
  255.  
  256.     /* Check for multi-tasking input operation */
  257.     if (tp != ((TASK *) tp -> queue.succ)) {
  258. #ifndef OSK
  259.        (void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, FNDELAY);
  260. #else
  261.        if (!isatty(io_fstack[io_fsp] -> fd))
  262.          (void) _ss_tiks(io_fstack[io_fsp] -> fd,1);
  263. #endif
  264.        tp -> status = IOWAITING;
  265.        nonblocking = TRUE;
  266.     }
  267.     else
  268.        nonblocking = FALSE;
  269.        
  270.     /* Allow multi-tasking during waiting for input */
  271.     for (;;) {
  272.  
  273.        /* Try reading a block from the current input stream */
  274. #ifndef OSK
  275.        if ((io_fstack[io_fsp] -> cc = read(io_fstack[io_fsp] -> fd,
  276.                                            io_fstack[io_fsp] -> buf,
  277.                                            BUFSIZE)) > 0) {
  278. #else
  279.        io_fstack[io_fsp]->cc = (nonblocking ?
  280.          (_gs_rdy(io_fstack[io_fsp]->fd) < 0 ? -1 :
  281.             (isatty(io_fstack[io_fsp]->fd) ? readln(io_fstack[io_fsp] -> fd,
  282.                                                     io_fstack[io_fsp] -> buf,
  283.                                                     BUFSIZE) :
  284.                                              read(io_fstack[io_fsp] -> fd,
  285.                                                   io_fstack[io_fsp] -> buf,
  286.                                                   BUFSIZE) ) ) :
  287.          (isatty(io_fstack[io_fsp]->fd) ? readln(io_fstack[io_fsp] -> fd,
  288.                                                  io_fstack[io_fsp] -> buf,
  289.                                                  BUFSIZE) :
  290.                                           read(io_fstack[io_fsp] -> fd,
  291.                                                io_fstack[io_fsp] -> buf,
  292.                                                BUFSIZE) ) );
  293.        if (io_fstack[io_fsp] -> cc > 0) {
  294. #endif
  295.            /* Restore to non-blocking input from file and foreground */
  296.            if (nonblocking) {
  297. #ifndef OSK
  298.                (void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, 0);
  299. #endif
  300.                spush(foreground);
  301.                doresume();
  302.                tp -> status = RUNNING;
  303.            }
  304.  
  305.            /* Initiate the buffer pointer and return the first character */
  306.            io_fstack[io_fsp] -> bufp = 0;
  307.            return io_getchar();
  308.        }
  309.  
  310.        /* Did the read operation result in an end of file */
  311. #ifndef OSK
  312.        if (io_fstack[io_fsp] -> cc == 0 && errno != EWOULDBLOCK) {
  313. #else
  314.        if (io_fstack[io_fsp] -> cc == 0 && errno != E_LOCK) {
  315. #endif
  316.  
  317.            /* Set back the file mode to synchronous and close the file */
  318.            if (nonblocking) {
  319. #ifndef OSK
  320.                (void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, 0);
  321. #else
  322.                (void) _ss_tiks(io_fstack[io_fsp] -> fd,0);
  323. #endif
  324.                spush(foreground);
  325.                doresume();
  326.                tp -> status = RUNNING;
  327.            }
  328.            (void) close(io_fstack[io_fsp--] -> fd); 
  329.            
  330.            /* Check if end of input source */
  331.            if (io_eof()) return IO_EOF;
  332.  
  333.            /* Get character from previous file buffer */
  334.            return io_getchar();
  335.        }
  336.  
  337.        /* Run forth level tasks while waiting for input */
  338.        if (tp == foreground) dodetach(); else doinner();
  339.        
  340.        /* Check if the task for empty, i.e., only the foreground */
  341.        if (tp == foreground && tp == ((TASK *) tp -> queue.succ)) {
  342. #ifndef OSK
  343.            (void) fcntl(io_fstack[io_fsp] -> fd, F_SETFL, 0); 
  344. #else
  345.            (void) _ss_tiks(io_fstack[io_fsp] -> fd,0);
  346. #endif
  347.            nonblocking = FALSE;
  348.        }
  349.        
  350.        /* Allow user extension of the io wait loop */
  351.        io_dispatch();
  352.     }
  353. }
  354.  
  355. void io_skip(skpchr)
  356.     char skpchr;               /* Skip character */
  357. {
  358.     /* Skip all characters until skip termination character or end of file */
  359.     while (io_not_eof() && io_getchar() != skpchr);
  360. }
  361.  
  362. void io_scan(buf, brkchr)
  363.     char *buf;                 /* Pointer to scan buffer */
  364.     char brkchr;               /* Break character */
  365. {
  366.     /* Initiate buffer as null string */
  367.     *buf = '\0';
  368.  
  369.     /* Check for scanning until white space or special break character */
  370.     if (brkchr == ' ') {
  371.  
  372.        /* While not white space or end of file */
  373.        while (io_not_eof() && !ISSPACE(*buf = io_getchar())) buf++;
  374.     }
  375.     else {
  376.  
  377.        /* While not the break character or end of file */
  378.        while (io_not_eof() && (*buf = io_getchar()) != brkchr) buf++;
  379.     }
  380.     
  381.     /* End the string and return */
  382.     *buf = '\0';
  383.     return;
  384. }
  385.  
  386. void io_skipspace()
  387. {
  388.     /* Skip all white spaces */
  389.     while (io_not_eof() && ISSPACE(io_getchar()));
  390.  
  391.     /* Step back the buffer pointer */
  392.     if (io_not_eof()) io_fstack[io_fsp] -> bufp -= 1;
  393. }
  394.  
  395. void io_initiate(banner)
  396.     char *banner;              /* Initiate application message */
  397. {
  398.     long i;
  399.  
  400.     /* Print banner and add initial paths */
  401.     (void) printf(banner);
  402.     (void) io_path(".", IO_PATH_LAST);
  403.     (void) io_path("$PWD", IO_PATH_LAST);
  404.     (void) io_path(home = (char *) getenv("HOME"), IO_PATH_LAST);
  405.     (void) io_path("$TILEPATH", IO_PATH_LAST);
  406. #ifdef OSK
  407.     (void) io_path("/dd/lib/tile", IO_PATH_LAST);
  408. #endif
  409.  
  410.     /* Allocate file buffers */
  411.     for (i = 0; i < FSTACKSIZE; i++) {
  412.        io_fstack[i] = (FILE_BUFFER *) malloc((unsigned) sizeof(FILE_BUFFER));
  413.        if (io_fstack[i] == NIL) {
  414.            (void) printf("io: can not allocate file buffers\n");
  415.            exit(0);
  416.        }
  417.     }
  418. }    
  419.     
  420. void io_finish()
  421. {
  422.     /* Flush any waiting output */
  423.     (void) fflush(stdout);    
  424.  
  425.     /* Close all open files */
  426.     while (io_not_eof()) (void) close(io_fstack[io_fsp--] -> fd);
  427. }
  428.  
  429.