modernc.org/knuth@v0.0.4/tangle/tangle.go (about)

     1  // Code generated by '[/tmp/go-build2075925341/b001/exe/generate]', DO NOT EDIT.
     2  
     3  // % This program by D. E. Knuth is not copyrighted and can be used freely.
     4  // % Version 0 was released in December, 1981.
     5  // % Version 1 was released in September, 1982, with version 0 of TeX.
     6  // % Slight changes were made in October, 1982, for version 0.6 of TeX.
     7  // % Version 1.2 introduced [:nnn] comments, added @= and @\ (December, 1982).
     8  // % Version 1.4 added "history" (February, 1983).
     9  // % Version 1.5 conformed to TeX version 0.96 and fixed @\ (March, 1983).
    10  // % Version 1.7 introduced the new change file format (June, 1983).
    11  // % Version 2.0 was released in July, 1983, with version 0.999 of TeX.
    12  // % Version 2.5 was released in November, 1983, with version 1.0 of TeX.
    13  // % Version 2.6 fixed a bug: force-line-break after a constant (August, 1984).
    14  // % Version 2.7 fixed the definition of check_sum_prime (May, 1985).
    15  // % Version 2.8 fixed a bug in change_buffer movement (August, 1985).
    16  // % Version 2.9 allows nonnumeric macros before their def (December, 1988).
    17  // % Version 3, for Sewell's book, fixed long-line bug in input_ln (March, 1989).
    18  // % Version 4 was major change to allow 8-bit input (September, 1989).
    19  // % Version 4.1 conforms to ANSI standard for-loop rules (September, 1990).
    20  // % Version 4.2 fixes stat report if phase one dies (March, 1991).
    21  // % Version 4.3 fixes @ bug in verbatim, catches extra ] (September, 1991).
    22  // % Version 4.4 activates debug_help on errors as advertised (February, 1993).
    23  // % Version 4.5 prevents modno-comments from being split across lines (Dec 2002).
    24  // % Version 4.6 fixes archaic @z logic; is again big enough for TeX (Jan 2021).
    25  //
    26  // % Here is TeX material that gets inserted after \input webmac
    27  // \def\hang[\hangindent 3em\indent\ignorespaces]
    28  // \font\ninerm=cmr9
    29  // \let\mc=\ninerm % medium caps for names like SAIL
    30  // \def\PASCAL[Pascal]
    31  // \def\pb[$\.|\ldots\.|$] % Pascal brackets (|...|)
    32  // \def\v[\.[\char'174]] % vertical (|) in typewriter font
    33  // \mathchardef\BA="3224 % double arrow
    34  // \def\([] % kludge for alphabetizing certain module names
    35  //
    36  // \def\title[TANGLE]
    37  // \def\contentspagenumber[125] % should be odd
    38  // \def\topofcontents[\null\vfill
    39  //   \titlefalse % include headline on the contents page
    40  //   \def\rheader[\mainfont Appendix E\hfil \contentspagenumber]
    41  //   \centerline[\titlefont The [\ttitlefont TANGLE] processor]
    42  //   \vskip 15pt
    43  //   \centerline[(Version 4.6)]
    44  //   \vfill]
    45  // \pageno=\contentspagenumber \advance\pageno by 1
    46  //
    47  //
    48  
    49  // 1. Introduction
    50  
    51  // tangle:pos tangle.web:45:17:
    52  
    53  // This program converts a \.[WEB] file to a \PASCAL\ file. It was written
    54  // by D. E. Knuth in September, 1981; a somewhat similar [\mc SAIL] program had
    55  // been developed in March, 1979. Since this program describes itself, a
    56  // bootstrapping process involving hand-translation had to be used to get started.
    57  //
    58  // For large \.[WEB] files one should have a large memory, since \.[TANGLE] keeps
    59  // all the \PASCAL\ text in memory (in an abbreviated form). The program uses
    60  // a few features of the local \PASCAL\ compiler that may need to be changed in
    61  // other installations:
    62  //
    63  // \yskip\item[1)] Case statements have a default.
    64  // \item[2)] Input-output routines may need to be adapted for use with a particular
    65  // character set and/or for printing messages on the user's terminal.
    66  //
    67  // \yskip\noindent
    68  // These features are also present in the \PASCAL\ version of \TeX, where they
    69  // are used in a similar (but more complex) way. System-dependent portions
    70  // of \.[TANGLE] can be identified by looking at the entries for `system
    71  // dependencies' in the index below.
    72  //  \xref[system dependencies]
    73  //
    74  // The ``banner line'' defined here should be changed whenever \.[TANGLE]
    75  // is modified.
    76  
    77  // 2.
    78  
    79  // tangle:pos tangle.web:72:3:
    80  
    81  // The program begins with a fairly normal header, made up of pieces that
    82  // \xref[system dependencies]
    83  // will mostly be filled in later. The \.[WEB] input comes from files |web_file|
    84  // and |change_file|, the \PASCAL\ output goes to file |Pascal_file|,
    85  // and the string pool output goes to file |pool|.
    86  //
    87  // If it is necessary to abort the job because of a fatal error, the program
    88  // calls the `|jump_out|' procedure, which goes to the label |end_of_TANGLE|.
    89  // \4
    90  // Compiler directives
    91  // $C-,A+,D-
    92  // no range check, catch arithmetic overflow, no debug overhead
    93  //  [$C+,D+]  [  ]
    94  // but turn everything on when debugging
    95  
    96  package tangle
    97  
    98  import (
    99  	"math"
   100  	"unsafe"
   101  
   102  	"modernc.org/knuth"
   103  )
   104  
   105  var (
   106  	_ = math.MaxInt32
   107  	_ unsafe.Pointer
   108  )
   109  
   110  type (
   111  	char   = byte
   112  	signal int
   113  )
   114  
   115  func strcopy(dst []char, src string) {
   116  	for i := 0; i < len(dst) && i < len(src); i++ {
   117  		dst[i] = src[i]
   118  	}
   119  }
   120  
   121  func arraystr(a []char) string {
   122  	b := make([]byte, len(a))
   123  	for i, c := range a {
   124  		b[i] = c
   125  	}
   126  	return string(b)
   127  }
   128  
   129  func abs(n int32) int32 {
   130  	if n >= 0 {
   131  		return n
   132  	}
   133  
   134  	return -n
   135  }
   136  
   137  func fabs(f float64) float64 {
   138  	if f >= 0 {
   139  		return f
   140  	}
   141  
   142  	return -f
   143  }
   144  
   145  func round(f float64) int32 {
   146  	if f >= 0 {
   147  		return int32(f + 0.5)
   148  	}
   149  
   150  	return int32(f - 0.5)
   151  }
   152  
   153  const (
   154  	endOfTangle     = 9999           /* go here to wrap it up */
   155  	exit            = 10             /* go here to leave a procedure */
   156  	restart         = 20             /* go here to start a procedure again */
   157  	reswitch        = 21             /* go here to start a case statement again */
   158  	continue1       = 22             /* go here to resume a loop */
   159  	done            = 30             /* go here to exit a loop */
   160  	found           = 31             /* go here when you've found it */
   161  	notFound        = 32             /* go here when you've found something else */
   162  	spotless        = 0              /* |history| value for normal jobs */
   163  	harmlessMessage = 1              /* |history| value when non-serious info was printed */
   164  	errorMessage    = 2              /* |history| value when an error was noted */
   165  	fatalMessage    = 3              /* |history| value when we had to stop prematurely */
   166  	firstTextChar   = 0              /* ordinal number of the smallest element of |text_char| */
   167  	lastTextChar    = 255            /* ordinal number of the largest element of |text_char| */
   168  	andSign         = 04             /* equivalent to `\.[and]' */
   169  	notSign         = 05             /* equivalent to `\.[not]' */
   170  	setElementSign  = 06             /* equivalent to `\.[in]' */
   171  	tabMark         = 011            /* ASCII code used as tab-skip */
   172  	lineFeed        = 012            /* ASCII code thrown away at end of line */
   173  	formFeed        = 014            /* ASCII code used at end of page */
   174  	carriageReturn  = 015            /* ASCII code used at end of line */
   175  	leftArrow       = 030            /* equivalent to `\.[:=]' */
   176  	notEqual        = 032            /* equivalent to `\.[<>]' */
   177  	lessOrEqual     = 034            /* equivalent to `\.[<=]' */
   178  	greaterOrEqual  = 035            /* equivalent to `\.[>=]' */
   179  	equivalenceSign = 036            /* equivalent to `\.[==]' */
   180  	orSign          = 037            /* equivalent to `\.[or]' */
   181  	ww              = 2              /* we multiply the byte capacity by approximately this amount */
   182  	zz              = 3              /* we multiply the token capacity by approximately this amount */
   183  	normal          = 0              /* ordinary identifiers have |normal| ilk */
   184  	numeric         = 1              /* numeric macros and strings have |numeric| ilk */
   185  	simple          = 2              /* simple macros have |simple| ilk */
   186  	parametric      = 3              /* parametric macros have |parametric| ilk */
   187  	less            = 0              /* the first name is lexicographically less than the second */
   188  	equal           = 1              /* the first name is equal to the second */
   189  	greater         = 2              /* the first name is lexicographically greater than the second */
   190  	prefix          = 3              /* the first name is a proper prefix of the second */
   191  	extension       = 4              /* the first name is a proper extension of the second */
   192  	param           = 0              /* ASCII null code will not appear */
   193  	verbatim        = 02             /* extended ASCII alpha should not appear */
   194  	forceLine       = 03             /* extended ASCII beta should not appear */
   195  	beginComment    = 011            /* ASCII tab mark will not appear */
   196  	endComment      = 012            /* ASCII line feed will not appear */
   197  	octal           = 014            /* ASCII form feed will not appear */
   198  	hex             = 015            /* ASCII carriage return will not appear */
   199  	doubleDot       = 040            /* ASCII space will not appear except in strings */
   200  	checkSum        = 0175           /* will not be confused with right brace */
   201  	join            = 0177           /* ASCII delete will not appear */
   202  	number          = 0200           /* code returned by |get_output| when next output is numeric */
   203  	moduleNumber    = 0201           /* code returned by |get_output| for module numbers */
   204  	identifier      = 0202           /* code returned by |get_output| for identifiers */
   205  	misc            = 0              /* state associated with special characters */
   206  	numOrId         = 1              /* state associated with numbers and identifiers */
   207  	sign            = 2              /* state associated with pending \.+ or \.- */
   208  	signVal         = numOrId + 2    /* state associated with pending sign and value */
   209  	signValSign     = sign + 2       /* |sign_val| followed by another pending sign */
   210  	signValVal      = signVal + 2    /* |sign_val| followed by another pending value */
   211  	unbreakable     = signValVal + 1 /* state associated with \.[@\&] */
   212  	str             = 1              /* |send_out| code for a string */
   213  	ident           = 2              /* |send_out| code for an identifier */
   214  	frac            = 3              /* |send_out| code for a fraction */
   215  	badCase         = 666            /* this is a label used below */
   216  	getFraction     = 2              /* this label is used below */
   217  	ignore          = 0              /* control code of no interest to \.[TANGLE] */
   218  	controlText     = 0203           /* control code for `\.[@t]', `\.[@\^]', etc. */
   219  	format          = 0204           /* control code for `\.[@f]' */
   220  	definition      = 0205           /* control code for `\.[@d]' */
   221  	beginPascal     = 0206           /* control code for `\.[@p]' */
   222  	moduleName      = 0207           /* control code for `\.[@<]' */
   223  	newModule       = 0210           /* control code for `\.[@\ ]' and `\.[@*]' */
   224  	breakpoint      = 888            // place where a breakpoint is desirable
   225  	// \xref[system dependencies]
   226  
   227  	// Constants in the outer block
   228  	bufSize  = 100   // maximum length of input line
   229  	maxBytes = 45000 // |1/ww| times the number of bytes in identifiers,
   230  	//   strings, and module names; must be less than 65536
   231  
   232  	maxToks = 65000 // |1/zz| times the number of bytes in compressed \PASCAL\ code;
   233  	//   must be less than 65536
   234  
   235  	maxNames = 4000 // number of identifiers, strings, module names;
   236  	//   must be less than 10240
   237  
   238  	maxTexts    = 2000 // number of replacement texts, must be less than 10240
   239  	hashSize    = 353  // should be prime
   240  	longestName = 400  // module names shouldn't be longer than this
   241  	lineLength  = 72   // lines of \PASCAL\ output have at most this many characters
   242  	outBufSize  = 144  // length of output buffer, should be twice |line_length|
   243  	stackSize   = 50   // number of simultaneous levels of macro expansion
   244  	maxIdLength = 32   // long identifiers are chopped to this length, which must
   245  	//   not exceed |line_length|
   246  
   247  	unambigLength = 32 // identifiers must be unique if chopped to this length
   248  )
   249  
   250  type (
   251  	// Types in the outer block
   252  	asciiCode = /* 0..255 */ byte // eight-bit numbers, a subrange of the integers
   253  
   254  	textFile = knuth.File
   255  
   256  	eightBits   = /* 0..255 */ byte     // unsigned one-byte quantity
   257  	sixteenBits = /* 0..65535 */ uint16 // unsigned two-byte quantity
   258  
   259  	namePointer = /* 0..maxNames */ uint16 // identifies a name
   260  
   261  	textPointer = /* 0..maxTexts */ uint16 // identifies a replacement text
   262  
   263  	// \4
   264  	outputState = struct {
   265  		endField  sixteenBits // ending location of replacement text
   266  		byteField sixteenBits // present location within replacement text
   267  		nameField namePointer // |byte_start| index for text being output
   268  		replField textPointer // |tok_start| index for text being output
   269  		modField  uint16      // module number or zero if not a module
   270  	}
   271  )
   272  
   273  type prg struct {
   274  	stdin, stdout, stderr knuth.File
   275  	/* Globals in the outer block  */ history/* spotless..fatalMessage */ byte // how bad was this run?
   276  
   277  	xord [256]asciiCode
   278  	// specifies conversion of input characters
   279  	xchr [256]char
   280  	// specifies conversion of output characters
   281  
   282  	termOut textFile // the terminal as an output file
   283  
   284  	webFile    textFile // primary input
   285  	changeFile textFile // updates
   286  
   287  	pascalFile textFile
   288  	pool       textFile
   289  
   290  	buffer [101]asciiCode
   291  
   292  	phaseOne bool // |true| in Phase I, |false| in Phase II
   293  
   294  	byteMem [2][45001]asciiCode
   295  	// characters of names
   296  	tokMem    [3][65001]eightBits // tokens
   297  	byteStart [4001]sixteenBits   // directory into |byte_mem|
   298  	tokStart  [2001]sixteenBits   // directory into |tok_mem|
   299  	link      [4001]sixteenBits   // hash table or tree links
   300  	ilk       [4001]sixteenBits   // type codes or tree links
   301  	equiv     [4001]sixteenBits   // info corresponding to names
   302  	textLink  [2001]sixteenBits   // relates replacement texts
   303  
   304  	namePtr   namePointer // first unused position in |byte_start|
   305  	stringPtr namePointer // next number to be given to a string of length |<>1|
   306  	bytePtr   [2] /* 0..maxBytes */ uint16
   307  	// first unused position in |byte_mem|
   308  	poolCheckSum int32 // sort of a hash for the whole string pool
   309  
   310  	// \hskip1em
   311  	textPtr textPointer // first unused position in |tok_start|
   312  	// \hskip1em
   313  	tokPtr [3] /* 0..maxToks */ uint16
   314  	// first unused position in a given segment of |tok_mem|
   315  	// \hskip1em
   316  	z/* 0..zz-1 */ byte // current segment of |tok_mem|
   317  	//   max_tok_ptr:array[0..zz-1] of 0..max_toks;
   318  	//   [largest values assumed by |tok_ptr|]
   319  	// [  ]
   320  
   321  	idFirst/* 0..bufSize */ byte     // where the current identifier begins in the buffer
   322  	idLoc/* 0..bufSize */ byte       // just after the current identifier in the buffer
   323  	doubleChars/* 0..bufSize */ byte // correction to length in case of strings
   324  
   325  	hash, chopHash [354]sixteenBits // heads of hash lists
   326  	choppedId      [33]asciiCode    // chopped identifier
   327  
   328  	modText [401]asciiCode // name being sought for
   329  
   330  	lastUnnamed textPointer // most recent replacement text of unnamed module
   331  
   332  	curState outputState // |cur_end|, |cur_byte|, |cur_name|,
   333  	//   |cur_repl|, |cur_mod|
   334  
   335  	stack                           [50]outputState // info for non-current levels
   336  	stackPtr/* 0..stackSize */ byte // first unused location in the output state stack
   337  
   338  	zo/* 0..zz-1 */ byte // the segment of |tok_mem| from which output is coming
   339  
   340  	braceLevel eightBits // current depth of $\.[@\[]\ldots\.[@\]]$ nesting
   341  
   342  	curVal int32 // additional information corresponding to output token
   343  
   344  	outBuf                           [145]asciiCode // assembled characters
   345  	outPtr/* 0..outBufSize */ byte   // first available place in |out_buf|
   346  	breakPtr/* 0..outBufSize */ byte // last breaking place in |out_buf|
   347  	semiPtr/* 0..outBufSize */ byte  // last semicolon breaking place in |out_buf|
   348  
   349  	outState                    eightBits // current status of partial output
   350  	outVal, outApp              int32     // pending values
   351  	outSign                     asciiCode // sign to use if appending |out_val>=0|
   352  	lastSign/*  -1.. +1 */ int8 // sign to use if appending a zero
   353  
   354  	outContrib [72]asciiCode // a contribution to |out_buf|
   355  
   356  	ii1       int32 // general purpose |for| loop variable in the outer block
   357  	line      int32 // the number of the current line in the current file
   358  	otherLine int32 // the number of the current line in the input file that
   359  	//   is not currently being read
   360  
   361  	tempLine                   int32 // used when interchanging |line| with |other_line|
   362  	limit/* 0..bufSize */ byte // the last character position occupied in the buffer
   363  	loc/* 0..bufSize */ byte   // the next character position to be read from the buffer
   364  	inputHasEnded              bool // if |true|, there is no more input
   365  	changing                   bool // if |true|, the current line is from |change_file|
   366  
   367  	changeBuffer                     [101]asciiCode
   368  	changeLimit/* 0..bufSize */ byte // the last position occupied in |change_buffer|
   369  
   370  	curModule   namePointer // name of module just scanned
   371  	scanningHex bool        // are we scanning a hexadecimal constant?
   372  
   373  	nextControl eightBits // control code waiting to be acted upon
   374  
   375  	curReplText textPointer // replacement text formed by |scan_repl|
   376  
   377  	moduleCount/* 0..027777 */ uint16 // the current module number
   378  
   379  	//  trouble_shooting:boolean; [is |debug_help| wanted?]
   380  	//  ddt:integer; [operation code for the |debug_help| routine]
   381  	//  dd:integer; [operand in procedures performed by |debug_help|]
   382  	//  debug_cycle:integer; [threshold for |debug_help| stopping]
   383  	//  debug_skipped:integer; [we have skipped this many |debug_help| calls]
   384  	//  term_in:text_file; [the user's terminal as an input file]
   385  	// [  ]
   386  
   387  	//   wo:0..ww-1; [segment of memory for which statistics are being printed]
   388  	// [  ]
   389  
   390  	// Error handling procedures
   391  	//
   392  	//	procedure debug_help; forward;  [  ]
   393  }
   394  
   395  func (prg *prg) error1() { // prints '\..' and location of error message
   396  	var (
   397  		j/* 0..outBufSize */ byte // index into |out_buf|
   398  		k, l/* 0..bufSize */ byte // indices into |buffer|
   399  	)
   400  	if prg.phaseOne {
   401  		if prg.changing {
   402  			prg.stdout.Write(". (change file ")
   403  		} else {
   404  			prg.stdout.Write(". (")
   405  		}
   406  		prg.stdout.Writeln("l.", prg.line, knuth.WriteWidth(1), ")")
   407  		if int32(prg.loc) >= int32(prg.limit) {
   408  			l = prg.limit
   409  		} else {
   410  			l = prg.loc
   411  		}
   412  		for ii := int32(1); ii <= int32(l); ii++ {
   413  			k = byte(ii)
   414  			_ = k
   415  			if int32(prg.buffer[int32(k)-1]) == tabMark {
   416  				prg.stdout.Write(" ")
   417  			} else {
   418  				prg.stdout.Write(string(rune(prg.xchr[prg.buffer[int32(k)-1]])))
   419  			}
   420  		} // print the characters already read
   421  		prg.stdout.Writeln()
   422  		for ii := int32(1); ii <= int32(l); ii++ {
   423  			k = byte(ii)
   424  			_ = k
   425  			prg.stdout.Write(" ")
   426  		} // space out the next line
   427  		for ii := int32(l) + 1; ii <= int32(prg.limit); ii++ {
   428  			k = byte(ii)
   429  			_ = k
   430  			prg.stdout.Write(string(rune(prg.xchr[prg.buffer[int32(k)-1]])))
   431  		} // print the part not yet read
   432  		prg.stdout.Write(" ") // this space separates the message from future asterisks
   433  	} else {
   434  		// Print error location based on output buffer
   435  		prg.stdout.Writeln(". (l.", prg.line, knuth.WriteWidth(1), ")")
   436  		for ii := int32(1); ii <= int32(prg.outPtr); ii++ {
   437  			j = byte(ii)
   438  			_ = j
   439  			prg.stdout.Write(string(rune(prg.xchr[prg.outBuf[int32(j)-1]])))
   440  		} // print current partial line
   441  		prg.stdout.Write("... ") // indicate that this information is partial
   442  	}
   443  	prg.history = byte(errorMessage)
   444  	//  debug_skipped:=debug_cycle; debug_help; [  ]
   445  }
   446  
   447  func (prg *prg) jumpOut() {
   448  	panic(signal(endOfTangle))
   449  }
   450  
   451  func (prg *prg) initialize() {
   452  	var (
   453  		// Local variables for initialization
   454  		i/* 0..255 */ byte
   455  
   456  		wi/* 0..ww-1 */ byte // to initialize the |byte_mem| indices
   457  
   458  		zi/* 0..zz-1 */ byte // to initialize the |tok_mem| indices
   459  
   460  		h/* 0..hashSize */ uint16 // index into hash-head arrays
   461  	)
   462  	prg.history = byte(spotless)
   463  
   464  	prg.xchr[040] = ' '
   465  	prg.xchr[041] = '!'
   466  	prg.xchr[042] = '"'
   467  	prg.xchr[043] = '#'
   468  	prg.xchr[044] = '$'
   469  	prg.xchr[045] = '%'
   470  	prg.xchr[046] = '&'
   471  	prg.xchr[047] = '\''
   472  
   473  	prg.xchr[050] = '('
   474  	prg.xchr[051] = ')'
   475  	prg.xchr[052] = '*'
   476  	prg.xchr[053] = '+'
   477  	prg.xchr[054] = ','
   478  	prg.xchr[055] = '-'
   479  	prg.xchr[056] = '.'
   480  	prg.xchr[057] = '/'
   481  
   482  	prg.xchr[060] = '0'
   483  	prg.xchr[061] = '1'
   484  	prg.xchr[062] = '2'
   485  	prg.xchr[063] = '3'
   486  	prg.xchr[064] = '4'
   487  	prg.xchr[065] = '5'
   488  	prg.xchr[066] = '6'
   489  	prg.xchr[067] = '7'
   490  
   491  	prg.xchr[070] = '8'
   492  	prg.xchr[071] = '9'
   493  	prg.xchr[072] = ':'
   494  	prg.xchr[073] = ';'
   495  	prg.xchr[074] = '<'
   496  	prg.xchr[075] = '='
   497  	prg.xchr[076] = '>'
   498  	prg.xchr[077] = '?'
   499  
   500  	prg.xchr[0100] = '@'
   501  	prg.xchr[0101] = 'A'
   502  	prg.xchr[0102] = 'B'
   503  	prg.xchr[0103] = 'C'
   504  	prg.xchr[0104] = 'D'
   505  	prg.xchr[0105] = 'E'
   506  	prg.xchr[0106] = 'F'
   507  	prg.xchr[0107] = 'G'
   508  
   509  	prg.xchr[0110] = 'H'
   510  	prg.xchr[0111] = 'I'
   511  	prg.xchr[0112] = 'J'
   512  	prg.xchr[0113] = 'K'
   513  	prg.xchr[0114] = 'L'
   514  	prg.xchr[0115] = 'M'
   515  	prg.xchr[0116] = 'N'
   516  	prg.xchr[0117] = 'O'
   517  
   518  	prg.xchr[0120] = 'P'
   519  	prg.xchr[0121] = 'Q'
   520  	prg.xchr[0122] = 'R'
   521  	prg.xchr[0123] = 'S'
   522  	prg.xchr[0124] = 'T'
   523  	prg.xchr[0125] = 'U'
   524  	prg.xchr[0126] = 'V'
   525  	prg.xchr[0127] = 'W'
   526  
   527  	prg.xchr[0130] = 'X'
   528  	prg.xchr[0131] = 'Y'
   529  	prg.xchr[0132] = 'Z'
   530  	prg.xchr[0133] = '['
   531  	prg.xchr[0134] = '\\'
   532  	prg.xchr[0135] = ']'
   533  	prg.xchr[0136] = '^'
   534  	prg.xchr[0137] = '_'
   535  
   536  	prg.xchr[0140] = '`'
   537  	prg.xchr[0141] = 'a'
   538  	prg.xchr[0142] = 'b'
   539  	prg.xchr[0143] = 'c'
   540  	prg.xchr[0144] = 'd'
   541  	prg.xchr[0145] = 'e'
   542  	prg.xchr[0146] = 'f'
   543  	prg.xchr[0147] = 'g'
   544  
   545  	prg.xchr[0150] = 'h'
   546  	prg.xchr[0151] = 'i'
   547  	prg.xchr[0152] = 'j'
   548  	prg.xchr[0153] = 'k'
   549  	prg.xchr[0154] = 'l'
   550  	prg.xchr[0155] = 'm'
   551  	prg.xchr[0156] = 'n'
   552  	prg.xchr[0157] = 'o'
   553  
   554  	prg.xchr[0160] = 'p'
   555  	prg.xchr[0161] = 'q'
   556  	prg.xchr[0162] = 'r'
   557  	prg.xchr[0163] = 's'
   558  	prg.xchr[0164] = 't'
   559  	prg.xchr[0165] = 'u'
   560  	prg.xchr[0166] = 'v'
   561  	prg.xchr[0167] = 'w'
   562  
   563  	prg.xchr[0170] = 'x'
   564  	prg.xchr[0171] = 'y'
   565  	prg.xchr[0172] = 'z'
   566  	prg.xchr[0173] = '{'
   567  	prg.xchr[0174] = '|'
   568  	prg.xchr[0175] = '}'
   569  	prg.xchr[0176] = '~'
   570  
   571  	prg.xchr[0] = ' '
   572  	prg.xchr[0177] = ' ' // these ASCII codes are not used
   573  
   574  	for ii := int32(1); ii <= 037; ii++ {
   575  		i = byte(ii)
   576  		_ = i
   577  		prg.xchr[i] = ' '
   578  	}
   579  	for ii := int32(0200); ii <= 0377; ii++ {
   580  		i = byte(ii)
   581  		_ = i
   582  		prg.xchr[i] = ' '
   583  	}
   584  
   585  	for ii := int32(firstTextChar); ii <= lastTextChar; ii++ {
   586  		i = byte(ii)
   587  		_ = i
   588  		prg.xord[i] = ' '
   589  	}
   590  	for ii := int32(1); ii <= 0377; ii++ {
   591  		i = byte(ii)
   592  		_ = i
   593  		prg.xord[prg.xchr[i]] = i
   594  	}
   595  	prg.xord[' '] = ' '
   596  
   597  	prg.pascalFile.Rewrite()
   598  	prg.pool.Rewrite()
   599  
   600  	for ii := int32(0); ii <= ww-1; ii++ {
   601  		wi = byte(ii)
   602  		_ = wi
   603  		prg.byteStart[wi] = 0
   604  		prg.bytePtr[wi] = 0
   605  	}
   606  	prg.byteStart[ww] = 0 // this makes name 0 of length zero
   607  	prg.namePtr = 1
   608  	prg.stringPtr = 256
   609  	prg.poolCheckSum = 271828
   610  
   611  	for ii := int32(0); ii <= zz-1; ii++ {
   612  		zi = byte(ii)
   613  		_ = zi
   614  		prg.tokStart[zi] = 0
   615  		prg.tokPtr[zi] = 0
   616  	}
   617  	prg.tokStart[zz] = 0 // this makes replacement text 0 of length zero
   618  	prg.textPtr = 1
   619  	prg.z = byte(1 % zz)
   620  
   621  	prg.ilk[0] = 0   // the binary search tree starts out with nothing in it
   622  	prg.equiv[0] = 0 // the undefined module has no replacement text
   623  
   624  	for ii := int32(0); ii <= hashSize-1; ii++ {
   625  		h = uint16(ii)
   626  		_ = h
   627  		prg.hash[h] = 0
   628  		prg.chopHash[h] = 0
   629  	}
   630  
   631  	prg.lastUnnamed = 0
   632  	prg.textLink[0] = 0
   633  
   634  	prg.scanningHex = false
   635  
   636  	prg.modText[0] = ' '
   637  
   638  	//  trouble_shooting:=true; debug_cycle:=1; debug_skipped:=0;
   639  	//
   640  	// trouble_shooting:=false; debug_cycle:=99999; [use these when it almost works]
   641  	// reset(term_in,'TTY:','/I'); [open |term_in| as the terminal, don't do a |get|]
   642  	// [  ]
   643  
   644  }
   645  
   646  // 3.
   647  
   648  // tangle:pos tangle.web:95:3:
   649  
   650  // Some of this code is optional for use when debugging only;
   651  // such material is enclosed between the delimiters |debug| and $|gubed|$.
   652  // Other parts, delimited by |stat| and $|tats|$, are optionally included if
   653  // statistics about \.[TANGLE]'s memory usage are desired.
   654  
   655  // 5.
   656  
   657  // tangle:pos tangle.web:124:3:
   658  
   659  // Labels are given symbolic names by the following definitions. We insert
   660  // the label `|exit|:' just before the `\ignorespaces|end|\unskip' of a
   661  // procedure in which we have used the `|return|' statement defined below;
   662  // the label `|restart|' is occasionally used at the very beginning of a
   663  // procedure; and the label `|reswitch|' is occasionally used just prior to
   664  // a \&[case] statement in which some cases change the conditions and we wish to
   665  // branch to the newly applicable case.
   666  // Loops that are set up with the \&[loop] construction defined below are
   667  // commonly exited by going to `|done|' or to `|found|' or to `|not_found|',
   668  // and they are sometimes repeated by going to `|continue|'.
   669  
   670  // 6.
   671  
   672  // tangle:pos tangle.web:143:3:
   673  
   674  // Here are some macros for common programming idioms.
   675  
   676  // 7.
   677  
   678  // tangle:pos tangle.web:153:3:
   679  
   680  // We assume that |case| statements may include a default case that applies
   681  // if no matching label is found. Thus, we shall use constructions like
   682  // \xref[system dependencies]
   683  // $$\vbox[\halign[#\hfil\cr
   684  // |case x of|\cr
   685  // 1: $\langle\,$code for $x=1\,\rangle$;\cr
   686  // 3: $\langle\,$code for $x=3\,\rangle$;\cr
   687  // |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
   688  // |endcases|\cr]]$$
   689  // since most \PASCAL\ compilers have plugged this hole in the language by
   690  // incorporating some sort of default mechanism. For example, the compiler
   691  // used to develop \.[WEB] and \TeX\ allows `|others|:' as a default label,
   692  // and other \PASCAL s allow syntaxes like `\ignorespaces|else|\unskip' or
   693  // `\&[otherwise]' or `\\[otherwise]:', etc. The definitions of |othercases|
   694  // and |endcases| should be changed to agree with local conventions. (Of
   695  // course, if no default mechanism is available, the |case| statements of
   696  // this program must be extended by listing all remaining cases. The author
   697  // would have taken the trouble to modify \.[TANGLE] so that such extensions
   698  // were done automatically, if he had not wanted to encourage \PASCAL\
   699  // compiler writers to make this important change in \PASCAL, where it belongs.)
   700  
   701  // 15.
   702  
   703  // tangle:pos tangle.web:432:3:
   704  
   705  // Some of the ASCII codes below @'40 have been given symbolic names in
   706  // \.[WEAVE] and \.[TANGLE] because they are used with a special meaning.
   707  
   708  // 19. Input and output
   709  
   710  // tangle:pos tangle.web:494:21:
   711  
   712  // The input conventions of this program are intended to be very much like those
   713  // of \TeX\ (except, of course, that they are much simpler, because much less
   714  // needs to be done). Furthermore they are identical to those of \.[WEAVE].
   715  // Therefore people who need to make modifications to all three systems
   716  // should be able to do so without too many headaches.
   717  //
   718  // We use the standard \PASCAL\ input/output procedures in several places that
   719  // \TeX\ cannot, since \.[TANGLE] does not have to deal with files that are named
   720  // dynamically by the user, and since there is no input from the terminal.
   721  
   722  // 22.
   723  
   724  // tangle:pos tangle.ch:77:3:
   725  
   726  // The |update_terminal| procedure is called when we want
   727  // to make sure that everything we have output to the terminal so far has
   728  // actually left the computer's internal buffers and been sent.
   729  // \xref[system dependencies]
   730  
   731  // 24.
   732  
   733  // tangle:pos tangle.web:541:3:
   734  
   735  // The following code opens the input files.  Since these files were listed
   736  // in the program header, we assume that the \PASCAL\ runtime system has
   737  // already checked that suitable file names have been given; therefore no
   738  // additional error checking needs to be done.
   739  // \xref[system dependencies]
   740  func (prg *prg) openInput() {
   741  	prg.webFile.Reset()
   742  	prg.changeFile.Reset()
   743  }
   744  
   745  // 28.
   746  
   747  // tangle:pos tangle.web:571:3:
   748  
   749  // The |input_ln| procedure brings the next line of input from the specified
   750  // file into the |buffer| array and returns the value |true|, unless the file has
   751  // already been entirely read, in which case it returns |false|. The conventions
   752  // of \TeX\ are followed; i.e., |ASCII_code| numbers representing the next line
   753  // of the file are input into |buffer[0]|, |buffer[1]|, \dots,
   754  // |buffer[limit-1]|; trailing blanks are ignored;
   755  // and the global variable |limit| is set to the length of the
   756  // \xref[system dependencies]
   757  // line. The value of |limit| must be strictly less than |buf_size|.
   758  //
   759  // We assume that none of the |ASCII_code| values
   760  // of |buffer[j]| for |0<=j<limit| is equal to 0, @'177, |line_feed|, |form_feed|,
   761  // or |carriage_return|.
   762  func (prg *prg) inputLn(f textFile) (r bool) {
   763  	// inputs a line or returns |false|
   764  	var (
   765  		finalLimit /* 0..bufSize */ byte // |limit| without trailing blanks
   766  	)
   767  	prg.limit = 0
   768  	finalLimit = 0
   769  	if f.EOF() {
   770  		r = false
   771  	} else {
   772  		for !f.EOLN() {
   773  			prg.buffer[prg.limit] = prg.xord[*f.ByteP()]
   774  			f.Get()
   775  			prg.limit = byte(int32(prg.limit) + 1)
   776  			if int32(prg.buffer[int32(prg.limit)-1]) != ' ' {
   777  				finalLimit = prg.limit
   778  			}
   779  			if int32(prg.limit) == bufSize {
   780  				for !f.EOLN() {
   781  					f.Get()
   782  				}
   783  				prg.limit = byte(int32(prg.limit) - 1) // keep |buffer[buf_size]| empty
   784  				if int32(finalLimit) > int32(prg.limit) {
   785  					finalLimit = prg.limit
   786  				}
   787  				{
   788  					prg.stdout.Writeln()
   789  					prg.stdout.Write("! Input line too long")
   790  				}
   791  				prg.loc = 0
   792  				prg.error1()
   793  				// \xref[Input line too long]
   794  			}
   795  		}
   796  		f.Readln()
   797  		prg.limit = finalLimit
   798  		r = true
   799  	}
   800  	return r
   801  }
   802  
   803  // 35.
   804  
   805  // tangle:pos tangle.web:699:3:
   806  
   807  // Sometimes the program's behavior is far different from what it should be,
   808  // and \.[TANGLE] prints an error message that is really for the \.[TANGLE]
   809  // maintenance person, not the user. In such cases the program says
   810  // |confusion('indication of where we are')|.
   811  
   812  // 36.
   813  
   814  // tangle:pos tangle.web:707:3:
   815  
   816  // An overflow stop occurs if \.[TANGLE]'s tables aren't large enough.
   817  
   818  // 47.
   819  
   820  // tangle:pos tangle.web:851:3:
   821  
   822  // Four types of identifiers are distinguished by their |ilk|:
   823  //
   824  // \yskip\hang |normal| identifiers will appear in the \PASCAL\ program as
   825  // ordinary identifiers since they have not been defined to be macros; the
   826  // corresponding value in the |equiv| array
   827  // for such identifiers is a link in a secondary hash table that
   828  // is used to check whether any two of them agree in their first |unambig_length|
   829  // characters after underline symbols are removed and lowercase letters are
   830  // changed to uppercase.
   831  //
   832  // \yskip\hang |numeric| identifiers have been defined to be numeric macros;
   833  // their |equiv| value contains the corresponding numeric value plus $2^[15]$.
   834  // Strings are treated as numeric macros.
   835  //
   836  // \yskip\hang |simple| identifiers have been defined to be simple macros;
   837  // their |equiv| value points to the corresponding replacement text.
   838  //
   839  // \yskip\hang |parametric| identifiers have been defined to be parametric macros;
   840  // like simple identifiers, their |equiv| value points to the replacement text.
   841  
   842  // 49.
   843  
   844  // tangle:pos tangle.web:893:3:
   845  
   846  // Here is a little procedure that prints the text of a given name.
   847  func (prg *prg) printId(p namePointer) { // print identifier or module name
   848  	var (
   849  		k/* 0..maxBytes */ uint16 // index into |byte_mem|
   850  		w/* 0..ww-1 */ byte       // segment of |byte_mem|
   851  	)
   852  	if int32(p) >= int32(prg.namePtr) {
   853  		prg.stdout.Write("IMPOSSIBLE")
   854  	} else {
   855  		w = byte(int32(p) % ww)
   856  		for ii := int32(prg.byteStart[p]); ii <= int32(prg.byteStart[int32(p)+ww])-1; ii++ {
   857  			k = uint16(ii)
   858  			_ = k
   859  			prg.stdout.Write(string(rune(prg.xchr[prg.byteMem[w][k]])))
   860  		}
   861  	}
   862  }
   863  
   864  // 53.
   865  
   866  // tangle:pos tangle.web:957:3:
   867  
   868  // Here now is the main procedure for finding identifiers (and strings).
   869  // The parameter |t| is set to |normal| except when the identifier is
   870  // a macro name that is just being defined; in the latter case, |t| will be
   871  // |numeric|, |simple|, or |parametric|.
   872  func (prg *prg) idLookup(t eightBits) (r namePointer) {
   873  	var (
   874  		c                            eightBits   // byte being chopped
   875  		i/* 0..bufSize */ byte                   // index into |buffer|
   876  		h/* 0..hashSize */ uint16                // hash code
   877  		k/* 0..maxBytes */ uint16                // index into |byte_mem|
   878  		w/* 0..ww-1 */ byte                      // segment of |byte_mem|
   879  		l/* 0..bufSize */ byte                   // length of the given identifier
   880  		p, q                         namePointer // where the identifier is being sought
   881  		s/* 0..unambigLength */ byte             // index into |chopped_id|
   882  	)
   883  	l = byte(int32(prg.idLoc) - int32(prg.idFirst)) // compute the length
   884  
   885  	// Compute the hash code |h|
   886  	h = uint16(prg.buffer[prg.idFirst])
   887  	i = byte(int32(prg.idFirst) + 1)
   888  	for int32(i) < int32(prg.idLoc) {
   889  		h = uint16((int32(h) + int32(h) + int32(prg.buffer[i])) % hashSize)
   890  		i = byte(int32(i) + 1)
   891  	}
   892  
   893  	// Compute the name location |p|
   894  	p = prg.hash[h]
   895  	for int32(p) != 0 {
   896  		if int32(prg.byteStart[int32(p)+ww])-int32(prg.byteStart[p]) == int32(l) {
   897  			i = prg.idFirst
   898  			k = prg.byteStart[p]
   899  			w = byte(int32(p) % ww)
   900  			for int32(i) < int32(prg.idLoc) && int32(prg.buffer[i]) == int32(prg.byteMem[w][k]) {
   901  				i = byte(int32(i) + 1)
   902  				k = uint16(int32(k) + 1)
   903  			}
   904  			if int32(i) == int32(prg.idLoc) {
   905  				goto found
   906  			} // all characters agree
   907  		}
   908  		p = prg.link[p]
   909  	}
   910  	p = prg.namePtr // the current identifier is new
   911  	prg.link[p] = prg.hash[h]
   912  	prg.hash[h] = p // insert |p| at beginning of hash list
   913  	// insert |p| at beginning of hash list
   914  found:
   915  	;
   916  	if int32(p) == int32(prg.namePtr) || int32(t) != normal {
   917  		if int32(p) != int32(prg.namePtr) && int32(t) != normal && int32(prg.ilk[p]) == normal || int32(p) == int32(prg.namePtr) && int32(t) == normal && int32(prg.buffer[prg.idFirst]) != '"' {
   918  			i = prg.idFirst
   919  			s = 0
   920  			h = 0
   921  			for int32(i) < int32(prg.idLoc) && int32(s) < unambigLength {
   922  				if int32(prg.buffer[i]) != '_' {
   923  					if int32(prg.buffer[i]) >= 'a' {
   924  						prg.choppedId[s] = byte(int32(prg.buffer[i]) - 040)
   925  					} else {
   926  						prg.choppedId[s] = prg.buffer[i]
   927  					}
   928  					h = uint16((int32(h) + int32(h) + int32(prg.choppedId[s])) % hashSize)
   929  					s = byte(int32(s) + 1)
   930  				}
   931  				i = byte(int32(i) + 1)
   932  			}
   933  			prg.choppedId[s] = 0
   934  		}
   935  		if int32(p) != int32(prg.namePtr) {
   936  			if int32(prg.ilk[p]) == normal {
   937  				if int32(t) == numeric {
   938  					prg.stdout.Writeln()
   939  					prg.stdout.Write("! This identifier has already appeared")
   940  					prg.error1()
   941  				}
   942  				// \xref[This identifier has already...]
   943  
   944  				// Remove |p| from secondary hash table
   945  				q = prg.chopHash[h]
   946  				if int32(q) == int32(p) {
   947  					prg.chopHash[h] = prg.equiv[p]
   948  				} else {
   949  					for int32(prg.equiv[q]) != int32(p) {
   950  						q = prg.equiv[q]
   951  					}
   952  					prg.equiv[q] = prg.equiv[p]
   953  				}
   954  			} else {
   955  				prg.stdout.Writeln()
   956  				prg.stdout.Write("! This identifier was defined before")
   957  				prg.error1()
   958  			}
   959  			// \xref[This identifier was defined...]
   960  			prg.ilk[p] = uint16(t)
   961  		} else {
   962  			// Enter a new identifier into the table at position |p|
   963  			if int32(t) == normal && int32(prg.buffer[prg.idFirst]) != '"' {
   964  				q = prg.chopHash[h]
   965  				for int32(q) != 0 {
   966  					{
   967  						k = prg.byteStart[q]
   968  						s = 0
   969  						w = byte(int32(q) % ww)
   970  						for int32(k) < int32(prg.byteStart[int32(q)+ww]) && int32(s) < unambigLength {
   971  							c = prg.byteMem[w][k]
   972  							if int32(c) != '_' {
   973  								if int32(c) >= 'a' {
   974  									c = byte(int32(c) - 040)
   975  								} // merge lowercase with uppercase
   976  								if int32(prg.choppedId[s]) != int32(c) {
   977  									goto notFound
   978  								}
   979  								s = byte(int32(s) + 1)
   980  							}
   981  							k = uint16(int32(k) + 1)
   982  						}
   983  						if int32(k) == int32(prg.byteStart[int32(q)+ww]) && int32(prg.choppedId[s]) != 0 {
   984  							goto notFound
   985  						}
   986  						{
   987  							prg.stdout.Writeln()
   988  							prg.stdout.Write("! Identifier conflict with ")
   989  						}
   990  						// \xref[Identifier conflict...]
   991  						for ii := int32(prg.byteStart[q]); ii <= int32(prg.byteStart[int32(q)+ww])-1; ii++ {
   992  							k = uint16(ii)
   993  							_ = k
   994  							prg.stdout.Write(string(rune(prg.xchr[prg.byteMem[w][k]])))
   995  						}
   996  						prg.error1()
   997  						q = 0 // only one conflict will be printed, since |equiv[0]=0|
   998  						// only one conflict will be printed, since |equiv[0]=0|
   999  					notFound:
  1000  					}
  1001  					q = prg.equiv[q]
  1002  				}
  1003  				prg.equiv[p] = prg.chopHash[h]
  1004  				prg.chopHash[h] = p // put |p| at front of secondary list
  1005  			}
  1006  			w = byte(int32(prg.namePtr) % ww)
  1007  			k = prg.bytePtr[w]
  1008  			if int32(k)+int32(l) > maxBytes {
  1009  				prg.stderr.Writeln("! Sorry, ", "byte memory", " capacity exceeded")
  1010  				prg.error1()
  1011  				prg.history = byte(fatalMessage)
  1012  				prg.jumpOut()
  1013  			}
  1014  			if int32(prg.namePtr) > maxNames-ww {
  1015  				prg.stderr.Writeln("! Sorry, ", "name", " capacity exceeded")
  1016  				prg.error1()
  1017  				prg.history = byte(fatalMessage)
  1018  				prg.jumpOut()
  1019  			}
  1020  			i = prg.idFirst // get ready to move the identifier into |byte_mem|
  1021  			for int32(i) < int32(prg.idLoc) {
  1022  				prg.byteMem[w][k] = prg.buffer[i]
  1023  				k = uint16(int32(k) + 1)
  1024  				i = byte(int32(i) + 1)
  1025  			}
  1026  			prg.bytePtr[w] = k
  1027  			prg.byteStart[int32(prg.namePtr)+ww] = k
  1028  			prg.namePtr = uint16(int32(prg.namePtr) + 1)
  1029  			if int32(prg.buffer[prg.idFirst]) != '"' {
  1030  				prg.ilk[p] = uint16(t)
  1031  			} else {
  1032  				// Define and output a new string of the pool
  1033  				prg.ilk[p] = uint16(numeric) // strings are like numeric macros
  1034  				if int32(l)-int32(prg.doubleChars) == 2 {
  1035  					prg.equiv[p] = uint16(int32(prg.buffer[int32(prg.idFirst)+1]) + 0100000)
  1036  				} else {
  1037  					prg.equiv[p] = uint16(int32(prg.stringPtr) + 0100000)
  1038  					l = byte(int32(l) - int32(prg.doubleChars) - 1)
  1039  					if int32(l) > 99 {
  1040  						prg.stdout.Writeln()
  1041  						prg.stdout.Write("! Preprocessed string is too long")
  1042  						prg.error1()
  1043  					}
  1044  					// \xref[Preprocessed string is too long]
  1045  					prg.stringPtr = uint16(int32(prg.stringPtr) + 1)
  1046  					prg.pool.Write(string(rune(prg.xchr['0'+int32(l)/10])), string(rune(prg.xchr['0'+int32(l)%10]))) // output the length
  1047  					prg.poolCheckSum = prg.poolCheckSum + prg.poolCheckSum + int32(l)
  1048  					for prg.poolCheckSum > 03777777667 {
  1049  						prg.poolCheckSum = prg.poolCheckSum - 03777777667
  1050  					}
  1051  					i = byte(int32(prg.idFirst) + 1)
  1052  					for int32(i) < int32(prg.idLoc) {
  1053  						prg.pool.Write(string(rune(prg.xchr[prg.buffer[i]]))) // output characters of string
  1054  						prg.poolCheckSum = prg.poolCheckSum + prg.poolCheckSum + int32(prg.buffer[i])
  1055  						for prg.poolCheckSum > 03777777667 {
  1056  							prg.poolCheckSum = prg.poolCheckSum - 03777777667
  1057  						}
  1058  						if int32(prg.buffer[i]) == '"' || int32(prg.buffer[i]) == '@' {
  1059  							i = byte(int32(i) + 2)
  1060  						} else {
  1061  							i = byte(int32(i) + 1)
  1062  						}
  1063  					}
  1064  					prg.pool.Writeln()
  1065  				}
  1066  			}
  1067  		}
  1068  	}
  1069  	r = p
  1070  	return r
  1071  }
  1072  
  1073  // 66.
  1074  
  1075  // tangle:pos tangle.web:1158:3:
  1076  
  1077  // According to the rules of \.[WEB], no module name
  1078  // should be a proper prefix of another, so a ``clean'' comparison should
  1079  // occur between any two names. The result of |mod_lookup| is 0 if this
  1080  // prefix condition is violated. An error message is printed when such violations
  1081  // are detected during phase two of \.[WEAVE].
  1082  func (prg *prg) modLookup(l sixteenBits) (r namePointer) {
  1083  	var (
  1084  		c/* less..extension */ byte              // comparison between two names
  1085  		j/* 0..longestName */ uint16             // index into |mod_text|
  1086  		k/* 0..maxBytes */ uint16                // index into |byte_mem|
  1087  		w/* 0..ww-1 */ byte                      // segment of |byte_mem|
  1088  		p                            namePointer // current node of the search tree
  1089  		q                            namePointer // father of node |p|
  1090  	)
  1091  	c = byte(greater)
  1092  	q = 0
  1093  	p = prg.ilk[0] // |rlink[0]| is the root of the tree
  1094  	for int32(p) != 0 {
  1095  		{
  1096  			k = prg.byteStart[p]
  1097  			w = byte(int32(p) % ww)
  1098  			c = byte(equal)
  1099  			j = 1
  1100  			for int32(k) < int32(prg.byteStart[int32(p)+ww]) && int32(j) <= int32(l) && int32(prg.modText[j]) == int32(prg.byteMem[w][k]) {
  1101  				k = uint16(int32(k) + 1)
  1102  				j = uint16(int32(j) + 1)
  1103  			}
  1104  			if int32(k) == int32(prg.byteStart[int32(p)+ww]) {
  1105  				if int32(j) > int32(l) {
  1106  					c = byte(equal)
  1107  				} else {
  1108  					c = byte(extension)
  1109  				}
  1110  			} else if int32(j) > int32(l) {
  1111  				c = byte(prefix)
  1112  			} else if int32(prg.modText[j]) < int32(prg.byteMem[w][k]) {
  1113  				c = byte(less)
  1114  			} else {
  1115  				c = byte(greater)
  1116  			}
  1117  		}
  1118  		q = p
  1119  		if int32(c) == less {
  1120  			p = prg.link[q]
  1121  		} else if int32(c) == greater {
  1122  			p = prg.ilk[q]
  1123  		} else {
  1124  			goto found
  1125  		}
  1126  	}
  1127  
  1128  	// Enter a new module name into the tree
  1129  	w = byte(int32(prg.namePtr) % ww)
  1130  	k = prg.bytePtr[w]
  1131  	if int32(k)+int32(l) > maxBytes {
  1132  		prg.stderr.Writeln("! Sorry, ", "byte memory", " capacity exceeded")
  1133  		prg.error1()
  1134  		prg.history = byte(fatalMessage)
  1135  		prg.jumpOut()
  1136  	}
  1137  	if int32(prg.namePtr) > maxNames-ww {
  1138  		prg.stderr.Writeln("! Sorry, ", "name", " capacity exceeded")
  1139  		prg.error1()
  1140  		prg.history = byte(fatalMessage)
  1141  		prg.jumpOut()
  1142  	}
  1143  	p = prg.namePtr
  1144  	if int32(c) == less {
  1145  		prg.link[q] = p
  1146  	} else {
  1147  		prg.ilk[q] = p
  1148  	}
  1149  	prg.link[p] = 0
  1150  	prg.ilk[p] = 0
  1151  	c = byte(equal)
  1152  	prg.equiv[p] = 0
  1153  	for ii := int32(1); ii <= int32(l); ii++ {
  1154  		j = uint16(ii)
  1155  		_ = j
  1156  		prg.byteMem[w][int32(k)+int32(j)-1] = prg.modText[j]
  1157  	}
  1158  	prg.bytePtr[w] = uint16(int32(k) + int32(l))
  1159  	prg.byteStart[int32(prg.namePtr)+ww] = uint16(int32(k) + int32(l))
  1160  	prg.namePtr = uint16(int32(prg.namePtr) + 1)
  1161  
  1162  found:
  1163  	if int32(c) != equal {
  1164  		{
  1165  			prg.stdout.Writeln()
  1166  			prg.stdout.Write("! Incompatible section names")
  1167  			prg.error1()
  1168  		}
  1169  		p = 0
  1170  		// \xref[Incompatible module names]
  1171  	}
  1172  	r = p
  1173  	return r
  1174  }
  1175  
  1176  // 69.
  1177  
  1178  // tangle:pos tangle.web:1218:3:
  1179  
  1180  // The |prefix_lookup| procedure is supposed to find exactly one module
  1181  // name that has |mod_text[1..l]| as a prefix. Actually the algorithm silently
  1182  // accepts also the situation that some module name is a prefix of
  1183  // |mod_text[1..l]|, because the user who painstakingly typed in more than
  1184  // necessary probably doesn't want to be told about the wasted effort.
  1185  func (prg *prg) prefixLookup(l sixteenBits) (r namePointer) { // finds name extension
  1186  	var (
  1187  		c/* less..extension */ byte               // comparison between two names
  1188  		count/* 0..maxNames */ uint16             // the number of hits
  1189  		j/* 0..longestName */ uint16              // index into |mod_text|
  1190  		k/* 0..maxBytes */ uint16                 // index into |byte_mem|
  1191  		w/* 0..ww-1 */ byte                       // segment of |byte_mem|
  1192  		p                             namePointer // current node of the search tree
  1193  		q                             namePointer // another place to resume the search after one branch is done
  1194  		r1                            namePointer // extension found
  1195  	)
  1196  	q = 0
  1197  	p = prg.ilk[0]
  1198  	count = 0
  1199  	r1 = 0 // begin search at root of tree
  1200  	for int32(p) != 0 {
  1201  		{
  1202  			k = prg.byteStart[p]
  1203  			w = byte(int32(p) % ww)
  1204  			c = byte(equal)
  1205  			j = 1
  1206  			for int32(k) < int32(prg.byteStart[int32(p)+ww]) && int32(j) <= int32(l) && int32(prg.modText[j]) == int32(prg.byteMem[w][k]) {
  1207  				k = uint16(int32(k) + 1)
  1208  				j = uint16(int32(j) + 1)
  1209  			}
  1210  			if int32(k) == int32(prg.byteStart[int32(p)+ww]) {
  1211  				if int32(j) > int32(l) {
  1212  					c = byte(equal)
  1213  				} else {
  1214  					c = byte(extension)
  1215  				}
  1216  			} else if int32(j) > int32(l) {
  1217  				c = byte(prefix)
  1218  			} else if int32(prg.modText[j]) < int32(prg.byteMem[w][k]) {
  1219  				c = byte(less)
  1220  			} else {
  1221  				c = byte(greater)
  1222  			}
  1223  		}
  1224  		if int32(c) == less {
  1225  			p = prg.link[p]
  1226  		} else if int32(c) == greater {
  1227  			p = prg.ilk[p]
  1228  		} else {
  1229  			r1 = p
  1230  			count = uint16(int32(count) + 1)
  1231  			q = prg.ilk[p]
  1232  			p = prg.link[p]
  1233  		}
  1234  		if int32(p) == 0 {
  1235  			p = q
  1236  			q = 0
  1237  		}
  1238  	}
  1239  	if int32(count) != 1 {
  1240  		if int32(count) == 0 {
  1241  			prg.stdout.Writeln()
  1242  			prg.stdout.Write("! Name does not match")
  1243  			prg.error1()
  1244  		} else {
  1245  			prg.stdout.Writeln()
  1246  			prg.stdout.Write("! Ambiguous prefix")
  1247  			prg.error1()
  1248  		}
  1249  	}
  1250  	// \xref[Ambiguous prefix]
  1251  	r = r1 // the result will be 0 if there was no match
  1252  	return r
  1253  }
  1254  
  1255  // 72.
  1256  
  1257  // tangle:pos tangle.web:1277:3:
  1258  
  1259  // If the first byte of a token is less than @'200, the token occupies a
  1260  // single byte. Otherwise we make a sixteen-bit token by combining two consecutive
  1261  // bytes |a| and |b|. If |@'200<=a<@'250|, then $(a-@'200)\times2^8+b$ points
  1262  // to an identifier; if |@'250<=a<@'320|, then
  1263  // $(a-@'250)\times2^8+b$ points to a module name; otherwise, i.e., if
  1264  // |@'320<=a<@'400|, then $(a-@'320)\times2^8+b$ is the number of the module
  1265  // in which the current replacement text appears.
  1266  //
  1267  // Codes less than @'200 are 7-bit ASCII codes that represent themselves.
  1268  // In particular, a single-character identifier like `|x|' will be a one-byte
  1269  // token, while all longer identifiers will occupy two bytes.
  1270  //
  1271  // Some of the 7-bit ASCII codes will not be present, however, so we can
  1272  // use them for special purposes. The following symbolic names are used:
  1273  //
  1274  // \yskip\hang |param| denotes insertion of a parameter. This occurs only in
  1275  // the replacement texts of parametric macros, outside of single-quoted strings
  1276  // in those texts.
  1277  //
  1278  // \hang |begin_comment| denotes \.[@\[], which will become either
  1279  // \.[\[] or \.[[].
  1280  //
  1281  // \hang |end_comment| denotes \.[@\]], which will become either
  1282  // \.[\]] or \.[]].
  1283  //
  1284  // \hang |octal| denotes the \.[@\'] that precedes an octal constant.
  1285  //
  1286  // \hang |hex| denotes the \.[@"] that precedes a hexadecimal constant.
  1287  //
  1288  // \hang |check_sum| denotes the \.[@\char'44] that denotes the string pool
  1289  // check sum.
  1290  //
  1291  // \hang |join| denotes the concatenation of adjacent items with no
  1292  // space or line breaks allowed between them (the \.[@\&] operation of \.[WEB]).
  1293  //
  1294  // \hang |double_dot| denotes `\.[..]' in \PASCAL.
  1295  //
  1296  // \hang |verbatim| denotes the \.[@=] that begins a verbatim \PASCAL\ string.
  1297  // The \.[@>] at the end of such a string is also denoted by |verbatim|.
  1298  //
  1299  // \hang |force_line| denotes the \.[@\\] that forces a new line in the
  1300  // \PASCAL\ output.
  1301  // \xref[ASCII code]
  1302  
  1303  // 73.
  1304  
  1305  // tangle:pos tangle.web:1332:3:
  1306  
  1307  // The following procedure is used to enter a two-byte value into
  1308  // |tok_mem| when a replacement text is being generated.
  1309  func (prg *prg) storeTwoBytes(x sixteenBits) {
  1310  	if int32(prg.tokPtr[prg.z])+2 > maxToks {
  1311  		prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  1312  		prg.error1()
  1313  		prg.history = byte(fatalMessage)
  1314  		prg.jumpOut()
  1315  	}
  1316  	prg.tokMem[prg.z][prg.tokPtr[prg.z]] = byte(int32(x) / 0400)          // this could be done by a shift command
  1317  	prg.tokMem[prg.z][int32(prg.tokPtr[prg.z])+1] = byte(int32(x) % 0400) // this could be done by a logical and
  1318  	prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 2)
  1319  }
  1320  
  1321  // 74.
  1322  
  1323  // tangle:pos tangle.web:1343:3:
  1324  
  1325  // When \.[TANGLE] is being operated in debug mode, it has a procedure to display
  1326  // a replacement text in symbolic form. This procedure has not been spruced up to
  1327  // generate a real great format, but at least the results are not as bad as
  1328  // a memory dump.
  1329  //  procedure print_repl( p:text_pointer);
  1330  // var k:0..max_toks; [index into |tok_mem|]
  1331  //  a: sixteen_bits; [current byte(s)]
  1332  //  zp: 0..zz-1; [segment of |tok_mem| being accessed]
  1333  // begin if p>=text_ptr then write('BAD')
  1334  // else  begin k:=tok_start[p]; zp:=p mod zz;
  1335  //   while k<tok_start[p+zz] do
  1336  //     begin a:=tok_mem[zp,k];
  1337  //     if a>=[0200=]128 then
  1338  // [ Display two-byte token starting with |a| ]
  1339  // begin   k:= k+1 ;
  1340  // if a<[0250=]168 then [identifier or string]
  1341  //   begin a:=(a-[0200=]128)*[0400=]256+tok_mem[zp,k]; print_id(a);
  1342  //   if byte_mem[a mod ww,byte_start[a]]=[""""=]34 then write('"')
  1343  //   else write(' ') ;
  1344  //   end
  1345  // else if a<[0320=]208 then [module name]
  1346  //   begin write('@<') ; print_id((a-[0250=]168)*[0400=]256+tok_mem[zp,k]);
  1347  //   write('@>') ;
  1348  //   end
  1349  // else  begin a:=(a-[0320=]208)*[0400=]256+tok_mem[zp,k]; [module number]
  1350  //   write('@', xchr[["["=] 123], a: 1,'@', xchr[["]"=] 125]) ; [can't use right brace
  1351  //     between \&[debug] and \&[gubed]]
  1352  //   end;
  1353  // end
  1354  //
  1355  //     else
  1356  // [ Display one-byte token |a| ]
  1357  // case a of
  1358  // begin_comment: write('@', xchr[["["=] 123]) ;
  1359  // end_comment: write('@', xchr[["]"=] 125]) ; [can't use right brace
  1360  //     between \&[debug] and \&[gubed]]
  1361  // octal: write('@''') ;
  1362  // hex: write('@"') ;
  1363  // check_sum: write(' 271828 ') ;
  1364  // param: write('#') ;
  1365  // ["@"=]64: write('@@') ;
  1366  // verbatim: write('@=') ;
  1367  // force_line: write('@\') ;
  1368  //  else  write( xchr[ a])
  1369  //  end
  1370  //
  1371  // ;
  1372  //       k:= k+1 ;
  1373  //     end;
  1374  //   end;
  1375  // end;
  1376  // [  ]
  1377  
  1378  // 77. Stacks for output
  1379  
  1380  // tangle:pos tangle.web:1396:22:
  1381  
  1382  // Let's make sure that our data structures contain enough information to
  1383  // produce the entire \PASCAL\ program as desired, by working next on the
  1384  // algorithms that actually do produce that program.
  1385  
  1386  // 81.
  1387  
  1388  // tangle:pos tangle.web:1453:3:
  1389  
  1390  // Parameters must also be stacked. They are placed in
  1391  // |tok_mem| just above the other replacement texts, and dummy parameter
  1392  // `names' are placed in |byte_start| just after the other names.
  1393  // The variables |text_ptr| and |tok_ptr[z]| essentially serve as parameter
  1394  // stack pointers during the output phase, so there is no need for a separate
  1395  // data structure to handle this problem.
  1396  
  1397  // 84.
  1398  
  1399  // tangle:pos tangle.web:1479:3:
  1400  
  1401  // When the replacement text for name |p| is to be inserted into the output,
  1402  // the following subroutine is called to save the old level of output and get
  1403  // the new one going.
  1404  func (prg *prg) pushLevel(p namePointer) {
  1405  	if int32(prg.stackPtr) == stackSize {
  1406  		prg.stderr.Writeln("! Sorry, ", "stack", " capacity exceeded")
  1407  		prg.error1()
  1408  		prg.history = byte(fatalMessage)
  1409  		prg.jumpOut()
  1410  	} else {
  1411  		prg.stack[prg.stackPtr-1] = prg.curState // save |cur_end|, |cur_byte|, etc.
  1412  		prg.stackPtr = byte(int32(prg.stackPtr) + 1)
  1413  		prg.curState.nameField = p
  1414  		prg.curState.replField = prg.equiv[p]
  1415  		prg.zo = byte(int32(prg.curState.replField) % zz)
  1416  		prg.curState.byteField = prg.tokStart[prg.curState.replField]
  1417  		prg.curState.endField = prg.tokStart[int32(prg.curState.replField)+zz]
  1418  		prg.curState.modField = 0
  1419  	}
  1420  }
  1421  
  1422  // 85.
  1423  
  1424  // tangle:pos tangle.web:1493:3:
  1425  
  1426  // When we come to the end of a replacement text, the |pop_level| subroutine
  1427  // does the right thing: It either moves to the continuation of this replacement
  1428  // text or returns the state to the most recently stacked level. Part of this
  1429  // subroutine, which updates the parameter stack, will be given later when we
  1430  // study the parameter stack in more detail.
  1431  func (prg *prg) popLevel() {
  1432  	if int32(prg.textLink[prg.curState.replField]) == 0 {
  1433  		if int32(prg.ilk[prg.curState.nameField]) == parametric {
  1434  			prg.namePtr = uint16(int32(prg.namePtr) - 1)
  1435  			prg.textPtr = uint16(int32(prg.textPtr) - 1)
  1436  			prg.z = byte(int32(prg.textPtr) % zz)
  1437  			//	if tok_ptr[z]>max_tok_ptr[z] then max_tok_ptr[z]:=tok_ptr[z];
  1438  			//
  1439  			// [  ]
  1440  			// the maximum value of |tok_ptr| occurs just before parameter popping
  1441  			prg.tokPtr[prg.z] = prg.tokStart[prg.textPtr]
  1442  			//    byte_ptr[ name_ptr  mod  ww]:= byte_ptr[ name_ptr  mod  ww]-1 ; [  ]
  1443  		}
  1444  	} else if int32(prg.textLink[prg.curState.replField]) < maxTexts {
  1445  		prg.curState.replField = prg.textLink[prg.curState.replField] // we will stay on the same level
  1446  		prg.zo = byte(int32(prg.curState.replField) % zz)
  1447  		prg.curState.byteField = prg.tokStart[prg.curState.replField]
  1448  		prg.curState.endField = prg.tokStart[int32(prg.curState.replField)+zz]
  1449  
  1450  		goto exit
  1451  	}
  1452  	prg.stackPtr = byte(int32(prg.stackPtr) - 1) // we will go down to the previous level
  1453  	if int32(prg.stackPtr) > 0 {
  1454  		prg.curState = prg.stack[prg.stackPtr-1]
  1455  		prg.zo = byte(int32(prg.curState.replField) % zz)
  1456  	}
  1457  
  1458  exit:
  1459  }
  1460  
  1461  // 87.
  1462  
  1463  // tangle:pos tangle.web:1536:3:
  1464  
  1465  // If |get_output| finds that no more output remains, it returns the value zero.
  1466  func (prg *prg) getOutput() (r sixteenBits) {
  1467  	var (
  1468  		a                         sixteenBits // value of current byte
  1469  		b                         eightBits   // byte being copied
  1470  		bal                       sixteenBits // excess of \.( versus \.) while copying a parameter
  1471  		k/* 0..maxBytes */ uint16             // index into |byte_mem|
  1472  		w/* 0..ww-1 */ byte                   // segment of |byte_mem|
  1473  	)
  1474  restart:
  1475  	if int32(prg.stackPtr) == 0 {
  1476  		a = 0
  1477  		goto found
  1478  	}
  1479  	if int32(prg.curState.byteField) == int32(prg.curState.endField) {
  1480  		prg.curVal = -int32(prg.curState.modField)
  1481  		prg.popLevel()
  1482  		if prg.curVal == 0 {
  1483  			goto restart
  1484  		}
  1485  		a = uint16(moduleNumber)
  1486  		goto found
  1487  	}
  1488  	a = uint16(prg.tokMem[prg.zo][prg.curState.byteField])
  1489  	prg.curState.byteField = uint16(int32(prg.curState.byteField) + 1)
  1490  	if int32(a) < 0200 {
  1491  		if int32(a) == param {
  1492  			prg.pushLevel(namePointer(int32(prg.namePtr) - 1))
  1493  			goto restart
  1494  		} else {
  1495  			goto found
  1496  		}
  1497  	}
  1498  	a = uint16((int32(a)-0200)*0400 + int32(prg.tokMem[prg.zo][prg.curState.byteField]))
  1499  	prg.curState.byteField = uint16(int32(prg.curState.byteField) + 1)
  1500  	if int32(a) < 024000 {
  1501  		switch prg.ilk[a] {
  1502  		case normal:
  1503  			prg.curVal = int32(a)
  1504  			a = uint16(identifier)
  1505  
  1506  		case numeric:
  1507  			prg.curVal = int32(prg.equiv[a]) - 0100000
  1508  			a = uint16(number)
  1509  
  1510  		case simple:
  1511  			prg.pushLevel(a)
  1512  			goto restart
  1513  
  1514  		case parametric:
  1515  			for int32(prg.curState.byteField) == int32(prg.curState.endField) && int32(prg.stackPtr) > 0 {
  1516  				prg.popLevel()
  1517  			}
  1518  			if int32(prg.stackPtr) == 0 || int32(prg.tokMem[prg.zo][prg.curState.byteField]) != '(' {
  1519  				{
  1520  					prg.stdout.Writeln()
  1521  					prg.stdout.Write("! No parameter given for ")
  1522  				}
  1523  				prg.printId(a)
  1524  				prg.error1()
  1525  				// \xref[No parameter given for macro]
  1526  
  1527  				// \xref[No parameter given for macro]
  1528  				goto restart
  1529  			}
  1530  
  1531  			// Copy the parameter into |tok_mem|
  1532  			bal = 1
  1533  			prg.curState.byteField = uint16(int32(prg.curState.byteField) + 1) // skip the opening `\.('
  1534  			for true {
  1535  				b = prg.tokMem[prg.zo][prg.curState.byteField]
  1536  				prg.curState.byteField = uint16(int32(prg.curState.byteField) + 1)
  1537  				if int32(b) == param {
  1538  					prg.storeTwoBytes(sixteenBits(int32(prg.namePtr) + 077777))
  1539  				} else {
  1540  					if int32(b) >= 0200 {
  1541  						{
  1542  							if int32(prg.tokPtr[prg.z]) == maxToks {
  1543  								prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  1544  								prg.error1()
  1545  								prg.history = byte(fatalMessage)
  1546  								prg.jumpOut()
  1547  							}
  1548  							prg.tokMem[prg.z][prg.tokPtr[prg.z]] = b
  1549  							prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  1550  						}
  1551  						b = prg.tokMem[prg.zo][prg.curState.byteField]
  1552  						prg.curState.byteField = uint16(int32(prg.curState.byteField) + 1)
  1553  					} else {
  1554  						switch b {
  1555  						case '(':
  1556  							bal = uint16(int32(bal) + 1)
  1557  						// ")"=
  1558  						case ')':
  1559  							bal = uint16(int32(bal) - 1)
  1560  							if int32(bal) == 0 {
  1561  								goto done
  1562  							}
  1563  
  1564  						// "'"=
  1565  						case '\'':
  1566  							for {
  1567  								{
  1568  									if int32(prg.tokPtr[prg.z]) == maxToks {
  1569  										prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  1570  										prg.error1()
  1571  										prg.history = byte(fatalMessage)
  1572  										prg.jumpOut()
  1573  									}
  1574  									prg.tokMem[prg.z][prg.tokPtr[prg.z]] = b
  1575  									prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  1576  								}
  1577  								b = prg.tokMem[prg.zo][prg.curState.byteField]
  1578  								prg.curState.byteField = uint16(int32(prg.curState.byteField) + 1)
  1579  								if int32(b) == '\'' {
  1580  									break
  1581  								}
  1582  							}
  1583  							// copy string, don't change |bal|
  1584  						default:
  1585  						}
  1586  					}
  1587  					{
  1588  						if int32(prg.tokPtr[prg.z]) == maxToks {
  1589  							prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  1590  							prg.error1()
  1591  							prg.history = byte(fatalMessage)
  1592  							prg.jumpOut()
  1593  						}
  1594  						prg.tokMem[prg.z][prg.tokPtr[prg.z]] = b
  1595  						prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  1596  					}
  1597  				}
  1598  			}
  1599  
  1600  		done:
  1601  			;
  1602  			prg.equiv[prg.namePtr] = prg.textPtr
  1603  			prg.ilk[prg.namePtr] = uint16(simple)
  1604  			w = byte(int32(prg.namePtr) % ww)
  1605  			k = prg.bytePtr[w]
  1606  			//	if k=max_bytes then begin writeln( stderr,'! Sorry, ','byte memory',' capacity exceeded') ; error; history:=fatal_message ; jump_out; end  [ \xref[Sorry, x capacity exceeded] ] ;
  1607  			//
  1608  			// byte_mem[w,k]:=["#"=]35;   k:= k+1 ; byte_ptr[w]:=k;
  1609  			// [  ]
  1610  			// this code has set the parameter identifier for debugging printouts
  1611  			if int32(prg.namePtr) > maxNames-ww {
  1612  				prg.stderr.Writeln("! Sorry, ", "name", " capacity exceeded")
  1613  				prg.error1()
  1614  				prg.history = byte(fatalMessage)
  1615  				prg.jumpOut()
  1616  			}
  1617  			prg.byteStart[int32(prg.namePtr)+ww] = k
  1618  			prg.namePtr = uint16(int32(prg.namePtr) + 1)
  1619  			if int32(prg.textPtr) > maxTexts-zz {
  1620  				prg.stderr.Writeln("! Sorry, ", "text", " capacity exceeded")
  1621  				prg.error1()
  1622  				prg.history = byte(fatalMessage)
  1623  				prg.jumpOut()
  1624  			}
  1625  			prg.textLink[prg.textPtr] = 0
  1626  			prg.tokStart[int32(prg.textPtr)+zz] = prg.tokPtr[prg.z]
  1627  			prg.textPtr = uint16(int32(prg.textPtr) + 1)
  1628  			prg.z = byte(int32(prg.textPtr) % zz)
  1629  			prg.pushLevel(a)
  1630  			goto restart
  1631  
  1632  		default:
  1633  			prg.stderr.Writeln("! This can't happen (", "output", ")")
  1634  			prg.error1()
  1635  			prg.history = byte(fatalMessage)
  1636  			prg.jumpOut() // \xref[This can't happen]
  1637  		}
  1638  
  1639  		goto found
  1640  	}
  1641  	if int32(a) < 050000 {
  1642  		a = uint16(int32(a) - 024000)
  1643  		if int32(prg.equiv[a]) != 0 {
  1644  			prg.pushLevel(a)
  1645  		} else if int32(a) != 0 {
  1646  			{
  1647  				prg.stdout.Writeln()
  1648  				prg.stdout.Write("! Not present: <")
  1649  			}
  1650  			prg.printId(a)
  1651  			prg.stdout.Write(">")
  1652  			prg.error1()
  1653  			// \xref[Not present: <section name>]
  1654  		}
  1655  
  1656  		goto restart
  1657  	}
  1658  	prg.curVal = int32(a) - 050000
  1659  	a = uint16(moduleNumber)
  1660  	prg.curState.modField = uint16(prg.curVal)
  1661  
  1662  found:
  1663  	r = a
  1664  	return r
  1665  }
  1666  
  1667  // 97.
  1668  
  1669  // tangle:pos tangle.web:1800:3:
  1670  
  1671  // Here is a routine that is invoked when |out_ptr>line_length|
  1672  // or when it is time to flush out the final line. The |flush_buffer| procedure
  1673  // often writes out the line up to the current |break_ptr| position, then moves the
  1674  // remaining information to the front of |out_buf|. However, it prefers to
  1675  // write only up to |semi_ptr|, if the residual line won't be too long.
  1676  func (prg *prg) flushBuffer() { // writes one line to output file
  1677  	var (
  1678  		k/* 0..outBufSize */ byte // index into |out_buf|
  1679  		b/* 0..outBufSize */ byte // value of |break_ptr| upon entry
  1680  	)
  1681  	b = prg.breakPtr
  1682  	if int32(prg.semiPtr) != 0 && int32(prg.outPtr)-int32(prg.semiPtr) <= lineLength {
  1683  		prg.breakPtr = prg.semiPtr
  1684  	}
  1685  	for ii := int32(1); ii <= int32(prg.breakPtr); ii++ {
  1686  		k = byte(ii)
  1687  		_ = k
  1688  		prg.pascalFile.Write(string(rune(prg.xchr[prg.outBuf[int32(k)-1]])))
  1689  	}
  1690  	prg.pascalFile.Writeln()
  1691  	prg.line = prg.line + 1
  1692  	if prg.line%100 == 0 {
  1693  		prg.stdout.Write(".")
  1694  		if prg.line%500 == 0 {
  1695  			prg.stdout.Write(prg.line, knuth.WriteWidth(1))
  1696  		}
  1697  		// progress report
  1698  	}
  1699  	if int32(prg.breakPtr) < int32(prg.outPtr) {
  1700  		if int32(prg.outBuf[prg.breakPtr]) == ' ' {
  1701  			prg.breakPtr = byte(int32(prg.breakPtr) + 1) // drop space at break
  1702  			if int32(prg.breakPtr) > int32(b) {
  1703  				b = prg.breakPtr
  1704  			}
  1705  		}
  1706  		for ii := int32(prg.breakPtr); ii <= int32(prg.outPtr)-1; ii++ {
  1707  			k = byte(ii)
  1708  			_ = k
  1709  			prg.outBuf[int32(k)-int32(prg.breakPtr)] = prg.outBuf[k]
  1710  		}
  1711  	}
  1712  	prg.outPtr = byte(int32(prg.outPtr) - int32(prg.breakPtr))
  1713  	prg.breakPtr = byte(int32(b) - int32(prg.breakPtr))
  1714  	prg.semiPtr = 0
  1715  	if int32(prg.outPtr) > lineLength {
  1716  		{
  1717  			prg.stdout.Writeln()
  1718  			prg.stdout.Write("! Long line must be truncated")
  1719  			prg.error1()
  1720  		}
  1721  		prg.outPtr = byte(lineLength)
  1722  		// \xref[Long line must be truncated]
  1723  	}
  1724  }
  1725  
  1726  // 99.
  1727  
  1728  // tangle:pos tangle.web:1840:3:
  1729  
  1730  // Another simple and useful routine appends the decimal equivalent of
  1731  // a nonnegative integer to the output buffer.
  1732  func (prg *prg) appVal(v int32) { // puts |v| into buffer, assumes |v>=0|
  1733  	var (
  1734  		k /* 0..outBufSize */ byte // index into |out_buf|
  1735  	)
  1736  	k = byte(outBufSize) // first we put the digits at the very end of |out_buf|
  1737  	for {
  1738  		prg.outBuf[k] = byte(v % 10)
  1739  		v = v / 10
  1740  		k = byte(int32(k) - 1)
  1741  		if v == 0 {
  1742  			break
  1743  		}
  1744  	}
  1745  	for {
  1746  		k = byte(int32(k) + 1)
  1747  		{
  1748  			prg.outBuf[prg.outPtr] = byte(int32(prg.outBuf[k]) + '0')
  1749  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1750  		}
  1751  		if int32(k) == outBufSize {
  1752  			break
  1753  		}
  1754  	} // then we append them, most significant first
  1755  }
  1756  
  1757  // 101.
  1758  
  1759  // tangle:pos tangle.web:1878:3:
  1760  
  1761  // A slightly subtle point in the following code is that the user may ask
  1762  // for a |join| operation (i.e., \.[@\&]) following whatever is being sent
  1763  // out.  We will see later that |join| is implemented in part by calling
  1764  // |send_out(frac,0)|.
  1765  func (prg *prg) sendOut(t eightBits, v sixteenBits) {
  1766  	var (
  1767  		k /* 0..lineLength */ byte // index into |out_contrib|
  1768  	)
  1769  	// Get the buffer ready for appending the new information
  1770  restart:
  1771  	switch prg.outState {
  1772  	case numOrId:
  1773  		if int32(t) != frac {
  1774  			prg.breakPtr = prg.outPtr
  1775  			if int32(t) == ident {
  1776  				prg.outBuf[prg.outPtr] = ' '
  1777  				prg.outPtr = byte(int32(prg.outPtr) + 1)
  1778  			}
  1779  		}
  1780  	case sign:
  1781  		{
  1782  			prg.outBuf[prg.outPtr] = byte(',' - prg.outApp)
  1783  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1784  		}
  1785  		if int32(prg.outPtr) > lineLength {
  1786  			prg.flushBuffer()
  1787  		}
  1788  		prg.breakPtr = prg.outPtr
  1789  
  1790  	case signVal, signValSign:
  1791  		if prg.outVal < 0 || prg.outVal == 0 && int32(prg.lastSign) < 0 {
  1792  			prg.outBuf[prg.outPtr] = '-'
  1793  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1794  		} else if int32(prg.outSign) > 0 {
  1795  			prg.outBuf[prg.outPtr] = prg.outSign
  1796  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1797  		}
  1798  		prg.appVal(abs(prg.outVal))
  1799  		if int32(prg.outPtr) > lineLength {
  1800  			prg.flushBuffer()
  1801  		}
  1802  
  1803  		prg.outState = byte(int32(prg.outState) - 2)
  1804  		goto restart
  1805  
  1806  	case signValVal:
  1807  		// Reduce |sign_val_val| to |sign_val| and |goto restart|
  1808  		if int32(t) == frac || (int32(t) == ident && int32(v) == 3 && (int32(prg.outContrib[1-1]) == 'D' && int32(prg.outContrib[2-1]) == 'I' && int32(prg.outContrib[3-1]) == 'V' || int32(prg.outContrib[1-1]) == 'M' && int32(prg.outContrib[2-1]) == 'O' && int32(prg.outContrib[3-1]) == 'D') || int32(t) == misc && (int32(v) == '*' || int32(v) == '/')) {
  1809  			if prg.outVal < 0 || prg.outVal == 0 && int32(prg.lastSign) < 0 {
  1810  				prg.outBuf[prg.outPtr] = '-'
  1811  				prg.outPtr = byte(int32(prg.outPtr) + 1)
  1812  			} else if int32(prg.outSign) > 0 {
  1813  				prg.outBuf[prg.outPtr] = prg.outSign
  1814  				prg.outPtr = byte(int32(prg.outPtr) + 1)
  1815  			}
  1816  			prg.appVal(abs(prg.outVal))
  1817  			if int32(prg.outPtr) > lineLength {
  1818  				prg.flushBuffer()
  1819  			}
  1820  
  1821  			prg.outSign = '+'
  1822  			prg.outVal = prg.outApp
  1823  		} else {
  1824  			prg.outVal = prg.outVal + prg.outApp
  1825  		}
  1826  		prg.outState = byte(signVal)
  1827  		goto restart
  1828  
  1829  	case misc:
  1830  		if int32(t) != frac {
  1831  			prg.breakPtr = prg.outPtr
  1832  		}
  1833  
  1834  	default: // this is for |unbreakable| state
  1835  	}
  1836  	if int32(t) != misc {
  1837  		for ii := int32(1); ii <= int32(v); ii++ {
  1838  			k = byte(ii)
  1839  			_ = k
  1840  			prg.outBuf[prg.outPtr] = prg.outContrib[k-1]
  1841  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1842  		}
  1843  	} else {
  1844  		prg.outBuf[prg.outPtr] = byte(v)
  1845  		prg.outPtr = byte(int32(prg.outPtr) + 1)
  1846  	}
  1847  	if int32(prg.outPtr) > lineLength {
  1848  		prg.flushBuffer()
  1849  	}
  1850  	if int32(t) == misc && (int32(v) == ';' || int32(v) == '}') {
  1851  		prg.semiPtr = prg.outPtr
  1852  		prg.breakPtr = prg.outPtr
  1853  	}
  1854  	if int32(t) >= ident {
  1855  		prg.outState = byte(numOrId)
  1856  	} else {
  1857  		prg.outState = byte(misc)
  1858  	}
  1859  }
  1860  
  1861  // 106.
  1862  
  1863  // tangle:pos tangle.web:1942:3:
  1864  
  1865  // The following routine is called with $v=\pm1$ when a plus or minus sign is
  1866  // appended to the output. It extends \PASCAL\ to allow repeated signs
  1867  // (e.g., `\.[--]' is equivalent to `\.+'), rather than to give an error message.
  1868  // The signs following `\.E' in real constants are treated as part of a fraction,
  1869  // so they are not seen by this routine.
  1870  func (prg *prg) sendSign(v int32) {
  1871  	switch prg.outState {
  1872  	case sign, signValSign:
  1873  		prg.outApp = prg.outApp * v
  1874  	case signVal:
  1875  		prg.outApp = v
  1876  		prg.outState = byte(signValSign)
  1877  
  1878  	case signValVal:
  1879  		prg.outVal = prg.outVal + prg.outApp
  1880  		prg.outApp = v
  1881  		prg.outState = byte(signValSign)
  1882  
  1883  	default:
  1884  		prg.breakPtr = prg.outPtr
  1885  		prg.outApp = v
  1886  		prg.outState = byte(sign)
  1887  
  1888  	}
  1889  
  1890  	prg.lastSign = int8(prg.outApp)
  1891  }
  1892  
  1893  // 107.
  1894  
  1895  // tangle:pos tangle.web:1962:3:
  1896  
  1897  // When a (signed) integer value is to be output, we call |send_val|.
  1898  func (prg *prg) sendVal(v int32) {
  1899  	switch prg.outState {
  1900  	case numOrId:
  1901  		if int32(prg.outPtr) == int32(prg.breakPtr)+3 || int32(prg.outPtr) == int32(prg.breakPtr)+4 && int32(prg.outBuf[prg.breakPtr]) == ' ' {
  1902  			if int32(prg.outBuf[int32(prg.outPtr)-3]) == 'D' && int32(prg.outBuf[int32(prg.outPtr)-2]) == 'I' && int32(prg.outBuf[int32(prg.outPtr)-1]) == 'V' || int32(prg.outBuf[int32(prg.outPtr)-3]) == 'M' && int32(prg.outBuf[int32(prg.outPtr)-2]) == 'O' && int32(prg.outBuf[int32(prg.outPtr)-1]) == 'D' {
  1903  				goto badCase
  1904  			}
  1905  		}
  1906  		prg.outSign = ' '
  1907  		prg.outState = byte(signVal)
  1908  		prg.outVal = v
  1909  		prg.breakPtr = prg.outPtr
  1910  		prg.lastSign = int8(+1)
  1911  
  1912  	case misc:
  1913  		if int32(prg.outPtr) == int32(prg.breakPtr)+1 && (int32(prg.outBuf[prg.breakPtr]) == '*' || int32(prg.outBuf[prg.breakPtr]) == '/') {
  1914  			goto badCase
  1915  		}
  1916  		prg.outSign = 0
  1917  		prg.outState = byte(signVal)
  1918  		prg.outVal = v
  1919  		prg.breakPtr = prg.outPtr
  1920  		prg.lastSign = int8(+1)
  1921  
  1922  	// \4
  1923  	// Handle cases of |send_val| when |out_state| contains a sign
  1924  	case sign:
  1925  		prg.outSign = '+'
  1926  		prg.outState = byte(signVal)
  1927  		prg.outVal = prg.outApp * v
  1928  
  1929  	case signVal:
  1930  		prg.outState = byte(signValVal)
  1931  		prg.outApp = v
  1932  		{
  1933  			prg.stdout.Writeln()
  1934  			prg.stdout.Write("! Two numbers occurred without a sign between them")
  1935  			prg.error1()
  1936  		}
  1937  
  1938  	case signValSign:
  1939  		prg.outState = byte(signValVal)
  1940  		prg.outApp = prg.outApp * v
  1941  
  1942  	case signValVal:
  1943  		prg.outVal = prg.outVal + prg.outApp
  1944  		prg.outApp = v
  1945  		{
  1946  			prg.stdout.Writeln()
  1947  			prg.stdout.Write("! Two numbers occurred without a sign between them")
  1948  			prg.error1()
  1949  		}
  1950  	// \xref[Two numbers occurred...]
  1951  
  1952  	default:
  1953  		goto badCase
  1954  	}
  1955  
  1956  	goto exit
  1957  
  1958  badCase:
  1959  	if v >= 0 {
  1960  		if int32(prg.outState) == numOrId {
  1961  			prg.breakPtr = prg.outPtr
  1962  			{
  1963  				prg.outBuf[prg.outPtr] = ' '
  1964  				prg.outPtr = byte(int32(prg.outPtr) + 1)
  1965  			}
  1966  		}
  1967  		prg.appVal(v)
  1968  		if int32(prg.outPtr) > lineLength {
  1969  			prg.flushBuffer()
  1970  		}
  1971  		prg.outState = byte(numOrId)
  1972  	} else {
  1973  		{
  1974  			prg.outBuf[prg.outPtr] = '('
  1975  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1976  		}
  1977  		{
  1978  			prg.outBuf[prg.outPtr] = '-'
  1979  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1980  		}
  1981  		prg.appVal(-v)
  1982  		{
  1983  			prg.outBuf[prg.outPtr] = ')'
  1984  			prg.outPtr = byte(int32(prg.outPtr) + 1)
  1985  		}
  1986  		if int32(prg.outPtr) > lineLength {
  1987  			prg.flushBuffer()
  1988  		}
  1989  		prg.outState = byte(misc)
  1990  	}
  1991  
  1992  exit:
  1993  }
  1994  
  1995  // 113.
  1996  
  1997  // tangle:pos tangle.web:2040:3:
  1998  
  1999  // A many-way switch is used to send the output:
  2000  func (prg *prg) sendTheOutput() {
  2001  	var (
  2002  		curChar                   eightBits // the latest character received
  2003  		k/* 0..lineLength */ byte           // index into |out_contrib|
  2004  		j/* 0..maxBytes */ uint16           // index into |byte_mem|
  2005  		w/* 0..ww-1 */ byte                 // segment of |byte_mem|
  2006  		n                         int32     // number being scanned
  2007  	)
  2008  	for int32(prg.stackPtr) > 0 {
  2009  		curChar = byte(prg.getOutput())
  2010  
  2011  	reswitch:
  2012  		switch curChar {
  2013  		case 0: // this case might arise if output ends unexpectedly
  2014  		// \4
  2015  		// Cases related to identifiers
  2016  		// "A"=
  2017  		case 'A', 'Z' - 24, 'Z' - 23, 'Z' - 22,
  2018  			'Z' - 21, 'Z' - 20, 'Z' - 19, 'Z' - 18,
  2019  			'Z' - 17, 'Z' - 16, 'Z' - 15, 'Z' - 14,
  2020  			'Z' - 13, 'Z' - 12, 'Z' - 11, 'Z' - 10,
  2021  			'Z' - 9, 'Z' - 8, 'Z' - 7, 'Z' - 6,
  2022  			'Z' - 5, 'Z' - 4, 'Z' - 3, 'Z' - 2,
  2023  			'Z' - 1, 'Z':
  2024  			prg.outContrib[1-1] = curChar
  2025  			prg.sendOut(eightBits(ident), sixteenBits(1))
  2026  
  2027  		// "a"=
  2028  		case 'a', 'z' - 24, 'z' - 23, 'z' - 22,
  2029  			'z' - 21, 'z' - 20, 'z' - 19, 'z' - 18,
  2030  			'z' - 17, 'z' - 16, 'z' - 15, 'z' - 14,
  2031  			'z' - 13, 'z' - 12, 'z' - 11, 'z' - 10,
  2032  			'z' - 9, 'z' - 8, 'z' - 7, 'z' - 6,
  2033  			'z' - 5, 'z' - 4, 'z' - 3, 'z' - 2,
  2034  			'z' - 1, 'z':
  2035  			prg.outContrib[1-1] = byte(int32(curChar) - 040)
  2036  			prg.sendOut(eightBits(ident), sixteenBits(1))
  2037  
  2038  		case identifier:
  2039  			k = 0
  2040  			j = prg.byteStart[prg.curVal]
  2041  			w = byte(prg.curVal % ww)
  2042  			for int32(k) < maxIdLength && int32(j) < int32(prg.byteStart[prg.curVal+ww]) {
  2043  				k = byte(int32(k) + 1)
  2044  				prg.outContrib[k-1] = prg.byteMem[w][j]
  2045  				j = uint16(int32(j) + 1)
  2046  				if int32(prg.outContrib[k-1]) >= 'a' {
  2047  					prg.outContrib[k-1] = byte(int32(prg.outContrib[k-1]) - 040)
  2048  				} else if int32(prg.outContrib[k-1]) == '_' {
  2049  					k = byte(int32(k) - 1)
  2050  				}
  2051  			}
  2052  			prg.sendOut(eightBits(ident), sixteenBits(k))
  2053  
  2054  		// \4
  2055  		// Cases related to constants, possibly leading to |get_fraction| or |reswitch|
  2056  		// "0"=
  2057  		case '0', '1', '2', '3',
  2058  			'4', '5', '6', '7',
  2059  			'8', '9':
  2060  			n = 0
  2061  			for {
  2062  				curChar = byte(int32(curChar) - '0')
  2063  				if n >= 01463146314 {
  2064  					prg.stdout.Writeln()
  2065  					prg.stdout.Write("! Constant too big")
  2066  					prg.error1()
  2067  				} else {
  2068  					n = 10*n + int32(curChar)
  2069  				}
  2070  				curChar = byte(prg.getOutput())
  2071  				if int32(curChar) > '9' || int32(curChar) < '0' {
  2072  					break
  2073  				}
  2074  			}
  2075  			prg.sendVal(n)
  2076  			k = 0
  2077  			if int32(curChar) == 'e' {
  2078  				curChar = 'E'
  2079  			}
  2080  			// \xref[uppercase]
  2081  			if int32(curChar) == 'E' {
  2082  				goto getFraction
  2083  			} else {
  2084  				goto reswitch
  2085  			}
  2086  
  2087  		case checkSum:
  2088  			prg.sendVal(prg.poolCheckSum)
  2089  		case octal:
  2090  			n = 0
  2091  			curChar = '0'
  2092  			for {
  2093  				curChar = byte(int32(curChar) - '0')
  2094  				if n >= 02000000000 {
  2095  					prg.stdout.Writeln()
  2096  					prg.stdout.Write("! Constant too big")
  2097  					prg.error1()
  2098  				} else {
  2099  					n = 8*n + int32(curChar)
  2100  				}
  2101  				curChar = byte(prg.getOutput())
  2102  				if int32(curChar) > '7' || int32(curChar) < '0' {
  2103  					break
  2104  				}
  2105  			}
  2106  			prg.sendVal(n)
  2107  			goto reswitch
  2108  
  2109  		case hex:
  2110  			n = 0
  2111  			curChar = '0'
  2112  			for {
  2113  				if int32(curChar) >= 'A' {
  2114  					curChar = byte(int32(curChar) + 10 - 'A')
  2115  				} else {
  2116  					curChar = byte(int32(curChar) - '0')
  2117  				}
  2118  				if n >= 01000000000 {
  2119  					prg.stdout.Writeln()
  2120  					prg.stdout.Write("! Constant too big")
  2121  					prg.error1()
  2122  				} else {
  2123  					n = 16*n + int32(curChar)
  2124  				}
  2125  				curChar = byte(prg.getOutput())
  2126  				if int32(curChar) > 'F' || int32(curChar) < '0' || int32(curChar) > '9' && int32(curChar) < 'A' {
  2127  					break
  2128  				}
  2129  			}
  2130  			prg.sendVal(n)
  2131  			goto reswitch
  2132  
  2133  		case number:
  2134  			prg.sendVal(prg.curVal)
  2135  		// "."=
  2136  		case '.':
  2137  			k = 1
  2138  			prg.outContrib[1-1] = '.'
  2139  			curChar = byte(prg.getOutput())
  2140  			if int32(curChar) == '.' {
  2141  				prg.outContrib[2-1] = '.'
  2142  				prg.sendOut(eightBits(str), sixteenBits(2))
  2143  			} else if int32(curChar) >= '0' && int32(curChar) <= '9' {
  2144  				goto getFraction
  2145  			} else {
  2146  				prg.sendOut(eightBits(misc), sixteenBits('.'))
  2147  				goto reswitch
  2148  			}
  2149  
  2150  		// "+"=
  2151  		case '+', '-':
  2152  			prg.sendSign(',' - int32(curChar))
  2153  		// \4
  2154  		// Cases like \.[<>] and \.[:=]
  2155  		case andSign:
  2156  			prg.outContrib[1-1] = 'A'
  2157  			prg.outContrib[2-1] = 'N'
  2158  			prg.outContrib[3-1] = 'D'
  2159  			// \xref[uppercase]
  2160  			prg.sendOut(eightBits(ident), sixteenBits(3))
  2161  
  2162  		case notSign:
  2163  			prg.outContrib[1-1] = 'N'
  2164  			prg.outContrib[2-1] = 'O'
  2165  			prg.outContrib[3-1] = 'T'
  2166  			prg.sendOut(eightBits(ident), sixteenBits(3))
  2167  
  2168  		case setElementSign:
  2169  			prg.outContrib[1-1] = 'I'
  2170  			prg.outContrib[2-1] = 'N'
  2171  			prg.sendOut(eightBits(ident), sixteenBits(2))
  2172  
  2173  		case orSign:
  2174  			prg.outContrib[1-1] = 'O'
  2175  			prg.outContrib[2-1] = 'R'
  2176  			prg.sendOut(eightBits(ident), sixteenBits(2))
  2177  
  2178  		case leftArrow:
  2179  			prg.outContrib[1-1] = ':'
  2180  			prg.outContrib[2-1] = '='
  2181  			prg.sendOut(eightBits(str), sixteenBits(2))
  2182  
  2183  		case notEqual:
  2184  			prg.outContrib[1-1] = '<'
  2185  			prg.outContrib[2-1] = '>'
  2186  			prg.sendOut(eightBits(str), sixteenBits(2))
  2187  
  2188  		case lessOrEqual:
  2189  			prg.outContrib[1-1] = '<'
  2190  			prg.outContrib[2-1] = '='
  2191  			prg.sendOut(eightBits(str), sixteenBits(2))
  2192  
  2193  		case greaterOrEqual:
  2194  			prg.outContrib[1-1] = '>'
  2195  			prg.outContrib[2-1] = '='
  2196  			prg.sendOut(eightBits(str), sixteenBits(2))
  2197  
  2198  		case equivalenceSign:
  2199  			prg.outContrib[1-1] = '='
  2200  			prg.outContrib[2-1] = '='
  2201  			prg.sendOut(eightBits(str), sixteenBits(2))
  2202  
  2203  		case doubleDot:
  2204  			prg.outContrib[1-1] = '.'
  2205  			prg.outContrib[2-1] = '.'
  2206  			prg.sendOut(eightBits(str), sixteenBits(2))
  2207  
  2208  		// "'"=
  2209  		case '\'':
  2210  			// Send a string, |goto reswitch|
  2211  			k = 1
  2212  			prg.outContrib[1-1] = '\''
  2213  			for {
  2214  				if int32(k) < lineLength {
  2215  					k = byte(int32(k) + 1)
  2216  				}
  2217  				prg.outContrib[k-1] = byte(prg.getOutput())
  2218  				if int32(prg.outContrib[k-1]) == '\'' || int32(prg.stackPtr) == 0 {
  2219  					break
  2220  				}
  2221  			}
  2222  			if int32(k) == lineLength {
  2223  				prg.stdout.Writeln()
  2224  				prg.stdout.Write("! String too long")
  2225  				prg.error1()
  2226  			}
  2227  			// \xref[String too long]
  2228  			prg.sendOut(eightBits(str), sixteenBits(k))
  2229  			curChar = byte(prg.getOutput())
  2230  			if int32(curChar) == '\'' {
  2231  				prg.outState = byte(unbreakable)
  2232  			}
  2233  
  2234  			goto reswitch
  2235  
  2236  		// Other printable characters
  2237  		// "!"=
  2238  		case '!', '"', '#', '$',
  2239  			'%', '&', '(', ')',
  2240  			'*', ',', '/', ':',
  2241  			';', '<', '=', '>',
  2242  			'?', '@', '[', '\\',
  2243  			']', '^', '_', '`',
  2244  			'{', '|':
  2245  			prg.sendOut(eightBits(misc), sixteenBits(curChar))
  2246  		// \4
  2247  		// Cases involving \.[@\[] and \.[@\]]
  2248  		case beginComment:
  2249  			if int32(prg.braceLevel) == 0 {
  2250  				prg.sendOut(eightBits(misc), sixteenBits('{'))
  2251  			} else {
  2252  				prg.sendOut(eightBits(misc), sixteenBits('['))
  2253  			}
  2254  			prg.braceLevel = byte(int32(prg.braceLevel) + 1)
  2255  
  2256  		case endComment:
  2257  			if int32(prg.braceLevel) > 0 {
  2258  				prg.braceLevel = byte(int32(prg.braceLevel) - 1)
  2259  				if int32(prg.braceLevel) == 0 {
  2260  					prg.sendOut(eightBits(misc), sixteenBits('}'))
  2261  				} else {
  2262  					prg.sendOut(eightBits(misc), sixteenBits(']'))
  2263  				}
  2264  			} else {
  2265  				prg.stdout.Writeln()
  2266  				prg.stdout.Write("! Extra @}")
  2267  				prg.error1()
  2268  			}
  2269  		// \xref[Extra \AT!\]]
  2270  		case moduleNumber:
  2271  			k = 2
  2272  			if int32(prg.braceLevel) == 0 {
  2273  				prg.outContrib[1-1] = '{'
  2274  			} else {
  2275  				prg.outContrib[1-1] = '['
  2276  			}
  2277  			if prg.curVal < 0 {
  2278  				prg.outContrib[k-1] = ':'
  2279  				prg.curVal = -prg.curVal
  2280  				k = byte(int32(k) + 1)
  2281  			}
  2282  			n = 10
  2283  			for prg.curVal >= n {
  2284  				n = 10 * n
  2285  			}
  2286  			for {
  2287  				n = n / 10
  2288  				prg.outContrib[k-1] = byte('0' + prg.curVal/n)
  2289  				prg.curVal = prg.curVal % n
  2290  				k = byte(int32(k) + 1)
  2291  				if n == 1 {
  2292  					break
  2293  				}
  2294  			}
  2295  			if int32(prg.outContrib[2-1]) != ':' {
  2296  				prg.outContrib[k-1] = ':'
  2297  				k = byte(int32(k) + 1)
  2298  			}
  2299  			if int32(prg.braceLevel) == 0 {
  2300  				prg.outContrib[k-1] = '}'
  2301  			} else {
  2302  				prg.outContrib[k-1] = ']'
  2303  			}
  2304  			prg.sendOut(eightBits(str), sixteenBits(k))
  2305  
  2306  		case join:
  2307  			prg.sendOut(eightBits(frac), sixteenBits(0))
  2308  			prg.outState = byte(unbreakable)
  2309  
  2310  		case verbatim:
  2311  			// Send verbatim string
  2312  			k = 0
  2313  			for {
  2314  				if int32(k) < lineLength {
  2315  					k = byte(int32(k) + 1)
  2316  				}
  2317  				prg.outContrib[k-1] = byte(prg.getOutput())
  2318  				if int32(prg.outContrib[k-1]) == verbatim || int32(prg.stackPtr) == 0 {
  2319  					break
  2320  				}
  2321  			}
  2322  			if int32(k) == lineLength {
  2323  				prg.stdout.Writeln()
  2324  				prg.stdout.Write("! Verbatim string too long")
  2325  				prg.error1()
  2326  			}
  2327  			// \xref[Verbatim string too long]
  2328  			prg.sendOut(eightBits(str), sixteenBits(int32(k)-1))
  2329  
  2330  		case forceLine:
  2331  			// Force a line break
  2332  			prg.sendOut(eightBits(str), sixteenBits(0)) // normalize the buffer
  2333  			for int32(prg.outPtr) > 0 {
  2334  				if int32(prg.outPtr) <= lineLength {
  2335  					prg.breakPtr = prg.outPtr
  2336  				}
  2337  				prg.flushBuffer()
  2338  			}
  2339  			prg.outState = byte(misc)
  2340  
  2341  		default:
  2342  			prg.stdout.Writeln()
  2343  			prg.stdout.Write("! Can't output ASCII code ", curChar, knuth.WriteWidth(1))
  2344  			prg.error1()
  2345  			// \xref[Can't output ASCII code n]
  2346  		}
  2347  
  2348  		goto continue1
  2349  
  2350  	getFraction:
  2351  		for {
  2352  			if int32(k) < lineLength {
  2353  				k = byte(int32(k) + 1)
  2354  			}
  2355  			prg.outContrib[k-1] = curChar
  2356  			curChar = byte(prg.getOutput())
  2357  			if int32(prg.outContrib[k-1]) == 'E' && (int32(curChar) == '+' || int32(curChar) == '-') {
  2358  				if int32(k) < lineLength {
  2359  					k = byte(int32(k) + 1)
  2360  				}
  2361  				prg.outContrib[k-1] = curChar
  2362  				curChar = byte(prg.getOutput())
  2363  			} else if int32(curChar) == 'e' {
  2364  				curChar = 'E'
  2365  			}
  2366  			if int32(curChar) != 'E' && (int32(curChar) < '0' || int32(curChar) > '9') {
  2367  				break
  2368  			}
  2369  		}
  2370  		if int32(k) == lineLength {
  2371  			prg.stdout.Writeln()
  2372  			prg.stdout.Write("! Fraction too long")
  2373  			prg.error1()
  2374  		}
  2375  		// \xref[Fraction too long]
  2376  		prg.sendOut(eightBits(frac), sixteenBits(k))
  2377  		goto reswitch
  2378  
  2379  	continue1:
  2380  	}
  2381  }
  2382  
  2383  // 123. Introduction to the input phase
  2384  
  2385  // tangle:pos tangle.web:2291:36:
  2386  
  2387  // We have now seen that \.[TANGLE] will be able to output the full
  2388  // \PASCAL\ program, if we can only get that program into the byte memory in
  2389  // the proper format. The input process is something like the output process
  2390  // in reverse, since we compress the text as we read it in and we expand it
  2391  // as we write it out.
  2392  //
  2393  // There are three main input routines. The most interesting is the one that gets
  2394  // the next token of a \PASCAL\ text; the other two are used to scan rapidly past
  2395  // \TeX\ text in the \.[WEB] source code. One of the latter routines will jump to
  2396  // the next token that starts with `\.[@]', and the other skips to the end
  2397  // of a \PASCAL\ comment.
  2398  
  2399  // 125.
  2400  
  2401  // tangle:pos tangle.web:2319:3:
  2402  
  2403  // As we change |changing| from |true| to |false| and back again, we must
  2404  // remember to swap the values of |line| and |other_line| so that the |err_print|
  2405  // routine will be sure to report the correct line number.
  2406  
  2407  // 127.
  2408  
  2409  // tangle:pos tangle.web:2337:3:
  2410  
  2411  // Here's a simple function that checks if the two buffers are different.
  2412  func (prg *prg) linesDontMatch() (r bool) {
  2413  	var (
  2414  		k /* 0..bufSize */ byte // index into the buffers
  2415  	)
  2416  	r = true
  2417  	if int32(prg.changeLimit) != int32(prg.limit) {
  2418  		goto exit
  2419  	}
  2420  	if int32(prg.limit) > 0 {
  2421  		for ii := int32(0); ii <= int32(prg.limit)-1; ii++ {
  2422  			k = byte(ii)
  2423  			_ = k
  2424  			if int32(prg.changeBuffer[k]) != int32(prg.buffer[k]) {
  2425  				goto exit
  2426  			}
  2427  		}
  2428  	}
  2429  	r = false
  2430  
  2431  exit:
  2432  	;
  2433  	return r
  2434  }
  2435  
  2436  // 128.
  2437  
  2438  // tangle:pos tangle.web:2349:3:
  2439  
  2440  // Procedure |prime_the_change_buffer| sets |change_buffer| in preparation
  2441  // for the next matching operation. Since blank lines in the change file are
  2442  // not used for matching, we have |(change_limit=0)and not changing| if and
  2443  // only if the change file is exhausted. This procedure is called only
  2444  // when |changing| is true; hence error messages will be reported correctly.
  2445  func (prg *prg) primeTheChangeBuffer() {
  2446  	var (
  2447  		k /* 0..bufSize */ byte // index into the buffers
  2448  	)
  2449  	prg.changeLimit = 0 // this value will be used if the change file ends
  2450  
  2451  	// Skip over comment lines in the change file; |return| if end of file
  2452  	for true {
  2453  		prg.line = prg.line + 1
  2454  		if !prg.inputLn(prg.changeFile) {
  2455  			goto exit
  2456  		}
  2457  		if int32(prg.limit) < 2 {
  2458  			goto continue1
  2459  		}
  2460  		if int32(prg.buffer[0]) != '@' {
  2461  			goto continue1
  2462  		}
  2463  		if int32(prg.buffer[1]) >= 'X' && int32(prg.buffer[1]) <= 'Z' {
  2464  			prg.buffer[1] = byte(int32(prg.buffer[1]) + 'z' - 'Z')
  2465  		} // lowercasify
  2466  		if int32(prg.buffer[1]) == 'x' {
  2467  			goto done
  2468  		}
  2469  		if int32(prg.buffer[1]) == 'y' || int32(prg.buffer[1]) == 'z' {
  2470  			prg.loc = 2
  2471  			{
  2472  				prg.stdout.Writeln()
  2473  				prg.stdout.Write("! Where is the matching @x?")
  2474  				prg.error1()
  2475  			}
  2476  			// \xref[Where is the match...]
  2477  		}
  2478  
  2479  	continue1:
  2480  	}
  2481  
  2482  done:
  2483  	;
  2484  
  2485  	// Skip to the next nonblank line; |return| if end of file
  2486  	for {
  2487  		prg.line = prg.line + 1
  2488  		if !prg.inputLn(prg.changeFile) {
  2489  			{
  2490  				prg.stdout.Writeln()
  2491  				prg.stdout.Write("! Change file ended after @x")
  2492  				prg.error1()
  2493  			}
  2494  			// \xref[Change file ended...]
  2495  
  2496  			// \xref[Change file ended...]
  2497  			goto exit
  2498  		}
  2499  		if int32(prg.limit) > 0 {
  2500  			break
  2501  		}
  2502  	}
  2503  
  2504  	// Move |buffer| and |limit| to |change_buffer| and |change_limit|
  2505  	{
  2506  		prg.changeLimit = prg.limit
  2507  		if int32(prg.limit) > 0 {
  2508  			for ii := int32(0); ii <= int32(prg.limit)-1; ii++ {
  2509  				k = byte(ii)
  2510  				_ = k
  2511  				prg.changeBuffer[k] = prg.buffer[k]
  2512  			}
  2513  		}
  2514  	}
  2515  
  2516  exit:
  2517  }
  2518  
  2519  // 132.
  2520  
  2521  // tangle:pos tangle.web:2400:3:
  2522  
  2523  // The following procedure is used to see if the next change entry should
  2524  // go into effect; it is called only when |changing| is false.
  2525  // The idea is to test whether or not the current
  2526  // contents of |buffer| matches the current contents of |change_buffer|.
  2527  // If not, there's nothing more to do; but if so, a change is called for:
  2528  // All of the text down to the \.[@y] is supposed to match. An error
  2529  // message is issued if any discrepancy is found. Then the procedure
  2530  // prepares to read the next line from |change_file|.
  2531  func (prg *prg) checkChange() {
  2532  	var (
  2533  		n                      int32 // the number of discrepancies found
  2534  		k/* 0..bufSize */ byte       // index into the buffers
  2535  	)
  2536  	if prg.linesDontMatch() {
  2537  		goto exit
  2538  	}
  2539  	n = 0
  2540  	for true {
  2541  		prg.changing = !prg.changing
  2542  		prg.tempLine = prg.otherLine
  2543  		prg.otherLine = prg.line
  2544  		prg.line = prg.tempLine // now it's |true|
  2545  		prg.line = prg.line + 1
  2546  		if !prg.inputLn(prg.changeFile) {
  2547  			{
  2548  				prg.stdout.Writeln()
  2549  				prg.stdout.Write("! Change file ended before @y")
  2550  				prg.error1()
  2551  			}
  2552  			// \xref[Change file ended...]
  2553  			prg.changeLimit = 0
  2554  			prg.changing = !prg.changing
  2555  			prg.tempLine = prg.otherLine
  2556  			prg.otherLine = prg.line
  2557  			prg.line = prg.tempLine // |false| again
  2558  			// |false| again
  2559  			goto exit
  2560  		}
  2561  
  2562  		// If the current line starts with \.[@y], report any discrepancies and |return|
  2563  		if int32(prg.limit) > 1 {
  2564  			if int32(prg.buffer[0]) == '@' {
  2565  				if int32(prg.buffer[1]) >= 'X' && int32(prg.buffer[1]) <= 'Z' {
  2566  					prg.buffer[1] = byte(int32(prg.buffer[1]) + 'z' - 'Z')
  2567  				} // lowercasify
  2568  				if int32(prg.buffer[1]) == 'x' || int32(prg.buffer[1]) == 'z' {
  2569  					prg.loc = 2
  2570  					{
  2571  						prg.stdout.Writeln()
  2572  						prg.stdout.Write("! Where is the matching @y?")
  2573  						prg.error1()
  2574  					}
  2575  					// \xref[Where is the match...]
  2576  				} else if int32(prg.buffer[1]) == 'y' {
  2577  					if n > 0 {
  2578  						prg.loc = 2
  2579  						{
  2580  							prg.stdout.Writeln()
  2581  							prg.stdout.Write("! Hmm... ", n, knuth.WriteWidth(1),
  2582  								" of the preceding lines failed to match")
  2583  							prg.error1()
  2584  						}
  2585  						// \xref[Hmm... n of the preceding...]
  2586  					}
  2587  
  2588  					goto exit
  2589  				}
  2590  			}
  2591  		}
  2592  
  2593  		// Move |buffer| and |limit|...
  2594  		{
  2595  			prg.changeLimit = prg.limit
  2596  			if int32(prg.limit) > 0 {
  2597  				for ii := int32(0); ii <= int32(prg.limit)-1; ii++ {
  2598  					k = byte(ii)
  2599  					_ = k
  2600  					prg.changeBuffer[k] = prg.buffer[k]
  2601  				}
  2602  			}
  2603  		}
  2604  		prg.changing = !prg.changing
  2605  		prg.tempLine = prg.otherLine
  2606  		prg.otherLine = prg.line
  2607  		prg.line = prg.tempLine // now it's |false|
  2608  		prg.line = prg.line + 1
  2609  		if !prg.inputLn(prg.webFile) {
  2610  			{
  2611  				prg.stdout.Writeln()
  2612  				prg.stdout.Write("! WEB file ended during a change")
  2613  				prg.error1()
  2614  			}
  2615  			// \xref[WEB file ended...]
  2616  			prg.inputHasEnded = true
  2617  			goto exit
  2618  		}
  2619  		if prg.linesDontMatch() {
  2620  			n = n + 1
  2621  		}
  2622  	}
  2623  
  2624  exit:
  2625  }
  2626  
  2627  // 135.
  2628  
  2629  // tangle:pos tangle.web:2460:3:
  2630  
  2631  // The |get_line| procedure is called when |loc>limit|; it puts the next
  2632  // line of merged input into the buffer and updates the other variables
  2633  // appropriately. A space is placed at the right end of the line.
  2634  func (prg *prg) getLine() {
  2635  restart:
  2636  	if prg.changing {
  2637  		prg.line = prg.line + 1
  2638  		if !prg.inputLn(prg.changeFile) {
  2639  			{
  2640  				prg.stdout.Writeln()
  2641  				prg.stdout.Write("! Change file ended without @z")
  2642  				prg.error1()
  2643  			}
  2644  			// \xref[Change file ended...]
  2645  			prg.buffer[0] = '@'
  2646  			prg.buffer[1] = 'z'
  2647  			prg.limit = 2
  2648  		}
  2649  		if int32(prg.limit) > 1 {
  2650  			if int32(prg.buffer[0]) == '@' {
  2651  				if int32(prg.buffer[1]) >= 'X' && int32(prg.buffer[1]) <= 'Z' {
  2652  					prg.buffer[1] = byte(int32(prg.buffer[1]) + 'z' - 'Z')
  2653  				} // lowercasify
  2654  				if int32(prg.buffer[1]) == 'x' || int32(prg.buffer[1]) == 'y' {
  2655  					prg.loc = 2
  2656  					{
  2657  						prg.stdout.Writeln()
  2658  						prg.stdout.Write("! Where is the matching @z?")
  2659  						prg.error1()
  2660  					}
  2661  					// \xref[Where is the match...]
  2662  				} else if int32(prg.buffer[1]) == 'z' {
  2663  					prg.primeTheChangeBuffer()
  2664  					prg.changing = !prg.changing
  2665  					prg.tempLine = prg.otherLine
  2666  					prg.otherLine = prg.line
  2667  					prg.line = prg.tempLine
  2668  				}
  2669  			}
  2670  		}
  2671  	}
  2672  	if !prg.changing {
  2673  		{
  2674  			prg.line = prg.line + 1
  2675  			if !prg.inputLn(prg.webFile) {
  2676  				prg.inputHasEnded = true
  2677  			} else if int32(prg.changeLimit) > 0 {
  2678  				prg.checkChange()
  2679  			}
  2680  		}
  2681  		if prg.changing {
  2682  			goto restart
  2683  		}
  2684  	}
  2685  	prg.loc = 0
  2686  	prg.buffer[prg.limit] = ' '
  2687  }
  2688  
  2689  // 139.
  2690  
  2691  // tangle:pos tangle.web:2513:3:
  2692  
  2693  // Important milestones are reached during the input phase when certain
  2694  // control codes are sensed.
  2695  //
  2696  // Control codes in \.[WEB] begin with `\.[@]', and the next character
  2697  // identifies the code. Some of these are of interest only to \.[WEAVE],
  2698  // so \.[TANGLE] ignores them; the others are converted by \.[TANGLE] into
  2699  // internal code numbers by the |control_code| function below. The ordering
  2700  // of these internal code numbers has been chosen to simplify the program logic;
  2701  // larger numbers are given to the control codes that denote more significant
  2702  // milestones.
  2703  func (prg *prg) controlCode(c asciiCode) (r eightBits) {
  2704  	switch c {
  2705  	case '@':
  2706  		r = '@' // `quoted' at sign
  2707  	// "'"=
  2708  	case '\'':
  2709  		r = byte(octal) // precedes octal constant
  2710  	// """"=
  2711  	case '"':
  2712  		r = byte(hex) // precedes hexadecimal constant
  2713  	// "$"=
  2714  	case '$':
  2715  		r = byte(checkSum) // string pool check sum
  2716  	// " "=
  2717  	case ' ', tabMark:
  2718  		r = byte(newModule) // beginning of a new module
  2719  	// "*"=
  2720  	case '*':
  2721  		prg.stdout.Write("*", int32(prg.moduleCount)+1, knuth.WriteWidth(1))
  2722  		// print a progress report
  2723  		r = byte(newModule) // beginning of a new module
  2724  
  2725  	// "D"=
  2726  	case 'D', 'd':
  2727  		r = byte(definition) // macro definition
  2728  	// "F"=
  2729  	case 'F', 'f':
  2730  		r = byte(format) // format definition
  2731  	// "["=
  2732  	case '{':
  2733  		r = byte(beginComment) // begin-comment delimiter
  2734  	// "]"=
  2735  	case '}':
  2736  		r = byte(endComment) // end-comment delimiter
  2737  	// "P"=
  2738  	case 'P', 'p':
  2739  		r = byte(beginPascal) // \PASCAL\ text in unnamed module
  2740  	// "T"=
  2741  	case 'T', 't', '^', '.',
  2742  		':':
  2743  		r = byte(controlText) // control text to be ignored
  2744  	// "&"=
  2745  	case '&':
  2746  		r = byte(join) // concatenate two tokens
  2747  	// "<"=
  2748  	case '<':
  2749  		r = byte(moduleName) // beginning of a module name
  2750  	// "="=
  2751  	case '=':
  2752  		r = byte(verbatim) // beginning of \PASCAL\ verbatim mode
  2753  	// "\"=
  2754  	case '\\':
  2755  		r = byte(forceLine)
  2756  		// force a new line in \PASCAL\ output
  2757  	default:
  2758  		r = byte(ignore) // ignore all other cases
  2759  	}
  2760  	return r
  2761  }
  2762  
  2763  // 140.
  2764  
  2765  // tangle:pos tangle.web:2557:3:
  2766  
  2767  // The |skip_ahead| procedure reads through the input at fairly high speed
  2768  // until finding the next non-ignorable control code, which it returns.
  2769  func (prg *prg) skipAhead() (r eightBits) {
  2770  	var (
  2771  		c eightBits // control code found
  2772  	)
  2773  	for true {
  2774  		if int32(prg.loc) > int32(prg.limit) {
  2775  			prg.getLine()
  2776  			if prg.inputHasEnded {
  2777  				c = byte(newModule)
  2778  				goto done
  2779  			}
  2780  		}
  2781  		prg.buffer[int32(prg.limit)+1] = '@'
  2782  		for int32(prg.buffer[prg.loc]) != '@' {
  2783  			prg.loc = byte(int32(prg.loc) + 1)
  2784  		}
  2785  		if int32(prg.loc) <= int32(prg.limit) {
  2786  			prg.loc = byte(int32(prg.loc) + 2)
  2787  			c = prg.controlCode(prg.buffer[int32(prg.loc)-1])
  2788  			if int32(c) != ignore || int32(prg.buffer[int32(prg.loc)-1]) == '>' {
  2789  				goto done
  2790  			}
  2791  		}
  2792  	}
  2793  
  2794  done:
  2795  	r = c
  2796  	return r
  2797  }
  2798  
  2799  // 141.
  2800  
  2801  // tangle:pos tangle.web:2579:3:
  2802  
  2803  // The |skip_comment| procedure reads through the input at somewhat high speed
  2804  // until finding the first unmatched right brace or until coming to the end
  2805  // of the file. It ignores characters following `\.\\' characters, since all
  2806  // braces that aren't nested are supposed to be hidden in that way. For
  2807  // example, consider the process of skipping the first comment below,
  2808  // where the string containing the right brace has been typed as \.[\`\\.\\\]\']
  2809  // in the \.[WEB] file.
  2810  func (prg *prg) skipComment() {
  2811  	var (
  2812  		bal eightBits // excess of left braces
  2813  		c   asciiCode // current character
  2814  	)
  2815  	bal = 0
  2816  	for true {
  2817  		if int32(prg.loc) > int32(prg.limit) {
  2818  			prg.getLine()
  2819  			if prg.inputHasEnded {
  2820  				{
  2821  					prg.stdout.Writeln()
  2822  					prg.stdout.Write("! Input ended in mid-comment")
  2823  					prg.error1()
  2824  				}
  2825  				// \xref[Input ended in mid-comment]
  2826  
  2827  				// \xref[Input ended in mid-comment]
  2828  				goto exit
  2829  			}
  2830  		}
  2831  		c = prg.buffer[prg.loc]
  2832  		prg.loc = byte(int32(prg.loc) + 1)
  2833  
  2834  		// Do special things when |c="@", "\", "[", "]"|; |return| at end
  2835  		if int32(c) == '@' {
  2836  			c = prg.buffer[prg.loc]
  2837  			if int32(c) != ' ' && int32(c) != tabMark && int32(c) != '*' {
  2838  				prg.loc = byte(int32(prg.loc) + 1)
  2839  			} else {
  2840  				{
  2841  					prg.stdout.Writeln()
  2842  					prg.stdout.Write("! Section ended in mid-comment")
  2843  					prg.error1()
  2844  				}
  2845  				// \xref[Section ended in mid-comment]
  2846  				prg.loc = byte(int32(prg.loc) - 1)
  2847  				goto exit
  2848  			}
  2849  		} else if int32(c) == '\\' && int32(prg.buffer[prg.loc]) != '@' {
  2850  			prg.loc = byte(int32(prg.loc) + 1)
  2851  		} else if int32(c) == '{' {
  2852  			bal = byte(int32(bal) + 1)
  2853  		} else if int32(c) == '}' {
  2854  			if int32(bal) == 0 {
  2855  				goto exit
  2856  			}
  2857  			bal = byte(int32(bal) - 1)
  2858  		}
  2859  	}
  2860  
  2861  exit:
  2862  }
  2863  
  2864  // 145.
  2865  
  2866  // tangle:pos tangle.web:2648:3:
  2867  
  2868  // At the top level, |get_next| is a multi-way switch based on the next
  2869  // character in the input buffer. A |new_module| code is inserted at the
  2870  // very end of the input file.
  2871  func (prg *prg) getNext() (r eightBits) {
  2872  	var (
  2873  		c                               eightBits // the current character
  2874  		d                               eightBits // the next character
  2875  		j, k/* 0..longestName */ uint16           // indices into |mod_text|
  2876  	)
  2877  restart:
  2878  	if int32(prg.loc) > int32(prg.limit) {
  2879  		prg.getLine()
  2880  		if prg.inputHasEnded {
  2881  			c = byte(newModule)
  2882  			goto found
  2883  		}
  2884  	}
  2885  	c = prg.buffer[prg.loc]
  2886  	prg.loc = byte(int32(prg.loc) + 1)
  2887  	if prg.scanningHex {
  2888  		if int32(c) >= '0' && int32(c) <= '9' || int32(c) >= 'A' && int32(c) <= 'F' {
  2889  			goto found
  2890  		} else {
  2891  			prg.scanningHex = false
  2892  		}
  2893  	}
  2894  	switch c {
  2895  	case 'A', 'Z' - 24, 'Z' - 23, 'Z' - 22,
  2896  		'Z' - 21, 'Z' - 20, 'Z' - 19, 'Z' - 18,
  2897  		'Z' - 17, 'Z' - 16, 'Z' - 15, 'Z' - 14,
  2898  		'Z' - 13, 'Z' - 12, 'Z' - 11, 'Z' - 10,
  2899  		'Z' - 9, 'Z' - 8, 'Z' - 7, 'Z' - 6,
  2900  		'Z' - 5, 'Z' - 4, 'Z' - 3, 'Z' - 2,
  2901  		'Z' - 1, 'Z', 'a', 'z' - 24,
  2902  		'z' - 23, 'z' - 22, 'z' - 21, 'z' - 20,
  2903  		'z' - 19, 'z' - 18, 'z' - 17, 'z' - 16,
  2904  		'z' - 15, 'z' - 14, 'z' - 13, 'z' - 12,
  2905  		'z' - 11, 'z' - 10, 'z' - 9, 'z' - 8,
  2906  		'z' - 7, 'z' - 6, 'z' - 5, 'z' - 4,
  2907  		'z' - 3, 'z' - 2, 'z' - 1, 'z':
  2908  		// Get an identifier
  2909  		if (int32(c) == 'e' || int32(c) == 'E') && int32(prg.loc) > 1 {
  2910  			if int32(prg.buffer[int32(prg.loc)-2]) <= '9' && int32(prg.buffer[int32(prg.loc)-2]) >= '0' {
  2911  				c = 0
  2912  			}
  2913  		}
  2914  		if int32(c) != 0 {
  2915  			prg.loc = byte(int32(prg.loc) - 1)
  2916  			prg.idFirst = prg.loc
  2917  			for {
  2918  				prg.loc = byte(int32(prg.loc) + 1)
  2919  				d = prg.buffer[prg.loc]
  2920  				if (int32(d) < '0' || int32(d) > '9' && int32(d) < 'A' || int32(d) > 'Z' && int32(d) < 'a' || int32(d) > 'z') && int32(d) != '_' {
  2921  					break
  2922  				}
  2923  			}
  2924  			if int32(prg.loc) > int32(prg.idFirst)+1 {
  2925  				c = byte(identifier)
  2926  				prg.idLoc = prg.loc
  2927  			}
  2928  		} else {
  2929  			c = 'E'
  2930  		} // exponent of a real constant
  2931  
  2932  	// """"=
  2933  	case '"':
  2934  		// Get a preprocessed string
  2935  		prg.doubleChars = 0
  2936  		prg.idFirst = byte(int32(prg.loc) - 1)
  2937  		for {
  2938  			d = prg.buffer[prg.loc]
  2939  			prg.loc = byte(int32(prg.loc) + 1)
  2940  			if int32(d) == '"' || int32(d) == '@' {
  2941  				if int32(prg.buffer[prg.loc]) == int32(d) {
  2942  					prg.loc = byte(int32(prg.loc) + 1)
  2943  					d = 0
  2944  					prg.doubleChars = byte(int32(prg.doubleChars) + 1)
  2945  				} else {
  2946  					if int32(d) == '@' {
  2947  						prg.stdout.Writeln()
  2948  						prg.stdout.Write("! Double @ sign missing")
  2949  						prg.error1()
  2950  					}
  2951  				}
  2952  			} else if int32(prg.loc) > int32(prg.limit) {
  2953  				{
  2954  					prg.stdout.Writeln()
  2955  					prg.stdout.Write("! String constant didn't end")
  2956  					prg.error1()
  2957  				}
  2958  				d = '"'
  2959  				// \xref[String constant didn't end]
  2960  			}
  2961  			if int32(d) == '"' {
  2962  				break
  2963  			}
  2964  		}
  2965  		prg.idLoc = byte(int32(prg.loc) - 1)
  2966  		c = byte(identifier)
  2967  
  2968  	// "@"=
  2969  	case '@':
  2970  		// Get control code and possible module name
  2971  		c = prg.controlCode(prg.buffer[prg.loc])
  2972  		prg.loc = byte(int32(prg.loc) + 1)
  2973  		if int32(c) == ignore {
  2974  			goto restart
  2975  		} else if int32(c) == hex {
  2976  			prg.scanningHex = true
  2977  		} else if int32(c) == moduleName {
  2978  			k = 0
  2979  			for true {
  2980  				if int32(prg.loc) > int32(prg.limit) {
  2981  					prg.getLine()
  2982  					if prg.inputHasEnded {
  2983  						{
  2984  							prg.stdout.Writeln()
  2985  							prg.stdout.Write("! Input ended in section name")
  2986  							prg.error1()
  2987  						}
  2988  						// \xref[Input ended in section name]
  2989  
  2990  						// \xref[Input ended in section name]
  2991  						goto done
  2992  					}
  2993  				}
  2994  				d = prg.buffer[prg.loc]
  2995  
  2996  				// If end of name, |goto done|
  2997  				if int32(d) == '@' {
  2998  					d = prg.buffer[int32(prg.loc)+1]
  2999  					if int32(d) == '>' {
  3000  						prg.loc = byte(int32(prg.loc) + 2)
  3001  						goto done
  3002  					}
  3003  					if int32(d) == ' ' || int32(d) == tabMark || int32(d) == '*' {
  3004  						{
  3005  							prg.stdout.Writeln()
  3006  							prg.stdout.Write("! Section name didn't end")
  3007  							prg.error1()
  3008  						}
  3009  						goto done
  3010  						// \xref[Section name didn't end]
  3011  					}
  3012  					k = uint16(int32(k) + 1)
  3013  					prg.modText[k] = '@'
  3014  					prg.loc = byte(int32(prg.loc) + 1) // now |d=buffer[loc]| again
  3015  				}
  3016  				prg.loc = byte(int32(prg.loc) + 1)
  3017  				if int32(k) < longestName-1 {
  3018  					k = uint16(int32(k) + 1)
  3019  				}
  3020  				if int32(d) == ' ' || int32(d) == tabMark {
  3021  					d = ' '
  3022  					if int32(prg.modText[int32(k)-1]) == ' ' {
  3023  						k = uint16(int32(k) - 1)
  3024  					}
  3025  				}
  3026  				prg.modText[k] = d
  3027  			}
  3028  
  3029  		done:
  3030  			if int32(k) >= longestName-2 {
  3031  				{
  3032  					prg.stdout.Writeln()
  3033  					prg.stdout.Write("! Section name too long: ")
  3034  				}
  3035  				// \xref[Section name too long]
  3036  				for ii := int32(1); ii <= 25; ii++ {
  3037  					j = uint16(ii)
  3038  					_ = j
  3039  					prg.stdout.Write(string(rune(prg.xchr[prg.modText[j]])))
  3040  				}
  3041  				prg.stdout.Write("...") /*   */
  3042  				if int32(prg.history) == spotless {
  3043  					prg.history = byte(harmlessMessage)
  3044  				}
  3045  			}
  3046  			if int32(prg.modText[k]) == ' ' && int32(k) > 0 {
  3047  				k = uint16(int32(k) - 1)
  3048  			}
  3049  
  3050  			if int32(k) > 3 {
  3051  				if int32(prg.modText[k]) == '.' && int32(prg.modText[int32(k)-1]) == '.' && int32(prg.modText[int32(k)-2]) == '.' {
  3052  					prg.curModule = prg.prefixLookup(sixteenBits(int32(k) - 3))
  3053  				} else {
  3054  					prg.curModule = prg.modLookup(k)
  3055  				}
  3056  			} else {
  3057  				prg.curModule = prg.modLookup(k)
  3058  			}
  3059  		} else if int32(c) == controlText {
  3060  			for {
  3061  				c = prg.skipAhead()
  3062  				if int32(c) != '@' {
  3063  					break
  3064  				}
  3065  			}
  3066  			if int32(prg.buffer[int32(prg.loc)-1]) != '>' {
  3067  				prg.stdout.Writeln()
  3068  				prg.stdout.Write("! Improper @ within control text")
  3069  				prg.error1()
  3070  			}
  3071  			// \xref[Improper \AT! within control text]
  3072  
  3073  			// \xref[Improper \AT! within control text]
  3074  			goto restart
  3075  		}
  3076  
  3077  	// \4
  3078  	// Compress two-symbol combinations like `\.[:=]'
  3079  	// "."=
  3080  	case '.':
  3081  		if int32(prg.buffer[prg.loc]) == '.' {
  3082  			if int32(prg.loc) <= int32(prg.limit) {
  3083  				c = byte(doubleDot)
  3084  				prg.loc = byte(int32(prg.loc) + 1)
  3085  			}
  3086  		} else if int32(prg.buffer[prg.loc]) == ')' {
  3087  			if int32(prg.loc) <= int32(prg.limit) {
  3088  				c = ']'
  3089  				prg.loc = byte(int32(prg.loc) + 1)
  3090  			}
  3091  		}
  3092  	// ":"=
  3093  	case ':':
  3094  		if int32(prg.buffer[prg.loc]) == '=' {
  3095  			if int32(prg.loc) <= int32(prg.limit) {
  3096  				c = byte(leftArrow)
  3097  				prg.loc = byte(int32(prg.loc) + 1)
  3098  			}
  3099  		}
  3100  	// "="=
  3101  	case '=':
  3102  		if int32(prg.buffer[prg.loc]) == '=' {
  3103  			if int32(prg.loc) <= int32(prg.limit) {
  3104  				c = byte(equivalenceSign)
  3105  				prg.loc = byte(int32(prg.loc) + 1)
  3106  			}
  3107  		}
  3108  	// ">"=
  3109  	case '>':
  3110  		if int32(prg.buffer[prg.loc]) == '=' {
  3111  			if int32(prg.loc) <= int32(prg.limit) {
  3112  				c = byte(greaterOrEqual)
  3113  				prg.loc = byte(int32(prg.loc) + 1)
  3114  			}
  3115  		}
  3116  	// "<"=
  3117  	case '<':
  3118  		if int32(prg.buffer[prg.loc]) == '=' {
  3119  			if int32(prg.loc) <= int32(prg.limit) {
  3120  				c = byte(lessOrEqual)
  3121  				prg.loc = byte(int32(prg.loc) + 1)
  3122  			}
  3123  		} else if int32(prg.buffer[prg.loc]) == '>' {
  3124  			if int32(prg.loc) <= int32(prg.limit) {
  3125  				c = byte(notEqual)
  3126  				prg.loc = byte(int32(prg.loc) + 1)
  3127  			}
  3128  		}
  3129  	// "("=
  3130  	case '(':
  3131  		if int32(prg.buffer[prg.loc]) == '*' {
  3132  			if int32(prg.loc) <= int32(prg.limit) {
  3133  				c = byte(beginComment)
  3134  				prg.loc = byte(int32(prg.loc) + 1)
  3135  			}
  3136  		} else if int32(prg.buffer[prg.loc]) == '.' {
  3137  			if int32(prg.loc) <= int32(prg.limit) {
  3138  				c = '['
  3139  				prg.loc = byte(int32(prg.loc) + 1)
  3140  			}
  3141  		}
  3142  	// "*"=
  3143  	case '*':
  3144  		if int32(prg.buffer[prg.loc]) == ')' {
  3145  			if int32(prg.loc) <= int32(prg.limit) {
  3146  				c = byte(endComment)
  3147  				prg.loc = byte(int32(prg.loc) + 1)
  3148  			}
  3149  		}
  3150  
  3151  	// " "=
  3152  	case ' ', tabMark:
  3153  		goto restart // ignore spaces and tabs
  3154  	// "["=
  3155  	case '{':
  3156  		prg.skipComment()
  3157  		goto restart
  3158  
  3159  	// "]"=
  3160  	case '}':
  3161  		{
  3162  			prg.stdout.Writeln()
  3163  			prg.stdout.Write("! Extra }")
  3164  			prg.error1()
  3165  		}
  3166  		goto restart
  3167  	// \xref[Extra \]]
  3168  
  3169  	default:
  3170  		if int32(c) >= 128 {
  3171  			goto restart
  3172  		} else {
  3173  		}
  3174  	}
  3175  
  3176  found:
  3177  	r = c
  3178  	return r
  3179  }
  3180  
  3181  // 157.
  3182  
  3183  // tangle:pos tangle.web:2846:3:
  3184  
  3185  // The evaluation of a numeric expression makes use of two variables called the
  3186  // |accumulator| and the |next_sign|. At the beginning, |accumulator| is zero and
  3187  // |next_sign| is $+1$. When a \.+ or \.- is scanned, |next_sign| is multiplied
  3188  // by the value of that sign. When a numeric value is scanned, it is multiplied by
  3189  // |next_sign| and added to the |accumulator|, then |next_sign| is reset to $+1$.
  3190  func (prg *prg) scanNumeric(p namePointer) {
  3191  	var (
  3192  		accumulator                 int32       // accumulates sums
  3193  		nextSign/*  -1.. +1 */ int8             // sign to attach to next value
  3194  		q                           namePointer // points to identifiers being evaluated
  3195  		val                         int32       // constants being evaluated
  3196  	)
  3197  	accumulator = 0
  3198  	nextSign = int8(+1)
  3199  	for true {
  3200  		prg.nextControl = prg.getNext()
  3201  
  3202  	reswitch:
  3203  		switch prg.nextControl {
  3204  		case '0', '1', '2', '3',
  3205  			'4', '5', '6', '7',
  3206  			'8', '9':
  3207  			val = 0
  3208  			for {
  3209  				val = 10*val + int32(prg.nextControl) - '0'
  3210  				prg.nextControl = prg.getNext()
  3211  				if int32(prg.nextControl) > '9' || int32(prg.nextControl) < '0' {
  3212  					break
  3213  				}
  3214  			}
  3215  			{
  3216  				accumulator = accumulator + int32(nextSign)*val
  3217  				nextSign = int8(+1)
  3218  			}
  3219  			goto reswitch
  3220  
  3221  		case octal:
  3222  			val = 0
  3223  			prg.nextControl = '0'
  3224  			for {
  3225  				val = 8*val + int32(prg.nextControl) - '0'
  3226  				prg.nextControl = prg.getNext()
  3227  				if int32(prg.nextControl) > '7' || int32(prg.nextControl) < '0' {
  3228  					break
  3229  				}
  3230  			}
  3231  			{
  3232  				accumulator = accumulator + int32(nextSign)*val
  3233  				nextSign = int8(+1)
  3234  			}
  3235  			goto reswitch
  3236  
  3237  		case hex:
  3238  			val = 0
  3239  			prg.nextControl = '0'
  3240  			for {
  3241  				if int32(prg.nextControl) >= 'A' {
  3242  					prg.nextControl = byte(int32(prg.nextControl) + '0' + 10 - 'A')
  3243  				}
  3244  				val = 16*val + int32(prg.nextControl) - '0'
  3245  				prg.nextControl = prg.getNext()
  3246  				if int32(prg.nextControl) > 'F' || int32(prg.nextControl) < '0' || int32(prg.nextControl) > '9' && int32(prg.nextControl) < 'A' {
  3247  					break
  3248  				}
  3249  			}
  3250  			{
  3251  				accumulator = accumulator + int32(nextSign)*val
  3252  				nextSign = int8(+1)
  3253  			}
  3254  			goto reswitch
  3255  
  3256  		case identifier:
  3257  			q = prg.idLookup(eightBits(normal))
  3258  			if int32(prg.ilk[q]) != numeric {
  3259  				prg.nextControl = '*'
  3260  				goto reswitch // leads to error
  3261  			}
  3262  			{
  3263  				accumulator = accumulator + int32(nextSign)*(int32(prg.equiv[q])-0100000)
  3264  				nextSign = int8(+1)
  3265  			}
  3266  
  3267  		// "+"=
  3268  		case '+':
  3269  		// "-"=
  3270  		case '-':
  3271  			nextSign = -nextSign
  3272  		case format, definition, moduleName, beginPascal,
  3273  			newModule:
  3274  			goto done
  3275  		// ";"=
  3276  		case ';':
  3277  			prg.stdout.Writeln()
  3278  			prg.stdout.Write("! Omit semicolon in numeric definition")
  3279  			prg.error1()
  3280  
  3281  		// \xref[Omit semicolon in numeric def...]
  3282  		default:
  3283  			{
  3284  				prg.stdout.Writeln()
  3285  				prg.stdout.Write("! Improper numeric definition will be flushed")
  3286  				prg.error1()
  3287  			}
  3288  			// \xref[Improper numeric definition...]
  3289  			for {
  3290  				prg.nextControl = prg.skipAhead()
  3291  				if int32(prg.nextControl) >= format {
  3292  					break
  3293  				}
  3294  			}
  3295  			if int32(prg.nextControl) == moduleName {
  3296  				prg.loc = byte(int32(prg.loc) - 2)
  3297  				prg.nextControl = prg.getNext()
  3298  			}
  3299  			accumulator = 0
  3300  			goto done
  3301  
  3302  		}
  3303  	}
  3304  
  3305  done:
  3306  	;
  3307  	if abs(accumulator) >= 0100000 {
  3308  		{
  3309  			prg.stdout.Writeln()
  3310  			prg.stdout.Write("! Value too big: ", accumulator, knuth.WriteWidth(1))
  3311  			prg.error1()
  3312  		}
  3313  		accumulator = 0
  3314  		// \xref[Value too big]
  3315  	}
  3316  	prg.equiv[p] = uint16(accumulator + 0100000) // name |p| now is defined to equal |accumulator|
  3317  }
  3318  
  3319  // 163. Scanning a macro definition
  3320  
  3321  // tangle:pos tangle.web:2930:32:
  3322  
  3323  // The rules for generating the replacement texts corresponding to simple
  3324  // macros, parametric macros, and \PASCAL\ texts of a module are almost
  3325  // identical, so a single procedure is used for all three cases. The
  3326  // differences are that
  3327  //
  3328  // \yskip\item[a)] The sign |#| denotes a parameter only when it appears
  3329  // outside of strings in a parametric macro; otherwise it stands for the
  3330  // ASCII character |#|. (This is not used in standard \PASCAL, but some
  3331  // \PASCAL s allow, for example, `\.[/\#]' after a certain kind of file name.)
  3332  //
  3333  // \item[b)]Module names are not allowed in simple macros or parametric macros;
  3334  // in fact, the appearance of a module name terminates such macros and denotes
  3335  // the name of the current module.
  3336  //
  3337  // \item[c)]The symbols \.[@d] and \.[@f] and \.[@p] are not allowed after
  3338  // module names, while they terminate macro definitions.
  3339  
  3340  // 165.
  3341  func (prg *prg) scanRepl(t eightBits) {
  3342  	var (
  3343  		a   sixteenBits // the current token
  3344  		b   asciiCode   // a character from the buffer
  3345  		bal eightBits   // left parentheses minus right parentheses
  3346  	)
  3347  	bal = 0
  3348  	for true {
  3349  	continue1:
  3350  		a = uint16(prg.getNext())
  3351  		switch a {
  3352  		case '(':
  3353  			bal = byte(int32(bal) + 1)
  3354  		// ")"=
  3355  		case ')':
  3356  			if int32(bal) == 0 {
  3357  				prg.stdout.Writeln()
  3358  				prg.stdout.Write("! Extra )")
  3359  				prg.error1()
  3360  			} else {
  3361  				bal = byte(int32(bal) - 1)
  3362  			}
  3363  		// "'"=
  3364  		case '\'':
  3365  			// Copy a string from the buffer to |tok_mem|
  3366  			b = '\''
  3367  			for true {
  3368  				{
  3369  					if int32(prg.tokPtr[prg.z]) == maxToks {
  3370  						prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3371  						prg.error1()
  3372  						prg.history = byte(fatalMessage)
  3373  						prg.jumpOut()
  3374  					}
  3375  					prg.tokMem[prg.z][prg.tokPtr[prg.z]] = b
  3376  					prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3377  				}
  3378  				if int32(b) == '@' {
  3379  					if int32(prg.buffer[prg.loc]) == '@' {
  3380  						prg.loc = byte(int32(prg.loc) + 1)
  3381  					} else {
  3382  						prg.stdout.Writeln()
  3383  						prg.stdout.Write("! You should double @ signs in strings")
  3384  						prg.error1()
  3385  					}
  3386  				}
  3387  				// \xref[You should double \AT! signs]
  3388  				if int32(prg.loc) == int32(prg.limit) {
  3389  					{
  3390  						prg.stdout.Writeln()
  3391  						prg.stdout.Write("! String didn't end")
  3392  						prg.error1()
  3393  					}
  3394  					// \xref[String didn't end]
  3395  					prg.buffer[prg.loc] = '\''
  3396  					prg.buffer[int32(prg.loc)+1] = 0
  3397  				}
  3398  				b = prg.buffer[prg.loc]
  3399  				prg.loc = byte(int32(prg.loc) + 1)
  3400  				if int32(b) == '\'' {
  3401  					if int32(prg.buffer[prg.loc]) != '\'' {
  3402  						goto found
  3403  					} else {
  3404  						prg.loc = byte(int32(prg.loc) + 1)
  3405  						{
  3406  							if int32(prg.tokPtr[prg.z]) == maxToks {
  3407  								prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3408  								prg.error1()
  3409  								prg.history = byte(fatalMessage)
  3410  								prg.jumpOut()
  3411  							}
  3412  							prg.tokMem[prg.z][prg.tokPtr[prg.z]] = '\''
  3413  							prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3414  						}
  3415  					}
  3416  				}
  3417  			}
  3418  
  3419  		found:
  3420  			; // now |a| holds the final |"'"| that will be stored
  3421  
  3422  		// "#"=
  3423  		case '#':
  3424  			if int32(t) == parametric {
  3425  				a = uint16(param)
  3426  			}
  3427  		// \4
  3428  		// In cases that |a| is a non-ASCII token (|identifier|, |module_name|, etc.), either process it and change |a| to a byte that should be stored, or |goto continue| if |a| should be ignored, or |goto done| if |a| signals the end of this replacement text
  3429  		case identifier:
  3430  			a = prg.idLookup(eightBits(normal))
  3431  			{
  3432  				if int32(prg.tokPtr[prg.z]) == maxToks {
  3433  					prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3434  					prg.error1()
  3435  					prg.history = byte(fatalMessage)
  3436  					prg.jumpOut()
  3437  				}
  3438  				prg.tokMem[prg.z][prg.tokPtr[prg.z]] = byte(int32(a)/0400 + 0200)
  3439  				prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3440  			}
  3441  			a = uint16(int32(a) % 0400)
  3442  
  3443  		case moduleName:
  3444  			if int32(t) != moduleName {
  3445  				goto done
  3446  			} else {
  3447  				{
  3448  					if int32(prg.tokPtr[prg.z]) == maxToks {
  3449  						prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3450  						prg.error1()
  3451  						prg.history = byte(fatalMessage)
  3452  						prg.jumpOut()
  3453  					}
  3454  					prg.tokMem[prg.z][prg.tokPtr[prg.z]] = byte(int32(prg.curModule)/0400 + 0250)
  3455  					prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3456  				}
  3457  				a = uint16(int32(prg.curModule) % 0400)
  3458  			}
  3459  		case verbatim:
  3460  			// Copy verbatim string from the buffer to |tok_mem|
  3461  			{
  3462  				if int32(prg.tokPtr[prg.z]) == maxToks {
  3463  					prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3464  					prg.error1()
  3465  					prg.history = byte(fatalMessage)
  3466  					prg.jumpOut()
  3467  				}
  3468  				prg.tokMem[prg.z][prg.tokPtr[prg.z]] = byte(verbatim)
  3469  				prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3470  			}
  3471  			prg.buffer[int32(prg.limit)+1] = '@'
  3472  
  3473  		reswitch:
  3474  			if int32(prg.buffer[prg.loc]) == '@' {
  3475  				if int32(prg.loc) < int32(prg.limit) {
  3476  					if int32(prg.buffer[int32(prg.loc)+1]) == '@' {
  3477  						{
  3478  							if int32(prg.tokPtr[prg.z]) == maxToks {
  3479  								prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3480  								prg.error1()
  3481  								prg.history = byte(fatalMessage)
  3482  								prg.jumpOut()
  3483  							}
  3484  							prg.tokMem[prg.z][prg.tokPtr[prg.z]] = '@'
  3485  							prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3486  						}
  3487  						prg.loc = byte(int32(prg.loc) + 2)
  3488  
  3489  						goto reswitch
  3490  					}
  3491  				}
  3492  			} else {
  3493  				{
  3494  					if int32(prg.tokPtr[prg.z]) == maxToks {
  3495  						prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3496  						prg.error1()
  3497  						prg.history = byte(fatalMessage)
  3498  						prg.jumpOut()
  3499  					}
  3500  					prg.tokMem[prg.z][prg.tokPtr[prg.z]] = prg.buffer[prg.loc]
  3501  					prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3502  				}
  3503  				prg.loc = byte(int32(prg.loc) + 1)
  3504  
  3505  				goto reswitch
  3506  			}
  3507  			if int32(prg.loc) >= int32(prg.limit) {
  3508  				prg.stdout.Writeln()
  3509  				prg.stdout.Write("! Verbatim string didn't end")
  3510  				prg.error1()
  3511  			} else if int32(prg.buffer[int32(prg.loc)+1]) != '>' {
  3512  				prg.stdout.Writeln()
  3513  				prg.stdout.Write("! You should double @ signs in verbatim strings")
  3514  				prg.error1()
  3515  			}
  3516  			// \xref[You should double \AT! signs]
  3517  			prg.loc = byte(int32(prg.loc) + 2)
  3518  			// another |verbatim| byte will be stored, since |a=verbatim|
  3519  
  3520  		case definition, format, beginPascal:
  3521  			if int32(t) != moduleName {
  3522  				goto done
  3523  			} else {
  3524  				{
  3525  					prg.stdout.Writeln()
  3526  					prg.stdout.Write("! @", string(rune(prg.xchr[prg.buffer[int32(prg.loc)-1]])),
  3527  						// \xref[\AT!p is ignored in Pascal text]
  3528  						// \xref[\AT!d is ignored in Pascal text]
  3529  						// \xref[\AT!f is ignored in Pascal text]
  3530  						" is ignored in Pascal text")
  3531  					prg.error1()
  3532  				}
  3533  				goto continue1
  3534  			}
  3535  		case newModule:
  3536  			goto done
  3537  
  3538  		default:
  3539  		}
  3540  
  3541  		{
  3542  			if int32(prg.tokPtr[prg.z]) == maxToks {
  3543  				prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3544  				prg.error1()
  3545  				prg.history = byte(fatalMessage)
  3546  				prg.jumpOut()
  3547  			}
  3548  			prg.tokMem[prg.z][prg.tokPtr[prg.z]] = byte(a)
  3549  			prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3550  		} // store |a| in |tok_mem|
  3551  	}
  3552  
  3553  done:
  3554  	prg.nextControl = byte(a)
  3555  
  3556  	// Make sure the parentheses balance
  3557  	if int32(bal) > 0 {
  3558  		if int32(bal) == 1 {
  3559  			prg.stdout.Writeln()
  3560  			prg.stdout.Write("! Missing )")
  3561  			prg.error1()
  3562  		} else {
  3563  			prg.stdout.Writeln()
  3564  			prg.stdout.Write("! Missing ", bal, knuth.WriteWidth(1), " )'s")
  3565  			prg.error1()
  3566  		}
  3567  		// \xref[Missing n )]
  3568  		for int32(bal) > 0 {
  3569  			{
  3570  				if int32(prg.tokPtr[prg.z]) == maxToks {
  3571  					prg.stderr.Writeln("! Sorry, ", "token", " capacity exceeded")
  3572  					prg.error1()
  3573  					prg.history = byte(fatalMessage)
  3574  					prg.jumpOut()
  3575  				}
  3576  				prg.tokMem[prg.z][prg.tokPtr[prg.z]] = ')'
  3577  				prg.tokPtr[prg.z] = uint16(int32(prg.tokPtr[prg.z]) + 1)
  3578  			}
  3579  			bal = byte(int32(bal) - 1)
  3580  		}
  3581  	}
  3582  	if int32(prg.textPtr) > maxTexts-zz {
  3583  		prg.stderr.Writeln("! Sorry, ", "text", " capacity exceeded")
  3584  		prg.error1()
  3585  		prg.history = byte(fatalMessage)
  3586  		prg.jumpOut()
  3587  	}
  3588  	prg.curReplText = prg.textPtr
  3589  	prg.tokStart[int32(prg.textPtr)+zz] = prg.tokPtr[prg.z]
  3590  	prg.textPtr = uint16(int32(prg.textPtr) + 1)
  3591  	if int32(prg.z) == zz-1 {
  3592  		prg.z = 0
  3593  	} else {
  3594  		prg.z = byte(int32(prg.z) + 1)
  3595  	}
  3596  }
  3597  
  3598  // 170.
  3599  
  3600  // tangle:pos tangle.web:3057:3:
  3601  
  3602  // The following procedure is used to define a simple or parametric macro,
  3603  // just after the `\.[==]' of its definition has been scanned.
  3604  func (prg *prg) defineMacro(t eightBits) {
  3605  	var (
  3606  		p namePointer // the identifier being defined
  3607  	)
  3608  	p = prg.idLookup(t)
  3609  	prg.scanRepl(t)
  3610  
  3611  	prg.equiv[p] = prg.curReplText
  3612  	prg.textLink[prg.curReplText] = 0
  3613  }
  3614  
  3615  // 172.
  3616  
  3617  // tangle:pos tangle.web:3075:3:
  3618  
  3619  // The top level of |scan_module| is trivial.
  3620  func (prg *prg) scanModule() {
  3621  	var (
  3622  		p namePointer // module name for the current module
  3623  	)
  3624  	prg.moduleCount = uint16(int32(prg.moduleCount) + 1)
  3625  
  3626  	// Scan the \(definition part of the current module
  3627  	prg.nextControl = 0
  3628  	for true {
  3629  	continue1:
  3630  		for int32(prg.nextControl) <= format {
  3631  			prg.nextControl = prg.skipAhead()
  3632  			if int32(prg.nextControl) == moduleName {
  3633  				prg.loc = byte(int32(prg.loc) - 2)
  3634  				prg.nextControl = prg.getNext()
  3635  			}
  3636  		}
  3637  		if int32(prg.nextControl) != definition {
  3638  			goto done
  3639  		}
  3640  		prg.nextControl = prg.getNext() // get identifier name
  3641  		if int32(prg.nextControl) != identifier {
  3642  			{
  3643  				prg.stdout.Writeln()
  3644  				prg.stdout.Write("! Definition flushed, must start with ",
  3645  					// \xref[Definition flushed...]
  3646  					"identifier of length > 1")
  3647  				prg.error1()
  3648  			}
  3649  			goto continue1
  3650  		}
  3651  		prg.nextControl = prg.getNext() // get token after the identifier
  3652  		if int32(prg.nextControl) == '=' {
  3653  			prg.scanNumeric(prg.idLookup(eightBits(numeric)))
  3654  			goto continue1
  3655  		} else if int32(prg.nextControl) == equivalenceSign {
  3656  			prg.defineMacro(eightBits(simple))
  3657  			goto continue1
  3658  		} else if int32(prg.nextControl) == '(' {
  3659  			prg.nextControl = prg.getNext()
  3660  			if int32(prg.nextControl) == '#' {
  3661  				prg.nextControl = prg.getNext()
  3662  				if int32(prg.nextControl) == ')' {
  3663  					prg.nextControl = prg.getNext()
  3664  					if int32(prg.nextControl) == '=' {
  3665  						{
  3666  							prg.stdout.Writeln()
  3667  							prg.stdout.Write("! Use == for macros")
  3668  							prg.error1()
  3669  						}
  3670  						// \xref[Use == for macros]
  3671  						prg.nextControl = byte(equivalenceSign)
  3672  					}
  3673  					if int32(prg.nextControl) == equivalenceSign {
  3674  						prg.defineMacro(eightBits(parametric))
  3675  						goto continue1
  3676  					}
  3677  				}
  3678  			}
  3679  		}
  3680  
  3681  		{
  3682  			prg.stdout.Writeln()
  3683  			prg.stdout.Write("! Definition flushed since it starts badly")
  3684  			prg.error1()
  3685  		}
  3686  		// \xref[Definition flushed...]
  3687  	}
  3688  
  3689  done:
  3690  	;
  3691  
  3692  	// Scan the \PASCAL\ part of the current module
  3693  	switch prg.nextControl {
  3694  	case beginPascal:
  3695  		p = 0
  3696  	case moduleName:
  3697  		p = prg.curModule
  3698  
  3699  		// Check that |=| or |==| follows this module name, otherwise |return|
  3700  		for {
  3701  			prg.nextControl = prg.getNext()
  3702  			if int32(prg.nextControl) != '+' {
  3703  				break
  3704  			}
  3705  		} // allow optional `\.[+=]'
  3706  		if int32(prg.nextControl) != '=' && int32(prg.nextControl) != equivalenceSign {
  3707  			{
  3708  				prg.stdout.Writeln()
  3709  				prg.stdout.Write("! Pascal text flushed, = sign is missing")
  3710  				prg.error1()
  3711  			}
  3712  			// \xref[Pascal text flushed...]
  3713  			for {
  3714  				prg.nextControl = prg.skipAhead()
  3715  				if int32(prg.nextControl) == newModule {
  3716  					break
  3717  				}
  3718  			}
  3719  
  3720  			goto exit
  3721  		}
  3722  
  3723  	default:
  3724  		goto exit
  3725  	}
  3726  
  3727  	// Insert the module number into |tok_mem|
  3728  	prg.storeTwoBytes(sixteenBits(0150000 + int32(prg.moduleCount))) // |@'150000=@'320*@'400|
  3729  
  3730  	prg.scanRepl(eightBits(moduleName)) // now |cur_repl_text| points to the replacement text
  3731  
  3732  	// Update the data structure so that the replacement text is accessible
  3733  	if int32(p) == 0 {
  3734  		prg.textLink[prg.lastUnnamed] = prg.curReplText
  3735  		prg.lastUnnamed = prg.curReplText
  3736  	} else if int32(prg.equiv[p]) == 0 {
  3737  		prg.equiv[p] = prg.curReplText
  3738  	} else {
  3739  		p = prg.equiv[p]
  3740  		for int32(prg.textLink[p]) < maxTexts {
  3741  			p = prg.textLink[p]
  3742  		} // find end of list
  3743  		prg.textLink[p] = prg.curReplText
  3744  	}
  3745  	prg.textLink[prg.curReplText] = uint16(maxTexts)
  3746  	// mark this replacement text as a nonmacro
  3747  
  3748  exit:
  3749  }
  3750  
  3751  // 181.
  3752  //  procedure debug_help; [routine to display various things]
  3753  // label breakpoint,exit;
  3754  // var k:integer; [index into various arrays]
  3755  // begin   debug_skipped:= debug_skipped+1 ;
  3756  // if debug_skipped<debug_cycle then  goto exit ;
  3757  // debug_skipped:=0;
  3758  //  while true do    begin  begin writeln()  ; write('#') ; end ;  ; [prompt]
  3759  //   read(term_in,ddt); [read a debug-command code]
  3760  //   if ddt<0 then  goto exit
  3761  //   else if ddt=0 then
  3762  //     begin goto breakpoint;
  3763  //  [go to every label at least once]
  3764  //     breakpoint: ddt:=0;
  3765  //
  3766  //     end
  3767  //   else  begin read(term_in,dd);
  3768  //     case ddt of
  3769  //     1: print_id(dd);
  3770  //     2: print_repl(dd);
  3771  //     3: for k:=1 to dd do write( xchr[ buffer[ k]]) ;
  3772  //     4: for k:=1 to dd do write( xchr[ mod_text[ k]]) ;
  3773  //     5: for k:=1 to out_ptr do write( xchr[ out_buf[ k]]) ;
  3774  //     6: for k:=1 to dd do write( xchr[ out_contrib[ k]]) ;
  3775  //      else  write('?')
  3776  //      end ;
  3777  //     end;
  3778  //   end;
  3779  // exit:end;
  3780  // [  ]
  3781  
  3782  // 182. The main program
  3783  
  3784  // tangle:pos tangle.web:3240:21:
  3785  
  3786  // We have defined plenty of procedures, and it is time to put the last
  3787  // pieces of the puzzle in place. Here is where \.[TANGLE] starts, and where
  3788  // it ends.
  3789  // \xref[system dependencies]
  3790  func (prg *prg) main() {
  3791  	defer func() {
  3792  		if prg.changeFile != nil {
  3793  			prg.changeFile.Close()
  3794  		}
  3795  		if prg.pascalFile != nil {
  3796  			prg.pascalFile.Close()
  3797  		}
  3798  		if prg.pool != nil {
  3799  			prg.pool.Close()
  3800  		}
  3801  		if prg.stderr != nil {
  3802  			prg.stderr.Close()
  3803  		}
  3804  		if prg.stdin != nil {
  3805  			prg.stdin.Close()
  3806  		}
  3807  		if prg.stdout != nil {
  3808  			prg.stdout.Close()
  3809  		}
  3810  		if prg.termOut != nil {
  3811  			prg.termOut.Close()
  3812  		}
  3813  		if prg.webFile != nil {
  3814  			prg.webFile.Close()
  3815  		}
  3816  	}()
  3817  
  3818  	prg.initialize()
  3819  
  3820  	// Initialize the input system
  3821  	prg.openInput()
  3822  	prg.line = 0
  3823  	prg.otherLine = 0
  3824  
  3825  	prg.changing = true
  3826  	prg.primeTheChangeBuffer()
  3827  	prg.changing = !prg.changing
  3828  	prg.tempLine = prg.otherLine
  3829  	prg.otherLine = prg.line
  3830  	prg.line = prg.tempLine
  3831  
  3832  	prg.limit = 0
  3833  	prg.loc = 1
  3834  	prg.buffer[0] = ' '
  3835  	prg.inputHasEnded = false
  3836  
  3837  	prg.stdout.Writeln("This is TANGLE, Version 4.6 (gotangle v0.0-prereleaase)") // print a ``banner line''
  3838  
  3839  	// Phase I: Read all the user's text and compress it into |tok_mem|
  3840  	prg.phaseOne = true
  3841  	prg.moduleCount = 0
  3842  	for {
  3843  		prg.nextControl = prg.skipAhead()
  3844  		if int32(prg.nextControl) == newModule {
  3845  			break
  3846  		}
  3847  	}
  3848  	for !prg.inputHasEnded {
  3849  		prg.scanModule()
  3850  	}
  3851  
  3852  	// Check that all changes have been read
  3853  	if int32(prg.changeLimit) != 0 {
  3854  		for ii := int32(0); ii <= int32(prg.changeLimit)-1; ii++ {
  3855  			prg.ii1 = ii
  3856  			_ = prg.ii1
  3857  			prg.buffer[prg.ii1] = prg.changeBuffer[prg.ii1]
  3858  		}
  3859  		prg.limit = prg.changeLimit
  3860  		prg.changing = true
  3861  		prg.line = prg.otherLine
  3862  		prg.loc = prg.changeLimit
  3863  		{
  3864  			prg.stdout.Writeln()
  3865  			prg.stdout.Write("! Change file entry did not match")
  3866  			prg.error1()
  3867  		}
  3868  		// \xref[Change file entry did not match]
  3869  	}
  3870  	prg.phaseOne = false
  3871  
  3872  	//  for ii:=0 to zz-1 do max_tok_ptr[ii]:=tok_ptr[ii]; [  ]
  3873  
  3874  	// Phase II:...
  3875  	if int32(prg.textLink[0]) == 0 {
  3876  		{
  3877  			prg.stdout.Writeln()
  3878  			prg.stdout.Write("! No output was specified.")
  3879  		} /*   */
  3880  		if int32(prg.history) == spotless {
  3881  			prg.history = byte(harmlessMessage)
  3882  		}
  3883  		// \xref[No output was specified]
  3884  	} else {
  3885  		{
  3886  			prg.stdout.Writeln()
  3887  			prg.stdout.Write("Writing the output file")
  3888  		}
  3889  
  3890  		// Initialize the output stacks
  3891  		prg.stackPtr = 1
  3892  		prg.braceLevel = 0
  3893  		prg.curState.nameField = 0
  3894  		prg.curState.replField = prg.textLink[0]
  3895  		prg.zo = byte(int32(prg.curState.replField) % zz)
  3896  		prg.curState.byteField = prg.tokStart[prg.curState.replField]
  3897  		prg.curState.endField = prg.tokStart[int32(prg.curState.replField)+zz]
  3898  		prg.curState.modField = 0
  3899  
  3900  		// Initialize the output buffer
  3901  		prg.outState = byte(misc)
  3902  		prg.outPtr = 0
  3903  		prg.breakPtr = 0
  3904  		prg.semiPtr = 0
  3905  		prg.outBuf[0] = 0
  3906  		prg.line = 1
  3907  
  3908  		prg.sendTheOutput()
  3909  
  3910  		// Empty the last line...
  3911  		prg.breakPtr = prg.outPtr
  3912  		prg.semiPtr = 0
  3913  		prg.flushBuffer()
  3914  		if int32(prg.braceLevel) != 0 {
  3915  			prg.stdout.Writeln()
  3916  			prg.stdout.Write("! Program ended at brace level ", prg.braceLevel, knuth.WriteWidth(1))
  3917  			prg.error1()
  3918  		}
  3919  		// \xref[Program ended at brace level n]
  3920  
  3921  		{
  3922  			prg.stdout.Writeln()
  3923  			prg.stdout.Write("Done.")
  3924  		}
  3925  	}
  3926  	if int32(prg.stringPtr) > 256 {
  3927  		{
  3928  			prg.stdout.Writeln()
  3929  			prg.stdout.Write(int32(prg.stringPtr)-256, knuth.WriteWidth(1), " strings written to string pool file.")
  3930  		}
  3931  		prg.pool.Write("*")
  3932  		for ii := int32(1); ii <= 9; ii++ {
  3933  			prg.ii1 = ii
  3934  			_ = prg.ii1
  3935  			prg.outBuf[prg.ii1] = byte(prg.poolCheckSum % 10)
  3936  			prg.poolCheckSum = prg.poolCheckSum / 10
  3937  		}
  3938  		for ii := int32(9); ii >= 1; ii-- {
  3939  			prg.ii1 = ii
  3940  			_ = prg.ii1
  3941  			prg.pool.Write(string(rune(prg.xchr['0'+int32(prg.outBuf[prg.ii1])])))
  3942  		}
  3943  		prg.pool.Writeln()
  3944  	}
  3945  	//
  3946  	// [ Print statistics about memory usage ]
  3947  	//  begin writeln()  ; write('Memory usage statistics:') ; end ;
  3948  	//  begin writeln()  ; write(  name_ptr:  1, ' names, ',   text_ptr:  1, ' replacement texts;') ; end ;
  3949  	//  begin writeln()  ; write(  byte_ptr[  0]:  1) ; end ;
  3950  	// for wo:=1 to ww-1 do write('+', byte_ptr[ wo]: 1) ;
  3951  	// if phase_one then
  3952  	//   for ii:=0 to zz-1 do max_tok_ptr[ii]:=tok_ptr[ii];
  3953  	// write(' bytes, ',  max_tok_ptr[ 0]: 1) ;
  3954  	// for ii:=1 to zz-1 do write('+', max_tok_ptr[ ii]: 1) ;
  3955  	// write(' tokens.') ;
  3956  	//
  3957  	// ; [  ]
  3958  
  3959  	// \4\4
  3960  	// here files should be closed if the operating system requires it
  3961  
  3962  	// Print the job |history|
  3963  	switch prg.history {
  3964  	case spotless:
  3965  		prg.stdout.Writeln()
  3966  		prg.stdout.Write("(No errors were found.)")
  3967  	case harmlessMessage:
  3968  		prg.stdout.Writeln()
  3969  		prg.stdout.Write("(Did you see the warning message above?)")
  3970  	case errorMessage:
  3971  		prg.stdout.Writeln()
  3972  		prg.stdout.Write("(Pardon me, but I think I spotted something wrong.)")
  3973  	case fatalMessage:
  3974  		prg.stdout.Writeln()
  3975  		prg.stdout.Write("(That was a fatal error, my friend.)")
  3976  	}
  3977  	prg.stdout.Writeln()
  3978  }
  3979  
  3980  // 188. System-dependent changes
  3981  
  3982  // tangle:pos tangle.web:3307:29:
  3983  
  3984  // This module should be replaced, if necessary, by changes to the program
  3985  // that are necessary to make \.[TANGLE] work at a particular installation.
  3986  // It is usually best to design your change file so that all changes to
  3987  // previous modules preserve the module numbering; then everybody's version
  3988  // will be consistent with the printed program. More extensive changes,
  3989  // which introduce new modules, can be inserted here; then only the index
  3990  // itself will get a new module number.
  3991  // \xref[system dependencies]
  3992  
  3993  // 189. Index
  3994  
  3995  // tangle:pos tangle.web:3317:10:
  3996  
  3997  // Here is a cross-reference table for the \.[TANGLE] processor.
  3998  // All modules in which an identifier is
  3999  // used are listed with that identifier, except that reserved words are
  4000  // indexed only when they appear in format definitions, and the appearances
  4001  // of identifiers in module names are not indexed. Underlined entries
  4002  // correspond to where the identifier was declared. Error messages and
  4003  // a few other things like ``ASCII code'' are indexed here too.