Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-04 - 43,50347/tulip.rnd
There are no other files named tulip.rnd in the archive.
.FLAGS INDEX
.FLAGS CAPIT
.LOWER CASE
.PAPER SIZE 58,72
.SPACING 2
.TITLE <TULIP - AN ^I^O PACKAGE FOR <MACRO-10 PROGRAMS
.SUBTITLE ^RIC ^WERME, ^SEPT. 1974
.NOFILL
.CENTER
^TABLE OF ^CONTENTS
.BLANK 2
.TAB STOPS 7
1	^ABSTRACT.
2	^INTRODUCTION.
3	^PRIMER OVERVIEW.
4	^PROGRAM 1 - ^A ^DATE/^TIME PRINTER.
5	^PROGRAM 2 - ^PRINT DIRECTORY OF <DTA0.
6	^REGISTER CONVENTIONS.
7	^INPUT <UUO\S.
8	^PROGRAM 3 - ^PRINT A DIRECTORY FROM ANY <DEC\\TAPE.
9	<LEXINT - ^THE '^L' IN <TULIP.
10	^PROGRAM 4 - ^THE LAST ONE.
11	<SIXSRC AND COROUTINES.
12	^COMMAND FILES.
13	^ODDS AND ENDS.
14	^FUTURE PLANS AND POSSIBILITIES.
15	^REFERENCE MANUAL.
.SPACING 1
.B 3;.TS 12
.INDEX SOURCE
.INDEX AUTHOR
.INDEX ^HARVARD ^UNIVERSITY
^AUTHOR	^ERIC ^WERME
##^DATE	^FEBRUARY, 1975
##^FILE	<>TULIP.RND
.BLANK 2
.CENTER
^DEDICATION
.SPACING 1
.FILL
.LEFT MARGIN 0
.PARAGRAPH
^THIS MANUAL IS DEDICATED TO ^ED ^TAFT WHO WROTE <TULIP
WHILE AN UNDERGRADUATE STUDENT AT ^HARVARD (AND WHO TELLS ME ^I
SHOULD ALSO GIVE CREDIT TO ^GEORGE ^MEALY WHO WAS HIS PROJECT
ADVISOR). ^I HOPE ^I NEVER FIND ANOTHER PIECE OF CODE SO DESERVING
OF GOOD DOCUMENTATION IN SUCH AN UNDOCUMENTED STATE!
.PAGE
.LEFT MARGIN 0
.FILL
.SPACING 1
.HL 1 ^ABSTRACT
.PARAGRAPH
^AN <LUUO DRIVEN, BYTE (OR CHARACTER) ORIENTED ^I^O PACKAGE IS
DESCRIBED. ^CAPABILITIES INCLUDE OCTAL OR DECIMAL
OUTPUT WITH LEADING SPACES OR ZEROS, <SIXBIT OR <ASCII STRINGS WITH
EXTENSIVE FORMATTING CAPABILITIES, ^I^O ERROR DETECTION WITH LIMITED
HANDLING BUT EXCELLENT REPORTING, AND A CHARACTER ORIENTED LEXICAL ANALYZER.
^THIS IS THE ONLY STUFFY SECTION IN THE WHOLE MANUAL.
.PAGE
.HL 1 ^INTRODUCTION
.INDEX <BLISS
.PARAGRAPH
^ONE OF THE MAIN REASONS WHY MOST COMPUTER LANGUAGES HAVE RUNTIME
SYSTEMS IS TO PROVIDE AN EASY MEANS OF DOING ^I^O.
^WITHOUT THIS AID, WRITING EVEN THE SIMPLEST PROGRAM SUDDENLY CAN BECOME
A TEDIOUS AFFAIR, ESPECIALLY IF ERROR HANDLING MUST BE DONE.
^ASSEMBLER AND <BLISS PROGRAMMERS HAVE LONG BEEN AWARE OF THESE PROBLEMS BUT FOR
THE MOST PART HAVE SIMPLY PUT UP WITH THEM.
^THOSE WHO DECIDE TO TRY THEIR HAND AT AN ^I^O PACKAGE GENERALLY 
WIND UP WITH SOMETHING TOO SIMPLE OR SMALL TO BE USED BY OTHERS, OR
(IF THEY HAVE THE TIME) SOME MONSTER CONTAINING SO MUCH THAT IT IS
DIFFICULT TO LEARN AND OFTEN PUTS RESTRICTIONS ON WHAT THE PROGRAMMER
IS ALLOWED TO DO HIMSELF.
(^ASSIGNING CHANNEL NUMBERS AND ERROR RECOVERY ARE COMMON PROBLEMS.)
.INDEX <BLISS
.PARAGRAPH
<TULIP (^THE ^UUO/^LEXINT ^IO ^PACKAGE)
IS DESIGNED FOR USE WITH <MACRO-10 PROGRAMS, AND PERHAPS
COULD BE INTERFACED TO <BLISS, BUT AT THE LOSS OF SOME
FEATURES.
(^A SIMPLE SOLUTION ^I'VE FOUND TO THAT PROBLEM IS TO REWRITE
<>BLISS PROGRAMS IN <MACRO. ^THE IMPROVEMENT IS
PHENOMENAL!)
^THE <TULIP DISTRIBUTION CONSISTS OF SEVERAL FILES FOR BOTH THE <IO
PACKAGE AND DOCUMENTATION:
.LEFT MARGIN 6
.SKIP 1
.INDENT -3
.INDEX <TULIP.MAC
<TULIP.MAC - ^A UNIVERSAL FILE THAT SUPPLIES <AC, <UUO, AND
MACRO DEFINITIONS THAT ENABLE THE <TULIP FEATURES TO BE USED.
^THIS FILE SHOULD BE USED WITH ANY PROGRAM THAT USES <TULIP.
.SKIP 1
.INDENT -3
.INDEX <TULLIB.MAC
<TULLIB.MAC - ^THE <TULIP LIBRARY AND IS SEARCHED AT LOAD TIME WITH EVERY PROGRAM.
^IT CONSISTS OF TWO MODULES:
.BLANK 1
.LEFT MARGIN 9
.INDENT -3
.INDEX <UUO HANDLER
<UUO - ^THE <UUO HANDLER ITSELF. ^ALWAYS LOADED.
.BLANK 1
.INDENT -3
.INDEX LEXICAL ANALYSIS
<LEXINT - ^THE LEXICAL INTERPRETER. ^LOADED ONLY IF THE SYMBOL
<LEXINT IS DECLARED EXTERNAL. 
.LEFT MARGIN 6
.SKIP 1
.INDENT -3
.INDEX <TULIP.RND
.INDEX <RUNOFF
<TULIP.RND - ^THE <RUNOFF (VERSION 10 OR LATER, <NOT 7^B)
DOCUMENTATION FILE THAT PRODUCES THIS
MANUAL.
.SKIP 1
.INDEX <EXAMPL.MAC
.INDENT -3
<EXAMPL.MAC - ^A LIBRARY OF FOUR <MACRO-10 PROGRAMS THAT ARE
DESCRIBED IN DETAIL IN THE FOLLOWING PRIMER. ^THE LISTING OF <EXAMPL.MAC
SHOULD BE APPENDED TO <>TULIP.DOC PRODUCED BY <>RUNOFF TO PROVIDE
COMPLETE DOCUMENTATION.
.LEFT MARGIN 0
.PARAGRAPH
^ONE TECHNIQUE THAT MOST PROGRAMMERS OVERLOOK OR ARE AFRAID TO
.INDEX <LUUO
USE ARE THE <LUUO\S, THE 31 INSTRUCTIONS (OPCODES 1-37) THAT TRAP TO THE USER
PROGRAM INSTEAD OF THE MONITOR.
^A <UUO CAN PASS A SURPRISING AMOUNT OF INFORMATION -
THE 5 BITS OF OPCODE, 4 OF ACCUMULATOR AND 18 OF ADDRESS (AFTER
INDEXING AND INDIRECTION) PROVIDE A WAY TO PASS A LOT
IN A SINGLE <PDP-10 WORD.
^IN MANY PROGRAMS, THE ^I^O ROUTINES ARE THE MOST FREQUENTLY CALLED,
AND JUST THE CODE NEEDED TO LOAD SPECIFIC REGISTERS AND CALL THE ROUTINES
TAKE A CONSIDERABLE AMOUNT OF SPACE, WHEREAS
ONE <UUO HAS ENOUGH ROOM TO PASS THE INFORMATION ONE OR TWO
REGISTERS COMMONLY DO IN A CONVENTIONAL ^I^O PACKAGE.
^FOR EXAMPLE, INSTEAD OF LOADING ONE REGISTER WITH A NUMBER TO
PRINT AND ANOTHER WITH THE FIELD WIDTH, A <TULIP <UUO
PASSES THE WIDTH FROM 0 TO 15 SPACES IN THE ACCUMULATOR FIELD
AND POINTS TO THE DATA IN THE ADDRESS FIELD.
^WHAT MIGHT HAVE TAKEN THREE INSTRUCTIONS IS ACCOMPLISHED WITH
ONE <UUO.
^BECAUSE <TULIP <UUO\S POINT TO THEIR DATA, A TEMPORARY ACCUMULATOR MAY BE USED AS A
LOOP COUNTER INSIDE A LOW LEVEL LOOP WITHOUT WORRYING ABOUT WHETHER
OR NOT ANY ^I^O CALLS WILL CLOBBER IT OR NEED IT AS A PARAMETER.
^WHILE <UUO HANDLERS DO NEED ACCUMULATORS,
ANY SAVING AND RESTORING MAY NOW TAKE PLACE AT A SINGLE POINT IN THE PROGRAM
INSTEAD OF EITHER AT THE CALLER OR THE ^I^O ROUTINE ITSELF.
.PARAGRAPH
^THIS IS NOT TO SAY <UUO\S ARE WITHOUT PROBLEMS - THERE IS NEW
OVERHEAD PROCESSING, BOTH FROM THE EXECUTION OF THE <UUO 
(WHICH IS A RATHER SLOW INSTRUCTION, SLOWER THAN A
<MOVEM/PUSHJ PAIR), AND TIME SPENT DECODING AND DISPATCHING
TO THE VARIOUS <UUO ROUTINES.
^STILL, THIS TIME IS SMALL IN SOME CASES COMPARED TO THE TIME THE MONITOR SPENDS
DOING THE ACTUAL ^I^O. ^ALL IN ALL, ^I THINK THEY
ARE WORTH THE EXPENSE CONSIDERING WHAT THEY BUY.
(^BY THE WAY, IN CASES WHERE HIGH SPEED ^I^O IS A NECESSITY,
YOU CAN DO IT YOURSELF, WHILE USING <TULIP TO REPORT ANY
ERRORS....)
.PAGE
.HL 1 ^PRIMER OVERVIEW
.INDEX <DEC
.INDEX <IBM
.INDEX <C.MAC
.PARAGRAPH
^AS MENTIONED BEFORE, THIS DOCUMENT IS BOTH A PRIMER AND A REFERENCE MANUAL.
^PROGRAMMERS TYPICALLY DON'T WRITE GOOD MANUALS AS THEY PREFER TO SPEND
THEIR TIME PROGRAMMING. ^FURTHERMORE, THE MAPPING FROM
PROGRAM TO DOCUMENT RESULTS IN A REFERENCE MANUAL, SO GENERALLY PEOPLE
LEARNING A NEW SYSTEM DO SO THE HARD WAY.
^HAVING BEEN ON BOTH THE RECEIVING AND GIVING ENDS,
^I HAVE ATTEMPTED TO DO THINGS RIGHT FOR A CHANGE.
(^BY THE WAY, IF YOU THINK <DEC TURNS OUT BAD DOCUMENTATION, TRY
TO READ <IBM'\S SOMETIME - <PSISER AND <IPCF EXCLUDED!)
^THIS PRIMER IS BASED ON THE DEVELOPMENT OF A PROGRAM THAT PRINTS
^^DEC\\TAPE DIRECTORIES, STARTING WITH ONE SO SIMPLE IT DOESN'T
EVEN USE A ^^DEC\\TAPE (OR PRINT A DIRECTORY) AND CULMINATING WITH ONE THAT HAS A REAL COMMAND
STRING PROCESSOR WITH COMMAND FILES, FULL WORD SWITCHES, AND MULTIPLE INPUT
AND OUTPUT FILES.
.PARAGRAPH
.INDEX ^PHILOSOPHY
^BESIDES DESCRIBING <TULIP, ^I WILL ALSO DO A LITTLE PHILOSOPHIZING ABOUT
<MACRO PROGRAMMING ALONG THE WAY. ^A WORD OF WARNING - ^I WILL
ASSUME A FAIRLY COMPLETE KNOWLEDGE OF <MACRO-10 AND THE <PDP-10
INSTRUCTION SET, SO KEEP A COPY OF THE PHONE BOOK (THE ASSEMBLER
LANGUAGE HANDBOOK) HANDY. <TULIP USES <DEC'\S <C.MAC
PARAMETER FILE, SO YOU SHOULD ALSO BE FAMILIAR WITH THAT.
.PAGE
.HL 1 ^PROGRAM 1 - ^A ^DATE/^TIME PRINTER
.PARAGRAPH
^OUR FIRST PROGRAM SIMPLY PRINTS THE CURRENT DATE AND TIME, WHICH
WE WILL USE FOR THE HEADING ON OUR DIRECTORIES. ^THE DATE IS PRINTED
TWICE, FIRST USING A SIMPLE MAPPING FROM CONVENTIONAL TO <TULIP
^I^O, THEN AGAIN USING THE FULL CAPABILITIES OF <TULIP.
^FOR THE TIME BEING, DO NOT WORRY ABOUT ACCUMULATOR DEFINITIONS TOO
MUCH. ^THE FULL SET WILL BE WELL DESCRIBED LATER ON.
.LEFT MARGIN 6
.TAB STOPS 7
.BLANK 1
.INDENT -6
^HERE ARE ALL THE <UUO\S THAT WE WILL USE IN THIS PROGRAM:
.BLANK 1
.INDENT -6
<>START - ^ACTUALLY A <MACRO, THIS DOES A <SALL
PSEUDO OP TO SUPPRESS PRINTING THE EXPANSION OF THE <MOVX CLASS
.INDEX <C.MAC
OF <MACRO\S FROM <C.MAC, AND THEN CALLS AN INITIALIZATION
ROUTINE IN THE <UUO HANDLER WHICH DOES A <RESET <UUO, CLEARS THE
.INDEX ^FLAG REGISTER
.INDEX ^INITIALIZATION
FLAG REGISTER, AND INITIALIZES THE INTERNAL DATA STRUCTURE.
^THIS SHOULD BE CALLED BETWEEN
THE TIME THE STACK POINTER IS SET UP AND THE FIRST ^^TULIP UUO\\
IS EXECUTED.
.BLANK 1
.INDENT -6
<>WDEC LENGTH,ADDR - ^OUTPUTS AN UNSIGNED DECIMAL NUMBER FROM LOCATION _<ADDR_>
IN A FIELD AT LEAST _<LENGTH_> CHARACTERS LONG. ^FOR NOW, ASSUME THAT
ALL <UUO\S ACCESS THE <TTY; HOW TO CHANGE THAT WILL BE DISCUSSED IN A SECTION OR TWO.
^FREE FORMAT OUTPUT IS SIMPLY ACHIEVED BY MAKING _<LENGTH_> BE ZERO,
OR BY LEAVING IT OUT ALTOGETHER AS IS USUALLY THE CASE.
.BLANK 1
.INDENT -6
<>WDECI LENGTH,NUMBER - ^LIKE <>WDEC BUT PRINTS THE NUMBER
IN THE ADDRESS FIELD OF THE <UUO.
.BLANK 1
.INDENT -6
<>WOCT AND <>WOCTI - ^NOT USED, BUT LIKE <>WDEC AND <WDECI, ONLY WITH OUTPUT IN OCTAL.
.BLANK 1
.INDENT -6
<>WCHI CHARACTER - ^OUTPUTS THE CHARACTER GIVEN BY THE EFFECTIVE
ADDRESS FIELD OF THE INSTRUCTION.
.BLANK 1
.INDENT -6
<>W2CHI _<CHAR#1_>^B28+_<CHAR#2_> - ^OUTPUTS THE TWO RIGHT JUSTIFIED
CHARACTERS GIVEN BY THE EFFECTIVE ADDRESS FIELD.
^THE SYMBOL <>CRLF IS DEFINED IN <>TULIP.MAC AND PROVIDES
THE MAIN USE FOR <W2CHI.
^NOTE THAT QUOTED CHARACTERS (E_. G_. <W2CHI#"<HI") MAY ALSO BE USED.
.BLANK 1
.INDENT -6
<>WCH AND <>W2CH - ^NOT USED, BUT ACTS LIKE <>WCHI AND <W2CHI, ONLY PRINTING
FROM _<ADDR_>.
.BLANK 1
.INDENT -6
<>WNAME ADDR - ^PRINTS THE <SIXBIT WORD IN _<ADDR_> WITHOUT
TRAILING SPACES.
^GOOD FOR OUTPUTING DEVICE NAMES.
.BLANK 1
.INDENT -6
<>DISIX [NEXT,,[^^SIXBIT\\_\STRING_\]
.INDENT -6
	INST 1
.INDENT -6
	INST 2
.INDENT -6
	........
.INDENT -6
	INST N] - ^OUTPUTS A <SIXBIT STRING WHILE PERFORMING SPECIAL ACTIONS AS THE
FOLLOWING CHARACTERS ARE PROCESSED:
.LEFT MARGIN 8
.TAB STOPS 9
.BLANK 1
.INDENT -6
>_#	^OUTPUT A <CRLF. (^NO <>CRLF IN <SIXBIT).
.BLANK 1
.INDENT -6
>$	^OUTPUT A TAB. (^NO <>TAB EITHER!)
.BLANK 1
.INDENT -6
.INDEX ^CASE CONVERSION
>_&	^SWITCH CURRENT CASE CONVERSION. ^STRING OUTPUT
IS INITIALLY IN UPPER CASE MODE, BUT MAY BE SHIFTED TO
LOWER AND BACK AGAIN WITH THIS CHARACTER. ^THIS ALLOWS YOU TO
WRITE A PROGRAM ON A TERMINAL NO SMARTER THAN A MODEL 33 <TTY YET
STILL USE LOWER CASE MESSAGES WITH A MINIMUM OF GRIEF.
(^NOT TO MENTION PREVENTING CONTINUALLY UPDATING UPDATED PROGRAMS
TO CHANGE UPPER CASE MESSAGES INTO LOWER CASE!)
.BLANK 1
.INDENT -6
.INDEX ^INSTRUCTION LIST
>%	^EXECUTE THE NEXT INSTRUCTION IN THE _<INST_> LIST, WHICH
WILL NORMALLY BE A <TULIP <UUO TO OUTPUT SOMETHING LIKE A NUMBER OR FILE NAME.
^IT MAY ALSO BE A <PUSHJ TO A ROUTINE TO DO MORE COMPLICATED
OUTPUT THAN ONE <UUO ALLOWS, OR IT COULD
EVEN BE A NORMAL INSTRUCTION READYING SOMETHING TO BE
PRINTED.
.B 1;.I -6
.INDEX ^CHARACTER QUOTING
>"	^QUOTING CHARACTER. ^OUTPUT THE NEXT CHARACTER AS IS WITH NO
SPECIAL PROCESSING.
^NEEDED TO PRINT ANY OF THE CHARACTERS IN THIS LIST.
.BLANK 1
.INDENT -6
.INDEX ^END OF STRING
>!	^END OF STRING. ^NEEDED BECAUSE <>NULL IN <SIXBIT
IS THE SPACE CHARACTER.
^THE NEXT INSTRUCTION TO BE EXECUTED WILL BE FROM LOCATION _<NEXT_> OR
WILL BE IMMEDIATELY AFTER THE <>DISIX IF _<NEXT_> IS OMITTED.
.BLANK 1
.INDENT -6
.INDEX <DISIX
.INDEX ^INSTRUCTION LIST
<>DIASC [....] - ^NOT USED, BUT ACTS LIKE <DISIX, ONLY WITH AN
<ASCIZ STRING. ^THE ONLY EDIT CHARACTER USED (OR NEEDED)
.INDEX <CTRL-A
IS <CTRL-A, WHICH ACTS LIKE >% DOES IN <DISIX.
.LEFT MARGIN 0
.INDEX ^INITIALIZATION
.PARAGRAPH
^THE INITIALIZATION FOR ^PROGRAM 1 IS AS SIMPLE AS IT CAN BE.
^THE FIRST THREE LINES COMPRISING SECTION 1 ARE NECESSARY AND DO IT ALL.
.PARAGRAPH
^SECTION 2 IS THE FIRST PASS AT A DATE PRINTER USING ONLY THE
SIMPLEST OF THE <UUO\S AND WITHOUT TAKING ADVANTAGE OF THE
FULL CAPABILITIES OF <TULIP OR THE <PDP-10 HARDWARE.
^THIS IS FOR TWO REASONS: FIRST, IT MAKES EACH INSTRUCTION EASIER
TO FOLLOW; AND SECOND, IT MAKES FOR A MORE DIRECT MAPPING FROM
CONVENTIONAL <IO PACKAGES THAT NORMALLY REQUIRE INSTRUCTIONS
LIKE THE ^^ADDI#T2,1\\
SINCE THEY DO NOT GENERALLY HAVE ROUTINES
FOR PRINTING A NUMBER ONE (OR 64) GREATER THAN PASSED.
.PARAGRAPH
^SECTION 3 IS A MUCH MORE POLISHED DATE PRINTER AND USES THE
FULL CAPABILITIES OF <TULIP.
^NOT SURPRISINGLY, ANOTHER ADVANTAGE OF <TULIP POPS UP IN THE PROCESS.
^SINCE WE CAN USE ALL THE TEMPORARY REGISTERS WITHOUT NEEDING THEM
FOR PARAMETERS, WE CAN CALCULATE ALL THE DATA FIRST THEN PRINT IT
IN ONE FELL SWOOP.
^BY PUTTING INDEXING TO GOOD ADVANTAGE WE CAN SAVE AN INSTRUCTION
AND HAVE <TULIP PRINT THE CONTENTS OF A REGISTER MODIFIED BY A CONSTANT,
WHICH IS A FEATURE WITH MORE USES THAN IN JUST DATE PRINTERS!
^THERE IS ONE MINOR DIFFERENCE BETWEEN THIS ROUTINE AND THE
PREVIOUS ONE - THIS ONE DOESN'T PRINT THE <CRLF, INSTEAD IT
LETS THE TIME PRINT ON THE SAME LINE.
^NOTE THAT TO INCLUDE THE <>CRLF ALL THAT NEED BE DONE IS TO
ADD A _# JUST BEFORE THE ! IN THE <>DISIX EDIT STRING.
.PARAGRAPH
^SECTION 4 AS PROMISED PRINTS THE TIME, PRETTY MUCH THE SAME WAY
AS THE DATE PRINTER WORKS, BUT USING A COUPLE EXTRA FEATURES.
^HERE WE START USING THE <>C.MAC MACROS, BOTH FOR ARITHMETIC
USE AND FLAG MANIPULATION. (^TO THOSE WHO THINK THE <>IDIVX
MACRO IS A BIT TOO MUCH, COMPARE 60*60*1000 WITH 2_^18!)
<>LZEFLG IS THE ONLY FLAG DEFINED IN THE <UUO PROCESSOR
AND DIRECTS <TULIP TO PRINT NUMBERS WITH LEADING ZEROS WHEN
IT IS ON.
^ALSO, WE NOW USE <>WDEC TO FORMAT NOT ONLY THE HOURS, MINUTES,
AND SECONDS IN THE STANDARD TWO CHARACTERS EACH FORMAT, BUT ALSO TO
PRINT THE THOUSANTHS WHICH NEEDS THE LEADING ZEROS.
.PARAGRAPH
^THERE ISN'T MUCH TO SAY ABOUT SECTION 5. ^FROM HERE OUT IT'S
PRETTY STANDARD. ^THE <>MAKLST MACRO DESERVES A LITTLE STUDY,
AS IT USES THE <IRP PSEUDO OP.
^BOTH <IRP AND <IRPC ARE EXTREMELY POWERFUL - THIS IS
JUST THEIR SIMPLEST USE.
.PARAGRAPH
^DATE AND TIME ROUTINES SHOULD BE SUBROUTINES (EVEN IF YOU EXPECT
.INDEX PHILOSOPHY
TO USE THEM ONLY ONCE [PHILOSOPHY]), AND SINCE WE'RE WRITING A PROGRAM
THAT WILL BE PRINTING SEVERAL DATES IN A LIST, EACH MONTH SHOULD
HAVE AN EQUAL LENGTH ABBREVIATION.
^IN THE TIME ROUTINE, WHO GIVES A DAMN ABOUT THE THOUSANTHS OF A SECOND?
^THE PURPOSE OF ^PROGRAM 1 WAS TO GIVE AN EXAMPLE OF <TULIP WITH
AS LITTLE OVERHEAD AS ABSOLUTELY NECESSARY.
^PROGRAM 2 WILL SCATTER IN A LITTLE MORE AND TURN THE DATE/TIME
ROUTINES INTO SOMETHING PRACTICAL.
.PAGE
.HL 1 ^PROGRAM 2 - ^PRINT DIRECTORY FOR <DTA0
.PARAGRAPH
^PROGRAM 2 ACTUALLY GOES OUT TO A TAPE AND PRINTS ITS DIRECTORY.
^FOR NOW, THE CHOICE IS RATHER LIMITED (<DTA0) AND THE OUTPUT FORMAT
EQUALLY SO (NO CHOICE BETWEEN LONG AND SHORT FORMS).
^THERE'S A LITTLE MORE OVERHEAD IN THE PROGRAM SUCH AS THE TITLE
AND SUBTITLE, AND THE CODE IS NOW IN THE <HISEG AND IS
REENTRANT.
^VARIOUS SYMBOLS ARE DEFINED TO SETUP <IO CHANNELS, PUSH DOWN
LIST LENGTH, AND THE CHARACTERISTICS OF ^^DEC\\TAPES AND THEIR
DIRECTORIES.
^A NEW OUTPUT <UUO IS USED THAT COMES IN TWO FORMS:
.BLANK 1
.LEFT MARGIN 6
.INDENT -3
<>WSIX LEN,ADDR - ^THIS FORM OUTPUTS A <SIXBIT STRING _<LEN_>
CHARACTERS LONG STARTING FROM LOCATION _<ADDR_>.
.INDEX <DISIX
^NO EDITING (AS DONE WITH <DISIX) WILL BE DONE, MAKING THIS <UUO
GOOD FOR OUR USE OF PRINTING FILE NAMES AND EXTENSIONS.
.BLANK 1
.INDENT -3
<>WSIX ADDR - ^THIS FORM OUTPUTS AN INDEFINITE LENGTH STRING
STARTING AT LOCATION _<ADDR_>.
^ALL EDITING CHARACTERS WILL APPLY, INCLUDING >% WHICH WILL PROBABLY
CAUSE THE PROGRAM TO BOMB. ^DON'T TRY IT!
.B 1;.I -6;<WSIX HAS A CLOSE RELATIVE THAT ISN'T USED IN ^PROGRAM 2:
.BLANK 1
.INDENT -3
<>WASC ADDR - ^OUTPUT AN <ASCIZ STRING THAT STARTS IN LOCATION _<ADDR_>.
.INDEX <CTRL-A
<CTRL-A, THE ONLY  <DIASC EDITING CHARACTER WILL NOT BE SPECIALLY PROCESSED.
^THE LENGTH FIELD MAY NOT BE SPECIFIED.
.LEFT MARGIN 0
.PARAGRAPH
^THERE ARE TWO <>DISIX <UUO\S THAT TRANSFER TO LOCATION <>CPOPJ WHEN
.INDEX <CPOPJ1
DONE. ^THIS AND <CPOPJ1 ARE ROUTINES IN THE <UUO HANDLER
THAT PROVIDE A MECHANISM TO DO A NON-SKIP OR SKIP RETURN FROM SUBROUTINES
WHEN NORMAL METHODS ARE INCONVENIENT.
^BOTH ARE GENERALLY REACHED BY CONDITIONAL JUMPS, E.#G_.
'^^JUMPE#T1,CPOPJ_#_#\\'.
.PARAGRAPH
.INDEX <POINTR
.INDEX ^BYTE POINTERS
^ONE OF THREE MACROS, <POINTR, THAT SIMPLIFY BYTE POINTER
USAGE IS USED WITHIN <PRTDIR TO EXTRACT THE DATE FIELD
FROM THE EXTENSION WORD.
^ALL THREE RELY ON BYTE MASKS WHICH ARE CONCEPTUALLY MUCH SIMPLER
TO USE THAN THE USUAL BIT POSITIONS.
^AFTER ^I WROTE THIS, ^I DISCOVERED THAT ALL THREE MACROS WERE
DEFINED IN <>C.MAC AND NOT IN <>TULIP.MAC AS ^I HAD THOUGHT.
^I HEREBY PRESENT THIS WITH THE HOPE IT WILL ACT AS A SEED FOR THE
DOCUMENTATION OF <C.MAC SOMETIME IN THE FUTURE.
.BLANK 1
.LEFT MARGIN 6
.INDENT -3
<>WID (MASK) - ^RETURNS THE WIDTH OF MASK IN BITS. [<WID(7777)=_^D12]
.INDENT -3
<>POS (MASK) - ^RETURNS THE POSITION OF THE RIGHTMOST BIT
IN MASK. [<POS(7777)=_^D35]
.INDENT -3
<>POINTR (ADDR,MASK) - ^GENERATES A BYTE POINTER VIA
.BREAK
<POINT  ^^WID\\(MASK),ADDR,^^POS\\(MASK)
.BREAK
[^^POINTR(DIREXT(P1),7777)=POINT 12,DIREXT(P1),35\\]
.LEFT MARGIN 0
.PARAGRAPH
^THE MOST IMPORTANT CHANGES
INVOLVE THE SETUP FOR SIMPLE FILE <IO, NAMELY THE <>FILE MACRO,
.INDEX <FIGET
<FIGET, AND <>FREL <UUO\S.
^THE ENTIRE SET OF FILE UTILITY <UUO\S FOLLOWS THE DESCRIPTION OF THE <>FILE MACRO:
.LEFT MARGIN 6
.BLANK 1
.INDENT -6
<>FILE CHAN,DIR,LOBLK,_<SPEC(ARG),...,SPEC(ARG)_> - ^ASSOCIATED WITH EACH
FILE IS ONE OR TWO <HISEG FILE BLOCKS CONTAINING THE DEFAULTS FOR
ENTRIES IN THEIR CORRESPONDING <LOSEG FILE BLOCK.
^THIS MACRO SETS UP THE <HISEG BLOCK BASED ON THESE PARAMETERS:
.BLANK 1
.LEFT MARGIN 9
.TAB STOPS 11
.INDENT -6
CHAN - ^THE SOFTWARE <IO CHANNEL NUMBER.
.BLANK 1
.INDENT -6
DIR - ^I FOR INPUT, ^O FOR OUTPUT. ^IF BOTH INPUT AND OUTPUT ARE
DONE ON AN <IO CHANNEL, THERE MUST BE ONE FILE BLOCK FOR EACH DIRECTION.
.BLANK 1
.INDENT -6
LOBLK - ^ADDRESS OF THE <LOSEG FILE BLOCK PAIRED WITH THIS <HISEG FILE BLOCK.
.BLANK 1
.INDENT -6
SPEC(ARG) - ^SPECIFY NONSTANDARD DEFAULTS, AND WILL BE A LIST COMPRISED
FROM SOME OF THE FOLLOWING MACROS:
(BRACKETS DENOTE THE DEFAULTS)
.BLANK 1
.LEFT MARGIN 12
.INDENT -6
<>DEV (N) [<DSK] ^DEVICE TO USE.
.BLANK 1
.INDENT -6
<>NAME (N) [BLANK] ^FILE NAME.
.BLANK 1
.INDENT -6
<>EXT (N) [BLANK] ^EXTENSION.
.BLANK 1
.INDENT -6
<>PPN (N) [0] ^PROJECT - PROGRAMMER NUMBER. ^COMMAS CANNOT BE USED
IN _<N_> BECAUSE THE MACRO WILL
THINK THEY MARK THE END OF THAT PARAMETER, SO TO SPECIFY [1,4],
YOU MUST USE A FORM LIKE <PPN(1000004), <PPN(1B17+4),
<PPN(SYSPPN), OR USE ANGLE BRACKETS AS DONE FOR <INST BELOW.
.BLANK 1
.INDENT -6
<>STATUS (N) [0] ^INITIAL FILE STATUS.
.BLANK 1
.INDENT -6
.INDEX <O1BYTE
_<<>INST (_<I_>)_> [<PUSHJ <P,>I1BYTE OR <PUSHJ <P,O1BYTE] ^INSTRUCTION
WHICH WILL BE USED TO READ OR WRITE ALL BYTES.
^SEE THE REGISTER CONVENTION SECTION FOR AN EXPLANATION OF
WHAT DATA IS IN THE <UUO HANDLER  REGISTERS.
^THE DEFAULTS (AND THOSE BELOW) ARE ROUTINES IN THE <UUO HANDLER.
.BLANK 1
.INDENT -6
<>OTHER (L) [NONE] ^ADDRESS OF THE OPPOSITE DIRECTION LOSEG BLOCK, AND IS
NECESSARY IF BOTH INPUT AND OUTPUT ARE DONE ON THIS CHANNEL.
.BLANK 1
.INDENT -6
.INDEX <ILERO1
<>OPEN (L) [<ILERI1 AND <ILERO1] ^LOCATION TO TRANSFER TO ON <>OPEN ERROR.
.BLANK 1
.INDENT -6
.INDEX <ILERO2
<>LOOKUP AND <>ENTER (L) [<>ILERI2 AND <ILERO2] <>LOOKUP AND <>ENTER FAILURE ADDRESS.
.BLANK 1
.INDENT -6
.INDEX <ILERO3
<>INPUT AND <>OUTPUT (L) [<>ILERI3 AND <ILERO3] <IO ERRORS EXCEPT END OF FILE.
.BLANK 1
.INDENT -6
.INDEX <ILERI3
<>EOF (L) [<ILERI3] ^END OF FILE.
.LEFT MARGIN 0
.PARAGRAPH
^WARNING: EACH SPECIFIER MUST BE IMMEDIATELY PRECEDED BY ITS COMMA OR ANGLE BRACKET.
.PARAGRAPH
^WITH EACH <>FILE MACRO GOES THE CORRESPONDING LOSEG BLOCK, <>FBSIZE WORDS LONG, WHICH IS
WHERE RUNTIME INFORMATION SUCH AS THE <OPEN, <LOOKUP, AND
BUFFER HEADER BLOCKS ARE KEPT.
^THE EXAMPLE USED IN ^PROGRAM 2 IS RATHER SIMPLE, SO HERE'S THE SOMEWHAT
MORE COMPLICATED USE OF FILE BLOCKS NEEDED FOR ACCESSING A DISK FILE
IN UPDATE MODE:
.BLANK 1
.TAB STOPS 8,16
.TP 7
^^DSKFIH:	<>FILE	DCHN,I,DSKFIL,_<OTHER(DSKFOL),NAME(FOO),EXT(BAR),
.INDENT 40
EOF(DSKEOF)_>
.BREAK
DSKFOH:	<>FILE	DCHN,O,DSKFOL_<OTHER(DSKFIL),NAME(FOO),EXT(BAR)_>
.BLANK 1
DSKFIL:	BLOCK	FBSIZE
.BREAK
DSKFOL:	BLOCK	FBSIZE\\
.PARAGRAPH
^THE ADDRESS FIELD OF ALL THE FILE UTILITY <UUO\S POINTS TO A FILE BLOCK.
.INDEX <FSETUP
^IN ALL BUT ONE CASE (<FSETUP) THEY POINT TO THE
LOSEG BLOCK.
.LEFT MARGIN 9
.BLANK 1
.TP 5
.INDENT -6
<>FSETUP - ^GENERATE THE LOSEG BLOCK FROM THE DEFAULT DATA IN THE HISEG BLOCK.
.BLANK 1
.INDENT -6
<>FIGET AND <>FOGET - ^DOES AN <>OPEN ON THE DEVICE IN THE
LOSEG FILE BLOCK.
.BLANK 1
.INDENT -6
<>FLOOK AND <>FENT - ^DOES A <>LOOKUP OR <>ENTER ON THE FILE IN THE LOSEG BLOCK.
.BLANK 1
.INDENT -6
.INDEX <ENTER
<>FIOPEN AND <>FOOPEN - ^DOES BOTH <>OPEN AND EITHER <>LOOKUP OR <ENTER.
.BLANK 1
.INDENT -6
<>FICLS AND <>FOCLS - ^DOES <>CLOSE ON CHANNEL.
.BLANK 1
.INDENT -6
<>FREL - ^DOES <>RELEASE ON CHANNEL.
.BLANK 1
.INDENT -6
<>FICLOS AND <>FOCLOS - ^DOES <>CLOSE AND <>RELEASE ON CHANNEL.
.LEFT MARGIN 0
.PARAGRAPH
^SO, TO HANDLE THE <IO FOR OUR UPDATE MODE DISK FILE ABOVE,
THE PROGRAM SECTION WILL LOOK SOMEWHAT LIKE:
.BLANK 1
.NOFILL
.TAB STOPS 8,16,24,32,40,48
.TEST PAGE 6
	^^<>FSETUP	DSKFIH		;READY THE LOSEG FILE BLOCKS
	<>FSETUP	DSKFOH
	<>FIOPEN	DSKFIL		;OPEN, LOOKUP
	<>FENT	DSKFOL		;ENTER TO GET INTO UPDATE MODE
	##;DO ALL IO
	<>FICLOS	DSKFIL		;CLOSE UP\\
.FILL
.PARAGRAPH
^THE <>FILE MACRO AS DESCRIBED ONLY SETS UP DEFAULTS IN THE LOSEG BLOCK.
^TO DO ANYTHING OTHER THAN THAT REQUIRES THAT THE PROGRAM SET UP THE
PERTINENT DATA ITSELF.
^THE COMPLETE LIST IS IN THE REFERENCE MANUAL, BUT THE MORE IMPORTANT
LOCATIONS ARE:
.BLANK 1
.NOFILL
	<>FILDEV - ^DEVICE NAME
	<>FILNAM - ^FILE NAME
	<>FILEXT - ^EXTENSION
	<>FILPPN - ^PROJECT - PROGRAMMER NUMBER OF THE FILE'S DISK AREA
.FILL
.PAGE
.HL 1 ^REGISTER CONVENTIONS
.FILL
.PARAGRAPH
^PROGRAM 2 ALSO STARTED TO MAKE COMPLEX USE OF REGISTERS, SO THIS IS A
GOOD PLACE TO GIVE THE FULL DESCRIPTION.
^MOST OF THE <PDP-10 REGISTERS ARE DEFINED BY <TULIP AND ARE
IN THESE CATAGORIES:
.NOFILL
.TAB STOPS 5,17,27
.TEST PAGE 7
.BLANK 1
.INDEX ^FLAG REGISTER
.INDEX ^TEMPORARY REGISTERS
.INDEX ^PERMANENT REGISTERS
.INDEX ^UNASSIGNED REGISTERS
.INDEX <TULIP REGISTERS
.INDEX STACK POINTER
	^NAME	^RANGE	^USE
	^F	0	^FLAGS
	^T1-^T4	1-4	^TEMPORARY
	^P1-^P4	5-10	^PERMANENT
		11-13	^UNASSIGNED
	^U1-^U3	14-16	^USED BY <UUO HANDLER (BUT PRESERVED)
	^P	17	^STACK POINTER
.FILL
.PARAGRAPH
^P IS THE STACK POINTER, USED FOR SUBROUTINE CALLS AND TEMPORARY
STORAGE.
^THE <>SAVE AND <>RESTORE MACROS MAKE THE LATTER EASIER TO DO.
^BOTH TAKE AN ANGLE BRACKETED LIST OF REGISTERS OR MEMORY LOCATIONS; <>SAVE WILL
PUSH THEIR DATA ON THE STACK AND <>RESTORE WILL POP IT BACK.
^THE PARAMETER LIST TO <>RESTORE MUST BE OPPOSITE THAT
USED FOR <SAVE, I.#E_. IF A <>SAVE#_<<A,B_> IS DONE,
<>RESTORE#_<<B,A_> MUST BE USED TO RESTORE THEM IN THE RIGHT ORDER.
^AS A SPECIAL (AND NOT VERY NECESSARY) FRILL, THE <>CALL AND
<>RETURN MACROS ARE AVAILABLE TO REPLACE ^^PUSHJ#P,\\ AND ^^POPJ#P,\\
MAKING THEM USEFUL MAINLY FOR EX-<FORTRAN PROGRAMMERS WITH FOND
MEMORIES OF A USELESS LANGUAGE.
.INDEX PHILOSOPHY
^SIGH. ^WE SYSTEM WIZARDS DO GET CYNICAL IN OUR OLD AGE....
^A NEW INSTRUCTION, <>MCALL, HAS BEEN DEFINED FOR
THOSE CASES WHERE THE <CALL <UUO IS NECESSARY, MAINLY WHEN
SOFTWARE THAT USES LOCAL <UUO<S (NEGATIVE <CALLI<S) IS ALSO EXPECTED
TO RUN ELSEWHERE.
.PARAGRAPH
.INDEX <PJRST
<>C.MAC PROVIDES AN INTERESTING INSTRUCTION, <PJRST, WHICH
IS OPDEFFED TO BE NOTHING MORE THAN A <JRST!
^NEVERTHELESS, IT DOES SERVE AN EXTREMELY IMPORTANT PLACE IN MAINTAINING
THE CLARITY OF ASSEMBLER PROGRAMS.
^ALTHOUGH THIS PARAGRAPH REALLY FALLS UNDER THE 'ASSUMED KNOWLEDGE OF
.INDEX <C.MAC
.INDEX PHILOSOPHY
<C.MAC', ^I FEEL COMPELLED TO ADD IT BECAUSE ^I KNOW OF NO PLACE
THAT REALLY DEFINES <>PJRST WELL, AND ^I HAVE SEEN SOME PROGRAMS RECENTLY
THAT MISUSE IT.
<>PJRST SAYS, "^THIS ROUTINE IS DONE AND HAS NO MORE
TO DO EXCEPT CALL ANOTHER, SO ^I WILL SIMPLY JUMP THERE AND
ITS <POPJ WILL BE MY RETURN".
^TECHNICALLY, THIS MEANS THAT '<PJRST#_<ADDR_>' SHOULD BE USED WHENEVER
IT CAN REPLACE THE FOLLOWING SEQUENCE:
.NOFILL
.BLANK 1
.TEST PAGE 4
.TAB STOPS 9,17
	^^PUSHJ	P,\\ADDR^^
	##POPJ	P,
	AOS	(P)
	POPJ	P,\\
.FILL
.B 1
^THEREFORE, <>PJRST IS NOT MEANT TO TRANSFER TO A 'SUBROUTINE' THAT EXPECTS DATA ON
THE TOP OF THE STACK INSTEAD OF A ^^PC\\WORD (AS IF A <PUSH WAS DONE
BEFORE THE <PJRST), BUT THERE IS AN EXCEPTION.
<>PJRST MAY GO TO CODE THAT REFERENCES SOLELY THE STACK,
EITHER TO PREPARE FOR A SKIP RETURN OR TO RESTORE REGISTERS.
^GENERALLY THESE ROUTINES HAVE '<POPJ' IN THEIR NAMES TO ADVERTISE
THEIR FUNCTION (<>CPOPJ AND <TPOPJ1 ARE COMMON EXAMPLES).
.PARAGRAPH
.INDEX TEMPORARY REGISTERS
^T1-^T4 ARE THE TEMPORARY, SCRATCH PAD TYPE REGISTERS AND ARE USED FOR MOST
OF THE CALCULATIONS DONE BY A PROGRAM. ^THEY ARE ALSO EXTENSIVELY USED
FOR PASSING AND RETURNING PARAMETERS TO AND FROM SUBROUTINES.
^TECHNICALLY, ANY SUBROUTINE MAY CLOBBER ^T1-^T4, BUT MOST PROGRAMS
(INCLUDING THESE SAMPLE ONES) WILL OFTEN ADVERTISE WHICH REGISTERS WILL
BE USED.
^MOST OF THE TIME IT WORKS OUT OKAY, THE MAIN EXCEPTION BEING WHEN A
PROGRAM BECOMES SO LARGE THAT IT IS DIFFICULT TO TRACE ALL POSSIBLE ROUTINE
FLOWS TO SEE WHICH REGISTERS WILL BE WIPED OUT.
^GENERALLY, PROBLEMS WITH LARGE PROGRAMS ARE NOT A RESULT OF JUST
THEIR SIZE, BUT POOR DESIGN AND NONADHERANCE TO SIMPLE PROTOCOLS
SUCH AS THESE [PHILOSPOHY (SORT OF)].
.INDEX ^PHILOSOPHY
.PARAGRAPH
.INDEX PERMANENT REGISTERS
^P1-^P4 ARE PERMANENT REGISTERS AND NORMALLY ARE NOT CLOBBERED BY
SUBROUTINES, THE MAIN EXCEPTION BEING ON A SUBROUTINE CALL MADE TO
SET ONE TO A VALUE FOR USE IN LATER SUBROUTINES.
^TO FACILITATE SAVING AND RESTORING THESE, FOUR SUBROUTINES
.INDEX <SAVE1
.INDEX <SAVE2
.INDEX <SAVE3
.INDEX <SAVE4
(<SAVE1 TO <SAVE4) ARE PROVIDED THAT SAVE THAT NUMBER
OF REGISTERS (E.#G_. <SAVE3 SAVES ^P1-^P3), THEN CALL THE
CALLER. ^WHEN THE CALLER FINALLY RETURNS, CONTROL GOES BACK TO
THE SAVE ROUTINE WHICH RESTORES THE REGISTERS AND DOES THE REAL
RETURN.
^THIS HAS GREAT ADVANTAGES FOR SUBROUTINES THAT HAVE SEVERAL EXIT
POINTS SINCE YOU'RE FREED OF THE HASSLE OF CHASING DOWN
EACH ONE WHENEVER THE SUBROUTINE IS CHANGED TO SAVE MORE OR FEWER
REGISTERS.
^HOWEVER, THERE IS ONE LIMITATION. ^SUBROUTINES THAT CALL THESE MUST
EXIT WITH EITHER A SKIP OR NON-SKIP RETURN, ANYTHING ELSE WILL PROBABLY
BOMB THE PROGRAM!
.PARAGRAPH
.INDEX TEMPORARY REGISTERS
^IN GENERAL, IF YOU ALWAYS ASSUME ^T1-^T4 GET CLOBBERED BY ANY ROUTINE
YOU CALL (EXCEPT <SAVE1-SAVE4) AND NEVER LET A SUBROUTINE
CLOBBER ^P1-^P4, YOU SHOULD HAVE NO TROUBLE WITH REGISTER USAGE.
(^BUT NOTE THAT <DIRLOP RELIES ON <DATTHN NOT CLOBBERING ^T4....)
.PARAGRAPH
.INDEX <TULIP REGISTERS
^U1-^U3 MAY NOT BE USED IN SUCH
A WAY AS TO REQUIRE <TULIP TO REFERENCE THEM AS MEMORY LOCATIONS (I.#E_. ^^WDECI#(U1)\\
IS OKAY, BUT ^^WDEC#U1\\ IS NOT), NOR MAY THEY BE USED
.INDEX ^INSTRUCTION LIST
AT ALL IN THE ^^DISIX UUO\\ INSTRUCTION LIST (OR SUBROUTINES THOSE
INSTRUCTIONS CALL).
^BASICALLY, IF YOU DON'T USE THEM, YOU'LL BE SAFE.
.INDEX <FILE
^HOWEVER, WHEN A PROGRAM DOES ITS OWN <IO VIA <FILE'\S <>INST
SUBMACRO, IT MUST ACCESS OR PASS DATA, AND THESE REGISTERS ARE SET
UP AS FOLLOWS:
.NOFILL
.TAB STOPS 9,17
.BLANK 1
	^U1	^HOLDS BYTE (EITHER SET OR READ BY ROUTINE).
	^U2	^HOLDS ADDRESS OF FILE BLOCK FOR THIS OPERATION.
	^U3	^UNUSED, MAY BE USED BY ROUTINE.
.FILL
.PARAGRAPH
^THE UNASSIGNED REGISTERS 11-13 ARE AVAILABLE TO THE PROGRAMMER FOR
ANY USE HE HAS, WHICH GENERALLY IS TO ACCESS A GLOBAL DATA STRUCTURE.
.PARAGRAPH
.INDEX ^FLAG REGISTER
.INDEX <LZEFLG
.INDEX <F
^THE FLAG REGISTER, ^F, CURRENTLY HAS ONLY ONE BIT DEFINED (<LZEFLG)
LEAVING THE REMAINING 35 TO THE PROGRAM WHICH MAY BE DEFINED VIA
THE <>FLAG MACRO. <>FLAG REQUIRES A LIST OF SYMBOL NAMES AND
WILL ASSIGN A BIT FROM 1^B35 TO 1^B0 TO EACH SYMBOL,
REQUIRING THAT THEY BE ACCESSED VIA THE <>C.MAC MACROS (<TXNE, ETC.).
^SINCE BITS ARE ASSIGNED FROM RIGHT TO LEFT, THIS NORMALLY LEAVES THE SIGN
BIT AVAILABLE FOR ANY HIGH SPEED FLAG REQUIREMENTS (IN THE SENSE
THAT IT MAY BE USED TO TRANSFER CONTROL IN A SINGLE INSTRUCTION
(<JUMPL) INSTEAD OF THE TWO THE OTHER FLAGS REQUIRE (<TXNE/JRST)).
.PAGE
.HL 1 ^INPUT <UUO\S
.PARAGRAPH
^SO FAR WE HAVE SEEN MOST OF THE OUTPUT <UUO\S, BUT HAVE SAID
NOTHING ABOUT INPUT.
^THE NEXT TWO PROGRAMS WILL DO INPUT VIA <TULIP, YET
WILL NOT EXECUTE THE <UUO\S.
^THIS PARADOX WILL BE RESOLVED IN THE NEXT SECTION, BUT SINCE
AN UNDERSTANDING OF <TULIP INPUT WILL BE HELPFUL, THE
<UUO\S ARE DESCRIBED HERE (EACH POINTS TO A MEMORY LOCATION).
.LEFT MARGIN 9
.TAB STOPS 10
.BLANK 1
.INDENT -6
<>RCH	^READ THE NEXT CHARACTER (OR ANY SIZE BYTE) INTO _<ADDR_>.
.BLANK 1
.INDENT -6
<>CCH	^REREAD THE CURRENT CHARACTER (RETURNED BY THE
LAST <RCH) INTO _<ADDR_>.
.BLANK 1
.INDENT -6
<>LCH	^REREAD THE LAST CHARACTER (RETURNED BY THE NEXT TO LAST <RCH)
INTO _<ADDR_>.
^INPUT MAY NOT BE BACKED UP MORE THAN ONE CHARACTER; ATTEMPTS TO DO
SO WILL BE IGNORED.
.BLANK 1
.INDENT -9
^THE FOLLOWING <UUO\S ARE MEANT FOR USE ONLY WITH <ASCII CHARACTERS:
.LEFT MARGIN 9
.BLANK 1
.INDENT -6
<>RFLG	^PUT THE CHARACTER FLAGS (BELOW) FOR THE CHARACTER IN _<ADDR_>
INTO _<ADDR_>+1.
.BLANK 1
.INDENT -6
.INDEX <RCHF
.INDEX <CCHF
<RCHF, <CCHF, AND <>LCHF - ^ACT LIKE <RCH, <CCH, AND <LCH FOLLOWED
BY <RFLG; HENCE READ A CHARACTER INTO _<ADDR_> AND THE FLAGS INTO
_<ADDR_>+1.
.LEFT MARGIN 0
.PARAGRAPH
^SINCE THERE ARE SEVERAL CHARACTERS THAT CANNOT BE USED AS PARAMETERS TO
A MACRO BECAUSE THEY WILL CONFUSE PARAMETER DECODING,
THE FOLLOWING SYMBOLS ARE DEFINED SO THEY MAY BE EASILY USED:
.TEST PAGE 6
.TAB STOPS 12
.BLANK 1
.NOFILL
.LEFT MARGIN 3
<>NULL	^NULL (0)
<>BELL	^CONTROL-^G (7)
<>TAB	^TAB (11)
<>LF	^LINEFEED (12)
<>VT	^VERTICAL TAB (13)
<>FF	^FORMFEED (14)
<>CR	^CARRIAGE RETURN (15)
<>CTRLZ	^CONTROL-^Z (32)
<>ESC	^ESCAPE (33)
<>ALT	^ALTMODE (33) [^LONG PAST TIME TO BURY 175 AND 176!]
<>DBLQ	^DOUBLE QUOTE (")
<>SNGLQ	^SINGLE QUOTE (')
<>LPAREN	^LEFT PARENTHESIS '('
<>RPAREN	^RIGHT PARENTHESIS ')'
<>COMMA	^COMMA (,)
<>SEMI	^SEMI-COLON (;)
<>LANGLE	^LEFT ANGLE BRACKET (_<)
<>RANGLE	^RIGHT ANGLE BRACKET (_>)
<>LSQUAR	^LEFT SQUARE BRACKET ([)
<>RSQUAR	^RIGHT SQUARE BRACKET (])
<>RUBOUT	^YES (177)
<>CRLF	<CR, <LF RIGHT JUSTIFIED (<_<CR_>B28+LF)
.FILL
.LEFT MARGIN 0
.PARAGRAPH
^ASSOCIATED WITH MOST <ASCII CHARACTERS ARE ONE OR MORE FLAGS WHICH
ARE USED TO SIMPLIFY CHARACTER PROCESSING AND PARSING.
^THE CURRENTLY DEFINED FLAGS ARE:
.TEST PAGE 6
.LEFT MARGIN 3
.BLANK 1
.TAB STOPS 12
.NOFILL
<>LETTER	^A-^Z, UPPER AND LOWER CASE.
<>DIGIT	0-9.
<>BLANK	^SPACE AND TAB.
<>BREAK	^LINEFEED, VERT. TAB, FORMFEED, ESCAPE, <CTRL-G, <CTRL-Z.
<>LGLSIX	^CODES 40-137. (^VALID <SIXBIT CHARACTERS.)
.FILL
.LEFT MARGIN 0
.PAGE
.HL 1 PROGRAM 3 - PRINT A DIRECTORY FROM ANY DECTAPE.
.PARAGRAPH
^ONE OF THE NEW ADDITIONS IN ^PROGRAM 3 IS THAT IT HAS A
VERSION NUMBER.
<TULIP IS INVOLVED IN THIS TOO AND WITH THREE MACROS ALLOWS
ANY VERSION NUMBER PROCESSING NEEDED.
.BLANK 1
.LEFT MARGIN 6
.INDENT -3
<>VERSION (VERSION,UPDATE,EDIT,WHO) - ^THIS PUTS THE PROGRAM VERSION IN
LOCATION <>.JBVER USING THE STANDARD <DEC FORMAT
WHICH IS FULLY DESCRIBED IN THE PHONE BOOK.
.INDEX <%VVERS
.INDEX <%VUPDA
.INDEX <%VEDIT
^IN ADDITION, SYMBOLS <%VVERS, <%VUPDA,
<%VEDIT, AND <>%VWHO ARE ALL DEFINED WITH THE APPROPRIATE DATA.
.INDEX <%%%TLP
<VERSION ALSO REFERENCES THE SYMBOL <%%%TLP, <TULIP<'S
MAJOR VERSION NUMBER, TO FORCE IT INTO THE SYMBOL TABLE SO THE LOADER
WILL COMPLAIN IF PROGRAMS ASSEMBLED WITH VERY DIFFERENT VERSIONS
OF <>TULIP.MAC ARE USED.
^THIS IS DONE AS A WARNING IF NEW <UUO<S OR REGISTER ASSIGNMENTS
HAVE BEEN MADE, HINTING AT POSSIBLE IMCOMPATIBILITIES.
.B 1;.I -3
<VERSION (VERSION,UPDATE,EDIT,WHO,SYMBOL) - [^LIKE THE PREVIOUS SAMPLE CALL,
BUT WITH A FIFTH PARAMETER.] ^INSTEAD OF STORING THE VERSION NUMBER IN
<.JBVER, THIS WILL DEFINE _<SYMBOL_> TO BE THE ASSEMBLED VALUE
AND IS PRIMARILY MEANT TO BE USED WITHIN LIBRARIES SINCE <.JBVER MAY NOT.
^IN THIS MANNER, <>TULLIB.MAC DEFINES <>%UUO AND <>%LEXINT TO BE
THE VERSIONS OF THOSE TWO MODULES.
.BLANK 1
.INDENT -3
<>VERSTR - ^DEFINED BY <VERSION, THIS EXPANDS TO SIMPLY
A CALL ON THE <>XX MACRO (BELOW) USING SAME PARAMETERS AS
WERE USED FOR <VERSION.
.BLANK 1
.INDENT -3
<>XX VER,UPD,EDIT,WHO - ^DEFINED IN THE PROGRAM, THIS MACRO
ALLOWS IT TO MAKE PRINTABLE STRINGS OR PRETTY <>TITLE
AND <>SUBTTL STATEMENTS CONTAINING THE VERSION NUMBER.
^THIS NEED NOT BE AT THE BEGINNING AS IS DONE IN
PROGRAM 3, BUT MAY BE ANYWHERE.
^IN FACT, FOR THE PURISTS, ONE COULD DEFINE <>XX AT THE
BEGINNING OF THE PROGRAM AND CALL VIA <>VERSTR TO SET UP THE
PROGRAM TITLE, THEN REDFINE <>XX LATER IN THE CONSTANTS AREA
TO PUT THE VERSION MESSAGE THERE!
^IF USING THREE MACROS SEEMS A LITTLE MORE COMPLICATED THAN
NECESSARY, IT IS DONE TO ALLOW THE VERSION NUMBER TO BE CHANGED
BY MODIFYING ONLY ONE LINE IN THE PROGRAM.
.LEFT MARGIN 0
.PARAGRAPH
.INDEX <FISEL
.INDEX <IO STREAMS
^A COUPLE NEW <UUO\S ARE USED, <FOSEL AND ITS MATE, <FISEL.
^AS MIGHT BE EXPECTED THESE ARE ACTUALLY FILE UTILITY <UUO\S,
BUT AS THEY ARE NOT INVOLVED WITH THE MONITOR <IO <UUO\S ^I DIDN'T
BOTHER TO DESCRIBE THEM IN THAT SECTION.
<TULIP IS DESIGNED TO HAVE ONE INPUT STREAM AND ONE OUTPUT STREAM
IN USE AT ANY GIVEN TIME (WHICH IS GENERALLY IDEAL FOR TASKS LIKE
COPYING FILES), AND THESE STREAMS ARE SET UP WITH ANY FILE
.INDEX <FREL
UTILITY <UUO EXCEPT <>FSETUP AND <FREL.
.INDEX <FISEL
.INDEX <FIOPEN
.INDEX <FIGET
.INDEX <FLOOK
.INDEX <FICLOS
.INDEX <FICLS
(<FISEL, <FIOPEN, <FIGET, <FLOOK, <FICLOS, AND <FICLS
ALL MAKE THE INPUT STREAM BE FROM THE FILE BLOCK THEY POINT TO AND
.INDEX <FOSEL
.INDEX <FOGET
.INDEX <FENT
.INDEX <FOCLOS
.INDEX <FOCLS
<FOSEL, <FOGET, <FENT, <FOCLOS, AND <FOCLS ALL MAKE THE OUTPUT
STREAM BE FROM THEIRS.)
^TO RESLECT THE DEFAULT <>TTCALL <IO BLOCKS, <>FISEL#0 AND
<>FOSEL#0 WILL DO THE JOB.
<>FOSEL IS USED HERE BECAUSE <>FIGET HAS ALREADY DONE THE
<OPEN, SO THERE IS NO REASON TO DO EVERYTHING A <>FOOPEN WOULD.
^THERE IS A SECOND OUTPUT STREAM WHICH MAY BE USED WITH A SPECIAL
SUBSET OF <UUO\S AND IS MEANT FOR USE AS AN ERROR REPORTING
STREAM, NORMALLY USING <>TTCALL <IO.
(^THIS IS THAT 'ALLOWABLE' USE OF <>TTCALL MENTIONED A COUPLE
OF SECTIONS AGO.
^IT IS ESPECIALLY HANDY FOR PROGRAMS THAT MAY OUTPUT TO ANY DEVICE
(INCLUDING <TTY) BUT ALWAYS WANT ERROR MESSAGES TO GO TO <TTY.
^TO USE BUFFERED MODE <IO FOR <TTY ERROR
MESSAGES, YOU MUST EITHER ALLOW THE <TTY TO BE
USED BY ONLY THE ERROR ROUTINES OR INTERCEPT ATTEMPTS TO OPEN IT AND
REDIRECT OUTPUT TO THE PREVIOUSLY OPENED <TTY FILE.)
.PARAGRAPH
^ALL THAT <>FISEL AND <>FOSEL DO IS SIMPLY PUT THEIR ADDRESS FIELDS
.INDEX <OFILE
IN LOCATIONS <>IFILE AND <OFILE, RESPECTIVELY.
^BOTH THESE LOCATIONS ARE DEFINED WITHIN <>TULLIB AND NORMALLY WILL
BE OF LITTLE INTEREST TO PROGRAMMERS.
^HOWEVER, AT TIMES THEY ARE MOST USEFUL
AS IN SAVING THE CONTENTS OF EITHER OF THEM TO ALLOW A SUBROUTINE
TO TEMPORARILY REDIRECT DATA FLOW AND RESTORE IT BEFORE RETURNING TO THE CALLER.
^ALSO, WHEN DEBUGGING PROGRAMS, THERE ARE MANY INSTANCES WHERE IT IS VERY
HANDY TO REDIRECT OUTPUT TO <>TTCALL SO
YOU CAN SEE WHAT THE BEAST IS DOING. <>DDT MAKES FOR A VERY SIMPLE
MEANS OF MANUALLY CLEARING <>OFILE TO DO EXACTLY THAT.
.INDEX <EFILE
^THE ERROR STREAM ALSO HAS ITS OWN FILE BLOCK LOCATION, <EFILE,
BUT SINCE THERE IS NO <'FESEL' <UUO, IF THE PROGRAM WANTS TO
REDIRECT THE ERROR STREAM, IT MUST DO SO EXPLICITLY.
.INDEX <IO ERROR <UUO\S
.PARAGRAPH
^PROGRAM 3 DOES ALL ITS OWN <IO ERROR HANDLING BECAUSE
<TULIP WOULD ONLY PRINT AN ERROR MESSAGE AND STOP THE PROGRAM.
^INSTEAD, ^PROGRAM 3 WILL PRINT THE SAME MESSAGE BUT THEN RESTART.
.P
^THERE ARE FOUR STRING PRINTING <UUO\S THAT DIRECT OUTPUT TO THE
ERROR DEVICE:
.LEFT MARGIN 9
.BLANK 1
.INDENT -6
.INDEX <WASC
<>EWSIX AND <>EWASC - ^LIKE <>WSIX AND <WASC.
^THE LENGTH (THE <AC FIELD) MAY NOT BE SPECIFIED.
.BLANK 1
.INDENT -6
.INDEX <DIASC
<>EDISIX AND <>EDIASC - ^LIKE <>DISIX AND <DIASC, EXCEPT THAT
ALL <TULIP OUTPUT <UUO\S IN THE INSTRUCTION LIST
WILL PRINT ON THE ERROR DEVICE, MEANING YOU CAN USE <UUO\S
LIKE <>WDEC AND FRIENDS.
.LEFT MARGIN 0
.TEST PAGE 9
.PARAGRAPH
^FURTHERMORE, THERE ARE TEN <UUO\S THAT REPORT FAILURES ON THE
MONITOR <IO <UUO\S.
^HALF OF THEM PRINT ON THE ERROR DEVICE AND PRECEDE EACH MESSAGE
WITH
.I 3
'? ^DEVICE _<DEV_>'
. ;FOR <>OPEN FAILURES OR
.I 3
'? _<DEV_>:_<FILE_>._<EXT_>[_<PPN_>] (_<ERROR CODE_>)'
. ;FOR ALL OTHERS.
^THE REST PRINT ON THE NORMAL OUTPUT DEVICE WITHOUT
THE MESSAGE HEADER.
.INDEX <ERR PREFIX
^THE NAMES OF THE ERROR DEVICE <UUO\S ARE PREFIXED WITH '<ERR'
.INDEX <WER PREFIX
AND THE NORMAL OUTPUT DEVICE ONES WITH '<WER'.
^ALL TAKE THE ADDRESS OF THE LOW SEGMENT FILE BLOCK INVOLVED IN THE
ADDRESS FIELD.
.INDEX <IO ERROR <UUO\S
.LEFT MARGIN 3
.BLANK 1
.INDENT -3
.INDEX <ERRIOP
^INPUT OPEN ERRORS: <ERRIOP, <>WERIOP AND
.INDENT -3
.INDEX <ERROOP
^OUTPUT OPEN ERRORS: <ERROOP, <>WEROOP
.BREAK
^CURRENTLY THE TWO PAIRS ARE IDENTICAL SINCE AN <>OPEN
FAILURE IS DIRECTION INDEPENDENT.
.TEST PAGE 4
.INDENT -3
^ASSOCIATED MESSAGES:
.BLANK 1
.TAB STOPS 6
	NOT AVAILABLE
.BREAK
	DOES NOT EXIST
.BLANK 2
.TP 3
.INDENT -3
.INDEX <ERRLK
<>LOOKUP ERRORS: <ERRLK, <>WERLK AND
.INDENT -3
.INDEX <ERRENT
<>ENTER ERRORS: <ERRENT, <>WERENT -
^DIFFERENT PROCESSING IS DONE FOR ERROR TYPE (<LOOKUP/ENTER) AND DEVICE
TYPE (DISK, ^^DEC\\TAPE, AND OTHER) WHICH SHOULD SOLVE THE CONFUSION
RESULTING FROM PROGRAMS LIKE <LIB40 COMPLAINING ABOUT FULL TAPES
WHEN THE DISK RUNS OUT OF SPACE!
<>ERRLK AND <>WERLK MAY ALSO BE USED TO REPORT <>GETSEG AND
.INDEX <RUN <UUO
<RUN <UUO FAILURES, BUT THE PERTINENT DATA MUST FIRST BE COPIED
INTO THE FILE BLOCK (DEVICE, FILE, EXTENSION, AND <PPN).
^EXTENDED <LOOKUP BLOCKS ARE NOT HANDLED SO DATA MUST BE COPIED FROM
THE EXTENDED BLOCK INTO THE FILE BLOCK BEFORE EXECUTING THIS <UUO.
.TEST PAGE 6
.INDENT -3
^ASSOCIATED MESSAGES:
.INDEX <IO ERROR <UUO\S
.LEFT MARGIN 6
.BLANK 1
.NOFILL
(0) ^FILE NOT FOUND
(0) ^ILLEGAL FILE NAME
(1) ^USER ^FILE ^DIRECTORY NOT FOUND
(2) ^PROTECTION VIOLATION
(2) ^DIRECTORY FULL
(3) ^FILE BEING MODIFIED
(4) ^ALREADY EXISTING FILENAME
(5) ^ILLEGAL <UUO SEQUENCE
(6) ^TRANSMISSION ERROR
(6) <UFD OR ^RIB ERROR
(7) ^NOT A SAVE FILE
(10) ^INSUFFICIENT CORE
(11) ^DEVICE NOT AVAILABLE
(12) ^NO SUCH DEVICE
(13) ^^GETSEG UUO\\ ILLEGAL
(14) ^DISK FULL OR QUOTA EXCEEDED
(15) ^WRITE-LOCK ERROR
(16) ^INSUFFCIENT MONITOR TABLE SPACE
(17) ^PARTIAL ALLOCATION ONLY
(20) ^BLOCK NOT FREE ON ALLOCATION
(21) ^ATTEMPT TO SUPERCEDE DIRECTORY
(22) ^ATTEMPT TO DELETE DIRECTORY
(23) ^SUB ^FILE ^DIRECTORY NOT FOUND
(24) ^SEARCH LIST EMPTY
(25) <SFD NESTED TOO DEEPLY
(26) ^NO-CREATE FOR SPECIFIED PATH
(27) ^SEGMENT NOT IN SWAP AREA
(..) ^UNEXPECTED ERROR
.LEFT MARGIN 3
.FILL
.BLANK 2
.INDENT -3
.INDEX <ERRIN
<>INPUT ERRORS: <ERRIN, <>WERIN AND
.INDENT -3
.INDEX <ERROUT
<>OUTPUT ERRORS: <ERROUT, <>WEROUT - ^THE ENTIRE 18 BIT FILE STATUS
IS PRINTED FOLLOWED BY THE APPROPRIATE ERROR MESSAGE.
^SHOULD MORE THAN ONE ERROR BIT BE SET, ONLY THE
FIRST APPLICABLE MESSAGE IN THE LIST WILL BE PRINTED.
^AGAIN, DIFFERENT PROCESSING IS DONE AS IN THE <LOOKUP/ENTER
ROUTINES.
.TEST PAGE 10
.INDENT -3
^ASSOCIATED MESSAGES:
.BLANK 1
.LEFT MARGIN 6
.NOFILL
(400000) ^WRITE LOCK ERROR
(200000) ^DEVICE ERROR
(100000) ^CHECKSUM OR PARITY ERROR
(40000) ^BLOCK OR BLOCK _# TOO LARGE
(40000) ^TAPE FULL
(40000) ^DISK FULL OR QUOTA EXCEEDED
(20000) ^END OF FILE
(.....) ^UNEXPECTED ERROR
.FILL
.LEFT MARGIN 0
.INDEX <IO ERROR <UUO\S
.INDEX ^LEXICAL ANALYSIS
.PAGE
.HL 1 <LEXINT - ^THE '^L' IN <TULIP.
.PARAGRAPH
^DESPITE THE SIZE OF THE LAST SECTION, THE MAJOR ADDITION IN
^PROGRAM 3 IS THE LEXICAL ANALYSIS TO PARSE A DEVICE NAME.
^USAGE HERE IS AS SIMPLE AS POSSIBLE AND IS DESIGNED TO SHOW
HOW TO USE IT WITH AS LITTLE OVERHEAD AS POSSIBLE (LIKE WHAT
WE DID IN PROGRAM 1).
^THREE BASIC THINGS ARE NECESSARY: A CALL ON <>LEXINT TO DO
THE PARSE, A PRODUCTION TABLE TO DRIVE <>LEXINT WHICH DESCRIBES
HOW TO PARSE THE INPUT STREAM, AND A SET OF ACTION ROUTINES
WHICH MANIPULATE THE PARSED DATA.
^THE HEART AND MOST INTERESTING PIECE IS THE PRODUCTION TABLE
WHICH IS SET UP WITH THE AID OF THREE MACROS:
.LEFT MARGIN 6
.BLANK 1
.INDENT -3
<>TBLBEG LABEL - ^THIS MUST BE AT THE BEGINNING OF A PRODUCTION
TABLE AND IS USED TO INITIALIZE INTERNAL SYMBOLS THAT ARE
OF NO INTEREST TO US. _<^LABEL_> WILL BE DEFINED TO BE THE ADDRESS OF
THE PRODUCTION TABLE AND IS USED FOR IDENTIFICATION.
.BLANK 1
.INDENT -3
<>TBLEND - ^THIS MUST APPEAR AT THE END OF THE PRODUCTION TABLE
AND GENERATES A DISPATCH TABLE TO THE ACTION ROUTINES.
^IF YOU FORGET IT, <MACRO WILL COMPLAIN ABOUT ALL SORTS
OF UNDEFINED SYMBOLS.
.BLANK 1
.INDENT -3
.INDEX <PROD
^^PROD\\(#CHAR SPEC,ACTION ROUTINE,CHAR DISP,NEXT PROD)
.BREAK
^NOW THIS IS A MACRO! ^EACH CALL GENERATES ONE PRODUCTION (IN
ONE WORD, BY THE WAY).
^TO AID READABILITY, THE PARAMETERS SHOULD BE IN THE FORMAT
USED IN THE PROGRAM, I.#E_. A TAB AFTER '<PROD(', 16 SPACES FOR
_<CHAR SPEC_> (TWO TAB STOPS), 4 FOR _<ACTION ROUTINE_>, 1 FOR _<CHAR
DISP_>, 6 FOR _<NEXT PROD_> AND A TAB FOR COMMENTS AFTER ')'.
^TRAILING BLANKS (TABS FOR _<CHAR SPEC_>) SHOULD BE USED INSTEAD OF
PRECEDING BLANKS.
^THE PARAMETERS ARE:
.INDEX ^LEXICAL ANALYSIS
.LEFT MARGIN 9
.BLANK 1
.INDENT -3
CHAR SPEC - ^THIS MAY BE A CHARACTER (E.#G_. "^M" OR <CR),
ANGLE BRACKETED FLAGS (E.#G_. <_<BLANK_> OR <_<LETTER!DIGIT_>),
NEGATED CHARACTERS (E.#G_. -"^M" OR -<CR),
OR NEGATED ANGLE BRACKETED FLAGS (E.#G_. <-_<BREAK_>).
^THIS PARAMETER DEFINES THE MATCH CONDITION FOR THE PRODUCTION.
^IF THE MATCH FAILS, THE REST OF THE PRODUCTION IS IGNORED, AND
THE NEXT ONE IS PROCESSED USING THE SAME CHARACTER.
^HOWEVER, SHOULD IT SUCCEED, THE REST OF THE PRODUCTION IS PROCESSED
AS DESCRIBED BELOW TO HANDLE THE PARSED DATA.
.INDEX <SG
_<<SG_> IS A SPECIAL _<CHAR SPEC_> AVAILABLE THAT WILL ALWAYS
MATCH AND IS USED EITHER FOR AN UNCONDITIONAL BRANCH
OR TO FORCE A CALL TO AN ACTION ROUTINE.
^DUE TO A SLIGHT MISUNDERSTANDING BETWEEN <MACRO-10 AND <TULIP,
THERE MUST BE A TAB BEFORE THE _<CHAR SPEC_>.
.BLANK 1
^ONE IMPLEMENTATION DETAIL IS IMPORTANT HERE.
^AS MIGHT BE EXPECTED, PROCESSING THESE CHARACTERS RESULTS IN
.INDEX <RCHF
.INDEX <CCHF
THE EXECUTION OF A <RCHF, <CCHF, OR <>LCHF <UUO.
^THIS IS VITAL TO THE ACTION OF THE COMMAND FILES IN ^PROGRAM 4,
TO BE DISCUSSED BELOW.
.BLANK 1
.INDENT -3
ACTION ROUTINE - ^THIS NAMES THE SPECIAL ACTION ROUTINE TO BE
USED TO MANIPULATE THE PARSED DATA.
^IT IS A ONE TO FOUR CHARACTER FIELD AND MAY BE LEFT BLANK
WHICH MEANS THAT NO SPECIAL ACTION WILL BE DONE.
.BLANK 1
.INDENT -3
CHAR DISP - ^ONE OF *, __, OR SPACE, AND SPECIFIES WHAT TO DO WITH
THE CHARACTER BEFORE THE NEXT PRODUCTION IS EXECUTED:
.LEFT MARGIN 12
.BLANK 1
.INDENT -3
* - ^WE ARE DONE WITH THIS CHARACTER, USE THE NEXT WITH THE NEXT
PRODUCTION.
.BLANK 1
.INDENT -3
__ - ^BACKUP A CHARACTER, USE THE PREVIOUS WITH THE NEXT PRODUCTION.
.BLANK 1
.INDENT -3
SPACE - ^NO CHANGE, USE THE SAME CHARACTER WITH THE NEXT PRODUCTION.
(^THE SAME HAPPENS IF THE PRODUCTION FAILS.)
.LEFT MARGIN 9
.BLANK 1
.INDENT -3
NEXT PROD - ^ADDRESS OF THE NEXT PRODUCTION TO EXECUTE (EACH
<>PROD MACRO CALL MAY BE LABELED).
^IF THE FIELD IS BLANK, THE NEXT PRODUCTION WILL BE ASSUMED.
.INDEX ^LEXICAL ANALYSIS
.INDEX ^ACTION ROUTINES
.LEFT MARGIN 0
.PARAGRAPH
^THE ACTION ROUTINES ALLOW US TO DO SOMETHING WITH THE DATA PARSED.
^WITHOUT THEM, WE COULDN'T EVEN STOP <>LEXINT EXCEPT VIA AN <IO ERROR!
^MOST OF THE ACTION ROUTINES ARE SUPPLIED BY THE PROGRAM AND
ARE USED WHENEVER A SUCCESSFUL PRODUCTION HAS FOUND SOMETHING
INTERESTING.
^ACTION ROUTINES MAY COMMUNICATE WITH EACH OTHER TO PASS RESULTS
THROUGH REGISTERS ^T1, ^T2, AND ^T3. (^T4 IS CLOBBERED.)
<>LEXINT PASSES DATA TO THE ACTION ROUTINE IN THE PERMANENT REGISTERS:
.LEFT MARGIN 3
.BLANK 1
^P1 - ^RELATIVE ADDRESS IN PRODUCTION TABLE OF THIS ONE.
.BLANK 1
^P2 - ^CURRENT CHARACTER UNDER SCAN.
.BLANK 1
^P3 - ^CHARACTER FLAGS FOR THIS CHARACTER.
.BLANK 1
^P4 - ^P1,,ADDRESS OF PRODUCTION TABLE.
.LEFT MARGIN 0
.BLANK 1
^OF THESE, ONLY ^P2 AND ^P3 HAVE DATA NORMALLY USED.
.TEST PAGE 5
.BLANK 1
^FOUR SPECIAL ACTION ROUTINES ARE SUPPLIED IN <LEXINT:
.LEFT MARGIN 6
.BLANK 1
.INDENT -3
<>SRET - ^PERFORM A SKIP RETURN FROM <LEXINT, NORMALLY
USED TO INDICATE A SUCCESSFUL PARSING.
.BLANK 1
.INDENT -3
<>RET - ^PERFORM A NON-SKIP RETURN, NORMALLY INDICATING AN
UNSUCCESSFUL PARSING.
.BLANK 1
.INDENT -3
<>CALL - <>LEXINT USES A STACK SUBROUTINE CALLING
CONVENTION FOR REPEATED PARSINGS OF DATA LIKE NUMBERS, FILE
SPECIFIERS, ETC.
^TAKE THE NEXT PRODUCTION SPECIFIED BY _<NEXT PROD_>, BUT WHEN
<>RET IS CALLED IT WILL DO A SUBROUTINE RETURN AND THE NEXT
PRODUCTION EXECUTED WILL BE THE ONE IMMEDIATELY AFTER THE <CALL.
<>SRET MAY ALSO BE USED TO CAUSE A SKIP RETURN FOR SUBROUTINES
NEEDING AN ERROR/SUCCESS INDICATION.
.BLANK 1
.INDENT -3
<>JUMP - ^NORMALLY ONLY CALLED (BY A <JRST) FROM AN ACTION ROUTINE INSTEAD OF
A PRODUCTION, THIS ALLOWS AN ACTION ROUTINE TO CONTROL PARSING.
^THE NEXT PRODUCTION EXECUTED WILL BE FROM THE ADDRESS POINTED
AT BY REGISTER ^T1.
^THIS IS MEANT FOR SOMETHING LIKE A COMMAND DISPATCH WHERE AN ACTION
ROUTINE IS CALLED AFTER A COMMAND IS PARSED.
^GENERALLY THE COMMAND IS MAPPED TO THE PRODUCTION USED TO PARSE
FURTHER DATA, AND THAT ADDRESS IS PASSED TO <JUMP.
.INDEX ^LEXICAL ANALYSIS
.INDEX ^ACTION ROUTINES
.LEFT MARGIN 0
.PARAGRAPH
^WHEREAS ACTION ROUTINES ARE REFERED TO BY A FOUR CHARACTER NAME
INSIDE A PRODUCTION, THEY ARE DEFINED IN THE PROGRAM AS THOSE
FOUR PREFIXED WITH '^A.'.
^THEREFORE, TO CALL THE <>JUMP ROUTINE, YOU NEED A <JRST#<A.JUMP
INSTRUCTION.
^ONE OTHER NOTE - THE <>TBLBEG MACRO DOES A <PHASE#0, SO ALL
THE LABELS ARE RELATIVE TO THE START OF THE TABLE.
.PARAGRAPH
^FINALLY, TO START ALL THIS ROLLING, THE PROGRAM CALLS <>LEXINT
WITH THE RIGHT HALF OF ^T1 POINTING TO THE TABLE
AND THE LEFT HALF POINTING TO THE RELATIVE ADDRESS OF THE FIRST PRODUCTION (WHICH IS
NORMALLY ZERO, SO A <MOVEI INSTRUCTION WILL SAVE A WORD).
^THE NORMAL RETURN IS TAKEN FROM <>LEXINT IF THE LAST PRODUCTION
CALLED <>RET AS THE ACTION ROUTINE, THE SKIP RETURN IF <>SRET
WAS THE ACTION ROUTINE.
.INDEX ^ACTION ROUTINE
.PARAGRAPH
^WHEW. ^WITH THAT BEHIND US, LET'S LOOK AT ^PROGRAM 3 AND SEE JUST
HOW WE USE ALL THIS.
^ON PAGE 2, <TRYAGN PROMPTS FOR A ^^DEC\\TAPE, FORCES
OUT THE BUFFER TO PRINT IT, THEN CALLS <LEXINT TELLING
IT TO USE <LEXTAB AS THE TABLE, AND TO START WITH THE FIRST
PRODUCTION.
.INDEX <RET
^SINCE WE ALWAYS RETURN VIA <RET, <>LEXINT
WILL ALWAYS DO A NON-SKIP RETURN.
^PAGE 5 HAS BOTH THE PRODUCTION TABLE AND THE TWO ACTION ROUTINES
NEEDED BY THE PROGRAM.
<>TBLBEG HEADS THE PRODUCTION TABLE, AND <LEXTAB WILL BE ITS NAME.
^IF YOU WANT TO COMMENT THAT LINE, SOME SEPARATOR MUST
OCCUR IMMEDIATELY AFTER THE TABLE NAME OR ELSE <MACRO-10 WILL GET
CONFUSED (DUMB PROGRAM).
^PERHAPS BETTER THAN A SEMI-COLON RIGHT AFTER <LEXTAB WOULD HAVE
BEEN TO SAY <TBLBEG(LEXTAB) WHICH SOLVES THE PROBLEM NICELY.
^THIS PRODUCTION TABLE SIMPLY PARSES A <SIXBIT DEVICE NAME
WITHOUT ANY ERROR CHECKING, SO WE NEED A FEW ACTION ROUTINES TO HELP
US COLLECT THAT INFORMATION.
^THE FIRST PRODUCTION LOOPS ON ITSELF (NOTE THE PERIOD IN THE
_<NEXT PROD_> FIELD), THROWING AWAY ANY NULLS
LEFT IN THE BUFFER AFTER THE PREVIOUS COMMAND, IF ANY.
^THE SECOND PRODUCTION CALLS <SIXI (REMEMBER, _<<SG_> MATCHES
ANY CHARACTER) WHICH IS CODED AFTER THE TABLE AT <A.SIXI.
^ALL IT DOES IS MAKE A BYTE POINTER TO THE REGISTER WHERE WE
WILL ASSEMBLE THE <SIXBIT WORD AS IT IS PARSED AND CLEARS
THAT REGISTER OF ANY GARBAGE IT HAD.
^THE THIRD PRODUCTION WILL CALL <SIXS FOR EVERY ALPHANUMERIC
CHARACTER UNTIL IT FINDS ONE THAT ISN'T.
^AFTER THE FIRST NON-ALPHANUMERIC CHARACTER IS SCANNED, <STOR
IS CALLED TO SAVE IT IN THE FILE BLOCK.
^AT THIS POINT, WE'RE DONE, BUT WE CONTINUE TO SCAN AND THROW AWAY
CHARACTERS UP TO (BUT NOT INCLUDING) THE BREAK,
WHICH MUST NOT BE SCANNED BECAUSE IT ALREADY HAS BEEN
READ ONCE.
^TELLING <>LEXINT TO SCAN IT WILL RESULT IN READING ANOTHER CHARACTER
FOR THE NEXT PRODUCTION,
WHICH WE DO NOT WANT TO HAPPEN.
.PAGE
.HL 1 ^P\\ROGRAM 4 - THE LAST ONE
.PARAGRAPH
^PROGRAM 4 STARTED OUT AS A PROGRAM IMPROVING MOSTLY ON THE LEXICAL
ANALYSIS PORTION TO PROVIDE REAL COMMAND SCANNING.
^HOWEVER, IT GOT A LITTLE CARRIED AWAY, AND WOUND UP HAVING A FEW
MULTI CHARACTER SWITCHES AND EVEN COMMAND FILES (NESTED, OF COURSE).
^AT LEAST, IT HAS GIVEN ME A CHANCE TO WRITE THE <SIXBIT NAME
SEARCH ROUTINE ^I'VE WANTED TO DO FOR SOME TIME!
^THE EASIEST WAY TO DISCUSS ALL THE CHANGES IS TO SIMPLY START ON
PAGE 14 AND SKIM THROUGH THE SIMPLE DIFFERENCES AND THEN RETURN
AND HIT THE BIG ONES.
^IN FACT, ^I THINK THAT JUST ABOUT EVERY PAGE IN THE PROGRAM HAS BEEN
CHANGED, SO ANY OTHER SCHEME WOULD PROBABLY BE MORE CONFUSING.
.PARAGRAPH
^THE FIRST PAGE HAS A NUMBER OF NEW ASSIGNMENTS PLUS A
.INDEX <GETCHN
NEW MACRO (<GETCHN) WHICH ASSIGNS SOFTWARE CHANNELS. ^IT IS USED NOT ONLY
HERE, BUT ALSO LATER TO ASSIGN <IO CHANNELS FOR THE COMMAND FILES.
.INDEX ^UNASSIGNED REGISTERS
^I CAME UP WITH A GOOD USE FOR A GLOBAL REGISTER, SO <FB WILL
BE USED TO POINT TO THE ADDRESS OF A LOSEG FILE BLOCK WITHIN THE
COMMAND SCANNER.
^FINALLY, THERE ARE SOME FLAGS FOR USE AROUND THE PROGRAM.
<FSTDIR AND <UNLOAD ARE SET BY SWITCHES IN THE COMMAND LINE
AND ARE USED TO REQUEST PRINTING A SHORT FORMAT DIRECTORY AND
UNLOADING THE ^^DEC\\TAPE AFTER THE DIRECTORY IS PRINTED.
<PRSDFL (^PA^R^SE^D ^FI^LE NAME) IS SET IN THE FILE SPECIFIER
CODE TO REMEMBER WHEN A FILE NAME HAS BEEN SEEN SO AS TO EXPECT AN
EXTENSION NEXT.
<LSTOPN IS SET WHEN OUTPUT IS GOING SOMEWHERE OTHER THAN TO
<TTY TO REMEMBER THAT THAT FILE MUST BE CLOSED SOMETIME.
.PARAGRAPH
^PAGE 15 HAS CODE TO RECLAIM ANY BUFFER SPACE USED DURING COMMAND PROCESSING AND IS
ESPECIALLY USEFUL WHEN SEVERAL OUTPUT FILES OR COMMAND FILES ARE USED.
.PARAGRAPH
^PAGES 16 AND 17 ARE A SLIGHTLY EXPANDED VERSION OF THE DIRECTORY PRINTER,
NOW WITH CODE TO HANDLE SHORT FORMAT DIRECTORIES.
^SINCE THE CODE FOR THAT IS SO SIMPLE (THANKS TO <TULIP),
IT IS IMPLEMENTED IN A SEPARATE LOOP.
^NOTE THAT SINCE <>SAVE1 HANDLES THE RESTORE ACTION ITSELF, WE
ARE FREE TO TRANSFER CONTROL TO <ZERDIR OR <DIRXIT WITHOUT HAVING TO WORRY ABOUT
THE STATE OF THE REGISTERS, EXCEPT THAT THOSE SECTIONS ARE NO LONGER
FREE TO USE ^P1.
.PARAGRAPH
^PAGES 18 AND 19 HAVE A VASTLY LARGER PRODUCTION TABLE WITH COMMAND DISPATCHING
AND SUBROUTINE CALLS - A FAR CRY FROM THE SIMPLISTIC TABLE IN ^PROGRAM 3!
.PARAGRAPH
^PAGES 20 TO 23 HAVE ALL THE ACTION ROUTINES WITH A FEW OTHERS PUT IN
WHEN THEY SEEM TO BELONG, SPECIFICALLY THE CODE NEEDED TO MANIPULATE
THE COMMAND FILES WHICH WORK ON THE DATA BASE ON PAGES 28 AND 30.
^ONE NEAT TRICK - NOTE THE <PUSH/POP
OF <>IFILE IN <A.DIRE TO PRESERVE THE INPUT STREAM FOR THE CALLER
(THE COMMAND SCANNER).
.PARAGRAPH
^EVEN <TIMPRT ON PAGE 24 HAS BEEN TWEAKED A LITTLE TO USE ONE LESS
REGISTER FOR NO BETTER REASON THAN TO USE ONE LESS REGISTER.
^THE OLD FORM WAS SORT OF A HOLDOVER FROM ^PROGRAM 1, WHICH DID USE THE
THOUSANTHS OF A SECOND, AS YOU MAY RECALL.
.PAGE
.INDEX ^COROUTINES
.INDEX <SIXSRC
.HL 1 <SIXSRC AND COROUTINES
.PARAGRAPH
^PAGES 25 AND 26 MAKE UP THE <SIXBIT NAME SCANNER, WHICH TAKES
TWO PAGES MAINLY BECAUSE OF ALL THE COMMENTS ^I'VE PUT IN TO THOROUGHLY
EXPLAIN IT. ^PERHAPS TOO MANY, BUT IT SHOULD BE HELPFUL TO ANYONE
STUMBLING ACROSS THIS WITHOUT BEING FAMILIAR WITH COROUTINES.
(^BY THE WAY, ^I HAVE LONG CLAIMED THAT THE ONLY COMMENT BETTER THAN A
.INDEX PHILOSOPHY
BLANK LINE IS A FORMFEED. [PHILOSOPHY])
^BESIDES <LUUO\S, ANOTHER THING THAT IS OFTEN OVERLOOKED BY PROGRAMMERS
ARE COROUTINES, WHICH AT TIMES PROVIDE A MORE CONVENIENT CALLING MECHANISM THAN
SUBROUTINES, ESPECIALLY WHEN PAST INFORMATION IS IMPORTANT.
^WHEREAS A SUBROUTINE MUST RECORD ITS STATE SOMEPLACE WHERE
IT CAN ACCESS IT LATER, A COROUTINE CAN SIMPLY STORE IT IN THE <AC
USED IN THE CALL INSTRUCTION.
<>SIXSRC IS IN TWO PIECES - THE MAIN ROUTINE, CALLED TO SEARCH A TABLE,
AND A PURE COROUTINE THAT REMEMBERS HOW MANY PARTIAL MATCHES HAVE BEEN MADE.
^A COROUTINE DIFFERS FROM A SUBROUTINE IN THAT WHEREAS A SUBROUTINE IS
ALWAYS ENTERED AT ITS START, A COROUTINE PICKS UP WHERE IT
LEFT OFF FROM THE LAST CALL.
^THE EFFECT IS NOT SO MUCH LIKE A CALL TO A COROUTINE AS IT IS
A <RETURN TO A CO.... NO, LIKE A CALL FROM... NO, LIKE A TRANSFER TO...
NO, LIKE A COROUTINE TRANSFER BETWEEN SECTIONS OF CODE. ^YEAH!
^LIKE A COROUTINE TRANSFERRING TO ANOTHER WHICH MIGHT TRANSFER
BACK! ^GOT IT.
^ONE INTERESTING FEATURE OF COROUTINES IS THAT THE CALL AND RETURN
INSTRUCTIONS ARE IDENTICAL.
^OOPS. ^ONE TRANSFER INSTRUCTION IS THE SAME AS ANOTHER. ^ERR, YOU KNOW WHAT ^I MEAN.
(^BY THE WAY, ^KNUTH VOLUME 1 HAS A SECTION ON COROUTINES IN CASE
YOU DIDN'T FOLLOW THIS SCHOLARLY DESCRIPTION!)
^THE COROUTINE INSTRUCTION ON A <PDP-10 IS A '^^JSP#AC,(AC)\\',
WHICH WILL SIMPLY EXCHANGE THE <PC WITH <AC
(WHICH MUST BE INITIALIZED BEFORE THE FIRST TRANSFER IS MADE).
^NOTE THAT IF THE FIRST TRANSFER TO THE COROUTINE IS NOT WITHIN A LOOP, THE STANDARD
'^^JSP#AC,\\ADDR' INSTRUCTION WILL DO IT QUITE NICELY!
.PARAGRAPH
^FROM THE OUTSIDE, <>SIXSRC ITSELF IS A SUBROUTINE. ^EACH CALL ENTERS IT FROM THE
TOP AND IT RETURNS AFTER A LIST IS SCANNED.
^HOWEVER, INTERNALLY IT IS  A COROUTINE, TRADING CONTROL BACK AND
FORTH BETWEEN ITSELF AND <SIXMAT AS IT FINDS EACH PARTIAL MATCH.
<SIXMAT'\S COROUTINE STRUCTURE ENABLES IT TO EASILY AND CLEANLY KEEP
TRACK OF THE PROGRESS OF THE SEARCH AND PRINT ANY NECESSARY ERROR
MESSAGES.
^ONE INTERESTING THING ABOUT THESE COROUTINES IS THAT BOTH OF THEM
DO SKIP TRANSFERS TO PASS A LITTLE MORE INFORMATION, MUCH LIKE A
SUBROUTINE'S SKIP RETURN, ONLY AUGMENTED WITH A SKIP ENTRY.
<>SIXSRC DOES A SKIP TRANSFER WHEN IT HAS REACHED THE END OF THE
LIST AND NEEDS TO KNOW WHAT <>SIXMAT FOUND CHECKING THE NUMBER OF MATCHES.
<SIXMAT DOES A SKIP TRANSFER ONLY WHEN ENTERED BY A SKIP TRANSFER,
AND THEN ONLY WHEN IT WISHES TO RETURN AN ERROR, WHICH WILL
BE WHEN <SIXMAT WAS NOT CALLED ONLY ONCE BEFORE (MEANING EITHER
THE ENTRY WAS NOT FOUND OR MORE THAN ONE PARTIAL MATCH WAS
DETECTED MEANING IT IS AMBIGUOUS).
^THE POINT OF ALL THIS IS TO HAVE A TABLE SEARCHER
THAT REPORTS ANY AMBIGUOUS COMMANDS, A VERY USEFUL FEATURE BUT SURPRISINGLY
NEVER DONE TO MY KNOWLEDGE.
.PAGE
.HL 1 ^COMMAND FILE PROCESSING
.PARAGRAPH
^NOT ONLY IS <TULIP'\S <IO STREAM CONCEPT VERY NICE FOR
ALLOWING ROUTINES TO OUTPUT TO ANY DEVICE, BUT THE SAME
HOLDS TRUE FOR INPUT AND ALLOWS COMMAND FILE IMPLEMENTATION TO BE
ALMOST TRIVIAL.
<TULIP GENERATES A COUPLE PROBLEMS, BUT NEITHER IS INSURMOUNTABLE.
^ALL THE COMMAND FILE CODE IS ON PAGES 21 AND 22; PAGE 21 HAS THE ACTION
ROUTINES FOR <>LEXINT AND PAGE 22 HAS THE ROUTINES REFERENCED IN THE
FILE BLOCKS.
^ON PAGE 21, <A.ACAL STEPS TO THE NEXT COMMAND FILE LEVEL AND SETS
REGISTER <FB TO POINT AT THE RIGHT FILE BLOCK TO RECIEVE THE DATA
FROM <FILSPC.
<A.DCMD OPENS THE COMMAND FILE, THEREBY REDIRECTING THE INPUT STREAM.
^THIS ROUTINE RUNS INTO ONE PROBLEM WITH <LEXINT.
^SINCE <>LEXINT MUST USE THE FIRST CHARACTER OF THE COMMAND
FILE, THE PRODUCTION THAT GOT US HERE HAS A '*' IN THE _<CHAR DISP_>
FIELD TO FORCE IT TO BE READ IN.
^IF IT DID NOT, PARSING WOULD CONTINUE WITH THE LAST CHARACTER READ VIA
THAT FILE BLOCK, WHICH WOULD CLEARLY BE WRONG.
^TO 'POP' BACK UP TO THE PREVIOUS LEVEL, WE MUST NOT ONLY CHANGE THE
INPUT STREAM, BUT WE MUST ALSO READ THE CURRENT CHARACTER.
^THINK ABOUT IT - IT REALLY DOES WORK! (^I THINK.)
.PARAGRAPH
^PAGE 22 HAS ALL THE ROUTINES REFERENCED IN THE FILE BLOCK (PLUS
AN ERROR ROUTINE CALLED FROM <A.ACAL).
^ANY ERROR IS REPORTED, THEN ALL THE OPEN COMMAND FILES ARE
CLOSED AND THE REST OF THE COMMAND IS ABORTED VIA <SWTBAD.
^WE EVEN DO OUR OWN <IO THROUGH THE <CMDCHR ROUTINE
BECAUSE WE MUST BE ABLE TO STOP PROCESSING BEFORE END OF FILE
IS REACHED.
^THIS IS DUE TO THE OTHER PROBLEM WITH <TULIP.
^HAD WE USED THE END OF FILE TRAP FACILITY
WE WOULD HAVE TRANSFERRED OUT OF <>LEXINT
WITHOUT ANY TRACKS FOR US TO FOLLOW
BACK TO REATTEMPT EXECUTION OF THE
<UUO.
^THEREFORE, <CMDCHR WILL STOP SCANNING WHEN IT FINDS A <CR
AND GO BACK TO THE PREVIOUS STREAM.
^WHAT IS REALLY NEEDED IS A MECHANISM TO ALLOW ACCESS TO THE
<PC OF THE <UUO SO ERROR ROUTINES CAN REATTEMPT <IO.
^MAYBE NEXT VERSION....
.PAPER SIZE 58,71
.PAGE
.HL 1 ^ODDS AND ENDS
.PARAGRAPH
^AT LONG LAST WE HAVE RUN OUT OF PROGRAMS TO DISCUSS AND ALL THAT
IS LEFT IS TO TIE UP SOME LOOSE ENDS, WHICH ARE ALL MACROS.
.LM 3;.B 1
.INDENT -3
<>PFILE LOSEG,INST,DATA - ^DEFINES A HIGH SEGMENT PSEUDO
FILE BLOCK WHICH DIFFERS FROM A NORMAL FILE BLOCK IN THAT IT
HAS NO DEVICE RELATED INFORMATION ASSOCIATED WITH IT.
^MEANT TO PROVIDE A MEANS OF DOING '<IO' TO CORE, PSEUDO FILES ARE
GREAT FOR SETTING UP PAGE HEADERS (LIKE FOR COMPILER LISTING FILES OR THE LINE
AT THE TOP OF THIS PAGE.
^OTHER USES INCLUDE A LINE BUFFER FOR LATER PROCESSING, AS <PIP AND
EDITORS DO; OR AS A MEANS TO SAVE THE TEXT OF A COMMAND
AND OUTPUT IT LATER TO SHOW THE LOCATION OF A SYNTAX ERROR AS <COMPIL
DOES NOT DO.
^I CONTEMPLATED PUTTING THAT INTO ^PROGRAM 4, BUT DECIDED IT WAS
PLENTY BIG ENOUGH ALREADY!
^MAYBE ^I WILL SOMETIME IN THE FUTURE.
^THE BIGGEST DIFFERENCE BETWEEN <>PFILE AND <>FILE IS THAT SINCE
NONE OF THE DEVICE DATA IS NECESSARY, <>PFILE IS ALMOST
A REASONABLE MACRO WITH A MERE THREE ARGUMENTS:
.LM 6
.BLANK 1
.INDENT -3
LOSEG - ^THE ADDRESS OF THE CORRESPONDING LOW SEGMENT PSEUDO
FILE BLOCK, WHICH IS <>PBSIZE WORDS LONG.
.BLANK 1
.INDENT -3
INST - ^THE INSTRUCTION WHICH WILL BE USED TO TRANSFER ALL THE DATA.
^U1 AND ^U2 HAVE DATA AS DESCRIBED IN THE REGISTER CONVENTIONS
SECTION A LONG TIME AGO.
^NORMALLY THIS WILL BE EITHER A <PUSHJ OR AN <ILDB#<U1,FILCHN(U2),
WHERE <FILCHN IS:
.BLANK 1
.INDENT -3
DATA - ^THIS ARGUMENT IS OPTIONAL, BUT IS NORMALLY EITHER A BYTE POINTER
OR THE ADDRESS OF A BUFFER.
^THIS WILL BE STORED IN LOCATION <>FILCHN OF THE LOSEG BLOCK
WHEN <>FSETUP IS EXECUTED.
^BASICALLY, IT ALLOWS THE STRING ROUTINES TO BE REENTRANT, OPERATING ON A NUMBER
OF THEM AT ONCE.
.LM 3
.B 1;.I -3;<>GLOBAL (SYM1,SYM2,...,SYMN)
. ;^THIS MACRO WILL TAKE THE LIST OF SYMBOLS SUPPLIED AND MAKE THEM
ALL GLOBAL (EITHER INTERNAL OR EXTERNAL).
^IT ACTS VERY MUCH LIKE THE <>GLOB MACRO IN <>C.MAC EXCEPT IT
PERFORMS SLIGHTLY DIFFERENTLY TO HANDLE A FEW SPECIAL CASES.
.B 1;.I -3;<>HWDGEN (NAME,MACRO,SUBMAC,PREFIX)
. ;^THIS MACRO IS USED TO GENERATE A HALFWORD DISPATCH TABLE BASED
UPON A DATA STRUCTURE PASSED TO IT AS MACROS.
.LM 6;.B 1
.I -3;NAME - ^OPTIONAL. ^IF SPECIFIED, DEFINE IT TO BE THE ADDRESS
OF THE TABLE.
.I -3;MACRO - ^NAME OF THE MACRO THAT HOLDS THE DATA STRUCTURE.
^IT CONSISTS OF A SERIES OF CALLS ON _<SUBMAC_>, BELOW.
.I -3;SUBMAC - ^THE NAME OF A MACRO HAVING ONE ARGUMENT, A
LABEL THAT IS TO BE PUT INTO THE DISPATCH TABLE.
^THIS MACRO IS DEFINED BY <>HWDGEN TO DO THE ACTUAL WORK.
.I -3;PREFIX - ^OPTIONAL. ^A PREFIX TO BE CONCATENATED WITH THE DATA PASSED
TO _<SUBMAC_>. ^THIS ALLOWS THE ENTIRE STRUCTURE TO BE USED TO GENERATE
SEVERAL DIFFERENT TYPES OF DATA.
.LM 0;.P
^NORMALLY THE SUBMACRO PARAMETERS INCLUDE A COMMAND NAME AND USUALLY
ASSCOCIATED FLAGS BESIDES THE TRANSFER ADDRESS.
<>HWDGEN WILL WORK ON THIS FORM TOO, IF A THIRD LEVEL MACRO IS
PASSED TO <>HWDGEN THAT IS CALLED BY THE REAL SUBMACRO THAT
EXTRACTS ONLY THE DATA.
^FOR EXAMPLE, IN ^PROGRAM 4 THE <SWITCH MACRO CONSISTS OF CALLS
TO A SUBMACRO THAT HAS THREE ARGUMENTS.
^I COULD HAVE (SHOULD HAVE!) USED <>HWDGEN TO GENERATE A TABLE BY
REPLACING THE LAST TWO LINES WITH:
.TS 3,11,25
.B 1;	^^DEFINE XX(A,B,C)_<FOO(C)_>
. ;	^^HWDGEN	(SWITDP,SWITCH,XX)\\
.B 1
^SEE <>TULLIB FOR SOME EVEN BETTER EXAMPLES!
^THE CODE TO DO THE SWITCH DISPATCH ON PAGE 20 WOULD REPLACE THE
.B 1 ;	^^SKIPA	T1,SWITDP(T3)\\
. ;WITH:
. ;	^^ROT	T3,-1	;DIVIDE BY 2, BUT KEEP THE REMAINDER
. ;	JUMPGE	T3,.+2	;IF EVEN, USE THE LEFT HAND SIDE
. ;	SKIPA	T1,SWITDP(T3)	;IF ODD GET THE RIGHT HAND SIDE
. ;	MOVS	T1,SWITDP(T3)	;GET THE LEFT SIDE IF IT WAS EVEN
. ;	TLZA	T1,-1	;CLEAR LEFT TO ISOLATE TRANSFER ADDRESS\\
.B 1;^IN MANY APPLICATIONS, THIS ROUTINE MAY BE WRITTEN TO USE
ONLY ONE REGISTER.
.PAGE
.HL 1 ^FUTURE PLANS AND POSSIBILITIES
.P
^SO, WHERE DOES <TULIP HEAD FROM HERE?
^SINCE IT WAS DEVELOPED ON A SMALL <PDP-10A THERE IS CURRENTLY
NO SUPPORT FOR EITHER <SFD'\S OR EXTENDED <LOOKUP/ENTER BLOCKS.
(^THE LATTER ARE SIMPLE TO PUT IN, BUT ^I'VE NEVER WORKED WITH
<SFD'\S BEFORE SO ^I HAVE NO IDEA HOW HARD THEY ARE TO ADD.)
^TIME AND TIME AGAIN ^I'VE WISHED FOR A MECHANISM TO ALLOW PROGRAMS
TO ADD <UUO'\S OF THEIR OWN,
.INDEX <DISIX
IF NOT FOR ALL THE UNASSIGNED ONES, THEN CERTAINLY FOR SOME <DISIX-<LIKE
<UUO\S THAT CALL USER ROUTINES.
^RETURNING THE <PC OF A <UUO THAT CAUSES AN <IO ERROR TRAP IS
A MUST (SEE THE COMMAND FILE SECTION) AND NEW SUBROUTINES THAT ACT
LIKE <SAVE1 - <SAVE4 BUT OPERATE ON <IO STEAMS ARE SO SIMPLE THEY
WILL BE ADDED.
<TULLIB SHOULD BE BROKEN INTO MORE MODULES (IF POSSIBLE) TO
ALLOW VERY SMALL PROGRAMS BY LEAVING OUT THE <IO ERROR SECTION.
<TULIP IS SO LARGE NOW THAT IT IS DIFFICULT TO WRITE A PROGRAM
IN LESS THAN <2K!
.INDEX ^HARVARD ^UNIVERSITY
^IN FACT, THE <DATE75 CODE PUSHED ^HARVARD'S <DIRECT CUSP TO 12
WORDS MORE THAN <1K.
^CODE NOT RELATED TO <TULIP COULD BE ADDED SUCH AS
ROUTINES LIKE <SIXSRC AND <PRTDIR (PERHAPS IN TWO PIECES,
<DTADRL AND <DTADRS).
^BASICALLY, ^I WOULD LIKE TO BUILD A LIBRARY OF USEFUL ASSEMBLER
ROUTINES.
^ONE INTERESTING SPINOFF THAT MIGHT OCCUR WOULD BE IN FORCING
BETTER STRUCTURED PROGRAMS.
^SOMETHING LIKE THE SECOND SAMPLE PROGRAM WOULD BE VERY SIMPLE
TO READ AND COMPREHEND IF IT CALLED EXTERNAL DIRECTORY ROUTINES,
WHEREAS A PROGRAM THAT NOT ONLY HAD ITS OWN DIRECTORY PRINTER
BUT ALL THE <IO ROUTINES COULD VERY WELL BE A MESS.
^NOT ONLY DOES <TULIP ALLOW BETTER STRUCTURED PROGRAMS BY ITS
.INDEX ^PHILOSOPHY
BEAUTIFUL DESIGN, BUT IT FORCES IT! [PHILOSOPHY]
.P
^ON THE LARGER SCALE OF THINGS, ^ED ^TAFT WROTE AND PARTIALLY
DEBUGGED A <SCAN AND <WILD PACKAGE PATTERNED AFTER AN EARLY
VERSION OF <DEC'\S.
^UNFORTUNATELY, IT WAS DESIGNED AROUND A VERY OLD PRECURSOR OF <TULIP,
SO WILL TAKE A FAIR AMOUNT OF TIME TO MAKE IT WORK (SIZE - A
LITTLE MORE THAN <1K).
^DON'T EXPECT IT SOON.
^ANOTHER PET IDEA IS TO WRITE A NEW MONITOR FOR THE <PDP-10 (THE
FIRST ONE ^I WORKED ON WAS ABOUT <10K, HOW BIG IS YOURS NOW?) AND
INCORPRATE <TULIP INTO THE <IO STRUCTURE.
^DON'T EVER EXPECT TO SEE THAT!
.P
^IN ANY CASE, ^I HAVE ENJOYED WRITING THIS PRIMER (WELL, WOULD
YOU BELIEVE ^I ENJOYED IT MORE THAN ^I HAD EXPECTED?) AND HOPE
YOU HAVE ENJOYED READING IT, BOTH FOR ITS INFORMATION CONTENT AND
INFORMAL STRUCTURE.
^THERE ARE A COUPLE NOTES ^I CAN'T (TERRIBLE, USING CONTRACTIONS IN PRINT!)
RESIST ADDING (^I THINK THIS SECTION HAS TOO MANY PARENTHETICAL
EXPRESSIONS).
^FIRST, THERE IS ONE ITEM IN THE INDEX THAT CARRIES VIRTUALLY
NO INFORMATION.
^WHAT IS IT?
^SECOND, ^I ACCIDENTALLY CODED A BEAUTIFUL 'PUN' INTO <SIXSRC/SIXMAT
INVOLVING COROUTINE DEFINITIONS.
^A FREE ^COKE TO THE FIRST PERSON WHO TELLS ME THE ANSWERS WHILE
IN SIGHT OF A ^COKE MACHINE!
.PAGE
.HL 1 ^REFERENCE MANUAL
.NUMBER LEVEL 1
.PARAGRAPH
^FINALLY THE PRIMER IS DONE AND ALL THAT REMAINS IS THE
REFERENCE MANUAL ^I PROMISED WAY BACK AT THE BEGINNING.
^THIS WILL NOT BE QUITE THE MANUAL THAT MOST PROGRAMMERS
WRITE AND CALL DOCUMENTATION AS THIS IS ONLY MEANT FOR USE AS A MEMORY
JOGGER AND A SOURCE OF ALL THE INFORMATION THAT IS NORMALLY AVAILABLE
ONLY FROM THE LISTINGS.
^BASICALLY, IT WILL BE A TRUE REFERENCE MANUAL!
^IN THE FOLLOWING TABLE OF CONTENTS, DATA TO BE DESCRIBED WILL
FOLLOW THE HEADING IN PARENTHESES AND THE FIRST ORDER
RELATED INFORMATION THAT IT REFERS TO WILL BE IN BRACKETS EITHER
WITHIN THE NAME LIST (FOR ISOLATED REFERENCES) OR WITHOUT (FOR
GLOBAL REFERENCES).
^FINALLY, ANGLE BRACKETS ARE USED TO ENCLOSE ITEMS THAT COULD HAVE
BEEN INCLUDED IN THE CURRENT SECTION, BUT HAVE BEEN DEFERRED TO A MORE
SUITABLE SECTION.
.LEFT MARGIN 6
.TAB STOPS 6
.BLANK 1
.INDENT -6
1	^REGISTER DEFINITIONS. (<^F [^MACROS: <FLAG; ^FLAG DEFINITIONS], ^T1-^T4, ^P1-^P4,
[^ROUTINES: <SAVE1-4], ^U1-^U3 [^FILE BLOCK MACROS], ^P [^MACROS: <START]) [^MACROS: <SAVE, <RESTORE]
.BLANK 1
.INDENT -6
2	^CHARACTER DEFINITIONS (<NULL, <BELL, <TAB, <LF, <VT, <FF,
<CR, <CTRLZ, <ESC, <ALT, <DBLQ, <SNGLQ, <LPAREN, <RPAREN, <COMMA,
<SEMI, <LANGLE, <RANGLE, <LSQUAR, <RSQUAR, <RUBOUT, <CRLF)
[<UUO\S: ^INPUT: <RFLG, <RCHF, <CCHF, <LCHF; ^FILE BLOCK MACROS: <FILE]
.BLANK 1
.INDENT -6
3	^FLAG DEFINITIONS (<LZEFLG [<UUO\S: ^OUTPUT WITH FIELD WIDTH])
[^MACROS: <FLAG]
.BLANK 1
.INDENT -6
4	^FILE BLOCK MACROS (<FILE, <PFILE) [<UUO\S: ^FILE BLOCK,
^FILE ERRORS; ^DATA STRUCTURES: ^FILE BLOCKS]
.BLANK 1
.INDENT -6
5	^DATA STRUCTURES (^LOSEG FILE AND PSEUDO-FILE BLOCKS
[^FILE BLOCK MACROS: <FILE, <PFILE; <UUO\S: ^FILE BLOCK, ^FILE ERRORS],
^EDIT LIST [<UUO\S: <DISIX, <DIASC, <EDISIX, <EDIASC])
.BLANK 1
.INDENT -6
6	^MACROS (<WID, <POS, <POINTR; <FLAG [^FLAG DEFINITIONS: <LZEFLG];
<VERSION, <VERSTR, <XX; <SAVE, <RESTORE; <START; <CONC; <HWDGEN;
<OPDEF<S: <MCALL, <CALL, <RETURN)
_<^LEXICAL ANALYSIS <TBLBEG, <PROD, <TBLEND_>
.BLANK 1
.INDENT -6
7	^ROUTINES (<SAVE1-4) _<^LEXICAL ANALYSIS: <LEXINT_>
.BLANK 1
.INDENT -6
8	<UUO\S [^MACRO <START]
.LEFT MARGIN 9
.TAB STOPS 9
.BLANK 1
.INDENT -6
8.1	^INPUT (<RCH, <CCH, <LCH, <RFLG, <RCHF, <CCHF, <LCHF) [^CHARACTER DEFINITIONS]
.BLANK 1
.INDENT -6
8.2	^OUTPUT WITHOUT FIELD WIDTH (<DISIX, <DIASC [^DATA STRUCTURES: ^EDIT LIST];
<WASC, <WCH, <WCHI, <W2CH, <W2CHI, <WNAME, <WPPN, <WNAMX, <WFNAME [<UUO\S: ^FILE BLOCK])
_<^OUTPUT WITH FIELD WIDTH: <WSIX_>
.BLANK 1
.INDENT -6
8.3	^OUTPUT WITH FIELD WIDTH (<WSIX, <WDEC, <WDECI, <WOCT,
<WOCTI)
.BLANK 1
.INDENT -6
8.4	^ERROR STREAM (<EDISIX, <EDIASC, <EWSIX, <EWASC) [^DATA
STRUCTURES: ^EDIT LIST]
.BLANK 1
.INDENT -6
8.5	^FILE BLOCK (<FSETUP [^FILE BLOCK MACROS], <FISEL, <FOSEL, <FIOPEN, <FOOPEN, <FIGET,
<FOGET, <FLOOK, <FENT, <FICLS, <FOCLS, <FICLOS, <FOCLOS, <FREL)
.BLANK 1
.INDENT -6
8.6	^FILE ERRORS (<ERRIOP, <WERIOP, <ERROOP, <WEROOP, <ERRLK, <WERLK, <ERRENT,
<WERENT, <ERRIN, <WERIN, <ERROUT, <WEROUT)
.LEFT MARGIN 6
.TAB STOPS 6
.BLANK 1
.INDENT -6
9	^LEXICAL ANALYSIS (^MACROS: <TBLBEG, <PROD, <TBLEND; ^ROUTINE: <LEXINT)
[^CHARACTER DEFINITIONS]
.BLANK 1
.INDENT -6
10	^SOURCE FILES, ASSEMBLY, AND USAGE INSTRUCTIONS. (<TULIP.MAC,
<TULLIB.MAC, <EXAMPL.MAC, <TULIP.RND)
.B 1;.I -6
11	^RESERVED SYMBOLS (MANY - SEE SECTION!)
.LEFT MARGIN 0
.HL 1 ^REGISTER DEFINITIONS
.NOFILL
.TS 3,12,21
.BLANK 1
.TP 7
.INDEX ^FLAG REGISTER
.INDEX ^TEMPORARY REGISTERS
.INDEX PERMANENT REGISTERS
.INDEX ^UNASSIGNED REGISTERS
.INDEX <TULIP REGISTERS
.INDEX ^STACK POINTER
	^NAME	^RANGE	^USE
	^F	0	^FLAGS
	^T1-^T4	1-4	^TEMPORARY
	^P1-^P4	5-10	^PERMANENT
		11-13	^UNASSIGNED
	^U1-^U3	14-16	^USED BY <UUO HANDLER (BUT PRESERVED)
	^P	17	^STACK POINTER
.FILL
.HL 1 ^CHARACTER DEFINITIONS
.BLANK 1
.NOFILL
	<NULL	^NULL (0)
	<BELL	^CONTROL-^G (7)
	<TAB	^TAB (11)
	<>LF	^LINEFEED (12)
	<>VT	^VERTICAL TAB (13)
	<>FF	^FORMFEED (14)
	<>CR	^CARRIAGE RETURN (15)
	<>CTRLZ	^CONTROL-^Z (32)
	<>ESC	^ESCAPE (33)
	<>ALT	^ALTMODE (33) [^LONG PAST TIME TO BURY 175 AND 176!]
	<>DBLQ	^DOUBLE QUOTE (")
	<>SNGLQ	^SINGLE QUOTE (')
	<>LPAREN	^LEFT PARENTHESIS '('
	<>RPAREN	^RIGHT PARENTHESIS ')'
	<>COMMA	^COMMA (,)
	<>SEMI	^SEMI-COLON (;)
	<>LANGLE	^LEFT ANGLE BRACKET (_<)
	<>RANGLE	^RIGHT ANGLE BRACKET (_>)
	<>LSQUAR	^LEFT SQUARE BRACKET ([)
	<>RSQUAR	^RIGHT SQUARE BRACKET (])
	<>RUBOUT	^YES (177)
.INDEX <CR
	<>CRLF	<CR, <>LF RIGHT JUSTIFIED (_<<CR_>^B28+LF).
.FILL
.BLANK 1
.TP 8
^CHARACTER CLASS DEFINITIONS RETURNED AS BIT FLAGS BY <>RFLG
AND RELATED <UUO\S:
.BLANK 1
.NOFILL
	<>LETTER	^A-^Z, UPPER AND LOWER CASE.
	<>DIGIT	0-9.
	<>BLANK	^SPACE AND TAB.
	<>BREAK	^LINEFEED, VERT. TAB, FORMFEED, ESCAPE, <CTRL-G, <CTRL-Z.
	<>LGLSIX	^CODES 40-137. (^VALID <SIXBIT CHARACTERS.)
.FILL
.HL 1 ^FLAG DEFINITIONS
	<>LZEFLG	^FORCE NUMERIC OUTPUT <UUO\S TO PRINT LEADING ZEROS.
.HL 1 ^FILE BLOCK MACROS
<>PFILE LOSEG BLOCK,INSTRUCTION,DATA
.BLANK 1
.LEFT MARGIN 6
.INDENT -3
^LOSEG BLOCK - ^THE ADDRESS OF THE CORRESPONDING LOW SEGMENT
<>PFILE BLOCK. (^SEE ^DATA STRUCTURES FOR FORMAT.)
.BLANK 1
.INDENT -3
^INSTRUCTION - ^THE INSTRUCTION ALL '<IO' FLOWS THROUGH.
.INDEX ^UNASSIGNED REGISTERS
^REGISTERS ^U1-^U3 HAVE THIS DATA:
.BLANK 1
.LEFT MARGIN 9
.INDENT -3
^U1 - ^THE CHARACTER (IF OUTPUT) OR WHERE THE CHARACTER IS TO BE
RETURNED (IF INPUT).
.BLANK 1
.INDENT -3
^U2 - ^FILE BLOCK ADDRESS.
.BLANK 1
.INDENT -3
^U3 - ^CURRENTLY AVAILABLE AS A TEMPORARY.
.BLANK 1
.INDENT -3
.INDEX ^TEMPORARY REGISTERS
^T1-^T4 -  ^CONTAIN USER'S DATA, AND MAY NOT BE CLOBBERED!
.LEFT MARGIN 6
.BLANK 1
.INDENT -3
^DATA - ^OPTIONAL, BUT IF SPECIFIED IS USUALLY THE ADDRESS
OF A BUFFER. ^STORED IN LOCATION <>FILCHN WITHIN THE LOW SEGMENT
<>PFILE BLOCK.
.BLANK 1
.I -6
<FILE CHAN,DIR,LOBLK,_<SPEC(ARG),...,SPEC(ARG)_>
.INDENT -3
CHAN - <IO CHANNEL NUMBER.
.BLANK 1
.INDENT -3
DIR - ^I FOR INPUT, ^O FOR OUTPUT.
.BLANK 1
.INDENT -3
LOBLK - ^ADDRESS OF CORRESPONDING LOW SEGMENT BLOCK.
.BLANK 1
.INDENT -3
_<SPEC(ARG),...,SPEC(ARG)_> - ^A LIST OF SPECIAL ARGUMENTS AND IS A LIST COMPOSED
FROM:
.TS 20,30;.B 1
.NOFILL
<>DEV (N)	[<DSK]	^DEVICE.
<>NAME (N)	[BLANK]	^FILE NAME.
<>EXT (N)	[BLANK]	^EXTENSION.
<>STATUS (N)	[0]	^STATUS (ALL 36 BITS ARE AVAILABLE).
.INDEX <O1BYTE
_<<>INST (_<I_>)_>	[<PUSHJ <P,>I1BYTE OR <O1BYTE]	<IO INSTRUCTION.
<>OTHER (N)	[NONE]	^ADDRESS OF MATCHING LOSEG FILE BLOCK.
.INDEX <ILERI1
.INDEX <ILERO1
<>OPEN (ADDR)	[<ILERI1, <ILERO1]	^ADDRESS FOR OPEN ERROR TRANSFER.
.INDEX <ILERI2
<>LOOKUP (ADDR)	[<ILERI2]	<LOOKUP ERROR.
.INDEX <ILERO2
<>ENTER (ADDR)	[<ILERO2]	<ENTER ERROR.
.INDEX <ILERI3
<>INPUT (ADDR)	[<ILERI3]	<INPUT ERROR.
.INDEX <ILERO3
<>OUTPUT (ADDR)	[<ILERO3]	<OUTPUT ERROR.
.INDEX <ILERI3
<>EOF (ADDR)	[<ILERI3]	^END OF FILE.
.FILL
.LEFT MARGIN 0
.BLANK 1
^WARNING: 1) ^EACH SPECIFIER MUST BE IMMEDIATELY PRECEDED WITH ITS
ANGLE BRACKET OR COMMA.
2) ^IF COMMAS ARE TO BE USED WITHIN ARGUMENTS THE SPEC(ARG)
MACROS, THEY MUST HAVE ANGLE BRACKETS AS USED FOR THE <>INST MACRO.
.HL 1 ^DATA STRUCTURES
.HL 2 ^LOSEG FILE BLOCK
.P
^BOTH FILE AND PSEUDO FILE BLOCKS USE THE SAME DATA STRUCTURE BELOW,
.INDEX <FILCHN
EXCEPT THE LATTER STOPS WITH <FILCHN, WHERE THE DATA WORD FROM
THE <>PFILE MACRO IS STORED.
^TWO SYMBOLS ARE USED TO RESERVE STORAGE FOR THEM:
.BLANK 1
<>FBSIZE - ^LENGTH OF FILE BLOCK
.
<>PBSIZE - ^LENGTH OF PSEUDO FILE BLOCK
.BLANK 1
.TAB STOPS 4,12
.NOFILL
^LOC	#NAME	CONTENTS
0	<>FILXCT	<IO INSTRUCTION
1	<>FILBAK	^CHARACTER (BYTE) BEFORE LAST (FOR <>LCH <UUO)
2	<>FILCUR	^CURRENT CHARACTER (FOR <>CCH <UUO)
3	<>FILCHN	^CHANNEL NUMBER IN <AC FIELD
4	<>FILSTS	^OPEN BLOCK - ^INITIAL FILE STATUS
5	<>FILDEV	##^DEVICE NAME
6	<>FILHDP	##^BUFFER HEADER ADDRESSES
7	<>FILNAM	<LOOKUP/<ENTER BLOCK - ^FILE NAME
10	<>FILEXT	##^EXTENSION (ET AL)
11	<>FILDAT	##^FILE DATA (CREATION DATA, PROTECTION, ETC.)
12	<>FILPP1	##<PPN BEFORE, FILE SIZE AFTER
13	<>FILPPN	^COPIED TO <>FILPP1 BEFORE EACH <LOOKUP/<ENTER <UUO
14	<>FILHDR	^BUFFER HEADER - ^ADDRESS OF CURRENT BUFFER
15	<>FILPTR	##^BYTE POINTER TO CURRENT BUFFER
16	<>FILCTR	##^COUNT OF BYTES LEFT IN CURRENT BUFFER
17	<>FILER1	<OPEN,,LOOKUP/ENTER ERROR ADDRESSES
20	<>FILER2	<EOF#,,<INPUT/OUTPUT ERROR ADDRESSES
.FILL
.HL 2 ^EDIT LIST
^THE EDIT LIST IS DATA FOR THE <UUO<S <DISIX, <EDISIX, <DIASC, AND <EDIASC.
^THE LEFT HALF OF FIRST WORD CONTAINS THE ADDRESS TO TRANSFER
TO AFTER THE <UUO COMPLETES AND THE RIGHT HALF IS THE ADDRESS OF THE EDIT
STRING.
^FOLLOWING THIS WORD ARE THE INSTRUCTIONS TO BE USED FOR VARIABLE
OUTPUT FROM THE <UUO.
^IF THE EDIT STRING IS <SIXBIT, THEN THE FOLLOWING CHARACTERS HAVE
SPECIAL EFFECTS:
.BLANK 1
.TAB STOPS 3 6
.NOFILL
.TP 6
.INDEX <CRLF
	_#	^PRINT A <CRLF.
.INDEX <TAB
	$	^PRINT A TAB.
.INDEX CASE CONVERSION
	_&	^SWITCH CASE MODE (INITIALLY UPPER CASE).
.INDEX INSTRUCTION LIST
	%	^EXECUTE THE NEXT INSTRUCTION IN THE INSTRUCTION LIST.
.INDEX CHARACTER QUOTING
	"	^OUTPUT THE NEXT CHARACTER AS IS.
.INDEX END OF STRING
	!	^END OF STRING.
.FILL
.BLANK 1
^IF THE EDIT STRING IS <ASCIZ, THEN THE ONLY SPECIAL CHARACTER
.INDEX <CTRL-A
WILL BE <CTRL-^A, WHICH ACTS AS % ABOVE.
.HL 1 ^MACROS
.LM 3;.I -3
.INDEX BYTE POINTERS
.INDEX <C.MAC
.INDEX <TULIP.MAC
^BYTE POINTER MACROS (^ACTUALLY IN <C.MAC, NOT <TULIP.MAC.)
.BLANK 1
.I -3;<>WID (MASK) - ^RETURN WIDTH OF SUPPLIED MASK IN BITS.
.I -3;<>POS (MASK) - ^RETURN BIT POSITION OF LAST BIT IN MASK.
.I -3;<>POINTR (ADDR,MASK) - ^MAKE BYTE POINTER TO THAT BYTE.
.BLANK 1
.I -3
^FLAG MACRO
.B 1
.I -3;<>FLAG (SYMBOL) - ^ASSIGNS A BIT VALUE TO SYMBOL, STARTING
AT BIT 34 AND WORKING TO THE LEFT.
^THERE MAY BE A LIST OF SYMBOLS AS AN ARGUMENT.
.B 1;.I -3
^VERSION MACROS
.B 1;.I -3
<>VERSION (VERSION,UPDATE,EDIT,WHO,SYMBOL)
^IF _<SYMBOL_> IS OMITTED, THIS SETS LOCATION <.JBVER TO BE
THE VERSION NUMBER. ^IF _<SYMBOL_> IS SUPPLIED, THIS DEFINES
IT TO BE THE VERSION NUMBER.
^SPECIAL SYMBOLS %<VVERS, <%VUPDA, %<VEDIT, AND %<VWHO ARE DEFINED AND
.INDENT -3
<>VERSTR
. ;IS DEFINED TO BE SIMPLY
.INDENT -3
<>XX (VERSION,UPDATE,EDIT,WHO)
. ;WHICH IS MEANT TO BE CALLED BY THE PROGRAMMER ONCE HE DEFINES <>XX
SO SOMETHING USEFUL IS DONE WITH IT.
.B 1;.I -3
^STACK MANIPULATERS
.B 1;.I -3
<>SAVE _<ARG1,ARG2,...,ARGN_> - ^SAVE THE SPECIFIED LOCATIONS
ON THE STACK.
.B 1;.I -3
<>RESTORE _<ARGN,...,ARG2,ARG1_> - ^RESTORE THE SPECIFIED
LOCATIONS FROM THE STACK. ^NOTE THAT THE ORDER OF THE LIST IS REVERSED!
.B 1;.TP 4;.I -3
^MISCELLANEOUS MACROS
.B 1;.I -3
<>START - ^INITIALIZE <UUO HANDLER BY CLEARING THE FLAG REGISTER (^F),
CLEARING ALL <IO STREAMS (<IFILE, <OFILE, AND <EFILE) AND RESETTING
JOB'S <IO STATUS (<>RESET <UUO).
^ALSO DOES AN <SALL <MACRO-10 PSEUDO OP TO SUPPRESS MACRO
EXPANSIONS (FOR ^C.<MAC AND <PROD).
^SHOULD BE USED BY EVERY PROGRAM AFTER THE STACK HAS BEEN SET UP.
.B 1;.I -3
<>CONC (A,B,C,D) - ^CONCATENATES UP TO FOUR PARAMETERS INTO A SINGLE
<MACRO-10 SOURCE LINE.
.B 1;.LM 6;.I -6
<>HWDGEN (NAME,MACRO,SUBMAC,PREFIX) - ^GENERATE HALF WORD DISPATCH.
.B 1;.I -3;NAME - ^BECOMES THE ADDRESS OF THE TABLE.
.I -3;MACRO - ^CONSISTS OF CALLS TO _<SUBMAC_>, ONE FOR EACH DISPATCH
GENERATED.
.I -3;SUBMAC - ^TAKES ONE ARGUMENT, THE LABEL TO TRANSFER TO FOR THIS
INDEX. ^THIS MACRO ALLOWS FURTHER PROCESSING TO BE DONE ON THE LABELS
AND IS DEFINED BY <>HWDGEN (AND ANY OTHER USERS OF THIS DATA
STRUCTURE).
.I -3;PREFIX - ^OPTIONAL. ^THIS WILL BE CONCATENATED WITH _<LABEL_> TO
ALLOW SEPARATION BETWEEN OTHER MACRO GENERATED NAMES.
.LM 0;.B 1
^THE GENERATED TABLE WILL BE IN 18 BIT BYTE FORMAT (ENTRIES START AT
LEFT, GO TO RIGHT AND DOWN).
.B 1;<OPDEF<S
.TS 8,16,24
.B 1;<>MCALL	<CALL		^SO THE <CALL <UUO IS STILL AVAILABLE.
. ;<>CALL	<PUSHJ	<P,
. ;<>RETURN	<POPJ	<P,
.LM 0
.HL 1 ROUTINES
.LM 3;.B 1;.I -3
.INDEX <SAVE1
.INDEX <SAVE2
.INDEX <SAVE3
.INDEX <SAVE4
.INDEX ^PERMANENT REGISTERS
<SAVE1-4 - ^SAVE UP TO ALL 4 PERMANENT REGISTERS (<P1-P4), AND THEN
CALL THE CALLER TO BE ABLE TO HANDLE THE RESTORE ITSELF, MEANING
THE CALLER DOES NOT HAVE TO WORRY ABOUT RESTORING THE REGISTERS
HIMSELF.
.LM 0
.HL 1 UUOS
.HL 2 ^INPUT
.TS 9,18;.LM 17
.I -17;<>RCH	LOC	^READS NEXT CHARACTER INTO _<LOC_>.
.I -17;<>CCH	LOC	^READS CURRENT CHARACTER INTO _<LOC_>.
.I -17;<>LCH	LOC	^READS LAST CHARACTER INTO _<LOC_>. ^NEXT <>RCH WILL REREAD THE
CURRENT CHARACTER. ^NOTE: <>LCH CANNOT BE USED TO BACK UP MORE
THAN ONE CHARACTER. ^ATTEMPTS TO DO SO WILL BE IGNORED.
.I -17;<>RFLG	LOC	^READS FLAGS FOR CHARACTER IN LOC INTO _<LOC_>+1.
.I -17;<RCHF, <CCHF, <>LCHF	^ACT AS <RCH, <CCH, AND <>LCH
.INDEX <RCHF
.INDEX <CCHF
IMMEDIATELY FOLLOWED BY A <RFLG.
.I -17;.HL 2 ^OUTPUT WITHOUT FIELD WIDTH
.I -17;<>DISIX	ELIST	^OUTPUT USING <SIXBIT EDIT LIST STARTING AT _<ELIST_>.
.I -17;<>DIASC	ELIST	^OUTPUT USING <ASCIZ EDIT LIST STARTING AT _<ELIST_>.
.I -17;<>WASC	ADDR	^OUTPUT <ASCIZ STRING STARTING AT _<ADDR_>.
.I -17;<>WCH	ADDR	^OUTPUT CHARACTER FROM _<ADDR_>.
.I -17;<>WCHI	CHAR	^OUTPUT CHARACTER IN ADDRESS FIELD.
.I -17;<>W2CH	ADDR	^OUTPUT TWO CHARACTERS RIGHT JUSTIFIED IN _<ADDR_>.
.I -17;<>W2CHI	CHARS	^OUTPUT TWO CHARACTERS RIGHT JUSTIFIED IN ADDRESS FIELD.
.I -17;<>WNAME	ADDR	^OUTPUT <SIXBIT WORD IN _<ADDR_>, NO TRAILING SPACES.
.I -17;<>WPPN	ADDR	^OUTPUT <PPN IN _<ADDR_>. (^WITHOUT BRACKETS.)
.I -17;<>WNAMX	ADDR	^OUTPUT '<NAME.EXT' IN _<ADDR_> AND _<ADDR_>+1.
.I -17;<>WFNAME	FILE	^OUTPUT '<DEV:NAME.EXT[PPN]' IN FILE BLOCK
STARTING AT _<FILE_>.
^IF THE EXTENSION IS '<UFD', THEN THE NAME WIL BE PRINTED AS A <PPN.
.I -17;.HL 2 ^OUTPUT WITH FIELD WIDTH.
.I -17;<>WSIX	W,ADDR	^WRITE FROM <SIXBIT TEST AT _<ADDR_>. ^IF _<W_> IS BLANK
THEN OUTPUT WILL BE CONTROLLED BY THE EDIT CHARACTERS (DO NOT USE
'%'!), OTHERWISE ONLY _<W_> CHARACTERS WILL BE WRITTEN.
.I -17;<>WDEC	W,ADDR	^WRITE A DECIMAL NUMBER AT LEAST _<W_> CHARACTERS LONG.
^IF <>LZEFLG IS SET IN ^F, THEN IT WILL BE PRECEDED WITH LEADING
ZEROS.
.I -17;<>WDECI	W,NUM	^LIKE <WDEC, BUT IMMEDIATE MODE.
.I -17;<>WOCT	W,ADDR	^LIKE <WDEC, BUT OCTAL OUTPUT.
.I -17;<>WOCTI	W,NUM	^LIKE <WOCT, BUT IMMEDIATE MODE.
.I -17;.HL 2 ^ERROR STREAM
.I -17;<>EDISIX	ELIST	^WRITE <SIXBIT EDIT LIST THROUGH ERROR STREAM (<EFILE).
.I -17;<>EDIASC	ELIST	^WRITE <ASCIZ EDIT LIST THROUGH ERROR STREAM.
.I -17;<>EWSIX	ADDR	^DO <>WSIX TO THE ERROR STREAM.
.I -17;<>EWASC	ADDR	^DO <>WASC TO THE ERROR STREAM.
.LM 0;.HL 2 ^FILE BLOCK
^ALL <UUO<S TAKE THE ADDRESS OF A LOSEG FILE BLOCK
(EXCEPT <FSETUP, WHICH USES A <HISEG FILE BLOCK).
'^SELECT INPUT' MEANS SIMPLY THAT THE FILE BLOCK ADDRESS IS STORED
IN LOCATION <>IFILE (A LOCATION IN THE <UUO HANDLER) AND
.INDEX <OFILE
'SELECT OUTPUT' MEANS STORING INTO <OFILE.
.INDEX <EFILE
^A THIRD LOCATION, <EFILE, IS THE FILE <IO STREAM LOCATION FOR
THE ERROR OUTPUT BUT MAY BE USED BY THE PROGRAM FOR ANY OTHER USE.
.B 1;<>FSETUP	^INITIALIZE LOSEG FILE BLOCK FROM HISEG BLOCK AT FILE.
. ;<>FISEL	^SELECT INPUT STREAM TO BE THROUGH FILE.
. ;<>FOSEL	^SELECT OUTPUT STREAM TO BE THROUGH FILE.
. ;<>FIOPEN	^SELECT INPUT, <OPEN, AND <>LOOKUP FILE.
. ;<>FOOPEN	^SELECT OUTPUT, <OPEN, AND <>ENTER FILE.
. ;<>FIGET	^SELECT INPUT AND <>OPEN FILE.
. ;<>FOGET	^SELECT OUTPUT AND <>OPEN FILE.
. ;<>FLOOK	^SELECT INPUT AND <>LOOKUP FILE.
. ;<>FENT	^SELECT OUTPUT AND <>ENTER FILE.
. ;<>FICLS	^SELECT INPUT AND <>CLOSE FILE.
. ;<>FOCLS	^SELECT OUTPUT AND <>CLOSE FILE.
. ;<>FICLOS	^SELECT INPUT, <CLOSE, AND <>RELEASE FILE.
. ;<>FOCLOS	^SELECT OUTPUT, <CLOSE, AND <>RELEASE FILE.
. ;<>FREL	<>RELEASE FILE (DON'T SELECT).
.HL 2 ^FILE ERRORS.
^ALL <UUO\S IN THIS SECTION WILL TAKE THE ADDRESS OF A LOSEG FILE BLOCK
TO REFERENCE, AND THEREFORE WILL NOT BE INCLUDED IN THE LIST.
.INDEX <ERR PREFIX
.INDEX <WER PREFIX
^EACH <UUO MAY BE PREFIXED WITH EITHER A '<WER'
OR A '<ERR'. ^THE FORMER WILL OUTPUT TO THE OUTPUT DEVICE
WHEREAS THE LATTER WILL OUTPUT TO THE ERROR DEVICE.
^FURTHERMORE, <UUO\S STARTING WITH '<WER' WILL NOT PRINT
THE DEVICE DESCRIPTOR BEFORE PRINTING THE ERROR MESSAGE.
.LM 9;.B 1
.INDEX <ERRIOP
.INDEX <WERIOP
.I -9;<???IOP	^WRITE <>OPEN ERROR MESSAGE.
.INDEX <ERROOP
.INDEX <WEROOP
.I -9;<???OOP	^LIKE <???IOP.
.INDEX <ERRLK
.INDEX <WERLK
.I -9;<???LK	^WRITE <LOOKUP/GETSEG ERROR MESSAGE.
.INDEX <ERRENT
.INDEX <WERENT
.I -9;<???ENT	^WRITE <>ENTER ERROR MESSAGE.
.INDEX <ERRIN
.INDEX <WERIN
.I -9;<???IN	^WRITE <>INPUT ERROR MESSAGE.
.INDEX <ERROUT
.INDEX <WEROUT
.I -9;<???OUT	^WRITE <>OUTPUT ERROR MESSAGE.
.LM 0
.HL 1 LEXICAL ANALYSIS
.INDEX ^LEXICAL ANALYSIS
^TO PERFORM LEXICAL ANALYSIS, A ROUTINE (<LEXINT) MUST BE CALLED 
WITH THE ADDRESS OF A PRODUCTION TABLE IN THE RIGHT SIDE OF <T1 AND THE
RELATIVE FIRST PRODUCTION NUMBER IN THE LEFT.
^TO MAKE A PRODUCTION TABLE, THREE MACROS ARE USED:
.LM 3;.B 1;.I -3
<>TBLBEG (SYMBOL) - ^DEFINES SYMBOL TO BE THE ADDRESS OF THE
PRODUCTION TABLE AND INITIALIZES DATA FOR THE OTHER MACROS.
.B 1;.I -3
.INDEX <PROD
<PROD( CHAR SPEC, ACTION ROUTINE, CHAR DISP, NEXT PROD) - ^THIS GENERATES
A PRODUCTION WORD.
.LM 9;.B 1;.I -3
CHAR SPEC - ^MATCH CONDITION (CHARACTER OR ANGLE BRACKETED FLAGS).
.B 1;.I -3;ACTION ROUTINE - ^LAST FOUR CHARACTERS (FIRST TWO ARE '^A.') TO
BE CALLED TO PARSE DATA IF THE CHARACTER MATCHES.
.B 1;.I -3;CHAR DISP - ^WHAT TO DO WITH CHARACTER BEFORE NEXT PRODUCTION IS
PROCESSED (*: READ A NEW ONE, __: READ LAST, BLANK: USE SAME).
.I -3;NEXT PROD - ^RELATIVE ADDRESS OF NEXT PRODUCTION TO PROCESS.
.LM 3
.B 1;.I -3
<>TBLEND - ^THIS MARKS THE END OF A PRODUCTION TABLE, GENERATING
A HALF WORD TABLE FOR USE BY <>LEXINT TO DISPATCH TO ACTION ROUTINES.
.LM 0
.HL 1 SOURCE FILES
.LM 12;.B 1;.TS 13
.I -12;<>C.MAC	^PROVIDED BY <DEC, THIS IS A UNIVERSAL FILE (WHEN PROPERLY
ASSEMBLED) THAT SUPPLIES MANY SYMBOL DEFINITIONS.
.I -12;<>TULIP.MAC	^A UNIVERSAL FILE PROVIDING ALL <TULIP DEFINITIONS.
.I -12;<>TULLIB.MAC	^LIBRARY THAT MUST BE SEARCHED TO LOAD THE <TULIP
ROUTINES NEEDED.
.I -12;<>TULIP.RND	^A <>RUNOFF FILE (VERSION 10) THAT GENERATES THIS
DOCUMENT.
.I -12;<>EXAMPL.MAC	^A LIBRARY OF SAMPLE PROGRAMS DISCUSSED BY THE
PRIMER.
.LM 0
.HL 1 RESERVED SYMBOLS
.B 1;^THE FOLLOWING SYMBOLS MAY BE USEFUL:
.TS 9,17
. ;^NAME	VALUE	FUNCTION
. ;<>FTDBUG	0	-1 IF A DEBUG VERSION OF <TULIP.MAC.
.INDEX <CREF
. ;<>FTCREF	0	-1 IF PRGRAMMER WANTS FULL <CREF.
.INDEX ^CARNEGIE -^MELLON ^UNIVERSITY
.INDEX ^HARVARD ^UNIVERSITY
. ;<>FTCMU	0	-1 AT <CMU FOR <CMUPPN\S.
. ;<>FTIMP	0	-1 AT ^HARVARD AND <CMU FOR <ARPA<NET FEATURES.
. ;<>$FLAGN	-	^BIT LOCATION OF LAST DEFINED FLAG.
. ;<>$NCHFL	-	^NON ZERO IF CHARACTER CLASSES ARE DEFINED.
. ;<>$UUON	-	^VALUE OF THE LAST <UUO DEFINED.
.B 1;		<HISEG FILE BLOCK FORMAT:
. ;<>FHDBTS	0	#^MARK BITS INDICATING WHICH WORDS ARE NON-ZERO.
. ;<>FHDLOC	1	#<AOBJN WORD TO USE IN DATA COPY LOOP.
. ;<>FHDOFS	2	#^OFFSET OF FIRST REAL DATA WORD IN <HISEG <FILE BLOCK.
.B 1;^THE FOLLOWING SYMBOLS ARE DEFINED IN <TULIP, BUT MAY BE USED
WITHOUT CAUSING TROUBLE:
. ;###^^$NBYPW, SCNBIT, RSCBIT, CLSBIT, NEGBIT, BAKFLG\\.
.INDEX VERSION NUMBERS
.INDEX <%TULIP
.INDEX <%UUO
.INDEX <%LEXINT
.INDEX <%%%TLP
.B 1;^VERSION NUMBERS: ^^%LEXINT, %TULIP, %UUO, %%%TLP\\.
.B 1;^THE FOLLOWING ARE USED OR DEFINED BY <HWDGEN:
. ;^MACROS	<>$HDW
. ;^SYMBOLS	<>ZZ
.B 1;^THE FOLLOWING ARE USED OR DEFINED BY THE LEXICAL ANALYSIS MACROS:
. ;^MACROS	^^$NWACT, %TBLFN, $ACT\\
. ;^SYMBOLS	^^$ACTN, $ANG, $TESTF, $NEXT, N$POPJ, N$????, ZZ\\
. ;	##(???? ARE THE NAMES OF ACTION ROUTINES USED)
.B 1;^MISCELLANEOUS MACROS:
. ;<UUOS	^CONTAINS ENTIRE <UUO STRUCTURE.
. ;<CLASSES	^USED BY <>TULLIB.MAC TO CREATE THE CHARACTER CLASS TABLE.
. ;<REDEF, <>TSTANG - ^USED BY LEXICAL ANALYSIS MACROS.
^MUST NOT BE REDEFINED.
.SUBTITLE ^INDEX
.PAGE
.INDEX INDEX
.PX