(FILECREATED "17-May-85 14:42:52" {ERIS}<LISPCORE>SOURCES>COURIER.;11 80555 changes to: (FNS \COURIER.RESULTS \BULK.DATA.CLOSE) previous date: "13-Feb-85 23:44:03" {ERIS}<LISPCORE>SOURCES>COURIER.;9) (* Copyright (c) 1983, 1984, 1985 by Xerox Corporation. All rights reserved.) (PRETTYCOMPRINT COURIERCOMS) (RPAQQ COURIERCOMS [(COMS (* Courier Remote Procedure Call Protocol.) (DECLARE: DONTCOPY (CONSTANTS (COURIER.VERSION# 3)) (CONSTANTS (\COURIERMSG.CALL 0) (\COURIERMSG.REJECT 1) (\COURIERMSG.RETURN 2) (\COURIERMSG.ABORT 3)) (CONSTANTS (\NS.WKS.Courier 5)) (MACROS \GET.COURIERPROGRAM \COURIER.QUALIFIED.NAMEP NULLORLISTP) (RECORDS COURIERPGM COURIERFN COURIERERR \BULK.DATA.CONTINUATION COURIERREPSTREAM BULKDATAGENERATOR) (GLOBALVARS DFNFLG LCASEFLG \COURIER.REP.DEVICE \BASEBYTESDEVICE) (COMS (CONSTANTS (\EXPEDITED.LENGTH (IPLUS \XIPOVLEN 6 4)) \EXTYPE.EXPEDITED.COURIER) (RECORDS EXPEDITEDXIP)) EVAL@COMPILE (FILES (LOADCOMP) LLNS)) (* Facilities for manipulating Courier definitions.) (INITVARS (\COURIERPROGRAM (HARRAY 20)) \COURIER.REP.DEVICE) (FNS COURIER.VERSION# COURIERPROGRAM \COURIER.PUTDEF \COURIER.CHECKDEF \COURIER.CHECK.PROCEDURES \COURIER.CHECK.ERRORS \COURIER.DELDEF \COURIER.GETDEF \GET.COURIERPROGRAM \DUMP.COURIERPROGRAMS \GET.COURIER.TYPE \GET.COURIER.DEFINITION) (GLOBALVARS \COURIERPROGRAM) (FILEPKGCOMS COURIERPROGRAMS) (COMS (MACROS COURIER.FETCH COURIER.CREATE) (PROP INFO COURIER.FETCH COURIER.CREATE) (FNS \COURIER.RECORDTRAN)) (* Functions for calling Courier procedures.) (FNS COURIER.OPEN \COURIER.WHENCLOSED COURIER.CALL COURIER.EXECUTE.CALL \COURIER.RESULTS \COURIER.HANDLE.BULKDATA \COURIER.HANDLE.ERROR \BULK.DATA.STREAM \COURIER.ATTENTIONFN \COURIER.OUTPUT.ABORTED \BULK.DATA.CLOSE \ABORT.BULK.DATA) (FNS COURIER.EXPEDITED.CALL COURIER.EXECUTE.EXPEDITED.CALL \BUILD.EXPEDITED.XIP \SEND.EXPEDITED.XIP \COURIER.EXPEDITED.ARGS \MAKE.EXPEDITED.STREAM \COURIER.EOF \COURIER.EXPEDITED.OVERFLOW) (FNS COURIER.BROADCAST.CALL \COURIER.BROADCAST.ON.NET) (FNS COURIER.READ \COURIER.UNKNOWN.TYPE COURIER.READ.SEQUENCE COURIER.READ.STRING COURIER.WRITE COURIER.WRITE.SEQUENCE COURIER.WRITE.STRING \COURIER.TYPE.ERROR) (FNS COURIER.READ.BULKDATA BULKDATA.GENERATOR BULKDATA.GENERATE.NEXT COURIER.WRITE.BULKDATA) (FNS COURIER.READ.REP COURIER.WRITE.REP COURIER.WRITE.SEQUENCE.UNSPECIFIED \CWSU.DEFAULT COURIER.REP.LENGTH \MAKE.COURIER.REP.STREAM \COURIER.REP.BIN \COURIER.REP.BOUT) (COMS (FNS COURIER.READ.NSADDRESS COURIER.WRITE.NSADDRESS) (PROP COURIERDEF NSADDRESS))) (COMS (* Debugging) (INITVARS (COURIERTRACEFILE) (COURIERTRACEFLG) (COURIERPRINTLEVEL (QUOTE (2 . 4))) (NSWIZARDFLG)) (GLOBALVARS COURIERTRACEFLG COURIERTRACEFILE COURIERPRINTLEVEL NSWIZARDFLG) (FNS COURIERTRACE \COURIER.TRACE)) (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS (ADDVARS (NLAMA \DUMP.COURIERPROGRAMS COURIERPROGRAM) (NLAML) (LAMA COURIER.EXPEDITED.CALL COURIER.CALL]) (* Courier Remote Procedure Call Protocol.) (DECLARE: DONTCOPY (DECLARE: EVAL@COMPILE (RPAQQ COURIER.VERSION# 3) (CONSTANTS (COURIER.VERSION# 3)) ) (DECLARE: EVAL@COMPILE (RPAQQ \COURIERMSG.CALL 0) (RPAQQ \COURIERMSG.REJECT 1) (RPAQQ \COURIERMSG.RETURN 2) (RPAQQ \COURIERMSG.ABORT 3) (CONSTANTS (\COURIERMSG.CALL 0) (\COURIERMSG.REJECT 1) (\COURIERMSG.RETURN 2) (\COURIERMSG.ABORT 3)) ) (DECLARE: EVAL@COMPILE (RPAQQ \NS.WKS.Courier 5) (CONSTANTS (\NS.WKS.Courier 5)) ) (DECLARE: EVAL@COMPILE (PUTPROPS \GET.COURIERPROGRAM MACRO ((PROGRAM) (GETHASH PROGRAM \COURIERPROGRAM))) [PUTPROPS \COURIER.QUALIFIED.NAMEP MACRO (OPENLAMBDA (X) (AND (LISTP X) (LITATOM (CDR X)) (LITATOM (CAR X] [PUTPROPS NULLORLISTP MACRO (OPENLAMBDA (X) (OR (NULL X) (LISTP X] ) [DECLARE: EVAL@COMPILE (RECORD COURIERPGM (VERSIONPAIR . COURIERDEFS) (RECORD VERSIONPAIR (PROGRAM# VERSION#)) (PROPRECORD COURIERDEFS (TYPES PROCEDURES ERRORS INHERITS))) (RECORD COURIERFN (FN# ARGS RETURNSNOISE RESULTS REPORTSNOISE ERRORS)) (RECORD COURIERERR (ERR# ARGS)) (RECORD \BULK.DATA.CONTINUATION (PROGRAM PROCEDURE PGMDEF PROCDEF NOERRORFLG INTERNALFLG)) (ACCESSFNS COURIERREPSTREAM ((CRWORDLIST (fetch F1 of DATUM) (replace F1 of DATUM with NEWVALUE)) (CRNEXTBYTE (fetch F2 of DATUM) (replace F2 of DATUM with NEWVALUE)) (CRLASTWORD (fetch F3 of DATUM) (replace F3 of DATUM with NEWVALUE)))) (RECORD BULKDATAGENERATOR (BGITEMSLEFT BGSTREAM (BGPROGRAM . BGTYPE) . BGLASTSEGMENT?)) ] (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS DFNFLG LCASEFLG \COURIER.REP.DEVICE \BASEBYTESDEVICE) ) (DECLARE: EVAL@COMPILE (RPAQ \EXPEDITED.LENGTH (IPLUS \XIPOVLEN 6 4)) (RPAQQ \EXTYPE.EXPEDITED.COURIER 2) (CONSTANTS (\EXPEDITED.LENGTH (IPLUS \XIPOVLEN 6 4)) \EXTYPE.EXPEDITED.COURIER) ) [DECLARE: EVAL@COMPILE (ACCESSFNS EXPEDITEDXIP ((EXPEDITEDBASE (fetch (PACKETEXCHANGEXIP PACKETEXCHANGEBODY) of DATUM))) (BLOCKRECORD EXPEDITEDBASE ((LOWVERSION WORD) (HIGHVERSION WORD) (MSGTYPE WORD) (TRANSACTIONID WORD) (PROGRAM# FIXP) (VERSION# WORD) (PROCEDURE# WORD) (ARG0 WORD))) [ACCESSFNS EXPEDITEDXIP ((EXPEDITEDMSGBODY (LOCF (fetch (EXPEDITEDXIP MSGTYPE) of DATUM))) (EXPEDITEDARGBASE (LOCF (fetch (EXPEDITEDXIP ARG0) of DATUM]) ] EVAL@COMPILE (FILESLOAD (LOADCOMP) LLNS) ) (* Facilities for manipulating Courier definitions.) (RPAQ? \COURIERPROGRAM (HARRAY 20)) (RPAQ? \COURIER.REP.DEVICE NIL) (DEFINEQ (COURIER.VERSION# (LAMBDA NIL (* bvm: " 2-May-84 12:27") (* * Returns number of the version of Courier we are running) COURIER.VERSION#)) (COURIERPROGRAM (NLAMBDA X (* bvm: "10-Jun-84 23:02") (* Define a Courier program and its associated types, constants, procedures, and errors. Syntax is (COURIERPROGRAM programName (programNumber versionNumber) TYPES (typeDeclarations ...) PROCEDURES (procedureDeclarations ...) ERRORS (errorDeclarations ...)) The TYPES, PROCEDURES, and ERRORS may appear in any order after the program number/version number pair.) (PUTDEF (CAR X) (QUOTE COURIERPROGRAMS) (CDR X)))) (\COURIER.PUTDEF (LAMBDA (NAME TYPE DEFINITION) (* bvm: "10-Jun-84 23:17") (* * PUTDEF for type COURIERPROGRAMS -- also called by COURIERPROGRAM) (PROG (OLDINFO) (SETQ OLDINFO (GETHASH (SETQ NAME (\DTEST NAME (QUOTE LITATOM))) \COURIERPROGRAM)) (COND ((NULL OLDINFO) (MARKASCHANGED NAME TYPE (QUOTE DEFINED))) ((AND OLDINFO (NOT (EQUAL OLDINFO DEFINITION))) (COND ((NEQ DFNFLG T) (LISPXPRINT (LIST (QUOTE COURIER) (QUOTE program) NAME (QUOTE redefined)) T T))) (MARKASCHANGED NAME TYPE (QUOTE CHANGED)))) (/PUTHASH NAME DEFINITION \COURIERPROGRAM) (RETURN NAME)))) (\COURIER.CHECKDEF (LAMBDA (NAME DEF) (* bvm: "16-Jul-84 15:36") (COND ((OR (NLISTP (fetch (COURIERPGM VERSIONPAIR) of DEF)) (NOT (FIXP (fetch (COURIERPGM PROGRAM#) of DEF))) (NOT (FIXP (fetch (COURIERPGM VERSION#) of DEF)))) (ERROR "Bad version specification in Courier def" NAME)) (T (for TAIL on (fetch COURIERDEFS of DEF) by (CDDR TAIL) do (SELECTQ (CAR TAIL) ((TYPES INHERITS)) (PROCEDURES (\COURIER.CHECK.PROCEDURES (CADR TAIL))) (ERRORS (\COURIER.CHECK.ERRORS (CADR TAIL))) (ERROR "Courier definition not understood" (CAR TAIL)))))))) (\COURIER.CHECK.PROCEDURES (LAMBDA (DEFS) (* bvm: "12-Oct-84 11:24") (for FNDEF in DEFS bind INFO unless (COND ((NLISTP FNDEF) NIL) ((EQ (CAR FNDEF) COMMENTFLG) (* Comments ok) T) (T (SETQ INFO (CDR FNDEF)) (COND ((AND (FIXP (fetch (COURIERFN FN#) of INFO)) (NULLORLISTP (fetch (COURIERFN ARGS) of INFO)) (LITATOM (fetch (COURIERFN RETURNSNOISE) of INFO)) (NULLORLISTP (fetch (COURIERFN RESULTS) of INFO)) (LITATOM (fetch (COURIERFN REPORTSNOISE) of INFO)) (NULLORLISTP (fetch (COURIERFN ERRORS) of INFO))) (* nice new format) T) (T (PROG (ARGS RESULTS ERRORS N) (RETURN (COND ((while INFO do (COND ((NULL (CDR INFO)) (RETURN (FIXP (SETQ N (CAR INFO))))) (T (SELECTQ (CAR INFO) (ARGS (OR (NULLORLISTP (SETQ ARGS (CADR INFO))) (RETURN))) (RESULTS (OR (NULLORLISTP (SETQ RESULTS (CADR INFO))) (RETURN))) (ERRORS (OR (NULLORLISTP (SETQ ERRORS (CADR INFO))) (RETURN))) (RETURN)) (SETQ INFO (CDDR INFO))))) (/RPLACD FNDEF (create COURIERFN FN# ← N ARGS ← ARGS RETURNSNOISE ←(QUOTE RETURNS) RESULTS ← RESULTS REPORTSNOISE ←(QUOTE REPORTS) ERRORS ← ERRORS)) T)))))))) do (ERROR "Bad Courier Procedure definition" FNDEF)))) (\COURIER.CHECK.ERRORS (LAMBDA (DEFS) (* bvm: "12-Oct-84 11:24") (for ERRDEF in DEFS bind INFO unless (COND ((NLISTP ERRDEF) NIL) ((EQ (CAR ERRDEF) COMMENTFLG) (* Comments ok) T) (T (SETQ INFO (CDR ERRDEF)) (COND ((AND (FIXP (fetch (COURIERERR ERR#) of INFO)) (NULLORLISTP (fetch (COURIERERR ARGS) of INFO))) (* nice new format) T) (T (COND ((AND (EQ (CAR INFO) (QUOTE ARGS)) (NULLORLISTP (CADR INFO)) (FIXP (CADDR INFO))) (* Old format) (/RPLACD ERRDEF (create COURIERERR ERR# ←(CADDR INFO) ARGS ←(CADR INFO))) T)))))) do (ERROR "Bad Courier Error definition" ERRDEF)))) (\COURIER.DELDEF (LAMBDA (NAME TYPE) (* bvm: "15-Jun-84 15:34") (AND (EQ TYPE (QUOTE COURIERPROGRAMS)) (PUTHASH NAME NIL \COURIERPROGRAM)))) (\COURIER.GETDEF (LAMBDA (NAME TYPE OPTIONS) (* bvm: " 4-Jul-84 15:44") (AND (EQ TYPE (QUOTE COURIERPROGRAMS)) (\GET.COURIERPROGRAM NAME)))) (\GET.COURIERPROGRAM (LAMBDA (PROGRAM) (* bvm: " 5-May-84 14:17") (GETHASH PROGRAM \COURIERPROGRAM))) (\DUMP.COURIERPROGRAMS (NLAMBDA NAMES (* bvm: " 4-Jul-84 15:44") (* Used by the COURIERPROGRAMS filepkgcom) (for PROGRAM in NAMES bind PGMDEF do (COND ((SETQ PGMDEF (\GET.COURIERPROGRAM PROGRAM)) (TERPRI) (* because if you have a really bold font, it lines up the bottoms, but you can get crowded into the line above.) (PRIN1 "(COURIERPROGRAM ") (COND ((AND FONTCHANGEFLG PRETTYCOMFONT) (CHANGEFONT PRETTYCOMFONT))) (PRIN2 PROGRAM) (COND ((AND FONTCHANGEFLG PRETTYCOMFONT) (CHANGEFONT DEFAULTFONT))) (SPACES 1) (PRIN2 (CAR PGMDEF)) (* Version pair) (for TAIL on (CDR PGMDEF) by (CDDR TAIL) do (TAB 4) (COND ((AND FONTCHANGEFLG CLISPFONT) (CHANGEFONT PRETTYCOMFONT))) (PRIN2 (CAR TAIL)) (COND ((AND FONTCHANGEFLG CLISPFONT) (CHANGEFONT DEFAULTFONT))) (* Property name) (TAB 6) (PRINTDEF (CADR TAIL) 6)) (PRIN1 (QUOTE %))) (TERPRI)) (T (LISPXPRINT (APPEND (QUOTE (no COURIER definition for)) (LIST PROGRAM)) T T)))))) (\GET.COURIER.TYPE (LAMBDA (PROGRAMNAME TYPENAME) (* ecc " 7-JUL-83 14:34") (CAR (\GET.COURIER.DEFINITION PROGRAMNAME TYPENAME (QUOTE TYPES))))) (\GET.COURIER.DEFINITION (LAMBDA (PROGRAM NAME TYPE PGMDEF) (* bvm: "16-Jul-84 15:35") (COND ((\COURIER.QUALIFIED.NAMEP NAME) (\GET.COURIER.DEFINITION (CAR NAME) (CDR NAME) TYPE)) (T (OR (CDR (ASSOC NAME (LISTGET (CDR (OR PGMDEF (SETQ PGMDEF (\GET.COURIERPROGRAM PROGRAM)))) TYPE))) (for OTHERPROGRAM in (LISTGET (CDR (OR PGMDEF (\GET.COURIERPROGRAM PROGRAM))) (QUOTE INHERITS)) when (SETQ $$VAL (CDR (ASSOC NAME (LISTGET (CDR (\GET.COURIERPROGRAM OTHERPROGRAM)) TYPE)))) do (* Is defined in an inherited program) (RETURN $$VAL)) (ERROR (CONCAT "No " TYPE " definition for") (LIST PROGRAM NAME))))))) ) (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS \COURIERPROGRAM) ) (PUTDEF (QUOTE COURIERPROGRAMS) (QUOTE FILEPKGCOMS) (QUOTE ((COM MACRO (X (E (\DUMP.COURIERPROGRAMS . X))) CONTENTS NILL) (TYPE DESCRIPTION "Courier programs" GETDEF \COURIER.GETDEF PUTDEF \COURIER.PUTDEF DELDEF \COURIER.DELDEF)))) (DECLARE: EVAL@COMPILE [PUTPROPS COURIER.FETCH MACRO (ARGS (\COURIER.RECORDTRAN ARGS (QUOTE FETCH] [PUTPROPS COURIER.CREATE MACRO (ARGS (\COURIER.RECORDTRAN ARGS (QUOTE CREATE] ) (PUTPROPS COURIER.FETCH INFO NOEVAL) (PUTPROPS COURIER.CREATE INFO NOEVAL) (DEFINEQ (\COURIER.RECORDTRAN (LAMBDA (ARGS OP) (* bvm: " 4-Jul-84 15:42") (PROG ((PROGRAM (CAR ARGS)) (REST (CDR ARGS)) TYPEDEF) (SETQ TYPEDEF (COND ((NLISTP PROGRAM) (\GET.COURIER.TYPE PROGRAM (pop REST))) ((\COURIER.QUALIFIED.NAMEP PROGRAM) (SETQ TYPEDEF (CDR PROGRAM)) (\GET.COURIER.TYPE (SETQ PROGRAM (CAR PROGRAM)) TYPEDEF)) (T (GO ERROR)))) LP (COND ((NLISTP TYPEDEF) (SETQ TYPEDEF (\GET.COURIER.TYPE PROGRAM TYPEDEF)) (GO LP)) ((NEQ (CAR TYPEDEF) (QUOTE RECORD)) (COND ((\COURIER.QUALIFIED.NAMEP TYPEDEF) (SETQ TYPEDEF (\GET.COURIER.TYPE (SETQ PROGRAM (CAR TYPEDEF)) (CDR TYPEDEF))) (GO LP)) (T (GO ERROR)))) (T (pop TYPEDEF))) (RETURN (SELECTQ OP (FETCH (* FETCH FIELD of DATUM - DATUM is a list of values, one for each field) (bind (FIELD ←(pop REST)) (FORM ←(CAR REST)) first (SELECTQ FORM ((OF of) (* Noise word) (COND ((AND (EQ FORM (QUOTE OF)) LCASEFLG) (/RPLACA REST (QUOTE of)))) (SETQ FORM (CAR (SETQ REST (CDR REST))))) (COND ((EQ FORM (QUOTE of)) (* Noise word) (SETQ FORM (CAR (SETQ REST (CDR REST))))))) (COND ((CDR REST) (* Too many args) (GO ERROR))) while TYPEDEF do (COND ((EQ (CAAR TYPEDEF) FIELD) (RETURN (LIST (QUOTE CAR) FORM)))) (SETQ FORM (LIST (QUOTE CDR) FORM)) (SETQ TYPEDEF (CDR TYPEDEF)) finally (GO ERROR))) (CREATE (* CREATE Field1 Value1 ... FieldN ValueN) (CONS (QUOTE LIST) (bind (TAIL ← REST) X while TAIL collect (COND ((NEQ (CAR TAIL) (CAR (pop TYPEDEF))) (* Fields not in order) (GO ERROR)) (T (PROG1 (COND ((EQ (SETQ X (CAR (SETQ TAIL (CDR TAIL)))) (QUOTE ←)) (* Noise token) (CAR (SETQ TAIL (CDR TAIL)))) (T X)) (SETQ TAIL (CDR TAIL))))) finally (COND (TYPEDEF (GO ERROR)))))) (GO ERROR))) ERROR (ERROR "Invalid Courier Record Access form" (CONS OP ARGS))))) ) (* Functions for calling Courier procedures.) (DEFINEQ (COURIER.OPEN (LAMBDA (HOSTNAME SERVERTYPE NOERRORFLG NAME WHENCLOSEDFN OTHERPROPS) (* ejs: "18-Dec-84 22:44") (* Open a Courier connection to the specified host.) (RESETLST (PROG (ADDRESS STREAM LOW.VERSION HIGH.VERSION) (COND ((NOT (SETQ ADDRESS (COND ((type? NSADDRESS HOSTNAME) HOSTNAME) (HOSTNAME (LOOKUP.NS.SERVER HOSTNAME SERVERTYPE))))) (RETURN (AND (NOT NOERRORFLG) (ERROR "Unknown host" HOSTNAME)))) ((NULL (SETQ STREAM (SPP.OPEN ADDRESS \NS.WKS.Courier T NAME (BQUOTE (CLOSEFN , (CONS (FUNCTION \COURIER.WHENCLOSED) (MKLIST WHENCLOSEDFN)) ,@ OTHERPROPS))))) (RETURN (AND (NOT NOERRORFLG) (ERROR "Host not responding" HOSTNAME))))) (RESETSAVE NIL (LIST (FUNCTION \SPP.CLOSE.IF.ERROR) STREAM)) (replace ENDOFSTREAMOP of STREAM with (FUNCTION \COURIER.EOF)) (SPP.DSTYPE STREAM \SPPDSTYPE.COURIER) (COND (COURIERTRACEFLG (printout COURIERTRACEFILE T "Opened " (OR NAME "") " with " (SPP.DESTADDRESS STREAM)))) (PUTWORD STREAM COURIER.VERSION#) (PUTWORD STREAM COURIER.VERSION#) (SPP.SENDEOM STREAM) (SETQ LOW.VERSION (GETWORD STREAM)) (SETQ HIGH.VERSION (GETWORD STREAM)) (COND ((NOT (AND (ILEQ LOW.VERSION COURIER.VERSION#) (ILEQ COURIER.VERSION# HIGH.VERSION))) (SPP.CLOSE STREAM) (RETURN (AND (NOT NOERRORFLG) (ERROR "Server supports wrong version of Courier" (LIST HOSTNAME LOW.VERSION HIGH.VERSION)))))) (RETURN STREAM))))) (\COURIER.WHENCLOSED (LAMBDA (STREAM CON) (* bvm: " 4-Jul-84 00:28") (COND (COURIERTRACEFLG (printout COURIERTRACEFILE .TAB0 0 "Closed with " (SPP.DESTADDRESS STREAM) T))))) (COURIER.CALL (LAMBDA ARGS (* bvm: "16-Jul-84 15:38") (* Call a Courier procedure. - (COURIER.CALL stream program-name procedure-name arg1 ... argN) - Returns the result of the remote procedure, or a list of such results if it returns more than one. A single flag NoErrorFlg can be optionally appended to the arglist -- If NoErrorFlg is NOERROR, return NIL if the Courier program aborts with an error; if RETURNERRORS, then return an expression (ERROR ERRNAME . args) on error. If the Courier procedure takes a Bulk Data parameter, then the result of COURIER.CALL is a stream for the transfer. When the stream is closed, the results will be read and the functional argument that was supplied in the call, if any, will be applied to the results.) (PROG ((STREAM (ARG ARGS 1)) (PROGRAM (ARG ARGS 2)) (PROCEDURE (ARG ARGS 3)) #ARGS ARGLIST NOERRORFLG PGMDEF PROCDEF ARGTYPES) (SETQ PGMDEF (OR (\GET.COURIERPROGRAM PROGRAM) (ERROR "No such Courier program" PROGRAM))) (SETQ PROCDEF (\GET.COURIER.DEFINITION PROGRAM PROCEDURE (QUOTE PROCEDURES) PGMDEF)) (SETQ #ARGS (LENGTH (SETQ ARGTYPES (fetch (COURIERFN ARGS) of PROCDEF)))) (OR (SELECTQ (IDIFFERENCE ARGS #ARGS) (3 (* Exactly right) T) (4 (* Extra arg is errorflg) (SELECTQ (SETQ NOERRORFLG (ARG ARGS (IPLUS #ARGS 4))) ((NOERROR RETURNERRORS T) T) NIL)) NIL) (ERROR "Wrong number of arguments to Courier procedure" (CONS PROGRAM PROCEDURE))) (SETQ ARGLIST (for I from 4 to (IPLUS #ARGS 3) collect (ARG ARGS I))) (RETURN (COND ((type? STREAM STREAM) (COURIER.EXECUTE.CALL STREAM PROGRAM PGMDEF PROCEDURE PROCDEF ARGLIST ARGTYPES NOERRORFLG)) ((type? NSADDRESS STREAM) (* Means to make a single call to this address) (RESETLST (PROG ((STREAM (COURIER.OPEN STREAM NIL NOERRORFLG))) (RETURN (COND (STREAM (RESETSAVE NIL (LIST (FUNCTION \SPP.RESETCLOSE) STREAM)) (COURIER.EXECUTE.CALL STREAM PROGRAM PGMDEF PROCEDURE PROCDEF ARGLIST ARGTYPES NOERRORFLG))))))) ((NULL NOERRORFLG) (\ILLEGAL.ARG STREAM))))))) (COURIER.EXECUTE.CALL (LAMBDA (STREAM PROGRAM PGMDEF PROCEDURE PROCDEF ARGLIST ARGTYPES NOERRORFLG) (* bvm: "12-Oct-84 22:36") (* Send the arguments for a Courier call to the remote program. Returns NIL if none of the formal parameters are of type BULK.DATA.SOURCE or BULK.DATA.SINK, otherwise returns a stream for the Bulk Data transfer.) (COND (COURIERTRACEFLG (\COURIER.TRACE (QUOTE CALL) PROGRAM PROCEDURE ARGLIST))) (PROG (SOURCEFLG SINKFLG BULKDATAFN DATASTREAM) (SPP.DSTYPE STREAM \SPPDSTYPE.COURIER) (PUTWORD STREAM \COURIERMSG.CALL) (PUTWORD STREAM 0) (* Transaction ID, ignored for now.) (PUTLONG STREAM (fetch (COURIERPGM PROGRAM#) of PGMDEF)) (PUTWORD STREAM (fetch (COURIERPGM VERSION#) of PGMDEF)) (PUTWORD STREAM (fetch (COURIERFN FN#) of PROCDEF)) (for VALUE in ARGLIST as TYPE in ARGTYPES do (SELECTQ TYPE (BULK.DATA.SOURCE (SETQ SOURCEFLG T) (SETQ BULKDATAFN VALUE) (PUTWORD STREAM 1)) (BULK.DATA.SINK (SETQ SINKFLG T) (SETQ BULKDATAFN VALUE) (PUTWORD STREAM 1)) (COURIER.WRITE STREAM VALUE PROGRAM TYPE))) (SPP.SENDEOM STREAM) (CHECK (NOT (AND SOURCEFLG SINKFLG))) (RETURN (COND ((AND (OR SOURCEFLG SINKFLG) (SETQ DATASTREAM (\BULK.DATA.STREAM STREAM (COND (SINKFLG (QUOTE INPUT)) (T (QUOTE OUTPUT))) PROGRAM PROCEDURE PGMDEF PROCDEF NOERRORFLG BULKDATAFN))) (COND (BULKDATAFN (\COURIER.HANDLE.BULKDATA DATASTREAM BULKDATAFN NOERRORFLG)) (T (* Return the stream to caller) DATASTREAM))) (T (\COURIER.RESULTS STREAM PROGRAM PGMDEF PROCEDURE PROCDEF NOERRORFLG))))))) (\COURIER.RESULTS [LAMBDA (STREAM PROGRAM PGMDEF PROCEDURE PROCDEF NOERRORFLG EXPEDITEDFLG) (* bvm: "17-May-85 14:17") (PROG (MSGTYPE RESULT ARGS) (SETQ RESULT (SELECTC (SETQ MSGTYPE (GETWORD STREAM)) [\COURIERMSG.RETURN (PROG ((RESULTTYPES (fetch (COURIERFN RESULTS) of PROCDEF))) (GETWORD STREAM) (* Skip the Transaction ID.) (RETURN (COND ((AND RESULTTYPES (NOT (CDR RESULTTYPES))) (* Single-valued procedures return conventionally) (COURIER.READ STREAM PROGRAM (CAR RESULTTYPES))) (T (for TYPE in RESULTTYPES collect (COURIER.READ STREAM PROGRAM TYPE] [\COURIERMSG.ABORT (PROG (NUMBER ERRORDEF) (GETWORD STREAM) (* Skip the Transaction ID.) (SETQ NUMBER (GETWORD STREAM)) (RETURN (CONS (QUOTE ERROR) (COND [(SETQ ERRORDEF (find ERR in (OR (fetch (COURIERPGM ERRORS) of PGMDEF) (for OTHER in (fetch (COURIERPGM INHERITS) of PGMDEF) when (SETQ $$VAL (fetch (COURIERPGM ERRORS) of ( \GET.COURIERPROGRAM OTHER))) do (RETURN $$VAL))) suchthat (IEQP (fetch (COURIERERR ERR#) of (CDR ERR)) NUMBER))) (CONS (CAR ERRORDEF) (for TYPE in (fetch (COURIERERR ARGS) of (CDR ERRORDEF)) collect (COURIER.READ STREAM PROGRAM TYPE] (T (LIST NUMBER] [\COURIERMSG.REJECT (GETWORD STREAM) (* Skip the Transaction ID.) (LIST (QUOTE ERROR) (QUOTE REJECT) (COURIER.READ STREAM PROGRAM (QUOTE (CHOICE (NoSuchService 0) (WrongVersionOfService 1 (RECORD (lowest CARDINAL) (highest CARDINAL))) (NoSuchProcedure 2) (invalidArguments 3) (unspecifiedError 65535] (LIST (QUOTE ERROR) (QUOTE UnknownResponseType) MSGTYPE))) (OR EXPEDITEDFLG (SPP.CLEAREOM STREAM)) (COND (COURIERTRACEFLG (\COURIER.TRACE (QUOTE RETURN) PROGRAM PROCEDURE RESULT))) [COND ((NEQ MSGTYPE \COURIERMSG.RETURN) (COND ((AND EXPEDITEDFLG (EQ (CADDR RESULT) (QUOTE USE.COURIER))) (* Special flag on expedited courier call saying to use regular Courier) (SETQ RESULT (QUOTE USE.COURIER))) (T (SELECTQ NOERRORFLG (RETURNERRORS) (NIL (ERROR (CONCAT (COND ((EQ (CAR (SETQ ARGS (CDR RESULT))) (QUOTE REJECT)) (SETQ ARGS (CADR ARGS)) "Courier rejected call to ") (T [SETQ ARGS (COND ((CDR ARGS) ARGS) (T (CAR ARGS] "Error in Courier procedure ")) PROGRAM "." PROCEDURE) ARGS)) (PROGN (\COURIER.HANDLE.ERROR PROGRAM PROCEDURE RESULT) (SETQ RESULT NIL] (RETURN RESULT]) (\COURIER.HANDLE.BULKDATA (LAMBDA (DATASTREAM BULKDATAFN NOERRORFLG) (* bvm: "12-Oct-84 16:10") (* * Called when a Courier call has a bulkdata argument. BULKDATAFN is a function to apply to the bulk data stream. If it returns a non-NIL result, that is returned as the value of the Courier call, ignoring the Courier results, if any. As a special case, a BULKDATAFN of (Program . Type) interprets the bulk data stream as a "Stream of Program.Type") (PROG ((BULKRESULTS (ERSETQ (COND ((AND (LISTP BULKDATAFN) (NEQ (CAR BULKDATAFN) (QUOTE LAMBDA))) (* Special case, interpret as a type) (COURIER.READ.BULKDATA DATASTREAM (CAR BULKDATAFN) (CDR BULKDATAFN) T)) (T (APPLY* BULKDATAFN DATASTREAM))))) MAINRESULTS) (SETQ MAINRESULTS (\BULK.DATA.CLOSE DATASTREAM (AND (NULL BULKRESULTS) (OR NOERRORFLG T)))) (RETURN (OR (CAR BULKRESULTS) MAINRESULTS))))) (\COURIER.HANDLE.ERROR (LAMBDA (PROGRAM PROCEDURE ERRORARGS) (* bvm: "27-Jun-84 23:05") (COND (NSWIZARDFLG (printout PROMPTWINDOW .TAB0 0 "Error in Courier program " PROGRAM ", procedure " PROCEDURE ": " ERRORARGS))))) (\BULK.DATA.STREAM (LAMBDA (STREAM MODE PROGRAM PROCEDURE PGMDEF PROCDEF NOERRORFLG INTERNALFLG) (* bvm: "12-Oct-84 17:13") (* Return a specialized version of an SPP stream suitable for sending or receiving a Bulk Data object. Uses the Bulk Data device, which redefines the EOFP and CLOSE functions. Save the program, procedure, and result function in the stream record for use by \BULK.DATA.CLOSE.) (PROG ((CON (GETSPPCON STREAM)) SUBSTREAM NEXTPKT) (COND ((EQ MODE (QUOTE INPUT)) (* Preview the incoming stream to see if there's any data there) (COND ((NOT (SETQ NEXTPKT (\GETSPP CON NIL T))) (* Connection died) (RETURN NIL)) ((NEQ (fetch (SPPXIP DSTYPE) of NEXTPKT) \SPPDSTYPE.BULKDATA) (* Bulkdata not coming, must be error) (RETURN NIL)) ((fetch (SPPXIP ATTENTION) of NEXTPKT) (* Immediately aborted, must be nothing coming) (\GETSPP CON) (* Eat the packet) (RETURN NIL))))) (SETQ SUBSTREAM (OR (fetch SPPSUBSTREAM of CON) (create STREAM DEVICE ← \SPP.BULKDATA.DEVICE))) (replace SPP.CONNECTION of SUBSTREAM with CON) (replace BULK.DATA.CONTINUATION of SUBSTREAM with (create \BULK.DATA.CONTINUATION PROGRAM ← PROGRAM PROCEDURE ← PROCEDURE PGMDEF ← PGMDEF PROCDEF ← PROCDEF NOERRORFLG ← NOERRORFLG INTERNALFLG ← INTERNALFLG)) (replace SPPEOFP of SUBSTREAM with NIL) (replace ACCESS of SUBSTREAM with MODE) (replace SPPSUBSTREAM of CON with SUBSTREAM) (replace SPPATTENTIONFN of CON with (FUNCTION \COURIER.ATTENTIONFN)) (COND (COURIERTRACEFLG (\COURIER.TRACE (QUOTE BEGIN.BULK.DATA) PROGRAM PROCEDURE))) (SPP.DSTYPE SUBSTREAM \SPPDSTYPE.BULKDATA) (RETURN SUBSTREAM)))) (\COURIER.ATTENTIONFN (LAMBDA (STREAM BYTE DSTYPE) (* bvm: "12-Oct-84 16:16") (* * Called when attention packet received on input STREAM. If we are currently writing bulkdata, this is an abort, so arrange to kill the writer) (PROG (CON) (RETURN (COND ((AND (EQ BYTE 1) (EQ DSTYPE \SPPDSTYPE.BULKDATA)) (* Bulk data stream truncation signal) (COND ((AND (SETQ CON (GETSPPCON STREAM)) (SETQ STREAM (fetch SPPSUBSTREAM of CON)) (WRITEABLE STREAM)) (replace SPPOUTPUTABORTEDFN of CON with (FUNCTION \COURIER.OUTPUT.ABORTED)) (replace SPPOUTPUTABORTEDP of CON with T))) (COND (NSWIZARDFLG (printout PROMPTWINDOW .TAB0 0 "[Remote host aborted data transfer]"))) T)))))) (\COURIER.OUTPUT.ABORTED (LAMBDA (OUTSTREAM) (* bvm: "12-Oct-84 17:54") (* Called when attempt is made to write data on OUTSTREAM when output has been aborted) (PROG (FILENAME CONTINUATION RESULT) (COND ((AND (SETQ CONTINUATION (fetch BULK.DATA.CONTINUATION of OUTSTREAM)) (NOT (fetch INTERNALFLG of CONTINUATION))) (* This was a standalone bulkdata stream) (SETQ RESULT (\BULK.DATA.CLOSE OUTSTREAM (QUOTE RETURNERRORS))) (COND ((AND (SETQ FILENAME (fetch FULLFILENAME of OUTSTREAM)) (EQ (CADDR RESULT) (QUOTE MediumFull))) (LISPERROR "FILE SYSTEM RESOURCES EXCEEDED" FILENAME)) (T (ERROR (CONCAT "Output aborted: " (CADR RESULT) " -- " (CADDR RESULT)) (OR FILENAME OUTSTREAM))))) (T (* Inside of \COURIER.HANDLE.BULKDATA) (ERROR!)))))) (\BULK.DATA.CLOSE [LAMBDA (STREAM ABORTFLG) (* bvm: "17-May-85 12:54") (* Close a Bulk Data stream after the transfer has taken place. If a result function was specified in COURIER.CALL, call it on the stream and the result or list of results.) (PROG ((CON (GETSPPCON STREAM)) (CONTINUATION (fetch BULK.DATA.CONTINUATION of STREAM))) (replace SPPATTENTIONFN of CON with NIL) (COND ((NULL (fetch SPPSUBSTREAM of CON)) (* This stream has already been closed. We don't want to try to read the Courier results twice) (RETURN))) [COND (COURIERTRACEFLG (\COURIER.TRACE (QUOTE END.BULK.DATA) (fetch PROGRAM of CONTINUATION) (fetch PROCEDURE of CONTINUATION] (COND [(WRITEABLE STREAM) (COND (ABORTFLG (SPP.SENDATTENTION STREAM 1)) (T (SPP.SENDEOM STREAM] ((NOT (\EOFP STREAM)) (* Closing before all the data has been read -- abort the transfer.) (OR ABORTFLG (SETQ ABORTFLG T)) (\ABORT.BULK.DATA STREAM))) (replace SPPINPKT of CON with NIL) (* This stream is closing; make sure there aren't any dangling pointers into the middle of ether packets.) (replace CBUFPTR of STREAM with NIL) (replace CBUFSIZE of STREAM with 0) (RETURN (CAR (ERSETQ (RESETLST (RESETSAVE NIL (LIST [FUNCTION (LAMBDA (CON) (replace SPPSUBSTREAM of CON with NIL) (COND (RESETSTATE (SPP.CLOSE (fetch SPPINPUTSTREAM of CON) T] CON)) (* The result of the Courier call may be an error which the user should see; however, we still need to clean up the substream, so we wrap it in this RESETLST.) (PROG ((COURIERSTREAM (fetch SPPINPUTSTREAM of CON))) [COND (ABORTFLG (RESETSAVE NIL (LIST [FUNCTION (LAMBDA (STREAM) (replace ENDOFSTREAMOP of STREAM with (FUNCTION \COURIER.EOF] COURIERSTREAM)) (replace ENDOFSTREAMOP of STREAM with (FUNCTION ERROR!] (RETURN (\COURIER.RESULTS COURIERSTREAM (fetch PROGRAM of CONTINUATION) (fetch PGMDEF of CONTINUATION) (fetch PROCEDURE of CONTINUATION) (fetch PROCDEF of CONTINUATION) (OR ABORTFLG (fetch NOERRORFLG of CONTINUATION]) (\ABORT.BULK.DATA (LAMBDA (STREAM) (* ejs: "18-Dec-84 17:32") (PROG (EPKT) (do (* Empty queue of waiting packets without blocking.) (replace COFFSET of STREAM with (fetch CBUFSIZE of STREAM)) repeatwhile (NOT (\SPP.PREPARE.INPUT STREAM 0))) (COND ((fetch SPPEOFP of STREAM) (* We've already received the last packet of the Bulk Data transfer.) ) (T (* Abort the bulk data stream by sending an Attention packet with a 1 in it. WARNING: if the EOM bit is set in this packet, the NS fileserver will crash.) (SPP.SENDATTENTION STREAM 1) (* (while (\SPP.PREPARE.INPUT STREAM SPP.USER.TIMEOUT) do (* Ignore any remaining bulk data packets -- there shouldn't be many if the other end is obeying the protocol.))) ))))) ) (DEFINEQ (COURIER.EXPEDITED.CALL (LAMBDA ARGS (* bvm: "16-Jul-84 15:39") (* * Like COURIER.CALL but tries to use "expedited" calls. The first two args are the address and socket# to talk to, rather than a single open Courier stream. Remaining args are identical. If expedited version fails, a regular courier call is executed. Bulk data is prohibited) (PROG ((ADDRESS (ARG ARGS 1)) (SOCKET# (ARG ARGS 2)) (PROGRAM (ARG ARGS 3)) (PROCEDURE (ARG ARGS 4)) #ARGS ARGLIST NOERRORFLG PGMDEF PROCDEF ARGTYPES) (SETQ PGMDEF (OR (\GET.COURIERPROGRAM PROGRAM) (ERROR "No such Courier program" PROGRAM))) (SETQ PROCDEF (\GET.COURIER.DEFINITION PROGRAM PROCEDURE (QUOTE PROCEDURES) PGMDEF)) (SETQ #ARGS (LENGTH (SETQ ARGTYPES (fetch (COURIERFN ARGS) of PROCDEF)))) (COND ((for TYPE in ARGTYPES thereis (OR (EQ TYPE (QUOTE BULK.DATA.SINK)) (EQ TYPE (QUOTE BULK.DATA.SOURCE)))) (ERROR "Can't transfer bulk data with expedited call" (CONS PROGRAM PROCEDURE)))) (OR (SELECTQ (IDIFFERENCE ARGS #ARGS) (4 (* Exactly right) T) (5 (* Extra arg is errorflg) (SELECTQ (SETQ NOERRORFLG (ARG ARGS (IPLUS #ARGS 5))) ((NOERROR RETURNERRORS T) T) NIL)) NIL) (ERROR "Wrong number of arguments to Courier procedure" (CONS PROGRAM PROCEDURE))) (SETQ ARGLIST (for I from 5 to (IPLUS #ARGS 4) collect (ARG ARGS I))) (RETURN (COURIER.EXECUTE.EXPEDITED.CALL ADDRESS SOCKET# PROGRAM PGMDEF PROCEDURE PROCDEF ARGLIST ARGTYPES NOERRORFLG))))) (COURIER.EXECUTE.EXPEDITED.CALL (LAMBDA (ADDRESS SOCKET# PROGRAM PGMDEF PROCEDURE PROCDEF ARGLIST ARGTYPES NOERRORFLG) (* bvm: "27-Jun-84 12:59") (* * Attempts the actual expedited call) (COND (COURIERTRACEFLG (\COURIER.TRACE (QUOTE CALL) PROGRAM PROCEDURE ARGLIST))) (RESETLST (PROG ((NSOC (OPENNSOCKET)) XIP STREAM RESULT) (RESETSAVE NIL (LIST (QUOTE CLOSENSOCKET) NSOC)) (SETQ XIP (CREATE.PACKET.EXCHANGE.XIP NSOC ADDRESS SOCKET# \EXTYPE.EXPEDITED.COURIER)) (OR (\BUILD.EXPEDITED.XIP XIP PROGRAM PGMDEF PROCDEF ARGLIST ARGTYPES) (GO USECOURIER)) (COND ((NEQ (SETQ RESULT (\SEND.EXPEDITED.XIP XIP NSOC PROGRAM PGMDEF PROCEDURE PROCDEF NOERRORFLG)) (QUOTE USE.COURIER)) (RETURN RESULT))) USECOURIER (RETURN (COND ((SETQ STREAM (COURIER.OPEN ADDRESS NIL NOERRORFLG (QUOTE COURIER))) (* Use regular courier) (RESETSAVE NIL (LIST (FUNCTION \SPP.RESETCLOSE) STREAM)) (COURIER.EXECUTE.CALL STREAM PROGRAM PGMDEF PROCEDURE PROCDEF ARGLIST ARGTYPES NOERRORFLG)))))))) (\BUILD.EXPEDITED.XIP (LAMBDA (XIP PROGRAM PGMDEF PROCDEF ARGLIST) (* bvm: " 4-Jul-84 15:41") (PROG (STREAM) (replace (EXPEDITEDXIP LOWVERSION) of XIP with (replace (EXPEDITEDXIP HIGHVERSION) of XIP with (COURIER.VERSION#))) (replace (EXPEDITEDXIP MSGTYPE) of XIP with \COURIERMSG.CALL) (replace (EXPEDITEDXIP TRANSACTIONID) of XIP with 0) (* Transaction ID, ignored for now.) (replace (EXPEDITEDXIP PROGRAM#) of XIP with (fetch (COURIERPGM PROGRAM#) of PGMDEF)) (replace (EXPEDITEDXIP VERSION#) of XIP with (fetch (COURIERPGM VERSION#) of PGMDEF)) (replace (EXPEDITEDXIP PROCEDURE#) of XIP with (fetch (COURIERFN FN#) of PROCDEF)) (replace XIPLENGTH of XIP with (COND (ARGLIST (SETQ STREAM (\MAKE.EXPEDITED.STREAM XIP (QUOTE OUTPUT))) (OR (\COURIER.EXPEDITED.ARGS STREAM PROGRAM ARGLIST (fetch (COURIERFN ARGS) of PROCDEF)) (RETURN)) (fetch COFFSET of STREAM)) (T (IPLUS \XIPOVLEN (UNFOLD (IPLUS 3 (INDEXF (fetch (EXPEDITEDXIP ARG0) of T))) BYTESPERWORD))))) (RETURN XIP)))) (\SEND.EXPEDITED.XIP [LAMBDA (XIP NSOC PROGRAM PGMDEF PROCEDURE PROCDEF NOERRORFLG #TRIES) (* bvm: " 5-Feb-85 18:26") (* * Sends XIP, which is in the form of an expedited courier call, and awaits a response on NSOC. The call is to PROCEDURE of PROGRAM. If there is no response, or the remote element responds with the USE.COURIER error, returns USE.COURIER else the actual result (which could be NIL)) (bind (TIMER ←(SETUPTIMER 0)) (EVENT ←(NSOCKETEVENT NSOC)) (ID ←(fetch PACKETEXCHANGEID of XIP)) IXIP to (OR #TRIES \MAXETHERTRIES) do (SENDXIP NSOC XIP) (SETUPTIMER \ETHERTIMEOUT TIMER) [SELECTQ (until (TIMEREXPIRED? TIMER) when (PROGN (AWAIT.EVENT EVENT TIMER T) (SETQ IXIP (GETXIP NSOC))) do (SELECTC (fetch XIPTYPE of IXIP) [\XIPT.EXCHANGE (COND ((AND (IEQP (fetch PACKETEXCHANGEID of IXIP) ID) (ILEQ (fetch (EXPEDITEDXIP LOWVERSION) of IXIP) (COURIER.VERSION#)) (IGEQ (fetch (EXPEDITEDXIP HIGHVERSION) of IXIP) (COURIER.VERSION#)) (SELECTC (fetch (EXPEDITEDXIP MSGTYPE) of IXIP) ((LIST \COURIERMSG.RETURN \COURIERMSG.REJECT \COURIERMSG.ABORT) T) NIL)) (RETURN T] [\XIPT.ERROR (COND ((EQ (fetch ERRORXIPCODE of IXIP) \XIPE.NOSOCKET) (* Not responding to calls on this socket) (RELEASE.XIP IXIP) (RETURN (QUOTE USE.COURIER] NIL) (RELEASE.XIP IXIP)) (USE.COURIER (RETURN (QUOTE USE.COURIER))) (NIL (* Keep trying)) (RETURN (PROG1 (\COURIER.RESULTS (\MAKE.EXPEDITED.STREAM IXIP (QUOTE INPUT)) PROGRAM PGMDEF PROCEDURE PROCDEF NOERRORFLG T) (RELEASE.XIP IXIP] finally (RETURN (QUOTE USE.COURIER]) (\COURIER.EXPEDITED.ARGS (LAMBDA (STREAM PROGRAM ARGLIST ARGTYPES) (* bvm: "15-Jun-84 12:00") (* * Store the args for an expedited call into packet addressed by STREAM. Returns T on success. Failure is indicated by a RETFROM this fn with value NIL) (for VALUE in ARGLIST as TYPE in ARGTYPES do (COURIER.WRITE STREAM VALUE PROGRAM TYPE)) T)) (\MAKE.EXPEDITED.STREAM (LAMBDA (XIP ACCESS OSTREAM) (* bvm: "27-Jun-84 11:07") (* * Makes a STREAM to access the contents of XIP as an expedited courier message body. We use the BASEBYTES device for simplicity. All the operations we actually need are BIN, BOUT, BLOCKIN and BLOCKOUT) (PROG ((STREAM (OR OSTREAM (NCREATE (QUOTE STREAM)))) END) (replace DEVICE of STREAM with \BASEBYTESDEVICE) (replace ACCESS of STREAM with ACCESS) (replace CBUFPTR of STREAM with (fetch (XIP XIPBASE) of XIP)) (replace COFFSET of STREAM with (IPLUS \XIPOVLEN (UNFOLD 3 BYTESPERWORD) (COND ((EQ ACCESS (QUOTE INPUT)) (* For COURIER.RESULTS) (SETQ END (fetch XIPLENGTH of XIP)) (UNFOLD (INDEXF (fetch (EXPEDITEDXIP MSGTYPE) of T)) BYTESPERWORD)) (T (* For COURIER.EXPEDITED.ARGS) (SETQ END (IPLUS \MAX.XIPDATALENGTH \XIPOVLEN)) (UNFOLD (INDEXF (fetch (EXPEDITEDXIP ARG0) of T)) BYTESPERWORD))))) (replace EOFFSET of STREAM with (replace CBUFSIZE of STREAM with END)) (COND ((EQ ACCESS (QUOTE INPUT)) (* Will cause error if COURIER.RESULTS tries to read more than was sent -- should never happen) (replace ENDOFSTREAMOP of STREAM with (FUNCTION \COURIER.EOF))) (T (* Invoked if COURIER.EXPEDITED.ARGS tries to write more than will fit in the packet) (replace (BASEBYTESTREAM WRITEXTENSIONFN) of STREAM with (FUNCTION \COURIER.EXPEDITED.OVERFLOW)))) (RETURN STREAM)))) (\COURIER.EOF (LAMBDA (STREAM) (* bvm: "15-Jun-84 11:56") (* * Called if we attempt to read beyond the end of a courier response) (ERROR "Unexpected end of stream while reading Courier response"))) (\COURIER.EXPEDITED.OVERFLOW (LAMBDA (STREAM) (* bvm: " 4-Jul-84 15:41") (* * Called when \COURIER.EXPEDITED.ARGS tries to write beyond the end of the packet) (COND (NSWIZARDFLG (printout PROMPTWINDOW T "[Expedited call did not fit in one packet]"))) (RETFROM (FUNCTION \COURIER.EXPEDITED.ARGS) NIL))) ) (DEFINEQ (COURIER.BROADCAST.CALL (LAMBDA (DESTSOCKET# PROGRAM PROCEDURE ARGS RESULTFN NETHINT MESSAGE) (* bvm: "16-Jul-84 15:39") (* Performs expanding ring broadcast for Courier PROCEDURE applied to ARGS. If RESULTFN is given, it is applied to the results of the courier call, and its result is returned, unless it is NIL, in which case the broadcast continues. NETHINT is a net or list of nets that are expected to have the desired server. If omitted, or if no server on those nets responds, broadcast starts with the connected net and expands outward) (RESETLST (PROG ((PGMDEF (OR (\GET.COURIERPROGRAM PROGRAM) (ERROR "No such Courier program" PROGRAM))) PROCDEF SKT EPKT ROUTINGTABLE RESULT NEARBYNETS) (DECLARE (SPECVARS NEARBYNETS)) (* For \MAP.ROUTING.TABLE) (SETQ PROCDEF (\GET.COURIER.DEFINITION PROGRAM PROCEDURE (QUOTE PROCEDURES) PGMDEF)) (RESETSAVE NIL (LIST (QUOTE CLOSENSOCKET) (SETQ SKT (OPENNSOCKET)))) (SETQ EPKT (CREATE.PACKET.EXCHANGE.XIP SKT BROADCASTNSHOSTNUMBER DESTSOCKET# \EXTYPE.EXPEDITED.COURIER)) (OR (\BUILD.EXPEDITED.XIP EPKT PROGRAM PGMDEF PROCDEF ARGS) (ERROR "Could not build broadcast for servers packet" (CONS PROGRAM PROCEDURE) )) (COND ((COND ((NOT NETHINT) NIL) ((FIXP NETHINT) (SETQ RESULT (\COURIER.BROADCAST.ON.NET NETHINT SKT EPKT PROGRAM PGMDEF PROCEDURE PROCDEF RESULTFN MESSAGE))) ((LISTP NETHINT) (for NET in NETHINT thereis (SETQ RESULT (\COURIER.BROADCAST.ON.NET NET SKT EPKT PROGRAM PGMDEF PROCEDURE PROCDEF RESULTFN MESSAGE))))) (* Found server on hinted net) ) (T (SETQ NEARBYNETS (CONS)) (\MAP.ROUTING.TABLE \NS.ROUTING.TABLE (FUNCTION (LAMBDA (RT) (* Gather up info about what nets are nearby in order of hop count) (PROG ((HOPS (fetch (ROUTING RTHOPCOUNT) of RT))) (COND ((ILEQ HOPS 5) (for (TAIL ← NEARBYNETS) while (AND (CDR TAIL) (ILESSP (CAR (CADR TAIL)) HOPS)) do (SETQ TAIL (CDR TAIL)) finally (push (CDR TAIL) (LIST HOPS (fetch (ROUTING RTNET#) of RT)))))))))) (COND ((OR (NULL (CDR NEARBYNETS)) (NEQ (CAR (CADR NEARBYNETS)) 0)) (* Include local net) (push (CDR NEARBYNETS) (LIST 0 0)))) (COND ((NOT (find PAIR in (CDR NEARBYNETS) suchthat (SETQ RESULT (\COURIER.BROADCAST.ON.NET (CADR PAIR) SKT EPKT PROGRAM PGMDEF PROCEDURE PROCDEF RESULTFN MESSAGE)))) (* Try once more, just in case we didn't wait long enough on the last guy. The previous tries overlapped each other, and we need to wait a bit to give the last one equal time) (SETQ RESULT (\COURIER.BROADCAST.ON.NET (CADR (CADR NEARBYNETS)) SKT EPKT PROGRAM PGMDEF PROCEDURE PROCDEF RESULTFN)))))) (RETURN RESULT))))) (\COURIER.BROADCAST.ON.NET (LAMBDA (NET NSOC XIP PROGRAM PGMDEF PROCEDURE PROCDEF RESULTFN MESSAGE) (* bvm: "27-Jun-84 14:38") (replace XIPDESTNET of XIP with NET) (COND (MESSAGE (printout PROMPTWINDOW .TAB0 0 "[Looking for " MESSAGE " on net " .I0.8 NET "]"))) (PROG ((RESULT (\SEND.EXPEDITED.XIP XIP NSOC PROGRAM PGMDEF PROCEDURE PROCDEF T 2))) (RETURN (COND ((EQ RESULT (QUOTE USE.COURIER)) NIL) (RESULTFN (APPLY* RESULTFN RESULT)) (T RESULT)))))) ) (DEFINEQ (COURIER.READ (LAMBDA (STREAM PROGRAM TYPE) (* bvm: "19-Jul-84 13:03") (PROG (X) (RETURN (COND ((LITATOM TYPE) (SELECTQ TYPE (BOOLEAN (NEQ 0 (GETWORD STREAM))) ((CARDINAL UNSPECIFIED) (GETWORD STREAM)) (INTEGER (SIGNED (GETWORD STREAM) BITSPERWORD)) ((LONGCARDINAL LONGINTEGER) (GETLONG STREAM)) (STRING (COURIER.READ.STRING STREAM)) (TIME (ALTO.TO.LISP.DATE (GETLONG STREAM))) (COND ((SETQ X (GETPROP TYPE (QUOTE COURIERDEF))) (* User-defined type) (APPLY* (CAR X) STREAM PROGRAM TYPE)) ((SETQ X (\GET.COURIER.TYPE PROGRAM TYPE)) (COURIER.READ STREAM PROGRAM X)) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))))) ((AND (LISTP TYPE) (LITATOM (CAR TYPE))) (SELECTQ (CAR TYPE) (ENUMERATION (bind (ITEM ←(GETWORD STREAM)) for DEF in (CDR TYPE) do (COND ((IEQP ITEM (CADR DEF)) (RETURN (CAR DEF)))) finally (RETURN ITEM))) (ARRAY (bind (BASETYPE ←(CADDR TYPE)) to (CADR TYPE) collect (COURIER.READ STREAM PROGRAM BASETYPE))) (SEQUENCE (* We ignore the maximum length of the sequence.) (COURIER.READ.SEQUENCE STREAM PROGRAM (OR (CADDR TYPE) (CADR TYPE)))) (RECORD (for NAMEANDTYPE in (CDR TYPE) collect (COURIER.READ STREAM PROGRAM (CADR NAMEANDTYPE)))) (NAMEDRECORD (* Expanded form for backward compatibility) (for NAMEANDTYPE in (CDR TYPE) collect (LIST (CAR NAMEANDTYPE) (COURIER.READ STREAM PROGRAM (CADR NAMEANDTYPE))))) (CHOICE (bind (WHICH ←(GETWORD STREAM)) for DEF in (CDR TYPE) do (* DEF = (tag choice# type); type = NIL is shorthand for type null record) (COND ((IEQP WHICH (CADR DEF)) (RETURN (CONS (CAR DEF) (AND (CADDR DEF) (LIST (COURIER.READ STREAM PROGRAM (CADDR DEF)))) )))) finally (RETURN (LIST WHICH (QUOTE ???))))) (COND ((LITATOM (CDR TYPE)) (* Qualified name) (COURIER.READ STREAM (CAR TYPE) (CDR TYPE))) ((SETQ X (GETPROP (CAR TYPE) (QUOTE COURIERDEF))) (APPLY* (CAR X) STREAM PROGRAM TYPE)) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))))) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))))))) (\COURIER.UNKNOWN.TYPE (LAMBDA (PROGRAM TYPE) (* bvm: "27-Jun-84 15:36") (ERROR "Unknown Courier Type" (COND (PROGRAM (CONS PROGRAM TYPE)) (T TYPE))))) (COURIER.READ.SEQUENCE (LAMBDA (STREAM PROGRAM BASETYPE) (* bvm: "27-Jun-84 15:16") (* * Reads a Courier SEQUENCE, returning it as a list of objects of type BASETYPE) (to (GETWORD STREAM) collect (COURIER.READ STREAM PROGRAM BASETYPE)))) (COURIER.READ.STRING (LAMBDA (STREAM) (* bvm: " 1-May-84 12:25") (PROG ((LENGTH (GETWORD STREAM)) STRING) (SETQ STRING (ALLOCSTRING LENGTH)) (\BINS STREAM (fetch (STRINGP BASE) of STRING) (fetch (STRINGP OFFST) of STRING) LENGTH) (COND ((ODDP LENGTH) (BIN STREAM))) (RETURN STRING)))) (COURIER.WRITE (LAMBDA (STREAM ITEM PROGRAM TYPE) (* bvm: "21-Jul-84 16:07") (PROG (X) (COND ((LITATOM TYPE) (SELECTQ TYPE (BOOLEAN (PUTWORD STREAM (COND (ITEM 1) (T 0)))) ((CARDINAL UNSPECIFIED) (PUTWORD STREAM ITEM)) (INTEGER (PUTWORD STREAM (UNSIGNED ITEM BITSPERWORD))) ((LONGCARDINAL LONGINTEGER) (PUTLONG STREAM ITEM)) (STRING (COURIER.WRITE.STRING STREAM ITEM)) (TIME (PUTLONG STREAM (LISP.TO.ALTO.DATE ITEM))) (COND ((SETQ X (GETPROP TYPE (QUOTE COURIERDEF))) (* User-defined type) (APPLY* (CADR X) STREAM ITEM PROGRAM TYPE)) ((SETQ X (\GET.COURIER.TYPE PROGRAM TYPE)) (COURIER.WRITE STREAM ITEM PROGRAM X)) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))))) ((AND (LISTP TYPE) (LITATOM (CAR TYPE))) (SELECTQ (CAR TYPE) (ENUMERATION (* Keys can be either atoms, for fast lookup, or strings, to save atom space) (PUTWORD STREAM (OR (CADR (OR (ASSOC ITEM (CDR TYPE)) (find X in (CDR TYPE) bind (KEY ←(MKSTRING ITEM)) suchthat (STREQUAL KEY (CAR X))))) (\COURIER.TYPE.ERROR ITEM (QUOTE ENUMERATION)) ))) (ARRAY (PROG ((SIZE (CADR TYPE)) (BASETYPE (CADDR TYPE))) (COND ((NOT (IEQP SIZE (LENGTH ITEM))) (\COURIER.TYPE.ERROR ITEM TYPE))) (for X in ITEM do (COURIER.WRITE STREAM X PROGRAM BASETYPE)))) (SEQUENCE (* We ignore the maximum length of the sequence.) (COURIER.WRITE.SEQUENCE STREAM ITEM PROGRAM (OR (CADDR TYPE) (CADR TYPE)))) (RECORD (for NAMEANDTYPE in (CDR TYPE) as VALUE in ITEM do (COURIER.WRITE STREAM VALUE PROGRAM (CADR NAMEANDTYPE)))) (NAMEDRECORD (* Old style) (for NAMEANDTYPE in (CDR TYPE) as NAMEANDVALUE in ITEM do (COND ((NEQ (CAR NAMEANDTYPE) (CAR NAMEANDVALUE)) (\COURIER.TYPE.ERROR ITEM (CAR TYPE)))) (COURIER.WRITE STREAM (CADR NAMEANDVALUE) PROGRAM (CADR NAMEANDTYPE)))) (CHOICE (PROG ((WHICH (OR (ASSOC (CAR ITEM) (CDR TYPE)) (\COURIER.TYPE.ERROR ITEM (QUOTE CHOICE))))) (PUTWORD STREAM (CADR WHICH)) (COND ((CADDR WHICH) (COURIER.WRITE STREAM (CADR ITEM) PROGRAM (CADDR WHICH)))))) (COND ((LITATOM (CDR TYPE)) (* Qualified name) (COURIER.WRITE STREAM ITEM (CAR TYPE) (CDR TYPE))) ((SETQ X (GETPROP (CAR TYPE) (QUOTE COURIERDEF))) (* User-defined type) (APPLY* (CADR X) STREAM ITEM PROGRAM TYPE)) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))))) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE)))))) (COURIER.WRITE.SEQUENCE (LAMBDA (STREAM ITEMLIST PROGRAM TYPE) (* bvm: " 4-Jul-84 15:13") (PROG ((BASETYPE TYPE)) (COND ((EQ (CAR (LISTP ITEMLIST)) (QUOTE INTERPRETATION)) (* This is how to write a (SEQUENCE UNSPECIFIED) without running it through COURIER.WRITE.REP first. ITEMLIST = (INTERPRETATION type value)) (COND ((NEQ BASETYPE (QUOTE UNSPECIFIED)) (\COURIER.TYPE.ERROR ITEMLIST TYPE)) (T (SETQ BASETYPE (CADR ITEMLIST)) (COURIER.WRITE.SEQUENCE.UNSPECIFIED STREAM (CADDR ITEMLIST) (COND ((LISTP BASETYPE) (PROG1 (CAR BASETYPE) (SETQ BASETYPE (CDR BASETYPE)))) (T PROGRAM)) BASETYPE)))) ((NULL ITEMLIST) (PUTWORD STREAM 0)) ((LISTP ITEMLIST) (PUTWORD STREAM (LENGTH ITEMLIST)) (for X in ITEMLIST do (COURIER.WRITE STREAM X PROGRAM BASETYPE))) (T (\COURIER.TYPE.ERROR ITEMLIST TYPE)))))) (COURIER.WRITE.STRING (LAMBDA (STREAM STRING) (* bvm: "12-Jun-84 11:23") (PROG ((LENGTH (NCHARS (OR (STRINGP STRING) (SETQ STRING (MKSTRING STRING)))))) (PUTWORD STREAM LENGTH) (\BOUTS STREAM (fetch (STRINGP BASE) of STRING) (fetch (STRINGP OFFST) of STRING) LENGTH) (COND ((ODDP LENGTH) (BOUT STREAM 0)))))) (\COURIER.TYPE.ERROR (LAMBDA (ITEM TYPE) (* bvm: " 3-Jul-84 17:53") (ERROR (CONCAT "Arg not of Courier type " TYPE) ITEM))) ) (DEFINEQ (COURIER.READ.BULKDATA [LAMBDA (STREAM PROGRAM TYPE DONTCLOSE) (* bvm: "13-Feb-85 23:42") (* Read a Bulk Data object which is a stream of the specified type. This can be done by declaring the stream type in Courier, as is done in the protocol specs, but that causes COURIER.READ to produce a deeply nested structure. Instead, this function returns a list of objects making up the stream. See the Bulk Data Transfer spec.) (* * Closes STREAM on exit unless DONTCLOSE is true. If STREAM is not a stream, returns it directly, presumably an error from COURIER.CALL) (COND [(type? STREAM STREAM) (PROG1 (bind LASTSEGMENT? join (PROGN (SETQ LASTSEGMENT? (NEQ (GETWORD STREAM) 0)) (COURIER.READ.SEQUENCE STREAM PROGRAM TYPE)) repeatuntil LASTSEGMENT?) (OR DONTCLOSE (CLOSEF STREAM] (T (* An error return from COURIER.CALL -- pass it thru) STREAM]) (BULKDATA.GENERATOR (LAMBDA (STREAM PROGRAM TYPE) (* bvm: "19-Jul-84 11:40") (* Produces a generator for reading from STREAM a Courier "Stream of PROGRAM.TYPE". The value returned from this function is an object to pass to BULKDATA.GENERATE.NEXT to retrieve the next item from the stream.) (create BULKDATAGENERATOR BGSTREAM ← STREAM BGPROGRAM ← PROGRAM BGTYPE ← TYPE BGLASTSEGMENT? ← NIL BGITEMSLEFT ← 0))) (BULKDATA.GENERATE.NEXT (LAMBDA (GENSTATE) (* bvm: "19-Jul-84 11:34") (* Returns the next item from bulkdata generator GENSTATE, updating the state. Returns NIL when generator exhausted) (PROG ((STREAM (fetch BGSTREAM of GENSTATE)) (CNT (fetch BGITEMSLEFT of GENSTATE))) LP (COND ((NEQ CNT 0) (* Middle of a segment) (replace BGITEMSLEFT of GENSTATE with (SUB1 CNT))) ((fetch BGLASTSEGMENT? of GENSTATE) (* Finished last segment) (RETURN NIL)) (T (* Finished a segment, get the next) (COND ((NEQ (GETWORD STREAM) 0) (replace BGLASTSEGMENT? of GENSTATE with T))) (SETQ CNT (GETWORD STREAM)) (GO LP))) (RETURN (COURIER.READ STREAM (fetch BGPROGRAM of GENSTATE) (fetch BGTYPE of GENSTATE)))))) (COURIER.WRITE.BULKDATA (LAMBDA (STREAM ITEMLIST PROGRAM TYPE) (* bvm: " 4-Jul-84 15:24") (* Writes ITEMLIST as a Bulk Data object which is a stream of the specified type, i.e., ITEMLIST is interpreted as a list of (PROGRAM . TYPE) objects. Returns NIL) (* * Format a little strange: a succession of SEQUENCE's, the last of which is flagged as the final sequence. In theory, one could send the entire list, up to 65535 items, as a single sequence, but maybe that overloads some processors, so break it up into smaller chunks) (PROG ((LEN (LENGTH ITEMLIST)) (TAIL ITEMLIST) SEGMENTLENGTH) (do (PUTWORD STREAM (COND ((IGREATERP LEN 100) (* Don't try to write too long segments) (SETQ SEGMENTLENGTH 100) (* Not last segment) 0) (T (SETQ SEGMENTLENGTH LEN) 1))) (PUTWORD STREAM SEGMENTLENGTH) (to SEGMENTLENGTH do (COURIER.WRITE STREAM (pop TAIL) PROGRAM TYPE)) (SETQ LEN (IDIFFERENCE LEN SEGMENTLENGTH)) repeatwhile TAIL)))) ) (DEFINEQ (COURIER.READ.REP (LAMBDA (LIST.OF.WORDS PROGRAM TEMPLATE) (* bvm: "14-Jun-84 15:08") (* Like COURIER.READ but "reads" from a list of integers corresponding to the words in the Courier representation.) (COURIER.READ (\MAKE.COURIER.REP.STREAM LIST.OF.WORDS) PROGRAM TEMPLATE))) (COURIER.WRITE.REP (LAMBDA (VALUE PROGRAM TYPE) (* bvm: "14-Jun-84 16:15") (PROG ((STREAM (\MAKE.COURIER.REP.STREAM))) (COURIER.WRITE STREAM VALUE PROGRAM TYPE) (COND ((fetch CRNEXTBYTE of STREAM) (\BOUT STREAM 0))) (RETURN (fetch CRWORDLIST of STREAM))))) (COURIER.WRITE.SEQUENCE.UNSPECIFIED (LAMBDA (STREAM ITEM PROGRAM TYPE) (* bvm: "21-Jul-84 16:07") (* * Write ITEM on STREAM as a (SEQUENCE UNSPECIFIED) interpreted as a (PROGRAM . TYPE); this means figuring out how long ITEM is so we can write the appropriate word count before sending ITEM) (PROG (X FN) (COND ((LITATOM TYPE) (SELECTQ TYPE (BOOLEAN (PUTWORD STREAM 1) (PUTWORD STREAM (COND (ITEM 1) (T 0)))) ((CARDINAL UNSPECIFIED) (PUTWORD STREAM 1) (PUTWORD STREAM ITEM)) (INTEGER (PUTWORD STREAM 1) (PUTWORD STREAM (UNSIGNED ITEM BITSPERWORD))) ((LONGCARDINAL LONGINTEGER) (PUTWORD STREAM 2) (PUTLONG STREAM ITEM)) (STRING (PROG ((LENGTH (NCHARS (OR (STRINGP ITEM) (SETQ ITEM (MKSTRING ITEM)))))) (PUTWORD STREAM (ADD1 (FOLDHI LENGTH BYTESPERWORD))) (PUTWORD STREAM LENGTH) (\BOUTS STREAM (fetch (STRINGP BASE) of ITEM) (fetch (STRINGP OFFST) of ITEM) LENGTH) (COND ((ODDP LENGTH) (BOUT STREAM 0))))) (TIME (PUTWORD STREAM 2) (PUTLONG STREAM (LISP.TO.ALTO.DATE ITEM))) (COND ((SETQ X (GETPROP TYPE (QUOTE COURIERDEF))) (* User-defined type) (GO USERTYPE)) ((SETQ X (\GET.COURIER.TYPE PROGRAM TYPE)) (COURIER.WRITE.SEQUENCE.UNSPECIFIED STREAM ITEM PROGRAM X)) (T (\CWSU.DEFAULT STREAM ITEM PROGRAM TYPE))))) ((AND (LISTP TYPE) (LITATOM (CAR TYPE))) (SELECTQ (CAR TYPE) (ENUMERATION (PUTWORD STREAM 1) (COURIER.WRITE STREAM ITEM PROGRAM TYPE)) ((ARRAY SEQUENCE RECORD NAMEDRECORD CHOICE) (PROG ((LENGTH (COURIER.REP.LENGTH ITEM PROGRAM TYPE))) (COND (LENGTH (PUTWORD STREAM LENGTH) (COURIER.WRITE STREAM ITEM PROGRAM TYPE)) (T (\CWSU.DEFAULT STREAM ITEM PROGRAM TYPE))))) (COND ((LITATOM (CDR TYPE)) (* Qualified name) (COURIER.WRITE.SEQUENCE.UNSPECIFIED STREAM ITEM (CAR TYPE) (CDR TYPE))) ((SETQ X (GETPROP (CAR TYPE) (QUOTE COURIERDEF))) (* User-defined type) (GO USERTYPE)) (T (\CWSU.DEFAULT STREAM ITEM PROGRAM TYPE))))) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))) (RETURN) USERTYPE (* X = (readFn writeFn lengthFn writeSequenceFn)) (COND ((SETQ FN (CADDDR X)) (APPLY* FN STREAM ITEM PROGRAM TYPE)) ((AND (SETQ FN (CADDR X)) (OR (FIXP FN) (SETQ FN (APPLY* FN ITEM PROGRAM TYPE)))) (* Says how long it is) (PUTWORD STREAM FN) (APPLY* (CADR X) STREAM ITEM PROGRAM TYPE)) (T (\CWSU.DEFAULT STREAM ITEM PROGRAM TYPE)))))) (\CWSU.DEFAULT (LAMBDA (STREAM ITEM PROGRAM TYPE) (* bvm: " 1-Jul-84 18:05") (COURIER.WRITE STREAM (COURIER.WRITE.REP ITEM PROGRAM TYPE) NIL (QUOTE (SEQUENCE UNSPECIFIED))))) (COURIER.REP.LENGTH (LAMBDA (ITEM PROGRAM TYPE) (* bvm: " 3-Jul-84 17:37") (* * Returns the number of words that the Courier rep of ITEM as a (PROGRAM . TYPE) would occupy or NIL if we can't easily figure it out) (PROG (X) (RETURN (COND ((LITATOM TYPE) (SELECTQ TYPE ((BOOLEAN CARDINAL INTEGER UNSPECIFIED) 1) ((LONGCARDINAL LONGINTEGER TIME) 2) (STRING (ADD1 (FOLDHI (NCHARS ITEM) BYTESPERWORD))) (COND ((SETQ X (GETPROP TYPE (QUOTE COURIERDEF))) (* User-defined type) (AND (SETQ X (CADDR X)) (OR (FIXP X) (APPLY* X ITEM PROGRAM TYPE)))) ((SETQ X (\GET.COURIER.TYPE PROGRAM TYPE)) (COURIER.REP.LENGTH ITEM PROGRAM X))))) ((AND (LISTP TYPE) (LITATOM (CAR TYPE))) (SELECTQ (CAR TYPE) (ENUMERATION 1) (ARRAY (for X in ITEM bind (BASETYPE ←(CADDR TYPE)) sum (OR (COURIER.REP.LENGTH X PROGRAM BASETYPE) (RETURN)))) (SEQUENCE (for X in ITEM bind (BASETYPE ←(OR (CADDR TYPE) (CADR TYPE))) sum (OR (COURIER.REP.LENGTH X PROGRAM BASETYPE) (RETURN)) finally (* Count the word which is the sequence length) (RETURN (ADD1 $$VAL)))) (RECORD (for NAMEANDTYPE in (CDR TYPE) as VALUE in ITEM do (OR (COURIER.REP.LENGTH VALUE PROGRAM (CADR NAMEANDTYPE)) (RETURN)))) (NAMEDRECORD (for NAMEANDTYPE in (CDR TYPE) as NAMEANDVALUE in ITEM do (OR (COURIER.REP.LENGTH (CADR NAMEANDVALUE) PROGRAM (CADR NAMEANDTYPE)) (RETURN)))) (CHOICE (PROG ((WHICH (OR (ASSOC (CAR ITEM) (CDR TYPE)) (\COURIER.TYPE.ERROR ITEM (QUOTE CHOICE)))) N) (RETURN (COND ((SETQ N (COND ((CADDR WHICH) (COURIER.REP.LENGTH (CADR ITEM) PROGRAM (CADDR WHICH))) (T 0))) (ADD1 N)))))) (COND ((LITATOM (CDR TYPE)) (* Qualified name) (COURIER.REP.LENGTH ITEM (CAR TYPE) (CDR TYPE))) ((SETQ X (GETPROP (CAR TYPE) (QUOTE COURIERDEF))) (* User-defined type) (AND (SETQ X (CADDR X)) (OR (FIXP X) (APPLY* X ITEM PROGRAM TYPE))))))) (T (\COURIER.UNKNOWN.TYPE PROGRAM TYPE))))))) (\MAKE.COURIER.REP.STREAM (LAMBDA (LIST.OF.WORDS) (* bvm: "15-Jun-84 11:54") (* * Makes a STREAM whose BIN operation produces bytes from LIST.OF.WORDS or whose BOUT operation produces a list of words in the stream's CRWORDLIST field (can only use stream for one or the other, of course)) (PROG ((STREAM (NCREATE (QUOTE STREAM)))) (replace DEVICE of STREAM with (OR \COURIER.REP.DEVICE (PROGN (SETQ \COURIER.REP.DEVICE (NCREATE (QUOTE FDEV))) (replace BLOCKIN of \COURIER.REP.DEVICE with (FUNCTION \NONPAGEDBINS)) (replace BLOCKOUT of \COURIER.REP.DEVICE with (FUNCTION \NONPAGEDBOUTS)) \COURIER.REP.DEVICE))) (replace ACCESSBITS of STREAM with BothBits) (replace STRMBINFN of STREAM with (FUNCTION \COURIER.REP.BIN)) (replace STRMBOUTFN of STREAM with (FUNCTION \COURIER.REP.BOUT)) (replace ENDOFSTREAMOP of STREAM with (FUNCTION \COURIER.EOF)) (replace CRWORDLIST of STREAM with LIST.OF.WORDS) (RETURN STREAM)))) (\COURIER.REP.BIN (LAMBDA (STREAM) (* bvm: "14-Jun-84 16:06") (PROG ((X (fetch CRNEXTBYTE of STREAM))) (RETURN (COND (X (replace CRNEXTBYTE of STREAM with NIL) X) (T (SETQ X (OR (pop (fetch CRWORDLIST of STREAM)) (ERROR "Courier stream prematurely terminated"))) (replace CRNEXTBYTE of STREAM with (fetch LOBYTE of X)) (fetch HIBYTE of X))))))) (\COURIER.REP.BOUT (LAMBDA (STREAM BYTE) (* bvm: "14-Jun-84 16:13") (PROG ((X (fetch CRNEXTBYTE of STREAM)) TAIL) (COND (X (SETQ X (create WORD HIBYTE ← X LOBYTE ← BYTE)) (replace CRLASTWORD of STREAM with (COND ((SETQ TAIL (fetch CRLASTWORD of STREAM)) (CDR (RPLACD TAIL (CONS X)))) (T (replace CRWORDLIST of STREAM with (LIST X))))) (replace CRNEXTBYTE of STREAM with NIL)) (T (replace CRNEXTBYTE of STREAM with BYTE)))))) ) (DEFINEQ (COURIER.READ.NSADDRESS (LAMBDA (STREAM) (* bvm: "12-Jun-84 11:41") (* Read a standard NSADDRESS from the next 6 words of STREAM) (PROG ((ADDR (create NSADDRESS))) (\BINS STREAM ADDR 0 (UNFOLD \#WDS.NSADDRESS BYTESPERWORD)) (RETURN ADDR)))) (COURIER.WRITE.NSADDRESS (LAMBDA (STREAM ADDR) (* bvm: "12-Jun-84 11:45") (\BOUTS STREAM (\DTEST ADDR (QUOTE NSADDRESS)) 0 (UNFOLD \#WDS.NSADDRESS BYTESPERWORD)))) ) (PUTPROPS NSADDRESS COURIERDEF (COURIER.READ.NSADDRESS COURIER.WRITE.NSADDRESS 6)) (* Debugging) (RPAQ? COURIERTRACEFILE ) (RPAQ? COURIERTRACEFLG ) (RPAQ? COURIERPRINTLEVEL (QUOTE (2 . 4))) (RPAQ? NSWIZARDFLG ) (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS COURIERTRACEFLG COURIERTRACEFILE COURIERPRINTLEVEL NSWIZARDFLG) ) (DEFINEQ (COURIERTRACE (LAMBDA (FLG REGION) (* ecc " 4-AUG-83 15:13") (if (NULL FLG) then (if (ACTIVEWP COURIERTRACEFILE) then (CLOSEW COURIERTRACEFILE)) (SETQ COURIERTRACEFILE T) (SETQ COURIERTRACEFLG NIL) else (if (NOT (ACTIVEWP COURIERTRACEFILE)) then (SETQ COURIERTRACEFILE (CREATEW REGION "Courier Trace Window"))) (WINDOWPROP COURIERTRACEFILE (QUOTE BUTTONEVENTFN) (FUNCTION (LAMBDA (WINDOW) (if (LASTMOUSESTATE (NOT UP)) then (\CHANGE.ETHER.TRACING WINDOW (QUOTE COURIERTRACEFLG)))))) (WINDOWPROP COURIERTRACEFILE (QUOTE CLOSEFN) (FUNCTION (LAMBDA (WINDOW) (if (EQ WINDOW COURIERTRACEFILE) then (SETQ COURIERTRACEFLG NIL) (SETQ COURIERTRACEFILE T))))) (DSPFONT (FONTCREATE (QUOTE GACHA) 8) COURIERTRACEFILE) (SETQ COURIERTRACEFLG FLG) (DSPSCROLL T COURIERTRACEFILE) (TOTOPW COURIERTRACEFILE) COURIERTRACEFILE))) (\COURIER.TRACE (LAMBDA (EVENT PROGRAM PROCEDURE ARGUMENTS) (* bvm: "22-Jun-84 17:16") (SELECTQ EVENT (CALL (printout COURIERTRACEFILE .TAB0 0 PROGRAM "." PROCEDURE "[") (COND (ARGUMENTS (COND ((EQ COURIERTRACEFLG (QUOTE PEEK)) (printout COURIERTRACEFILE (QUOTE --))) (T (for X in ARGUMENTS bind (FIRSTTIME ← T) do (COND (FIRSTTIME (SETQ FIRSTTIME NIL)) (T (SPACES 1 COURIERTRACEFILE))) (LVLPRIN2 X COURIERTRACEFILE (CAR COURIERPRINTLEVEL) (CDR COURIERPRINTLEVEL))))))) (printout COURIERTRACEFILE (QUOTE %]))) (RETURN (printout COURIERTRACEFILE " => ") (COND ((EQ COURIERTRACEFLG (QUOTE PEEK)) (printout COURIERTRACEFILE (COND ((CDR (LISTP ARGUMENTS)) (QUOTE --)) (T "&")))) (T (LVLPRINT ARGUMENTS COURIERTRACEFILE (CAR COURIERPRINTLEVEL) (CDR COURIERPRINTLEVEL))))) (BEGIN.BULK.DATA (printout COURIERTRACEFILE (COND ((EQ COURIERTRACEFLG (QUOTE PEEK)) (QUOTE {)) (T "{bulk data")))) (END.BULK.DATA (printout COURIERTRACEFILE (QUOTE }))) (SHOULDNT)))) ) (DECLARE: DONTEVAL@LOAD DOEVAL@COMPILE DONTCOPY COMPILERVARS (ADDTOVAR NLAMA \DUMP.COURIERPROGRAMS COURIERPROGRAM) (ADDTOVAR NLAML ) (ADDTOVAR LAMA COURIER.EXPEDITED.CALL COURIER.CALL) ) (PUTPROPS COURIER COPYRIGHT ("Xerox Corporation" 1983 1984 1985)) (DECLARE: DONTCOPY (FILEMAP (NIL (6154 14982 (COURIER.VERSION# 6164 . 6379) (COURIERPROGRAM 6381 . 6976) (\COURIER.PUTDEF 6978 . 7812) (\COURIER.CHECKDEF 7814 . 8563) (\COURIER.CHECK.PROCEDURES 8565 . 10469) ( \COURIER.CHECK.ERRORS 10471 . 11636) (\COURIER.DELDEF 11638 . 11849) (\COURIER.GETDEF 11851 . 12054) ( \GET.COURIERPROGRAM 12056 . 12216) (\DUMP.COURIERPROGRAMS 12218 . 13891) (\GET.COURIER.TYPE 13893 . 14091) (\GET.COURIER.DEFINITION 14093 . 14980)) (15616 18687 (\COURIER.RECORDTRAN 15626 . 18685)) ( 18742 39027 (COURIER.OPEN 18752 . 20679) (\COURIER.WHENCLOSED 20681 . 20929) (COURIER.CALL 20931 . 23604) (COURIER.EXECUTE.CALL 23606 . 25726) (\COURIER.RESULTS 25728 . 29334) (\COURIER.HANDLE.BULKDATA 29336 . 30496) (\COURIER.HANDLE.ERROR 30498 . 30774) (\BULK.DATA.STREAM 30776 . 32988) ( \COURIER.ATTENTIONFN 32990 . 33904) (\COURIER.OUTPUT.ABORTED 33906 . 35084) (\BULK.DATA.CLOSE 35086 . 37990) (\ABORT.BULK.DATA 37992 . 39025)) (39028 49287 (COURIER.EXPEDITED.CALL 39038 . 40988) ( COURIER.EXECUTE.EXPEDITED.CALL 40990 . 42376) (\BUILD.EXPEDITED.XIP 42378 . 43891) ( \SEND.EXPEDITED.XIP 43893 . 46146) (\COURIER.EXPEDITED.ARGS 46148 . 46571) (\MAKE.EXPEDITED.STREAM 46573 . 48601) (\COURIER.EOF 48603 . 48877) (\COURIER.EXPEDITED.OVERFLOW 48879 . 49285)) (49288 53662 (COURIER.BROADCAST.CALL 49298 . 53035) (\COURIER.BROADCAST.ON.NET 53037 . 53660)) (53663 62971 ( COURIER.READ 53673 . 56694) (\COURIER.UNKNOWN.TYPE 56696 . 56921) (COURIER.READ.SEQUENCE 56923 . 57228 ) (COURIER.READ.STRING 57230 . 57692) (COURIER.WRITE 57694 . 61160) (COURIER.WRITE.SEQUENCE 61162 . 62292) (COURIER.WRITE.STRING 62294 . 62779) (\COURIER.TYPE.ERROR 62781 . 62969)) (62972 66904 ( COURIER.READ.BULKDATA 62982 . 64067) (BULKDATA.GENERATOR 64069 . 64573) (BULKDATA.GENERATE.NEXT 64575 . 65727) (COURIER.WRITE.BULKDATA 65729 . 66902)) (66905 76745 (COURIER.READ.REP 66915 . 67334) ( COURIER.WRITE.REP 67336 . 67718) (COURIER.WRITE.SEQUENCE.UNSPECIFIED 67720 . 71028) (\CWSU.DEFAULT 71030 . 71264) (COURIER.REP.LENGTH 71266 . 74243) (\MAKE.COURIER.REP.STREAM 74245 . 75519) ( \COURIER.REP.BIN 75521 . 76061) (\COURIER.REP.BOUT 76063 . 76743)) (76746 77410 ( COURIER.READ.NSADDRESS 76756 . 77170) (COURIER.WRITE.NSADDRESS 77172 . 77408)) (77768 80264 ( COURIERTRACE 77778 . 78917) (\COURIER.TRACE 78919 . 80262))))) STOP