/*
 * lineread.c
 *
 * Author: Tomi Ollila <too@cs.hut.fi>
 *
 * This module is FREEWARE. Standard "NO WARRANTY" disclaimer applies.
 *
 * Created: Thu Jul 12 16:40:03 EET 1990 too
 * Last modified: Tue Jul 13 18:05:49 1993 too
 *
 * $Id: lineread.c,v 1.2 1994/01/12 18:23:14 jasegler Exp jasegler $
 *
 * HISTORY
 * $Log: lineread.c,v $
 * Revision 1.2  1994/01/12  18:23:14  jasegler
 * *** empty log message ***
 *
 * Revision 1.1  1994/01/11  19:02:22  jasegler
 * Initial revision
 *
 * Revision 1.1  1994/01/11  19:02:22  jasegler
 * Initial revision
 *
 * Revision 1.3  1993/07/13  15:15:53  too
 * Made lineread.c compile without <sys/cdefs.h> file
 *
 * Revision 1.1  1993/06/16  16:43:52  too
 * Initial revision
 *
 *
 */

#include "lineread.h"

#ifdef AMIGA
extern struct Library *SocketBase;
#define READ(a, b, c) recv(a, b, c, 0)
#if __SASC
#include <proto/socket.h>
#elif __GNUC__
#include <clib/socket_protos.h>
#endif
#else /* not AMIGA */
#define READ(a, b, c) read(a, b, c)
#endif /* AMIGA */

#ifndef NULL
#define NULL 0
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif

#ifndef __CONCAT
#if defined (__STDC__) || defined (__cplusplus)
#define __CONCAT(x,y) x ## y
#else
#define __CONCAT(x,y) x/**/y
#endif
#endif /* __CONCAT not defined */

#define RLP(field) __CONCAT(rl->rl_Private.rlp_,field)


#if defined (__STDC__) || defined (__cplusplus)

int
lineRead (struct LineRead *rl)

#else

int
lineRead (rl)
     struct LineRead *rl;

#endif
{
  int i;

  if (RLP (Bufpointer) == RLP (Howlong))

    if (RLP (Selected))
      {

	if (RLP (Line_completed))
	  RLP (Startp) = RLP (Bufpointer) = 0;

	if ((i = READ (rl->rl_Fd,
		       RLP (Buffer) + RLP (Bufpointer),
		       RLP (Buffersize) - RLP (Bufpointer))) <= 0)
	  {
	    /*
	       * here if end-of-file or on error. set Howlong == Bufpointer
	       * so if non-blocking I/O is in use next call will go to READ()
	     */
	    RLP (Howlong) = RLP (Bufpointer);
	    rl->rl_Line = NULL;
	    return i;
	  }
	else
	  RLP (Howlong) = RLP (Bufpointer) + i;
      }
    else
      /* Inform user that next call may block (unless select()ed) */
      {
	RLP (Selected) = TRUE;
	return 0;
      }
  else
    /* Bufpointer has not reached Howlong yet. */
    {
      RLP (Buffer)[RLP (Bufpointer)] = RLP (Saved);
      RLP (Startp) = RLP (Bufpointer);
    }

  /*
   * Scan read string for next newline.
   */
  while (RLP (Bufpointer) < RLP (Howlong))
    if (RLP (Buffer)[RLP (Bufpointer)++] == '\n')
      goto Skip;

  /*
   * Here if Bufpointer == Howlong.
   */
  if (rl->rl_Lftype != RL_LFNOTREQ)
    {
      RLP (Selected) = TRUE;

      if (RLP (Bufpointer) == RLP (Buffersize))
	{
	  /*
	     * Here if Bufpointer reaches end-of-buffer.
	   */
	  if (RLP (Startp) == 0)
	    {			/* (buffer too short for whole string) */
	      RLP (Line_completed) = TRUE;
	      rl->rl_Line = RLP (Buffer);
	      RLP (Buffer)[RLP (Bufpointer)] = '\0';
	      return -1;
	    }
	  /*
	     * Copy partial string to start-of-buffer and make control ready for
	     * filling rest of buffer when next call to lineRead() is made
	     * (perhaps after select()).
	   */
	  for (i = 0; i < RLP (Buffersize) - RLP (Startp); i++)
	    RLP (Buffer)[i] = RLP (Buffer)[RLP (Startp) + i];
	  RLP (Howlong) -= RLP (Startp);
	  RLP (Bufpointer) = RLP (Howlong);
	  RLP (Startp) = 0;
	}

      RLP (Line_completed) = FALSE;
      return 0;
    }

Skip:
  RLP (Line_completed) = TRUE;
  if (rl->rl_Lftype == RL_LFREQNUL)
    RLP (Buffer)[RLP (Bufpointer) - 1] = '\0';
  RLP (Saved) = RLP (Buffer)[RLP (Bufpointer)];
  RLP (Buffer)[RLP (Bufpointer)] = '\0';
  RLP (Selected) = FALSE;
  rl->rl_Line = RLP (Buffer) + RLP (Startp);

  return (RLP (Bufpointer) - RLP (Startp));
}

#undef READ

#if defined (__STDC__) || defined (__cplusplus)

void
initLineRead (struct LineRead *rl, int fd, int lftype, int buffersize)

#else

int
initLineRead (rl, fd, lftype, buffersize)
     struct LineRead *rl;
     int fd;
     int lftype;
     int buffersize;

#endif
{
  rl->rl_Fd = fd;
  rl->rl_Lftype = lftype;

  RLP (Bufpointer) = RLP (Howlong) = 0;
  RLP (Selected) = RLP (Line_completed) = TRUE;

  RLP (Buffersize) = buffersize;
}
