
* THIS PROGRAM ACCEPTS AN ASCII SOURCE FILE
* ASSUMED TO BE IN THE FORM OF A SOMEWHAT
* STANDARD DEC FUNCTIONAL SPECIFICATION AND
* CONVERTS IT INTO A FILE WHICH CAN BE PROCESSED
* BY BOB CLEMENT'S RUNOFF PROGRAM.  IT ASSUMES THAT
* EVERY PARAGRAPH IS NUMBERED.  IT WILL PRECEED
* THE BEGINNING OF EVERY SENTENCE WITH '^', IT
* WILL CAPITALIZE EACH WORD OF A PARAGRAPH
* HEADER LINE, IT WILL CAPITALIZE KEYWORDS.
* IT WILL ALSO MAKE
* AN ATTEMPT TO PRESERVE THE ESSENTIAL CHARACTER
* OF FIGURES AND DIAGRAMS.
*
* L. P. WADE  12-15-70

	&TRACE = 100000
	BELLS = ASCII(7) ASCII(7)
	CR = ASCII(15) ASCII(12)
	TAB = '	'
	BLANK = ' '
	DIGITS = '0123456789'
	DEFAULTMARGIN = 8

	&TRIM = 1
	&ERRLIMIT = 1
	&ANCHOR = 1
	TRACE('STCOUNT','KEYWORD',,'LIMIT')
	DEFINE('LIMIT(NAME,TAG)')	:(LIMEND)
LIMIT	LASTNO = &LASTNO
	OUTPUT = 'WORDS REMAINING = '  COLLECT(1)
	OUTPUT = 'LASTNO = ' LASTNO	:(RETURN)
LIMEND

	TRACE('ERRTYPE','KEYWORD',,'KILL')

	DEFINE('KILL(NAME,TAG)')	:(KEND)
KILL	LASTNO = &LASTNO	NE(&ERRTYPE,28)	:S(DOKILL)
* SPECIAL CASE FOR STLIMIT EXCEEDED

	TYPE = 'THIS PROGRAM IS SURE TAKING A LONG TIME'
+	BELLS CR
DOKILL	TYPE = 'ERROR ' &ERRTYPE ' OCCURRED' ' AT LINE ' LASTNO CR
	TYPE = 'SAVE ALL FILES ON DECTAPE' CR
	&DUMP = 1
	TYPE = 'CLOSING OUTPUT AND QUITTING'  CR	:(EOF)
KEND

	DEFINE('WATCH(NAME,TAG)')	:(WEND)
WATCH	OUTPUT = TAG ' ' $NAME	:(RETURN)
WEND


	ALWAYS = 'UFD' ! 'RC11' ! 'RK11' !
+ 'TTY' ! 'DEC' ! 'PC11' ! 'LP11' ! 'ROM' !
+ 'PDP' ! 'ASR' ! 'DOS' ! 'ASCII' ! 'CR' ! 'LF'

INIT	LMARG = 0
	NOFILE = 'FILE NOT THERE'  CR

	OUTPUT('TYPE',99,'(1X,16A5)')
	INPUT('ACCEPT',2,80)

	OUTPUT('OUT',21,'(1X,27A5)')
	INPUT('IN',20,80)	:(GETIN)
BADIN	TYPE = NOFILE
GETIN	TYPE = 'INPUT FILENAME: '
	INNAM = ACCEPT
	IFILE(20,INNAM)		:F(BADIN)

	TYPE = 'OUTPUT FILENAME: '
	OUTNAM = ACCEPT
	OFILE(21,OUTNAM)	:(GETKEY)
BADKEY	TYPE = NOFILE

GETKEY	TYPE = 'KEYWORD FILENAME: '
	KEYNAM = ACCEPT
	IDENT(KEYNAM)		:S(GETI)
	IFILE(22,KEYNAM)	:F(BADKEY)
GETI
	INPUT('KEY',22,80)

* BUILD UP THE KEYWORD PATTERN

	IDENT(KEYNAM)		:S(KEYEND)
	KEYPAT = 'LARRY'
KEYLOOP	T = KEY			:F(GETKEY)
	IDENT(T)		:S(KEYLOOP)
	KEYPAT = T ' ! ' KEYPAT	:(KEYLOOP)
KEYEND


	&TRACE = 10000
				:(GETCAP)

BADCAP	TYPE = NOFILE
GETCAP	TYPE = 'CAPITALS FILENAME: '
	CAPNAM = ACCEPT
	IDENT(CAPNAM)		:S(ENDCAP)
	IFILE(23,CAPNAM)	:F(BADCAP)
	INPUT('CAP',23,80)

* BUILD UP THE CAPITALS PATTERN

CAPLOOP	T = CAP			:F(GETCAP)
	IDENT(T)		:S(CAPLOOP)
	ALWAYS = T ' ! ' ALWAYS	:(CAPLOOP)
ENDCAP

	OUT = '.; RUN MADE ON FILE ' INNAM ' ON ' DATE()
+	' AT ' MSTIME() / 1000 / 1000
	OUT = '.SPACING 1'
	OUT = '.TAB STOPS 8'
GETTIT	TYPE = 'TITLE: '
	OUT = '.TITLE ' ACCEPT
ENDTIT

-EJECT

* DEFINE A PARAGRAPH NUMBER AS A STRING OF
* DIGITS WITH PERIODS INSIDE, I.E. 3.1 OR 3.5.1.6.2

	PNUM = SPAN(DIGITS '.')

* DEFINE FILL AS A SPAN OF BLANKS OR TABS.

	SPACE = BLANK TAB
	FILL = SPAN(SPACE)

	DEFINE('CAPSENTENCE(S)N')

* THIS FUNCTION WILL ACCEPT A STRING AS INPUT AND
* RETURN THE SAME STRING WITH THE FIRST LETTER OF
* EVERY SENTENCE CAPITALIZED.

	SENTENCEPAT = TAB(*N) . A BREAK('.') . B  '.' . P
+ @N (FILL ! RPOS(0) ! FAIL) . C  REM . D
				:(SENTEND)

CAPSENTENCE	N = 0

CAPSEN	T SENTENCEPAT	:F(RETURN)
	IDENT(C D)	:S(CAPQUIT)
	T = A B P C '^' D	:(CAPSEN)
* THIS LINE ENDED WITH A PERIOD SO CAPITALIZE THE FIRST WORD
* OF THE NEXT LINE IF IT IS NON-EMPTY

CAPQUIT	CAPFLAG = 1	:(RETURN)
SENTEND

	DEFINE('CAPALL(S)N')

* THIS FUNCTION WILL ACCEPT A STRING AS INPUT AND
* RETURN THE SAME STRING WITH THE FIRST LETTER OF ALL WORDS CAPITALIZED.
*
* 'WORDS' ARE DEFINED AS ANY SYMBOL STRING FOLLOWING A
* SPAN OF BLANKS OR TABS.
* 
* 	CAPPAT = TAB(*N) . A  ARB . B
* + NOTANY(SPACE) . LETTER @N REM . C
* 				:(CAPEND)
* 
* CAPALL	N = 0
* 
* CAPALL1	T  CAPPAT = A B '^' LETTER C  :S(CAPALL1)F(RETURN)
* CAPEND

* MAKE SURE ALL RESERVED WORDS ARE ALL CAPITALIZED

	DEFINE('CAPS(S)N')

	DELIM = SPACE "((-=,.:*?/><;+!'#$%&"   '"'
	RESPAT = (TAB(*N + 2)) ARB ANY(DELIM) . A ALWAYS . B
+	@N ANY(DELIM) . C REM . D	:(RESEND)

CAPS	N = -2
CAPS1	T RESPAT = A '^^' B '\\' C D :S(CAPS1)F(RETURN)
RESEND

	DEFINE('CAPFIRST(S)N')

* THIS FUNCTION WILL ACCEPT A STRING AS INPUT AND
* RETURN THE SAME STRING WITH THE FIRST LETTER OF
* THE FIRST WORD CAPITALIZED.  IT TAKES INTO ACCOUNT
* THE POSSIBILITY THAT THE LINE MAY HAVE A LEADING
* PARAGRAPH NUMBER.

	FIRSTPAT = (PNUM ! NULL) . A FILL . B  REM . C  :(FIRSTEND)

CAPFIRST	T FIRSTPAT = A B '^'  C  :(RETURN)
FIRSTEND

	DEFINE('KEYWORD(S)')

	KPAT = (TAB(*N) FILL) . A KEYPAT . B (FILL ! NULL) . C
+		@N  REM . D	:(DEFKEY)

KEYWORD	N = 0
KEYW1	T  KPAT = A '^' B C D :S(KEYW1)F(RETURN)
DEFKEY

	DEFINE('SPECIAL()')
	SPC = '&^\_#'
	SPCPAT = TAB(*(N + 1)) . A  BREAK(SPC) . B LEN(1) . C
+	@N REM . D
		:(SPCEND)
SPECIAL	N = -1
SPC1	T SPCPAT = A B '_' C D  :S(SPC1)F(RETURN)
SPCEND

-EJECT

******************************************************************
*
* BEHOLD THE MAIN LOOP!
*
******************************************************************

* READ A LINE FROM THE INPUT STREAM, AND CHECK FOR END OF FILE

NEWLINE	T = IN			:F(EOF)

* PRESERVE ANY RUNOFF CONTROL CHARACTERS

NEW1	SPECIAL()

* CHECK IF THIS LINE IS THE BEGINNING OF A NEW
* PARAGRAPH, THAT IS DOES IT BEGIN WITH A
* PARAGRAPH NUMBER?

	T TAB(0) PNUM		:S(NEWPAR)

* CHECK TO SEE IF THIS IS A NULL LINE.

	IDENT(T)		:S(EMPTY)



* CHECK FOR THE SPECIAL CASE OF BEING IN THE
* MIDST OF A FIGURE.  I WILL ATTEMPT TO IDENTIFY
* THIS BY SEEING IF THE FILL EXTENDS BEYOND
* THE LEFT MARGIN.

	T SPAN(BLANK) @N	:F(CHKTAB)
	GT(N,LMARG)		:S(STARTFIG)
CHKTAB	T SPAN(TAB) @N :F(NOFIGURE)
	N = N * 8
	GT(N,LMARG)	:S(STARTFIG)

NOFIGURE

* CHECK TO SEE IF THIS IS THE FIRST LINE SEEN SINCE THE HEADER

	EQ(HDFLAG,1)	:S(FIRSTLINE)

	EQ(CAPFLAG,0)		:S(REJOIN)
	CAPFIRST(T)
	CAPFLAG = 0

* NOW CAPITALIZE THE FIRST WORD OF EVERY SENTENCE

REJOIN	CAPSENTENCE(T)

* NOW MAKE ALL SPECIAL WORDS ALL CAPITALS

REJOIN1	KEYWORD(T)
	CAPS(T)

* DELETE LEADING BLANKS AND TAB

	T FILL REM . B  = B

OUTIT	OUT = T			:(NEWLINE)

-EJECT

* THIS CODE HANDLES THE CASE OF A NEW PARAGRAPH.
* THE LINE IS ASSUMED TO BEGIN WITH A PARAGRAPH
* NUMBER.

* CAPITALIZE THE FIRST LETTER OF THE FIRST WORD

NEWPAR	CAPFIRST(T)
	LMARG = 0
	OUT = '.LEFT MARGIN ' LMARG

* OUTPUT SOME COMMANDS TO RUNOFF
	EQ(FILLMODE,1)		:F(NEWPAR1)
	OUT = '.FILL';	OUT = '.JUSTIFY'
	FILLMODE = 1
NEWPAR1

* I ASSUME THE NUMBER OF SPACES BETWEEN THE PARAGRAPH
* NUMBER AND THE FIRST WORD ARE SIGNIFICANT SO I
* PRESERVE THEM WITH THE '#' FEATURE OF RUNOFF

* 	T (PNUM . A SPAN(BLANK) . N REM . C) =
* +	A DUPL('#',SIZE(N)) C
* 	T (PNUM . A SPAN(TAB) . N REM . C) =
* +	A DUPL('#',(8 * SIZE(N)))  C


* RECORD THE FACT THAT THE HEADER FOR THIS PARAGRAPH
* HAS BEEN SEEN

	HDFLAG = 1		:(REJOIN1)

* THIS CODE HANDLES THE CASE OF THE FIRST LINE
* AFTER THE BEGINNING OF A PARAGRAPH WHICH HAS TEXT.
* IT SETS THE MARGIN TO A DEFAULT VALUE IF
* THERE IS NO FILL, TO THE LENGTH OF SPAN OF BLANKS,
* OR ELSE SETS THE TAB STOPS IF THE SENTENCE BEGINS
* WITH THEM

FIRSTLINE	N = 0
	T SPAN(TAB) . N		:S(TABIT)
	T SPAN(BLANK) . N	:F(DEFAULTIT)
* SO MAKE THE MARGIN CORRESPOND TO THE NO. OF BLANKS.

	LMARG = SIZE(N)		:(FIRSTCONT)

* THE LINE HAS TABS

TABIT	LMARG = SIZE(N) * 8	:(FIRSTCONT)

* MAKE IT THE DEFAULT

DEFAULTIT	LMARG = DEFAULTMARGIN
FIRSTCONT	HDFLAG = 0
	OUT = '.LEFT MARGIN ' LMARG
	CAPFIRST(T)
	CAPSENTENCE(T)	:(REJOIN1)

-EJECT
* THIS CODE ATTEMPTS TO PRESERVE THE ESSENCE OF
* FIGURES

STARTFIG	FIGFLAG = 1
	CAPFLAG = 0

* NOW REPLACE ALL BLANKS WITH THE PROPER CHARACTER(#)

* REPLACE HAS A BUG IN SNOBOL VER 3.4.2  PUT THIS
* STATEMENT BACK IN WHEN IT IS FIXED
*	REPLACE(T,BLANK,'#')
FIG1	T BLANK	 = '#' :S(FIG1)

* REPLACE ALL TABS WITH 8 #S
* 	TABPAT = BREAK(TAB) . A TAB REM . B
* 	N = 0
* TAB1	T TABPAT = A   '########' B :S(TAB1)

* NOW GUARD AGAINST FILLING AND JUSTIFYING

	EQ(FILMODE,1)		:F(TAB2)
	OUT = '.NOFILL'
	OUT = '.NOJUSTIFY'
	FILLMODE = 0

* MAKE THE FIGURE ALL UPPER CASE

TAB2	OUT = '^^'
	OUT = T
	OUT = '\\'		:(NEWLINE)


* THIS CODE HANDLES THE CASE OF A NULL LINE.

EMPTY	CAPFLAG = 0
	SKPCNT = SKPCNT + 1
	T = IN			:F(EOF)
	IDENT(T)		:S(EMPTY)
	OUT = '.SKIP ' SKPCNT
	HDFLAG = 1
	SKPCNT = 0		:(NEW1)

* CLEANUP THE OUTPUT FILE AND SAY GOODBY

EOF	OUT = '.PAGE'

	ENDFILE(21)
	TYPE = 'SUCCESS' CR
	COLLECT(1)
END
