3
FWEB version 1.62 (September 25, 1998)
5
Based on version 0.5 of S. Levy's CWEB [copyright (C) 1987 Princeton University]
7
@x-----------------------------------------------------------------------------
10
\Title{STYLE.WEB} % Reading the style file for FWEAVE and FTANGLE.
14
Here we read a style file. Style files are used to customize the output of
15
\FWEAVE---for example, to adjust the appearance of the index. The default
16
style file is called \.{fweb.sty} in the directory set by the environment
17
variable \.{FWEB\_STYLE\_DIR}, or in the directory of the \WEB\ source.
18
The name can be changed with the \.{-z}~option: ``\.{-znew\_name}''.
20
Unlike the rest of the \FWEB\ processors, the style file does not
21
automatically convert its input into |ASCII|. That's because most of its
22
fields are never manipulated internally, but are just written to the output
23
file. This may or may not have been a good design decision.
25
Associations between vocabulary words and internal \FWEB\ fields are made
28
\It{We should discuss the detailed scheme here.}
35
@<Typedef declarations@>@;
36
@<Global variables@>@;
46
@d CMNT_CHAR '%' // The comment character in the style file.
50
@ We need a few miscellaneous declarations.
53
outer_char HUGE *sprm_buf,HUGE *sprm_ptr,HUGE *sprm_end; // For \.{-p} option.
54
outer_char HUGE *sprm_ptr0; // Marks beginning of command-line \.{-p} options.
57
static BUF_SIZE sbuf_len; // Length of line buffer.
58
static outer_char HUGE *stemp, HUGE *stemp_end,HUGE *tloc; /* Temporary
59
hold for the argument, and position in it. */
60
static outer_char cur_char; /* Current character after possible escape
63
extern outer_char xchr[];
65
@* PROCESSING ARGUMENTS. We begin with a routine that converts the
66
character representation of an escaped character to the proper byte. Note
67
that the escapes \.{'\\\\'}, \.{'\\''}, \.{'\\"'}, and~\.{'\\?'} can be
68
handled as part of the |default|. This routine also handles octal and hex
69
escapes of the form~\.{\\123} or~\.{\\xFF}. The function takes the address
70
of a pointer to the first character; when it exits, that pointer has been
71
updated to the next non-translated character. We provide separate
72
functions for escaping |outer_char|s and |ASCII|s.
74
@d isodigit(c) (isdigit(c) && (c)!='8' && (c)!='9')
75
// An |outer_char| octal digit?
80
CONST outer_char HUGE * HUGE *ppc C1("")@;
84
CONST outer_char HUGE *pc = *ppc; // Pointer to first character after~'\.\\'.
87
@<Process octal constant@>@;
88
else if(*pc == 'x' && isxdigit(*(pc+1)))
89
@<Process hex constant@>@;
91
{ /* Handle ordinary escaped character. */
94
case 'a': n = '\007'; @+ break;
95
case 'b': n = '\b'; @+ break;
96
case 'e': n = '\033'; @+ break; // Non-ANSI (escape).
97
case 'f': n = '\f'; @+ break;
98
case 'n': n = '\n'; @+ break;
99
case 'r': n = '\r'; @+ break;
100
case 't': n = '\t'; @+ break;
101
case 'v': n = '\v'; @+ break;
103
n = (unsigned)(*pc); // Unknowns, like '\.{\\m}' $\to$~'\.m'.
110
return (outer_char)n;
113
@ Octal constants have the form \.{\\123}.
114
@<Process octal constant@>=
122
n = 8*n + ctoi(*pc++);
126
@ Hex constants have the form \.{\\xFF}.
127
@<Process hex constant@>=
129
pc++; // Position after \.{'x'}.
133
n = 16*n + ctoi(*pc++);
136
@ The corresponding function for |ASCII|.
141
CONST ASCII HUGE * HUGE *ppc C1("")@;
145
CONST ASCII HUGE *pc = *ppc; // Pointer to first character after~'\.\\'.
148
@<Process Octal constant@>@;
149
else if(*pc == @'x' && isXdigit(*(pc+1)))
150
@<Process Hex constant@>@;
155
case @'a': n = @'\007'; @+ break;
156
case @'b': n = @'\b'; @+ break;
157
case @'e': n = @'\033'; @+ break; // Non-ANSI (escape).
158
case @'f': n = @'\f'; @+ break;
159
case @'n': n = @'\n'; @+ break;
160
case @'r': n = @'\r'; @+ break;
161
case @'t': n = @'\t'; @+ break;
162
case @'v': n = @'\v'; @+ break;
163
default: n = *pc; @+ break; // Unknowns, like '\.{\\m}' $\to$~'\.m'.
172
*ppc = pc; // Advance the pointer to point beyond the end of the constant.
178
return (ASCII)n; // Return the value.
181
@ Octal constants have the form \.{\\123}. The following is for |ASCII|.
182
@<Process Octal constant@>=
187
if(!isOdigit(*pc)) break;
188
n = 8*n + Ctoi(*pc++);
192
@ Hex constants have the form \.{\\xFF}. The following is for |ASCII|.
193
@<Process Hex constant@>=
195
pc++; // Position after \.{'x'}.
197
if(isXdigit(*pc)) n = 16*n + Ctoi(*pc++);
200
@ Translate a hex |outer_char| into integer.
202
@m XC(cin,cout) case cin: return 0x##cout@;
204
@d Ctoi(c) ctoi(XCHR(c)) // For |ASCII|.
209
outer_char c C1("")@;
213
XC('0',0); XC('1',1); XC('2',2); XC('3',3); XC('4',4); XC('5',5);
214
XC('6',6); XC('7',7); XC('8',8); XC('9',9);
215
XC('a',a); @+ XC('A',A);
216
XC('b',b); @+ XC('B',B);
217
XC('c',c); @+ XC('C',C);
218
XC('d',d); @+ XC('D',D);
219
XC('e',e); @+ XC('E',E);
220
XC('f',f); @+ XC('F',F);
225
@ Search for a keyword. Returns address of the relevant |S_MAP| entry.
228
HUGE *find_sty FCN((m,keyword))
229
S_MAP HUGE *m C0("Array of map variables")@;
230
CONST outer_char HUGE *keyword C1("Search for this keyword")@;
232
for(; *(m->keyword); m++)
233
if(STRCMP(keyword,m->keyword) == 0) return m;
238
@ Read one line from style file.
243
typedef enum {FROM_INI, FROM_LOCAL, FROM_CMD_LINE} STYLE_MODE;
245
static STYLE_MODE mode = FROM_INI;
247
from_sprm = BOOLEAN(mode == FROM_INI || mode == FROM_CMD_LINE);
252
if(!sty0_line(sprm_ptr0))
264
return sty0_line(sprm_end);
267
return YES; // Dummy.
271
sty0_line FCN((last_sprm))
272
outer_char HUGE *last_sprm C1("")@;
274
int c; /* Single character read from style file. |int| rather than |char|
275
because that's what |getc| returns. */
277
sloc = slimit = sbuf; // Position to beginning of line.
280
{ /* Read from the \.{-p} buffer. */
281
if(sprm_ptr >= last_sprm)
282
{ /* Nothing more in the \.{-p} buffer. */
287
{ /* Copy line from \.{-p} buffer. */
291
if((p=(outer_char HUGE *)STRCHR(sprm_ptr,'\n')) == NULL)
293
err_print(S,"Trouble in sty_line");
296
else n = PTR_DIFF(int, p, sprm_ptr);
298
STRNCPY(sloc,sprm_ptr,n);
305
{ /* Read from the local style file. */
307
@<Attempt to open style file@>@;
309
@<Move characters from style file; |return NO| if end-of-file@>@;
316
@<Attempt to open...@>=
318
outer_char full_sty_name[MAX_FILE_NAME_LENGTH];
320
/* If there's no style file, do nothing. */
326
STRCPY(full_sty_name, sty_file_name);
327
add_prefix(full_sty_name);
330
mk_fname(full_sty_name, MAX_FILE_NAME_LENGTH,
331
OC(ENV_FWEB_STY), NO,sty_file_name);
333
if((sty_file = fopen((char *)full_sty_name,"r")) == NULL)
337
err_print(C,"Can't open style file %s",
343
reading(full_sty_name,YES);
347
@<Move characters from style...@>=
354
while((c = getc(sty_file)) != EOF && c != '\n')
356
if(slimit == sbuf_end)
358
err_print(S,"Input line too long; max is %lu characters",
364
*slimit++ = (outer_char)c; // Put character into buffer.
368
@ Extract the next argument from the style file. Keywords begin with an
369
alphabetic character or an underscore.
374
outer_char c; /* Single character from the buffer. */
378
/* If we get to the end of the line or recognize a comment, read the next
380
if(sloc == slimit || (c= *sloc++) == CMNT_CHAR)
383
return S_DONE; // Get more.
388
if(isalpha(c) || c=='_')
390
else if(isdigit(c) || c=='-' || c=='+')
395
@<Style character@>@;
396
else if(c==' ' || c=='\t' || c=='=')
400
err_print(S,"Invalid style-file field; \
401
skipping remainder of file");
402
longjmp(top_of_style,1);
406
DUMMY_RETURN(S_DONE);
409
@ Read a keyword into the buffer |stemp|. Keywords consists of
410
alphanumeric characters, underscores, or periods. However, the periods are
411
made equivalent to underscore so one can things such as ``\.{color.red}''
412
instead of ``\.{color\_red}''.
414
@m S_RETURN(t) *tloc = '\0'; return S_##t@; /* Terminate |stemp|, and
415
return the appropriate type. */
423
&& (isalpha(*sloc) || isdigit(*sloc) || *sloc=='_' || *sloc=='.'))
426
@<Copy and translate style character@>@;
432
@ Move one character into |stemp|.
433
@<Copy and translate style char...@>=
436
*tloc++ = (outer_char)CHOICE(cur_char=='.', '_', cur_char);
439
err_print(S, "Style-file buffer overflow. \
440
Try using `-ysb' to increase the size");
446
@<Copy style character@>=
452
err_print(S, "Style-file buffer overflow. \
453
Try using `-ysb' to increase the size");
458
@ Process a string argument (bracketed by double quotes). We must allow
459
for escapes, such as ``\.{\\123}''.
462
tloc = stemp; /* Start of buffer. */
468
err_print(S, "Missing double quote inserted at end of string. \
469
Did you mean to continue the line with '\\'? \
470
(No white space is allowed after the '\\'.)");
478
sty_line(); // String is continued.
482
cur_char = esc_char(&sloc);
490
sloc++; // Skip over terminating quote.
495
@ Process a numerical argument.
501
if(*sloc=='+' || *sloc=='-')
507
while(sloc < slimit && isdigit(*sloc))
516
/* We allow the possibility of long integers. */
517
if(*sloc == 'l' || *sloc == 'L')
519
sloc++; // Skip over '\.L'.
526
@ Process a character argument such as~'\.c' or~'\.{\\n}'.
531
/* If the character is escaped, turn the next character into the actual
536
cur_char = esc_char(&sloc);
544
err_print(S, "Missing single quote inserted");
546
sloc++; // Skip over closing quote.
551
@* READING the STYLE FILE.
552
The style file is both opened and closed in this module.
558
static CONST outer_char *sty_file_name;
559
static boolean warn_if_absent;
560
static FILE *sty_file;
561
static S_MAP HUGE *map_array = fweb_map; /* Points to the common map
562
array for both \FWEAVE\ and \FTANGLE. */
563
jmp_buf top_of_style; // Environment for the |setjmp|--|longjmp|.
565
@ It's read line by line into a buffer. The length of that buffer can be
566
set by dynamic memory allocation with option~\.{-ysb}.
568
@d ENV_FWEB_STY "FWEB_STYLE_DIR" /* Environment variable that defines
569
directory of style file. */
573
read_sty FCN((sty_file_name0,warn_if_absent0))
574
CONST outer_char sty_file_name0[] C0("")@;
575
boolean warn_if_absent0 C1("")@;
577
sty_file_name = sty_file_name0;
578
warn_if_absent = warn_if_absent0;
580
@<Modify defaults based on option settings@>@;
582
@<Allocate buffers for the style file@>@;
584
if(setjmp(top_of_style) != 0)
587
/* Read the first line of style file. If the file's empty, do nothing. */
591
/* Parse the file. */
598
@<Process style keyword@>@;
602
err_print(S,"Was expecting keyword or comment here; \
603
skipping remainder of file"); // Falls through to |case S_DONE@:|.
611
FREE_MEM(sprm_buf, "sprm_buf",
612
SPRM_LEN, outer_char);
614
FREE_MEM(stemp,"stemp",sbuf_len,outer_char);
615
FREE_MEM(sbuf,ABBREV(sbuf_len),sbuf_len,outer_char);
620
@ In a few cases, the proper defaults depend on command-line options; for
621
example, which processor will be used to process \FWEAVE's output.
622
@<Modify defaults...@>=
624
IN_COMMON outer_char HUGE *style_args;
626
if(TeX_processor == LaTeX_p)
628
W_META HUGE *m = &w_style.misc.meta;
629
INDEX HUGE *i = &w_style.indx;
631
pfrmt->id = pfrmt->id_outer = pfrmt->id_inner = OC("\\>");
632
pfrmt->ID = pfrmt->ID_OUTER = pfrmt->ID_INNER = OC("\\WUC");
633
pfrmt->RESERVED = OC("\\WRS");
635
m->TeX.begin = OC("\\begin{verbatim}");
636
m->TeX.end = OC("\\end{verbatim}");
637
m->code.begin = OC("\\WBM ");
638
m->code.end = OC("\\WEM ");
640
i->encap_prefix = OC("\\M");
641
i->encap_infix = OC("{");
642
i->encap_suffix = OC("}");
645
if(prn_style_defaults)
646
see_style(style_args, YES);
649
@ We temporarily allocate buffers for working with the style file.
650
@<Allocate buffers...@>=
652
ALLOC(outer_char,sbuf,ABBREV(sbuf_len),sbuf_len,0);
653
sbuf_end = sbuf + sbuf_len;
655
stemp = GET_MEM("stemp",sbuf_len,outer_char);
656
stemp_end = stemp + sbuf_len;
658
/* Reset the \.{-p} buffer. */
659
sprm_end = sprm_ptr; // Actual end of material in buffer.
660
sprm_ptr = sprm_buf; // Start at beginning.
663
@ At the very beginning, initializations must be finished.
668
ini_colors(NO_COLOR); // So default links are set up.
669
ini_colors(ATOI(get_option(OC("-C"))+2)); // Read \.{-C} option from command line.
671
@<Finish initializing mappings@>@;
674
@ Obtaining a command-line option.
675
Command-line arguments are normally processed a bit later in the program.
676
However, in at least one case (the color mode), one needs to know right
677
away whether that has been set. The |get_option| routine scans through all
678
the command-line arguments, comparing their leading characters against its
679
string argument, and returns the string if found.
685
outer_char *s C1("")@;
691
for(k=1; k<argc; k++)
692
if(STRNCMP(s, argv[k], len) == 0)
698
@ We've recognized a keyword. Now deal with its arguments. First, the
699
argument is copied into the appropriate field. Then, if an initialization
700
routine has been defined, that routine is run on the argument. The
701
argument might be checked for validity, or it might be changed into
703
@<Process style key...@>=
705
S_MAP HUGE *ps; // Returned from |find_sty|.
708
/* Is it a valid keyword? */
709
if((ps = find_sty(map_array,stemp)) == NULL)
711
err_print(S,"Invalid style-file keyword; skipping remainder of line");
716
/* Get the next argument. Is its type correct? */
717
type = ps->type & ~S_MODIFIED;
719
if(type != next_sty())
721
err_print(S,"Argument of keyword \"%s\" has wrong type; \
722
conversion to %s attempted", ps->keyword, s_type_name[type]);
734
err_print(S,"Was expecting %s here; argument not processed",
739
/* Store the argument, check for validity, or process the result in some
744
CONFUSION("style keyword","NULL ini fcn");
746
/* Flag it as modified. */
747
ps->type |= S_MODIFIED;
753
@ Initialize a string. (No error checking.)
757
S_MAP HUGE *ps C1("")@;
759
a_str(ps->ptr, (CONST outer_char HUGE *)stemp);
762
@ Here we add a string to an already-existing (non-NULL) one, placing a
763
newline in between. If the original string is null, we just initialize it
769
S_MAP HUGE *ps C1("")@;
771
outer_char HUGE *pa = *(outer_char HUGE **)ps->ptr, HUGE *pb;
773
if(*pa && (ps->type & S_MODIFIED))
775
pb = GET_MEM("add_str", STRLEN(pa) + STRLEN(stemp) + 2, outer_char);
779
*(outer_char HUGE **)ps->ptr = pb;
785
@ Initialize an integer. (No error checking.)
789
S_MAP HUGE *ps C1("")@;
791
*((int *)ps->ptr) = ATOI(stemp);
794
@ Similarly, initialize a long. (No error checking.)
798
S_MAP HUGE *ps C1("")@;
800
*((long *)ps->ptr) = ATOL(stemp);
803
@ Initialize a character (no error checking).
807
S_MAP HUGE *ps C1("")@;
809
*((outer_char *)ps->ptr) = *stemp;
821
CLR_MATCH clr_match[] = {
827
{"magenta", MAGENTA},
835
We begin with an initialization routine for color. It replaces strings like
836
\.{"red"} by enumerated values like~|RED|.
840
S_MAP HUGE *ps C1("")@;
846
for(c=clr_match; STRCMP(c->name,"") != 0; c++)
847
if(STRCMP(c->name, *(outer_char HUGE **)ps->ptr) == 0)
849
*(COLOR *)ps->ptr = c->value;
853
CLR_PRINTF(WARNINGS, warning, ("! Color name \"%s\" is invalid; \
854
replaced by \"default\"\n",(char *)ps->ptr));
857
*(COLOR *)ps->ptr = NORMAL;
860
@ Initialization routine for \.{color.mode} (no longer used).
864
S_MAP HUGE *ps C1("")@;
867
ini_colors((COLOR_MODE)(*(int *)ps->ptr));
870
@ Initialization routines for file name extension are create via a \WEB\
873
@m EXT_LINK(file,dflt) link0(&wt_style.input_ext.file,OC(dflt),ext_set)
876
SRTN ini_##file FCN((ps))
877
CONST S_MAP HUGE *ps C1("")@;
879
EXT_LINK(file,(outer_char *)ps->ptr);
883
/* Actual functions are being created here. */
893
S_MAP HUGE *ps C1("")@;
896
ext_set((CONST outer_char HUGE **)ps->ptr);
899
@ Convert the delimiters for dot constants to |ASCII|.
903
S_MAP HUGE *ps C1("")@;
906
*(ASCII *)ps->ptr = XORD(*(outer_char *)ps->ptr);
913
S_MAP HUGE *ps C1("")@;
918
c = *(outer_char *)ps->ptr;
920
if(!(c && isprint(c) && c != ' ' && c != '0'))
922
*(outer_char *)ps->ptr = CCHAR;
923
err_print(S,"Invalid continuation character '%c'; '%c' assumed",
928
@ Here we check the validity of the line length for Fortran's output.
932
ini_output_line_length FCN((ps))
933
S_MAP HUGE *ps C1("")@;
935
int output_line_length;
938
output_line_length = *(int *)ps->ptr;
940
if(output_line_length < MIN_OUTPUT_LINE_LENGTH ||
941
output_line_length > MAX_OUTPUT_LINE_LENGTH)
943
*(int *)ps->ptr = STANDARD_OUTPUT_LINE_LENGTH;
944
err_print(S,"Line length %d is invalid; %d assumed",
946
STANDARD_OUTPUT_LINE_LENGTH + FORTRAN90_LIKE(language));
954
CONST S_MAP HUGE *ps C1("")@;
959
temp = GET_MEM("temp_cdir",
960
(n=2*STRLEN(*((outer_char HUGE **)ps->ptr)))+1,outer_char);
961
esc_buf(temp,temp+n,*((CONST outer_char HUGE **)ps->ptr),stemp,YES);
964
@* INITIALIZING CONTROL CODES.
965
The control code mapping can be overridden from the style file, although
966
this is not recommended except in unusual circumstances.
972
eight_bits ccode[128]; // Meaning of a character following '\.{@@}'.
973
CONST outer_char *cname[128]; // Associated names of control codes.
974
CONST ASCII HUGE *at_codes;
976
@ Here we initialize |ccode| with values that aren't allowed to be changed
977
by the style file. The flag |USED_BY_NEITHER| is written into everything
978
first; if such a control code is encountered during the scan of either
979
processor, an error message will be issued.
985
int c; // Must be |int|, not |eight_bits|, so the |for| loop will end.
988
/* Start out by initializing the array to a special flag. */
989
for (c=0; c<=127; c++)
991
ccode[c] = USED_BY_NEITHER;
995
@<Initialize unchangable codes@>@;
998
@ The following several codes aren't allowed to be changed.
999
@<Initialize unchangable...@>=
1001
ccode[@'@@']=@'@@'; /* `quoted' at sign. This is so fundamental that it
1002
isn't allowed to be changed by the style file. */
1004
ccode[@'{'] = @'{'; /* Since this is related to the C or \Ratfor\ languages,
1005
it shouldn't be changed. */
1006
ccode[@'}'] = @'}'; // As above.
1008
ccode[@'>'] = ignore;
1009
/* |ignore| is historical, and probably dangerous. But
1010
it can't be |USED_BY_NEITHER|, because some of the routines
1011
that scan over control text expect this control code to be
1012
returned from |get_control_code|. */
1015
@ The next routine is used by \FWEAVE\ or \FTANGLE\ to initialize the
1016
control code table. Say, for example,
1017
``\.{INI\_CCODE("Aa",begin\_code)}. If at any point a |ccode|
1018
entry has already been filled in, that means we \It{must} use the default
1019
value. Thus, if the style file has attempted to override that value,
1020
we complain---and abort after we've checked all the initializations.
1023
ini_ccode FCN((keyword,defaults,code))
1024
CONST outer_char *keyword C0("The desired keyword.")@;
1025
CONST outer_char *defaults C0("String of default characters.")@;
1026
eight_bits code C1("Assign this \FWEB\ universal code")@;
1028
CONST outer_char *pc; /* Pointer to the default characters to initialize. */
1029
CONST S_MAP HUGE *m; /* Points to map entry for requested keyword. */
1030
boolean bad_code = NO;
1032
boolean override; /* Are the default values overridden by the style file? */
1033
IN_COMMON outer_char style_file_name[];
1034
ASCII a; // Position in |ccode|.
1036
/* Search for the keyword in the map array. */
1037
if( (m=find_sty(map_array,keyword)) == NULL)
1038
override = NO; // The keyword isn't even in the table.
1040
/* If the style file has set some values for this keyword, and the default
1041
values for this code are non-zero, then use the values from the style file.
1042
Otherwise, use the defaults. */
1043
override = BOOLEAN(*(outer_char **)m->ptr != NULL);
1044
// The style file is overriding.
1046
pc = (override && code) ? *(outer_char **)m->ptr : defaults;
1048
/* If we're not ignoring this code completely, assign it to the relevant
1050
if(code != USED_BY_NEITHER)
1053
if(override && ((cval = ccode[XORD(*pc)]) != USED_BY_NEITHER) )
1055
printf("! ccode['%c'] already filled with \"%s\"; \
1056
not filled with \"%s\" = \"%s\".\n",
1057
*pc, (char *)ccode_name(cval), (char *)keyword,
1058
(char *)ccode_name(code));
1069
"Invalid control code mapping; ",
1070
"check the style file %s.",
1074
@ For \FTANGLE, after all the |ccode|s have been assigned, a few of them
1075
must be reinterpreted. For example, by default the codes ``\.{\^.9tT}'' are
1076
all interpreted as |control_text|.
1079
reassign FCN((old_code,new_code))
1080
eight_bits old_code C0("")@;
1081
eight_bits new_code C1("")@;
1085
for(c=0; c<128; c++)
1086
if(ccode[c] == old_code)
1087
ccode[c] = new_code;
1090
@ The following array is used for sorting the control-code keywords.
1093
static CC_BUF HUGE *cc_buf;
1095
@ Here we print out the control code mappings in resonse to \.{-@@}. They
1096
are printed twice, first alphabetized by the control code, next by the
1097
keyword. These are printed out side by side.
1103
IN_COMMON boolean found_web;
1104
int HUGE *cc_indices;
1105
boolean prn_all = NO;
1108
int n = 0; // Number of codes to print.
1113
puts("Control-code assignments \
1114
([S,D,C]==`Begins [Section,Definition,Code])':");
1116
cc_buf = GET_MEM("cc_buf", 128, CC_BUF);
1117
cc_indices = GET_MEM("cc_indices", 128, int);
1119
if(*at_codes && at_codes[0] == @'*' && at_codes[1] == @'*')
1122
if(*at_codes && !prn_all)
1123
{ /* A specific list was given on command line. */
1126
for(p=at_codes; *p; p++)
1127
prn0_code(*p, cc_buf, &n);
1130
{ /* Do all of them. */
1133
for(a=0; a<128; a++)
1135
if(ccode[a] == USED_BY_NEITHER && !prn_all)
1138
prn0_code(a, cc_buf, &n);
1142
FREE_MEM(at_codes, "at_codes", 200, ASCII);
1147
QSORT(cc_indices, n, sizeof(int), cc_cmp);
1150
STRCPY(cc_buf[k][1], cc_buf[cc_indices[k]][0]);
1153
printf("%-40s%-40s\n", cc_buf[k][0], cc_buf[k][1]);
1155
FREE_MEM(cc_buf, "cc_buf", 128, CC_BUF);
1156
FREE_MEM(cc_indices, "cc_indices", 128, int);
1162
@ We alphabetize on the keywords, which follow the `\.{---}'.
1166
cc_cmp FCN((k0, k1))
1167
CONST VOID *pk0 C0("")@;
1168
CONST VOID *pk1 C1("")@;
1172
s0 = strrchr(cc_buf[*(int *)pk0][0], '-');
1173
s1 = strrchr(cc_buf[*(int *)pk1][0], '-');
1175
return STRCMP(s0, s1);
1178
@ The |used_by_buf| is used for printing the interpretation of
1179
|USED_BY_OTHER| control codes, which depend on which processor is currently
1183
@m USED_BY_MSG "Used by ftangle"
1187
outer_char used_by_buf[$XLEN(USED_BY_MSG)+1];
1189
@ Print out one control code.
1192
prn0_code FCN((a, cc_buf, pk))
1194
CC_BUF HUGE *cc_buf C0("")@;
1197
ASCII new_module, begin_code, formatt;
1198
ASCII cc = ccode[a];
1203
/* The following assumes that these particular codes never change. This
1204
was easier than including the header files. */
1205
new_module = ccode[@'*'];
1206
begin_code = ccode[@'a'];
1207
formatt = ccode[@'f'];
1211
if(cc == USED_BY_NEITHER)
1213
else if(cc >= new_module)
1215
else if(cc >= begin_code)
1217
else if(cc >= formatt)
1222
n = NSPRINTF((outer_char *)&cc_buf[*pk][0][0],
1223
isprint(c) ? " %s @@%c" : " %s@@'\\x%02x'",
1224
isprint(c) ? letter : OC(""), c);
1226
if(cc == USED_BY_OTHER)
1228
STRCPY(used_by_buf, "Used by ");
1229
STRCAT(used_by_buf, program==tangle ? WEAVE : TANGLE);
1230
cname[c] = used_by_buf;
1232
else if(cc == USED_BY_NEITHER)
1233
cname[c] = OC("Unassigned");
1237
cname[c] = OC("(verbatim comment)");
1241
cname[c] = OC("(end of module name)");
1245
cname[c] = OC("(literal '@@')");
1249
sprintf(&cc_buf[*pk][0][n], " --- %s", (char *)cname[c]);
1250
(*pk)++; // Increment array index.
1255
@d SET_ACOLOR(field,clr) wt_style.color.field.value = clr
1259
static outer_char HUGE *tcap_buffer; // Allocated dynamically.
1261
@ Colors are initialized to default values, then overridden for several
1265
ini_colors FCN((color_mode0))
1266
COLOR_MODE color_mode0 C1("")@;
1268
color_mode = color_mode0;
1270
@<Set default colors@>@; // Attach colors to fields.
1272
if(!(termcap=get_termcap()))
1273
color_mode = NO_COLOR;
1279
@<Make default links between bilevel mode and colors@>@;
1283
CLR_LINK1(NORMAL, "\033[0m");
1284
CLR_LINK1(BLACK, "\033[01;30m");
1285
CLR_LINK1(RED, "\033[01;31m");
1286
CLR_LINK1(GREEN, "\033[01;32m");
1287
CLR_LINK1(YELLOW, "\033[01;33m");
1288
CLR_LINK1(BLUE, "\033[01;34m");
1289
CLR_LINK1(MAGENTA, "\033[01;35m");
1290
CLR_LINK1(CYAN, "\033[01;36m");
1291
CLR_LINK1(WHITE, "\033[01;37m");
1295
CLR_LINK(NORMAL, me);
1296
CLR_LINK(BLACK, me);
1297
CLR_LINK(RED, mdmr);
1298
CLR_LINK(GREEN, md);
1299
CLR_LINK(YELLOW, md);
1301
CLR_LINK(MAGENTA, me);
1303
CLR_LINK(WHITE, mr);
1307
CLR_LINK(NORMAL, me);
1308
CLR_LINK(BLACK, me);
1309
CLR_LINK(RED, mdmr);
1310
CLR_LINK(GREEN, md);
1311
CLR_LINK(YELLOW, md);
1312
CLR_LINK(BLUE, usmd);
1313
CLR_LINK(MAGENTA, me);
1315
CLR_LINK(WHITE, mr);
1322
beeps = YES; // Not set yet from the style file.
1323
printf("!%c Color mode %i is invalid; replaced by 0.\n",
1324
beep(1), color_mode); // Can't be in color; defaults not set yet.
1326
color_mode = NO_COLOR;
1333
@ Get control sequence for a color. This is an ini routine for
1337
ini_bilevel FCN((ps))
1338
S_MAP HUGE *ps C1("")@;
1348
@ Default color assignments to the various FWEB fields. Change these in the
1349
style file by saying ``\.{color.error = "red"}''.
1351
@<Set default colors@>=
1353
SET_ACOLOR(ordinary, NORMAL);
1354
SET_ACOLOR(program_name, CYAN);
1355
SET_ACOLOR(md_name, CYAN);
1356
SET_ACOLOR(info, GREEN);
1357
SET_ACOLOR(warning, YELLOW);
1358
SET_ACOLOR(error, RED);
1359
SET_ACOLOR(fatal, RED);
1360
SET_ACOLOR(module_num, MAGENTA);
1361
SET_ACOLOR(line_num, MAGENTA);
1362
SET_ACOLOR(in_file, CYAN);
1363
SET_ACOLOR(include_file, BLUE);
1364
SET_ACOLOR(out_file, CYAN);
1365
SET_ACOLOR(timing, MAGENTA);
1366
SET_ACOLOR(character, MAGENTA);
1369
@ Associate a color with a control sequence.
1370
`\.{me}'---turn off all appearance modes.
1371
`\.{md}'---double-bright mode.
1372
`\.{mr}'---reverse video.
1374
@d CLR_LINK(CLR,id) link0(&wt_style.color._##CLR, OC(#id), termset)
1375
@d CLR_LINK1(CLR,id) link0(&wt_style.color._##CLR, OC(id), termset)
1377
@<Make default links...@>=
1379
CLR_LINK(NORMAL, me);
1380
CLR_LINK(BLACK, me);
1381
CLR_LINK(RED, mdmr);
1382
CLR_LINK(GREEN, me);
1383
CLR_LINK(YELLOW, md);
1385
CLR_LINK(MAGENTA, me);
1387
CLR_LINK(WHITE, mr);
1393
link0 FCN((pp,id,fcn))
1394
outer_char HUGE **pp C0("")@;
1395
CONST outer_char HUGE *id C0("")@;
1396
SRTN (HUGE_FCN_PTR *fcn)PROTO((CONST outer_char HUGE **)) C1("")@;
1398
a_str(pp, id); // Allocate space, and store abbreviation string.
1399
(*fcn)((CONST outer_char HUGE **)pp); /* Replace that string by actual escape
1403
@ Similarly, initialize extensions.
1405
@<Finish initializing mappings@>=
1407
EXT_LINK(web, "web");
1408
EXT_LINK(change, "ch");
1409
EXT_LINK(hweb, "hweb");
1410
EXT_LINK(hchange, "hch");
1413
@ Allocate and store an abbreviation string.
1417
outer_char HUGE **pp C0("")@;
1418
CONST outer_char HUGE *id C1("")@;
1420
@% if(*pp) FREE(*pp); // It's VERY destructive to free memory here!
1421
*((outer_char HUGE * *)pp) = GET_MEM("map_string", STRLEN(id)+1, outer_char);
1422
STRCPY(*((outer_char HUGE * *)pp), id);
1425
@ Open and read the termcap file.
1427
@d ENV_TERM "TERM" // Unix environment variable for terminal type.
1436
if((termcap = GETENV(ENV_TERM)) == NULL)
1439
tcap_buffer = GET_MEM("tcap_buffer", 1024, outer_char);
1441
switch(tgetent(tcap_buffer, termcap))
1444
printf("! Can't open termcap file `%s'.\n", (char *)termcap);
1451
#endif // |HAVE_GETENV|
1454
@ On entry, takes as argument a pointer to a string of blank-separated
1455
abbreviations. On exit, the pointer is changed to point to a |SEQUENCES|
1456
structure that contains the actual escape sequences.
1463
CONST outer_char HUGE **pid C1("")@;
1465
outer_char value_buf[500], *area = value_buf; // For |tgetstr|.
1468
CONST outer_char HUGE *t;
1471
SEQUENCES HUGE *ps = GET_MEM("termcap struct", 1, SEQUENCES);
1472
outer_char *string[NUM_TEMP_PTRS];
1477
for(t=*pid,n=0; *t; t+=len)
1479
if(n == NUM_TEMP_PTRS)
1486
printf("TERMSET: <0%o>: `%s'\n", t[0], t+1);
1490
{ /* Kludge: Recognized a hard-coded escape sequence. */
1492
string[n++] = (outer_char *)t;
1495
@<Get escape sequence from termcap file@>@;
1498
@<Allocate and initialize memory for the strings@>@;
1504
/* Put the abbreviation for escape sequence into |id|. */
1506
STRNCPY(id, t, len);
1509
/* Get the actual escape sequence from termcap file. */
1510
if((s=tgetstr(id, &area)) == NULL)
1511
printf("! Termcap entry \"%s\" not found \
1512
for terminal type \"%s\".\n", (char *)id, (char *)termcap);
1518
@<Allocate and initialize memory for the strings@>=
1521
ps->string = GET_MEM("termcap strings", n, outer_char *);
1525
ps->string[k] = GET_MEM("termcap string",
1526
STRLEN(string[k])+1,outer_char);
1527
STRCPY(ps->string[k],string[k]);
1530
FREE((void *)(*pid));
1531
*pid = (CONST outer_char HUGE *)ps;
1534
@ A similar routine processes a blank-delimited list of extensions.
1538
CONST outer_char HUGE **pid C1("")@;
1540
outer_char id[1000],*p,*p0;
1541
CONST outer_char HUGE *t;
1542
outer_char *string[NUM_TEMP_PTRS];
1544
SEQUENCES HUGE *ps = GET_MEM("termcap struct", 1, SEQUENCES);
1546
t = *pid; // Beginning of blank-separated list.
1547
n = 0; // Number of fields found.
1548
p = id; // Start of storage area
1552
if(n == NUM_TEMP_PTRS)
1556
t++; // Skip initial white space.
1559
while(*t != ' ' && *t)
1563
string[n++] = p0; // Remember where string is.
1566
@<Allocate and init...@>@;
1569
@ Used by |tputs|, which is an output routine used to send one character.
1570
We need this intermediate function |put_out| because |putchar| is a macro
1580
@ Output the control sequences corresponding to a color. This needs to be
1583
@m SEND(CLR) put_((SEQUENCES *)wt_style.color._##CLR)
1592
set_color FCN((clr))
1595
color0.last = color0.present; // Save the incoming color, for later restore.
1619
color0.present = clr;
1625
sset_color FCN((clr))
1628
#define put_ return sput
1653
@ Send each abbreviation in turn.
1657
SEQUENCES *ps C1("")@;
1661
for(k=0; k<ps->n; k++)
1662
tputs(ps->string[k], 1, put_out);
1665
@ As above, but for writing to strings.
1669
SEQUENCES *ps C1("")@;
1672
outer_char temp[100], *temp1;
1674
if(color_mode == NO_COLOR)
1677
STRCPY(temp, ps->string[0]);
1679
for(k=1; k<ps->n; k++)
1680
STRCAT(temp, ps->string[k]);
1682
temp1 = GET_MEM("sput buf", STRLEN(temp)+1, outer_char);
1683
STRCPY(temp1, temp);
1685
return push_buf(&sput_buf, temp1); // This needs to be freed at some point!
1689
@ Print to terminal in particular color. (This routine is independent of
1690
the particular color mechanism.) \It{Check the variable arguments; they're
1691
not right for Sun-CC yet.}
1695
clr_printf FCN(VA_ALIST((clr,fmt VA_ARGS)))
1698
outer_char *fmt C2("")@;)@;
1702
set_color(clr); // Remembers previous color in |color0.last|.
1704
VA_START(arg_ptr, fmt);
1705
vprintf_(fmt, arg_ptr)@;
1708
set_color(color0.last); // Restore color.
1711
@* PRINTING OUT VALUES.
1715
outer_char *name C1("")@;
1718
outer_char key_name[100];
1721
STRCPY(key_name,name);
1722
for(p=key_name; *p; p++)
1723
if(*p == '.') *p = '_';
1725
for(m=fweb_map; *m->keyword; m++)
1726
if(STRCMP(m->keyword,key_name) == 0)
1728
for(p=key_name; *p; p++)
1729
if(*p == '_') *p = '.';
1731
printf("%s = ",key_name);
1735
if(*(int *)m->ptr < (int)HIGHEST_COLOR)
1736
printf("%s\n",clr_name[*(int *)m->ptr]);
1737
else printf("\"%s\"\n",*(char * *)m->ptr);
1741
printf("'%c'\n",*(char *)m->ptr);
1745
printf("%d\n",*(int *)m->ptr);
1749
printf("%ld\n",*(long *)m->ptr);
1753
printf("INVALID TYPE\n");
1763
@ Query the style-file parameters; from \.{-Z}~option.
1766
see_style FCN((pa, see_all))
1767
CONST outer_char HUGE *pa C0("")@;
1768
boolean see_all C1("")@;
1770
S_MAP HUGE **s0,HUGE **s,HUGE **s1,HUGE *m;
1772
s0 = GET_MEM("s0", sizeof(fweb_map)/sizeof(S_MAP), S_MAP HUGE *);
1774
/* Fill an array of pointers. */
1775
for(s=s0,m=fweb_map; *(m->keyword); s++,m++)
1778
/* Sort the array. */
1779
QSORT(s0, s-s0, sizeof(S_MAP HUGE *), cmpr_s_map);
1781
/* Print out the values. */
1783
printf("%s style-file parameters%s%s%s%s:\n",
1784
see_all ? "Default" : "Modified",
1785
*pa ? " beginning with \"" : "", (char *)pa, *pa ? "\"" : "",
1787
see_all // Got tired of reading this; nobody cares anyway.
1789
0 ? "\n (null or empty values for \
1790
@@ command codes are misleading)" : "");
1792
SET_COLOR(ordinary);
1795
{ /* Convert \.{'.'} to \.{'\_'}. */
1798
for(p=(outer_char HUGE *)pa; *p; p++)
1803
for(s1=s0; s1<s; s1++)
1804
see_map(*s1, pa, see_all);
1806
FREE_MEM(s0,"s0",sizeof(fweb_map)/sizeof(S_MAP),S_MAP);
1812
cmpr_s_map FCN((s0,s1))
1813
S_MAP HUGE **s0 C0("")@;
1814
S_MAP HUGE **s1 C1("")@;
1816
return STRCMP((*s0)->keyword,(*s1)->keyword);
1819
@ Print out an individual style-file parameter.
1822
see_map FCN((s, pa, see_all))
1823
S_MAP HUGE *s C0("")@;
1824
CONST outer_char HUGE *pa C0("")@;
1825
boolean see_all C1("")@;
1830
boolean modified = NO;
1833
if(*pa && STRNCMP(pa, s->keyword, STRLEN(pa)) != 0)
1841
modified = s->type & S_MODIFIED;
1843
/* The |S_CLR| type handles parameters that are arrays of strings. */
1844
if(STRNCMP(s->keyword, "Color", 5) == 0)
1846
ps = (SEQUENCES *)(*(outer_char **)s->ptr);
1850
else if(color_mode == USER_COLORS)
1851
type = S_CLR | modified;
1855
else if(STRNCMP(s->keyword, "ext", 3) == 0)
1858
type = S_CLR | modified;
1866
{ /* Handled modified parameters. */
1867
if(type & S_MODIFIED)
1869
CLR_PRINTF(ALWAYS, warning,
1870
((type == S_CLR_MOD && !modified ? " " : "*")));
1871
type &= ~S_MODIFIED;
1872
// Convert to ordinary type like |S_STRING|.
1878
is_color = (type == S_STRING)
1879
&& *(int *)s->ptr > NULL_COLOR && *(int *)s->ptr < (int)HIGHEST_COLOR;
1883
tput(ps); // Print color parameters in color!
1885
set_color(*(int *)s->ptr);
1887
printf(" %s = ", (char *)s->keyword);
1893
printf("\"%s\"\n",clr_name[*(int *)s->ptr]);
1895
see_str(*((outer_char **)s->ptr), OC("\n"));
1899
printf("'%c'\n",*(outer_char *)s->ptr);
1903
printf("%d\n",*(int *)s->ptr);
1907
printf("%ld\n",*(long *)s->ptr);
1911
ps = (SEQUENCES *)(*(outer_char **)s->ptr);
1913
for(k=0; k<ps->n; k++)
1914
see_str(ps->string[k], OC(" "));
1922
SET_COLOR(ordinary);
1928
see_str FCN((s, eos))
1929
CONST outer_char HUGE *s C0("")@;
1930
CONST outer_char *eos C1("")@;
1939
else if(s < (outer_char HUGE *)100)
1940
{ /* Horrible kludge to handle stupid color processing. (Maybe no
1941
longer necessary.) */
1959
case '\a': c = 'a'; goto print_it;
1960
case '\b': c = 'b'; goto print_it;
1961
case '\f': c = 'f'; goto print_it;
1962
case '\n': c = 'n'; goto print_it;
1963
case '\r': c = 'r'; goto print_it;
1964
case '\t': c = 't'; goto print_it;
1965
case '\v': c = 'v'; goto print_it;
1966
case '\033': c = 'e'; goto print_it; // Escape.