;Alto->8086 small-c compiler rev 2.0
C←CODE SEGMENT

$INCLUDE(8086LIB.D)

$INCLUDE(pupmisc.DEC)

ASSUME CS:C←CODE, DS:C←DATA

; #include <Ec.h>

; struct Calendar {

;   int time[2];

;   int zoneInfo;

;   int dstStartDay;

;   int dstEndDay;

;   int base[2];  /* last ms timer, for updating time */

;   };

; struct RoutingEntry {

;   byte net;      /* Target net */

;   byte gateNet;  /* A net along the route */

;   byte gateHost; /* A gateway on gateNet */

;   byte hops;     /* hops from responding gateway to target net */

;   };

; extern Move2();

; extern Timer();

; extern DoubleDifference();

; extern DoubleIncrement();

; extern DoubleUDiv();

; extern GetRem();

; extern Marshall();

; extern CallSwat();

; extern SetTmr();

; extern TmrExp();

; extern Swab();

; extern InitQueue();

; extern Block();

; extern GetPBI();

; extern ReleasePBI();

; extern OpenLevel1Socket();

; extern WaitUntilSent();

; extern CloseLevel1Socket();

; extern AppendStringToPup();

; extern SendPup();

; static int simpleSent;

; static int simpleRcvd;

; static int calSent;

; static int calRcvd;

; static int routSent;

; static int routRcvd;

; struct Calendar calendar;

; ReadCalendar(c)
←ReadCalendar:

;   int c[];
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   int t[], newbase[2], ms[2];

;   if (calendar.base[0] == 0) Timer(calendar.base);
ADD SP,0FFF6X
MOV BX,WORD PTR ←calendar+0AX
OR BX,BX
JNZ X1
LEA BX,←calendar+0AX
CALL ←Timer
X1:

;   t = calendar.time;
LEA BX,←calendar

;	←t ← BX
MOV [BP-4],BX

;   Timer(newbase);
;&←newbase
LEA BX,[BP-8]
CALL ←Timer

;   Move2(ms, newbase);
;&←newbase
LEA BX,[BP-8]
;&←ms
LEA CX,[BP-12]
CALL ←Move2

;   DoubleDifference(ms, calendar.base);
LEA BX,←calendar+0AX
;&←ms
LEA CX,[BP-12]
CALL ←DoubleDifference

;   DoubleIncrement(t, DoubleUDiv(ms, 1000));
MOV BX,03E8X
;&←ms
LEA CX,[BP-12]
CALL ←DoubleUDiv

;	CX ← ←t
MOV CX,[BP-4]
CALL ←DoubleIncrement

;   ms[1] = 0;
MOV WORD PTR [BP-10],0

;   ms[0] = GetRem();
CALL ←GetRem

;	←ms ← BX
POP DX
PUSH BX

;   DoubleDifference(newbase, ms);
;&←ms
LEA BX,[BP-12]
;&←newbase
LEA CX,[BP-8]
CALL ←DoubleDifference

;   Move2(calendar.base, newbase);
;&←newbase
LEA BX,[BP-8]
LEA CX,←calendar+0AX
CALL ←Move2

;   Move2(c, t);

;	BX ← ←t
MOV BX,[BP-4]

;	CX ← ←c
MOV CX,[BP-2]
CALL ←Move2

;   };
MOV SP,BP
POP BP
RET;

; InitCalendar()
←InitCalendar:
PUSH BP
MOV BP,SP

;   {

;   struct PBI *pbi;

;   struct Pup *p;

;   int temp;
ADD SP,0FFFAX

;   Timer(calendar.base);
LEA BX,←calendar+0AX
CALL ←Timer

;   Timer(calendar.time);  /* Default value, if no answer */
LEA BX,←calendar
CALL ←Timer

;   pbi = SimpleExch(0206, 0207, 4, 3);
MOV BX,086X
PUSH BX
MOV BX,087X
PUSH BX
MOV BX,3
MOV CX,4
CALL ←SimpleExch
ADD SP,4

;	←pbi ← BX
MOV [BP-2],BX

;   calSent += simpleSent;
MOV BX,←simpleSent
ADD ←calSent,BX

;   if (pbi == 0) return; /* didn't get an answer, fake it */

;	BX ← ←pbi
MOV BX,[BP-2]
OR BX,BX
JNZ X2
MOV SP,BP
POP BP
RET;
X2:

;   calRcvd += 1;
INC ←calRcvd

;   p = pbi->pup;

;	BX ← ←pbi
MOV BX,[BP-2]
MOV CX,[BX+6]

;	←p ← CX
MOV [BP-4],CX

;   Marshall(true, calendar.time, p->data.words, 5);
MOV BX,0FFFFX
PUSH BX
LEA BX,←calendar
PUSH BX

;	BX ← ←p
MOV BX,[BP-4]
ADD BX,014X
PUSH BX
MOV BX,5
POP CX
CALL ←Marshall
ADD SP,4

;   ReleasePBI(pbi);

;	BX ← ←pbi
MOV BX,[BP-2]
CALL ←ReleasePBI

;   temp = calendar.time[0];
MOV BX,WORD PTR ←calendar

;	←temp ← BX
POP DX
PUSH BX

;   calendar.time[0] = calendar.time[1];
MOV BX,WORD PTR ←calendar+2
MOV WORD PTR ←calendar,BX

;   calendar.time[1] = temp;

;	BX ← ←temp
POP BX
PUSH BX
MOV WORD PTR ←calendar+2,BX

;   };
MOV SP,BP
POP BP
RET;

; extern struct SocketEntry pupSockets[1 /*maxPupSockets*/];

; extern struct Route routingTable[maxNetworks];

; extern int localNet;

; extern int localHost;

; int routingSoc;

; static RoutePr(pbi)
←RoutePr:

;   struct PBI *pbi;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   struct Pup *p;

;   int numEntries, i;

;   struct RoutingEntry entries[];

;   int net, hops;

;   struct Route *route;
ADD SP,0FFF2X

;   p = pbi->pup;

;	BX ← ←pbi
MOV BX,[BP-2]
MOV CX,[BX+6]

;	←p ← CX
MOV [BP-4],CX

;   if (p->type == 0201) {

;	BX ← ←p
MOV BX,[BP-4]
MOV AL,[BX+3]
CMP AL,081X
JNZ X3

;     routRcvd += 1;
INC ←routRcvd

;     numEntries = (Swab(p->length) - pupOvBytes) >> 2;

;	DI ← ←p
MOV DI,[BP-4]
MOV BX,[DI]
CALL ←Swab
ADD BX,0FFEAX
MOV CX,2
SHR BX,CX

;	←numEntries ← BX
MOV [BP-6],BX

;     entries = (struct RoutingEntry *) p->data.words;

;	BX ← ←p
MOV BX,[BP-4]
ADD BX,014X

;	←entries ← BX
MOV [BP-10],BX

;     for (i = 0; i < numEntries; i += 1) {
MOV WORD PTR [BP-8],0
X6:

;	BX ← ←numEntries
MOV BX,[BP-6]

;	CX ← ←i
MOV CX,[BP-8]
CMP CX,BX
JGE X5
JR X4
X7:
INC WORD PTR [BP-8]
JR X6
X4:

;       Block();
CALL ←Block

;       net = entries[i].net;

;	BX ← ←i
MOV BX,[BP-8]

;	CX ← ←entries
MOV CX,[BP-10]
SAL BX
SAL BX
ADD BX,CX
MOV AL,[BX]
XOR AH,AH

;	←net ← AX
MOV [BP-12],AX

;       route = &routingTable[net];

;	BX ← ←net
MOV BX,[BP-12]
LEA CX,←routingTable
ADD CX,BX
ADD CX,BX
ADD BX,CX

;	←route ← BX
POP DX
PUSH BX

;       hops = entries[i].hops + 1;

;	BX ← ←i
MOV BX,[BP-8]

;	CX ← ←entries
MOV CX,[BP-10]
SAL BX
SAL BX
ADD BX,CX
MOV AL,[BX+3]
INC AL
XOR AH,AH

;	←hops ← AX
MOV [BP-14],AX

;       if ((route->hops > hops) || (route->host == p->sPort.host) || ((route->hops == hops) && (route->age == 0x00ff))) {

;	BX ← ←route
POP BX
PUSH BX
MOV AL,[BX+1]
JR $+5
X3:
JMP X9
XOR AH,AH

;	BX ← ←hops
MOV BX,[BP-14]
CMP AX,BX
JG X11

;	DI ← ←route
POP DI
PUSH DI
MOV AL,[DI]

;	BX ← ←p
MOV BX,[BP-4]
MOV CL,[BX+15]
CMP AL,CL
JZ X13

;	BX ← ←route
POP BX
PUSH BX
MOV AL,[BX+1]
XOR AH,AH

;	BX ← ←hops
MOV BX,[BP-14]
CMP AX,BX
JNZ X14

;	BX ← ←route
POP BX
PUSH BX
MOV AL,[BX+2]
JR $+5
X5:
JMP X15
CMP AL,0FFX
X14:
X13:
X12:
JNZ X10
X11:
MOV AL,1
JR X16
X10:
XOR AL,AL
X16:
OR AL,AL
JZ X8

;         route->host = p->sPort.host;

;	BX ← ←p
MOV BX,[BP-4]
MOV AL,[BX+15]

;	BX ← ←route
POP BX
PUSH BX
MOV [BX],AL

;         route->hops = hops;

;	BX ← ←route
POP BX
PUSH BX

;	AL ← ←hops
MOV AL,[BP-14]
MOV [BX+1],AL

;         route->age = 0;

;	BX ← ←route
POP BX
PUSH BX
MOV BYTE PTR [BX+2],0

;         };
X8:

;       };
JMP X7
X15:

;     };
X9:

;   ReleasePBI(pbi);

;	BX ← ←pbi
MOV BX,[BP-2]
CALL ←ReleasePBI

;   };
MOV SP,BP
POP BP
RET;

; RequestRoute(net)
←RequestRoute:

;   int net;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   struct PBI *pbi;

;   struct SocketEntry *pse;

;   struct Port lclPort;

;   if (!routingSoc) {
ADD SP,0FFF6X
MOV BX,←routingSoc
OR BX,BX
JNZ X17

;     lclPort.net = localNet;
MOV AX,←localNet

;	←lclPort ← AL
POP DX
PUSH AX

;     lclPort.host = localHost;
MOV AX,←localHost

;	←lclPort+1 ← AL
MOV [BP-11],AL

;     lclPort.socket.LS = 0;
MOV WORD PTR [BP-10],0

;     lclPort.socket.ms = Swab(2);
MOV BX,2
CALL ←Swab

;	←lclPort+4 ← BX
MOV [BP-8],BX

;     routingSoc = OpenLevel1Socket(&lclPort, &RoutePr, 0);
;&←lclPort
LEA BX,[BP-12]
PUSH BX
XOR BX,BX
MOV CX,OFFSET ←RoutePr
CALL ←OpenLevel1Socket
POP DX
MOV ←routingSoc,BX

;     if (!routingSoc) return;
MOV BX,←routingSoc
OR BX,BX
JNZ X18
MOV SP,BP
POP BP
RET;
X18:

;     };
X17:

;   pbi = GetPBI();
CALL ←GetPBI

;	←pbi ← BX
MOV [BP-4],BX

;   pbi->pup->sPort.socket.LS = 0;

;	BX ← ←pbi
MOV BX,[BP-4]
MOV CX,[BX+6]
MOV BX,CX
MOV WORD PTR [BX+16],0

;   pbi->pup->sPort.socket.ms = Swab(2);

;	BX ← ←pbi
MOV BX,[BP-4]
MOV CX,[BX+6]
PUSH CX
MOV BX,2
CALL ←Swab
MOV CX,BX
POP BX
MOV [BX+18],CX

;   SimpleSend(pbi, 0200, 02);

;	BX ← ←pbi
MOV BX,[BP-4]
PUSH BX
MOV BX,2
MOV CX,080X
CALL ←SimpleSend
POP DX

;   routSent += 1;
INC ←routSent

;   };
MOV SP,BP
POP BP
RET;

; static struct PBI *rcvPBI;

; static int rcvType;

; static int z[2];  /* actually a null ShortSTRING */

; static int counter[2];

; static RcvPr(pbi)
←RcvPr:

;   struct PBI *pbi;
PUSH BP
MOV BP,SP
PUSH BX

;   {

;   if ((pbi->pup->type != rcvType) || (rcvPBI != 0)) ReleasePBI(pbi);

;	BX ← ←pbi
POP BX
PUSH BX
MOV CX,[BX+6]
MOV DI,CX
MOV AL,[DI+3]
XOR AH,AH
MOV BX,←rcvType
CMP AX,BX
JNZ X21
MOV BX,←rcvPBI
OR BX,BX
X21:
X20:
JZ X19

;	BX ← ←pbi
POP BX
PUSH BX
CALL ←ReleasePBI

;   else {
JR X22
X19:

;     rcvPBI = pbi;

;	BX ← ←pbi
POP BX
PUSH BX
MOV ←rcvPBI,BX

;     simpleRcvd += 1;
INC ←simpleRcvd

;     };
X22:

;   };
MOV SP,BP
POP BP
RET;

; struct PBI *SimpleExch(sendType, recvType, servSoc, tries)
←SimpleExch:

;   int sendType, recvType, servSoc, tries;
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

;   {

;   struct PBI *pbi;

;   struct Pup *p;

;   int soc, i;

;   struct Queue tQ[1];

;   int tmr[1];

;   int wait;
ADD SP,0FFF0X

;   InitQueue(tQ)
;&←tQ
LEA BX,[BP-16]
CALL ←InitQueue

;   pbi = GetPBI();
CALL ←GetPBI

;	←pbi ← BX
MOV [BP-6],BX

;   p = pbi->pup;

;	BX ← ←pbi
MOV BX,[BP-6]
MOV CX,[BX+6]

;	←p ← CX
MOV [BP-8],CX

;   Timer(&p->sPort.socket.LS);

;	BX ← ←p
MOV BX,[BP-8]
ADD BX,010X
CALL ←Timer

;   rcvPBI = 0;
MOV WORD PTR ←rcvPBI,0

;   if (!(soc = OpenLevel1Socket(&p->sPort, &RcvPr, 0))) CallSwat(ecPup1+10);

;	BX ← ←p
MOV BX,[BP-8]
ADD BX,0EX
PUSH BX
XOR BX,BX
MOV CX,OFFSET ←RcvPr
CALL ←OpenLevel1Socket
POP DX

;	←soc ← BX
MOV [BP-10],BX
OR BX,BX
JNZ X23
MOV BX,0400AX
CALL ←CallSwat
X23:

;   pbi->queue = tQ;

;	BX ← ←pbi
MOV BX,[BP-6]
;&←tQ
LEA CX,[BP-16]
MOV [BX+2],CX

;   rcvType = recvType;

;	BX ← ←recvType
MOV BX,[BP+4]
MOV ←rcvType,BX

;   Timer(counter);
LEA BX,←counter
CALL ←Timer

;   wait = 100;
MOV WORD PTR [BP-20],064X

;   for (i = 0; ((i<tries) && (rcvPBI == 0)); i += 1) {
MOV WORD PTR [BP-12],0
X26:

;	BX ← ←tries
MOV BX,[BP-4]

;	CX ← ←i
MOV CX,[BP-12]
CMP CX,BX
JGE X27
MOV BX,←rcvPBI
OR BX,BX
JNZ X27
MOV AL,1
JR X28
X27:
XOR AL,AL
X28:
OR AL,AL
JZ X25
JR X24
X29:
INC WORD PTR [BP-12]
JR X26
X24:

;     simpleSent += 1;
INC ←simpleSent

;     SimpleSend(pbi, sendType, servSoc);

;	BX ← ←pbi
MOV BX,[BP-6]
PUSH BX

;	BX ← ←servSoc
MOV BX,[BP-2]

;	CX ← ←sendType
MOV CX,[BP+6]
CALL ←SimpleSend
POP DX

;     WaitUntilSent(pbi);  /* Removed from tQ after sent */

;	BX ← ←pbi
MOV BX,[BP-6]
CALL ←WaitUntilSent

;     SetTmr(wait, tmr);
;&←tmr
LEA BX,[BP-18]

;	CX ← ←wait
POP CX
PUSH CX
CALL ←SetTmr

;     while ((!TmrExp(tmr)) && (rcvPBI == 0)) Block();
X30:
;&←tmr
LEA BX,[BP-18]
CALL ←TmrExp
OR BX,BX
JNZ X32
MOV BX,←rcvPBI
OR BX,BX
X32:
JNZ X31
CALL ←Block
JR X30
X31:

;     wait = wait + 500;

;	BX ← ←wait
POP BX
ADD BX,01F4X

;	←wait ← BX
PUSH BX

;     };
JR X29
X25:

;   ReleasePBI(pbi);

;	BX ← ←pbi
MOV BX,[BP-6]
CALL ←ReleasePBI

;   CloseLevel1Socket(soc);  /* We either got it or we didn't! */

;	BX ← ←soc
MOV BX,[BP-10]
CALL ←CloseLevel1Socket

;   return(rcvPBI);
MOV BX,←rcvPBI
MOV SP,BP
POP BP
RET;

;   };

; SimpleSend(pbi, sendType, servSoc)
←SimpleSend:

;   struct PBI *pbi;

;   int sendType, servSoc;
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

;   {

;   struct Pup *p;
PUSH DX

;   p = pbi->pup;

;	BX ← ←pbi
MOV BX,[BP+4]
MOV CX,[BX+6]

;	←p ← CX
POP DX
PUSH CX

;   p->dPort.net = localNet;

;	BX ← ←p
POP BX
PUSH BX
MOV AX,←localNet
MOV [BX+8],AL

;   p->dPort.socket.ms = Swab(servSoc);

;	BX ← ←p
POP BX
PUSH BX
PUSH BX

;	BX ← ←servSoc
MOV BX,[BP-4]
CALL ←Swab
MOV CX,BX
POP BX
MOV [BX+12],CX

;   p->sPort.net = localNet;

;	BX ← ←p
POP BX
PUSH BX
MOV AX,←localNet
MOV [BX+14],AL

;   p->sPort.host = localHost;

;	BX ← ←p
POP BX
PUSH BX
MOV AX,←localHost
MOV [BX+15],AL

;   p->type = sendType;

;	BX ← ←p
POP BX
PUSH BX

;	AL ← ←sendType
MOV AL,[BP-2]
MOV [BX+3],AL

;   if (!counter[0]) Timer(counter);
MOV BX,←counter
OR BX,BX
JNZ X33
LEA BX,←counter
CALL ←Timer
X33:

;   DoubleInc(counter, 1);
MOV BX,1
LEA CX,←counter
CALL ←DoubleInc

;   p->id[0] = counter[1];

;	BX ← ←p
POP BX
PUSH BX
ADD BX,4
MOV CX,←counter+2
MOV [BX],CX

;   p->id[1] = counter[0];

;	BX ← ←p
POP BX
PUSH BX
ADD BX,4
MOV CX,←counter
MOV [BX+2],CX

;   Zero(z, 2);
MOV BX,2
LEA CX,←z
CALL ←Zero

;   AppendStringToPup(pbi, 0, z);  /* Just to compute length of empty packet */

;	BX ← ←pbi
MOV BX,[BP+4]
PUSH BX
LEA BX,←z
XOR CX,CX
CALL ←AppendStringToPup
POP DX

;   SendPup(pbi);

;	BX ← ←pbi
MOV BX,[BP+4]
CALL ←SendPup

;   };
MOV SP,BP
POP BP
RET;

; Externals Declared Here
PUBLIC ←calendar
PUBLIC ←ReadCalendar
PUBLIC ←InitCalendar
PUBLIC ←SimpleExch
PUBLIC ←routingSoc
PUBLIC ←RequestRoute
PUBLIC ←SimpleSend

C←CODE ENDS

; Number of Bytes of Code = 0404X, (1028)