TITLE SPROUT -- Spooling PRocessor for OUTput - Version 4 SUBTTL D.A. Lewine - L.S. Samberg/PJT/DPM/NT/CTK 1-Mar-83 CSM01$==^D400 ;Plotter has 3 pens, ON-LINE indicator, 400 SPI CSM02$==-1 ;Compressed plot files CSM03$==-1 ;Red and Black in banner CSM04$==-1 ;Do CSM accounting (minutes and inches used) CSM05$==-1 ;Add SLEEP time to $DSCHD macro for TTY response wait CSM06$==^D1200 ;Support the TAB Products Card Terminal at 1200 baud CSM07$==-1 ;Change some QUEUE defaults CSM08$==^D2400 ;PTC-6 Plotter Terminal Controller at 2400 baud IF2,> IF2,> IF2,> REPEAT 0,< ;To completely remove the CSM changes, make this a REPEAT 1 CSM01$==0 ;Normal XY-10 plotter CSM02$==0 ;Plot files are 1 byte per increment (very big) CSM03$==0 ;Do not exercise the black and red pens CSM04$==0 ;Account disk reads instead of forms type CSM05$==0 ;No TTY I/O, therefore no sleep requests CSM06$==0 ;Card punch is on I/O bus or front-end 11 CSM07$==0 ;Use whatever QUEUE says CSM08$==0 ;Plotter is not connected to a TTY line DEFINE CSMEDT($EDIT,$PART),<> ;Dummy macro CSMED$==0 ;No additional edits > ;End of REPEAT 0 ; ; ; ; COPYRIGHT (c) 1975,1976,1977,1978,1979,1980,1981,1982 BY ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MA. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE ; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS ; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR ; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO ; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE ; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT ; BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY ; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY ; DIGITAL. PAGE SALL ;Also searches UUOSYM and ACTSYM.UNV SEARCH GLXMAC ;SEARCH GLXLIB SYMBOLS SEARCH QSRMAC ;GET QUASAR SYMBOLS SEARCH ORNMAC ;GET OPERATOR SYMBOLS PROLOGUE(SPROUT) ;DO STANDARD PROLOG IFNDEF CSMEDT,< SEARCH CSMEDT > ;CSM edit macro .XCREF S1,S2,T1,T2,T3,T4,C,J,P ;[CSM] Save some trees ;VERSION INFORMATION SPOVER==4 ;MAJOR VERSION NUMBER SPOMIN==0 ;MINOR VERSION NUMBER SPOEDT==2533 ;EDIT LEVEL SPOWHO==2 ;Who last patched (JMS @ CSM) %SPO==+CSMED$ ;STORE VERSION NUMBER IN JOBVER LOC 137 .JBVER:: EXP %SPO ;SPROUT VERSION RELOC 0 COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1971,1984. SUBTTL Table of Contents ; Table of Contents for SPROUT ; ; ; Section Page ; ; 1. Table of Contents . . . . . . . . . . . . . . . . . . 1 ; 2. Revision History . . . . . . . . . . . . . . . . . . . 2 ; 3. CSM Revision History . . . . . . . . . . . . . . . . . 2 ; 4. Constants (Conditional and Unconditional) . . . . . . 4 ; 5. MACROS . . . . . . . . . . . . . . . . . . . . . . . . 5 ; 6. Special Forms Handling Parameters . . . . . . . . . . 6 ; 7. Flag Definitions . . . . . . . . . . . . . . . . . . . 7 ; 8. Job Parameter Area . . . . . . . . . . . . . . . . . . 8 ; 9. Random Impure Storage . . . . . . . . . . . . . . . . 11 ; 10. Resident JOB DaTABase . . . . . . . . . . . . . . . . 12 ; 11. Non-zero daTABase . . . . . . . . . . . . . . . . . . 13 ; 12. $TEXT Utilities . . . . . . . . . . . . . . . . . . . 14 ; 13. Program Initialization . . . . . . . . . . . . . . . . 15 ; 14. Idle Loop . . . . . . . . . . . . . . . . . . . . . . 16 ; 15. Deschedule Process . . . . . . . . . . . . . . . . . . 17 ; 16. CHKTIM - Routine to see if it's time to schedule a s . 17 ; 17. Do the Job . . . . . . . . . . . . . . . . . . . . . . 18 ; 18. Process a File . . . . . . . . . . . . . . . . . . . . 19 ; 19. End of Job . . . . . . . . . . . . . . . . . . . . . . 20 ; 20. FILDIS . . . . . . . . . . . . . . . . . . . . . . . . 21 ; 21. CHKQUE . . . . . . . . . . . . . . . . . . . . . . . . 22 ; 22. CHKOBJ . . . . . . . . . . . . . . . . . . . . . . . . 23 ; 23. FNDOBJ . . . . . . . . . . . . . . . . . . . . . . . . 24 ; 24. GETBLK . . . . . . . . . . . . . . . . . . . . . . . . 25 ; 25. NEXTJOB Message from QUASAR . . . . . . . . . . . . . 26 ; 26. User CANCEL Request . . . . . . . . . . . . . . . . . 27 ; 27. UPDATE Routine to send status update . . . . . . . . . 28 ; 28. CHKPNT Routine to send checkpoint message . . . . . . 29 ; 29. SETUP/SHUTDOWN Message . . . . . . . . . . . . . . . . 30 ; 30. Response to setup message . . . . . . . . . . . . . . 31 ; 31. Operator CANCEL command . . . . . . . . . . . . . . . 32 ; 32. Operator STOP command . . . . . . . . . . . . . . . . 33 ; 33. Operator CONTINUE command . . . . . . . . . . . . . . 33 ; 34. Operator RESPONSE command . . . . . . . . . . . . . . 33 ; 35. Operator REQUEUE command . . . . . . . . . . . . . . . 34 ; 36. CLRMSG and SNDQSR routines . . . . . . . . . . . . . . 35 ; 37. FRMLEX - Forms limit exceeded routine . . . . . . . . 36 ; 38. Accounting routines . . . . . . . . . . . . . . . . . 37 ; 39. FORMS - Setup Forms for a job . . . . . . . . . . . . 40 ; 40. Forms switch Subroutines . . . . . . . . . . . . . . . 44 ; 41. Plotter only switches . . . . . . . . . . . . . . . . 45 ; 42. I/O Subroutines for SPFORM.INI . . . . . . . . . . . . 46 ; 43. INPOPN - Routine to open the input file . . . . . . . 48 ; 44. INPBUF - Read a buffer from the input file . . . . . . 49 ; 45. INPBYT - Read a byte from the input file . . . . . . . 49 ; 46. INPERR - Handle an input failure . . . . . . . . . . . 49 ; 47. INPFEF - Force end-of-file on next input . . . . . . . 49 ; 48. INPREW - Rewind the input file . . . . . . . . . . . . 49 ; 49. OUTGET - OPEN the output device . . . . . . . . . . . 49 ; 50. OUTBYT - Deposit a byte in the output buffer . . . . . 53 ; 51. OUTOUT - Routine to output a buffer . . . . . . . . . 53 ; 52. DEVERR - Handle Output Device Errors . . . . . . . . . 55 ; 53. OUTREL - Release output device . . . . . . . . . . . . 56 ; 54. OUTWON - Wait for on-line . . . . . . . . . . . . . . 57 ; 55. OUTFLS Routine to flush output buffers . . . . . . . . 58 ; 56. TTY I/O ; 56.1 Input character from TTY, no wait . . . . . . 59 ; 56.2 Input character, wait up to 30 seconds . . . . 60 ; 57. Card punch service ; 57.1 Dispatch table . . . . . . . . . . . . . . . . 61 ; 57.2 Checkpoint text generation . . . . . . . . . . 62 ; 57.3 File processing . . . . . . . . . . . . . . . 63 ; 57.4 File headers . . . . . . . . . . . . . . . . . 69 ; 57.5 File trailers . . . . . . . . . . . . . . . . 70 ; 57.6 Banners . . . . . . . . . . . . . . . . . . . 71 ; 57.7 Word punching . . . . . . . . . . . . . . . . 72 ; 57.8 Letters . . . . . . . . . . . . . . . . . . . 73 ; 57.9 Byte output . . . . . . . . . . . . . . . . . 74 ; 58. Plotter service ; 58.1 Dispatch table . . . . . . . . . . . . . . . . 75 ; 58.2 Checkpoint text generation . . . . . . . . . . 76 ; 58.3 File processing . . . . . . . . . . . . . . . 77 ; 58.4 Expand CSM's compressed plot format . . . . . 79 ; 58.5 READ36, OPRTXT, PAUSEP, TITLE for TOLP . . . . 81 ; 58.6 NEWPEN for 3-pen plotter . . . . . . . . . . . 82 ; 58.7 DEVOUT output errors . . . . . . . . . . . . . 83 ; 58.8 Banners . . . . . . . . . . . . . . . . . . . 84 ; 58.9 File headers . . . . . . . . . . . . . . . . . 85 ; 58.10 File trailers . . . . . . . . . . . . . . . . 86 ; 58.11 Job trailers . . . . . . . . . . . . . . . . . 87 ; 58.12 Solid lines . . . . . . . . . . . . . . . . . 88 ; 58.13 Dashed lines . . . . . . . . . . . . . . . . . 89 ; 58.14 Job information plotting . . . . . . . . . . . 90 ; 58.15 Alignment and testing . . . . . . . . . . . . 91 ; 58.16 Pen calibration . . . . . . . . . . . . . . . 92 ; 58.17 Compute character size . . . . . . . . . . . . 93 ; 58.18 Letters . . . . . . . . . . . . . . . . . . . 94 ; 58.19 Line segments . . . . . . . . . . . . . . . . 95 ; 58.20 PTC-6 interface . . . . . . . . . . . . . . . 97 ; 58.21 Rotation and XY20 translation . . . . . . . . 98 ; 58.22 Pen movement generation . . . . . . . . . . . 99 ; 58.23 Character set . . . . . . . . . . . . . . . . 101 ; 59. Paper tape punch service ; 59.1 Dispatch table . . . . . . . . . . . . . . . . 106 ; 59.2 Checkpoint text generation . . . . . . . . . . 107 ; 59.3 File processing . . . . . . . . . . . . . . . 108 ; 59.4 Banners . . . . . . . . . . . . . . . . . . . 113 ; 59.5 File headers . . . . . . . . . . . . . . . . . 114 ; 59.6 File trailers . . . . . . . . . . . . . . . . 115 ; 59.7 Trailers . . . . . . . . . . . . . . . . . . . 116 ; 59.8 Blank folds . . . . . . . . . . . . . . . . . 117 ; 59.9 Letters . . . . . . . . . . . . . . . . . . . 118 ; 59.10 Byte output . . . . . . . . . . . . . . . . . 119 ; 60. Character Bit Array for 5 X 7 Character Matrix . . . . 120 ; 61. Common Utilities . . . . . . . . . . . . . . . . . . . 122 ; 62. Interrupt Module . . . . . . . . . . . . . . . . . . . 124 ; 63. IPCF and DEVICE Interrupt service for TOPS10 . . . . . 128 ; 64. IPCF and DEVICE interrupt service for TOPS20 . . . . . 129 SUBTTL Revision History Comment\ 2000 First GALAXY-10 Field-Test release, June, 1975. 2100 Make this version 2, August, 1976. First field-test release of GALAXY release 2, Jan 1977 2400 MAKE THIS VERSION 4, APRIL 1977. (NOTE: RELEASE 3 OF GALAXY WAS TOPS20 ONLY AND DID NOT INCLUDE SPROUT) INSERT CHANGES FOR NEW FP/FD. 2401 START CONVERTING TO USE GLXLIB INSTEAD OF CSP??? AND SBS???. 2402 FIX UP AC CONVENTIONS TO BE COMPATIBLE WITH GLXLIB. 2403 MAKE SPROUT INTO A SINGLE SEGMENT AND DO A CODE CLEANUP. 2404 START MERGING IN GLXFIL USAGE FOR THE INPUT FILE. 2405 MORE OF 2404 AND START REPLACING LUUOS WITH $TEXTS. 2406 MAKE MORE USE OF $TEXT. 2407 MANY MINOR BUG FIXES AND CHANGES. 2410 SOME MAJOR CODE CLEANUP. 2411 START MAJOR RE-WORK OF SPROUT TO MAKE MORE USE OF GLXLIB AND TO TALK WITH THE NEW OPERATOR INTERFACE. 2412 CHANGE IMAGE MODE ON THE CDP TO IGNORE EACH 81ST BYTE READ FROM DISK SO THAT IT IS COMPATIBLE WITH SPRINT AND PIP. 2413 DONT ENFORCE LIMITS ON PTP AND PLT SINCE THE LIMITS ARE DIRECTLY DERIVABLE FROM THE FILE-SIZE. 2414 DO SOME CODE CLEANUP. 2415 Code Cleanup and add plotter and card letter routines 2416 Added Forms processing for SPFORM.INI File 2417 Added MSGFLG and Changed interrupt and Scheduling code to set/check msgflg for IPCF messages 2420 Added code to check length of message for DEP6BP and DEPBP 2421 Removed msgflg (twas a bad idea) 2422 Fixed OUTOUT and DEVERR for TOPS10 2423 Fixed ACTION operator message processing 2424 Fixed Offline device interrupt code 2425 Updated to new library and message formats 2426 Added preliminary accounting parameters Added two pass scheduling algorithm to allow mulitple devices to operate in parallel on TOPS20 2427 Fixed bug in INPOPN regarding access checks Moved impure interrupt stuff to impure storage Added call to I%HOST to get local node name 2430 Changed all message processing to use ac M Changed scheduling loop to WAIT instead of SLEEP when no jobs are scheduable 2431 Added correct mulitple stream runtime accounting code 2432 Put IB.PRG back into IB 2433 add Mount Bypass 2434 Add WTOR kill code (AWC) 2435 Fix a $TEXT bug - IQN Stopcode (AWC) 2436 Put in Null routines for TOPS10 accounting 2437 Fix Plotter Banner Header and Trailer code 2440 Add plotter limit check code 2441 MAKE 8 BIT PAPER TAPE OUTPUT BYTE SIZE 2442 Add usage accounting for TOPS-10 (DPM) 2443 Use new feature IB.DET to detach from FRCLIN (DPM) 2444 Delete IB.DET (GLXLIB defaults to detach) 2445 Change reference of symbol z to ZZ [QAR 10-04715] 2446 Add missing (S2) in DVINTR rouine [QAR 10-4903] 2447 Close SPFORM.INI before returning from FRMSWI [QAR 10-4855] 2450 Call OUTOUT after outputing trailers (SPR 20-14682) Make # chars per fanfold 85 not 90 (SPR 20-14680) Fix spelling error & FRMFD length error (SPR 20-14911) 2451 Get the correct owners name based on type of system. 2452 Fix OUTOUT so we don't loose output done interrupts 2453 Adjust J$XPOS and J$YPOS before clipping output per limits 2454 Always call file trailer routine during file processing 2455 Add support for /DISP:RENAME 2456 Account for X plotter usage 2457 Compute minimum character size (YMAX-YMIN)/90 2460 Have SPROUT generate own checkpoints 2461 Make cryptic error messages more explicit. 2462 Position pen at EOF before printing error message. General cleanup of job/file headers and trailers. 2463 Add missing entries in PLT dispatch table for /TAPE:BINARY. 2464 Add accounting support for the plotter. 2465 Don't do things like JRST .+3 2466 Remove edit 2456. Plotter usage is accounted for in minites, not amount of paper. 2467 Clear up /BANNER/HEADER/TRAILER problems with plotter. Edit 2457 made the switch arguments nearly useless. Don't allow arguments for the plotter. 2470 SPFORM.INI switch arguments were sometimes stored in half-words, and later full-word multiplies were done. That produces strange results in banners, headers and trailers. 2471 Remove /GUIDE, /ORIGIN and /SIZE switches from SPFORM.INI since they didn't work and it was unclear how they should work. Replace the "+" guide marks with a line across the paper. Always ram the pen into the stops prior to starting a new job instead of setting the origin where ever the operator left the pen. 2472 Remove SPFORM.INI switch defaulting since it could never work correctly for all switches all the time (some switches take multiple arguments). 2473 Remove TOPS-20 fork code since it never worked & will never be made to. 2474 Fix limit clipping so plots don't overwrite banners and trailers. 2475 If we get an I/O error on the plotter, complain but continue the job, since plotters aren't supposed to get output errors. 2476 Always clear PSF%DO (device off-line bit) when the operator issues a continue command. This can't hurt anything and will be a win while driving a PTP. The PTP gives only off-line interrupts, but no on-line interrupts. 2477 Add PTP accounting and fix up checkpoint messages a bit. 2500 Insure plotter trailers won't clip. 2501 Fix PTP banners, header and trailers so characters don't get mangled. 2502 Process /BANNER, /HEADER and /TRAILER switches for all devices like it is done for PLTs. Also, add NOTE:foo to CDP and PTP banners since they tell me it's documented that way. 2503 Fix problem with J$XLIM growing with every plot done. 2504 Use symbol FTFACT from GALGEN dialogue and remove references to FTOACT. 2505 Fix up CDP headers and trailers. 2506 Do both a status update and a checkpoint prior to asking about limit exceeded action. 2507 Don't call EOF routines twice. Remove extra call at FILE.2+ a few. 2510 Clean up /NOTE switch processing a bit. 2511 Fix bug in PTPBYT that caused S1 and S2 to get trashed. 2512 Default /SPU value to 1 if not set in SPFORM.INI 2513 Make sure T1 is set up before calling BLKFLD to punch blank folds off paper tape. 2514 Correct the calculation of the number of minutes of plotting time. 2515 Fix compiler errors on TOPS20 by putting TOPS10 refs under conditional 2516 Store sixbit device name on TOPS-20 so accounting doesn't get screwed up. Also accumulate the number of feet plotted. Clean up other assorted accounting bugs. 2517 Clean up TOPS-20 card banners, headers and trailers. 2520 Zap output buffer after doing SOUT. 2521 Clarify $WTOR responses as 'ABORT' or 'PROCEED' only. 2522 Fix UP-DOWN RIGHT-LEFT confusion. QAR 10-06785 2523 Add file name info to Cannot Access File message QAR 10-06759 2524 Correct checking for a null /NOTE switch. Terminate job banner text properly. Terminate note text with a NUL when processing job banners. Requeue reason text may never gets to the error buffer. Fix it. 2525 Fix logic bug in SPFORM.INI parsing. 2526 Fix some bad error messages. GCO: 1298 2527 Remove two extraneous intructions at the end of routine P$CHKS. GCO: 1319 2530 Fix a bug that would not allow plots to be output if /HEADER was not specified. GCO: 1320 2531 Several very trivial fixes which don't really deserve seperate edit numbers. 1) Put OUTSOK under TOPS-20 conditional since it's only needed for that system. 2) Remove some extraneous symbols: J$FMSP, FOB. Put FILNAM under TOPS20 conditional. 3) Fix OUTOUT on the -10 to not save S1/S2 if it is called from itself. GCO: 1341 2532 Fix a bug that keeps the last buffer from being output to the plotter. It may be an obscure monitor bug that has to be worked around. ;BEGIN CODE MEINTENANCE 2533 Fix bug in FILDIS. The /DELETE switch was improperly processed, when the job was ABORTED by OPR, the file was deleted. SPR 20-17944/CTK 1-MAR-83 End of revision history \ PAGE SUBTTL CSM Revision History ; ; Edit Date Who Description ;====== ========= === =========== ; ;CSM01$ 14-Nov-80 JMS Plotter has 3 pens and an ON-LINE indicator. Add ; routines to change pens and proper positioning after ; the plot. Make sure the plotter is on-line at OUTOUT. CSMEDT 01 ;Show value of CSM01$ INCS= ;400 increments per inch = 620 octal IFN CSM01$, ;Checkpoint every minute. ; ;CSM02$ 14-Nov-80 JMS Use the compressed plot file format as defined ; in PLOT.REL (from CSM's FORLIB). Instead of one ; byte per increment, most halfwords in the file ; contains 9-bits of delta-X and 9 of delta-Y. ; Use TOLP.REL to translate the disk file back ; into calls to subroutine PLOT. CSMEDT 02 ;Show value of CSM02$ IFN CSM02$,> ; ;CSM03$ 14-Nov-80 JMS Change the plot banner to exercise the red and ; black pens. Plot error message even if no ; /TRAILER and set blue pen at P$EOF. CSMEDT 03 ;Show value of CSM03$ ; ;CSM04$ 25-Mar-81 JMS Put the forms name in place of DISK-WRITES, ; amount of paper in PAGES-PRINTED, cards, feet, ; or plot time in DISK-READS. CSMEDT 04 ;Show value of CSM04$ ; ;CSM05$ 8-Jan-81 JMS Add a sleep request to $DSCHD. RH of flags is ; number of seconds to wait. This is needed for ; non-blocking TTY I/O routines. CSMEDT 05 ;Show value of CSM05$ ; ;CSM06$ 8-Jan-81 JMS Add support for the TAB Products Card Terminal. ; It is a Reader/Punch that acts like a TTY. CSMEDT 06 ;Show baud rate (^D1200=^O2260) IFN CSM06$,> ; ;CSM07$ 8-Mar-83 JMS Remove DSPMOD so that cards are punched in ASCII, ; paper tape is punched in ASCII, and plots are ; done in 18-bit BINARY mode unless explicitly ; requested otherwise. This is so that output ; from SOS or SED is not punched in image-binary. ; Remove "BEGIN:", "JOB", "jobnam", "USER:" from ; card punch banner, ignore QUEUE's default of ; /NOHEADER and always punch file header on cards. CSMEDT 07 ;Show value of CSM07$ ; ;CSM08$ 28-Jun-83 JMS Add support for the Houston Instruments PTC-6 ; Plotter Terminal Controller on a TTY line. CSMEDT 08 ;Show value of CSM08$ IFN CSM08$,< EXTERN PTCINI,PTCMOV,PTCOUT,PTCFIN IFE CSM05$,> ; CSMED$==10 ;Increment this to change .JBVER ;End of CSM Revision History SUBTTL Constants (Conditional and Unconditional) ;ACCUMULATORS M==12 ;MESSAGE ADDRESS S==13 ;STATUS FLAGS J==14 ;BASE ADDRESS OF CONTEXT DATA C==15 ;I/O CHARACTER E==16 ;POINTER TO CURRENT FP ;SYSTEM DEPENDENT PARAMETERS DEFINE FACT, SYSPRM PTPBSZ,^D36,^D8 ;OUTPUT BYTESIZE FOR PTP ;RANDOM CONSTANTS ND PDSIZE,100 ;SIZE OF PUSHDOWN LIST ND FACTSW,-1 ;-1 TO INCLUDE ACCOUNTING ND NSTRMS,5 ;NUMBER OF STREAMS ND ACCTSW,1 ;TURN ACCOUNTING ON/OFF ND TXT$LN,^D50 ;LENGTH OF JOB TEXT BUFFER ND ERR$LN,^D20 ;LENGTH OF JOB ERROR TEXT BUFFER ND NBFRS,2 ;NUMBER OF BUFFERS TO CREATE ND NJBPGS,3 ;NUMBER OF JOB PAGES TO CREATE ND CKPTIM,^D120 ;# of seconds between chkpnts XP MSBSIZ,50 ;SIZE OF A MESSAGE BLOCK ;CHECKPOINT BLOCK OFFSETS XP CKFIL,0 ;NUMBER OF FILES COMPLETED XP CKCOP,1 ;NUMBER OF COPIES COMPLETED XP CKPAG,2 ;NUMBER OF UNITS OF LAST COPY XP CKTPP,3 ;NUMBER OF TOTAL UNITS processed XP CKFLG,4 ;CHECKPOINT FLAGS XP CKFREQ,1B0 ;REQUED BY OPERATOR XP CKFCHK,1B1 ;JOB WAS CHECKPOINTED ;DEVICE DISPATCH TABLE OFFSETS XP DHEAD,0 ;ADDRESS OF FILE HEADER ROUTINE XP DTAIL,1 ;ADDRESS OF FILE TRAILER (EOF) ROUTINE XP DNAME,2 ;DEVICE GENERIC NAME IN 6BIT XP DBYTE,3 ;OUTPUT BYTE SIZE XP DPROC,4 ;ADDRESS OF FILE processing ROUTINE XP DBANN,5 ;ADDRESS OF JOB BANNER ROUTINE XP DEOJ,6 ;ADDRESS OF JOB TRAILER (EOJ) ROUTINE XP DLETR,7 ;ADDRESS OF CHARACTER processing ROUTINE XP DERR,10 ;ADDRESS OF ERROR HANDLER XP DACCT,11 ;ADDRESS OF END ACCOUTING ROUTINE XP DCHKP,12 ;ADDRESS OF CHECKPOINT TEXT ROUTINE CONT. (Constants) ;FORCE NEW LISTING PAGE ; Card punch constants ; XP CPC,^D80 ;CHARACTERS PER CARD ; Plotter constants ; COMMENT ~ From the OPERATOR's point of view, the supply spool on the plotter is above the pen holder, and the takeup spool is below the pen holder. Therefore, to move the pen in the +Y direction, the pen holder moves to the left. To move the pen in the +X direction, the pen stays still and the paper is moved down (towards the takeup spool). The following definitions are based on this point of view. ;End of COMMENT ~ XP PNUP,40 ;RAISE PEN XP PNDN,20 ;LOWER PEN XP PEN2,14 ;SELECT PEN 2 XP PEN3,03 ;SELECT PEN 3 XP CNGP,17 ;CHANGE PENS XP XYU,10 ;-X move the paper up XP XYD,4 ;+X move the paper down XP XYL,2 ;+Y move pen holder left XP XYR,1 ;-Y move pen holder right PLUSX== XYD ;[CSM] ;Move in positive X direction 0 PLUSY== XYL ;[CSM] ;Move in positive Y direction 90 MINUSX==XYU ;[CSM] ;Move in negative X direction 180 MINUSY==XYR ;[CSM] ;Move in negative Y direction 270 XP XYUL,XYL!XYU ;-X+Y MOVE UP+LEFT XP XYDL,XYL!XYD ;+X+Y MOVE DOWN+LEFT XP XYUR,XYR!XYU ;-X-Y MOVE UP+RIGHT XP XYDR,XYR!XYD ;+X-Y MOVE DOWN+RIGHT CSMEDT 01,0 ;3-pen plotter, definitions IFE CSM01$, ;# TICS FOR PLOT PEN UP/DOWN IFN CSM01$, ;30 millisec compared to 1800 per second XP PLTMOV,1 ;# TICS FOR PEN MOVEMENT XP CHRPLN,^D90 ;# CHARACTERS PER LINE MAXIMUM ; Paper tape punch constants ; XP CHPFLD,^D85 ;CHARACTERS PER FOLD OF PTP XP FRMPFT,^D120 ;FRAMES PER FOOT OF TAPE SUBTTL MACROS DEFINE LP(SYM,VAL,FLAG),<;;Flag="Z" marks a variable to be zeroed per job IF1,< XLIST IFNDEF J...X, IFDEF SYM, SYM==J...X J...X==J...X+VAL IFNDEF ...BP,<...BP==1B0> IFNDEF ...WP,<...WP==0> REPEAT VAL,< IFIDN , ...BP==...BP_<-1> IFE ...BP,< ...BP==1B0 ...WP==...WP+1 > ;;END IFE ...BP > ;;END REPEAT VAL IFL 2000-J...X, LIST SALL > ;END IF1 IF2,< .XCREF J...X==SYM .CREF SYM==J...X>;;END IF2>;;END DEFINE LP ;[CSM] Removed 2 CRLFs so that MACRO will show value in listing DEFINE LPZ(A,B),< IFNDEF ...Z'A,<...Z'A==B> IFDEF ...Z'A,<...Z'A==...Z'A!B> > ;END DEFINE LPZ SUBTTL Special Forms Handling Parameters ;Format of SYS:SPFORM.INI ; DEV FORM/SWITCH This line applies to all devices of this type ; DEV FORM:ALL/SWITCH This line applies to all devices of this type ; DEV FORM:LOC/SWITCH This line applies to devices at the central site ; DEV FORM:REM/SWITCH This line applies to devices on remote nodes ; "DEV" can be one of PLT, CDP, or PTP ; "FORM" is the name of the forms type, 6 characters or less ;Note: SPROUT will use the first entry which meets the location ; specification for its device. Therefore, if ALL is used with ; LOC or REM, ALL should be after the LOC or the REM. ;Switches legal for all devices ; /BANNER Output the job header ; /HEADER Output file headers ; /TRAILER Output the job trailer ; /NOTE:AA Type NOTE to the OPR when forms are mounted ;Switches legal for plotters only ; /SPU:NN Steps per unit (a factor of all XX and YY) ; /SPS:NN Steps per second (for calculating run time) ; /MAXIMUM:XX:YY Maximum pen position ; /MINIMUM:XX:YY Minimum pen position after file header ;In the above and below explanations: ; NN is a decimal number ; AA is a string of 1 to 50 characters, terminated by next "/" ; XX is a limit for the X axis ; YY is a limit for the Y axis ;Typical SPFORM.INI forms specification ; CDP NORMAL/BANNER/HEADER - ; /NOTE:Load NORMAL Cards in Card Punch ; ; PLT NORMAL/BANNER/HEADER/TRAILER/SPS:900 ; /SPU:1/MINIMUM:0:0/MAXIMUM:0:5900- ; /NOTE:Set Plotter Controls to 200 Steps per inch ; ; PTP NORMAL/BANNER/HEADER/TRAILER ; PTP BLACK /BANNER/HEADER/TRAILER/NOTE:Black oiled paper tape PAGE COMMENT | CSM interpretation of plotter parameters ; Example for a drum plotter: ; PLT NORMAL /SPS:1800/SPU:4/MINIMUM:0:0/MAXIMUM:0:1100 - /BANNER/HEADER/TRAILER ; PLT = This line applies to the plotter (not CDP or PTP). NORMAL = The forms name. /SPS:1800 = Do accounting based on speed of 1800 steps per second. /SPU:4 = This plotter uses 400 steps per inch, the following numbers are in 1/100ths of an inch. /MINIMUM:0:0 = Pen cannot go to left or below the starting point. /MAXIMUM::1100 = There is no maximum limit in the +X direction, +Y movement is limited to 11.00 inches. The height of characters used in the /BANNER/HEADER/TRAILER is 11.00/90 = 0.12 inches. - = Hypen indicates a continued line. /BANNER = Plot "* Start job XXX" 0.12 inches high, plot user's name and PPN 0.36 inches high, and a line across the paper. /HEADER = Plot file name 0.12 inches high and a dashed line. /TRAILER = Plot a dashed line and the summary 0.12 inches high. /NOTE = No note is specified, so that "OPR>START PLOT 0" will not require a "RESPOND 'PROCEED' WHEN READY". ; End of COMMENT | DEFINE SWITCHES,< FF BANNER FF TRAILER FF HEADER FF NOTE FF SPS FF SPU FF MINIMUM FF MAXIMUM > ;GENERATE TABLE OF SWITCH NAMES DEFINE FF(A),< <&777777B17>+S$'A >;;All on 1 line to look nice XALL ;[CSM] Show definition in the listing FFNAMS: SWITCHES F$NSW==.-FFNAMS ;NUMBER OF SWITCHES SALL ;[CSM] Normal macro expansions SUBTTL Job Parameter Area LP J$$BEG,0 ;BEGINNING OF PARAMETER AREA ;REQUEST PARAMETERS LP J$RFLN,1 ;NUMBER OF FILES IN REQUEST LP J$RLIM,1,Z ;JOB LIMIT IN PAGES LP J$RTIM,1 ;START TIME OF JOB LP J$RNFP,1,Z ;NUMBER OF FILES processed LP J$RNCP,1,Z ;NUMBER OF COPIES OF CURRENT FILE LP J$RNPP,1,Z ;NUMBER OF PAGES IN CURRNET FILE LP J$RACS,20 ;CONTEXT ACS LP J$RPDL,PDSIZE ;CONTEXT PUSHDOWN LIST ;DEV PARAMETERS LP J$LBUF,1 ;ADDRESS OF DEV BUFFER LP J$LBRH,1 ;BUFFER RING HEADER LP J$LBPT,1 ;BUFFER BYTE POINTER LP J$LBCT,1 ;BUFFER BYTE COUNT LP J$TBCT,1 ;TOTAL BYTE COUNT FOR DEVICE LP J$LIOA,1 ;-1 IF WE ARE IN A SOUT OR OUT LP J$LREM,1 ;-1 IF WE ARE A REMOTE DEVICE LP J$LSER,1 ;ADDRESS OF DEVICE SERVICE DISPATCH TOPS10 < LP J$LJFN,1 ;DEV I/O CHANNEL (OR JFN) LP J$LDEV,1 ;DEVICE NAME (SIXBIT) LP J$LIOS,2 ;DEVICE STATUS LP J$LIOE,1 ;-1 IF DEVICE ERROR > ;END TOPS10 CONDITIONAL TOPS20 < LP J$LJFN,1 ;JFN FOR THE DEV LP J$LDEV,2 ;DEVICE NAME STRING LP J$LIOS,2 ;DEVICE STATUS LP J$LIOE,1 ;-1 IF DEVICE ERROR LP J$LIBP,1 ;INITIAL BYTE POINTER LP J$LIBC,1 ;INITIAL BYTE COUNT FOR BUFFERS > ;END TOPS20 CONDITIONAL ;CURRENT FORMS PARAMETERS LP J$FIFN,1 ;TEMPORARY IFN FOR FORM FILE LP J$FORM,1 ;CURRENT FORMS TYPE LP J$FPFM,1 ;PREVIOUS FORMS TYPE LP J$FPLT,1 ;-1 = Plotter-only switches are legal ;STORAGE FOR CURRENT FORMS SWITCHS DEFINE FF(X) LP J$FCUR,0 ;ORIGIN OF CURRENT SWITCH VALUES SWITCHES ;ONE ENTRY PER SWITCH ;MISCELLANY LP J$XFOB,FOB.SZ ;A FILE OPEN BLOCK LP J$XTBF,TXT$LN,Z ;$TEXT BUFFER FOR OUTPUT DEVICE LP J$XERR,ERR$LN,Z ;$TEXT BUFFER FOR ERROR MESSAGES ;CARD PUNCH VARIABLES LP J$XCD1,1 ;1 SCRATCH LOCATION FOR CDP OUTPUT LP J$CMSK,1 ;SPECIAL MASK FOR BLOCK CARD LETTERS LP J$XCHB,40 ;CHECKSUM BLOCK CSMEDT 05,1 ;TTY I/O and SLEEP, part 1 just before PLOTTER VARIABLES IFN CSM05$,< ;Flags and variables LP J$TTY,1 ;'CDP' in LH, UDX in RH LP J$WUDT,1 ;UDT when to wakeup LP J$NACK,1 ;Count of Negative ACKs > ;End of IFN CSM05$ ;PLOTTER VARIABLES ;[CSM] LP J$PAUS,1 ;PAUSE FOR EVERY FORM LP J$XPOS,1 ;CURRENT PLOTTER X COORDINATE LP J$XORG,1 ;ORIGINAL X MINIMUM LP J$XLIM,1,Z ;HIGHEST XSTEP SEEN THIS PLOT LP J$XMIN,1 ;X MINIMUM POINT IN FORM LP J$XMAX,1 ;X MAXIMUM POINT IN FORM LP J$YPOS,1 ;CURRENT PLOTTER Y COORDINATE LP J$YLIM,1 ;HIGHEST YSTEP SEEN THIS PLOT LP J$YMIN,1 ;MINIMUM Y POINT IN FORM LP J$YMAX,1 ;MAXIMUM ALLOWABLE Y COORDINATE LP J$ROTA,1 ;GRID ROTATION (0-3) LP J$PPOS,1 ;PEN POSITION (UP 0 DOWN -1) LP J$CSIZ,1 ;CHARACTER SIZE LP J$XBAS,1 ;CHARACTER X BASE LP J$YBAS,1 ;CHARACTER Y BASE LP J$FUDG,1 ;CHARACTER WIDTH FUDG LP J$SPTR,1 ;POINTER TO CHARACTER SEGMENT BYTES LP J$STEP,1 ;STEP FUNCTION DETERMINES MOVEMENT CSMEDT 01,1 ;3-Pen plotter, part 1 in "PLOTTER VARIABLES" IFN CSM01$,< ;Flags and variables for plotter LP J$PENN,1 ;Pen number, from 1 to 3 LP J$XLOW,1 ;Lowest XSTEP seen while pen was down > ;End of IFN CSM01$ ; Paper tape punch variables ; LP J$TFRM,1,Z ;FRAMES OF TAPE PUNCHED ;ACCOUNTING BLOCK LP J$PTPM,1 ;PLOTTER TICS PER MINUTE LP J$PTIC,1,Z ;ACCOUNTING FOR PLOTTER LP J$APRT,1,Z ;NUMBER OF PAGES processed LP J$ADRD,1,Z ;DISK BLOCKS READ. LP J$APRI,1,Z ;JOBS PRIORITY LP J$ARTM,1,Z ;JOBS RUN TIME (CPU) LP J$ASEQ,1,Z ;JOBS SEQUENCE NUMBER LP J$AFXC,1,Z ;TOTAL FILES processed (FILES*COPIES) LP J$ADSP,1,Z ;DISPOSITION (SIXBIT) LP J$AQUE,1,Z ;QUEUE NAME (SIXBIT) ;DISK FILE PARAMETERS LP J$DIFN,1 ;THE IFN LP J$DFDA,1 ;THE FD ADDRESS LP J$DBPT,1 ;BUFFER BYTE POINTER LP J$DBCT,1 ;BUFFER BYTE COUNT LP J$DBSZ,1 ;INPUT BYTE SIZE LP J$DMOD,1 ;I/O MODE OF DISK FILE LP J$DSPN,1 ;SPOOLED FILE NAME IF ANY LP J$DSPX,1 ;SPOOLED FILE EXTENSION LP J$$END,1 ;END OF PARAMETER AREA J$$LEN==J$$END ;LENGTH OF PARAMETER AREA INTERN J$$END ;[CSM] ;For .ASSIGNing data areas ;NOW GENERATE A BIT TABLE OF WHICH WORDS IN THE JOB DATA PAGE TO ZERO ; ON A NEW JOB ZTABLE: ;PUT TABLE HERE DEFINE ZTAB(A),< IFNDEF ...Z'A,<...Z'A==0> EXP ...Z'A > ;END DEFINE ZTAB ZZ==0 REPEAT <^D512+^D35>/^D36,< XLIST ZTAB(\ZZ) ZZ==ZZ+1 LIST > ;END REPEAT SUBTTL Resident JOB DaTABase STREAM: BLOCK 1 ;(LH) -1 WHILE IN STREAM CONTEXT ; 0 WHILE IN SCHED CONTEXT ;(RH) CURRENT STREAM NUMBER JOBPAG: BLOCK NSTRMS ;ADDRESS OF A THREE PAGE BLOCK ; ONE FOR REQUEST, ONE FOR JOB PARAMS, ONE FOR BUFFER JOBOBA: BLOCK NSTRMS ;TABLE OF OBJECT BLOCK ADDRESSES JOBSTW: BLOCK NSTRMS ;JOB STATUS WORD JOBACT: BLOCK NSTRMS ;-1 IF STREAM IS ACTIVE, 0 OTHERWISE JOBOBJ: BLOCK 3*NSTRMS ;LIST OF SETUP OBJECTS JOBWAC: BLOCK NSTRMS ;WTOR ACK CODE (TIME SETUP WAS RECIEVED) JOBCHK: BLOCK NSTRMS ;Stream checkpoint indicator ;Contains the time for the next chkpnt ; or 0 if one is requested CSMEDT 05,2 ;TTY I/O and SLEEP, part 2 before "LOWEND==" IFN CSM05$,< SLEEPT: BLOCK 1 ;Time to sleep > ;End of IFN CSM05$ LOWEND==.-1 TOPS10 < VECTOR: BLOCK 0 ;BEGINNING OF INTERRUPT VECTOR VECIPC: BLOCK 4 ;IPCF INTERRUPT BLOCK VECDEV: BLOCK 4*NSTRMS ;DEVICE INTERRUPT BLK ENDVEC==.-1 ;END OF INTERRUPT VECTOR > ;END TOPS10 CONDITIONAL TOPS20 < LEV1PC: BLOCK 1 ;LVL 1 INTERRUPT PC STORED HERE LEV2PC: BLOCK 1 ;LVL 2 INTERRUPT PC STORED HERE LEV3PC: BLOCK 1 ;LVL 3 INTERRUPT PC STORED HERE > ;END TOPS20 CONDITIONAL ;SCHEDULER FLAGS PSF%OB==1B1 ;OUTPUT BLOCKED PSF%DO==1B2 ;DEVICE IS OFF-LINE PSF%ST==1B3 ;STOPPED BY OPERATOR PSF%OR==1B4 ;OPERATOR RESPONSE WAIT PSF%NP==1B5 ;GO TO NEXT PROCESS DEFINE $DSCHD(FLAGS),< $CALL DSCHD XLIST JUMP [EXP FLAGS] LIST SALL > ;END DEFINE $DSCHD SUBTTL Program Initialization SPROUT: JFCL ;NO CCL ENTRY RESET ;CLEAR ALL ACTIVE I/O IFN CSM02$,< ;Check to see where LINK .ASSIGNed the buffers SKIPLE [TOLP..##-1777] ;Make sure data area is only one page OUTSTR [ASCIZ /?Data area for TOLP extends past 1777/] > ;End of IFN CSM02$ IFN CSM06$,< SKIPLE [TABC..##-1777] ;Make sure data area is only one page OUTSTR [ASCIZ /?Data area for TABCDP extends past 1777/] > ;End of IFN CSM06$ IFN CSM08$,< SKIPLE [PTC6..##-1777] ;Make sure data area is only one page OUTSTR [ASCIZ /?Data area for PTC6 extends past 1777/] > ;End of IFN CSM08$ MOVE P,[IOWD PDSIZE,PDL] MOVEI S1,IB.SZ ;GET SIZE OF IB MOVEI S2,IB ;GET ADDR OF IB $CALL I%INIT ;START UP THE WORLD MOVEI S1,+1 ;LOAD LENGTH OF RESIDENT IMPURE DATA MOVEI S2,LOWBEG ;AND ITS ADDRESS $CALL .ZCHNK ;AND ZERO IT OUT $CALL INTINI ;INITIALIZE THE INTERRUPT SYSTEM IFN ACCTSW,< SETOM ACTFLG ;UNLESS HE DOESN'T WANT IT PUSHJ P,ACTINI ;SET UP ACCOUNTING DATA > ;END IFE ACCTSW TOPS20 < HRRZI S1,.MSIIC ;BYPASS MOUNTS MSTR ERJMP .+1 > ;END TOPS20 CONDITIONAL $CALL I%ION ;TURN ON INTERRUPTS MOVEI T1,HELLO ;GET HELLO MESSAGE $CALL SNDQSR ;SEND IT TOPS10< MOVSI S1,.STSPL ;PULL A SETUUO TO SETUUO S1, ; CLEAR ANY SPOOLING BITS JFCL ;IGNORE THE ERROR > $CALL I%HOST ;GET LOCAL HOST STUFF TOPS10 ;SAVE NUMBER AS CENTRAL STATION TOPS20 ;SAVE NAME AS CENTRAL STATION JRST MAIN ;AND GO! SUBTTL Idle Loop MAIN: MOVE P,[IOWD PDSIZE,PDL] ;SETUP A NEW PDL HRROS STREAM ;SET SCHEDULER CONTEXT $CALL CHKQUE ;PROCESS MESSAGES MOVX P2,PSF%NP ;GET NEXT PASS FLAG MAIN.1: MOVSI P1,-NSTRMS ;SET UP DISPATCH AC MAIN.2: SKIPN JOBACT(P1) ;IS THIS STREAM ACTIVE? JRST MAIN.3 ;NO,,GET THE NEXT STREAM. HRROM P1,STREAM ;YES -- SAVE NUMBER (IN SCHED CONTEXT) MOVE J,JOBPAG(P1) ;GET ADDRESS OF JOB PAGES PUSHJ P,CHKPNT ;CHECKPOINT JOB IF NECESSARY CSMEDT 05,2 ;TTY I/O and SLEEP, part 2 at MAIN.2:+5 IFN CSM05$,< ;Watch for sleep time PUSHJ P,CHKTIM ;Time to run this stream? JUMPF MAIN.3 ;Not yet > ;End of IFN CSM05$ SKIPN JOBSTW(P1) ;IS THE STREAM BLOCKED? JRST MAIN.4 ;NO -- SETUP STREAM CONTEXT MAIN.3: ANDCAM P2,JOBSTW(P1) ;CLEAR NEXT PASS BIT AOBJN P1,MAIN.2 ;TRY NEXT STREAM TXZE P2,PSF%NP ;ON SECOND PASS? JRST MAIN.1 ;NOT YET..TRY AGAIN ;HERE IF NO STREAM IS RUNNABLE IFE CSM05$,< MOVEI S1,0 > ;SNOOZE FOR INTERRUPT IFN CSM05$,< MOVE S1,SLEEPT > ;Get sleep time in seconds $CALL I%SLP ;GO WAIT $CALL CHKQUE ;PROCESS MESSAGES IFN CSM05$,< SETZM SLEEPT > ;Clear timer request JRST MAIN.1 ;AND TRY AGAIN MAIN.4: CAME J,ACTPAG ;SAME STREAM? $CALL ACTRNT ;NO..INIT RUNTIME VALUES MOVEM J,ACTPAG ;SAVE THIS AS ACCOUNTING PAGE HRLZI 0,J$RACS+1(J) ;SET UP STREAM CONTEXT BLT HRRI 0,1 ;START WITH AC 1 BLT 0,17 ;RESTORE THE ACS HRRZS STREAM ;SET STREAM CONTEXT POPJ P, ;AND RESTORE STREAM PC ;NOTE: Stream is now active and will return via DSCHD (see next page) SUBTTL Deschedule Process ;DSCHD is called by the $DSCHD macro to cause the "current" stream to ; be un-scheduled. The call is: ; ; $DSCHD(flags) ; ;which generates: ; ; PUSHJ P,DSCHD ; JUMP [EXP flags] DSCHD: HRROS STREAM ;SET SCHED CONTEXT MOVEM 0,J$RACS(J) ;SAVE AC 0 MOVEI 0,J$RACS+1(J) ;PLACE TO PUT AC 1 HRLI 0,1 ;SETUP THE BLT POINTER BLT 0,J$RACS+17(J) ;SAVE STREAM ACS HRRZ S1,0(P) ;GET ADDRESS OF "JUMP [FLAGS]" CSMEDT 05,2 ;TTY I/O and SLEEP, part 2 at DSCHD:+6 IFE CSM05$,< MOVE S1,@0(S1) > ;GET THE FLAGS IFN CSM05$,< HRRZ T1,@0(S1) ;Get the seconds to sleep HLLZ S1,@0(S1) ;Get the flags > ;End of IFN CSM05$ HRRZ S2,STREAM ;GET STREAM NUMBER IORM S1,JOBSTW(S2) ;SET THE FLAGS IFE CSM05$,< JRST MAIN > ;AND GO LOOP IFN CSM05$,< ;This code taken from LPTSPL JUMPE T1,MAIN ;Loop if no sleep time CONT. (SCHEDULER) SKIPE SLEEPT ;Is a sleep time set? CAMG T1,SLEEPT ;And current amount smaller? MOVEM T1,SLEEPT ;Yes, save shorter interval $CALL I%NOW ;Get the current time IMULI T1,3 ;Seconds to UDT ticks ADD T1,S1 ;Build wake-up time MOVEM T1,J$WUDT(J) ;Save for CHKTIM JRST MAIN ;Loop SUBTTL CHKTIM - Routine to see if it's time to schedule a stream ;CALL: J/ Pointer to job page ; ;REG: TRUE if stream can be scheduled now (timewise) ; FALSE if stream needs to wait CHKTIM: $CALL I%NOW ;Get the current time MOVE S2,S1 ;Get the UDT in S2 MOVE S1,J$WUDT(J) ;Get the stream wakeup time SUB S1,S2 ;Get time left in UDT ticks IDIVI S1,3 ;Convert to seconds SKIPG S1 ;Any seconds left? JRST [SETZM SLEEPT ;No, clear old sleep time $RETT ] ;Return TRUE SKIPE SLEEPT ;Is a sleep time set? CAMG S1,SLEEPT ;And current amount smaller? MOVEM S1,SLEEPT ;Yes, save the shorter interval $RETF ;Return FALSE ;End of code taken from LPTSPL> ;End of IFN CSM05$ SUBTTL SETUP/SHUTDOWN Message SETUP: LOAD S2,SUP.FL(M) ;GET THE FLAGS TXNE S2,SUFSHT ;IS IT A SHUTDOWN? JRST [MOVEI S1,SUP.TY(M) ;GET OBJECT ADDRESS $CALL FNDOBJ ;FIND IT JRST SHUTDN] ;AND SHUT IT DOWN SETZ T2, ;CLEAR A LOOP REG SETU.1: SKIPN JOBPAG(T2) ;A FREE STREAM? JRST SETU.2 ;YES! CAIGE T2,NSTRMS-1 ;NO, LOOP THRU THEM ALL? AOJA T2,SETU.1 ;NO, KEEP GOING $STOP(TMS,Too many setups) ;[CSM] There is a problem if two streams start with 1/3 of a second SETU.2: HRRZM T2,STREAM ;SAVE THE STREAM NUMBER $CALL I%NOW ;USE SETUP TIME AS ACK STAMP LSH S1,3 ;[CSM] ;Free up 3 bits IOR S1,T2 ;[CSM] ;Make it be unique MOVEM S1,JOBWAC(T2) ;SAVE CODE FOR $WTOR MOVEI S1,NJBPGS ;NUMBER OF PAGES NEEDED $CALL M%AQNP ;GET THEM PG2ADR S1 ;CONVERT TO AN ADDRESS MOVEM S1,JOBPAG(T2) ;AND SAVE IT MOVE J,S1 ;PUT IT IN J MOVEM J,J$RACS+J(J) ;SAVE J AWAY MOVEI S1,2000(J) ;DEV BUFFER ADDRESS MOVEM S1,J$LBUF(J) ;STORE IT MOVE S2,T2 ;COPY OVER THE STREAM NUMBER IMULI T2,OBJ.SZ ;GET OFFSET OF OBJECT BLOCK ADDI T2,JOBOBJ ;ADD IN THE BASE MOVEM T2,JOBOBA(S2) ;STORE OBJECT ADDRESS MOVE S2,T2 ;GET DESTINATION OF BLT INTO S2 HRLI S2,SUP.TY(M) ;MAKE A BLT POINTER BLT S2,OBJ.SZ-1(T2) ;BLT THE OBJECT BLOCK $CALL OUTGET ;GET THE OUTPUT DEVICE $CALL RSETUP ;SEND RESPONSE TO SETUP HRRZ S2,STREAM ;GET OUR STREAM NUMBER $WTO (^T/@SETMSG(S1)/,,@JOBOBA(S2)) ;TELL THE OPERATOR CAIN S1,%RSUOK ;ALL IS OK? $RETT ;YES, RETURN JRST SHUTDN ;NO, SHUT IT DOWN SETMSG: [ASCIZ /Started/] [ASCIZ /Not available right now/] [ASCIZ /Does not exist/] ACTBEG: SKIPN ACTFLG ;ACCOUNTING? $RETT ;NO..JUST RETURN LOAD S1,.EQSEQ(J),EQ.SEQ ;GET SEQUENCE NUMBER STORE S1,J$ASEQ(J) ;STORE IT LOAD S1,.EQSEQ(J),EQ.PRI ;GET EXTERNAL PRIORITY STORE S1,J$APRI(J) ;STORE IT MOVE S1,J$LSER(J) ;GET DISPATCH ADDRESS MOVE S1,DNAME(S1) ;GET DEVICE (QUEUE) NAME MOVEM S1,J$AQUE(J) ;SAVE FOR ACT END SETZM J$PTIC(J) ;CLEAR PLOTTER ACCOUNTING $RETT ;RETURN ACTEND: SKIPN ACTFLG ;ARE WE DOING ACCT? $RETT ;NO,,RETURN NOW. LOAD S1,.EQSEQ(J),EQ.IAS ;GET THE INVALID ACCT STRING BIT JUMPN S1,.RETT ;IF LIT,,THEN JUST RETURN MOVE S1,J$LSER(J) ;GET DISPATCH ADDRESS PUSHJ P,DACCT(S1) ;DO FINAL ACCOUNTING MOVX S2,'NORMAL' ;ASSUME NORMAL DISPOSITION TXNE S,RQB ;REQUED? MOVX S2,'REQUED' ;YES TXNE S,ABORT ;ABORTED? MOVX S2,'CANCEL' MOVEM S2,J$ADSP(J) ;STORE DISPOSITION $CALL ACTRNT ;DO FINAL RUNTIME ACCOUTING SETZM ACTPAG ;CLEAR THE PAGE ADDRESS TOPS10< MOVE S1,[.NDRNN,,S2] ;GET CONVERT TO NAME FCT CODE MOVEI S2,2 ;A BLOCK LENGTH OF 2 MOVE T1,.EQROB+.ROBND(J) ;GET THE NODE NUMBER CONT. (ACTEND) FACT< HRLZM T1,FACTBL+3 > ;STORE NODE NUMBER NOW NODE. S1, ;CONVERT IT SKIPA ;SKIP ON AN ERROR MOVEM S1,.EQROB+.ROBND(J) ;SAVE THE NODE NAME MOVX S1, ;SET UP AC QUEUE. S1, ;MAKE A USAGE ENTRY PUSHJ P,ACTE.1 ;FAILED,,TELL OPR FACT< MOVE S1,L.LIN ;GET LINE NUMBER LDB S2,[POINT 7,L.TTY,6] ;GET TERMINAL DESIGNATOR CAIN S2,"C" ;ON THE CTY MOVEI S1,7777 ;YES, CTY DESIGNATOR CAIN S2,"D" ;DETACHED MOVEI S1,7776 ;YES, FLAG THAT INSTEAD OF LINE NUMBER LSH S1,6 ;PUT IN BITS 18-29 HRL S1,L.JOB ;INSERT JOB NUMBER IOR S1,[251000,,13] ;ADD FACT TYPE AND NUMBER OF WORDS MOVEM S1,FACTBL+0 ;STORE IN BLOCK MOVE S1,.EQOID(J) ;GET PPN MOVEM S1,FACTBL+1 ;STORE SETZM FACTBL+2 ;DAEMON FILLS IN THE DATE/TIME MOVE S1,[%CNSER] ;CPU SERIAL NUMBER GETTAB S1, ;ASK FOR IT SETZ S1, ;USE 0 IF CAN'T FIND IT HLLZ S2,J$AQUE(J) ;GET QUEUE NAME TLZ S2,77 ;CLEAR JUNK IOR S1,S2 ;INSERT QUEUE NAME IORM S1,FACTBL+3 ;NODE NUMBER ALREADY STORED FROM ABOVE MOVE S1,J$ARTM(J) ;RUN TIME IN MILLISECONDS MOVEM S1,FACTBL+4 ;STORE SETZM FACTBL+5 ;*** CORE TIME INTERGRAL MOVE S1,J$ADRD(J) ;DISK READS MOVEM S1,FACTBL+6 ;STORE CSMEDT 04,1 ;CSM accounting, part 1 after QUEUE. uuo IFE CSM04$,< SETZM FACTBL+7 > ;No disk writes IFN CSM04$,< MOVE S1,J$FORM(J) ;Get the forms type MOVEM S1,FACTBL+7 ;Instead of disk writes > ;End of CSM04$ CONT. (ACTEND) MOVE S1,J$LDEV(J) ;DEVICE NAME MOVEM S1,FACTBL+10 ;STORE MOVE S1,J$ASEQ(J) ;SEQUENCE NUMBER MOVEM S1,FACTBL+11 ;STORE MOVE S1,J$APRT(J) ;Number of cards, feet, minutes MOVEM S1,FACTBL+12 ;Store as pages printed MOVE S1,[14,,FACTBL-1] ;DAEMON ARGUMENT DAEMON S1, ;MAKE THE FACT ENTRY JRST ACTE.1 ;REPORT THE FAILURE > ;END FACT ACCOUNTING > ;END TOPS10 ACCOUNTING TOPS20< MOVX S1,.USENT ;WRITE AN ENTRY MOVEI S2,ACTLST ;POINT TO THE LIST USAGE ;DO THE JSYS ERJMP ACTE.1 ;ON AN ERROR,,TELL THE OPERATOR > ;END OF TOPS-20 CONDITIONAL $RETT ;RETURN WHEN DONE ACTE.1: MOVE S1,STREAM ;GET THIS STREAM NUMBER $WTO (System Accounting Failure,<^R/.EQJBB(J)/>,@JOBOBA(S1)) $RETT ;RETURN ACTRNT: SKIPN ACTFLG ;Accounting turned on? $RETT ;No - return SETO S1, ;-1 Means us MOVX S2,JI.RTM ;Function code $CALL I%JINF ;Get our runtime ADDM S2,ACTRNN ;Store accumulated time MOVNS S2 ;Negate actual runtime EXCH S2,ACTRNN ;INIT FOR NEXT PASS SKIPE S1,ACTPAG ;GET LAST PROCESSES PAGE ADDRESS ADDM S2,J$ARTM(S1) ;ACCUMULATE TOTAL $RETT ;RETURN SUBTTL FORMS - Setup Forms for a job FORMS: GETLIM S1,.EQLIM(J),FORM ;GET THE FORMS TYPE CAMN S1,J$FORM(J) ;EXACTLY THE SAME? $RETT ;YES, JUST RETURN MOVE S2,[POINT 7,J$XTBF(J)] ;GET POINTER TO WTOR BUFFER. MOVEM S2,TEXTBP ;AND SAVE IT FOR DEPBP. MOVEI S2,TXT$LN*5 ;GET MAXIMUM BYTE COUNT MOVEM S2,TEXTBC SKIPN S2,J$FORM(J) ;GET FORMS TYPE MOVX S2,FRMNOR ;USE NORMAL IF NULL XOR S1,S2 ;GET COMMON PART AND S1,[EXP FRMSK1] ;AND IT WITH THE IMPORTANT PART GETLIM S2,.EQLIM(J),FORM ;GET FORMS TYPE EXCH S2,J$FORM(J) ;SAVE IT MOVEM S2,J$FPFM(J) ;SAVE OLD ONES SKIPE S1 ;NO NEED TO CHANGE FORMS. $TEXT (DEPBP,) FORM.1: HRLZI S1,J$FCUR(J) ;GET START OF SWITCH STORAGE HRRI S1,J$FCUR+1(J) ;MAKE BLT POINTER SETZM J$FCUR(J) ;CLEAR THE FIRST WORD BLT S1,J$FCUR+F$NSW-1(J) ;CLEAR THE BLOCK FORM.2: $CALL FRMINI ;READ THE SPFORM.INI FILE. MOVE S1,TEXTBP ;GET THE WTOR BYTE POINTER. CAMN S1,[POINT 7,J$XTBF(J)] ;IS THERE A MESSAGE FOR THE OPERATOR? $RETT ;NO,,RETURN. IFN CSM02$,< FORM.3: > ;PUSHJ to here to wait for 'PROCEED' in OPRTXT $TEXT (DEPBP,) HRRZ S1,STREAM ;GET STREAM NUMBER $WTOR (,<^T/J$XTBF(J)/>,@JOBOBA(S1),JOBWAC(S1)) ;SEND THE WTOR. $DSCHD (PSF%OR) ;WAIT FOR OPERATOR RESPONSE. $RETT ;RETURN... SUBTTL Plotter only switches S$SPS: SKIPN J$FPLT(J) ;IS DEVICE A PLOTTER? $RETF ;NO PUSHJ P,FH$DEC ;GET STEPS PER SECOND MOVEM T1,J$FSPS(J) ;STORE IT $RETT ;RETURN S$SPU: SKIPN J$FPLT(J) ;IS DEVICE A PLOTTER? $RETF ;NO -- ERROR RETURN $CALL FH$DEC ;GET STEPS PER UNIT MOVEM T1,J$FSPU(J) ;AND SAVE IT $RETT S$MINI: SKIPN J$FPLT(J) ;IS DEVICE A PLOTTER? $RETF ;NO -- INVALID SWITCH SETZM J$XORG(J) ;DEFAULT TO ZERO SETZM J$YMIN(J) ;DITTO $CALL FH$DEC ;GET DECIMAL INTEGER MOVEM T1,J$XORG(J) ;STORE X MINIMUM CAIE C,":" ;IS Y ARGUMENT SPECIFIED? $RETT ;NO -- RETURN $CALL FH$DEC ;GET DECIMAL INTEGER MOVEM T1,J$YMIN(J) ;STORE Y MINIMUM $RETT ;AND RETURN S$MAXI: SKIPN J$FPLT(J) ;IS DEVICE A PLOTTER? $RETF ;NO -- INVALID SWITCH MOVX T1,.INFIN ;GET A LARGE NUMBER MOVEM T1,J$XMAX(J) ;DEFAULT MOVEM T1,J$YMAX(J) ;DITTO $CALL FH$DEC ;GET DECIMAL INTEGER SKIPE T1 ;[CSM] ;If not zero, MOVEM T1,J$XMAX(J) ;STORE X MAXIMUM CAIE C,":" ;IS Y ARGUMENT SPECIFIED? $RETT ;NO -- RETURN $CALL FH$DEC ;GET DECIMAL INTEGER SKIPE T1 ;[CSM] ;If not zero, MOVEM T1,J$YMAX(J) ;STORE Y MAXIMUM $RETT ;AND RETURN ;ROUTINE TO SEARCH FOR EOL IN SPFORM.INI FH$EOL: $CALL FH$CHR ;GET A CHARACTER JUMPF .RETF ;FAIL IF EOF CAIE C,.CHLFD ;EOL? JRST FH$EOL ;NO, LOOP $RETT ;YES, RETURN! ;ROUTINE TO PICK UP A DECIMAL NUMBER FH$DEC: SETZ T1, ;PLACE TO ACCUMULATE RESULT FH$DE1: $CALL FH$CHR ;GET A CHARACTER JUMPF .RETF ;EOF, RETURN CAIL C,"0" ;CHECK THE RANGE CAILE C,"9" ;0-9 POPJ P, ;RETURN IMULI T1,^D10 ;[CSM] ;Shift one decimal place ADDI T1,-"0"(C) ;ADD IN A DIGIT JRST FH$DE1 ;AND LOOP AROUND SUBTTL OUTGET - OPEN the output device ;THIS ROUTINE OPENS THE SPECIFIED OUTPUT DEVICE, AND SETS UP A BUFFER RING TOPS10 < OUTGET: HRRZ S1,STREAM ;GET THE STREAM NUMBER MOVE S1,JOBOBA(S1) ;GET OBJECT BLOCK ADDRESS MOVE S1,OBJ.TY(S1) ;GET OBJECT TYPE SETZ S2, ;AND CLEAR AN AC CAXN S1,.OTPTP ;IS IT A PAPERTAPE PUNCH? MOVEI S2,T$DISP ;YES! CAXN S1,.OTCDP ;NO, HOW ABOUT A CARD PUNCH? MOVEI S2,C$DISP ;WIN! CAXN S1,.OTPLT ;TRY FOR A PLOTTER MOVEI S2,P$DISP ;AND GET THE PLOTTER DISPATCH JUMPE S2,OUTDDE ;DONT KNOW ABOUT IT MOVEM S2,J$LSER(J) ;SAVE IT MOVEI S1,J$LDEV(J) ;ADDRESS OF WHERE TO PUT DEVNAM HRLI S1,(POINT 6,0) ;MAKE IT A BYTE POINTER MOVEM S1,TEXTBP ;SAVE IT MOVEI S1,6 ;MAXIMUM CHARACTER COUNT MOVEM S1,TEXTBC HRRZ S1,STREAM ;GET THE STREAM NUMBER MOVE S1,JOBOBA(S1) ;GET OBJECT BLOCK ADDRESS $TEXT(DEP6BP,<^W3/DNAME(S2)/^O2R0/OBJ.ND(S1)/^O1/OBJ.UN(S1)/^A>) MOVE T1,J$LDEV(J) ;GET THE DEVICE NAME DEVNAM T1, ;GET ITS PHYSICAL NAME JRST OUTDDE ;LOSE? MOVEM T1,J$LDEV(J) ;AND SAVE IT MOVX T1,.IOIMG+UU.PHS+UU.AIO ;IMAGE+PHONLY+NBIO CSMEDT 05,3 ;TTY I/O and SLEEP, part 3 after DEVNAM in OUTGET IFN CSM05$,< ;Check for devices connected to TTY lines HLRZ T2,J$LDEV(J) ;Get first part of physical name CAIE T2,'TTY' ;Is it a terminal? JRST CSM05Z ;No MOVE S2,J$LSER(J) ;Get service routine MOVE S1,DNAME(S2) ;Get 'PLT' or 'CDP' MOVEM S1,J$TTY(J) ;Put in LH MOVE T2,J$LDEV(J) ;Get device again IONDX. T2, ;Get UDX SETZB T2,J$TTY(J) ;Should never happen HRRM T2,J$TTY(J) ;Store TTY UDX in RH CONT. (OUTGET) ;FORCE NEW LISTING PAGE ;Disable free CRLFs every 80 characters and SET TTY NO GAG MOVX T1,.TONFC+.TOSET ;Change setting to MOVEI T3,1 ; no free CRLFs MOVE S1,[3,,T1] TRMOP. S1, ;SET TTY NO CRLF JFCL ;*BUG*; MOVX T1,.IOPIM+UU.PHS ;Packed image mode (no echo) MOVX T1,.IOIMG+UU.PHS+IO.SUP ;Image mode, no echo HLRZ S1,J$TTY(J) ;Get device type CAIN S1,'PLT' ;Output to plotter? MOVX T1,.IOASC+UU.PHS+IO.SUP ;ASCII mode, no echo CSM05Z: > ;End of IFN CSM05$ MOVE T2,J$LDEV(J) ;OUTPUT DEVICE NAME MOVSI T3,J$LBRH(J) ;BUFFER HEADER MOVE S1,STREAM ;GET OUR STREAM NUMBER MOVEM S1,J$LJFN(J) ;SAVE AS THE STREAM NUMBER LSH S1,^D23 ;PUT IN THE RIGHT PLACE IOR S1,[OPEN T1] ;MAKE IT AN INSTRUCTION XCT S1 ;AND EXECUTE IT JRST OUTDNA ;LOSE GIVE ERROR MOVE S1,J$LSER(J) ;GET DEVICE DISPATCH ADDRESS MOVE S1,DBYTE(S1) ;GET OUTPUT BYTE SIZE IFN CSM05$,< ;Cannot use 6 bits to PTC-6 HLRZ S2,J$TTY(J) ;Nonzero if TTY as output device CAIN S2,'PLT' ;Going to the plotter? MOVEI S1,7 ;Yes, use normal ASCII mode ;SET TTY NO GAG after it has been inited MOVX T1,.TOSND+.TOSET ;Change setting to HRRZ T2,J$TTY(J) MOVEI T3,0 ; no SENDs allowed MOVE S2,[3,,T1] SKIPE T2 ;Don't TRMOP. if not a TTY TRMOP. S2, ;SET TTY GAG JFCL > ;End of IFN CSM05$ STORE S1,J$LBRH+1(J),BP.SIZ ;STORE IT MOVX S1,PSF%OB!PSF%DO ;GET OUTPUT-BLOCKED AND DEVICE OFFLINE HRRZ S2,STREAM ;AND STREAM NUMBER ANDCAM S1,JOBSTW(S2) ;AND CLEAR THE CONDITIONS MOVE T1,J$LJFN(J) ;LOAD CHANNEL NUMBER WHERE T1, ;GET OUR STATION NUMBER SETZ T1, TLZ T1,-1 ;CLEAR STATION FLAGS CAME T1,CNTSTA ;IS THIS CENTRAL STATION? SETOM J$LREM(J) ;NO -- SET REMOTE MOVEI S1,T1 ;LOAD ADDRESS OF ARGBLOCK FOR DEVSIZ MOVX T1,.IOIMG ;GET IMAGE MODE MOVE T2,J$LJFN(J) ;GET THE CHANNEL DEVSIZ S1, ;DO THE DEVSIZ JRST OUTDNA ;LOSE MOVEI T1,PAGSIZ ;LOAD PAGE SIZE IDIVI T1,(S1) ;GET NUMBER OF BUFFER TO CREATE MOVE S1,J$LBUF(J) ;GET ADDRESS OF BUFFER PAGE EXCH S1,.JBFF ;SWAP WITH JOBFF MOVE S2,J$LJFN(J) ;GET CHANEL NUMBER LSH S2,^D23 ;POSITION IT IOR S2,[OUTBUF 0(T1)] ;BUILD THE OUTBUF XCT S2 ;AND DO IT MOVEM S1,.JBFF ;RESTORE JOBFF $CALL INTCNL ;CONNECT TO INTERRUPTS MOVX S1,%RSUOK ;LOAD OK CODE $RETT ;AND RETURN > ;END TOPS10 CONDITIONAL SUBTTL OUTOUT - Routine to output a buffer TOPS10 < OUTOUT: $SAVE ;SAVE SOME ACS CSMEDT 01,2 ;3-Pen plotter, part 2 at OUTOUT:+1 IFN CSM01$,< ;The plotter does not interrupt for off-line or on-line SKIPE J$FPLT(J) ;Is this going to the plotter? PUSHJ P,PLTCHK ;Yes, check if it is on-line > ;End of CSM01$ OUTO.1: MOVE S1,STREAM ;Get our stream number MOVX S2,PSF%OB ;Assume we are blocked IORM S2,JOBSTW(S1) ; waiting for output done MOVE S1,J$LJFN(J) ;GET THE CHANNEL NUMBER LSH S1,^D23 ;POSITION IT TLO S1,(OUT 0,0) ;MAKE IT AN OUTPUT UUO XCT S1 ;AND DO IT JRST [MOVE S1,STREAM ;We won! Clear blocked bit ANDCAM S2,JOBSTW(S1) ; so we are runnable $RETT] OUTERR: PUSHJ P,OUTSTS ;READ DEVICE STATUS JUMPT [$DSCHD (0) ;ASSUME OUTPUT BLOCKED JRST OUTO.1] ;RETRY OUTPUT $CALL DEVERR ;PROCESS DEVICE ERROR JUMPT OUTO.1 ;RETRY OUTPUT IF CORRECTED JRST MAIN ;STREAM IS SHUTDOWN OUTWAT: $CALL OUTOUT ;OUTPUT THE BUFFER OUTW.1: $CALL OUTSTS ;GET THE STATUS TXNN S1,IO.ACT ;DONE? $RETT ;YES, RETURN $DSCHD (0) ;FORCE A SCHEDULING RUN JRST OUTW.1 ;TRY AGAIN CONT. (OUTOUT) IFN CSM01$,< ;After OUTWAT: inside TOPS10<> ;Ask the monitor to do a CONI to check if PLT is on-line OPDEF STSPL. [CALLI -4] ;CSM UUO to do PLT.ON==1B30 ;The plotter power is on PLTCHK: CSMEDT 08,1 ;PTC-6 Plotter Controller, part 1 inside CSM01$ IFN CSM08$,< SKIPE J$TTY(J) ;Output going to a TTY? POPJ P, ;Yes, cannot determine on-line status > ;End of IFN CSM08$ STSPL. S1, ;Get current status of plotter TXNE S1,PLT.ON ;Is the POWER-ON bit set? JRST PLTONL ;Yes, plotter is on-line now AOS S1,J$NACK(J) ;Increment NACK count IDIVI S1,^D30 ;Set S2 modulo 30 JUMPN S2,PLTCH1 ;Complain every 30 seconds HRRZ S1,STREAM ;Get stream number SETOM JOBCHK(S1) ;Request checkpoint $WTO (Off-line,,@JOBOBA(S1)) PLTCH1: CSMEDT 05,4 ;TTY I/O and SLEEP, part 4 after PLTCHK: IFN CSM05$,< $DSCHD (1) > ;De-schedule for 1 second IFE CSM05$,< MOVEI S1,1 ;Wait 1 second SLEEP S1, > ; before continuing JRST PLTCHK ;Check if it is on-line now PLTONL: SETOM J$NACK(J) ;Plotter is on-line now $RETT ;OK to do the OUT UUO > ;End of IFN CSM01$ > ;END TOPS10 CONDITIONAL CONT. (OUTOUT) TOPS20 < OUTOUT: $SAVE ;PRESERVE TEMPORARIES MOVE S1,J$LJFN(J) ;GET DEV JFN MOVE S2,J$LIBP(J) ;GET POINTER TO BUFFER SKIPGE T1,J$LBCT(J) ;GET REMAINING BYTE COUNT SETZ T1, ;MUST BE .GE. 0 SUB T1,J$LIBC(J) ;GET NEG. BYTE COUNT JUMPE T1,OUTO.2 ;DONE -- RESET BUFFER HEADER OUTO.1: HRRZ T2,STREAM ;GET STREAM SETOM J$LIOA(J) ;SET I/O ACT SKIPE JOBSTW(T2) ;BLOCKED? JRST OUTINT ;YES -- POSTPONE SOUT SOUTR ;DUMP THE BUFFER ERJMP OUTERR ;PROCESS ERROR OUTO.2: SETZM J$LIOA(J) ;CLEAR I/O ACT MOVE S1,J$LIBC(J) ;GET INITIAL BYTE COUNT MOVEM S1,J$LBCT(J) ;RESET BUFFER COUNT MOVE S1,J$LIBP(J) ;GET INITIAL BYTE POINTER MOVEM S1,J$LBPT(J) ;RESET BUFFER POINTER HRRZ T1,J$LIBP(J) ;GET START ADDRESS OF BUFFER HRLZ T2,T1 ;COPY IT HRRI T2,1(T1) ;MAKE A BLT POINTER SETZM (T1) ;CLEAR THE FIRST WORD BLT T2,PAGSIZ-1(T1) ;CLEAR THE BUFFER $DSCHD (PSF%NP) ;PICK UP AGAIN AFTER SCHEDULE $RETT ;AND FINALLY RETURN OUTERR: SETOM J$LIOE(J) ;SET ERROR FLAG OUTINT: SETZM J$LIOA(J) ;CLEAR IO ACTIVE MOVEM S2,J$LBPT(J) ;SAVE THE CURRENT POINTER MOVEM T1,J$LBCT(J) ;SAVE NUMBER OF CHARACTERS LEFT SKIPE JOBSTW(J) ;DEVICE OFF-LINE? $CALL OUTWON ;POSSIBLY. GO CHECK SKIPE J$LIOE(J) ;ERROR? $CALL OUTSTS ;READ DEVICE STATUS SKIPT ;ERROR? $CALL DEVERR ;YES -- PROCESS IT JUMPF MAIN ;STREAM HAS BEEN SHUTDOWN MOVE S1,J$LJFN(J) ;RESTORE DEVICE JFN MOVE S2,J$LBPT(J) ;RESTORE POINTER MOVE T1,J$LBCT(J) ;RESTORE COUNT JRST OUTO.1 ;RESTART SOUT > ;END TOPS20 CONDITIONAL SUBTTL TTY I/O -- Input character from TTY, no wait CSMEDT 05,5 ;TTY I/O and SLEEP, part 5 between OUTFLS and C$DISP IFN CSM05$,< INTERN TIWAIT,TTYIN,TRMERR ;Entry points for TABCDP.MAC ;Routine to input a single character from terminal into S1. ;Uses T1 and T2. TTYIN:: MOVX T1,.TOSIP ;Skip if input in progress HRRZ T2,J$TTY(J) ;Get UDX MOVE S1,[2,,T1] ;Point to args TRMOP. S1, ;Check if input JRST TTYIN1 ;Nothing there MOVX T1,.TOISC ;Input single character MOVE S1,[2,,T1] ;Point to args TRMOP. S1, ;Get the char PUSHJ P,TRMERR ;Should never happen $RETT ;Got char in S1 TTYIN1: MOVEI S1,0 ;Signify failure $RETF TRMERR::$STOP (TUF,TRMOP. UUO Failure) SUBTTL TTY I/O -- Input character, wait up to 30 seconds ;Routine to wait up to 30 seconds for a character to come in. ;Returns TRUE if char in S1, FALSE and zero in S1 if timed out TIWAIT::PUSHJ P,TTYIN ;Check for input JUMPT TIWAI2 ;Clear NACK counter if got input ;There is a good possibility that the response will come in within 1 second MOVX S1,HB.RTC+^D1000 ;Wait 1 second, wake on char ready HIBER S1, JFCL PUSHJ P,TTYIN ;Anything now? JUMPT TIWAI2 ;Return if so AOS J$NACK(J) ;No, waited 1 second already TIWAT1: $DSCHD (1) ;De-schedule this stream for 1 second PUSHJ P,TTYIN ;Input now? JUMPT TIWAI2 ;Yes, continue AOSG S1,J$NACK(J) ;No, count failure JRST TIWAT1 ;Keep waiting if negative or zero IDIVI S1,^D30 ;Set S2 modulo 30 JUMPN S2,TIWAT1 ;If less than 30 seconds, wait again HRRZ S1,STREAM ;Get stream number $WTO (,,@JOBOBA(S1)) MOVEI S1,0 ;Signify no response $RETF TIWAI2: SETZM J$NACK(J) ;Terminal is responding POPJ P, ;TF has been set to TRUE already > ;End of IFN CSM05$ SUBTTL Card punch service -- Dispatch table C$DISP: JRST C$HEAD ;(0) FILE HEADER JRST C$EOF ;(1) FILE TRAILER SIXBIT /CDP/ ;(2) GENERIC DEVICE NAME EXP ^D12 ;(3) OUTPUT BYTE SIZE JRST C$PROC ;(4) PROCESS A FILE JRST C$BANN ;(5) JOB BANNER JRST C$TRAI ;(6) JOB TRAILER JRST C$LETR ;(7) LETTER DEVICE JRST .RETF ;(10) ERROR PROCESSOR CSMEDT 04,2 ;CSM accounting, part 2 at C$DISP:+11 IFE CSM04$,< JRST .RETT > ;(11) ACCOUNTING IFN CSM04$,< JRST CSMACT > ;(11) Accounting JRST C$CHKP ;(12) CHECKPOINT TEXT GENERATION IFN CSM04$,< CSMACT: MOVE S1,J$APRT(J) ;Get cards punched or feet punched MOVEM S1,J$ADRD(J) ;Save instead of disk reads $RETT > ;End of IFN CSM04$ SUBTTL Card punch service -- File processing C$PROC: LOAD S1,.FPINF(E),FP.FPF ;GET PAPER FORMAT CAILE S1,CDROUL ;WITHIN RANGE? JRST BADMOD ;NO, LOSE JUMPN S1,@C$ROUT-1(S1) ;YES, DISPATCH IF NON-ZERO CSMEDT 07,1 ;QUEUE defaults, part 1 at C$PROC:+4 IFE CSM07$,< MOVEI S1,C$MTAB ;GET ADDRESS OF MODE TABLE MOVEI S2,C$ROUT ;GET ADDRESS OF ROUTINE TABLE PJRST DSPMOD ;AND DISPATCH BASED ON MODE > ;End of CSM07$ IFN CSM07$, ;Default to ASCII mode ;TABLE OF processing ROUTINES C$ROUT: EXP CDASC ;ASCII EXP CD026 ;026 EXP CDBIN ;CHECKSUMMED BINARY EXP CDASC ;ASCII EXP CDIMA ;IMAGE AND IMAGE BINARY CDROUL==.-C$ROUT ;LENGTH OF ROUTINE TABLE ;MODE TABLE C$MTAB: BYTE (3) 1,1,0,0,0,0,0,0,5,0,0,5,3,0,3,3 SUBTTL Card punch service -- File headers C$HEAD: SKIPN J$FHEA(J) ;HEADER ALLOWED? $RETT ;NO -- RETURN CSMEDT 07,2 ;QUEUE defaults, part 2 at C$HEAD:+2 IFE CSM07$,< ;Ignore QUEUE's default of /NOHEADER, always punch it LOAD S1,.FPINF(E),FP.NFH ;GET NO FILE HEADER BIT JUMPN S1,.RETT ;RETURN IF NOT WANTED > ;End of IFN CSM07$ MOVEI C,4001 ;SPECIAL MASK FOR FILE CARDS MOVEM C,J$CMSK(J) ;SAVE FOR C$LETR MOVE S1,J$DFDA(J) ;POINT TO FD SKIPN S2,J$DSPN(J) ;SPOOL NAME? TOPS10< MOVE S2,.FDNAM(S1) > ;NO -- USE FILE NAME TOPS20< MOVX S1,GJ%SHT!GJ%OFG ;PARSE ONLY, SHORT JFN MOVE S2,J$DFDA(J) ;GET FD ADDRESS HRROI S2,.FDSTG(S2) ;POINT TO START OF FILESPEC GTJFN ;GET A JFN ERJMP .POPJ ;ASSUME A SPOOLED FILE MOVE S2,[POINT 7,FILNAM] ;POINT TO FILENAME STORAGE EXCH S1,S2 ;S1:= POINTER, S2:= JFN MOVE T1,[FILNAM,,FILNAM+1] ;SET UP BLT SETZM FILNAM ;CLEAR THE FIRST WORD BLT FILNAM+7 ;CLEAR THE ENTIRE BLOCK MOVX T1,1B8 ;WANT FILENAME ONLY JFNS ;GET IT HRROI S1,FILNAM ;POINT TO THE FILENAME $CALL S%SIXB ;CONVERT TO SIXBIT > MOVEI S1,[ITEXT<^W6/S2/>] ;POINT TO NAME PJRST C$WORD ;PUNCH CARD AND RETURN SUBTTL Card punch service -- File trailers C$EOF: MOVEI S1,^D80 ;PUNCH EOF CARD MOVEI C,7417 ;TOP FOUR AND BOTTOM FOUR ROWS PUSHJ P,CDPREP ;PUNCH EOF CARDS ;[CSM] PJRST OUTOUT ;FORCE OUTPUT PJRST OUTCD1 ;[CSM] ;FORCE OUTPUT SUBTTL Card punch service -- Banners C$BANN: CSMEDT 06,1 ;TTY CDP, part 1 at C$BANN: IFN CSM06$,< ;Set terminal to PUNCH+PRINT mode if /FORMS:NORMAL MOVEI S1,J$FORM(J) ;Get forms name CAMN S1,['NORMAL'] ;Normal forms? MOVEI S1,0 ;Yes, turn on print mode SKIPE S2,J$TTY(J) ;Punch really a terminal? PUSHJ P,TABINI## ;Yes, set it up > ;End of IFN CSM06$ SKIPN J$FBAN(J) ;BANNER cards wanted? $RETT ;RETURN IF ZERO MOVEI C,4003 ;MASK FOR JOB CARDS MOVEM C,J$CMSK(J) ;SAVE FOR C$LETR CSMEDT 07,3 ;QUEUE defaults, part 3 at C$BANN:+4 IFE CSM07$,< ;"BEGIN: JOB jobnam USER:" wastes 4 cards. MOVEI S1,[ITEXT] PJRST CTRA.1 ;FALL INTO COMMON CODE > ;End of IFE CSM07$ IFN CSM07$,< ;Punch just NAME, PPN, and NOTE (if any) PJRST CTRA.2 ;Punch user name > ;End of IFN CSM07$ IFE CSM06$,< C$TRAI: SKIPN J$FTRA(J) ;Check TRAILER wanted flag $RETT ;RETURN IF ZERO > ;End of IFE CSM06$ IFN CSM06$,< ;Call TABFIN after all is done C$TRAI: SKIPE J$FTRA(J) ;Trailer cards wanted? $CALL CTRA.0 ;Yes SKIPE J$TTY(J) ;Output to a TTY? PUSHJ P,TABFIN## ;Yes, finish up $RETT CTRA.0: > ;End of IFN CSM06$ MOVEI C,4003 ;MASK FOR JOB CARDS MOVEM C,J$CMSK(J) ;SAVE FOR C$LETR MOVEI S1,[ITEXT] CTRA.1: $CALL C$WORD MOVEI S1,[ITEXT<^W6/.EQJOB(J)/>] $CALL C$WORD MOVEI S1,[ITEXT ] PUSHJ P,C$WORD MOVEI S1,[ITEXT<#^D5R0/.EQJBB+JIB.ID(J)/>] ;REQUEST ID $CALL C$WORD MOVEI S1,[ITEXT] $CALL C$WORD $CALL SETTBF ;POINT TO TEXT BUFFER CONT. (C$BANN) IFN CSM07$,< CTRA.2: > ;Here to skip over garbage TOPS10 < ;TOPS-10 ONLY MOVEI S1,[ITEXT <^W6/.EQJBB+JIB.NM(J)/>] ;USER NAME (WORD 1) PUSHJ P,C$WORD ;PUNCH IT MOVEI S1,[ITEXT <^W6/.EQJBB+JIB.NM+1(J)/>] ;USER NAME (WORD 2) PUSHJ P,C$WORD ;PUNCH IT MOVEI S1,[ITEXT <^O6R /.EQOID(J),LHMASK/>] ;PROJECT NUMBER PUSHJ P,C$WORD ;PUNCH IT MOVEI S1,[ITEXT <^O6L /.EQOID(J),RHMASK/>] ;PROGRAMMER NUMBER PUSHJ P,C$WORD ;PUNCH IT > ;END TOPS-10 CONDITIONAL TOPS20 < MOVE TF,[POINT 6,FILNAM] ;GET BYTE POINTER MOVEM TF,TEXTBP ;STORE THE BYTE POINTER MOVEI TF,TXT$LN*^D12 ;GET BYTE COUNT MOVEM TF,TEXTBC ;AND SAVE IT SETZM FILNAM+0 ;CLEAR A WORD SETZM FILNAM+1 ;CLEAR ANOTHER WORD $TEXT (DEP6BP,<^T/.EQOWN(J)/^A>) ;ALLOW UP TO 12 CHARACTER NAMES MOVEI S1,[ITEXT <^W6/FILNAM+0/>] ;WORD 1 PUSHJ P,C$WORD ;OUTPUT IT MOVEI S1,[ITEXT <^W6/FILNAM+1/>] ;WORD 2 SKIPE FILNAM+1 ;IS THERE A SECOND WORD? PUSHJ P,C$WORD ;OUTPUT IT PUSHJ P,SETTBF ;RESET BYTE POINTER AND COUNT > GETLIM T1,.EQLIM(J),NOT1 ;GET /NOTE VALUE (WORD 1) GETLIM T2,.EQLIM(J),NOT2 ;GET /NOTE VALUE (WORD 2) SKIPN T1 ;RETURN IF BOTH JUMPE T2,.RETT ; WORDS ARE ZERO MOVEI S1,[ITEXT] PUSHJ P,C$WORD ;PUNCH IT GETLIM T1,.EQLIM(J),NOT1 ;GET /NOTE VALUE (WORD 1) MOVEI S1,[ITEXT<^W6/T1/>] PUSHJ P,C$WORD ;PUNCH IT GETLIM T1,.EQLIM(J),NOT2 ;GET /NOTE VALUE (WORD 2) JUMPE T1,.RETT ;RETURN IF NO SECOND WORD MOVEI S1,[ITEXT<^W6/T1/>] PJRST C$WORD ;PUNCH LAST CARD AND RETURN SUBTTL Card punch service -- Word punching ;C$WORD ;Call S1/ Address of Itext to punch as 6 Character word on card ; Also J$CMSK Specifies Extra Rows to punch with Characters C$WORD: $CALL SETTBF ;SET POINTERS TO TEXT BUFFER $TEXT(DEPBP,<^I/(S1)/^0>) ;STORE STRING IN BUFFER MOVEI S1,0 ;GET A NULL DPB S1,[POINT 7,J$XTBF+1(J),13] ;TRUNCATE TO SIX CHARACTERS MOVEI C,3776 ;FIRST COLUMN WITH ROUNDED CORNERS PUSHJ P,CDPBYT MOVEI C,7777 ;SECOND COLUMN FULLY LACED PUSHJ P,CDPBYT MOVEI S1,3 ;NEXT 3 COLUMNS WITH SPECIAL MASK MOVE C,J$CMSK(J) PUSHJ P,CDPREP $CALL STRING ;COLUMNS 6-77 FOR CHARACTERS MOVE C,J$CMSK(J) ;COLUMN 78 SPECIAL MASK PUSHJ P,CDPBYT MOVEI C,7777 ;COLUMN 79 FULLY LACED PUSHJ P,CDPBYT MOVEI C,3776 ;COLUMN 80 ROUNDED CORNERS PUSHJ P,CDPBYT ;[CSM] PJRST OUTOUT ;PUNCH CARD AND RETURN PJRST OUTCD1 ;[CSM] ;PUNCH CARD AND RETURN SUBTTL Card punch service -- Byte output ; AC 'C' contains the byte to output ; CDPBYT: CSMEDT 06,2 ;TTY CDP, part 2 at CDPBYT IFE CSM06$,< PJRST OUTBYT > IFN CSM06$,< ;Special output for TAB Products Cardpunch Terminal SKIPN J$TTY(J) ;Output to a TTY? PJRST OUTBYT ;No $SAVE ;Yes, preserve ACs used MOVE S1,C ;Copy to expected AC PJRST TABBYT## ;Store byte in other buffer > ;End of IFN CSM06$ ; Force card out ; OUTCDP: AOS S1,J$APRT(J) ;COUNT ANOTHER ONE CAMLE S1,J$RLIM(J) ;OVER LIMIT? PUSHJ P,FRMLEX ;HANDLE LIMIT EXCEEDED OUTCD1: ;Output without counting IFN CSM06$,< ;Special output for TAB Products Cardpunch Terminal SKIPE J$TTY(J) ;Output to a TTY? PJRST TABPUN## ;Yes, output the card > ;End of IFN CSM06$ PJRST OUTOUT ;FORCE CARD OUT ; Repeat the byte in AC 'C' ; Call: MOVE S1,repeat count ; MOVE C,byte to output ; PUSHJ P,CDPREP ; CDPREP: PUSH P,P1 ;SAVE P1 MOVE P1,S1 ;GET COUNT ;[CSM] PUSHJ P,PTPBYT ;OUTPUT A BYTE PUSHJ P,CDPBYT ;[CSM] ;Use the right output routine SOJG P1,.-1 ;AND LOOP POP P,P1 ;RESTORE P1 POPJ P, ;RETURN SUBTTL Plotter service -- Dispatch table P$DISP: JRST P$HEAD ;(0) FILE HEADER JRST P$EOF ;(1) FILE TRAILER SIXBIT /PLT/ ;(2) GENERIC DEVICE NAME EXP ^D6 ;(3) OUTPUT BYTE SIZE JRST P$PROC ;(4) PROCESS A FILE JRST P$BANN ;(5) JOB BANNER JRST P$TRAI ;(6) JOB TRAILER JRST P$LETR ;(7) LETTER PROCESSER JRST P$DERR ;(10) DEVICE ERROR PROCESSOR CSMEDT 04,3 ;CSM accounting, part 3 at P$DISP:+11 IFE CSM04$, ;(11) ACCOUNTING IFN CSM04$, ;(11) Plotter accounting JRST P$CHKP ;(12) CHECKPOINT TEXT GENERATION IFN CSM04$,< ;Account for both elapsed time and paper used PLTACT: MOVE S1,J$XLIM(J) ;Get total X increments ADDI S1,INCS/2 ;Round up IDIVI S1,INCS ;Convert to inches EXCH S1,J$APRT(J) ;Store amount of paper used MOVEM S1,J$ADRD(J) ;Store minutes in place of disk reads $RETT > ;End of IFN CSM04$ SUBTTL Plotter service -- Checkpoint text generation P$CHKP: $SAVE ;SAVE SOME ACS MOVE P1,J$PTIC(J) ;GET # TICS FOR JOB IDIV P1,J$PTPM(J) ;P1:= MINUTES, P2:= FRACTION IMULI P2,^D10 ;[CSM] One decimal place IDIV P2,J$PTPM(J) ;P2:= DECIMAL FRACTION OF A MINUTE MOVE P3,J$RLIM(J) ;GET LIMIT CAMN P3,[.INFIN] ;+INFINITY? JRST P$CHK1 ;YES CAMG P1,J$RLIM(J) ;OPERATOR ALLOW LIMIT TO EXCEED? $TEXT (DEPBP,) CAMLE P1,J$RLIM(J) ;OPERATOR ALLOW LIMIT TO EXCEED? P$CHK1: $TEXT (DEPBP,) POPJ P, ;RETURN SUBTTL Plotter service -- File processing P$PROC: LOAD S1,.FPINF(E),FP.FPF ;GET PAPER FORMAT CAILE S1,PLROUL ;WITHIN RANGE? JRST BADMOD ;NO, LOSE JUMPN S1,@P$ROUT-1(S1) ;YES, DISPATCH IF NON-ZERO CSMEDT 07,4 ;QUEUE defaults, part 4 at P$PROC:+4 IFE CSM07$,< ;This code removed because all plots must be BINARY halfwords MOVEI S1,P$MTAB ;GET ADDRESS OF MODE TABLE MOVEI S2,P$ROUT ;GET ADDRESS OF ROUTINE TABLE PJRST DSPMOD ;AND DISPATCH BASED ON MODE > ;End of IFE CSM07$ IFN CSM07$,< JRST PLTHLF > ;Default always to halfword format P$ROUT: EXP PLTSIX ;/PLOT:IMAGE (6 BIT) EXP PLTSVN ;/PLOT:ASCII (7 BIT) CSMEDT 02,1 ;Halfword format, part 1 at P$ROUT:+3 IFE CSM02$, ;/PLOT:BINARY (6 BIT) IFN CSM02$, ;/PLOT:BINARY (18 bit) PLROUL==.-P$ROUT ;LENGTH OF ROUTINE TABLE ;MODE TABLE P$MTAB: BYTE (3) 2,2,0,0,0,0,0,0,1,0,0,1,1,1,1,1 SUBTTL Plotter service -- Expand CSM's compressed plot format CSMEDT 02,2 ;Halfword format, part 2 after PLTLP0: IFN CSM02$,< ;Read halfwords from disk COMMENT ~ Do not use many semicolons, it confuses FILCOM's /C switch !=======================================================! ! ! ! PLOTTER MODE -- 18 BIT ! ! ! ! In 18 bit mode, each word read from disk is divided ! ! into halfwords, which are interpreted by subroutine ! ! TOLP. Most halfwords have 9 bits of delta-X and ! ! 9 bits of delta-Y, special opcodes raise and lower ! ! the pen. See TOLP.MAC for a full description. ! ! ! !=======================================================! ! Delta Y ! Delta X ! Delta Y ! Delta X ! !=======================================================! Call TOLP. with S1/ Addr of input routine, which returns data in S1, -1 on EOF S2/ 0 to suppress header/trailer, 1 for header, 2 for trailer, 3 for both T1/ Current X position (should be same as J$XMIN) T2/ Current Y position (should be same as J$YMIN) On return, ACs 7-16 have been preserved TF/ Garbage S1/ Garbage S2/ Addr of error message, or 0 if no error T1-T4/ Garbage ~ ;End of COMMENT EXTERN TOLP. ;Routine to reverse PLOT INTERN PLOT ;Routine to move the pen INTERN NEWPEN,OPRTXT,PAUSEP,TITLE ;Other routines called by TOLP ND INCS,^D400 ;Steps per inch (620 octal) SUBTTL Plotter service -- READ36, OPRTXT, PAUSEP, TITLE for TOLP ;Routine to read a word from the input file, returns -1 for EOF, -2 if ABORT READ36: MOVE S1,J$PTIC(J) ;Get tics plotted IDIV S1,J$PTPM(J) ;Convert to minutes CAMLE S1,J$RLIM(J) ;Still in range? PUSHJ P,FRMLEX ;No, complain PUSHJ P,INPBYT ;Get a word MOVE T1,C ;Copy to expected AC JUMPT .POPJ ;Use it if OK MOVNI T1,1 ;-1 for EOF TXNE S,RQB+ABORT ;Unless OPR caused EOF MOVNI T1,2 ;-2 for ABORT POPJ P, ;Continue back in TOLP ;Routine to send a message to the OPR. ;Called with byte count in S1, addr of ASCIZ message in S2. OPRTXT: PUSHJ P,PLTOUT ;Dump buffers HRRZ S1,STREAM ;Get the stream number $WTO (OPRTXT message,<^T/0(S2)/>,@JOBOBA(S1)) ;Tell OPR POPJ P, ;Routine to pause the plotter. ;Zero in S1 means to wait for human intervention, nonzero causes graphic ;terminals to pause that many seconds before automatically resuming. PAUSEP: PUSHJ P,PLTOUT ;Dump the buffers JUMPN S1,.POPJ ;Nonzero valid for graphics terminals PUSHJ P,SETTBF ;Set up WTO buffer PJRST FORM.3 ;Wait for a "PROCEED" response ;Routine to plot text. ; T1/ Height in increments ; T2/ Addr of text ; T3/ Angle in degrees, 0 to 359 ; T4/ Byte count for text TITLE: POPJ P, ;Not implemented PLTOUT: IFE CSM08$,< PJRST OUTOUT > IFN CSM08$,< SKIPE J$TTY(J) ;Output to a TTY? PJRST OUTOUT ;No PUSHJ P,PTCOUT## ;Yes, get ready to output last buffer SETZM J$PPOS(J) ;PTCOUT always raises the pen PJRST OUTRSP ;Output string and wait for response > ;End of IFN CSM08$ > ;End of IFN CSM02$ SUBTTL Plotter service -- NEWPEN for 3-pen plotter CSMEDT 01,3 ;3-Pen plotter, part 3 before P$DERR IFN CSM01$,< PEN.1: MOVEI S1,1 ;Set to blue pen JRST NEWPEN PEN.2: MOVEI S1,2 ;Set to black pen JRST NEWPEN PEN.3: MOVEI S1,3 ;Set to red pen and fall into NEWPEN JRST NEWPEN ND PENSEP,INCS*4/4 ;Pen separation is 1 inch or 3/4 inch CHGPEN: BYTE (6) CNGP,PNDN,0 ;Codes to change to pen #1 BYTE (6) CNGP,PEN2,PNDN,0 ; #2 BYTE (6) CNGP,PEN3,PNDN,0 ; #3 ;Routine to change pens. Called with pen number in S1, trashes it and S2. NEWPEN: $SAVE ;Save preserved ACs ;Make sure pen number in S1 is between 1 and 3 inclusive SUBI S1,1 ;Change to number from 0 to 2 IDIVI S1,3 ;Set S2 modulo 3 AOS P2,S2 ;Copy new pen number (from 1 to 3) CSMEDT 08,2 ;PTC-6 Plotter Controller, part 2 in NEWPEN IFN CSM08$,< ;Special codes for PTC-6 SKIPE J$TTY(J) ;Using a terminal line? JRST [PUSHJ P,PTCPEN## ;Yes, tell it (pen number in S2) JRST NEWPN2 ] ;Then move the pen holder > ;End of IFN CSM08$ MOVEI P1,CHGPEN-1(S2) ;Get addr of data HRLI P1,(POINT 6,) ;Make into byte pointer PUSHJ P,PENUP ;Raise any and all pens ;Output the codes to select new pen (even if it was previously selected) NEWPN1: ILDB C,P1 ;Get a byte PUSHJ P,PLTBTX ;Send to plotter (even if no-op) JUMPN C,NEWPN1 ;Loop till no-op is sent ;When pen #1 is positioned at Y=5.0, then pen #2 is at Y=4.0 and pen #3 ;is at Y=3.0. Therefore, when changing from pen #1 to pen #2 (or 2 to 3), ;the pen holder must be moved 1.0 inches in the +Y direction, without ;affecting J$YPOS and in spite of J$YMAX and J$YMIN. NEWPN2: MOVE P1,P2 ;Copy new pen number SUB P1,J$PENN(J) ;Find change (+1 if from pen 1 to pen 2) JUMPE P1,.POPJ ;All done if same as previous pen EXCH P2,J$PENN(J) ;Set new, get old JUMPE P2,.POPJ ;All done if called from P$CPEN IMULI P1,PENSEP ;Distance between pens SKIPL P1 ;If going plus, ADDM P1,J$YMAX(J) ; allow blue pen to move off the paper SKIPG P1 ;If going minus, ADDM P1,J$YMIN(J) ; allow red pen to move off the paper MOVE T1,J$XPOS(J) ;No change in X MOVE T2,P1 ;Delta Y ADD T2,J$YPOS(J) ;New Y position MOVEI T3,PN.UP ;Raise the pen PUSHJ P,PLOT ;Move the pen holder into position MOVNS P1 ;Cancel the offset SKIPG P1 ;If used to be positive, ADDM P1,J$YMAX(J) ; reset max limit SKIPL P1 ;If used to be negative, ADDM P1,J$YMIN(J) ; reset min limit ADDM P1,J$YPOS(J) ;New pen is where previous one was POPJ P, ;Routine to output bytes to plotter, passing nulls and CNGP codes correctly. ;Note: When changing pens, the first PNDN code does NOT lower the pen. PLTBTX: MOVEI S1,PLTMOV ;Load # tics for movement CAIN C,PNDN ;Pen down code? MOVEI S1,PLTPEN ;Load # tics for pen up/down ADDM S1,J$PTIC(J) ;Add in for accounting PJRST OUTBYT ;Bypass J$ROTA check > ;End of IFN CSM01$ SUBTTL Plotter service -- Banners CSMEDT 03,1 ;Banner changes, part 1 at P$BANN: ;*; IFN CSM03$, ND NAMSIZ,3 ;User's name will be 3 times larger than other text P$BANN: CSMEDT 08,3 ;PTC-6 Plotter Controller, part 3 at P$BANN IFN CSM08$,< SKIPE J$TTY(J) ;PTC-6 controller? PUSHJ P,[MOVEI T1,PLTPEN ;Yes, positive to use CR handshake PUSHJ P,PTCINI## ;Initialize terminal PJRST OUTRSP ] ;Output string to TTY > ;End of IFN CSM08$ PUSHJ P,P$CPEN ;RE-CALIBRATE THE PEN SKIPN J$FBANN(J) ;BANNER WANTED? POPJ P, ;NO - JUST RETURN PUSH P,J$PTIC(J) ;DON'T CHARGE FOR PLOTTER OVERHEAD MOVEI S1,[ASCIZ |Start|] ;GET LINE IDENTIFIER PUSHJ P,PLTJOB ;PLOT JOB INFORMATION BANN.1: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IFN NAMSIZ-1,< ;Start a separate line ADD T1,J$XPOS(J) ;POINT TO NEXT LINE MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION > ;End of IFN NAMSIZ-1 IFE NAMSIZ-1,< ;Put LIMIT on same line as user name MOVE T2,T1 ;Copy character size ADD T2,J$YPOS(J) ;Space over a bit in plus-Y direction MOVE T1,J$XPOS(J) ;Current X position > ;End of IFN NAMSIZ-1 MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;MOVE THE PEN PUSHJ P,SETTBF ;SET UP TEXT BUFFER $TEXT (DEPBP,< Limit: ^D/J$RLIM(J)/, Forms: ^W/J$FORM(J)/^A>) BANN.2: GETLIM T1,.EQLIM(J),NOT1 ;GET /NOTE VALUE (WORD 1) GETLIM T2,.EQLIM(J),NOT2 ;GET /NOTE VALUE (WORD 2) SKIPN T1 ;CHECK WORD 1 SKIPE T2 ;CHECK WORD 2 $TEXT (DEPBP,<, Note: ^W6/T1/^W/T2/^A>) ;YES MOVEI S1,.CHNUL ;GET A PUSHJ P,DEPBP ;STORE IT PUSHJ P,STRING ;PLOT STRING POP P,J$PTIC(J) ;RESTORE # PLOTTER TICS POPJ P, ;RETURN SUBTTL Plotter service -- File headers P$HEAD: PUSH P,J$PTIC(J) ;DON'T CHARGE FOR PLOTTER OVERHEAD PUSHJ P,P$DASH ;SEPARATE FROM BANNER OR LAST FILE SKIPN J$FHEA(J) ;HEADER ALLOWED? PJRST P$HEA1 ;NO..POSITION TO ORIGIN LOAD S1,.FPINF(E),FP.NFH ;GET NO FILE HEADER BIT JUMPN S1,P$HEA1 ;SKIP IF NOT WANTED PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE $CALL SETTBF ;SETUP TO PRINT STIRNG MOVE S1,J$DIFN(J) ;GET FILE IFN MOVEI S2,FI.CRE ;GET CREATION DATE TIME $CALL F%INFO MOVEI S2,[ITEXT (<>)] ;ASSUME NOT /DISPOSE:RENAME SKIPE J$DSPN(J) ;WAS IT /DISPOSE:RENAME? MOVEI S2,[ITEXT (< (^W/J$DSPN(J)/.^W/J$DSPX(J)/)>)] ;YES CSMEDT 02,3 ;Halfword format, part 3 at P$HEA1:-2 IFE CSM02$,< $TEXT (DEPBP,<* File: ^F/@J$DFDA(J)/^I/(S2)/ created:^H/S1/ *^0>) > IFN CSM02$,< $TEXT (DEPBP,<* File: ^F/@J$DFDA(J)/^I/(S2)/ *^0>) > ;CSM internal headers have creation date/time PUSHJ P,STRING ;PLOT TEXT P$HEA1: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE ADD T1,J$XPOS(J) ;OFFSET BY CURRENT POSITION MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN MOVE T1,J$XPOS(J) ;GET CURRENT X POSITION MOVEM T1,J$XMIN(J) ;UPDATE NEW MINIMUM IFN CSM01$,< ;Allow plots to butt up against each other ADDI T1,INCS/2 ;Set lowest seen to 1/2 inch margins MOVEM T1,J$XLOW(J) ;(not fully implemented yet) > ;End of IFN CSM01$ POP P,J$PTIC(J) ;RESTORE # PLOTTER TICS POPJ P, ;RETURN SUBTTL Plotter service -- File trailers P$EOF: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE ADD T1,J$XLIM(J) ;POSITION BEYOND THE HIGHEST X STEP MOVE T2,J$YMIN(J) ;GO BACK TO THE MARGIN MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN CSMEDT 08,4 ;PTC-6 Plotter Controller, part 4 at end of P$EOF IFN CSM08$,< ;Call PTCOUT instead of OUTOUT SKIPE J$TTY(J) ;PTC-6 controller? JRST [PUSHJ P,PTCOUT## ;Yes, raise pen PJRST OUTRSP ] ;Wait for response > ;End of IFN CSM08$ PJRST OUTOUT ;DUMP WHAT WE HAVE SUBTTL Plotter service -- Job trailers P$TRAI: CSMEDT 03,3 ;Banner changes, part 3 at P$TRAI: IFE CSM03$,< ;This test prevents error messages from coming out PUSHJ P,P$DASH ;SEPARATE FROM LAST FILE PUSH P,J$PTIC(J) ;DON'T CHARGE FOR PLOTTER OVERHEAD SKIPN J$FTRA(J) ;TRAILER ALLOWED? JRST P$TRA3 ;NO > ;End of IFE CSM03$ IFN CSM03$,< ;Output dashed line only if text will be plotted PUSH P,J$PTIC(J) ;Don't charge for plotter overhead SKIPN J$FTRA(J) ;Plot the trailer? SKIPE J$XERR(J) ; or an error message? PUSHJ P,P$DASH ;Yes, separate text from plot > ;End of IFN CSM03$ SKIPN J$XERR(J) ;ANY ERROR TEXT? JRST P$TRA0 ;NO - ONWARD PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,2 ;[CSM] ;Make room for characters ADD T1,J$XPOS(J) ;POINT TO NEXT LINE MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN PUSHJ P,SETTBF ;SET UP TEXT BUFFER $TEXT (DEPBP,<^T/J$XERR(J)/^0>) ;INCLUDE ERROR TEXT PUSHJ P,STRING ;PLOT ERROR TEXT P$TRA0: IFN CSM03$,< ;Check for /TRAILER after plotting error message SKIPN J$FTRA(J) ;Trailer wanted? JRST P$TRA3 ;No, skip job line and summary > ;End of IFN CSM03$ MOVEI S1,[ASCIZ |End|] ;GET LINE IDENTIFIER PUSHJ P,PLTJOB ;PLOT JOB LINE CONT. (P$TRAI) P$TRA1: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IFN NAMSIZ-1,< ;Start a separate line ADD T1,J$XPOS(J) ;POINT TO NEXT LINE MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION > ;End of IFN NAMSIZ-1 IFE NAMSIZ-1,< ;Put SUMMARY on same line as user name MOVE T2,T1 ;Copy character size ADD T2,J$YPOS(J) ;Space over a bit in plus-Y direction MOVE T1,J$XPOS(J) ;Current X position > ;End of IFN NAMSIZ-1 MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN PUSHJ P,SETTBF ;SET UP TEXT BUFFER LOAD T1,.EQSPC(J),EQ.NUM ;GET NUMBER OF FILES MOVEI T2,[ITEXT ()] ;ASSUME 1 FILE CAIE T1,1 ;WAS IT MOVEI T2,[ITEXT ()] ;NO $TEXT (DEPBP,< Summary: ^D/T1/ ^I/(T2)/^A>) P$TRA2: MOVE T1,(P) ;GET # TICS FOR JOB IDIV T1,J$PTPM(J) ;T1:= MINUTES, T2:= FRACTION IMULI T2,^D10 ;[CSM] 1 decimal place (=6 seconds) IDIV T2,J$PTPM(J) ;T2:= DECIMAL FRACTION OF A MINUTE $TEXT (DEPBP,< plotted in ^D/T1/.^D/T2/ minutes^0>) PUSHJ P,STRING ;PLOT TEXT P$TRA3: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,2 ;LEAVE THIS MUCH SPACE ADD T1,J$XPOS(J) ;OFFSET BY CURRENT POSITION PUSHJ P,P$LINE ;PLOT SEPARATOR PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,2 ;POINT TO NEXT LINE ADD T1,J$XPOS(J) ;OFFSET BY CURRENT POSITION MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN POP P,J$PTIC(J) ;RESTORE # PLOTTER TICS MOVE T1,J$PTIC(J) ;GET # TICS IDIV T1,J$PTPM(J) ;GET MINUTES OF PLOTTER TIME MOVEM T1,J$APRT(J) ;STORE IT CSMEDT 08,5 ;PTC-6 Plotter Controller, part 5 at end of P$TRAI IFN CSM08$,< SKIPE J$TTY(J) ;PTC-6 controller? PUSHJ P,[PUSHJ P,PTCOUT## ;Yes, raise pen PUSHJ P,OUTRSP ;Wait for response PUSHJ P,PTCFIN## ;Finish up and deselect PJRST OUTSTG ] ;Output string to TTY > ;End of IFN CSM08$ POPJ P, ;RETURN SUBTTL Plotter service -- Solid lines ; This routine does the following: ; 1. Position to the next line ; 2. Plot a solid line ; 3. Position to the next line ; P$LINE: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE ADD T1,J$XPOS(J) ;POINT TO NEXT LINE CSMEDT 03,4 ;Banner changes, part 4 at P$LINE:+2 IFE CSM03$,< ;Going from MIN to MAX when pen is near MAX wastes time MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN MOVE T1,J$XPOS(J) ;Use current X position MOVE T2,J$YMAX(J) ;GET MAXIMUM Y VALUE > ;End of IFE CSM03$ IFN CSM03$,< ;Go to MAX, then to MIN and end there MOVE T2,J$YMAX(J) ;Go to closer end point CAIL T2,INCS*6 ;More than 6 inches? MOVEI T2,INCS*6 ;Yes, don't waste inc MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;Position pen MOVE T1,J$XPOS(J) ;Use current X position MOVE T2,J$YMIN(J) ;Go to "HOME" position > ;End of IFE CSM03$ MOVEI T3,PN.DWN ;Pen down PUSHJ P,PLOT ;PLOT A LINE LINE.1: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,2 ;LEAVE SOME SPACE ADD T1,J$XPOS(J) ;POSITION TO NEXT LINE MOVE T2,J$YMIN(J) ;GET MINIMUM Y VALUE MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN AT START OF NEXT LINE PUSHJ P,OUTOUT ;DUMP BUFFERS POPJ P, ;RETURN SUBTTL Plotter service -- Dashed lines ; This routine works like P$LINE, but line is drawn with dashes. ; The length of each dash is the same as the height of the characters P$DASH: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE ADD T1,J$XPOS(J) ;POINT TO NEXT LINE CSMEDT 03,5 ;Banner changes, part 5 at P$DASH:+3 IFE CSM03$,< MOVE T2,J$YMIN(J) > ;GET MINIMUM Y POSITION IFN CSM03$,< MOVE T2,J$YMAX(J) ;Get maximum Y position CAIL T2,INCS*6 ;More than 6 inches? MOVEI T2,INCS*6 ;Yes, don't waste time and ink > ;End of IFN CSM03$ MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN DASH.1: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IFE CSM03$,< ADD T1,J$YPOS(J) ;ADD TO Y POSITION CAML T1,J$YMAX(J) ;GONE TOO FAR? > ;End of IFE CSM03$ IFN CSM03$,< MOVNS T1 ;Make negative ADD T1,J$YPOS(J) ;Decrement Y position CAMG T1,J$YMIN(J) ;Gone too far? > ;End of IFN CSM03$ JRST LINE.1 ;YES - FINISH UP MOVE T2,T1 ;PUT IN PROPER PLACE MOVE T1,J$XPOS(J) ;GET X POSITION MOVEI T3,PN.DWN ;Pen down PUSHJ P,PLOT ;PLOT A LINE DASH.2: PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IFE CSM03$,< ADD T1,J$YPOS(J) ;ADD TO Y POSITION CAML T1,J$YMAX(J) ;GONE TOO FAR? > ;End of IFE CSM03$ IFN CSM03$,< MOVNS T1 ;Make negative ADD T1,J$YPOS(J) ;Decrement Y position CAMG T1,J$YMIN(J) ;Gone too far? > ;End of IFN CSM03$ JRST LINE.1 ;YES - FINISH UP MOVE T2,T1 ;PUT IN PROPER PLACE MOVE T1,J$XPOS(J) ;GET X POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;PLOT A LINE JRST DASH.1 ;GO BACK AND DO IT AGAIN SUBTTL Plotter service -- Job information plotting ; Here to job information for banner and trailer lines ; Call: MOVEI S1,[ASCIZ |Start|] ;OR [ASCIZ |End|] ; PUSHJ P,PLTJOB ; PLTJOB: PUSH P,S1 ;SAVE TEXT POINTER PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,2 ;MOVE OUT A BIT ADD T1,J$XPOS(J) ;OFFSET BY CURRENT POSITION MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN PUSHJ P,SETTBF ;SET UP TEXT BUFFER CSMEDT 03,6 ;Banner changes, part 6 at PLTJOB:+8 IFN CSM03$,< PUSHJ P,PEN.3 > ;Do "*START*" in red MOVE T1,.EQJBB+JIB.JN(J) ;GET JOB NAME MOVE T2,.EQJBB+JIB.ID(J) ;GET REQUEST ID POP P,T3 ;RESTORE TEXT POINTER $TEXT (DEPBP,<* ^T/(T3)/ Job ^W/T1/ req #^D/T2/ ^H/[-1]/ ^T/(T3)/ *^0>) PUSHJ P,STRING ;PLOT STRING PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,NAMSIZ+1 ;[CSM] ;Size of name plus blank space ADD T1,J$XPOS(J) ;OFFSET BY CURRENT POSITION MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;MOVE THE PEN PUSHJ P,SETTBF ;SET UP POINTERS TO THE BUFFER PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,NAMSIZ ;[CSM] ;The name is bigger than other text MOVEM T1,J$CSIZ(J) ;STORE IT IFN CSM03$,< PUSHJ P,PEN.2 > ;Do user's name in black CONT. (PLTJOB) ;PLOT THE USERS NAME TOPS10< DMOVE T3,.EQOWN(J) ;Name and PPN, 28 chars max $TEXT (DEPBP,< ^W6/T3/^W/T4/ ^P/.EQOID(J)/^0>) > TOPS20< $TEXT (DEPBP,< ^T/.EQOWN(J)/^0>) > PUSHJ P,STRING ;PLOT THE STRING PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE ADD T1,J$XPOS(J) ;POINT TO NEXT LINE MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN IFN CSM03$,< PUSHJ P,PEN.1 > ;Next dividing line will be blue POPJ P, ;RETURN SUBTTL Plotter service -- Alignment and testing REPEAT 0,< ; Routine to test character plots ; P$TEST: $SAVE ;SAVE P1 PUSHJ P,SETTBF ;SET UP TEXT BUFFER PUSHJ P,P$CPEN ;CALIBRATE THE PEN MOVEI C,.CHNUL ;START WITH TEST.1: PUSH P,C ;SAVE CHARACTER MOVEI S1,.CHNUL ;[CSM] ;Terminate previous string PUSHJ P,DEPBP ;[CSM] ; (in case of /NOTE: in SPFORM.INI) PUSHJ P,STRING ;OUTPUT TEXT PUSHJ P,P$CHKS ;COMPUTE CHARACTER SIZE IMULI T1,2 ;WANT DOUBLE HEIGHT CHARACTERS MOVEM T1,J$CSIZ(J) ;REMEMBER IT ADD T1,J$XPOS(J) ;OFFSET BY CURRENT POSITION MOVE T2,J$YMIN(J) ;GET MINIMUM Y POSITION MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN PUSHJ P,SETTBF ;SET UP TEXT BUFFER POP P,C ;RESTORE CHARACTER CAIN C,200 ;DONE ALL CHARACTERS? PJRST OUTOUT ;PLOT TEXT AND RETURN MOVEI P1,40 ;SET UP COUNTER TEST.2: SKIPN S1,C ;GET CHARACTER MOVEI S1," " ;STRING SUBROUTINE CAN'T HANDLE PUSHJ P,DEPBP ;PUT CARACTER ADDI C,1 ;ADVANCE TO NEXT CHARACTER SOJLE P1,TEST.1 ;DONE WITH THIS LINE? JRST TEST.2 ;NO > SUBTTL Plotter service -- Pen calibration ;This is the only place that J$XPOS is reset. It is called from P$BANN. P$CPEN: MOVE T1,J$YMAX(J) ;GET THE MAXIMUM Y VALUE WE KNOW ABOUT CSMEDT 01,4 ;3-pen plotter, part 4 at end of P$CPEN IFN CSM01$,< ;Assume pen is positioned close to the origin CAIL T1,INCS*4 ;More than 4 inches? MOVEI T1,INCS*4 ;Yes, don't waste time ramming the pen > ;End of IFN CSM01$ MOVEM T1,J$YPOS(J) ;FAKE OUT THE LOW LEVEL OUTPUT ROUTINE PUSH P,J$YMIN(J) ;SAVE MINIMUM Y POSITION SETZM J$YMIN(J) ;CLEAR SO WE CAN GO BELOW IT MOVE T1,J$XPOS(J) ;Use current X position MOVEI T2,0 ;RAM THE PEN INTO THE AXIS MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;POSITION PEN SETZM J$XMIN(J) ;ZERO X MINIMUM SETZM J$YMIN(J) ;ZERO Y MINIMUM SETZM J$XPOS(J) ;ZERO X POSITION SETZM J$YPOS(J) ;ZERO Y POSITION MOVE T1,J$XORG(J) ;GET ORIGINAL X MINIMUM MOVE T2,(P) ;GET MINIMUM Y VALUE MOVEI T3,PN.UP ;Pen up PUSHJ P,PLOT ;PUT PEN THERE MOVE T1,J$XORG(J) ;GET ORIGINAL X MINIMUM MOVEM T1,J$XMIN(J) ;STORE IT POP P,J$YMIN(J) ;RESTORE MINIMUM Y POSITION IFN CSM01$,< ;RECAL has positioned pen #1 at YMIN SETZM J$PENN(J) ;Flag that pen holder was reset MOVEI S1,1 ;Select pen number 1 PUSHJ P,NEWPEN ;Tell the plotter which pen to use > ;End of IFN CSM01$ POPJ P, ;RETURN SUBTTL Plotter service -- Compute character size P$CHKS: MOVE T1,J$YMAX(J) ;CALCULATE SIZE SUB T1,J$YMIN(J) ; OF PLOTTING AREA IDIVI T1,CHRPLN ;MAXIMUM NUMBER OF CHARACTERS PER LINE CSMEDT 01,5 ;3-Pen plotter, part 5 at P$CHKS:+3 IFN CSM01$,< ;Don't plot giant letters on 36 inch wide paper CAIL T1,INCS/6 ;Bigger than 1/6 inch? MOVEI T1,INCS/6 ;Yes, reduce size > ;End of IFN CSM01$ MOVEM T1,J$CSIZ(J) ;STORE CHARACTER SIZE POPJ P, ;RETURN SUBTTL Plotter service -- Line segments ;Call T1/ X Coordinate to move to ; T2/ Y Coordinate to move to ; T3/ Pen code as follows PN.SAM==1 ;No Change in Pen PN.DWN==2 ;Pen Down before Plotting PN.UP== 3 ;Pen Up before moving ; PLOT: $SAVE ;PRESERVE TEMPORARIES CSMEDT 08,6 ;PTC-6 Plotter Controller, part 6 at PLOT:+1 IFN CSM08$,< ;Delay testing of T3 if output to a terminal SKIPN J$TTY(J) ;Is the plotter really a TTY? > ;End of IFN CSM08$ CAIG T3,PN.SAM ;CHANGE REQUESTED? JRST PLT.1 ;NO..PROCEED SUBI T3,PN.UP ;Yes, get -1 or 0 CAMN T3,J$PPOS(J) ;PEN IN POSITION? JRST PLT.1 ;YES -- PROCEED MOVEI C,PNUP ;GET PEN UP CODE SKIPGE T3 ;WANT IT LOWERED? MOVEI C,PNDN ;YES..GET THE CODE $CALL PLTBYT ;MOVE THE PEN PLT.1: SUB T1,J$XPOS(J) ;COMPUTE DELTA X SUB T2,J$YPOS(J) ;COMPUTE DELTA Y IFN CSM08$,< ;Call external routine if PTC-6 SKIPE J$TTY(J) ;TTY? (T1, T2, and T3 set up) JRST PTCMV ;Yes, calculate character string > ;End of IFN CSM08$ MOVEI T3,XYD ;ASSUME DOWN MOVEMENT SKIPG T1 ;IS THAT CORRECT? MOVEI T3,XYU ;NO..ASSUME UP MOVEI T4,XYL ;ASSUME LEFTWARD MOVEMENT SKIPG T2 ;IS THAT CORRECT? MOVEI T4,XYR ;NO..THEN ASSUME RIGHT MOVMS T1 ;MAKE DELTA X POSITIVE MOVMS T2 ;MAKE DELTA Y POSITIVE CAML T1,T2 ;IS SMALLEST DELTA IN T2? JRST PLT.2 ;YES -- PROCEED EXCH T1,T2 ;NO -- MAKE IT SO EXCH T3,T4 ;EXCHANGE MOVEMENT CODES PLT.2: JUMPE T1,PLT.8 ;DONE IF NO MOVEMENT REQUESTED JUMPE T2,PLT.6 ;PLOT ONLY ONE DIRECTION SUBTTL Plotter service -- PTC-6 interface IFN CSM08$,< ;T1 & T2 have delta movement, T3 has 2 or 3 PTCMV: ADDM T1,J$XPOS(J) ;Update position ADDM T2,J$YPOS(J) MOVE S1,J$XPOS(J) ;Get new X position CAIL T3,3 ;Pen up? JRST PTCMV1 ;No, skip next tests CAMLE S1,J$XLIM(J) ;Highest seen so far? MOVEM S1,J$XLIM(J) ;Yes CAMGE S1,J$XLOW(J) ;Closest to the origin? MOVEM S1,J$XLOW(J) ;Yes ;T1, T2, and T3 are set up with delta-X, delta-Y, and pen up/down code PTCMV1: PUSHJ P,PTCMOV## ;Translate move, fall into OUTRSP PAGE ;Routine to output the string pointed to by T1 and wait for response. ;S1 has accumulated increments for the last 4 buffers, to be used to ;predict how long it will take for the PTC-6 to respond. OUTRSP: JUMPE T1,.POPJ ;Don't wait if no string IMULI S1,PLTMOV ;Number of ticks to move LSH S1,-2 ;S1 has count for 4 buffers ADDM S1,J$PTIC(J) ;Predict elapsed time IMULI S1,^D60*4 ;Cancel LSH, use seconds not minutes IDIV S1,J$PTPM(J) ;Number of seconds required ADDI S1,^D<512*10/CSM08$> ;512 chars take 2 seconds at 2400 baud MOVNM S1,J$NACK(J) ;Negative to delay the complaints OUTRS1: PUSHJ P,OUTSTG ;Send the string OUTRS2: PUSHJ P,TIWAIT ;Get response, waiting up to 30 seconds JUMPT OUTRS3 ;Got it TXNE S,RQB+ABORT ;REQUEUE or ABORT? $RETF ;Yes, give up PUSHJ P,PTCOUT## ;Send string to raise pen SETZM J$PPOS(J) ;(just to get controller to respond) JRST OUTRS1 ;Loop until response or REQUEUE OUTRS3: CAIE S1,.CHCRT ;CR at end? JRST OUTRS2 ;No, skip over "0", "C" PJRST TTYIN ;Yes, snarf up the LF (if it's there) ;Routine to output the string pointed to by T1. ;The Monitor will put the job in "TO" Terminal Output wait if there are more ;than 400 characters in the TTY chunks. TOMAX=^D248 ;Avoid output wait for TTY OUTSTG: JUMPE T1,.POPJ ;Return if nothing to do HRLI T1,(POINT 7,) ;Make into ASCII byte pointer OUTST1: MOVEI S1,0 ;Clear byte count OUTST2: ILDB C,T1 ;Get a character JUMPE C,OUTOUT ;Stop on null, output buffer, return PUSHJ P,OUTBYT ;Send it CAIG S1,TOMAX ;Almost enough to cause 'TO' wait? AOJA S1,OUTST2 ;Loop till end of ASCIZ PUSHJ P,OUTOUT ;Dump partial buffer $DSCHD (TOMAX*^D10/CSM08$) ;Wait 1 second at 2400 baud JRST OUTST1 ;(gives checkpoint routine a chance) > ;End of IFN CSM08$ SUBTTL Plotter service -- Rotation and XY20 translation ;Plotter Translation Table Entry Description ; 0 17 20 23 24 27 28 31 32 35 ; ================================================================ ; ! XY20 CODE ! !ROT = 3!ROT = 2!ROT = 1!ROT = 0! ; ================================================================ ; ROTAB: EXP 0 ; 0 NO MOVEMENT BYTE (18) 106 (2) 0 (4) XYU ,XYL ,XYD ,XYR ; 1 Minus X BYTE (18) 102 (2) 0 (4) XYD ,XYR ,XYU ,XYL ; 2 Plus X BYTE (18) 114 (2) 0 (4) PEN3,PEN3,PEN3,PEN3 ; 3 SELECT PEN3 BYTE (18) 104 (2) 0 (4) XYR ,XYU ,XYL ,XYD ; 4 Plus Y BYTE (18) 105 (2) 0 (4) XYDL,XYUL,XYUR,XYDR ; 5 Plus Y & Minus X ;[CSM] BYTE (18) 103 (2) 0 (4) XYDR,XYDL,XYUL,XYUR ;MOVE UP+RIGHT BYTE (18) 103 (2) 0 (4) XYDR,XYUR,XYUL,XYDL;[CSM] 6 Plus Y & Plus X EXP -1 ; 7 ILLEGAL BYTE (18) 100 (2) 0 (4) XYL ,XYD ,XYR ,XYU ;10 Minus Y ;[CSM] BYTE (18) 107 (2) 0 (4) XYUL,XYUR,XYDR,XYDL ;MOVE DOWN+LEFT BYTE (18) 107 (2) 0 (4) XYUL,XYDL,XYDR,XYUR;[CSM]11 Minus Y & Minus X BYTE (18) 101 (2) 0 (4) XYUR,XYDR,XYDL,XYUL ;12 Minus Y & Plus X EXP -1 ;13 ILLEGAL BYTE (18) 113 (2) 0 (4) PEN2,PEN2,PEN2,PEN2 ;14 SELECT PEN 2 EXP -1 ;15 ILLEGAL EXP -1 ;16 ILLEGAL BYTE (18) 112 (2) 0 (4) CNGP,CNGP,CNGP,CNGP ;17 CHANGE PENS ROPTR: POINT 4,ROTAB(C),35 ;POINTER TO ZERO ROTATION POINT 4,ROTAB(C),31 ; ROTATION = 1 POINT 4,ROTAB(C),27 ; ROTATION = 2 POINT 4,ROTAB(C),23 ; ROTATION = 3 SUBTTL Plotter service -- Pen movement generation ;Call C/ Character to plot ; ;Will adjust values in J$XPOS and J$YPOS based on pen movement ;Also checks range on J$XMIN-J$XMAX and J$YMIN-J$YMAX ;Saves highest pen movement in J$XLIM and J$YLIM ; PLTBYT: $SAVE ;[CSM] ;Preserve ACs TRZE C,PNUP ;TEST AND CLEAR PEN UP CODE $CALL PENUP ;RAISE PEN TRZE C,PNDN ;TEST AND CLEAR PEN DOWN CODE $CALL PENDN ;LOWER PEN PLTXYD: TRNN C,XYD ;GOING DOWN? JRST PLTXYU ;NO TRNE C,XYU ;[CSM] ;Going +X and -X at the same time? JRST PLTB.8 ;[CSM] ;Yes, this is a change-pen code AOS S1,J$XPOS(J) ;+1 CAMG S1,J$XMAX(J) ;BEYOND X MAXIMUM? CAMG S1,J$XMIN(J) ;WITHIN X BOUNDS? TRZ C,XYD!XYU ;STOP MOVING PLTXYU: TRNN C,XYU ;GOING UP? JRST PLTXYL ;NO SOS S1,J$XPOS(J) ;-1 CAMGE S1,J$XMAX(J) ;BEYOND X MAXIMUM? CAMGE S1,J$XMIN(J) ;WITHIN X BOUNDS? TRZ C,XYD!XYU ;STOP MOVING PLTXYL: TRNN C,XYL ;GOING LEFT? JRST PLTXYR ;NO TRNE C,XYR ;[CSM] ;Going +Y and -Y at the same time? JRST PLTB.8 ;[CSM] ;Yes, this is a change-pen code AOS S2,J$YPOS(J) ;+1 CAMG S2,J$YMAX(J) ;BEYOND Y MAXIMUM? CAMG S2,J$YMIN(J) ;WITHIN Y BOUNDS? TRZ C,XYR!XYL ;STOP MOVING PLTXYR: TRNN C,XYR ;GOING RIGHT? JRST PLTB.6 ;NO SOS S2,J$YPOS(J) ;-1 CAMGE S2,J$YMAX(J) ;BEYOND Y MAXIMUM? CAMGE S2,J$YMIN(J) ;WITHIN Y BOUNDS? TRZ C,XYR!XYL ;STOP MOVING CONT. (PLTBYT) PLTB.6: SKIPN J$PPOS(J) ;IS PEN DOWN? PJRST PLTB.8 ;NO..DON'T RECORD MAX POSITIONS MOVE S1,J$XPOS(J) ;[CSM] ;In case of no AOS or SOS was done CAMLE S1,J$XMAX(J) ;CLIPPED? JRST PLTB.7 ;YES -- DON'T ADJUST LIMIT CAMLE S1,J$XLIM(J) ;HIGHEST POINT SO FAR? MOVEM S1,J$XLIM(J) ;YES -- SAVE IT CSMEDT 01,6 ;3-pen plotter, part 6 at PLTB.6:+5 IFN CSM01$,< ;Remember X minimum for positioning trailer after X maximum CAMGE S1,J$XLOW(J) ;Smaller than the previous XLOW? MOVEM S1,J$XLOW(J) ;Yes, user went near -X boundry ;therefore put dashed line close to plot > ;End of IFN CSM01$ PLTB.7: CAMLE S2,J$YMAX(J) ;CLIPPED? JRST PLTB.8 ;YES -- DON'T ADJUST LIMIT CAMLE S2,J$YLIM(J) ;HIGHEST POINT SO FAR? MOVEM S2,J$YLIM(J) ;YES -- SAVE IT PLTB.8: JUMPE C,.RETT ;RETURN IF NOTHING TO PLOT MOVEI S1,PLTMOV ;LOAD # TICS FOR MOVEMENT ADDM S1,J$PTIC(J) ;ADD TO TOTAL SO FAR ; MOVE S1,[LDB C,ROPTR] ;GET ROTATE INSTRUCTION ; ADD S1,J$ROTA(J) ;OFFSET BY GRID ROTATION ; XCT S1 ;ROTATE PJRST OUTBYT ;OUTPUT THE BYTE CHRBAS==6 CHRWID==6 FIN==B31!B35 PLTTAB: ;Characters used at Stanford (SUAI) C%000: Z ;NULL IS ILLEGAL C%001: XX <200,542,702,142,604,FIN> ;Down arrow .XCREF ;[CSM] Don't CREF the rest C%002: XX <144,563,603,622,621,600,560,541,542,563,603,624,FIN> ;Alpha C%003: XX <561,701,702,663,642,241,643,624,603,601,FIN>;Beta C%004: XX <602,544,FIN> ;Up angle bracket C%005: XX <220,624,564,FIN> ;Negation C%006: XX <243,641,620,560,541,543,200,602,FIN> ;Epsilon C%007: XX <141,641,240,644,243,543,FIN> ;Pi C%010: XX <602,240,544,FIN> ;Lambda C%011: XX <240,661,604,564,543,562,602,644,FIN> ;Gamma C%012: XX <242,641,620,560,541,543,564,624,643,642,702,704,FIN> ;Linefeed C%013: XX <160,541,562,662,703,664,FIN> ;Integral C%014: XX <240,644,302,562,160,564,FIN> ;Plus or Minus C%015: XX <200,560,541,543,564,624,643,641,620,600,604,242,542,FIN> ;CR C%016: XX <202,561,600,620,641,622,602,563,604,624,643,622,FIN> ;Infinity C%017: XX <204,623,621,600,560,541,543,564,644,702,701,FIN> ;Delta C%020: XX <244,641,620,560,541,544,FIN> ;Subset C%021: XX <240,643,624,564,543,540,FIN> ;Element of C%022: XX <160,640,661,663,644,564,FIN> ;Intersection C%023: XX <260,600,561,563,604,664,FIN> ;Union C%024: XX <300,600,542,604,704,240,644,FIN> ;All elements C%025: XX <544,704,700,221,624,206> ;There exists C%026: XX <100,640,600,561,562,603,643,603,564,FIN> ;Mu (micro) C%027: XX <143,564,603,164,560,221,640,661,240,644,FIN>;Double arrow C%030: XX <541,561,600,620,641,643,624,604,563,543,544,FIN> ;Omega C%031: XX <220,624,262,624,562,FIN> ;Left arrow C%032: XX <142,600,642,604,542,FIN> ;Formerly C%175 ;Diamond box [CSM] C%033: XX <602,642,704,244,640,200,604,FIN> ;Not equal C%034: XX <160,563,303,620,623,FIN> ;Less or equal C%035: XX <300,623,620,160,563,FIN> ;Greater or equal C%036: XX <160,564,224,620,260,664,FIN> ;Identically C%037: XX <200,542,604,FIN> ;Down angle bracket C%140: XX <341,703,FIN> C%141: XX <163,542,541,560,620,641,643,563,544,FIN> C%142: XX <300,540,543,564,624,643,640,FIN> C%143: XX <224,643,641,620,560,541,543,564,FIN> C%144: XX <304,544,541,560,620,641,644,FIN> C%145: XX <143,541,560,620,641,643,624,604,600,FIN> C%146: XX <141,661,702,703,664,220,622,FIN> C%147: XX <144,541,560,620,641,643,624,524,503,501,FIN> C%150: XX <700,220,641,643,624,544,FIN> C%151: XX <141,543,542,642,641,262,702,662,FIN> C%152: XX <121,502,503,524,644,643,FIN> C%153: XX <700,243,601,600,602,544,FIN> C%154: XX <141,543,542,702,701,FIN> C%155: XX <640,620,641,622,542,622,643,624,544,FIN> C%156: XX <640,200,642,643,624,544,FIN> C%157: XX <160,620,641,643,624,564,543,541,560,FIN> C%160: XX <100,640,643,624,564,543,540,FIN> C%161: XX <144,541,560,620,641,644,504,FIN> C%162: XX <640,200,642,643,624,FIN> C%163: XX <543,564,603,601,620,641,644,FIN> C%164: XX <301,561,542,543,564,240,642,FIN> C%165: XX <240,560,541,542,604,644,544,FIN> C%166: XX <240,600,542,604,644,FIN> C%167: XX <240,560,541,562,642,562,543,564,644,FIN> C%170: XX <644,240,544,FIN> C%171: XX <240,560,541,544,244,524,503,501,FIN> C%172: XX <240,644,540,544,201,603,FIN> ;z Lowercase Z C%173: XX <144,543,562,602,621,620,621,642,662,703,704,FIN> ;{ C%174: XX <102,702,FIN> ;| Vertical bar ;[CSM] Put close brace and tilde where they belong in the ASCII code C%175: XX <541,562,602,623,624,623,642,662,701,700,FIN> ;} 175, not C%176 C%176: XX <160,601,543,564,FIN> ;~ Tilde, formerly C%032 .CREF ;[CSM] ;OK to CREF now C%177: XX <260,564,FIN> ;\ Backslash, duplicate of C%134 SUBTTL Paper tape punch service -- Dispatch table T$DISP: JRST T$HEAD ;(0) FILE HEADER JRST T$EOF ;(1) FILE TRAILER SIXBIT /PTP/ ;(2) GENERIC DEVICE NAME EXP PTPBSZ ;(3) OUTPUT BYTE SIZE JRST T$PROC ;(4) PROCESS A FILE JRST T$BANN ;(5) JOB BANNER JRST T$TRAI ;(6) JOB TRAILER JRST T$LETR ;(7) LETTER ProcessER JRST .RETF ;(10) ERROR PROCCESSOR CSMEDT 04,4 ;CSM accounting, part 4 at T$DISP:+11 IFE CSM04$,< JRST .RETT > ;(11) ACCOUNTING IFN CSM04$,< JRST CSMACT > ;(11) ACCOUNTING JRST T$CHKP ;(12) CHECKPOINT TEXT GENERATION SUBTTL Paper tape punch service -- File processing T$PROC: LOAD S1,.FPINF(E),FP.FFF ;GET FILE FORMAT CAIN S1,.FPF11 ;/FILE:ELEVEN? JRST PTELF ;YES, DO IT LOAD S1,.FPINF(E),FP.FPF ;GET PAPER FORMAT CAILE S1,PTROUL ;WITHIN RANGE? JRST BADMOD ;NO, LOSE JUMPN S1,@T$ROUT-1(S1) ;YES, DISPATCH IF NON-ZERO CSMEDT 07,5 ;QUEUE defaults, part 5 at T$PROC:+6 IFE CSM07$,< ;This code will punch SOS files in BINARY mode MOVEI S1,T$MTAB ;GET ADDRESS OF MODE TABLE MOVEI S2,T$ROUT ;GET ADDRESS OF ROUTINE TABLE PJRST DSPMOD ;AND DISPATCH BASED ON MODE > ;End of IFE CSM07$ IFN CSM07$,< JRST PTASC > ;Default always to ASCII T$ROUT: EXP PTASC ;ASCII EXP PTIMA ;IMAGE EXP PTIBI ;IBIN EXP PTBIN ;BINARY PTROUL==.-T$ROUT ;LENGTH OF ROUTINE TABLE ;MODE TABLE T$MTAB: BYTE (3) 1,1,0,0,0,0,0,0,2,0,0,3,4,4,4,4 SUBTTL Paper tape punch service -- Byte output ; AC 'C' contains the byte to output ; PTPBYT: $SAVE ;[CSM] ;Preserve ACs PUSHJ P,OUTBYT ;OUTPUT THE BYTE AOS S1,J$TFRM(J) ;COUNT THE FRAME IDIVI S1,FRMPFT ;COMPUTE FEET OF TAPE USED MOVEM S1,J$APRT(J) ;STORE FOR ACCOUNTING PURPOSES CAMLE S1,J$RLIM(J) ;EXCEEDED LIMIT? PUSHJ P,FRMLEX ;YES - ASK THE OPERATOR'S ADVICE POPJ P, ;[CSM] ;ACs automatically retored on return ; Repeat the byte in AC 'C' ; Call: MOVE S1,repeat count ; MOVE C,byte to output ; PUSHJ P,PTPREP ; PTPREP: $SAVE ;[CSM] ;Save P1 MOVE P1,S1 ;GET COUNT PUSHJ P,PTPBYT ;OUTPUT A BYTE SOJG P1,.-1 ;AND LOOP POPJ P, ;RETURN SUBTTL Common Utilities ;PUTERR Routine to Move error Messages into J$XERR Buffer ; Call: MOVE S1,address if ITEXT block ; PUSHJ P,PUTERR ; PUTERR: $CALL SETEBF ;POINT $TEXT TO ERROR BUFFER $TEXT (DEPBP,) ;YES -- MOVE TO BUFFER $RETT ;HERE TO PRINT THE STRING IN J$XTBF(J) ON THE DEVICE STRING: $SAVE ;SAVE P1 AND P2 MOVE P1,[POINT 7,J$XTBF(J)] ;LOAD A BYTE POINTER MOVE P2,J$LSER(J) ;AND ADDRESS OF DISPATCH TABLE STRI.1: ILDB S1,P1 ;GET A BYTE JUMPE S1,.RETT ;END OF STRING PUSHJ P,DLETR(P2) ;PRINT THE LETTER JRST STRI.1 ;AND LOOP ;HERE TO SETUP A BYTE POINTER TO THE J$XTBF(J) BUFFER SETTBF: MOVEI TF,J$XTBF(J) ;GET THE ADDRESS OF TEXT BUFFER HRLI TF,(POINT 7,0) ;MAKE A POINTER MOVEM TF,TEXTBP ;STORE THE BYTE POINTER MOVEI TF,TXT$LN*5 ;GET BYTE COUNT MOVEM TF,TEXTBC ;AND SAVE IT SETZM J$XTBF(J) ;ZAP FIRST WORD $RETT ;AND RETURN SETEBF: MOVEI TF,J$XERR(J) ;GET THE ADDRESS OF ERROR BUFFER HRLI TF,(POINT 7,0) ;MAKE A POINTER MOVEM TF,TEXTBP ;STORE THE BYTE POINTER MOVEI TF,ERR$LN*5 ;GET BYTE COUNT MOVEM TF,TEXTBC ;AND SAVE IT SETZM J$XERR(J) ;ZAP FIRST WORD $RETT ;AND RETURN PAGE CSMEDT 07,6 ;QUEUE defaults, part 6 before DSPMOD: IFE CSM07$,< ;HERE TO DISPATCH TO A processing ROUTINE BASED ON FILE MODE. ; S1 CONTAINS THE MODE-TABLE ADDRESS AND S2 CONTAINS THE ROUTINE- ; TABLE ADDRESS. DSPMOD: $SAVE ;SAVE SOME ACS MOVE T1,J$DMOD(J) ;GET THE MODE IMULI T1,3 ;3 BITS/MODE DMOVE T2,0(S1) ;GET THE MODE TABLE LSHC T2,(T1) ;GET THE CORRECT BYTE ON TOP LDB T2,[POINT 3,T2,2] ;AND PICK IT UP JUMPE T2,BADMOD ;LOSE BIG ADD S2,T2 ;ELSE ADD IT IN JRST @-1(S2) ;AND DISPATCH > ;End of IFE CSM07$ BADMOD: MOVEI S1,[ITEXT ()] PJRST PUTERR ;AND FORCE IT OUT LITS: XLIST ;[CSM] Literals LIT ;[CSM] LIST ;[CSM] SPOEND::END SPROUT