This repository was archived by the owner on Jun 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathctwill.diffs
More file actions
1805 lines (1699 loc) · 66.9 KB
/
ctwill.diffs
File metadata and controls
1805 lines (1699 loc) · 66.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
*** ../cweb3.61/cweave.w Mon Jul 24 00:16:43 2000
--- ctwill.w Mon Jul 24 08:20:43 2000
***************
*** 1,10 ****
! % This file is part of CWEB.
! % This program by Silvio Levy and Donald E. Knuth
! % is based on a program by Knuth.
! % It is distributed WITHOUT ANY WARRANTY, express or implied.
% Version 3.61 --- July 2000
- % (essentially the same as version 3.6, which added
- % recently introduced features of standard C++ to version 3.4)
% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
--- 1,6 ----
! % This program by Don Knuth is based on CWEAVE by Levy and Knuth.
! % It's somewhat flaky, so you probably shouldn't try to use it.
% Version 3.61 --- July 2000
% Copyright (C) 1987,1990,1993,2000 Silvio Levy and Donald E. Knuth
***************
*** 17,23 ****
% entire resulting derived work is given a different name and distributed
% under the terms of a permission notice identical to this one.
! % Here is TeX material that gets inserted after \input cwebmac
\def\hang{\hangindent 3em\indent\ignorespaces}
\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
\def\v{\char'174} % vertical (|) in typewriter font
--- 13,19 ----
% entire resulting derived work is given a different name and distributed
% under the terms of a permission notice identical to this one.
! % Here is TeX material that gets inserted after \input ctwimac
\def\hang{\hangindent 3em\indent\ignorespaces}
\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
\def\v{\char'174} % vertical (|) in typewriter font
***************
*** 29,37 ****
\def\skipxTeX{\\{skip\_\TEX/}}
\def\copyxTeX{\\{copy\_\TEX/}}
! \def\title{CWEAVE (Version 3.61)}
\def\topofcontents{\null\vfill
! \centerline{\titlefont The {\ttitlefont CWEAVE} processor}
\vskip 15pt
\centerline{(Version 3.61)}
\vfill}
--- 25,33 ----
\def\skipxTeX{\\{skip\_\TEX/}}
\def\copyxTeX{\\{copy\_\TEX/}}
! \def\title{CTWILL (Version 3.61)}
\def\topofcontents{\null\vfill
! \centerline{\titlefont The {\ttitlefont CTWILL} processor}
\vskip 15pt
\centerline{(Version 3.61)}
\vfill}
***************
*** 54,71 ****
@s not_eq normal @q unreserve a C++ keyword @>
@** Introduction.
! This is the \.{CWEAVE} program by Silvio Levy and Donald E. Knuth,
! based on \.{WEAVE} by Knuth.
! We are thankful to Steve Avery,
! Nelson Beebe, Hans-Hermann Bode (to whom the original \CPLUSPLUS/ adaptation
! is due), Klaus Guntermann, Norman Ramsey, Tomas Rokicki, Joachim Schnitter,
! Joachim Schrod, Lee Wittenberg, Saroj Mahapatra, Cesar Augusto Rorato
! Crusius, and others who have contributed improvements.
! The ``banner line'' defined here should be changed whenever \.{CWEAVE}
! is modified.
! @d banner "This is CWEAVE (Version 3.61)\n"
@c @<Include files@>@/
@h
--- 50,73 ----
@s not_eq normal @q unreserve a C++ keyword @>
@** Introduction.
! This is the \.{CTWILL} program by D. E. Knuth, based
! on \.{CWEAVE} by Silvio Levy and D.~E. Knuth. It is also based on
! \.{TWILL}, a private \.{WEB} program that Knuth wrote to produce
! Volumes B and~D of {\sl Computers {\char`\&} Typesetting\/} in 1985.
! \.{CTWILL} was hacked together hastily in June, 1992, to generate pages for
! Knuth's book about the Stanford GraphBase, and updated even more hastily
! in March, 1993 to generate final copy for that book. The main idea was to
! extend \.{CWEAVE} so that ``mini-indexes'' could appear.
! No time was available to make \.{CTWILL} into a refined or complete system,
! nor even to fully update the program documentation below. Subsequent changes
! were made only to maintain compatibility with \.{CWEAVE}. Further information
! can be found in Knuth's article ``Mini-indexes for literate programs,''
! reprinted in {\sl Digital Typography\/} (1999), 225--245.
! The ``banner line'' defined here should be changed whenever \.{CTWILL} is
! modified. The version number parallels the corresponding version of \.{CWEAVE}.
! @d banner "This is CTWILL (Version 3.61)\n"
@c @<Include files@>@/
@h
***************
*** 86,91 ****
--- 88,253 ----
extern int strncmp(); /* compare up to $n$ string characters */
extern char* strncpy(); /* copy up to $n$ string characters */
+ @ Here is a sort of user manual for \.{CTWILL}---which is exactly like
+ \.{CWEAVE} except that it produces much better documentation, for which you
+ must work harder. As with \.{CWEAVE}, input comes from a source file
+ \.{foo.w} and from an optional (but now almost mandatory) change file
+ \.{foo.ch}; output goes to \.{foo.tex}, \.{foo.idx}, and \.{foo.scn}.
+ Unlike \.{CWEAVE}, there is an additional output file, \.{foo.aux},
+ which records all nonexternal definitions. The \.{.aux} file also
+ serves as an input file on subsequent runs. You should run \.{CTWILL}
+ twice, once to prime the pump and once to get decent answers.
+
+ Moreover, you must run the output twice through \TeX. (This double duplicity
+ suggested the original name \.{TWILL}.) After `\.{tex} \.{foo}' you
+ will have output that looks like final pages except that the entries
+ of mini-indexes won't be alphabetized. \TeX\ will say `This is the first
+ pass', and it will produce a weird file called \.{foo.ref}. Say
+ $$\.{refsort < foo.ref > foo.sref}$$
+ and then another `\.{tex} \.{foo}' will produce alphabetized output.
+ While \TeX\ runs it emits messages filled with numeric data, indicating how
+ much space is consumed by each program section. If you can decipher these
+ numbers (see \.{ctwimac.tex}), you can use them to fine-tune the page
+ layout. You might be tempted to do fine tuning by editing \.{foo.tex}
+ directly, but it's better to incorporate all changes into \.{foo.ch}.
+
+ The mini-indexes list identifiers that are used but not defined on
+ each two-page spread. At the end of each section, \.{CTWILL} gives
+ \TeX\ a list of identifiers used in that section and information
+ about where they are defined. The macros in \.{ctwimac.tex} figure out
+ which identifiers should go in each mini-index, based on how the pages
+ break. (Yes, those macros are pretty hairy.)
+
+ The information that \.{CTWILL} concocts from \.{foo.w} is not always
+ correct. Sometimes you'll use an identifier that you don't want
+ indexed; for example, your exposition might talk about |f(x)| when you
+ don't mean to refer to program variables |f| or |x|. Sometimes you'll
+ use an identifier that's defined in a header file, unknown to
+ \.{CTWILL}. Sometimes you'll define a single identifier in several
+ different places, and \.{CTWILL} won't know which definition to choose.
+ But all is not lost. \.{CTWILL} guesses right most of the time, and you can
+ give it the necessary hints in other places via your change file.
+
+ If you think it's easy to write a completely automatic system that doesn't
+ make \.{CTWILL}'s mistakes and doesn't depend so much on change files,
+ please do so.
+
+ \.{CTWILL} uses a very simple method to generate mini-index info. By
+ understanding this method, you will understand how to fix it when things
+ go wrong. Every identifier has a current ``meaning,'' consisting of its
+ abstract type and the number of the section in which it was most recently
+ defined. For example, if your \Cee\ program says `|char *s|' in section~3,
+ the meaning of~|s| gets changed to `\&{char} $*$, \S3' while \.{CTWILL}
+ is processing that section. If you refer to~|s| in section~10, and if
+ |s|~hasn't been redefined in the meantime, and if section~10 doesn't
+ wind up on the same two-page spread as section~3, the mini-index generated
+ by section~10 will say ``|s|: \&{char}~$*$, \S3.''
+
+ The current meaning of every identifier is initially `\.{\\uninitialized}'.
+ Then \.{CTWILL} reads the \.{.aux} file for your job, if any; this
+ \.{.aux} file contains all definitions of new meanings in the previous
+ run, so it tells \.{CTWILL} about definitions that will be occurring
+ in the future. If all identifiers have a unique definition, they will
+ have a unique and appropriate meaning in the mini-indexes.
+
+ But some identifiers, like parameters to procedures, may be defined
+ several times. Others may not be defined at all, because they are
+ defined elsewhere and mentioned in header files included by the \Cee\
+ preprocessor. To solve this problem, \.{CTWILL} provides mechanisms by which
+ the current meaning of an identifier can be temporarily or permanently
+ changed.
+
+ For example, the operation
+ $$\.{@@\$s \{FOO\}3 \\\&\{char\} \$*\$@@>}$$
+ changes the current meaning of |s| to the \TeX\ output of `\.{\\\&\{char\}}
+ \.{\$*\$}' in section~3 of program {\sc FOO}. All entries in the \.{.aux}
+ file are expressed in the form of this \.{@@\$} operator; therefore you
+ can use a text editor to paste such entries into a \.{.ch} file, whenever
+ you want to tell \.{CTWILL} about definitions that are out of order
+ or from other programs.
+
+ Before reading the \.{.aux} file, \.{CTWILL} actually looks for a file
+ called \.{system.bux}, which will be read if present. And after
+ \.{foo.aux}, a third possibility is \.{foo.bux}. The general
+ convention is to put definitions of system procedures such as |printf|
+ into \.{system.bux}, and to put definitions found in specifically
+ foo-ish header files into \.{foo.bux}. Like the \.{.aux}
+ files, \.{.bux} files should contain only \.{@@\$} specifications;
+ this rule corresponds to the fact that `bux' is the plural of `\$'.
+ The \.{.bux} files may also contain \.{@@i} includes.
+
+ A companion operation \.{@@\%} signifies that all \.{@@\$}
+ specifications from the present point to the beginning of the next
+ section will define {\it temporary\/} meanings instead of permanent
+ ones. Temporary meanings are placed into the
+ mini-index of the current section; the permanent (current) meaning of
+ the identifier will not be changed, nor will it appear in the
+ mini-index of the section. If several temporary meanings are assigned
+ to the same identifier in a section, all will appear in the mini-index.
+ Each \.{@@\%} toggles the temporary/permanent convention; thus, after
+ an even number of \.{@@\%} operations in a section, meanings specified
+ by \.{@@\$} are permanent.
+
+ The operation \.{@@-} followed by an identifier followed by \.{@@>}
+ specifies that the identifier should not generate a mini-index entry
+ in the current section (unless, of course, a temporary meaning is assigned).
+
+ If \.{@@-foo@@>} appears in a section where a new permanent meaning is
+ later defined by the semantics of~\Cee, the current meaning of \\{foo}
+ will not be redefined; moreover, this current meaning, which may have
+ been changed by \.{@@\$foo ...@@>}, will also be written to the
+ \.{.aux} file. Therefore you can control what \.{CTWILL} outputs; you
+ can keep it from repeatedly contaminating the \.{.aux} file with
+ things you don't like.
+
+ The meaning specified by \.{@@\$...@@>} generally has four components:
+ an identifier (followed by space), a program name (enclosed in braces),
+ a section number (followed by space), and a \TeX\ part. The \TeX\ part
+ must have fewer than 50 characters. If the \TeX\ part starts
+ with `\.=', the mini-index entry will contain an equals sign instead
+ of a colon; for example,
+ $$\.{@@\$buf\_size \{PROG\}10 =\\T\{200\}@@>}$$
+ generates either `$\\{buf\_size}=200$, \S10' or
+ `$\\{buf\_size}=200$, {\sc PROG}\S10', depending on whether
+ `{\sc PROG}' is or isn't the title of the current program. If the
+ \TeX\ part is `\.{\\zip}', the mini-index entry will contain neither
+ colon nor equals, just a comma. The program name and section number
+ can also be replaced by a string. For example,
+ $$\.{@@\$printf "<stdio.h>" \\zip@@>}$$
+ will generate a mini-index entry like `\\{printf}, \.{<stdio.h>}.'.
+
+ A special ``proofmode'' is provided so that you can check \.{CTWILL}'s
+ conclusions about cross-references. Run \.{CTWILL} with the
+ flag \.{+P}, and \TeX\ will produce a specially formatted document
+ ({\it without\/} mini-indexes)
+ in which you can check that your specifications are correct.
+ You should always do this before generating mini-indexes, because
+ mini-indexes can mask errors if page breaks are favorable but the
+ errors might reveal themselves later after your program has changed.
+ The proofmode output is much easier to check than the mini-indexes themselves.
+
+ The control code \.{@@r} or \.{@@R} causes \.{CTWILL} to emit
+ the \TeX\ macro `\.{\\shortpage}' just before starting the next
+ section of the program. This causes the section to appear at the top of
+ a right-hand page, if it would ordinarily have appeared near the bottom
+ of a left-hand page and split across the pages. (The \.{\\shortpage} macro
+ is fragile and should be used only in cases where it will not mess up
+ the output; insert it only when fine-tuning a set of pages.) If the
+ next section is a starred section, the behavior is slightly different
+ (but still fragile): The starred section will either be postponed to
+ a left-hand page, if it normally would begin on a right-hand page,
+ or vice versa. In other words, \.{@@r@@*} inverts the left/right logic.
+
+ \.{CTANGLE} does not recognize the operations \.{@@\$}, \.{@@\%}, \.{@@-},
+ and \.{@@r}, which are unique to \.{CTWILL}. But that is no problem,
+ since you use them only in change files set up for book publishing,
+ which are quite different from the change files you set up for tangling.
+
+ (End of user manual. We now resume the program for \.{CWEAVE}, with occasional
+ outbursts of new code.)
+
+ @d max_tex_chars 50 /* limit on the \TeX\ part of a meaning */
+
@ \.{CWEAVE} has a fairly straightforward outline. It operates in
three phases: First it inputs the source file and stores cross-reference
data, then it inputs the source once again and produces the \TEX/ output
***************
*** 202,211 ****
@ We keep track of the current section number in |section_count|, which
is the total number of sections that have started. Sections which have
been altered by a change file entry have their |changed_section| flag
! turned on during the first phase.
!
! @<Global...@>=
! boolean change_exists; /* has any section changed? */
@ The other large memory area in \.{CWEAVE} keeps the cross-reference data.
All uses of the name |p| are recorded in a linked list beginning at
--- 364,370 ----
@ We keep track of the current section number in |section_count|, which
is the total number of sections that have started. Sections which have
been altered by a change file entry have their |changed_section| flag
! turned on during the first phase---NOT!
@ The other large memory area in \.{CWEAVE} keeps the cross-reference data.
All uses of the name |p| are recorded in a linked list beginning at
***************
*** 242,247 ****
--- 401,517 ----
xref_pointer xref_ptr; /* the largest occupied position in |xmem| */
sixteen_bits xref_switch,section_xref_switch; /* either zero or |def_flag| */
+ @ \.{CTWILL} also has special data structures to keep track of current
+ and temporary meanings. These structures were not designed for maximum
+ efficiency; they were designed to be easily grafted into \.{CWEAVE}'s
+ existing code without major surgery.
+
+ @d max_meanings 100 /* max temporary meanings per section */
+ @d max_titles 100 /* max distinct program or header names in meanings */
+
+ @<Type...@>=
+ typedef struct {
+ name_pointer id; /* identifier whose meaning is being recorded */
+ sixteen_bits prog_no; /* title of program or header in which defined */
+ sixteen_bits sec_no; /* section number in which defined */
+ char tex_part[max_tex_chars]; /* \TeX\ part of meaning */
+ } meaning_struct;
+
+ @ @<Glob...@>=
+ struct perm_meaning {
+ meaning_struct perm; /* current meaning of an identifier */
+ int stamp; /* last section number in which further output suppressed */
+ struct perm_meaning *link; /* another meaning to output in this section */
+ } cur_meaning[max_names]; /* the current ``permanent'' meanings */
+ struct perm_meaning *top_usage; /* first meaning to output in this section */
+ meaning_struct temp_meaning_stack[max_meanings]; /* the current ``temporary'' meanings */
+ meaning_struct *temp_meaning_ptr; /* first available slot in |temp_meaning_stack| */
+ meaning_struct *max_temp_meaning_ptr; /* its maximum value so far */
+ name_pointer title_code[max_titles]; /* program names seen so far */
+ name_pointer *title_code_ptr; /* first available slot in |title_code| */
+ char ministring_buf[max_tex_chars]; /* \TeX\ code being generated */
+ char *ministring_ptr; /* first available slot in |ministring_buf| */
+ boolean ms_mode; /* are we outputting to |ministring_buf|? */
+
+ @ @<Set init...@>=
+ max_temp_meaning_ptr=temp_meaning_stack;
+ title_code_ptr=title_code;
+ ms_mode=0;
+
+ @ Here's a routine that converts a program title from the buffer
+ into an internal number for the |prog_no| field of a meaning.
+ It advances |loc| past the title found.
+
+ @c sixteen_bits title_lookup()
+ {
+ char *first,*last; /* boundaries */
+ int balance; /* excess of left over right */
+ register name_pointer *p;
+ first=loc;
+ if (*loc=='"') {
+ while (++loc<=limit && *loc!='"') if (*loc=='\\') loc++;
+ } else if (*loc=='{') {
+ balance=1;
+ while (++loc<=limit) {
+ if (*loc=='}' && --balance==0) break;
+ if (*loc=='{') balance++;
+ }
+ } else err_print("! Title should be enclosed in braces or doublequotes");
+ last=++loc;
+ if (last>limit) err_print("! Title name didn't end");
+ if (title_code_ptr==&title_code[max_titles]) overflow("titles");
+ *title_code_ptr=id_lookup(first,last,title);
+ for (p=title_code;;p++) if (*p==*title_code_ptr) break;
+ if (p==title_code_ptr) title_code_ptr++;
+ return p-title_code;
+ }
+
+ @ @<Give a default title to the program, if necessary@>=
+ if (title_code_ptr==title_code) { /* no \.{\\def\\title} found in limbo */
+ char *saveloc=loc,*savelimit=limit;
+ loc=limit+1; limit=loc;
+ *limit++='{';
+ strncpy(limit,tex_file_name,strlen(tex_file_name)-4);
+ limit+=strlen(tex_file_name)-4;
+ *limit++='}';
+ title_lookup();
+ loc=saveloc; limit=savelimit;
+ }
+
+ @ The |new_meaning| routine changes the current ``permanent meaning''
+ when an identifier is redeclared. It gets the |tex_part| from
+ |ministring_buf|.
+
+ @c
+ void
+ new_meaning(p)
+ name_pointer p;
+ {
+ struct perm_meaning *q=p-name_dir+cur_meaning;
+ ms_mode=0;
+ if (q->stamp!=section_count) {
+ if (*(ministring_ptr-1)==' ') ministring_ptr--;
+ if (ministring_ptr>=&ministring_buf[max_tex_chars])
+ strcpy(ministring_buf,"\\zip"); /* ignore |tex_part| if too long */
+ @.\\zip@>
+ else *ministring_ptr='\0';
+ q->perm.prog_no=0; /* |q->perm.id=p| */
+ q->perm.sec_no=section_count;
+ strcpy(q->perm.tex_part,ministring_buf);
+ }
+ @<Write the new meaning to the \.{.aux} file@>;
+ }
+
+ @ @<Write the new meaning to the \.{.aux} file@>=
+ {@+int n=q->perm.prog_no;
+ fprintf(aux_file,"@@$%.*s %.*s",@|
+ (p+1)->byte_start-p->byte_start,p->byte_start,@|
+ (title_code[n]+1)->byte_start-title_code[n]->byte_start,
+ title_code[n]->byte_start);
+ if (*(title_code[n]->byte_start)=='{') fprintf(aux_file,"%d",q->perm.sec_no);
+ fprintf(aux_file," %s@@>\n",q->perm.tex_part);
+ }
+
@ A section that is used for multi-file output (with the \.{@@(} feature)
has a special first cross-reference whose |num| field is |file_flag|.
***************
*** 384,390 ****
--- 654,666 ----
name_pointer p;
eight_bits t;
{
+ struct perm_meaning *q=p-name_dir+cur_meaning;
p->ilk=t; p->xref=(char*)xmem;
+ q->stamp=0;
+ q->link=NULL;
+ q->perm.id=p;
+ q->perm.prog_no=q->perm.sec_no=0;
+ strcpy(q->perm.tex_part,"\\uninitialized");
}
void
***************
*** 434,440 ****
id_lookup("error",NULL,if_like);
id_lookup("explicit",NULL,int_like);
id_lookup("export",NULL,int_like);
! id_lookup("extern",NULL,int_like);
id_lookup("FILE",NULL,raw_int);
id_lookup("float",NULL,raw_int);
id_lookup("for",NULL,for_like);
--- 710,716 ----
id_lookup("error",NULL,if_like);
id_lookup("explicit",NULL,int_like);
id_lookup("export",NULL,int_like);
! ext_loc=id_lookup("extern",NULL,int_like)-name_dir;
id_lookup("FILE",NULL,raw_int);
id_lookup("float",NULL,raw_int);
id_lookup("for",NULL,for_like);
***************
*** 446,452 ****
id_lookup("ifndef",NULL,if_like);
id_lookup("include",NULL,if_like);
id_lookup("inline",NULL,int_like);
! id_lookup("int",NULL,raw_int);
id_lookup("jmp_buf",NULL,raw_int);
id_lookup("ldiv_t",NULL,raw_int);
id_lookup("line",NULL,if_like);
--- 722,728 ----
id_lookup("ifndef",NULL,if_like);
id_lookup("include",NULL,if_like);
id_lookup("inline",NULL,int_like);
! int_loc=id_lookup("int",NULL,raw_int)-name_dir;
id_lookup("jmp_buf",NULL,raw_int);
id_lookup("ldiv_t",NULL,raw_int);
id_lookup("line",NULL,if_like);
***************
*** 503,508 ****
--- 779,787 ----
id_lookup("TeX",NULL,custom);
id_lookup("make_pair",NULL,func_template);
+ @ @<Glob...@>=
+ sixteen_bits int_loc, ext_loc; /* locations of special reserved words */
+
@* Lexical scanning.
Let us now consider the subroutines that read the \.{CWEB} source file
and break it into meaningful units. There are four such procedures:
***************
*** 533,556 ****
@d xref_typewriter 0205 /* control code for `\.{@@.}' */
@d TeX_string 0206 /* control code for `\.{@@t}' */
@f TeX_string TeX
! @d ord 0207 /* control code for `\.{@@'}' */
! @d join 0210 /* control code for `\.{@@\&}' */
! @d thin_space 0211 /* control code for `\.{@@,}' */
! @d math_break 0212 /* control code for `\.{@@\v}' */
! @d line_break 0213 /* control code for `\.{@@/}' */
! @d big_line_break 0214 /* control code for `\.{@@\#}' */
! @d no_line_break 0215 /* control code for `\.{@@+}' */
! @d pseudo_semi 0216 /* control code for `\.{@@;}' */
! @d macro_arg_open 0220 /* control code for `\.{@@[}' */
! @d macro_arg_close 0221 /* control code for `\.{@@]}' */
! @d trace 0222 /* control code for `\.{@@0}', `\.{@@1}' and `\.{@@2}' */
! @d translit_code 0223 /* control code for `\.{@@l}' */
! @d output_defs_code 0224 /* control code for `\.{@@h}' */
! @d format_code 0225 /* control code for `\.{@@f}' and `\.{@@s}' */
! @d definition 0226 /* control code for `\.{@@d}' */
! @d begin_C 0227 /* control code for `\.{@@c}' */
! @d section_name 0230 /* control code for `\.{@@<}' */
! @d new_section 0231 /* control code for `\.{@@\ }' and `\.{@@*}' */
@ Control codes are converted to \.{CWEAVE}'s internal
representation by means of the table |ccode|.
--- 812,839 ----
@d xref_typewriter 0205 /* control code for `\.{@@.}' */
@d TeX_string 0206 /* control code for `\.{@@t}' */
@f TeX_string TeX
! @d meaning 0207 /* control code for `\.{@@\$}' */
! @d suppress 0210 /* control code for `\.{@@-}' */
! @d temp_meaning 0211 /* control code for `\.{@@\%}' */
! @d right_start 0212 /* control code for `\.{@@r}' */
! @d ord 0213 /* control code for `\.{@@'}' */
! @d join 0214 /* control code for `\.{@@\&}' */
! @d thin_space 0215 /* control code for `\.{@@,}' */
! @d math_break 0216 /* control code for `\.{@@\v}' */
! @d line_break 0217 /* control code for `\.{@@/}' */
! @d big_line_break 0220 /* control code for `\.{@@\#}' */
! @d no_line_break 0221 /* control code for `\.{@@+}' */
! @d pseudo_semi 0222 /* control code for `\.{@@;}' */
! @d macro_arg_open 0224 /* control code for `\.{@@[}' */
! @d macro_arg_close 0225 /* control code for `\.{@@]}' */
! @d trace 0226 /* control code for `\.{@@0}', `\.{@@1}' and `\.{@@2}' */
! @d translit_code 0227 /* control code for `\.{@@l}' */
! @d output_defs_code 0230 /* control code for `\.{@@h}' */
! @d format_code 0231 /* control code for `\.{@@f}' and `\.{@@s}' */
! @d definition 0232 /* control code for `\.{@@d}' */
! @d begin_C 0233 /* control code for `\.{@@c}' */
! @d section_name 0234 /* control code for `\.{@@<}' */
! @d new_section 0235 /* control code for `\.{@@\ }' and `\.{@@*}' */
@ Control codes are converted to \.{CWEAVE}'s internal
representation by means of the table |ccode|.
***************
*** 578,583 ****
--- 861,868 ----
ccode['+']=no_line_break; ccode[';']=pseudo_semi;
ccode['[']=macro_arg_open; ccode[']']=macro_arg_close;
ccode['\'']=ord;
+ ccode['$']=meaning; ccode['%']=temp_meaning; ccode['-']=suppress;
+ ccode['r']=ccode['R']=right_start;
@<Special control codes for debugging@>@;
@ Users can write
***************
*** 599,609 ****
@<Predec...@>=
void skip_limbo();
! @ @c
void
skip_limbo() {
while(1) {
if (loc>limit && get_line()==0) return;
*(limit+1)='@@';
while (*loc!='@@') loc++; /* look for '@@', then skip two chars */
if (loc++ <=limit) { int c=ccode[(eight_bits)*loc++];
--- 884,901 ----
@<Predec...@>=
void skip_limbo();
! @ We look for a clue about the program's title, because this will become
! part of all meanings.
!
! @c
void
skip_limbo() {
while(1) {
if (loc>limit && get_line()==0) return;
+ if (loc==buffer && strncmp(buffer,"\\def\\title{",11)==0) {
+ loc=buffer+10;
+ title_lookup(); /* this program's title will be code zero */
+ }
*(limit+1)='@@';
while (*loc!='@@') loc++; /* look for '@@', then skip two chars */
if (loc++ <=limit) { int c=ccode[(eight_bits)*loc++];
***************
*** 659,664 ****
--- 951,957 ----
|get_next| to take additional actions:
\yskip\hang |xref_roman|, |xref_wildcard|, |xref_typewriter|, |TeX_string|,
+ |meaning|, |suppress|,
|verbatim|: The values of |id_first| and |id_loc| will have been set to
the beginning and ending-plus-one locations in the buffer.
***************
*** 728,734 ****
for |ord|, since |get_next| changes |ord| into a string.
@d left_preproc ord /* begins a preprocessor command */
! @d right_preproc 0217 /* ends a preprocessor command */
@<Glob...@>=
boolean preprocessing=0; /* are we scanning a preprocessor command? */
--- 1021,1027 ----
for |ord|, since |get_next| changes |ord| into a string.
@d left_preproc ord /* begins a preprocessor command */
! @d right_preproc 0223 /* ends a preprocessor command */
@<Glob...@>=
boolean preprocessing=0; /* are we scanning a preprocessor command? */
***************
*** 894,902 ****
case translit_code: err_print("! Use @@l in limbo only"); continue;
@.Use @@l in limbo...@>
case underline: xref_switch=def_flag; continue;
case trace: tracing=c-'0'; continue;
case xref_roman: case xref_wildcard: case xref_typewriter:
! case noop: case TeX_string: c=ccode[c]; skip_restricted(); return(c);
case section_name:
@<Scan the section name and make |cur_section| point to it@>;
case verbatim: @<Scan a verbatim string@>;
--- 1187,1198 ----
case translit_code: err_print("! Use @@l in limbo only"); continue;
@.Use @@l in limbo...@>
case underline: xref_switch=def_flag; continue;
+ case temp_meaning: temp_switch=1-temp_switch; continue;
+ case right_start: right_start_switch=1; continue;
case trace: tracing=c-'0'; continue;
case xref_roman: case xref_wildcard: case xref_typewriter:
! case meaning: case suppress:
! case noop: case TeX_string: c=ccode[(eight_bits)c]; skip_restricted(); return(c);
case section_name:
@<Scan the section name and make |cur_section| point to it@>;
case verbatim: @<Scan a verbatim string@>;
***************
*** 975,981 ****
@ @c
void
skip_restricted()
! {
id_first=loc; *(limit+1)='@@';
false_alarm:
while (*loc!='@@') loc++;
--- 1271,1277 ----
@ @c
void
skip_restricted()
! { int c=ccode[(eight_bits)*(loc-1)];
id_first=loc; *(limit+1)='@@';
false_alarm:
while (*loc!='@@') loc++;
***************
*** 989,997 ****
--- 1285,1346 ----
if (*loc++!='>')
err_print("! Control codes are forbidden in control text");
@.Control codes are forbidden...@>
+ if (c==meaning && phase==2) @<Process a user-generated meaning@>@;
+ else if (c==suppress && phase==2) @<Suppress mini-index entry@>;
}
}
+ @ @<Suppress mini-index entry@>=
+ { char *first=id_first,*last=id_loc;
+ while (xisspace(*first)) first++;
+ while (xisspace(*(last-1))) last--;
+ if (first<last) {
+ struct perm_meaning *q=id_lookup(first,last,normal)-name_dir+cur_meaning;
+ q->stamp=section_count; /* this is what actually suppresses output */
+ }
+ }
+
+ @ @<Process a user-generated meaning@>=
+ { char *first=id_first;
+ while (xisspace(*first)) first++;
+ loc=first;
+ while (xisalpha(*loc)||xisdigit(*loc)||*loc=='_') loc++;
+ if (*loc++!=' ')
+ err_print("! Identifier in meaning should be followed by space");
+ else { name_pointer p=id_lookup(first,loc-1,normal);
+ sixteen_bits t; int n=0;
+ t=title_lookup();
+ if (*(loc-1)=='}')
+ while (xisdigit(*loc)) n=10*n+(*loc++)-'0';
+ if (*loc++!=' ')
+ err_print("! Location in meaning should be followed by space");
+ else @<Digest the meaning of |p|, |t|, |n|@>;
+ }
+ loc=id_loc+2;
+ }
+
+ @ @<Digest...@>=
+ { meaning_struct *m;
+ struct perm_meaning *q=p-name_dir+cur_meaning;
+ if (temp_switch) {
+ m=temp_meaning_ptr++;
+ if (temp_meaning_ptr>max_temp_meaning_ptr) {
+ if (temp_meaning_ptr>&temp_meaning_stack[max_meanings])
+ overflow("temp meanings");
+ max_temp_meaning_ptr=temp_meaning_ptr;
+ }
+ } else m=&(q->perm);
+ m->id=p;
+ m->prog_no=t;
+ m->sec_no=n;
+ if (id_loc-loc>=max_tex_chars) strcpy(m->tex_part,"\\zip");
+ @.\\zip@>
+ else { char *q=m->tex_part;
+ while (loc<id_loc) *q++=*loc++;
+ *q='\0';
+ }
+ }
+
@ At the present point in the program we
have |*(loc-1)==verbatim|; we set |id_first| to the beginning
of the string itself, and |id_loc| to its ending-plus-one location in the
***************
*** 1029,1039 ****
void
phase_one() {
phase=1; reset_input(); section_count=0;
! skip_limbo(); change_exists=0;
while (!input_has_ended)
@<Store cross-reference data for the current section@>;
- changed_section[section_count]=change_exists;
- /* the index changes if anything does */
phase=2; /* prepare for second phase */
@<Print error messages about unused or undefined section names@>;
}
--- 1378,1387 ----
void
phase_one() {
phase=1; reset_input(); section_count=0;
! skip_limbo();
! @<Give a default title to the program, if necessary@>;
while (!input_has_ended)
@<Store cross-reference data for the current section@>;
phase=2; /* prepare for second phase */
@<Print error messages about unused or undefined section names@>;
}
***************
*** 1041,1048 ****
@ @<Store cross-reference data...@>=
{
if (++section_count==max_sections) overflow("section number");
- changed_section[section_count]=changing;
- /* it will become 1 if any line changes */
if (*(loc-1)=='*' && show_progress) {
printf("*%d",section_count);
update_terminal; /* print a progress report */
--- 1389,1394 ----
***************
*** 1050,1056 ****
@<Store cross-references in the \TEX/ part of a section@>;
@<Store cross-references in the definition part of a section@>;
@<Store cross-references in the \CEE/ part of a section@>;
- if (changed_section[section_count]) change_exists=1;
}
@ The |C_xref| subroutine stores references to identifiers in
--- 1396,1401 ----
***************
*** 1138,1143 ****
--- 1483,1489 ----
case trace: tracing=*(loc-1)-'0'; continue;
case '|': C_xref(section_name); break;
case xref_roman: case xref_wildcard: case xref_typewriter:
+ case meaning: case suppress:
case noop: case section_name:
loc-=2; next_control=get_next(); /* scan to \.{@@>} */
if (next_control>=xref_roman && next_control<=xref_typewriter) {
***************
*** 1365,1375 ****
@ In particular, the |finish_line| procedure is called near the very
beginning of phase two. We initialize the output variables in a slightly
tricky way so that the first line of the output file will be
! `\.{\\input cwebmac}'.
@<Set init...@>=
out_ptr=out_buf+1; out_line=1; active_file=tex_file;
! *out_ptr='c'; tex_printf("\\input cwebma");
@ When we wish to append one character |c| to the output buffer, we write
`|out(c)|'; this will cause the buffer to be emptied if it was already
--- 1711,1725 ----
@ In particular, the |finish_line| procedure is called near the very
beginning of phase two. We initialize the output variables in a slightly
tricky way so that the first line of the output file will be
! `\.{\\input ctwimac}'. Or, if the user has specified proofing by
! saying \.{+P} on the command line, it's `\.{\\input proofmac}',
! a set of macros used when debugging mini-index entries.
@<Set init...@>=
out_ptr=out_buf+1; out_line=1; active_file=tex_file;
! *out_ptr='c';
! if (flags['P']) tex_printf("\\input proofma");
! else tex_printf("\\input ctwima");
@ When we wish to append one character |c| to the output buffer, we write
`|out(c)|'; this will cause the buffer to be emptied if it was already
***************
*** 1379,1385 ****
A line break will occur at a space or after a single-nonletter
\TEX/ control sequence.
! @d out(c) {if (out_ptr>=out_buf_end) break_out(); *(++out_ptr)=c;}
@c
void
--- 1729,1743 ----
A line break will occur at a space or after a single-nonletter
\TEX/ control sequence.
! @d out(c)
! {if (ms_mode) { /* outputting to |ministring_buf| */
! if (ministring_ptr<&ministring_buf[max_tex_chars])
! *ministring_ptr++=c;
! } else {
! if (out_ptr>=out_buf_end) break_out();
! *(++out_ptr)=c;
! }
! }
@c
void
***************
*** 1435,1442 ****
@ Here is a macro that outputs a section number in decimal notation.
The number to be converted by |out_section| is known to be less than
! |def_flag|, so it cannot have more than five decimal digits. If
! the section is changed, we output `\.{\\*}' just after the number.
@c
void
--- 1793,1799 ----
@ Here is a macro that outputs a section number in decimal notation.
The number to be converted by |out_section| is known to be less than
! |def_flag|, so it cannot have more than five decimal digits.
@c
void
***************
*** 1445,1452 ****
{
char s[6];
sprintf(s,"%d",n); out_str(s);
- if(changed_section[n]) out_str ("\\*");
- @.\\*@>
}
@ The |out_name| procedure is used to output an identifier or index
--- 1802,1807 ----
***************
*** 1502,1507 ****
--- 1857,1863 ----
case format_code: if (get_next()==identifier) get_next();
if (loc>=limit) get_line(); /* avoid blank lines in output */
break; /* the operands of \.{@@s} are ignored on this pass */
+ case right_start: right_start_switch=1; break;
default: err_print("! Double @@ should be used in limbo");
@.Double @@ should be used...@>
out('@@');
***************
*** 1711,1716 ****
--- 2067,2073 ----
@d new_exp 60 /* \&{new} and a following type identifier */
@d begin_arg 61 /* \.{@@[} */
@d end_arg 62 /* \.{@@]} */
+ @d title 63 /* program name or header name in a ``meaning'' */
@<Glo...@>=
char cat_name[256][12];
***************
*** 2101,2106 ****
--- 2458,2464 ----
@<Global...@>=
scrap scrap_info[max_scraps]; /* memory array for scraps */
+ scrap null_scrap; /* a scrap with empty translation */
scrap_pointer scrap_info_end=scrap_info+max_scraps -1; /* end of |scrap_info| */
scrap_pointer pp; /* current position for reducing productions */
scrap_pointer scrap_base; /* beginning of the current scrap sequence */
***************
*** 2110,2115 ****
--- 2468,2474 ----
scrap_pointer max_scr_ptr; /* largest value assumed by |scrap_ptr| */
@ @<Set init...@>=
+ null_scrap.trans=&tok_start[0];
scrap_base=scrap_info+1;
max_scr_ptr=scrap_ptr=scrap_info;
***************
*** 2158,2165 ****
default: @<Print token |r| in symbolic form@>;
}
}
! fflush(stdout);
}
@ @<Print token |r|...@>=
switch (r) {
--- 2517,2528 ----
default: @<Print token |r| in symbolic form@>;
}
}
! printf("|\n"); fflush(stdout);
}
+ @#
+ void pr_txt(k)
+ int k;
+ { print_text(&tok_start[k]); }
@ @<Print token |r|...@>=
switch (r) {
***************
*** 2444,2458 ****
occurrence of the identifier that we're making reserved; hence
the |for| loop below.
@c
void
make_reserved(p) /* make the first identifier in |p->trans| like |int| */
scrap_pointer p;
{
sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
! token_pointer tok_loc; /* pointer to |tok_value| */
! if ((tok_loc=find_first_ident(p->trans))<=operator_found)
! return; /* this should not happen */
tok_value=*tok_loc;
for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
if (p->cat==exp) {
--- 2807,2823 ----
occurrence of the identifier that we're making reserved; hence
the |for| loop below.
+ We use the fact that |make_underlined| has been called immediately preceding
+ |make_reserved|, hence |tok_loc| has been set.
+
@c
+ token_pointer tok_loc; /* where the first identifier appears */
void
make_reserved(p) /* make the first identifier in |p->trans| like |int| */
scrap_pointer p;
{
sixteen_bits tok_value; /* the name of this identifier, plus its flag*/
! if (tok_loc<=operator_found) return; /* this should not happen */
tok_value=*tok_loc;
for (;p<=scrap_ptr; p==lo_ptr? p=hi_ptr: p++) {
if (p->cat==exp) {
***************
*** 2481,2487 ****
/* underline the entry for the first identifier in |p->trans| */
scrap_pointer p;
{
- token_pointer tok_loc; /* where the first identifier appears */
if ((tok_loc=find_first_ident(p->trans))<=operator_found)
return; /* this happens, for example, in |case found:| */
xref_switch=def_flag;
--- 2846,2851 ----
***************
*** 2533,2538 ****
--- 2897,3018 ----
while (r->xlink!=q) {r->num=r->xlink->num; r=r->xlink;}
r->num=m; /* everything from |q| on is left undisturbed */
+ @ \.{CTWILL} needs the following procedure, which appends tokens of a
+ translated text until coming to |tok_loc|, then suppresses text that may
+ appear between parentheses or brackets. The calling routine should set
+ |ident_seen=0| first. (This is admittedly tricky.)
+
+ @c boolean ident_seen;
+ boolean app_supp(p)
+ text_pointer p;
+ { token_pointer j;
+ text_pointer q;
+ if (ident_seen && **p>=tok_flag) {
+ q=**p-tok_flag+tok_start;
+ if (**q=='(') {
+ app('(');@+app('\\');@+app(',');@+app(')'); goto catch14;
+ }
+ if (**q=='[') {
+ app('[');@+app('\\');@+app(',');@+app(']'); goto catch14;
+ }
+ }
+ for (j=*p;j<*(p+1);j++) {
+ if (*j<tok_flag) {
+ if (*j==inserted) return 0;
+ if (j==tok_loc) ident_seen=1;
+ else app(*j);
+ } else if (*j>=inner_tok_flag) confusion("inner");
+ else if (app_supp(*j-tok_flag+tok_start)) goto catch14;;
+ }
+ return 0;
+ catch14: if (*(*(p+1)-1)=='9') return 1; /* production 14 was used */
+ else return 0;
+ }
+
+ @ The trickiest part of \.{CTWILL} is the procedure |make_ministring(l)|,
+ which tries to figure out a symbolic form of definition after
+ |make_underlined(pp+l)| has been called. We rely heavily on the
+ existing productions, which force the translated texts to have a
+ structure that's decodable even though the underlying |cat| and |mathness|
+ codes have disappeared.
+
+ @c void
+ make_ministring(l)
+ int l; /* 0, 1, or 2 */