~ubuntu-branches/ubuntu/vivid/fweb/vivid

« back to all changes in this revision

Viewing changes to .pc/18-Web--style.web.patch/Web/style.web

  • Committer: Package Import Robot
  • Author(s): Jari Aalto
  • Date: 2011-11-18 21:05:43 UTC
  • Revision ID: package-import@ubuntu.com-20111118210543-i4gn84g98pi86war
Tags: 1.62-11.1
* Non-maintainer upload.
  - Move to packaging format "3.0 (quilt)".
* debian/compat
  - Update to 8.
* debian/control
  - (Build-Depends): update to debhelper 8.
  - (Description): Adjust first line (lintian).
  - (Homepage): Add.
  - (Recommends): Change to tetex-base to texlive (Closes: #601268).
  - (Standards-Version): Update to 3.9.2.
  - (Suggests): Remove tetex-base.
  Package fweb-doc
  - (Description): Extend first line (Lintian).
  - (Depends): Add ${misc:Depends}, add dpkg (>= 1.15.4) | install-info
  - (Section): Add doc.
* debian/copyright
  - Remove obsolete FSF address. Correct GPL path.
* debian/idxmerge.1
  - Fix hyphen-used-as-minus-sign (Lintian).
* debian/patches
  - New. Convert embedded changes to upstream code into individual patches.
* debian/rules
  - Replace obsolete dh_clean with dh_prep
  - (build-arch, build-indep): New (W: Lintian).
  - (clean): Adjust make call Web/Makefile (Lintian).
    Delete generated files: Web/fweave.mds Web/fweave.ndx
  - (docdir): Install docs to $package-doc.
  - (infodir): New variable.
  - (install): Don't create directory doc-base (lintian).
    Don't create empty info dir (Lintian).
  - (tmpdir): Install to $package, not tmp dir thus no longer needing
    dh_movefiles.
* debian/source/format
  - New file.
* fweb-doc.doc-base
  - (Section): Update from Apps/Programming to Programming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
@z --- style.web ---
 
2
 
 
3
FWEB version 1.62 (September 25, 1998)
 
4
 
 
5
Based on version 0.5 of S. Levy's CWEB [copyright (C) 1987 Princeton University]
 
6
 
 
7
@x-----------------------------------------------------------------------------
 
8
 
 
9
 
 
10
\Title{STYLE.WEB} % Reading the style file for FWEAVE and FTANGLE.
 
11
 
 
12
@c
 
13
@* INTRODUCTION.
 
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}''.
 
19
 
 
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.
 
24
 
 
25
Associations between vocabulary words and internal \FWEB\ fields are made
 
26
in \.{map.web}.
 
27
 
 
28
\It{We should discuss the detailed scheme here.}
 
29
 
 
30
@m _STYLE_
 
31
@d _STYLE_h
 
32
 
 
33
@A 
 
34
@<Include files@>@;
 
35
@<Typedef declarations@>@;
 
36
@<Global variables@>@;
 
37
 
 
38
@I typedefs.hweb
 
39
 
 
40
@
 
41
@<Include...@>=
 
42
#include "map.h"
 
43
 
 
44
 
45
 
 
46
@d CMNT_CHAR '%' // The comment character in the style file.
 
47
 
 
48
@I mem.hweb
 
49
 
 
50
@ We need a few miscellaneous declarations.
 
51
@<Glob...@>=
 
52
 
 
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.
 
55
 
 
56
boolean from_sprm;
 
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
 
61
                                translation. */
 
62
extern ASCII xord[];
 
63
extern outer_char xchr[];
 
64
 
 
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.
 
73
 
 
74
@d isodigit(c) (isdigit(c) && (c)!='8' && (c)!='9')
 
75
        // An |outer_char| octal digit?
 
76
 
 
77
@a
 
78
outer_char @\
 
79
esc_char FCN((ppc))
 
80
        CONST outer_char HUGE * HUGE *ppc C1("")@;
 
81
{
 
82
int k;
 
83
unsigned n;
 
84
CONST outer_char HUGE *pc = *ppc; // Pointer to first character after~'\.\\'.
 
85
 
 
86
if(isodigit(*pc))
 
87
        @<Process octal constant@>@;
 
88
else if(*pc == 'x' && isxdigit(*(pc+1)))
 
89
        @<Process hex constant@>@;
 
90
else 
 
91
        { /* Handle ordinary escaped character. */
 
92
        switch(*pc)
 
93
                {
 
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;
 
102
           default: 
 
103
                n = (unsigned)(*pc); // Unknowns, like '\.{\\m}' $\to$~'\.m'.
 
104
                break;
 
105
                }
 
106
        pc++;
 
107
        }
 
108
 
 
109
*ppc = pc;
 
110
return (outer_char)n;
 
111
}
 
112
 
 
113
@ Octal constants have the form \.{\\123}.
 
114
@<Process octal constant@>=
 
115
{
 
116
n = ctoi(*pc++);
 
117
for(k=0; k<2; k++)
 
118
        {
 
119
        if(!isodigit(*pc)) 
 
120
                break;
 
121
 
 
122
        n = 8*n + ctoi(*pc++);
 
123
        }
 
124
}
 
125
 
 
126
@ Hex constants have the form \.{\\xFF}.
 
127
@<Process hex constant@>=
 
128
{
 
129
pc++; // Position after \.{'x'}.
 
130
n = ctoi(*pc++);
 
131
 
 
132
if(isxdigit(*pc)) 
 
133
        n = 16*n + ctoi(*pc++);
 
134
}
 
135
 
 
136
@ The corresponding function for |ASCII|.
 
137
 
 
138
@a
 
139
ASCII @\
 
140
esc_achar FCN((ppc))
 
141
        CONST ASCII HUGE * HUGE *ppc C1("")@;
 
142
{
 
143
int k;
 
144
unsigned n;
 
145
CONST ASCII HUGE *pc = *ppc; // Pointer to first character after~'\.\\'.
 
146
 
 
147
if(isOdigit(*pc))
 
148
        @<Process Octal constant@>@;
 
149
else if(*pc == @'x' && isXdigit(*(pc+1)))
 
150
        @<Process Hex constant@>@;
 
151
else 
 
152
        {
 
153
        switch(*pc)
 
154
                {
 
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'.
 
164
                }
 
165
 
 
166
#if(DEBUG_XCHR)
 
167
        n = XCHR(n);
 
168
#endif
 
169
        pc++;
 
170
        }
 
171
 
 
172
*ppc = pc; // Advance the pointer to point beyond the end of the constant.
 
173
 
 
174
#if(DEBUG_XCHR)
 
175
        n = xord[n];
 
176
#endif
 
177
 
 
178
return (ASCII)n; // Return the value.
 
179
}
 
180
 
 
181
@ Octal constants have the form \.{\\123}.  The following is for |ASCII|.
 
182
@<Process Octal constant@>=
 
183
{
 
184
n = Ctoi(*pc++);
 
185
for(k=0; k<2; k++)
 
186
        {
 
187
        if(!isOdigit(*pc)) break;
 
188
        n = 8*n + Ctoi(*pc++);
 
189
        }
 
190
}
 
191
 
 
192
@ Hex constants have the form \.{\\xFF}.  The following is for |ASCII|.
 
193
@<Process Hex constant@>=
 
194
{
 
195
pc++; // Position after \.{'x'}.
 
196
n = Ctoi(*pc++);
 
197
if(isXdigit(*pc)) n = 16*n + Ctoi(*pc++);
 
198
}
 
199
 
 
200
@ Translate a hex |outer_char| into integer.
 
201
 
 
202
@m XC(cin,cout) case cin: return 0x##cout@;
 
203
 
 
204
@d Ctoi(c) ctoi(XCHR(c)) // For |ASCII|.
 
205
 
 
206
@a
 
207
int @\
 
208
ctoi FCN((c))
 
209
        outer_char c C1("")@;
 
210
{
 
211
switch(c)
 
212
        {
 
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);
 
221
   default: return 0;
 
222
        }
 
223
}
 
224
 
 
225
@ Search for a keyword.  Returns address of the relevant |S_MAP| entry.
 
226
@a
 
227
S_MAP @\
 
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")@;
 
231
{
 
232
for(; *(m->keyword); m++)
 
233
        if(STRCMP(keyword,m->keyword) == 0) return m;
 
234
 
 
235
return NULL;
 
236
}
 
237
 
 
238
@ Read one line from style file. 
 
239
@a
 
240
boolean @\
 
241
sty_line(VOID)
 
242
{
 
243
typedef enum {FROM_INI, FROM_LOCAL, FROM_CMD_LINE} STYLE_MODE;
 
244
 
 
245
static STYLE_MODE mode = FROM_INI;
 
246
 
 
247
from_sprm = BOOLEAN(mode == FROM_INI || mode == FROM_CMD_LINE);
 
248
 
 
249
switch(mode)
 
250
        {
 
251
   case FROM_INI:
 
252
        if(!sty0_line(sprm_ptr0))
 
253
                mode++;
 
254
        else
 
255
                return YES;
 
256
 
 
257
   case FROM_LOCAL:
 
258
        if(!sty0_line(NULL))
 
259
                mode++;
 
260
        else
 
261
                return YES;
 
262
 
 
263
   case FROM_CMD_LINE:
 
264
        return sty0_line(sprm_end);
 
265
        }
 
266
 
 
267
return YES; // Dummy.
 
268
}
 
269
 
 
270
boolean @\
 
271
sty0_line FCN((last_sprm))
 
272
        outer_char HUGE *last_sprm C1("")@;
 
273
{
 
274
int c; /* Single character read from style file. |int| rather than |char|
 
275
                because that's what |getc| returns. */
 
276
 
 
277
sloc = slimit = sbuf; // Position to beginning of line.
 
278
 
 
279
if(last_sprm)
 
280
        { /* Read from the \.{-p} buffer. */
 
281
        if(sprm_ptr >= last_sprm) 
 
282
                { /* Nothing more in the \.{-p} buffer. */
 
283
                s_line = 0;
 
284
                return NO;
 
285
                }
 
286
        else
 
287
                { /* Copy line from \.{-p} buffer. */
 
288
                int n;
 
289
                outer_char HUGE *p;
 
290
 
 
291
                if((p=(outer_char HUGE *)STRCHR(sprm_ptr,'\n')) == NULL)
 
292
                        {
 
293
                        err_print(S,"Trouble in sty_line");
 
294
                        return NO;
 
295
                        }
 
296
                else n = PTR_DIFF(int, p, sprm_ptr);
 
297
        
 
298
                STRNCPY(sloc,sprm_ptr,n);
 
299
                sprm_ptr += n + 1;
 
300
                slimit += n;
 
301
                s_line++;
 
302
                }
 
303
        }
 
304
else
 
305
        { /* Read from the local style file. */
 
306
        if(!sty_file) 
 
307
                @<Attempt to open style file@>@;
 
308
 
 
309
        @<Move characters from style file; |return NO| if end-of-file@>@;
 
310
        }
 
311
 
 
312
return YES;
 
313
}
 
314
 
 
315
@
 
316
@<Attempt to open...@>=
 
317
{
 
318
outer_char full_sty_name[MAX_FILE_NAME_LENGTH];
 
319
 
 
320
/* If there's no style file, do nothing. */
 
321
if(!*sty_file_name) 
 
322
        return NO;
 
323
 
 
324
if(warn_if_absent) 
 
325
        {
 
326
        STRCPY(full_sty_name, sty_file_name);
 
327
        add_prefix(full_sty_name);
 
328
        }
 
329
else 
 
330
        mk_fname(full_sty_name, MAX_FILE_NAME_LENGTH,
 
331
                                OC(ENV_FWEB_STY), NO,sty_file_name);
 
332
 
 
333
if((sty_file = fopen((char *)full_sty_name,"r")) == NULL)
 
334
        {
 
335
        if(warn_if_absent) 
 
336
                {
 
337
                err_print(C,"Can't open style file %s",
 
338
                        full_sty_name);
 
339
                }
 
340
        return NO;
 
341
        }
 
342
 
 
343
reading(full_sty_name,YES);
 
344
}
 
345
 
 
346
@
 
347
@<Move characters from style...@>=
 
348
{
 
349
if(feof(sty_file)) 
 
350
        return NO;
 
351
 
 
352
s_line++;
 
353
 
 
354
while((c = getc(sty_file)) != EOF && c != '\n')
 
355
        {
 
356
        if(slimit == sbuf_end)
 
357
                {
 
358
                err_print(S,"Input line too long; max is %lu characters",
 
359
                        sbuf_len);
 
360
                ungetc(c,sty_file);
 
361
                break;
 
362
                }
 
363
 
 
364
        *slimit++ = (outer_char)c; // Put character into buffer.
 
365
        }
 
366
}
 
367
 
 
368
@ Extract the next argument from the style file.  Keywords begin with an
 
369
alphabetic character or an underscore.
 
370
@a
 
371
STY_TYPE @\
 
372
next_sty(VOID)
 
373
{
 
374
outer_char c; /* Single character from the buffer. */
 
375
 
 
376
WHILE()
 
377
        {
 
378
/* If we get to the end of the line or recognize a comment, read the next
 
379
line. */
 
380
        if(sloc == slimit || (c= *sloc++) == CMNT_CHAR) 
 
381
                {
 
382
                if(!sty_line()) 
 
383
                        return S_DONE; // Get more.
 
384
 
 
385
                continue;
 
386
                }
 
387
 
 
388
        if(isalpha(c) || c=='_') 
 
389
                @<Style keyword@>@;
 
390
        else if(isdigit(c) || c=='-' || c=='+') 
 
391
                @<Style number@>@;
 
392
        else if(c == '"') 
 
393
                @<Style string@>@;
 
394
        else if(c == '\'') 
 
395
                @<Style character@>@;
 
396
        else if(c==' ' || c=='\t' || c=='=') 
 
397
                continue;
 
398
        else 
 
399
                {
 
400
                err_print(S,"Invalid style-file field; \
 
401
skipping remainder of file");
 
402
                longjmp(top_of_style,1);
 
403
                }
 
404
        }
 
405
 
 
406
DUMMY_RETURN(S_DONE);
 
407
}
 
408
 
 
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}''.
 
413
 
 
414
@m S_RETURN(t) *tloc = '\0'; return S_##t@; /* Terminate |stemp|, and
 
415
                                        return the appropriate type. */
 
416
 
 
417
@<Style keyword@>=
 
418
{
 
419
sloc--;
 
420
tloc = stemp;
 
421
 
 
422
while(sloc < slimit 
 
423
           && (isalpha(*sloc) || isdigit(*sloc) || *sloc=='_' || *sloc=='.'))
 
424
        {
 
425
        cur_char = *sloc++;
 
426
        @<Copy and translate style character@>@; 
 
427
        }
 
428
 
 
429
S_RETURN(KEYWORD);
 
430
}
 
431
 
 
432
@ Move one character into |stemp|.
 
433
@<Copy and translate style char...@>=
 
434
{
 
435
if(tloc < stemp_end) 
 
436
        *tloc++ = (outer_char)CHOICE(cur_char=='.', '_', cur_char);
 
437
else
 
438
        {
 
439
        err_print(S, "Style-file buffer overflow.  \
 
440
Try using `-ysb' to increase the size");
 
441
        break;
 
442
        }
 
443
}
 
444
 
 
445
@
 
446
@<Copy style character@>=
 
447
{
 
448
if(tloc < stemp_end) 
 
449
        *tloc++ = cur_char;
 
450
else
 
451
        {
 
452
        err_print(S, "Style-file buffer overflow.  \
 
453
Try using `-ysb' to increase the size");
 
454
        break;
 
455
        }
 
456
}
 
457
 
 
458
@ Process a string argument (bracketed by double quotes).  We must allow
 
459
for escapes, such as ``\.{\\123}''.
 
460
@<Style string@>=
 
461
{
 
462
tloc = stemp; /* Start of buffer. */
 
463
 
 
464
while(*sloc != '"')
 
465
        {
 
466
        if(sloc == slimit)
 
467
                {
 
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 '\\'.)");
 
471
                S_RETURN(STRING);
 
472
                }
 
473
 
 
474
        if(*sloc == '\\')
 
475
                {
 
476
                if(++sloc == slimit)
 
477
                        {
 
478
                        sty_line(); // String is continued.
 
479
                        continue;
 
480
                        }
 
481
                else 
 
482
                        cur_char = esc_char(&sloc);
 
483
                }
 
484
        else 
 
485
                cur_char = *sloc++;
 
486
 
 
487
        @<Copy sty...@>@;
 
488
        }
 
489
 
 
490
sloc++; // Skip over terminating quote.
 
491
 
 
492
S_RETURN(STRING);
 
493
}
 
494
 
 
495
@ Process a numerical argument.
 
496
@<Style number@>=
 
497
{
 
498
sloc--;
 
499
tloc = stemp;
 
500
 
 
501
if(*sloc=='+' || *sloc=='-') 
 
502
        {
 
503
        cur_char = *sloc++; 
 
504
        @<Copy sty...@>@;
 
505
        }
 
506
 
 
507
while(sloc < slimit && isdigit(*sloc)) 
 
508
        {
 
509
        cur_char = *sloc++; 
 
510
        @<Copy sty...@>@;
 
511
        }
 
512
 
 
513
if(sloc == slimit)
 
514
        S_RETURN(INT);
 
515
 
 
516
/* We allow the possibility of long integers. */
 
517
if(*sloc == 'l' || *sloc == 'L')
 
518
        {
 
519
        sloc++; // Skip over '\.L'.
 
520
        S_RETURN(LONG);
 
521
        }
 
522
 
 
523
S_RETURN(INT);
 
524
}
 
525
 
 
526
@ Process a character argument such as~'\.c' or~'\.{\\n}'.
 
527
@<Style character@>=
 
528
{
 
529
tloc = stemp;
 
530
 
 
531
/* If the character is escaped, turn the next character into the actual
 
532
byte. */
 
533
if(*sloc == '\\') 
 
534
        {
 
535
        sloc++; 
 
536
        cur_char = esc_char(&sloc);
 
537
        }
 
538
else 
 
539
        cur_char = *sloc++;
 
540
 
 
541
@<Copy sty...@>@;
 
542
 
 
543
if(*sloc != '\'')
 
544
        err_print(S, "Missing single quote inserted");
 
545
else
 
546
        sloc++; // Skip over closing quote.
 
547
 
 
548
S_RETURN(CHAR);
 
549
}
 
550
 
 
551
@* READING the STYLE FILE.
 
552
The style file is both opened and closed in this module.
 
553
 
 
554
@f jmp_buf int
 
555
 
 
556
@<Glob...@>=
 
557
 
 
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|.
 
564
 
 
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}.
 
567
 
 
568
@d ENV_FWEB_STY "FWEB_STYLE_DIR" /* Environment variable that defines
 
569
                directory of style file.  */
 
570
 
 
571
@a
 
572
SRTN @\
 
573
read_sty FCN((sty_file_name0,warn_if_absent0))
 
574
        CONST outer_char sty_file_name0[] C0("")@;
 
575
        boolean warn_if_absent0 C1("")@;
 
576
{
 
577
sty_file_name = sty_file_name0;
 
578
warn_if_absent = warn_if_absent0;
 
579
 
 
580
@<Modify defaults based on option settings@>@;
 
581
 
 
582
@<Allocate buffers for the style file@>@;
 
583
 
 
584
if(setjmp(top_of_style) != 0) 
 
585
        goto done_sty;
 
586
 
 
587
/* Read the first line of style file. If the file's empty, do nothing. */
 
588
if(!sty_line()) 
 
589
        goto done_sty;
 
590
 
 
591
/* Parse the file. */
 
592
WHILE()
 
593
        switch(next_sty())
 
594
                {
 
595
                case S_CMNT: break;
 
596
 
 
597
                case S_KEYWORD:
 
598
                        @<Process style keyword@>@;
 
599
                        break;
 
600
 
 
601
                default:
 
602
                        err_print(S,"Was expecting keyword or comment here; \
 
603
skipping remainder of file"); // Falls through to |case S_DONE@:|.
 
604
 
 
605
                case S_DONE:
 
606
                 done_sty:
 
607
                        if(sty_file) 
 
608
                                fclose(sty_file);
 
609
 
 
610
                        if(sprm_buf) 
 
611
                                FREE_MEM(sprm_buf, "sprm_buf",
 
612
                                        SPRM_LEN, outer_char);
 
613
 
 
614
                        FREE_MEM(stemp,"stemp",sbuf_len,outer_char);
 
615
                        FREE_MEM(sbuf,ABBREV(sbuf_len),sbuf_len,outer_char);
 
616
                        return;
 
617
                }
 
618
}
 
619
 
 
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...@>=
 
623
{
 
624
IN_COMMON outer_char HUGE *style_args;
 
625
 
 
626
if(TeX_processor == LaTeX_p)
 
627
        {
 
628
        W_META HUGE *m = &w_style.misc.meta;
 
629
        INDEX HUGE *i = &w_style.indx;
 
630
 
 
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");
 
634
 
 
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 ");
 
639
 
 
640
        i->encap_prefix = OC("\\M");
 
641
        i->encap_infix = OC("{");
 
642
        i->encap_suffix = OC("}");
 
643
        }
 
644
 
 
645
if(prn_style_defaults) 
 
646
        see_style(style_args, YES);
 
647
}
 
648
 
 
649
@ We temporarily allocate buffers for working with the style file.
 
650
@<Allocate buffers...@>=
 
651
{
 
652
ALLOC(outer_char,sbuf,ABBREV(sbuf_len),sbuf_len,0);
 
653
sbuf_end = sbuf + sbuf_len;
 
654
 
 
655
stemp = GET_MEM("stemp",sbuf_len,outer_char);
 
656
stemp_end = stemp + sbuf_len;
 
657
 
 
658
/* Reset the \.{-p} buffer. */
 
659
sprm_end = sprm_ptr; // Actual end of material in buffer.
 
660
sprm_ptr = sprm_buf; // Start at beginning.
 
661
}
 
662
 
 
663
@ At the very beginning, initializations must be finished.
 
664
@a
 
665
SRTN 
 
666
ini_style(VOID)
 
667
{
 
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.
 
670
 
 
671
@<Finish initializing mappings@>@;
 
672
}
 
673
 
 
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.
 
680
 
 
681
@a
 
682
 
 
683
outer_char *
 
684
get_option FCN((s))
 
685
        outer_char *s C1("")@;
 
686
{
 
687
int k, len;
 
688
 
 
689
len = STRLEN(s);
 
690
 
 
691
for(k=1; k<argc; k++)
 
692
        if(STRNCMP(s, argv[k], len) == 0)
 
693
                return argv[k];
 
694
 
 
695
return OC("");
 
696
}
 
697
 
 
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
 
702
something else.
 
703
@<Process style key...@>=
 
704
{
 
705
S_MAP HUGE *ps; // Returned from |find_sty|.
 
706
STY_TYPE type;
 
707
 
 
708
/* Is it a valid keyword? */
 
709
if((ps = find_sty(map_array,stemp)) == NULL)
 
710
        {
 
711
        err_print(S,"Invalid style-file keyword; skipping remainder of line");
 
712
        sty_line();
 
713
        break;
 
714
        }
 
715
 
 
716
/* Get the next argument. Is its type correct? */
 
717
type = ps->type & ~S_MODIFIED;
 
718
 
 
719
if(type != next_sty())
 
720
        {
 
721
        err_print(S,"Argument of keyword \"%s\" has wrong type; \
 
722
conversion to %s attempted", ps->keyword, s_type_name[type]);
 
723
        }
 
724
 
 
725
switch(type)
 
726
        {
 
727
        case S_INT:
 
728
        case S_LONG:
 
729
        case S_STRING:
 
730
        case S_CHAR:
 
731
        break;
 
732
 
 
733
        default:
 
734
                err_print(S,"Was expecting %s here; argument not processed",
 
735
                        s_type_name[type]);
 
736
                goto processed;
 
737
        }
 
738
 
 
739
/* Store the argument, check for validity, or process the result in some
 
740
way. */
 
741
if(ps->init) 
 
742
        (*ps->init)(ps); 
 
743
else 
 
744
        CONFUSION("style keyword","NULL ini fcn");
 
745
 
 
746
/* Flag it as modified. */
 
747
ps->type |= S_MODIFIED;
 
748
 
 
749
processed:;
 
750
}
 
751
 
 
752
        
 
753
@ Initialize a string.  (No error checking.)
 
754
@a
 
755
SRTN @\
 
756
set_str FCN((ps))
 
757
        S_MAP HUGE *ps C1("")@;
 
758
{
 
759
a_str(ps->ptr, (CONST outer_char HUGE *)stemp);
 
760
}
 
761
 
 
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
 
764
as usual.
 
765
 
 
766
@a
 
767
SRTN @\
 
768
add_str FCN((ps))
 
769
        S_MAP HUGE *ps C1("")@;
 
770
{
 
771
outer_char HUGE *pa = *(outer_char HUGE **)ps->ptr, HUGE *pb;
 
772
 
 
773
if(*pa && (ps->type & S_MODIFIED))
 
774
        {
 
775
        pb = GET_MEM("add_str", STRLEN(pa) + STRLEN(stemp) + 2, outer_char);
 
776
        STRCPY(pb, pa);
 
777
        STRCAT(pb, "\n");
 
778
        STRCAT(pb, stemp);
 
779
        *(outer_char HUGE **)ps->ptr = pb;
 
780
        }
 
781
else 
 
782
        set_str(ps);
 
783
}
 
784
 
 
785
@ Initialize an integer.  (No error checking.)
 
786
@a
 
787
SRTN @\
 
788
set_int FCN((ps))
 
789
        S_MAP HUGE *ps C1("")@;
 
790
{
 
791
*((int *)ps->ptr) = ATOI(stemp);
 
792
}
 
793
 
 
794
@ Similarly, initialize a long.  (No error checking.)
 
795
@a
 
796
SRTN @\
 
797
set_long FCN((ps))
 
798
        S_MAP HUGE *ps C1("")@;
 
799
{
 
800
*((long *)ps->ptr) = ATOL(stemp);
 
801
}
 
802
 
 
803
@ Initialize a character (no error checking).
 
804
@a
 
805
SRTN @\
 
806
set_char FCN((ps))
 
807
        S_MAP HUGE *ps C1("")@;
 
808
{
 
809
*((outer_char *)ps->ptr) = *stemp;
 
810
}
 
811
 
 
812
@
 
813
@<Typedef...@>=
 
814
 
 
815
typedef struct
 
816
        {
 
817
        CONST char *name;
 
818
        COLOR value;
 
819
        } CLR_MATCH;
 
820
 
 
821
CLR_MATCH clr_match[] = {
 
822
        {"black", BLACK},
 
823
        {"blue", BLUE}, 
 
824
        {"cyan", CYAN},
 
825
        {"default", NORMAL}, 
 
826
        {"green", GREEN}, 
 
827
        {"magenta", MAGENTA},
 
828
        {"normal", NORMAL}, 
 
829
        {"red", RED}, 
 
830
        {"yellow", YELLOW}, 
 
831
        {"", NORMAL}
 
832
        };
 
833
 
 
834
@* VALIDITY CHECKS. 
 
835
We begin with an initialization routine for color.  It replaces strings like
 
836
\.{"red"} by enumerated values like~|RED|.
 
837
@a
 
838
SRTN @\
 
839
ini_aclr FCN((ps))
 
840
        S_MAP HUGE *ps C1("")@;
 
841
{
 
842
CLR_MATCH HUGE *c;
 
843
 
 
844
set_str(ps);
 
845
 
 
846
for(c=clr_match; STRCMP(c->name,"") != 0; c++)
 
847
        if(STRCMP(c->name, *(outer_char HUGE **)ps->ptr) == 0)
 
848
                {
 
849
                *(COLOR *)ps->ptr = c->value;
 
850
                return;
 
851
                }
 
852
 
 
853
CLR_PRINTF(WARNINGS, warning, ("! Color name \"%s\" is invalid; \
 
854
replaced by \"default\"\n",(char *)ps->ptr));
 
855
mark_harmless;
 
856
 
 
857
*(COLOR *)ps->ptr = NORMAL;
 
858
}
 
859
 
 
860
@ Initialization routine for \.{color.mode} (no longer used).
 
861
@a
 
862
SRTN @\
 
863
ini_clr FCN((ps))
 
864
        S_MAP HUGE *ps C1("")@;
 
865
{
 
866
set_int(ps);
 
867
ini_colors((COLOR_MODE)(*(int *)ps->ptr));
 
868
}
 
869
 
 
870
@ Initialization routines for file name extension are create via a \WEB\
 
871
macro. 
 
872
 
 
873
@m EXT_LINK(file,dflt) link0(&wt_style.input_ext.file,OC(dflt),ext_set)
 
874
 
 
875
@m INI_EXT(file) 
 
876
        SRTN ini_##file FCN((ps))
 
877
                CONST S_MAP HUGE *ps C1("")@;
 
878
        {
 
879
        EXT_LINK(file,(outer_char *)ps->ptr);
 
880
        }
 
881
 
 
882
@<Unused@>=
 
883
/* Actual functions are being created here. */
 
884
INI_EXT(web)@;
 
885
INI_EXT(change)@;
 
886
INI_EXT(hweb)@;
 
887
INI_EXT(hchange)@;
 
888
 
 
889
@
 
890
@a
 
891
SRTN @\
 
892
ini_ext FCN((ps))
 
893
        S_MAP HUGE *ps C1("")@;
 
894
{
 
895
set_str(ps);
 
896
ext_set((CONST outer_char HUGE **)ps->ptr);
 
897
}
 
898
 
 
899
@ Convert the delimiters for dot constants to |ASCII|.
 
900
@a
 
901
SRTN @\
 
902
ini_dot FCN((ps))
 
903
        S_MAP HUGE *ps C1("")@;
 
904
{
 
905
set_char(ps);
 
906
*(ASCII *)ps->ptr = XORD(*(outer_char *)ps->ptr);
 
907
}
 
908
 
 
909
@
 
910
@a
 
911
SRTN @\
 
912
ini_cchar FCN((ps))
 
913
        S_MAP HUGE *ps C1("")@;
 
914
{
 
915
outer_char c;
 
916
 
 
917
set_char(ps);
 
918
c = *(outer_char *)ps->ptr;
 
919
 
 
920
if(!(c && isprint(c) && c != ' ' && c != '0'))
 
921
        {
 
922
        *(outer_char *)ps->ptr = CCHAR;
 
923
        err_print(S,"Invalid continuation character '%c'; '%c' assumed",
 
924
                c,CCHAR);
 
925
        }
 
926
}
 
927
 
 
928
@ Here we check the validity of the line length for Fortran's output.
 
929
 
 
930
@a
 
931
SRTN @\
 
932
ini_output_line_length FCN((ps))
 
933
        S_MAP HUGE *ps C1("")@;
 
934
{
 
935
int output_line_length;
 
936
 
 
937
set_int(ps);
 
938
output_line_length = *(int *)ps->ptr;
 
939
 
 
940
if(output_line_length < MIN_OUTPUT_LINE_LENGTH ||
 
941
                output_line_length > MAX_OUTPUT_LINE_LENGTH)
 
942
        {
 
943
        *(int *)ps->ptr = STANDARD_OUTPUT_LINE_LENGTH;
 
944
        err_print(S,"Line length %d is invalid; %d assumed",
 
945
                output_line_length,
 
946
                STANDARD_OUTPUT_LINE_LENGTH + FORTRAN90_LIKE(language));
 
947
        }
 
948
}
 
949
 
 
950
 
951
@<Unused@>=
 
952
SRTN @\
 
953
ini_cdir FCN((ps))
 
954
        CONST S_MAP HUGE *ps C1("")@;
 
955
{
 
956
outer_char *temp;
 
957
int n;
 
958
 
 
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);
 
962
}
 
963
 
 
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.
 
967
 
 
968
@d ignore 0
 
969
 
 
970
@<Glob...@>=
 
971
 
 
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;
 
975
 
 
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.
 
980
 
 
981
@a
 
982
SRTN @\
 
983
zero_ccodes(VOID)
 
984
@B
 
985
int c; // Must be |int|, not |eight_bits|, so the |for| loop will end.
 
986
 
 
987
@b
 
988
/* Start out by initializing the array to a special flag. */
 
989
 for (c=0; c<=127; c++) 
 
990
        {
 
991
        ccode[c] = USED_BY_NEITHER;
 
992
        cname[c] = OC("?");
 
993
        }
 
994
 
 
995
@<Initialize unchangable codes@>@;
 
996
}
 
997
 
 
998
@ The following several codes aren't allowed to be changed.
 
999
@<Initialize unchangable...@>=
 
1000
{
 
1001
ccode[@'@@']=@'@@'; /* `quoted' at sign. This is so fundamental that it
 
1002
                        isn't allowed to be changed by the style file. */
 
1003
 
 
1004
ccode[@'{'] = @'{'; /* Since this is related to the C or \Ratfor\ languages,
 
1005
                        it shouldn't be changed. */
 
1006
ccode[@'}'] = @'}'; // As above.
 
1007
 
 
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|. */
 
1013
}
 
1014
 
 
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.
 
1021
@a
 
1022
SRTN @\
 
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")@;
 
1027
{
 
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;
 
1031
eight_bits cval;
 
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|.
 
1035
 
 
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.
 
1039
else
 
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.
 
1045
 
 
1046
pc = (override && code) ? *(outer_char **)m->ptr : defaults;
 
1047
 
 
1048
/* If we're not ignoring this code completely, assign it to the relevant
 
1049
values. */
 
1050
if(code != USED_BY_NEITHER)
 
1051
   while(*pc)
 
1052
        {
 
1053
        if(override && ((cval = ccode[XORD(*pc)]) != USED_BY_NEITHER) )
 
1054
                {
 
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));
 
1059
                bad_code = YES;
 
1060
                }
 
1061
 
 
1062
        a = XORD(*pc++);
 
1063
        ccode[a] = code;
 
1064
        cname[a] = keyword;
 
1065
        }
 
1066
 
 
1067
if(bad_code) 
 
1068
        FATAL(S, 
 
1069
                "Invalid control code mapping; ",
 
1070
                "check the style file %s.",
 
1071
                style_file_name);
 
1072
}
 
1073
 
 
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|.
 
1077
@a
 
1078
SRTN @\
 
1079
reassign FCN((old_code,new_code))
 
1080
        eight_bits old_code C0("")@;
 
1081
        eight_bits new_code C1("")@;
 
1082
{
 
1083
int c;
 
1084
 
 
1085
for(c=0; c<128; c++)
 
1086
        if(ccode[c] == old_code) 
 
1087
                ccode[c] = new_code;
 
1088
}
 
1089
 
 
1090
@ The following array is used for sorting the control-code keywords.
 
1091
@<Glob...@>=
 
1092
 
 
1093
static CC_BUF HUGE *cc_buf;
 
1094
 
 
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.
 
1098
 
 
1099
@a
 
1100
SRTN @\
 
1101
prn_codes(VOID)
 
1102
{
 
1103
IN_COMMON boolean found_web;
 
1104
int HUGE *cc_indices;
 
1105
boolean prn_all = NO;
 
1106
 
 
1107
int k;
 
1108
int n = 0; // Number of codes to print.
 
1109
 
 
1110
if(!at_codes) 
 
1111
        return;
 
1112
 
 
1113
puts("Control-code assignments \
 
1114
([S,D,C]==`Begins [Section,Definition,Code])':");
 
1115
 
 
1116
cc_buf = GET_MEM("cc_buf", 128, CC_BUF);
 
1117
cc_indices = GET_MEM("cc_indices", 128, int);
 
1118
 
 
1119
if(*at_codes && at_codes[0] == @'*' && at_codes[1] == @'*')
 
1120
        prn_all = YES;
 
1121
 
 
1122
if(*at_codes && !prn_all)
 
1123
        { /* A specific list was given on command line. */
 
1124
        CONST ASCII *p;
 
1125
 
 
1126
        for(p=at_codes; *p; p++)
 
1127
                prn0_code(*p, cc_buf, &n);
 
1128
        }
 
1129
else
 
1130
        { /* Do all of them. */
 
1131
        ASCII a;
 
1132
 
 
1133
        for(a=0; a<128; a++)
 
1134
                {
 
1135
                if(ccode[a] == USED_BY_NEITHER && !prn_all)
 
1136
                        continue;
 
1137
 
 
1138
                prn0_code(a, cc_buf, &n);
 
1139
                }
 
1140
        }
 
1141
 
 
1142
FREE_MEM(at_codes, "at_codes", 200, ASCII);
 
1143
 
 
1144
for(k=0; k<n; k++)
 
1145
        cc_indices[k] = k;
 
1146
 
 
1147
QSORT(cc_indices, n, sizeof(int), cc_cmp);
 
1148
 
 
1149
for(k=0; k<n; k++)
 
1150
        STRCPY(cc_buf[k][1], cc_buf[cc_indices[k]][0]);
 
1151
 
 
1152
for(k=0; k<n; k++)
 
1153
        printf("%-40s%-40s\n", cc_buf[k][0], cc_buf[k][1]);
 
1154
 
 
1155
FREE_MEM(cc_buf, "cc_buf", 128, CC_BUF);
 
1156
FREE_MEM(cc_indices, "cc_indices", 128, int);
 
1157
 
 
1158
if(!found_web) 
 
1159
        wrap_up();
 
1160
}
 
1161
 
 
1162
@ We alphabetize on the keywords, which follow the `\.{---}'.
 
1163
 
 
1164
@a
 
1165
int @\
 
1166
cc_cmp FCN((k0, k1))
 
1167
        CONST VOID *pk0 C0("")@;
 
1168
        CONST VOID *pk1 C1("")@;
 
1169
{
 
1170
char *s0, *s1;
 
1171
 
 
1172
s0 = strrchr(cc_buf[*(int *)pk0][0], '-');
 
1173
s1 = strrchr(cc_buf[*(int *)pk1][0], '-');
 
1174
 
 
1175
return STRCMP(s0, s1);
 
1176
}
 
1177
 
 
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
 
1180
running.
 
1181
 
 
1182
@m $XLEN(s) $LEN(s)
 
1183
@m USED_BY_MSG "Used by ftangle"
 
1184
 
 
1185
@<Glob...@>=
 
1186
 
 
1187
outer_char used_by_buf[$XLEN(USED_BY_MSG)+1];
 
1188
 
 
1189
@ Print out one control code.
 
1190
@a
 
1191
SRTN @\
 
1192
prn0_code FCN((a, cc_buf, pk))
 
1193
        ASCII a C0("")@;
 
1194
        CC_BUF HUGE *cc_buf C0("")@;
 
1195
        int *pk C1("")@;
 
1196
{       
 
1197
ASCII new_module, begin_code, formatt;
 
1198
ASCII cc = ccode[a];
 
1199
outer_char c;
 
1200
int n;
 
1201
outer_char *letter;
 
1202
 
 
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'];
 
1208
 
 
1209
c = XCHR(a);
 
1210
 
 
1211
if(cc == USED_BY_NEITHER)
 
1212
        letter = OC("   ");
 
1213
else if(cc >= new_module)
 
1214
        letter = OC("[S]");
 
1215
else if(cc >= begin_code)
 
1216
        letter = OC("[C]");
 
1217
else if(cc >= formatt)
 
1218
        letter = OC("[D]");
 
1219
else
 
1220
        letter = OC("   ");
 
1221
 
 
1222
n = NSPRINTF((outer_char *)&cc_buf[*pk][0][0], 
 
1223
isprint(c) ? "  %s @@%c" : " %s@@'\\x%02x'", 
 
1224
                isprint(c) ? letter : OC(""), c);
 
1225
 
 
1226
if(cc == USED_BY_OTHER)
 
1227
        {
 
1228
        STRCPY(used_by_buf, "Used by ");
 
1229
        STRCAT(used_by_buf, program==tangle ? WEAVE : TANGLE);
 
1230
        cname[c] = used_by_buf;
 
1231
        }
 
1232
else if(cc == USED_BY_NEITHER)
 
1233
        cname[c] = OC("Unassigned");
 
1234
else switch(c)
 
1235
        {
 
1236
   case '/':
 
1237
        cname[c] = OC("(verbatim comment)");
 
1238
        break;
 
1239
 
 
1240
   case '>':
 
1241
        cname[c] = OC("(end of module name)");
 
1242
        break;
 
1243
 
 
1244
   case '@@':
 
1245
        cname[c] = OC("(literal '@@')");
 
1246
        break;
 
1247
        }
 
1248
 
 
1249
sprintf(&cc_buf[*pk][0][n], " --- %s", (char *)cname[c]);
 
1250
(*pk)++; // Increment array index.
 
1251
}
 
1252
 
 
1253
@* COLOR.
 
1254
 
 
1255
@d SET_ACOLOR(field,clr) wt_style.color.field.value = clr
 
1256
 
 
1257
@<Glob...@>=
 
1258
 
 
1259
static outer_char HUGE *tcap_buffer; // Allocated dynamically.
 
1260
 
 
1261
@  Colors are initialized to default values, then overridden for several
 
1262
built-in palettes.
 
1263
@a
 
1264
COLOR_MODE @\
 
1265
ini_colors FCN((color_mode0))
 
1266
        COLOR_MODE color_mode0 C1("")@;
 
1267
{
 
1268
color_mode = color_mode0;
 
1269
 
 
1270
@<Set default colors@>@; // Attach colors to fields.
 
1271
 
 
1272
if(!(termcap=get_termcap())) 
 
1273
        color_mode = NO_COLOR;
 
1274
 
 
1275
new_color:
 
1276
switch(color_mode)
 
1277
        {
 
1278
   case NO_COLOR:
 
1279
        @<Make default links between bilevel mode and colors@>@;
 
1280
        break;
 
1281
 
 
1282
   case ANSI_COLOR:
 
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");
 
1292
        break;
 
1293
 
 
1294
   case BILEVEL:
 
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);
 
1300
        CLR_LINK(BLUE, me);
 
1301
        CLR_LINK(MAGENTA, me);
 
1302
        CLR_LINK(CYAN, me);
 
1303
        CLR_LINK(WHITE, mr);
 
1304
        break;
 
1305
 
 
1306
   case TRILEVEL:
 
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);
 
1314
        CLR_LINK(CYAN, us);
 
1315
        CLR_LINK(WHITE, mr);
 
1316
        break;
 
1317
 
 
1318
   case USER_COLORS:
 
1319
        break;
 
1320
 
 
1321
   default:
 
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.
 
1325
        beeps = BEEPS;
 
1326
        color_mode = NO_COLOR;
 
1327
        goto new_color;
 
1328
        }
 
1329
 
 
1330
return color_mode;
 
1331
}
 
1332
 
 
1333
@ Get control sequence for a color.  This is an ini routine for
 
1334
\.{color.red} etc.
 
1335
@a
 
1336
SRTN @\
 
1337
ini_bilevel FCN((ps))
 
1338
        S_MAP HUGE *ps C1("")@;
 
1339
{
 
1340
set_str(ps);
 
1341
 
 
1342
if(termcap==NULL) 
 
1343
        return;
 
1344
 
 
1345
termset(ps->ptr);
 
1346
}
 
1347
 
 
1348
@ Default color assignments to the various FWEB fields. Change these in the
 
1349
style file by saying ``\.{color.error = "red"}''.
 
1350
 
 
1351
@<Set default colors@>=
 
1352
{
 
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);
 
1367
}
 
1368
 
 
1369
@ Associate a color with a control sequence.
 
1370
`\.{me}'---turn off all appearance modes.
 
1371
`\.{md}'---double-bright mode.
 
1372
`\.{mr}'---reverse video.
 
1373
 
 
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)
 
1376
 
 
1377
@<Make default links...@>=
 
1378
{
 
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);
 
1384
CLR_LINK(BLUE, me);
 
1385
CLR_LINK(MAGENTA, me);
 
1386
CLR_LINK(CYAN, me);
 
1387
CLR_LINK(WHITE, mr);
 
1388
}
 
1389
 
 
1390
@
 
1391
@a
 
1392
SRTN @\
 
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("")@;
 
1397
{
 
1398
a_str(pp, id); // Allocate space, and store abbreviation string.
 
1399
(*fcn)((CONST outer_char HUGE **)pp); /* Replace that string by actual escape
 
1400
                                        sequences. */
 
1401
}
 
1402
 
 
1403
@ Similarly, initialize extensions.
 
1404
 
 
1405
@<Finish initializing mappings@>=
 
1406
{
 
1407
EXT_LINK(web, "web");
 
1408
EXT_LINK(change, "ch");
 
1409
EXT_LINK(hweb, "hweb");
 
1410
EXT_LINK(hchange, "hch");
 
1411
}
 
1412
 
 
1413
@ Allocate and store an abbreviation string.
 
1414
@a
 
1415
SRTN @\
 
1416
a_str FCN((pp,id))
 
1417
        outer_char HUGE **pp C0("")@;
 
1418
        CONST outer_char HUGE *id C1("")@;
 
1419
{
 
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);
 
1423
}
 
1424
 
 
1425
@ Open and read the termcap file.
 
1426
 
 
1427
@d ENV_TERM "TERM" // Unix environment variable for terminal type.
 
1428
 
 
1429
@a
 
1430
outer_char * @\
 
1431
get_termcap(VOID)
 
1432
{
 
1433
#if !HAVE_GETENV
 
1434
        return NULL;
 
1435
#else
 
1436
if((termcap = GETENV(ENV_TERM)) == NULL) 
 
1437
        return NULL;
 
1438
 
 
1439
tcap_buffer = GET_MEM("tcap_buffer", 1024, outer_char);
 
1440
 
 
1441
switch(tgetent(tcap_buffer, termcap))
 
1442
        {
 
1443
   case -1:
 
1444
        printf("! Can't open termcap file `%s'.\n", (char *)termcap);
 
1445
 
 
1446
   case 0:
 
1447
        return NULL;
 
1448
        }
 
1449
 
 
1450
return termcap;
 
1451
#endif // |HAVE_GETENV|
 
1452
}
 
1453
 
 
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.
 
1457
 
 
1458
@d NUM_TEMP_PTRS 20
 
1459
 
 
1460
@a
 
1461
SRTN @\
 
1462
termset FCN((pid))
 
1463
        CONST outer_char HUGE **pid C1("")@;
 
1464
{
 
1465
outer_char value_buf[500], *area = value_buf; // For |tgetstr|.
 
1466
 
 
1467
outer_char *s;
 
1468
CONST outer_char HUGE *t;
 
1469
outer_char id[3];
 
1470
int k, n, len;
 
1471
SEQUENCES HUGE *ps = GET_MEM("termcap struct", 1, SEQUENCES);
 
1472
outer_char *string[NUM_TEMP_PTRS];
 
1473
 
 
1474
if(!termcap) 
 
1475
        return;
 
1476
 
 
1477
for(t=*pid,n=0; *t; t+=len)
 
1478
        {
 
1479
        if(n == NUM_TEMP_PTRS) 
 
1480
                break;
 
1481
 
 
1482
        while(*t==' ') 
 
1483
                t++;
 
1484
 
 
1485
#if 0
 
1486
        printf("TERMSET:  <0%o>: `%s'\n", t[0], t+1);
 
1487
#endif
 
1488
 
 
1489
        if(*t == ESC)
 
1490
                { /* Kludge:  Recognized a hard-coded escape sequence. */
 
1491
                len = STRLEN(t);
 
1492
                string[n++] = (outer_char *)t;
 
1493
                }
 
1494
        else
 
1495
                @<Get escape sequence from termcap file@>@;
 
1496
        }
 
1497
 
 
1498
@<Allocate and initialize memory for the strings@>@;
 
1499
}
 
1500
 
 
1501
@
 
1502
@<Get escape...@>=
 
1503
{
 
1504
/* Put the abbreviation for escape sequence into |id|. */
 
1505
len = 2;
 
1506
STRNCPY(id, t, len);
 
1507
TERMINATE(id, len);
 
1508
 
 
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);
 
1513
else 
 
1514
        string[n++] = s;
 
1515
}
 
1516
 
 
1517
@
 
1518
@<Allocate and initialize memory for the strings@>=
 
1519
{
 
1520
ps->n = (short)n;
 
1521
ps->string = GET_MEM("termcap strings", n, outer_char *);
 
1522
 
 
1523
for(k=0; k<n; k++)
 
1524
        {
 
1525
        ps->string[k] = GET_MEM("termcap string",
 
1526
                STRLEN(string[k])+1,outer_char);
 
1527
        STRCPY(ps->string[k],string[k]);
 
1528
        }
 
1529
 
 
1530
FREE((void *)(*pid));
 
1531
*pid = (CONST outer_char HUGE *)ps;
 
1532
}
 
1533
 
 
1534
@ A similar routine processes a blank-delimited list of extensions.
 
1535
@a
 
1536
SRTN @\
 
1537
ext_set FCN((pid))
 
1538
        CONST outer_char HUGE **pid C1("")@;
 
1539
{
 
1540
outer_char id[1000],*p,*p0;
 
1541
CONST outer_char HUGE *t;
 
1542
outer_char *string[NUM_TEMP_PTRS];
 
1543
int k,n;
 
1544
SEQUENCES HUGE *ps = GET_MEM("termcap struct", 1, SEQUENCES);
 
1545
 
 
1546
t = *pid; // Beginning of blank-separated list.
 
1547
n = 0; // Number of fields found.
 
1548
p = id; // Start of storage area
 
1549
 
 
1550
while(*t)
 
1551
        {
 
1552
        if(n == NUM_TEMP_PTRS) 
 
1553
                break;
 
1554
 
 
1555
        while(*t == ' ') 
 
1556
                t++; // Skip initial white space.
 
1557
        
 
1558
        p0 = p;
 
1559
        while(*t != ' ' && *t) 
 
1560
                *p++ = *t++;
 
1561
        TERMINATE(p,0);
 
1562
        p++;
 
1563
        string[n++] = p0; // Remember where string is.
 
1564
        }
 
1565
 
 
1566
@<Allocate and init...@>@;
 
1567
}
 
1568
 
 
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
 
1571
on some systems.
 
1572
@a
 
1573
int @\
 
1574
put_out FCN((c))
 
1575
        int c C1("")@;
 
1576
{
 
1577
return putchar(c);
 
1578
}
 
1579
 
 
1580
@ Output the control sequences corresponding to a color.  This needs to be
 
1581
generalized for~X.
 
1582
 
 
1583
@m SEND(CLR) put_((SEQUENCES *)wt_style.color._##CLR)
 
1584
 
 
1585
@m CLR_CASE(CLR) 
 
1586
        case CLR:
 
1587
           SEND(CLR);
 
1588
           break@;
 
1589
 
 
1590
@a
 
1591
SRTN @\
 
1592
set_color FCN((clr))
 
1593
        COLOR clr C1("")@;
 
1594
{
 
1595
color0.last = color0.present; // Save the incoming color, for later restore.
 
1596
 
 
1597
#define put_ tput
 
1598
 
 
1599
if(color_mode)
 
1600
  switch(clr)
 
1601
        {
 
1602
        CLR_CASE(NORMAL);
 
1603
        CLR_CASE(BLACK);
 
1604
        CLR_CASE(RED);
 
1605
        CLR_CASE(GREEN);
 
1606
        CLR_CASE(YELLOW);
 
1607
        CLR_CASE(BLUE);
 
1608
        CLR_CASE(MAGENTA);
 
1609
        CLR_CASE(CYAN);
 
1610
        CLR_CASE(WHITE);
 
1611
 
 
1612
   default:
 
1613
        SEND(NORMAL);
 
1614
        break;
 
1615
        }
 
1616
 
 
1617
#undef put_
 
1618
 
 
1619
color0.present = clr;
 
1620
}
 
1621
 
 
1622
@
 
1623
@a
 
1624
outer_char * @\
 
1625
sset_color FCN((clr))
 
1626
        COLOR clr C1("")@;
 
1627
{
 
1628
#define put_ return sput
 
1629
 
 
1630
if(color_mode)
 
1631
  switch(clr)
 
1632
        {
 
1633
        CLR_CASE(NORMAL);
 
1634
        CLR_CASE(BLACK);
 
1635
        CLR_CASE(RED);
 
1636
        CLR_CASE(GREEN);
 
1637
        CLR_CASE(YELLOW);
 
1638
        CLR_CASE(BLUE);
 
1639
        CLR_CASE(MAGENTA);
 
1640
        CLR_CASE(CYAN);
 
1641
        CLR_CASE(WHITE);
 
1642
 
 
1643
   default:
 
1644
        SEND(NORMAL);
 
1645
        break;
 
1646
        }
 
1647
 
 
1648
#undef put_
 
1649
 
 
1650
return OC("");
 
1651
}
 
1652
 
 
1653
@ Send each abbreviation in turn.
 
1654
@a
 
1655
SRTN @\
 
1656
tput FCN((ps))
 
1657
        SEQUENCES *ps C1("")@;
 
1658
{
 
1659
int k;
 
1660
 
 
1661
for(k=0; k<ps->n; k++)
 
1662
        tputs(ps->string[k], 1, put_out);
 
1663
}
 
1664
 
 
1665
@ As above, but for writing to strings.
 
1666
@a
 
1667
outer_char * @\
 
1668
sput FCN((ps))
 
1669
        SEQUENCES *ps C1("")@;
 
1670
{
 
1671
int k;
 
1672
outer_char temp[100], *temp1;
 
1673
 
 
1674
if(color_mode == NO_COLOR)
 
1675
        return OC("");
 
1676
 
 
1677
STRCPY(temp, ps->string[0]);
 
1678
 
 
1679
for(k=1; k<ps->n; k++)
 
1680
        STRCAT(temp, ps->string[k]);
 
1681
 
 
1682
temp1 = GET_MEM("sput buf", STRLEN(temp)+1, outer_char);
 
1683
STRCPY(temp1, temp);
 
1684
 
 
1685
return push_buf(&sput_buf, temp1); // This needs to be freed at some point!
 
1686
}
 
1687
 
 
1688
 
 
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.}
 
1692
@<Unused@>=
 
1693
 
 
1694
SRTN @\
 
1695
clr_printf FCN(VA_ALIST((clr,fmt VA_ARGS)))
 
1696
        VA_DCL(
 
1697
        COLOR clr C0("")@;
 
1698
        outer_char *fmt C2("")@;)@;
 
1699
{
 
1700
VA_LIST(arg_ptr)@;
 
1701
 
 
1702
set_color(clr); // Remembers previous color in |color0.last|.
 
1703
 
 
1704
VA_START(arg_ptr, fmt);
 
1705
vprintf_(fmt, arg_ptr)@;
 
1706
va_end(arg_ptr);
 
1707
 
 
1708
set_color(color0.last); // Restore color.
 
1709
}
 
1710
 
 
1711
@* PRINTING OUT VALUES.
 
1712
@<Unused@>=
 
1713
boolean @\
 
1714
out_map FCN((name))
 
1715
        outer_char *name C1("")@;
 
1716
{
 
1717
outer_char *p;
 
1718
outer_char key_name[100];
 
1719
S_MAP *m;
 
1720
 
 
1721
STRCPY(key_name,name);
 
1722
for(p=key_name; *p; p++)
 
1723
        if(*p == '.') *p = '_';
 
1724
 
 
1725
for(m=fweb_map; *m->keyword; m++)
 
1726
        if(STRCMP(m->keyword,key_name) == 0)
 
1727
                {
 
1728
                for(p=key_name; *p; p++)
 
1729
                        if(*p == '_') *p = '.';
 
1730
 
 
1731
                printf("%s = ",key_name);
 
1732
                switch(m->type)
 
1733
                        {
 
1734
                   case S_STRING:
 
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);
 
1738
                        break;
 
1739
 
 
1740
                   case S_CHAR:
 
1741
                        printf("'%c'\n",*(char *)m->ptr);
 
1742
                        break;
 
1743
 
 
1744
                   case S_INT:
 
1745
                        printf("%d\n",*(int *)m->ptr);
 
1746
                        break;
 
1747
 
 
1748
                   case S_LONG:
 
1749
                        printf("%ld\n",*(long *)m->ptr);
 
1750
                        break;
 
1751
 
 
1752
                   default:
 
1753
                        printf("INVALID TYPE\n");
 
1754
                        break;
 
1755
                        }
 
1756
 
 
1757
                return YES;
 
1758
                }
 
1759
 
 
1760
return NO;
 
1761
}
 
1762
 
 
1763
@ Query the style-file parameters; from \.{-Z}~option.
 
1764
@a
 
1765
SRTN @\
 
1766
see_style FCN((pa, see_all))
 
1767
        CONST outer_char HUGE *pa C0("")@;
 
1768
        boolean see_all C1("")@;
 
1769
{
 
1770
S_MAP HUGE **s0,HUGE **s,HUGE **s1,HUGE *m;
 
1771
 
 
1772
s0 = GET_MEM("s0", sizeof(fweb_map)/sizeof(S_MAP), S_MAP HUGE *);
 
1773
 
 
1774
/* Fill an array of pointers. */
 
1775
for(s=s0,m=fweb_map; *(m->keyword); s++,m++)
 
1776
        *s = m;
 
1777
 
 
1778
/* Sort the array. */
 
1779
QSORT(s0, s-s0, sizeof(S_MAP HUGE *), cmpr_s_map);
 
1780
 
 
1781
/* Print out the values. */
 
1782
SET_COLOR(info);
 
1783
printf("%s style-file parameters%s%s%s%s:\n",
 
1784
        see_all ? "Default" : "Modified",
 
1785
        *pa ? " beginning with \"" : "", (char *)pa, *pa ? "\"" : "",
 
1786
#if 0
 
1787
        see_all // Got tired of reading this; nobody cares anyway.
 
1788
#endif
 
1789
        0 ? "\n (null or empty values for \
 
1790
@@ command codes are misleading)" : "");
 
1791
 
 
1792
SET_COLOR(ordinary);
 
1793
 
 
1794
if(*pa)
 
1795
        { /* Convert \.{'.'} to \.{'\_'}. */
 
1796
        outer_char HUGE *p;
 
1797
 
 
1798
        for(p=(outer_char HUGE *)pa; *p; p++)
 
1799
                if(*p == '.')
 
1800
                        *p = '_';
 
1801
        }
 
1802
 
 
1803
for(s1=s0; s1<s; s1++)
 
1804
        see_map(*s1, pa, see_all);
 
1805
 
 
1806
FREE_MEM(s0,"s0",sizeof(fweb_map)/sizeof(S_MAP),S_MAP);
 
1807
}
 
1808
 
 
1809
@
 
1810
@a
 
1811
int @\
 
1812
cmpr_s_map FCN((s0,s1))
 
1813
        S_MAP HUGE **s0 C0("")@;
 
1814
        S_MAP HUGE **s1 C1("")@;
 
1815
{
 
1816
return STRCMP((*s0)->keyword,(*s1)->keyword);
 
1817
}
 
1818
 
 
1819
@ Print out an individual style-file parameter.
 
1820
@a
 
1821
SRTN @\
 
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("")@;
 
1826
{
 
1827
SEQUENCES *ps;
 
1828
int k;
 
1829
STY_TYPE type;
 
1830
boolean modified = NO;
 
1831
boolean is_color;
 
1832
 
 
1833
if(*pa && STRNCMP(pa, s->keyword, STRLEN(pa)) != 0) 
 
1834
        return;
 
1835
 
 
1836
ps = NULL;
 
1837
 
 
1838
if(see_all)
 
1839
        modified = NO;
 
1840
else
 
1841
        modified = s->type & S_MODIFIED;
 
1842
 
 
1843
/* The |S_CLR| type handles parameters that are arrays of strings. */
 
1844
if(STRNCMP(s->keyword, "Color", 5) == 0)
 
1845
        {
 
1846
        ps = (SEQUENCES *)(*(outer_char **)s->ptr);
 
1847
 
 
1848
        if(see_all)
 
1849
                type = S_CLR;
 
1850
        else if(color_mode == USER_COLORS)
 
1851
                type = S_CLR | modified;
 
1852
        else
 
1853
                type = S_CLR_MOD;
 
1854
        }
 
1855
else if(STRNCMP(s->keyword, "ext", 3) == 0)
 
1856
        {
 
1857
        ps = NULL;
 
1858
        type = S_CLR | modified;
 
1859
        }
 
1860
else
 
1861
        type = s->type;
 
1862
 
 
1863
if(see_all) 
 
1864
        printf(" ");
 
1865
else
 
1866
        { /* Handled modified parameters. */
 
1867
        if(type & S_MODIFIED) 
 
1868
                {
 
1869
                CLR_PRINTF(ALWAYS, warning, 
 
1870
                        ((type == S_CLR_MOD && !modified ? " " : "*")));
 
1871
                type &= ~S_MODIFIED; 
 
1872
                        // Convert to ordinary type like |S_STRING|. 
 
1873
                }
 
1874
 
 
1875
        else return;
 
1876
        }
 
1877
 
 
1878
is_color = (type == S_STRING) 
 
1879
        && *(int *)s->ptr > NULL_COLOR && *(int *)s->ptr < (int)HIGHEST_COLOR;
 
1880
 
 
1881
if(color_mode)
 
1882
if(ps)
 
1883
        tput(ps); // Print color parameters in color!
 
1884
else if(is_color)
 
1885
        set_color(*(int *)s->ptr);
 
1886
 
 
1887
printf(" %s = ", (char *)s->keyword);
 
1888
 
 
1889
switch(type)
 
1890
        {
 
1891
   case S_STRING:
 
1892
        if(is_color)
 
1893
                printf("\"%s\"\n",clr_name[*(int *)s->ptr]);
 
1894
        else
 
1895
                see_str(*((outer_char **)s->ptr), OC("\n"));
 
1896
        break;
 
1897
 
 
1898
   case S_CHAR:
 
1899
        printf("'%c'\n",*(outer_char *)s->ptr);
 
1900
        break;
 
1901
 
 
1902
   case S_INT:
 
1903
        printf("%d\n",*(int *)s->ptr);
 
1904
        break;
 
1905
 
 
1906
   case S_LONG:
 
1907
        printf("%ld\n",*(long *)s->ptr);
 
1908
        break;
 
1909
 
 
1910
   case S_CLR:
 
1911
        ps = (SEQUENCES *)(*(outer_char **)s->ptr);
 
1912
        
 
1913
        for(k=0; k<ps->n; k++)
 
1914
                see_str(ps->string[k], OC(" "));
 
1915
        puts("");
 
1916
        break;
 
1917
 
 
1918
   default:
 
1919
        break;
 
1920
        }
 
1921
 
 
1922
SET_COLOR(ordinary);
 
1923
}
 
1924
 
 
1925
@
 
1926
@a
 
1927
SRTN @\
 
1928
see_str FCN((s, eos))
 
1929
        CONST outer_char HUGE *s C0("")@;
 
1930
        CONST outer_char *eos C1("")@;
 
1931
{
 
1932
outer_char c;
 
1933
 
 
1934
if(s==NULL) 
 
1935
        {
 
1936
        printf("NULL\n");
 
1937
        return;
 
1938
        }
 
1939
else if(s < (outer_char HUGE *)100) 
 
1940
        { /* Horrible kludge to handle stupid color processing.  (Maybe no
 
1941
                longer necessary.) */
 
1942
        printf("\n");
 
1943
        return;
 
1944
        }
 
1945
 
 
1946
printf("\"");
 
1947
 
 
1948
while((c = *s++))
 
1949
  print_it:
 
1950
        if(c=='\\') 
 
1951
                printf("\\\\");
 
1952
        else if(isprint(c)) 
 
1953
                printf("%c",c);
 
1954
        else 
 
1955
                {
 
1956
                printf("\\");
 
1957
                switch(c)
 
1958
                        {
 
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.
 
1967
                   default:
 
1968
                        printf("%o",c);
 
1969
                        break;
 
1970
                        }
 
1971
                }
 
1972
 
 
1973
printf("\"");
 
1974
printf("%s", eos);
 
1975
}
 
1976
 
 
1977
@* INDEX.