1 {2:}{4:}{$C-,A+,D-}{[$C+,D+]}
2 {:4}program TANGLE(webfile,changefile,Pascalfile,pool);
3 const{8:}bufsize=3000;maxbytes=65535;maxtoks=65535;maxnames=10000;
4 maxtexts=10000;hashsize=353;longestname=400;linelength=72;
5 outbufsize=144;stacksize=100;maxidlength=50;defunambiglength=32;
6 {:8}type{11:}ASCIIcode=0..255;
7 {:11}{12:}textfile=packed file of ASCIIcode;{:12}{37:}eightbits=0..255;
8 sixteenbits=0..65535;{:37}{39:}namepointer=0..maxnames;
9 {:39}{43:}textpointer=0..maxtexts;
10 {:43}{78:}outputstate=record endfield:sixteenbits;bytefield:sixteenbits;
11 namefield:namepointer;replfield:textpointer;modfield:0..12287;end;
12 {:78}var{9:}history:0..3;{:9}{13:}xord:array[ASCIIcode]of ASCIIcode;
13 xchr:array[ASCIIcode]of ASCIIcode;{:13}{23:}webfile:textfile;
14 changefile:textfile;{:23}{25:}Pascalfile:textfile;pool:textfile;
15 {:25}{27:}buffer:array[0..bufsize]of ASCIIcode;
16 {:27}{29:}phaseone:boolean;
17 {:29}{38:}bytemem:packed array[0..2,0..maxbytes]of ASCIIcode;
18 tokmem:packed array[0..4,0..maxtoks]of eightbits;
19 bytestart:array[0..maxnames]of sixteenbits;
20 tokstart:array[0..maxtexts]of sixteenbits;
21 link:array[0..maxnames]of sixteenbits;
22 ilk:array[0..maxnames]of sixteenbits;equiv:array[0..maxnames]of integer;
23 textlink:array[0..maxtexts]of sixteenbits;{:38}{40:}nameptr:namepointer;
24 stringptr:namepointer;byteptr:array[0..2]of 0..maxbytes;
25 poolchecksum:integer;{:40}{44:}textptr:textpointer;
26 tokptr:array[0..4]of 0..maxtoks;z:0..4;
27 {maxtokptr:array[0..4]of 0..maxtoks;}{:44}{50:}idfirst:0..bufsize;
28 idloc:0..bufsize;doublechars:0..bufsize;
29 hash,chophash:array[0..hashsize]of sixteenbits;
30 choppedid:array[0..maxidlength]of ASCIIcode;
31 {:50}{65:}modtext:array[0..longestname]of ASCIIcode;
32 {:65}{70:}lastunnamed:textpointer;{:70}{79:}curstate:outputstate;
33 stack:array[1..stacksize]of outputstate;stackptr:0..stacksize;
34 {:79}{80:}zo:0..4;{:80}{82:}bracelevel:eightbits;
35 {:82}{86:}curval:integer;
36 {:86}{94:}outbuf:array[0..outbufsize]of ASCIIcode;outptr:0..outbufsize;
37 breakptr:0..outbufsize;semiptr:0..outbufsize;
38 {:94}{95:}outstate:eightbits;outval,outapp:integer;outsign:ASCIIcode;
39 lastsign:-1..+1;{:95}{100:}outcontrib:array[1..linelength]of ASCIIcode;
40 {:100}{124:}ii:integer;line:integer;otherline:integer;templine:integer;
41 limit:0..bufsize;loc:0..bufsize;inputhasended:boolean;changing:boolean;
42 {:124}{126:}changebuffer:array[0..bufsize]of ASCIIcode;
43 changelimit:0..bufsize;{:126}{143:}curmodule:namepointer;
44 scanninghex:boolean;{:143}{156:}nextcontrol:eightbits;
45 {:156}{164:}currepltext:textpointer;{:164}{171:}modulecount:0..12287;
46 {:171}{179:}{troubleshooting:boolean;ddt:integer;dd:integer;
47 debugcycle:integer;debugskipped:integer;}{:179}{185:}{wo:0..2;}
48 {:185}{199:}webname,chgname,pascalname,poolname:constcstring;
49 forceuppercase,forcelowercase,allowunderlines,strictmode:boolean;
50 unambiglength:0..maxidlength;{:199}{30:}{procedure debughelp;forward;}
51 {:30}{31:}procedure error;var j:0..outbufsize;k,l:0..bufsize;
52 begin if phaseone then{32:}begin if changing then write(stdout,
53 '. (change file ')else write(stdout,'. (');
54 writeln(stdout,'l.',line:1,')');if loc>=limit then l:=limit else l:=loc;
55 for k:=1 to l do if buffer[k-1]=9 then write(stdout,' ')else write(
56 stdout,xchr[buffer[k-1]]);writeln(stdout);
57 for k:=1 to l do write(stdout,' ');
58 for k:=l+1 to limit do write(stdout,xchr[buffer[k-1]]);
60 end{:32}else{33:}begin writeln(stdout,'. (l.',line:1,')');
61 for j:=1 to outptr do write(stdout,xchr[outbuf[j-1]]);
62 write(stdout,'... ');end{:33};fflush(stdout);history:=2;
63 {debugskipped:=debugcycle;debughelp;}end;
64 {:31}{188:}procedure parsearguments;const noptions=10;
65 var longoptions:array[0..noptions]of getoptstruct;
66 getoptreturnval:integer;optionindex:cinttype;currentoption:0..noptions;
67 len:integer;begin{189:}currentoption:=0;
68 longoptions[currentoption].name:='help';
69 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
70 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
71 {:189}{190:}longoptions[currentoption].name:='version';
72 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
73 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
74 {:190}{191:}longoptions[currentoption].name:='mixedcase';
75 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
76 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
77 {:191}{192:}longoptions[currentoption].name:='uppercase';
78 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
79 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
80 {:192}{193:}longoptions[currentoption].name:='lowercase';
81 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
82 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
83 {:193}{194:}longoptions[currentoption].name:='underlines';
84 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
85 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
86 {:194}{195:}longoptions[currentoption].name:='strict';
87 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
88 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
89 {:195}{196:}longoptions[currentoption].name:='loose';
90 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
91 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
92 {:196}{197:}longoptions[currentoption].name:='length';
93 longoptions[currentoption].hasarg:=1;longoptions[currentoption].flag:=0;
94 longoptions[currentoption].val:=0;currentoption:=currentoption+1;
95 {:197}{198:}longoptions[currentoption].name:=0;
96 longoptions[currentoption].hasarg:=0;longoptions[currentoption].flag:=0;
97 longoptions[currentoption].val:=0;{:198};
98 unambiglength:=defunambiglength;
99 repeat getoptreturnval:=getoptlongonly(argc,argv,'',longoptions,
100 addressof(optionindex));if getoptreturnval=-1 then begin;
101 end else if getoptreturnval=63 then begin usage('tangle');
102 end else if(strcmp(longoptions[optionindex].name,'help')=0)then begin
103 usagehelp(TANGLEHELP,nil);
104 end else if(strcmp(longoptions[optionindex].name,'version')=0)then begin
105 printversionandexit('This is TANGLE, Version 4.5',nil,'D.E. Knuth',nil);
106 end else if(strcmp(longoptions[optionindex].name,'mixedcase')=0)then
107 begin forceuppercase:=false;forcelowercase:=false;
108 end else if(strcmp(longoptions[optionindex].name,'uppercase')=0)then
109 begin forceuppercase:=true;forcelowercase:=false;
110 end else if(strcmp(longoptions[optionindex].name,'lowercase')=0)then
111 begin forceuppercase:=false;forcelowercase:=true;
112 end else if(strcmp(longoptions[optionindex].name,'underlines')=0)then
113 begin allowunderlines:=true;
114 end else if(strcmp(longoptions[optionindex].name,'strict')=0)then begin
116 end else if(strcmp(longoptions[optionindex].name,'loose')=0)then begin
118 end else if(strcmp(longoptions[optionindex].name,'length')=0)then begin
119 len:=atoi(optarg);if(len<=0)or(len>maxidlength)then len:=maxidlength;
120 unambiglength:=len;end;until getoptreturnval=-1;
121 if(optind+1<>argc)and(optind+2<>argc)then begin writeln(stderr,'tangle',
122 ': Need one or two file arguments.');usage('tangle');end;
123 webname:=extendfilename(cmdline(optind),'web');
124 if optind+2=argc then begin chgname:=extendfilename(cmdline(optind+1),
125 'ch');end;pascalname:=basenamechangesuffix(webname,'.web','.p');end;
126 {:188}procedure initialize;var{16:}i:0..255;{:16}{41:}wi:0..2;
127 {:41}{45:}zi:0..4;{:45}{51:}h:0..hashsize;
128 {:51}begin kpsesetprogramname(argv[0],'tangle');parsearguments;
129 {10:}history:=0;{:10}{14:}xchr[32]:=' ';xchr[33]:='!';xchr[34]:='"';
130 xchr[35]:='#';xchr[36]:='$';xchr[37]:='%';xchr[38]:='&';xchr[39]:='''';
131 xchr[40]:='(';xchr[41]:=')';xchr[42]:='*';xchr[43]:='+';xchr[44]:=',';
132 xchr[45]:='-';xchr[46]:='.';xchr[47]:='/';xchr[48]:='0';xchr[49]:='1';
133 xchr[50]:='2';xchr[51]:='3';xchr[52]:='4';xchr[53]:='5';xchr[54]:='6';
134 xchr[55]:='7';xchr[56]:='8';xchr[57]:='9';xchr[58]:=':';xchr[59]:=';';
135 xchr[60]:='<';xchr[61]:='=';xchr[62]:='>';xchr[63]:='?';xchr[64]:='@';
136 xchr[65]:='A';xchr[66]:='B';xchr[67]:='C';xchr[68]:='D';xchr[69]:='E';
137 xchr[70]:='F';xchr[71]:='G';xchr[72]:='H';xchr[73]:='I';xchr[74]:='J';
138 xchr[75]:='K';xchr[76]:='L';xchr[77]:='M';xchr[78]:='N';xchr[79]:='O';
139 xchr[80]:='P';xchr[81]:='Q';xchr[82]:='R';xchr[83]:='S';xchr[84]:='T';
140 xchr[85]:='U';xchr[86]:='V';xchr[87]:='W';xchr[88]:='X';xchr[89]:='Y';
141 xchr[90]:='Z';xchr[91]:='[';xchr[92]:='\';xchr[93]:=']';xchr[94]:='^';
142 xchr[95]:='_';xchr[96]:='`';xchr[97]:='a';xchr[98]:='b';xchr[99]:='c';
143 xchr[100]:='d';xchr[101]:='e';xchr[102]:='f';xchr[103]:='g';
144 xchr[104]:='h';xchr[105]:='i';xchr[106]:='j';xchr[107]:='k';
145 xchr[108]:='l';xchr[109]:='m';xchr[110]:='n';xchr[111]:='o';
146 xchr[112]:='p';xchr[113]:='q';xchr[114]:='r';xchr[115]:='s';
147 xchr[116]:='t';xchr[117]:='u';xchr[118]:='v';xchr[119]:='w';
148 xchr[120]:='x';xchr[121]:='y';xchr[122]:='z';xchr[123]:='{';
149 xchr[124]:='|';xchr[125]:='}';xchr[126]:='~';xchr[0]:=' ';
150 xchr[127]:=' ';{:14}{17:}for i:=1 to 31 do xchr[i]:=chr(i);
151 for i:=128 to 255 do xchr[i]:=chr(i);
152 {:17}{18:}for i:=0 to 255 do xord[chr(i)]:=32;
153 for i:=1 to 255 do xord[xchr[i]]:=i;xord[' ']:=32;
154 {:18}{21:}{:21}{26:}rewrite(Pascalfile,pascalname);
155 {:26}{42:}for wi:=0 to 2 do begin bytestart[wi]:=0;byteptr[wi]:=0;end;
156 bytestart[3]:=0;nameptr:=1;stringptr:=256;poolchecksum:=271828;
157 {:42}{46:}for zi:=0 to 4 do begin tokstart[zi]:=0;tokptr[zi]:=0;end;
158 tokstart[5]:=0;textptr:=1;z:=1 mod 5;{:46}{48:}ilk[0]:=0;equiv[0]:=0;
159 {:48}{52:}for h:=0 to hashsize-1 do begin hash[h]:=0;chophash[h]:=0;end;
160 {:52}{71:}lastunnamed:=0;textlink[0]:=0;{:71}{144:}scanninghex:=false;
161 {:144}{152:}modtext[0]:=32;{:152}{180:}{troubleshooting:=true;
162 debugcycle:=1;debugskipped:=0;troubleshooting:=false;debugcycle:=99999;}
163 {:180}end;{:2}{24:}procedure openinput;
164 begin webfile:=kpseopenfile(webname,kpsewebformat);
165 if chgname then changefile:=kpseopenfile(chgname,kpsewebformat);end;
166 {:24}{28:}function inputln(var f:textfile):boolean;
167 var finallimit:0..bufsize;begin limit:=0;finallimit:=0;
168 if eof(f)then inputln:=false else begin while not eoln(f)do begin buffer
169 [limit]:=xord[getc(f)];limit:=limit+1;
170 if buffer[limit-1]<>32 then finallimit:=limit;
171 if limit=bufsize then begin while not eoln(f)do vgetc(f);limit:=limit-1;
172 if finallimit>limit then finallimit:=limit;begin writeln(stdout);
173 write(stdout,'! Input line too long');end;loc:=0;error;end;end;
174 readln(f);limit:=finallimit;inputln:=true;end;end;
175 {:28}{49:}procedure printid(p:namepointer);var k:0..maxbytes;w:0..2;
176 begin if p>=nameptr then write(stdout,'IMPOSSIBLE')else begin w:=p mod 3
178 for k:=bytestart[p]to bytestart[p+3]-1 do write(stdout,xchr[bytemem[w,k]
179 ]);end;end;{:49}{53:}function idlookup(t:eightbits):namepointer;
180 label 31,32;var c:eightbits;i:0..bufsize;h:0..hashsize;k:0..maxbytes;
181 w:0..2;l:0..bufsize;p,q:namepointer;s:0..maxidlength;
182 begin l:=idloc-idfirst;{54:}h:=buffer[idfirst];i:=idfirst+1;
183 while i<idloc do begin h:=(h+h+buffer[i])mod hashsize;i:=i+1;end{:54};
185 while p<>0 do begin if bytestart[p+3]-bytestart[p]=l then{56:}begin i:=
186 idfirst;k:=bytestart[p];w:=p mod 3;
187 while(i<idloc)and(buffer[i]=bytemem[w,k])do begin i:=i+1;k:=k+1;end;
188 if i=idloc then goto 31;end{:56};p:=link[p];end;p:=nameptr;
189 link[p]:=hash[h];hash[h]:=p;31:{:55};
190 if(p=nameptr)or(t<>0)then{57:}begin if((p<>nameptr)and(t<>0)and(ilk[p]=0
191 ))or((p=nameptr)and(t=0)and(buffer[idfirst]<>34))then{58:}begin i:=
193 while(i<idloc)and(s<unambiglength)do begin if(buffer[i]<>95)or(
194 allowunderlines and not strictmode)then begin if(strictmode or
195 forceuppercase)and(buffer[i]>=97)then choppedid[s]:=buffer[i]-32 else if
196 (not strictmode and forcelowercase)and(buffer[i]>=65)and(buffer[i]<=90)
197 then choppedid[s]:=buffer[i]+32 else choppedid[s]:=buffer[i];
198 h:=(h+h+choppedid[s])mod hashsize;s:=s+1;end;i:=i+1;end;choppedid[s]:=0;
200 if p<>nameptr then{59:}begin if ilk[p]=0 then begin if t=1 then begin
201 writeln(stdout);write(stdout,'! This identifier has already appeared');
202 error;end;{60:}q:=chophash[h];
203 if q=p then chophash[h]:=equiv[p]else begin while equiv[q]<>p do q:=
204 equiv[q];equiv[q]:=equiv[p];end{:60};end else begin writeln(stdout);
205 write(stdout,'! This identifier was defined before');error;end;
207 end{:59}else{61:}begin if(t=0)and(buffer[idfirst]<>34)then{62:}begin q:=
208 chophash[h];while q<>0 do begin{63:}begin k:=bytestart[q];s:=0;
210 while(k<bytestart[q+3])and(s<unambiglength)do begin c:=bytemem[w,k];
211 if c<>95 or(allowunderlines and not strictmode)then begin if(strictmode
212 or forceuppercase)and(c>=97)then c:=c-32 else if(not strictmode and
213 forcelowercase)and(c>=65)and(c<=90)then c:=c+32;
214 if choppedid[s]<>c then goto 32;s:=s+1;end;k:=k+1;end;
215 if(k=bytestart[q+3])and(choppedid[s]<>0)then goto 32;
216 begin writeln(stdout);write(stdout,'! Identifier conflict with ');end;
217 for k:=bytestart[q]to bytestart[q+3]-1 do write(stdout,xchr[bytemem[w,k]
218 ]);error;q:=0;32:end{:63};q:=equiv[q];end;equiv[p]:=chophash[h];
219 chophash[h]:=p;end{:62};w:=nameptr mod 3;k:=byteptr[w];
220 if k+l>maxbytes then begin writeln(stdout);
221 write(stderr,'! Sorry, ','byte memory',' capacity exceeded');error;
222 history:=3;uexit(1);end;
223 if nameptr>maxnames-3 then begin writeln(stdout);
224 write(stderr,'! Sorry, ','name',' capacity exceeded');error;history:=3;
225 uexit(1);end;i:=idfirst;while i<idloc do begin bytemem[w,k]:=buffer[i];
226 k:=k+1;i:=i+1;end;byteptr[w]:=k;bytestart[nameptr+3]:=k;
228 if buffer[idfirst]<>34 then ilk[p]:=t else{64:}begin ilk[p]:=1;
229 if l-doublechars=2 then equiv[p]:=buffer[idfirst+1]+1073741824 else
230 begin if stringptr=256 then begin poolname:=basenamechangesuffix(webname
231 ,'.web','.pool');rewritebin(pool,poolname);end;
232 equiv[p]:=stringptr+1073741824;l:=l-doublechars-1;
233 if l>99 then begin writeln(stdout);
234 write(stdout,'! Preprocessed string is too long');error;end;
235 stringptr:=stringptr+1;write(pool,xchr[48+l div 10],xchr[48+l mod 10]);
236 poolchecksum:=poolchecksum+poolchecksum+l;
237 while poolchecksum>536870839 do poolchecksum:=poolchecksum-536870839;
238 i:=idfirst+1;while i<idloc do begin write(pool,xchr[buffer[i]]);
239 poolchecksum:=poolchecksum+poolchecksum+buffer[i];
240 while poolchecksum>536870839 do poolchecksum:=poolchecksum-536870839;
241 if(buffer[i]=34)or(buffer[i]=64)then i:=i+2 else i:=i+1;end;
242 writeln(pool);end;end{:64};end{:61};end{:57};idlookup:=p;end;
243 {:53}{66:}function modlookup(l:sixteenbits):namepointer;label 31;
244 var c:0..4;j:0..longestname;k:0..maxbytes;w:0..2;p:namepointer;
245 q:namepointer;begin c:=2;q:=0;p:=ilk[0];
246 while p<>0 do begin{68:}begin k:=bytestart[p];w:=p mod 3;c:=1;j:=1;
247 while(k<bytestart[p+3])and(j<=l)and(modtext[j]=bytemem[w,k])do begin k:=
249 if k=bytestart[p+3]then if j>l then c:=1 else c:=4 else if j>l then c:=3
250 else if modtext[j]<bytemem[w,k]then c:=0 else c:=2;end{:68};q:=p;
251 if c=0 then p:=link[q]else if c=2 then p:=ilk[q]else goto 31;end;
252 {67:}w:=nameptr mod 3;k:=byteptr[w];
253 if k+l>maxbytes then begin writeln(stdout);
254 write(stderr,'! Sorry, ','byte memory',' capacity exceeded');error;
255 history:=3;uexit(1);end;
256 if nameptr>maxnames-3 then begin writeln(stdout);
257 write(stderr,'! Sorry, ','name',' capacity exceeded');error;history:=3;
258 uexit(1);end;p:=nameptr;if c=0 then link[q]:=p else ilk[q]:=p;
259 link[p]:=0;ilk[p]:=0;c:=1;equiv[p]:=0;
260 for j:=1 to l do bytemem[w,k+j-1]:=modtext[j];byteptr[w]:=k+l;
261 bytestart[nameptr+3]:=k+l;nameptr:=nameptr+1;{:67};
262 31:if c<>1 then begin begin writeln(stdout);
263 write(stdout,'! Incompatible section names');error;end;p:=0;end;
265 {:66}{69:}function prefixlookup(l:sixteenbits):namepointer;var c:0..4;
266 count:0..maxnames;j:0..longestname;k:0..maxbytes;w:0..2;p:namepointer;
267 q:namepointer;r:namepointer;begin q:=0;p:=ilk[0];count:=0;r:=0;
268 while p<>0 do begin{68:}begin k:=bytestart[p];w:=p mod 3;c:=1;j:=1;
269 while(k<bytestart[p+3])and(j<=l)and(modtext[j]=bytemem[w,k])do begin k:=
271 if k=bytestart[p+3]then if j>l then c:=1 else c:=4 else if j>l then c:=3
272 else if modtext[j]<bytemem[w,k]then c:=0 else c:=2;end{:68};
273 if c=0 then p:=link[p]else if c=2 then p:=ilk[p]else begin r:=p;
274 count:=count+1;q:=ilk[p];p:=link[p];end;if p=0 then begin p:=q;q:=0;end;
275 end;if count<>1 then if count=0 then begin writeln(stdout);
276 write(stdout,'! Name does not match');error;
277 end else begin writeln(stdout);write(stdout,'! Ambiguous prefix');error;
278 end;prefixlookup:=r;end;
279 {:69}{73:}procedure storetwobytes(x:sixteenbits);
280 begin if tokptr[z]+2>maxtoks then begin writeln(stdout);
281 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
282 uexit(1);end;tokmem[z,tokptr[z]]:=x div 256;
283 tokmem[z,tokptr[z]+1]:=x mod 256;tokptr[z]:=tokptr[z]+2;end;
284 {:73}{74:}{procedure printrepl(p:textpointer);var k:0..maxtoks;
285 a:sixteenbits;zp:0..4;
286 begin if p>=textptr then write(stdout,'BAD')else begin k:=tokstart[p];
287 zp:=p mod 5;while k<tokstart[p+5]do begin a:=tokmem[zp,k];
288 if a>=128 then[75:]begin k:=k+1;
289 if a<168 then begin a:=(a-128)*256+tokmem[zp,k];printid(a);
290 if bytemem[a mod 3,bytestart[a]]=34 then write(stdout,'"')else write(
291 stdout,' ');end else if a<208 then begin write(stdout,'@<');
292 printid((a-168)*256+tokmem[zp,k]);write(stdout,'@>');
293 end else begin a:=(a-208)*256+tokmem[zp,k];
294 write(stdout,'@',xchr[123],a:1,'@',xchr[125]);end;
295 end[:75]else[76:]case a of 9:write(stdout,'@',xchr[123]);
296 10:write(stdout,'@',xchr[125]);12:write(stdout,'@''');
297 13:write(stdout,'@"');125:write(stdout,'@$');0:write(stdout,'#');
298 64:write(stdout,'@@');2:write(stdout,'@=');3:write(stdout,'@\');
299 others:write(stdout,xchr[a])end[:76];k:=k+1;end;end;end;}
300 {:74}{84:}procedure pushlevel(p:namepointer);
301 begin if stackptr=stacksize then begin writeln(stdout);
302 write(stderr,'! Sorry, ','stack',' capacity exceeded');error;history:=3;
303 uexit(1);end else begin stack[stackptr]:=curstate;stackptr:=stackptr+1;
304 curstate.namefield:=p;curstate.replfield:=equiv[p];
305 zo:=curstate.replfield mod 5;
306 curstate.bytefield:=tokstart[curstate.replfield];
307 curstate.endfield:=tokstart[curstate.replfield+5];curstate.modfield:=0;
308 end;end;{:84}{85:}procedure poplevel;label 10;
309 begin if textlink[curstate.replfield]=0 then begin if(ilk[curstate.
310 namefield]=3)or(ilk[curstate.namefield]=4)then{91:}begin nameptr:=
311 nameptr-1;textptr:=textptr-1;z:=textptr mod 5;
312 {if tokptr[z]>maxtokptr[z]then maxtokptr[z]:=tokptr[z];}
313 tokptr[z]:=tokstart[textptr];
314 {byteptr[nameptr mod 3]:=byteptr[nameptr mod 3]-1;}end{:91};
315 end else if textlink[curstate.replfield]<maxtexts then begin curstate.
316 replfield:=textlink[curstate.replfield];zo:=curstate.replfield mod 5;
317 curstate.bytefield:=tokstart[curstate.replfield];
318 curstate.endfield:=tokstart[curstate.replfield+5];goto 10;end;
319 stackptr:=stackptr-1;if stackptr>0 then begin curstate:=stack[stackptr];
320 zo:=curstate.replfield mod 5;end;10:end;
321 {:85}{87:}function getoutput:sixteenbits;label 20,30,31;
322 var a:sixteenbits;b:eightbits;bal:sixteenbits;k:0..maxbytes;w:0..2;
323 begin 20:if stackptr=0 then begin a:=0;goto 31;end;
324 if curstate.bytefield=curstate.endfield then begin curval:=-curstate.
325 modfield;poplevel;if curval=0 then goto 20;a:=129;goto 31;end;
326 a:=tokmem[zo,curstate.bytefield];
327 curstate.bytefield:=curstate.bytefield+1;
328 if a<128 then if a=0 then{92:}begin pushlevel(nameptr-1);goto 20;
329 end{:92}else goto 31;a:=(a-128)*256+tokmem[zo,curstate.bytefield];
330 curstate.bytefield:=curstate.bytefield+1;
331 if a<10240 then{89:}begin case ilk[a]of 0:begin curval:=a;a:=130;end;
332 1:begin curval:=equiv[a]-1073741824;a:=128;end;2:begin pushlevel(a);
334 3,4:begin{90:}while(curstate.bytefield=curstate.endfield)and(stackptr>0)
336 if(stackptr=0)or((ilk[a]=3)and(tokmem[zo,curstate.bytefield]<>40))or((
337 ilk[a]=4)and(tokmem[zo,curstate.bytefield]<>91))then begin begin writeln
338 (stdout);write(stdout,'! No parameter given for ');end;printid(a);error;
339 goto 20;end;{93:}bal:=1;curstate.bytefield:=curstate.bytefield+1;
340 while true do begin b:=tokmem[zo,curstate.bytefield];
341 curstate.bytefield:=curstate.bytefield+1;
342 if b=0 then storetwobytes(nameptr+32767)else begin if b>=128 then begin
343 begin if tokptr[z]=maxtoks then begin writeln(stdout);
344 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
345 uexit(1);end;tokmem[z,tokptr[z]]:=b;tokptr[z]:=tokptr[z]+1;end;
346 b:=tokmem[zo,curstate.bytefield];
347 curstate.bytefield:=curstate.bytefield+1;
348 end else case b of 40:if ilk[a]=3 then bal:=bal+1;
349 41:if ilk[a]=3 then begin bal:=bal-1;if bal=0 then goto 30;end;
350 91:if ilk[a]=4 then bal:=bal+1;93:if ilk[a]=4 then begin bal:=bal-1;
351 if bal=0 then goto 30;end;
352 39:repeat begin if tokptr[z]=maxtoks then begin writeln(stdout);
353 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
354 uexit(1);end;tokmem[z,tokptr[z]]:=b;tokptr[z]:=tokptr[z]+1;end;
355 b:=tokmem[zo,curstate.bytefield];
356 curstate.bytefield:=curstate.bytefield+1;until b=39;others:end;
357 begin if tokptr[z]=maxtoks then begin writeln(stdout);
358 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
359 uexit(1);end;tokmem[z,tokptr[z]]:=b;tokptr[z]:=tokptr[z]+1;end;end;end;
360 30:{:93};equiv[nameptr]:=textptr;ilk[nameptr]:=2;w:=nameptr mod 3;
361 k:=byteptr[w];{if k=maxbytes then begin writeln(stdout);
362 write(stderr,'! Sorry, ','byte memory',' capacity exceeded');error;
363 history:=3;uexit(1);end;bytemem[w,k]:=35;k:=k+1;byteptr[w]:=k;}
364 if nameptr>maxnames-3 then begin writeln(stdout);
365 write(stderr,'! Sorry, ','name',' capacity exceeded');error;history:=3;
366 uexit(1);end;bytestart[nameptr+3]:=k;nameptr:=nameptr+1;
367 if textptr>maxtexts-5 then begin writeln(stdout);
368 write(stderr,'! Sorry, ','text',' capacity exceeded');error;history:=3;
369 uexit(1);end;textlink[textptr]:=0;tokstart[textptr+5]:=tokptr[z];
370 textptr:=textptr+1;z:=textptr mod 5{:90};pushlevel(a);goto 20;end;
371 others:begin writeln(stdout);
372 write(stderr,'! This can''t happen (','output',')');error;history:=3;
373 uexit(1);end end;goto 31;end{:89};if a<20480 then{88:}begin a:=a-10240;
374 if equiv[a]<>0 then pushlevel(a)else if a<>0 then begin begin writeln(
375 stdout);write(stdout,'! Not present: <');end;printid(a);
376 write(stdout,'>');error;end;goto 20;end{:88};curval:=a-20480;a:=129;
377 curstate.modfield:=curval;31:{if troubleshooting then debughelp;}
378 getoutput:=a;end;{:87}{97:}procedure flushbuffer;var k:0..outbufsize;
379 b:0..outbufsize;begin b:=breakptr;
380 if(semiptr<>0)and(outptr-semiptr<=linelength)then breakptr:=semiptr;
381 for k:=1 to breakptr do write(Pascalfile,xchr[outbuf[k-1]]);
382 writeln(Pascalfile);line:=line+1;
383 if line mod 100=0 then begin write(stdout,'.');
384 if line mod 500=0 then write(stdout,line:1);fflush(stdout);end;
385 if breakptr<outptr then begin if outbuf[breakptr]=32 then begin breakptr
386 :=breakptr+1;if breakptr>b then b:=breakptr;end;
387 for k:=breakptr to outptr-1 do outbuf[k-breakptr]:=outbuf[k];end;
388 outptr:=outptr-breakptr;breakptr:=b-breakptr;semiptr:=0;
389 if outptr>linelength then begin begin writeln(stdout);
390 write(stdout,'! Long line must be truncated');error;end;
391 outptr:=linelength;end;end;{:97}{99:}procedure appval(v:integer);
392 var k:0..outbufsize;begin k:=outbufsize;repeat outbuf[k]:=v mod 10;
393 v:=v div 10;k:=k-1;until v=0;repeat k:=k+1;
394 begin outbuf[outptr]:=outbuf[k]+48;outptr:=outptr+1;end;
395 until k=outbufsize;end;{:99}{101:}procedure sendout(t:eightbits;
396 v:sixteenbits);label 20;var k:0..linelength;
397 begin{102:}20:case outstate of 1:if t<>3 then begin breakptr:=outptr;
398 if t=2 then begin outbuf[outptr]:=32;outptr:=outptr+1;end;end;
399 2:begin begin outbuf[outptr]:=44-outapp;outptr:=outptr+1;end;
400 if outptr>linelength then flushbuffer;breakptr:=outptr;end;
401 3,4:begin{103:}if(outval<0)or((outval=0)and(lastsign<0))then begin
402 outbuf[outptr]:=45;outptr:=outptr+1;
403 end else if outsign>0 then begin outbuf[outptr]:=outsign;
404 outptr:=outptr+1;end;appval(abs(outval));
405 if outptr>linelength then flushbuffer;{:103};outstate:=outstate-2;
407 5:{104:}begin if(t=3)or({105:}((t=2)and(v=3)and(((outcontrib[1]=68)and(
408 outcontrib[2]=73)and(outcontrib[3]=86))or((outcontrib[1]=100)and(
409 outcontrib[2]=105)and(outcontrib[3]=118))or((outcontrib[1]=77)and(
410 outcontrib[2]=79)and(outcontrib[3]=68))or((outcontrib[1]=109)and(
411 outcontrib[2]=111)and(outcontrib[3]=100))))or((t=0)and((v=42)or(v=47)))
412 {:105})then begin{103:}if(outval<0)or((outval=0)and(lastsign<0))then
413 begin outbuf[outptr]:=45;outptr:=outptr+1;
414 end else if outsign>0 then begin outbuf[outptr]:=outsign;
415 outptr:=outptr+1;end;appval(abs(outval));
416 if outptr>linelength then flushbuffer;{:103};outsign:=43;outval:=outapp;
417 end else outval:=outval+outapp;outstate:=3;goto 20;end{:104};
418 0:if t<>3 then breakptr:=outptr;others:end{:102};
419 if t<>0 then for k:=1 to v do begin outbuf[outptr]:=outcontrib[k];
420 outptr:=outptr+1;end else begin outbuf[outptr]:=v;outptr:=outptr+1;end;
421 if outptr>linelength then flushbuffer;
422 if(t=0)and((v=59)or(v=125))then begin semiptr:=outptr;breakptr:=outptr;
423 end;if t>=2 then outstate:=1 else outstate:=0 end;
424 {:101}{106:}procedure sendsign(v:integer);
425 begin case outstate of 2,4:outapp:=outapp*v;3:begin outapp:=v;
426 outstate:=4;end;5:begin outval:=outval+outapp;outapp:=v;outstate:=4;end;
427 others:begin breakptr:=outptr;outapp:=v;outstate:=2;end end;
428 lastsign:=outapp;end;{:106}{107:}procedure sendval(v:integer);
430 begin case outstate of 1:begin{110:}if(outptr=breakptr+3)or((outptr=
431 breakptr+4)and(outbuf[breakptr]=32))then if((outbuf[outptr-3]=68)and(
432 outbuf[outptr-2]=73)and(outbuf[outptr-1]=86))or((outbuf[outptr-3]=100)
433 and(outbuf[outptr-2]=105)and(outbuf[outptr-1]=118))or((outbuf[outptr-3]=
434 77)and(outbuf[outptr-2]=79)and(outbuf[outptr-1]=68))or((outbuf[outptr-3]
435 =109)and(outbuf[outptr-2]=111)and(outbuf[outptr-1]=100))then goto 666
436 {:110};outsign:=32;outstate:=3;outval:=v;breakptr:=outptr;lastsign:=+1;
438 0:begin{109:}if(outptr=breakptr+1)and((outbuf[breakptr]=42)or(outbuf[
439 breakptr]=47))then goto 666{:109};outsign:=0;outstate:=3;outval:=v;
440 breakptr:=outptr;lastsign:=+1;end;{108:}2:begin outsign:=43;outstate:=3;
441 outval:=outapp*v;end;3:begin outstate:=5;outapp:=v;
442 begin writeln(stdout);
443 write(stdout,'! Two numbers occurred without a sign between them');
444 error;end;end;4:begin outstate:=5;outapp:=outapp*v;end;
445 5:begin outval:=outval+outapp;outapp:=v;begin writeln(stdout);
446 write(stdout,'! Two numbers occurred without a sign between them');
447 error;end;end;{:108}others:goto 666 end;goto 10;
448 666:{111:}if v>=0 then begin if outstate=1 then begin breakptr:=outptr;
449 begin outbuf[outptr]:=32;outptr:=outptr+1;end;end;appval(v);
450 if outptr>linelength then flushbuffer;outstate:=1;
451 end else begin begin outbuf[outptr]:=40;outptr:=outptr+1;end;
452 begin outbuf[outptr]:=45;outptr:=outptr+1;end;appval(-v);
453 begin outbuf[outptr]:=41;outptr:=outptr+1;end;
454 if outptr>linelength then flushbuffer;outstate:=0;end{:111};10:end;
455 {:107}{113:}procedure sendtheoutput;label 2,21,22;var curchar:eightbits;
456 k:0..linelength;j:0..maxbytes;w:0..2;n:integer;
457 begin while stackptr>0 do begin curchar:=getoutput;
458 21:case curchar of 0:;
459 {116:}65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,
460 87,88,89,90:begin if forcelowercase then outcontrib[1]:=curchar+32 else
461 outcontrib[1]:=curchar;sendout(2,1);end;
462 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115
463 ,116,117,118,119,120,121,122:begin if forceuppercase then outcontrib[1]
464 :=curchar-32 else outcontrib[1]:=curchar;sendout(2,1);end;
465 130:begin k:=0;j:=bytestart[curval];w:=curval mod 3;
466 while(k<maxidlength)and(j<bytestart[curval+3])do begin k:=k+1;
467 outcontrib[k]:=bytemem[w,j];j:=j+1;
468 if forceuppercase and(outcontrib[k]>=97)then outcontrib[k]:=outcontrib[k
469 ]-32 else if forcelowercase and(outcontrib[k]<=90)then outcontrib[k]:=
470 outcontrib[k]+32 else if not allowunderlines and(outcontrib[k]=95)then k
471 :=k-1;end;sendout(2,k);end;
472 {:116}{119:}48,49,50,51,52,53,54,55,56,57:begin n:=0;
473 repeat curchar:=curchar-48;if n>=214748364 then begin writeln(stdout);
474 write(stdout,'! Constant too big');error;end else n:=10*n+curchar;
475 curchar:=getoutput;until(curchar>57)or(curchar<48);sendval(n);k:=0;
476 if curchar=101 then curchar:=69;if curchar=69 then goto 2 else goto 21;
477 end;125:sendval(poolchecksum);12:begin n:=0;curchar:=48;
478 repeat curchar:=curchar-48;if n>=1073741824 then begin writeln(stdout);
479 write(stdout,'! Constant too big');error;end else n:=8*n+curchar;
480 curchar:=getoutput;until(curchar>55)or(curchar<48);sendval(n);goto 21;
481 end;13:begin n:=0;curchar:=48;
482 repeat if curchar>=65 then curchar:=curchar-55 else curchar:=curchar-48;
483 if n>=1073741824 then begin writeln(stdout);
484 write(stdout,'! Constant too big');error;end else n:=16*n+curchar;
486 until(curchar>70)or(curchar<48)or((curchar>57)and(curchar<65));
487 sendval(n);goto 21;end;128:sendval(curval);46:begin k:=1;
488 outcontrib[1]:=46;curchar:=getoutput;
489 if curchar=46 then begin outcontrib[2]:=46;sendout(1,2);
490 end else if(curchar>=48)and(curchar<=57)then goto 2 else begin sendout(0
491 ,46);goto 21;end;end;{:119}43,45:sendsign(44-curchar);
492 {114:}4:begin outcontrib[1]:=97;outcontrib[2]:=110;outcontrib[3]:=100;
493 sendout(2,3);end;5:begin outcontrib[1]:=110;outcontrib[2]:=111;
494 outcontrib[3]:=116;sendout(2,3);end;6:begin outcontrib[1]:=105;
495 outcontrib[2]:=110;sendout(2,2);end;31:begin outcontrib[1]:=111;
496 outcontrib[2]:=114;sendout(2,2);end;24:begin outcontrib[1]:=58;
497 outcontrib[2]:=61;sendout(1,2);end;26:begin outcontrib[1]:=60;
498 outcontrib[2]:=62;sendout(1,2);end;28:begin outcontrib[1]:=60;
499 outcontrib[2]:=61;sendout(1,2);end;29:begin outcontrib[1]:=62;
500 outcontrib[2]:=61;sendout(1,2);end;30:begin outcontrib[1]:=61;
501 outcontrib[2]:=61;sendout(1,2);end;32:begin outcontrib[1]:=46;
502 outcontrib[2]:=46;sendout(1,2);end;{:114}39:{117:}begin k:=1;
503 outcontrib[1]:=39;repeat if k<linelength then k:=k+1;
504 outcontrib[k]:=getoutput;until(outcontrib[k]=39)or(stackptr=0);
505 if k=linelength then begin writeln(stdout);
506 write(stdout,'! String too long');error;end;sendout(1,k);
507 curchar:=getoutput;if curchar=39 then outstate:=6;goto 21;end{:117};
508 {115:}33,34,35,36,37,38,40,41,42,44,47,58,59,60,61,62,63,64,91,92,93,94,
509 95,96,123,124{:115}:sendout(0,curchar);
510 {121:}9:begin if bracelevel=0 then sendout(0,123)else sendout(0,91);
511 bracelevel:=bracelevel+1;end;
512 10:if bracelevel>0 then begin bracelevel:=bracelevel-1;
513 if bracelevel=0 then sendout(0,125)else sendout(0,93);
514 end else begin writeln(stdout);write(stdout,'! Extra @}');error;end;
516 if bracelevel=0 then outcontrib[1]:=123 else outcontrib[1]:=91;
517 if curval<0 then begin outcontrib[k]:=58;curval:=-curval;k:=k+1;end;
518 n:=10;while curval>=n do n:=10*n;repeat n:=n div 10;
519 outcontrib[k]:=48+(curval div n);curval:=curval mod n;k:=k+1;until n=1;
520 if outcontrib[2]<>58 then begin outcontrib[k]:=58;k:=k+1;end;
521 if bracelevel=0 then outcontrib[k]:=125 else outcontrib[k]:=93;
522 sendout(1,k);end;{:121}127:begin sendout(3,0);outstate:=6;end;
523 2:{118:}begin k:=0;repeat if k<linelength then k:=k+1;
524 outcontrib[k]:=getoutput;until(outcontrib[k]=2)or(stackptr=0);
525 if k=linelength then begin writeln(stdout);
526 write(stdout,'! Verbatim string too long');error;end;sendout(1,k-1);
527 end{:118};3:{122:}begin sendout(1,0);
528 while outptr>0 do begin if outptr<=linelength then breakptr:=outptr;
529 flushbuffer;end;outstate:=0;end{:122};others:begin writeln(stdout);
530 write(stdout,'! Can''t output ASCII code ',curchar:1);error;end end;
531 goto 22;2:{120:}repeat if k<linelength then k:=k+1;
532 outcontrib[k]:=curchar;curchar:=getoutput;
533 if(outcontrib[k]=69)and((curchar=43)or(curchar=45))then begin if k<
534 linelength then k:=k+1;outcontrib[k]:=curchar;curchar:=getoutput;
535 end else if curchar=101 then curchar:=69;
536 until(curchar<>69)and((curchar<48)or(curchar>57));
537 if k=linelength then begin writeln(stdout);
538 write(stdout,'! Fraction too long');error;end;sendout(3,k);
539 goto 21{:120};22:end;end;{:113}{127:}function linesdontmatch:boolean;
540 label 10;var k:0..bufsize;begin linesdontmatch:=true;
541 if changelimit<>limit then goto 10;
542 if limit>0 then for k:=0 to limit-1 do if changebuffer[k]<>buffer[k]then
543 goto 10;linesdontmatch:=false;10:end;
544 {:127}{128:}procedure primethechangebuffer;label 22,30,10;
545 var k:0..bufsize;begin changelimit:=0;
546 {129:}while true do begin line:=line+1;
547 if not inputln(changefile)then goto 10;if limit<2 then goto 22;
548 if buffer[0]<>64 then goto 22;
549 if(buffer[1]>=88)and(buffer[1]<=90)then buffer[1]:=buffer[1]+32;
550 if buffer[1]=120 then goto 30;
551 if(buffer[1]=121)or(buffer[1]=122)then begin loc:=2;
552 begin writeln(stdout);write(stdout,'! Where is the matching @x?');error;
553 end;end;22:end;30:{:129};{130:}repeat line:=line+1;
554 if not inputln(changefile)then begin begin writeln(stdout);
555 write(stdout,'! Change file ended after @x');error;end;goto 10;end;
556 until limit>0;{:130};{131:}begin changelimit:=limit;
557 if limit>0 then for k:=0 to limit-1 do changebuffer[k]:=buffer[k];
558 end{:131};10:end;{:128}{132:}procedure checkchange;label 10;
559 var n:integer;k:0..bufsize;begin if linesdontmatch then goto 10;n:=0;
560 while true do begin changing:=not changing;templine:=otherline;
561 otherline:=line;line:=templine;line:=line+1;
562 if not inputln(changefile)then begin begin writeln(stdout);
563 write(stdout,'! Change file ended before @y');error;end;changelimit:=0;
564 changing:=not changing;templine:=otherline;otherline:=line;
565 line:=templine;goto 10;end;
566 {133:}if limit>1 then if buffer[0]=64 then begin if(buffer[1]>=88)and(
567 buffer[1]<=90)then buffer[1]:=buffer[1]+32;
568 if(buffer[1]=120)or(buffer[1]=122)then begin loc:=2;
569 begin writeln(stdout);write(stdout,'! Where is the matching @y?');error;
570 end;end else if buffer[1]=121 then begin if n>0 then begin loc:=2;
571 begin writeln(stdout);
572 write(stdout,'! Hmm... ',n:1,' of the preceding lines failed to match');
573 error;end;end;goto 10;end;end{:133};{131:}begin changelimit:=limit;
574 if limit>0 then for k:=0 to limit-1 do changebuffer[k]:=buffer[k];
575 end{:131};changing:=not changing;templine:=otherline;otherline:=line;
576 line:=templine;line:=line+1;
577 if not inputln(webfile)then begin begin writeln(stdout);
578 write(stdout,'! WEB file ended during a change');error;end;
579 inputhasended:=true;goto 10;end;if linesdontmatch then n:=n+1;end;
580 10:end;{:132}{135:}procedure getline;label 20;
581 begin 20:if changing then{137:}begin line:=line+1;
582 if not inputln(changefile)then begin begin writeln(stdout);
583 write(stdout,'! Change file ended without @z');error;end;buffer[0]:=64;
584 buffer[1]:=122;limit:=2;end;
585 if limit>1 then if buffer[0]=64 then begin if(buffer[1]>=88)and(buffer[1
586 ]<=90)then buffer[1]:=buffer[1]+32;
587 if(buffer[1]=120)or(buffer[1]=121)then begin loc:=2;
588 begin writeln(stdout);write(stdout,'! Where is the matching @z?');error;
589 end;end else if buffer[1]=122 then begin primethechangebuffer;
590 changing:=not changing;templine:=otherline;otherline:=line;
591 line:=templine;end;end;end{:137};
592 if not changing then begin{136:}begin line:=line+1;
593 if not inputln(webfile)then inputhasended:=true else if limit=
594 changelimit then if buffer[0]=changebuffer[0]then if changelimit>0 then
595 checkchange;end{:136};if changing then goto 20;end;loc:=0;
596 buffer[limit]:=32;end;
597 {:135}{139:}function controlcode(c:ASCIIcode):eightbits;
598 begin case c of 64:controlcode:=64;39:controlcode:=12;
599 34:controlcode:=13;36:controlcode:=125;32,9:controlcode:=136;
600 42:begin write(stdout,'*',modulecount+1:1);fflush(stdout);
601 controlcode:=136;end;68,100:controlcode:=133;70,102:controlcode:=132;
602 123:controlcode:=9;125:controlcode:=10;80,112:controlcode:=134;
603 84,116,94,46,58:controlcode:=131;38:controlcode:=127;
604 60:controlcode:=135;61:controlcode:=2;92:controlcode:=3;
605 others:controlcode:=0 end;end;{:139}{140:}function skipahead:eightbits;
606 label 30;var c:eightbits;
607 begin while true do begin if loc>limit then begin getline;
608 if inputhasended then begin c:=136;goto 30;end;end;buffer[limit+1]:=64;
609 while buffer[loc]<>64 do loc:=loc+1;if loc<=limit then begin loc:=loc+2;
610 c:=controlcode(buffer[loc-1]);if(c<>0)or(buffer[loc-1]=62)then goto 30;
611 end;end;30:skipahead:=c;end;{:140}{141:}procedure skipcomment;label 10;
612 var bal:eightbits;c:ASCIIcode;begin bal:=0;
613 while true do begin if loc>limit then begin getline;
614 if inputhasended then begin begin writeln(stdout);
615 write(stdout,'! Input ended in mid-comment');error;end;goto 10;end;end;
616 c:=buffer[loc];loc:=loc+1;{142:}if c=64 then begin c:=buffer[loc];
617 if(c<>32)and(c<>9)and(c<>42)and(c<>122)and(c<>90)then loc:=loc+1 else
618 begin begin writeln(stdout);
619 write(stdout,'! Section ended in mid-comment');error;end;loc:=loc-1;
621 end end else if(c=92)and(buffer[loc]<>64)then loc:=loc+1 else if c=123
622 then bal:=bal+1 else if c=125 then begin if bal=0 then goto 10;
623 bal:=bal-1;end{:142};end;10:end;{:141}{145:}function getnext:eightbits;
624 label 20,30,31;var c:eightbits;d:eightbits;j,k:0..longestname;
625 begin 20:if loc>limit then begin getline;
626 if inputhasended then begin c:=136;goto 31;end;end;c:=buffer[loc];
628 if scanninghex then{146:}if((c>=48)and(c<=57))or((c>=65)and(c<=70))then
629 goto 31 else scanninghex:=false{:146};
630 case c of 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85
631 ,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111
632 ,112,113,114,115,116,117,118,119,120,121,122:{148:}begin if((c=101)or(c=
633 69))and(loc>1)then if(buffer[loc-2]<=57)and(buffer[loc-2]>=48)then c:=0;
634 if c<>0 then begin loc:=loc-1;idfirst:=loc;repeat loc:=loc+1;
636 until((d<48)or((d>57)and(d<65))or((d>90)and(d<97))or(d>122))and(d<>95);
637 if loc>idfirst+1 then begin c:=130;idloc:=loc;end;end else c:=69;
638 end{:148};34:{149:}begin doublechars:=0;idfirst:=loc-1;
639 repeat d:=buffer[loc];loc:=loc+1;
640 if(d=34)or(d=64)then if buffer[loc]=d then begin loc:=loc+1;d:=0;
641 doublechars:=doublechars+1;
642 end else begin if d=64 then begin writeln(stdout);
643 write(stdout,'! Double @ sign missing');error;
644 end end else if loc>limit then begin begin writeln(stdout);
645 write(stdout,'! String constant didn''t end');error;end;d:=34;end;
646 until d=34;idloc:=loc-1;c:=130;end{:149};
647 64:{150:}begin c:=controlcode(buffer[loc]);loc:=loc+1;
648 if c=0 then goto 20 else if c=13 then scanninghex:=true else if c=135
649 then{151:}begin{153:}k:=0;
650 while true do begin if loc>limit then begin getline;
651 if inputhasended then begin begin writeln(stdout);
652 write(stdout,'! Input ended in section name');error;end;goto 30;end;end;
653 d:=buffer[loc];{154:}if d=64 then begin d:=buffer[loc+1];
654 if d=62 then begin loc:=loc+2;goto 30;end;
655 if(d=32)or(d=9)or(d=42)then begin begin writeln(stdout);
656 write(stdout,'! Section name didn''t end');error;end;goto 30;end;k:=k+1;
657 modtext[k]:=64;loc:=loc+1;end{:154};loc:=loc+1;
658 if k<longestname-1 then k:=k+1;if(d=32)or(d=9)then begin d:=32;
659 if modtext[k-1]=32 then k:=k-1;end;modtext[k]:=d;end;
660 30:{155:}if k>=longestname-2 then begin begin writeln(stdout);
661 write(stdout,'! Section name too long: ');end;
662 for j:=1 to 25 do write(stdout,xchr[modtext[j]]);write(stdout,'...');
663 if history=0 then history:=1;end{:155};
664 if(modtext[k]=32)and(k>0)then k:=k-1;{:153};
665 if k>3 then begin if(modtext[k]=46)and(modtext[k-1]=46)and(modtext[k-2]=
666 46)then curmodule:=prefixlookup(k-3)else curmodule:=modlookup(k);
667 end else curmodule:=modlookup(k);
668 end{:151}else if c=131 then begin repeat c:=skipahead;until c<>64;
669 if buffer[loc-1]<>62 then begin writeln(stdout);
670 write(stdout,'! Improper @ within control text');error;end;goto 20;end;
672 {147:}46:if buffer[loc]=46 then begin if loc<=limit then begin c:=32;
674 end else if buffer[loc]=41 then begin if loc<=limit then begin c:=93;
676 58:if buffer[loc]=61 then begin if loc<=limit then begin c:=24;
678 61:if buffer[loc]=61 then begin if loc<=limit then begin c:=30;
680 62:if buffer[loc]=61 then begin if loc<=limit then begin c:=29;
682 60:if buffer[loc]=61 then begin if loc<=limit then begin c:=28;
684 end else if buffer[loc]=62 then begin if loc<=limit then begin c:=26;
686 40:if buffer[loc]=42 then begin if loc<=limit then begin c:=9;
688 end else if buffer[loc]=46 then begin if loc<=limit then begin c:=91;
690 42:if buffer[loc]=41 then begin if loc<=limit then begin c:=10;
691 loc:=loc+1;end;end;{:147}32,9:goto 20;123:begin skipcomment;goto 20;end;
692 125:begin begin writeln(stdout);write(stdout,'! Extra }');error;end;
693 goto 20;end;others:if c>=128 then goto 20 else end;
694 31:{if troubleshooting then debughelp;}getnext:=c;end;
695 {:145}{157:}procedure scannumeric(p:namepointer);label 21,30;
696 var accumulator:integer;nextsign:-1..+1;q:namepointer;val:integer;
697 begin{158:}accumulator:=0;nextsign:=+1;
698 while true do begin nextcontrol:=getnext;
699 21:case nextcontrol of 48,49,50,51,52,53,54,55,56,57:begin{160:}val:=0;
700 repeat val:=10*val+nextcontrol-48;nextcontrol:=getnext;
701 until(nextcontrol>57)or(nextcontrol<48){:160};
702 begin accumulator:=accumulator+nextsign*(val);nextsign:=+1;end;goto 21;
703 end;12:begin{161:}val:=0;nextcontrol:=48;
704 repeat val:=8*val+nextcontrol-48;nextcontrol:=getnext;
705 until(nextcontrol>55)or(nextcontrol<48){:161};
706 begin accumulator:=accumulator+nextsign*(val);nextsign:=+1;end;goto 21;
707 end;13:begin{162:}val:=0;nextcontrol:=48;
708 repeat if nextcontrol>=65 then nextcontrol:=nextcontrol-7;
709 val:=16*val+nextcontrol-48;nextcontrol:=getnext;
710 until(nextcontrol>70)or(nextcontrol<48)or((nextcontrol>57)and(
711 nextcontrol<65)){:162};begin accumulator:=accumulator+nextsign*(val);
712 nextsign:=+1;end;goto 21;end;130:begin q:=idlookup(0);
713 if ilk[q]<>1 then begin nextcontrol:=42;goto 21;end;
714 begin accumulator:=accumulator+nextsign*(equiv[q]-1073741824);
715 nextsign:=+1;end;end;43:;45:nextsign:=-nextsign;
716 132,133,135,134,136:goto 30;59:begin writeln(stdout);
717 write(stdout,'! Omit semicolon in numeric definition');error;end;
718 others:{159:}begin begin writeln(stdout);
719 write(stdout,'! Improper numeric definition will be flushed');error;end;
720 repeat nextcontrol:=skipahead until(nextcontrol>=132);
721 if nextcontrol=135 then begin loc:=loc-2;nextcontrol:=getnext;end;
722 accumulator:=0;goto 30;end{:159}end;end;30:{:158};
723 if abs(accumulator)>=1073741824 then begin begin writeln(stdout);
724 write(stdout,'! Value too big: ',accumulator:1);error;end;
725 accumulator:=0;end;equiv[p]:=accumulator+1073741824;end;
726 {:157}{165:}procedure scanrepl(t:eightbits);label 22,30,31,21;
727 var a:sixteenbits;b:ASCIIcode;bal:eightbits;begin bal:=0;
728 while true do begin 22:a:=getnext;case a of 40:if t=3 then bal:=bal+1;
729 41:if t=3 then if bal=0 then begin writeln(stdout);
730 write(stdout,'! Extra )');error;end else bal:=bal-1;
731 91:if t=4 then bal:=bal+1;
732 93:if t=4 then if bal=0 then begin writeln(stdout);
733 write(stdout,'! Extra ]');error;end else bal:=bal-1;
734 39:{168:}begin b:=39;
735 while true do begin begin if tokptr[z]=maxtoks then begin writeln(stdout
736 );write(stderr,'! Sorry, ','token',' capacity exceeded');error;
737 history:=3;uexit(1);end;tokmem[z,tokptr[z]]:=b;tokptr[z]:=tokptr[z]+1;
739 if b=64 then if buffer[loc]=64 then loc:=loc+1 else begin writeln(stdout
740 );write(stdout,'! You should double @ signs in strings');error;end;
741 if loc=limit then begin begin writeln(stdout);
742 write(stdout,'! String didn''t end');error;end;buffer[loc]:=39;
743 buffer[loc+1]:=0;end;b:=buffer[loc];loc:=loc+1;
744 if b=39 then begin if buffer[loc]<>39 then goto 31 else begin loc:=loc+1
745 ;begin if tokptr[z]=maxtoks then begin writeln(stdout);
746 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
747 uexit(1);end;tokmem[z,tokptr[z]]:=39;tokptr[z]:=tokptr[z]+1;end;end;end;
748 end;31:end{:168};35:if(t=3)or(t=4)then a:=0;
749 {167:}130:begin a:=idlookup(0);
750 begin if tokptr[z]=maxtoks then begin writeln(stdout);
751 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
752 uexit(1);end;tokmem[z,tokptr[z]]:=(a div 256)+128;
753 tokptr[z]:=tokptr[z]+1;end;a:=a mod 256;end;
754 135:if t<>135 then goto 30 else begin begin if tokptr[z]=maxtoks then
755 begin writeln(stdout);
756 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
757 uexit(1);end;tokmem[z,tokptr[z]]:=(curmodule div 256)+168;
758 tokptr[z]:=tokptr[z]+1;end;a:=curmodule mod 256;end;
759 2:{169:}begin begin if tokptr[z]=maxtoks then begin writeln(stdout);
760 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
761 uexit(1);end;tokmem[z,tokptr[z]]:=2;tokptr[z]:=tokptr[z]+1;end;
763 21:if buffer[loc]=64 then begin if loc<limit then if buffer[loc+1]=64
764 then begin begin if tokptr[z]=maxtoks then begin writeln(stdout);
765 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
766 uexit(1);end;tokmem[z,tokptr[z]]:=64;tokptr[z]:=tokptr[z]+1;end;
767 loc:=loc+2;goto 21;end;
768 end else begin begin if tokptr[z]=maxtoks then begin writeln(stdout);
769 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
770 uexit(1);end;tokmem[z,tokptr[z]]:=buffer[loc];tokptr[z]:=tokptr[z]+1;
771 end;loc:=loc+1;goto 21;end;if loc>=limit then begin writeln(stdout);
772 write(stdout,'! Verbatim string didn''t end');error;
773 end else if buffer[loc+1]<>62 then begin writeln(stdout);
774 write(stdout,'! You should double @ signs in verbatim strings');error;
775 end;loc:=loc+2;end{:169};
776 133,132,134:if t<>135 then goto 30 else begin begin writeln(stdout);
777 write(stdout,'! @',xchr[buffer[loc-1]],' is ignored in Pascal text');
778 error;end;goto 22;end;136:goto 30;{:167}others:end;
779 begin if tokptr[z]=maxtoks then begin writeln(stdout);
780 write(stderr,'! Sorry, ','token',' capacity exceeded');error;history:=3;
781 uexit(1);end;tokmem[z,tokptr[z]]:=a;tokptr[z]:=tokptr[z]+1;end;end;
783 {166:}if bal>0 then if t=3 then begin if bal=1 then begin writeln(stdout
784 );write(stdout,'! Missing )');error;end else begin writeln(stdout);
785 write(stdout,'! Missing ',bal:1,' )''s');error;end;
786 while bal>0 do begin begin if tokptr[z]=maxtoks then begin writeln(
787 stdout);write(stderr,'! Sorry, ','token',' capacity exceeded');error;
788 history:=3;uexit(1);end;tokmem[z,tokptr[z]]:=41;tokptr[z]:=tokptr[z]+1;
789 end;bal:=bal-1;end;end else begin if bal=1 then begin writeln(stdout);
790 write(stdout,'! Missing ]');error;end else begin writeln(stdout);
791 write(stdout,'! Missing ',bal:1,' ]''s');error;end;
792 while bal>0 do begin begin if tokptr[z]=maxtoks then begin writeln(
793 stdout);write(stderr,'! Sorry, ','token',' capacity exceeded');error;
794 history:=3;uexit(1);end;tokmem[z,tokptr[z]]:=93;tokptr[z]:=tokptr[z]+1;
795 end;bal:=bal-1;end;end{:166};
796 if textptr>maxtexts-5 then begin writeln(stdout);
797 write(stderr,'! Sorry, ','text',' capacity exceeded');error;history:=3;
798 uexit(1);end;currepltext:=textptr;tokstart[textptr+5]:=tokptr[z];
799 textptr:=textptr+1;if z=4 then z:=0 else z:=z+1;end;
800 {:165}{170:}procedure definemacro(t:eightbits);var p:namepointer;
801 begin p:=idlookup(t);scanrepl(t);equiv[p]:=currepltext;
802 textlink[currepltext]:=0;end;{:170}{172:}procedure scanmodule;
803 label 22,30,10;var p:namepointer;begin modulecount:=modulecount+1;
804 {173:}nextcontrol:=0;
805 while true do begin 22:while nextcontrol<=132 do begin nextcontrol:=
806 skipahead;if nextcontrol=135 then begin loc:=loc-2;nextcontrol:=getnext;
807 end;end;if nextcontrol<>133 then goto 30;nextcontrol:=getnext;
808 if nextcontrol<>130 then begin begin writeln(stdout);
809 write(stdout,'! Definition flushed, must start with ',
810 'identifier of length > 1');error;end;goto 22;end;nextcontrol:=getnext;
811 if nextcontrol=61 then begin scannumeric(idlookup(1));goto 22;
812 end else if nextcontrol=30 then begin definemacro(2);goto 22;
813 end else{174:}if nextcontrol=40 then begin nextcontrol:=getnext;
814 if nextcontrol=35 then begin nextcontrol:=getnext;
815 if nextcontrol=41 then begin nextcontrol:=getnext;
816 if nextcontrol=61 then begin begin writeln(stdout);
817 write(stdout,'! Use == for macros');error;end;nextcontrol:=30;end;
818 if nextcontrol=30 then begin definemacro(3);goto 22;end;end;end;
819 end else if nextcontrol=91 then begin nextcontrol:=getnext;
820 if nextcontrol=35 then begin nextcontrol:=getnext;
821 if nextcontrol=93 then begin nextcontrol:=getnext;
822 if nextcontrol=61 then begin begin writeln(stdout);
823 write(stdout,'! Use == for macros');error;end;nextcontrol:=30;end;
824 if nextcontrol=30 then begin definemacro(4);goto 22;end;end;end;
825 end{:174};begin writeln(stdout);
826 write(stdout,'! Definition flushed since it starts badly');error;end;
827 end;30:{:173};{175:}case nextcontrol of 134:p:=0;135:begin p:=curmodule;
828 {176:}repeat nextcontrol:=getnext;until nextcontrol<>43;
829 if(nextcontrol<>61)and(nextcontrol<>30)then begin begin writeln(stdout);
830 write(stdout,'! Pascal text flushed, = sign is missing');error;end;
831 repeat nextcontrol:=skipahead;until nextcontrol=136;goto 10;end{:176};
832 end;others:goto 10 end;{177:}storetwobytes(53248+modulecount);{:177};
834 {178:}if p=0 then begin textlink[lastunnamed]:=currepltext;
835 lastunnamed:=currepltext;
836 end else if equiv[p]=0 then equiv[p]:=currepltext else begin p:=equiv[p]
837 ;while textlink[p]<maxtexts do p:=textlink[p];textlink[p]:=currepltext;
838 end;textlink[currepltext]:=maxtexts;{:178};{:175};10:end;
839 {:172}{181:}{procedure debughelp;label 888,10;var k:integer;
840 begin debugskipped:=debugskipped+1;
841 if debugskipped<debugcycle then goto 10;debugskipped:=0;
842 while true do begin begin writeln(stdout);write(stdout,'#');end;
843 fflush(stdout);read(stdin,ddt);
844 if ddt<0 then goto 10 else if ddt=0 then begin goto 888;
846 end else begin read(stdin,dd);case ddt of 1:printid(dd);2:printrepl(dd);
847 3:for k:=1 to dd do write(stdout,xchr[buffer[k]]);
848 4:for k:=1 to dd do write(stdout,xchr[modtext[k]]);
849 5:for k:=1 to outptr do write(stdout,xchr[outbuf[k]]);
850 6:for k:=1 to dd do write(stdout,xchr[outcontrib[k]]);
851 others:write(stdout,'?')end;end;end;10:end;}
852 {:181}{182:}begin initialize;{134:}openinput;line:=0;otherline:=0;
853 changing:=true;primethechangebuffer;changing:=not changing;
854 templine:=otherline;otherline:=line;line:=templine;limit:=0;loc:=1;
855 buffer[0]:=32;inputhasended:=false;{:134};
856 write(stdout,'This is TANGLE, Version 4.5');
857 writeln(stdout,versionstring);{183:}phaseone:=true;modulecount:=0;
858 repeat nextcontrol:=skipahead;until nextcontrol=136;
859 while not inputhasended do scanmodule;
860 {138:}if changelimit<>0 then begin for ii:=0 to changelimit do buffer[ii
861 ]:=changebuffer[ii];limit:=changelimit;changing:=true;line:=otherline;
862 loc:=changelimit;begin writeln(stdout);
863 write(stdout,'! Change file entry did not match');error;end;end{:138};
864 phaseone:=false;{:183};{for ii:=0 to 4 do maxtokptr[ii]:=tokptr[ii];}
865 {112:}if textlink[0]=0 then begin begin writeln(stdout);
866 write(stdout,'! No output was specified.');end;
867 if history=0 then history:=1;end else begin begin writeln(stdout);
868 write(stdout,'Writing the output file');end;fflush(stdout);
869 {83:}stackptr:=1;bracelevel:=0;curstate.namefield:=0;
870 curstate.replfield:=textlink[0];zo:=curstate.replfield mod 5;
871 curstate.bytefield:=tokstart[curstate.replfield];
872 curstate.endfield:=tokstart[curstate.replfield+5];curstate.modfield:=0;
873 {:83};{96:}outstate:=0;outptr:=0;breakptr:=0;semiptr:=0;outbuf[0]:=0;
874 line:=1;{:96};sendtheoutput;{98:}breakptr:=outptr;semiptr:=0;
875 flushbuffer;if bracelevel<>0 then begin writeln(stdout);
876 write(stdout,'! Program ended at brace level ',bracelevel:1);error;end;
877 {:98};begin writeln(stdout);write(stdout,'Done.');end;end{:112};
878 if stringptr>256 then{184:}begin begin writeln(stdout);
879 write(stdout,stringptr-256:1,' strings written to string pool file.');
881 for ii:=1 to 9 do begin outbuf[ii]:=poolchecksum mod 10;
882 poolchecksum:=poolchecksum div 10;end;
883 for ii:=9 downto 1 do write(pool,xchr[48+outbuf[ii]]);writeln(pool);
884 end{:184};{[186:]begin writeln(stdout);
885 write(stdout,'Memory usage statistics:');end;begin writeln(stdout);
886 write(stdout,nameptr:1,' names, ',textptr:1,' replacement texts;');end;
887 begin writeln(stdout);write(stdout,byteptr[0]:1);end;
888 for wo:=1 to 2 do write(stdout,'+',byteptr[wo]:1);
889 if phaseone then for ii:=0 to 4 do maxtokptr[ii]:=tokptr[ii];
890 write(stdout,' bytes, ',maxtokptr[0]:1);
891 for ii:=1 to 4 do write(stdout,'+',maxtokptr[ii]:1);
892 write(stdout,' tokens.');[:186];}
893 {187:}case history of 0:begin writeln(stdout);
894 write(stdout,'(No errors were found.)');end;1:begin writeln(stdout);
895 write(stdout,'(Did you see the warning message above?)');end;
896 2:begin writeln(stdout);
897 write(stdout,'(Pardon me, but I think I spotted something wrong.)');end;
898 3:begin writeln(stdout);
899 write(stdout,'(That was a fatal error, my friend.)');end;end{:187};
900 writeln(stdout);if(history<>0)and(history<>1)then uexit(1)else uexit(0);