/*
 * File: rsys.c
 *  Contents: [flushrec], [getrec], getstrg, host, longread, [putrec], putstr
 */

#include "..\h\config.h"
#include "..\h\rt.h"
#include "rproto.h"

#if AMIGA
#if LATTICE
#include <ios1.h>
#endif					/* LATTICE */
#endif					/* AMIGA */

#ifdef RecordIO
#if SASC
#include <lcio.h>
#endif					/* SASC */
#endif					/* RecordIO */

#ifdef RecordIO
/*
 * flushrec - force buffered output to be written with a record break.
 *  Applies only to files with mode "s".
 */

novalue flushrec(fd)
FILE *fd;
{
#if SASC
   afwrite("", 1, 0, fd);
#endif					/* SASC */
}

/*
 * getrec - read a record into buf from file fd. At most maxi characters
 *  are read.  getrec returns the length of the record.
 *  Returns -1 if EOF and -2 if length was limited by
 *  maxi. [[ Needs ferror() check. ]]
 *  This function is meaningful only for files opened with mode "s".
 */

int getrec(buf, maxi, fd)
register char *buf;
int maxi;
FILE *fd;
   {
#ifdef SASC
   register int l;

   l = afreadh(buf, 1, maxi+1, fd);     /* read record or maxi+1 chars */
   if (l == 0) return -1;
   if (l <= maxi) return l;
   ungetc(buf[maxi], fd);               /* if record not used up, push
                                           back last char read */
   return -2;
#endif					/* SASC */
   }
#endif					/* RecordIO */

/*
 * getstrg - read a line into buf from file fd.  At most maxi characters
 *  are read.  getstrg returns the length of the line, not counting
 *  the newline.  Returns -1 if EOF and -2 if length was limited by
 *  maxi. [[ Needs ferror() check. ]]
 */

int getstrg(buf, maxi, fd)
register char *buf;
int maxi;
FILE *fd;
   {
   register int c, l;


#if AMIGA
#if LATTICE
   /* This code is special for Lattice 4.0.  It was different for
    *  Lattice 3.10 and probably won't work for other C compilers.
    */
   extern struct UFB _ufbs[];

   if (IsInteractive(_ufbs[fileno(fd)].ufbfh))
      return read(fileno(fd),buf,maxi);
#endif					/* LATTICE */
#endif					/* AMIGA */


   l = 0;
   while ((c = fgetc(fd)) != '\n') {
      if (c == EOF)
	 if (l > 0) return l;
	 else return -1;
      if (++l > maxi) {
	 ungetc(c, fd);
	 return -2;
	 }
      *buf++ = c;
      }
   return l;
   }

#ifdef UtsName
#include <sys\utsname.h>
#endif					/* UtsName */

/*
 * iconhost - return some sort of host name into the buffer pointed at
 *  by hostname.  This code accommodates several different host name
 *  fetching schemes.
 */
novalue iconhost(hostname)
char *hostname;
   {

#ifdef WhoHost
   /*
    * The host name is in /usr/include/whoami.h. (V7, 4.[01]bsd)
    */
   whohost(hostname);
#endif					/* WhoHost */

#ifdef UtsName
   {
   /*
    * Use the uname system call.  (System III & V)
    */
   struct utsname utsn;
   uname(&utsn);
   strcpy(hostname,utsn.nodename);
   }
#endif					/* UtsName */

#ifdef GetHost
   /*
    * Use the gethostname system call.  (4.2bsd)
    */
   gethostname(hostname,MaxCvtLen);
#endif					/* GetHost */

#if VMS
   /*
    * VMS has its own special logic.
    */
   char *h;
   if (!(h = getenv("ICON$HOST")) && !(h = getenv("SYS$NODE")))
      h = "VAX/VMS";
   strcpy(hostname,h);
#endif					/* VMS */

#ifdef HostStr
   /*
    * The string constant HostStr contains the host name.
    */
   strcpy(hostname,HostStr);
#endif					/* HostStr */

   }

#ifdef WhoHost
#define HdrFile "/usr/include/whoami.h"

/*
 * whohost - look for a line of the form
 *  #define sysname "name"
 * in HdrFile and return the name.
 */
novalue whohost(hostname)
char *hostname;
   {
   char buf[BUFSIZ];
   FILE *fd;

   fd = fopen(HdrFile, ReadText);
   if (fd == NULL) {
      sprintf(buf, "Cannot open %s, no value for &host\n", HdrFile);
      syserr(buf);
   }

   for (;;) {   /* each line in the file */
      if (fgets(buf, sizeof buf, fd) == NULL) {
         sprintf(buf, "No #define for sysname in %s, no value for &host\n",
            HdrFile);
         syserr(buf);
      }
      if (sscanf(buf,"#define sysname \"%[^\"]\"", hostname) == 1) {
         fclose(fd);
         return;
      }
   }
   }
#endif					/* WhoHost */

/*
 * Read a long string in shorter parts. (Standard read may not handle long
 *  strings.)
 */
word longread(s,width,len,fname)
FILE *fname;
int width;
char *s;
long len;
{
   long tally = 0;
   long n = 0;
 
   while (len > 0) {
      n = fread(s, width, (int)((len < MaxIn) ? len : MaxIn), fname);
      if (n <= 0)
         return tally;
      tally += n;
      s += n;
      len -= n;
      }  
   return tally;
   }

#ifdef RecordIO
/*
 * Write string referenced by descriptor d, avoiding a record break.
 *  Applies only to files openend with mode "s".
 */

int putrec(f, d)
register FILE *f;
dptr d;
   {
#if SASC
   register char *s;
   register word l;

   l = StrLen(*d);
   if (l == 0)
      return Success;
   s = StrLoc(*d);

   if (afwriteh(s,1,l,f) < l)
      return Failure;
   else
      return Success;
   /*
    * Note:  Because RecordIO depends on SASC, and because SASC
    *  uses its own malloc rather than the Icon malloc, file usage
    *  cannot cause a garbage collection.  This may require
    *  reevaluation if RecordIO is supported for any other compiler.
    */
#endif					/* SASC */
   }
#endif					/* RecordIO */

/*
 * Print string referenced by descriptor d. Note, d must not move during
 *   a garbage collection.
 */

int putstr(f, d)
register FILE *f;
dptr d;
   {
   register char *s;
   register word l;

   l = StrLen(*d);
   if (l == 0)
      return  Success;
   s = StrLoc(*d);

#ifdef FixedRegions
   if (longwrite(s,l,f) < 0)
      return Failure;
   else
      return Success;
#else					/* FixedRegions */
   /*
    * In expandable regions storage management, the first output to a file may
    *  cause allocation, which in turn may cause a garbage collection, changing
    *  where the string is.  So write one character and reload the address
    *  of the string from the tended descriptor.
    */

   putc(*s, f);
   s = StrLoc(*d) + 1;
   if (longwrite(s,--l,f) < 0)
      return Failure;
   else
      return Success;
#endif					/* FixedRegions */
   }
