/* RPCUtilsImpl.c*/
/* Last modified by D. Swinehart, November 11, 1982 10:26 am
   L. Stewart, December 27, 1982  3:16 PM, flush nested declarations
   L. Stewart, January 1, 1983  4:18 PM, flush AllocZero
   L. Stewart, March 6, 1983  4:16 PM, flush Alloc
 */

#include <Env.h>
#include <Ec.h>
#include <rpc.h>
#include <signal.h>
#include <Context.h>
#include <Queue.h>
#include <Lark.h>
#include <Pup.h>

/* Imports */

    /* From RPCPktIO*/
extern int NewPSB();

    /* From Numerical package */
extern int Min();
extern int lc();

    /* From Context and Queue Packages*/
extern struct RPCCtx *CurrentContext();
extern int *Enqueue();
extern struct RPCCtx *InitNContext();

    /* From OS*/
extern int *GetFixed();
extern int CallSwat();
extern int MoveBlock();
extern int Zero();
extern int DoubleDiff();

struct HostNet {
  char net;
  char host;
  };

union Machine {
  int w;
  struct HostNet b;
  };
	
struct Calendar {
  int time[2];
  int zoneInfo;
  int dstStartDay;
  int dstEndDay;
  int base[2];	/* last ms timer, for updating time */
  };
static struct Calendar calendar;

int /*bool allFit*/
AppendString(tO, fRom)
  struct ShortSTRING *tO, *fRom;
  { /* RETURNS[allFit: BOOLEAN]*/
  int i, toLen, totLen, fromLen;
  toLen = tO->length;
  totLen = Min(tO->maxLength, toLen+fRom->length);
  fromLen = totLen-toLen;
  for (i=0; i<fromLen; ++i) tO->text[i+toLen] = fRom->text[i];
  tO->length = totLen;
  return(fromLen == fRom->length);
  };

int /*bool*/
EquivalentStrings(a,b)
  struct ShortSTRING *a, *b;
  {
  int i;
  if (a->length != b->length) return(false);
  for (i=0; i<a->length; ++i)
    if (lc(a->text[i]) != lc(b->text[i])) return(false);
  return(true);
  };

struct ShortSTRING
*CStringToString(b)
  char b[];
  {
  int len, i;
  struct ShortSTRING *s;
  len = strlen(b);
  s = (struct ShortSTRING *) GetFixed(StringSizeN(len));
  s->length = s->maxLength = len;
  for (i = 0; i<len; ++i) s->text[i] = b[i];
  return(s);
  };

static int strlen(b)
  char b[];
  {
  int i;
  for (i = 0; i<100; ++i) if (b[i] == 0) return (i);
  return (100);
  };
  
int
InstanceToMachine(instance)
  struct ShortSTRING *instance;
  { /* parses fixed-form net address*/
  /* Input MUST be in the form net#host#*/
  int i, net;
  i=0;
  net=Num(instance, &i);
  return((Num(instance, &i)<<8) + net);
  };
  
static int
Num(s, lvChar)
  struct ShortSTRING *s;
  int *lvChar;
  {
  int res, i;
  char c;
  res=0;
  for (i=*lvChar; i<s->length; ++i) {
    c = s->text[i];
    if (c == '#') {
      *lvChar=i+1;
      return(res);
      };
    if ('0' > c || c > '7') break;
    res = (res<<3) + c - '0';
    if (res > 0377) break;
    };
  SIGNAL(ERROR, 0);
  };

int StringSize(s)
  struct ShortSTRING *s;
  {
  return(lenShortSTRING+(s->length+1)/2);
  };

int StringSizeN(n)
  int n;
  {
  return(lenShortSTRING+(n+1)/2);
  };

int *GetSigVec()
  {
  struct RPCCtx *CtxRunning;
  CtxRunning = CurrentContext();
  return(CtxRunning->user.sigVec);
  };

StartNProcess(name, ctxQ, proc, len, sigVecLen)
  char *name;
  struct Queue *ctxQ;
  int *proc, len, sigVecLen;
  {
  int cBase;
  struct RPCCtx *context;
  cBase = (int) GetFixed(len);
  len = len - (sigVecLen + lenRPCCtx + 3); /* 3 for slop */
  context = InitNContext(name, cBase, len, proc);
  context->user.myPSB = NewPSB(context);
  SigInit(context->user.sigVec, sigVecLen, &GetSigVec);
  Enqueue(ctxQ, context);
  };

/* Move string to dest, or to newly allocated block (dest=0).
    If how is marshall, convert to, else from, big-endian lengths.
    In result, maxLength == length.
    return dest */
struct ShortSTRING
/*[Un]Mar*/ *ShallString(dest, src, how)
  struct ShortSTRING *dest, *src;
  int  how;
  {
/* how is:
     0 -> copy string, little-endian format
     1 -> marshall string to big-endian format
     2 -> unmarshall string from big-endian format
     3 -> copy string, big-endian format */
  int ln;
  if (src==0) return 0;
  ln = src->length;
  if ((how&2)!=0) ln = swab(ln); /* source is big-endian */
  ln = (ln+5)/2; /* now word count */
  if (dest == 0) dest = (struct ShortSTRING *) GetFixed(ln);
  MoveBlock(dest, src, ln);
  switch (how) {
    case 1: case 2:
      dest->length = swab(dest->length);
    default: {};
    };
  dest->maxLength = dest->length;
  Block();
  return (dest);
  };

#define maxV 077777
#define minV 0100001

/* Return px-py, clipped to about 16 bits */

int DoubleComp(px, py)
  int px[], py[];
  {
  int pt0, pt[2];
  Move2(pt, px);
  pt0 = DoubleDiff(pt, py);
  if (pt[1]==0) {
    if (pt0>=0) return (pt0);
    return (maxV);
    };
  if (pt[1]==-1) {
    if (pt0<0) return (pt0);
    return (minV);
    };
  if (pt[1]>0) return (maxV);
  /* if (pt[1]<-1) */ return (minV);
  };