File: common.hweb

package info (click to toggle)
fweb 1.60beta-11
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 4,348 kB
  • ctags: 5,018
  • sloc: ansic: 38,347; makefile: 393; sh: 163
file content (435 lines) | stat: -rw-r--r-- 11,998 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
@z --- common.hweb ---

FWEB version 1.60-beta (January 1, 1997)

Based on version 0.5 of S. Levy's CWEB [copyright (C) 1987 Princeton University]

@x-----------------------------------------------------------------------------

@i typedefs.hwb

@* DEFINITIONS for TANGLE and WEAVE. Here's stuff required for
\.{tangle.web} and \.{weave.web}. 

@ As much as possible, we adhere to ANSI conventions. However, to support
pre-ANSI compilers such as \.{gcc}, we must make some modifications. It is
assumed that the compilers predefine macros such as |vax|, |sun|, or |mac|,
in \It{lower case}; if they do not, then these macros must be defined from
the command line. In addition, the \WEB\ files must be tangled with
\It{upper case} macros such as |VAX|, |SUN|, or |MAC| defined from the
command line, as in \.{ftangle tangle -m"SUN"}. It is conventional to put
the machine macro command into the ini file \.{.fweb}, as in ``\.{+mSUN}''.

@i os.hweb // System-dependent definitions.

@ The following flag is used for \Cpp. (??)
@<Common...@>=

EXTERN boolean long_comment;

@ Code related to the character set. \It{Mess around here only at your own
risk.} 

@D and_and OCTAL(4) // `|&&|'.
@D star_star OCTAL(5) // `|@r x**y|' .
@D colon_colon OCTAL(11) // \Cpp\ and \Fortran--90: `$\CF$'.

/* The next two only occur in different languages, so they can have the same
value. */  
@D neqv OCTAL(10) // `|@r .neqv.|'.
@D ellipsis neqv // `|...|'.

@D stmt_label OCTAL(30)

@D slash_slash OCTAL(26)  // Concatenation `|@r \/|' .

@D bell OCTAL(7) // |ASCII| code for ringing the bell.
@D tab_mark @'\t' // |ASCII| code used as tab-skip.
@D line_feed OCTAL(12) /* |ASCII| code thrown away at end of line; $\equiv$
			\.{'\\n'}. */
@D form_feed OCTAL(14) // |ASCII| code used at end of page.
@D carriage_return OCTAL(15) // |ASCII| code used at end of line.

@D gt_gt OCTAL(20) // `|>>|'; this doesn't exist in MIT.
@D lt_lt OCTAL(22) // `|<<|'; this doesn't exist in MIT.

@D plus_plus OCTAL(13) // `|++|'; this corresponds to MIT's up-arrow.
@D minus_minus OCTAL(1) // `|--|'; this corresponds to MIT's down-arrow.

@D minus_gt OCTAL(31) // `|->|'.
@D eqv minus_gt // `|@r .eqv.|'.

@D not_eq OCTAL(32) // `|!=|'.

@D paste OCTAL(33) // `|##|'.

@D lt_eq OCTAL(34) // `|<=|'.
@D gt_eq OCTAL(35) // `|>=|'.

@D eq_eq OCTAL(36) // `|==|'.

@D or_or OCTAL(37) // `||| |'.

@D begin_language OCTAL(16) // Mark a language switch.

@D left_array OCTAL(21)  // `$\LS$'.
@D right_array OCTAL(25) // `$\SR$'.

@D interior_semi OCTAL(24) // `\.;'.

@<Common code...@>=

IN_COMMON ASCII xord[]; // specifies conversion of input characters.
@#ifdef scramble_ASCII
	IN_COMMON ASCII xxord[];
@#endif
IN_COMMON outer_char xchr[]; // specifies conversion of output characters.

@ Code related to input routines:

@<Common code...@>=

IN_COMMON BUF_SIZE buf_size; // Used for \FWEAVE; see \.{common.web}.
IN_COMMON ASCII HUGE *loc; /* points to the next character to be read from the
				buffer*/ 

@ Code related to identifier and module name storage:

@d ID_FLAG 10240 // \bf DON'T MONKEY WITH THIS NUMBER!.

@d length(c) (c+1)->byte_start-(c)->byte_start // the length of a name.

@d llink link // left link in binary search tree for module names.
@d root name_dir->rlink /* the root of the binary search tree
  for module names */

@d is_intrinsic(n) (n->intrinsic_word & (boolean)language)
@d is_keyword(n) (n->keyword & (boolean)language)

@<Common code...@>=

IN_COMMON name_pointer name_ptr; // first unused position in |byte_start|.
IN_COMMON ASCII HUGE *byte_ptr; // first unused position in |byte_mem|.

typedef name_pointer HUGE *hash_pointer;
IN_COMMON hash_pointer hash, /* heads of hash lists */
	hash_end, /* end of |hash| */
	h; /* index into hash-head array */


@ To distinguish between the constructions \.{@@<\dots@@>} and
\.{\#<\dots@@>}, both of which return |module_name|, we introduce the flag
|mac_mod_name|. 

@<Common code...@>=

EXTERN boolean mac_mod_name;

@ Code related to module numbers:
@<Common code...@>=

IN_COMMON sixteen_bits module_count; // The current module number.
IN_COMMON boolean HUGE *chngd_module; // Dynamic array: Is the module changed?
IN_COMMON boolean prn_where; // Tells \.{TANGLE} to print line and file	info.

@ Code relating to output:

@d UPDATE_TERMINAL fflush(stdout) // Empty the terminal output buffer.
@d new_line putchar('\n') @d putxchar putchar
@d ASCII_write(p0,n) fflush(stdout),
		ASCII_file_write(stdout,p0,(int)(n))@;
	/* Write on the standard output, converting from |ASCII|. */ 

@ For FORTRAN, \&{format} commands are annoying, because the use of slashes
doesn't fit with the rest of the \Fortran\ syntax. Thus, we'll deal with the
|format| statement something like a preprocessor statement, in that we'll
raise a special flag when we're inside it, and issue special tokens to
indicate the start and the end of the statement.

@D begin_format_stmt OCTAL(171)
@D end_format_stmt OCTAL(172)

@ For~C, getting an identifier is simple. For FORTRAN, we treat \&{format}
statements much like C's preprocessor statement. However, there's no
special character to start a \&{format} line; we have to actually check the
identifier. Furthermore, it looks nicer if constructions such as \\{f6.2}
are treated as one identifier, so when we're inside a \&{format} statement
we allow the period to be an acceptable (internal) character for an identifier.

@d is_identifier(c) (isAlpha(c) || c==@'_' || c==@'$' ||
	(c==@'%' && language!=C && !Fortran88) ) /* This defines the starting
					character of an identifier. */ 

@d is_kind(c) (isDigit(c) || isAlpha(c) || c==@'_' || c==@'$') 
	/* \Fortran-90 kind parameter. */

@<Get an identifier@>= 
@{
IN_COMMON ASCII HUGE *pformat, HUGE *pdata;
@% IN_COMMON ASCII HUGE *pdefault, HUGE *pcontains;

get_identifier:
  id_first = --loc;

/* Scan over subsequent elements of an identifier. */
  for(++loc; isAlpha(*loc) || isDigit(*loc) || 
	*loc==@'_' || *loc==@'$' || (in_format && *loc==@'.'); loc++)
		;

id_loc=loc;  /* End plus one of the identifier. */

if(FORTRAN_LIKE(language))
	{
	if(web_strcmp(pformat,pformat+6,id_first,id_loc) == EQUAL)
		{ /* Raise special flag to say we're inside a |@r format|
statement. */ 
		in_format = YES;
		return begin_format_stmt; 
		}
	else if(program==weave)
		{
		if(web_strcmp(pdata,pdata+4,id_first,id_loc) == EQUAL)
			{ // Inside a |@r data| statement.
			in_data = YES;
			return identifier;
			}
		else if(at_beginning && *loc==@':' &&
				!is_in(non_labels,id_first,id_loc))
			return stmt_label;  
		}
	}

if(is_include_like()) sharp_include_line = YES;
return identifier;
}

@ Here we obtain the file name after an \.{@@o}~command.
@<Scan the output file name@>=
{
while(*loc == @' ' || *loc == tab_mark)
	{
	loc++;
	if(loc > limit) return ignore;
	}

id_first = loc;
while(*loc != @' ' && *loc != tab_mark) loc++; // Absorb file name.
id_loc = loc;
if(*id_first == @'"') id_first++;
if(*(id_loc-1) == @'"') id_loc--;
if(id_loc - id_first >= MAX_FILE_NAME_LENGTH)
	{
	err_print(T,"Output file name too long; allowed only %d characters",
		MAX_FILE_NAME_LENGTH - 1);
	id_loc = id_first + MAX_FILE_NAME_LENGTH - 1;
	}
}

@ These tables are initialized during |common_init|.

@<Common...@>=

#undef expr
#define expr 1

#undef unop
#define unop 2

#undef binop
#define binop 3

extern DOTS HUGE *dots; /* The dynamic table; see \.{common.web}. */

#ifdef _FWEB_h

	EXTERN DOTS dots0[]
   #if(part == 0 || part == 1)
	    = {
		{(ASCII *)"@@@@@@",3,dot_const,expr,0}, /* Dummy */
		{(ASCII *)"AND",3,dot_const,binop,and_and}, /* |and_and| */
		{(ASCII *)"EQ",2,dot_const,binop,eq_eq}, /* |eq_eq| */
		{(ASCII *)"EQV",3,dot_const,binop,eqv}, /* |eqv| */
		{(ASCII *)"FALSE",5,dot_const,expr,0},
		{(ASCII *)"GE",2,dot_const,binop,gt_eq}, /* |gt_eq| */
		{(ASCII *)"GT",2,dot_const,binop,@'>'}, /* |@'>'| */
		{(ASCII *)"LE",2,dot_const,binop,lt_eq}, /* |lt_eq| */
		{(ASCII *)"LT",2,dot_const,binop,@'<'}, /* |@'<'| */
		{(ASCII *)"NE",2,dot_const,binop,not_eq}, /* |not_eq| */
		{(ASCII *)"NEQV",4,dot_const,binop,neqv}, /* |neqv| */
		{(ASCII *)"NOT",3,dot_const,unop,@'!'}, /* |@'!'| */
		{(ASCII *)"OR",2,dot_const,binop,or_or}, /* |or_or| */
		{(ASCII *)"TRUE",4,dot_const,expr,1},
		{(ASCII *)"XOR",3,dot_const,binop,neqv}, /* |neqv| */
		{(ASCII *)"",0,0,0,0}
		}
	#endif /* |part == 1| */
		;
#endif /* |_FWEB_h| */

@ The preprocessor commands have a similar format.
@<Common...@>=

#ifdef _FWEB_h

	EXTERN DOTS mcmds[] 
   #if(part ==0 || part == 1)
	 = {
		{(ASCII *)"define",6,WEB_definition},
		{(ASCII *)"elif",4,m_elif},
		{(ASCII *)"elseif",6,m_elif},
		{(ASCII *)"else",4,m_else},
		{(ASCII *)"endfor",6,m_endfor},
		{(ASCII *)"endif",5,m_endif},
		{(ASCII *)"for",3,m_for},
		{(ASCII *)"if",2,m_if},
		{(ASCII *)"ifdef",5,m_ifdef},
		{(ASCII *)"ifndef",6,m_ifndef},
		{(ASCII *)"pragma",6,m_pragma},
		{(ASCII *)"undef",5,m_undef},
		{(ASCII *)"",0,0}
	    }
	#endif /* |part == 1| */
		;
#endif /* |_FWEB_h| */

@ The preprocessor commands are piggy-backed on the \.{@@\#} command. If
there's text after that command, then we hunt through the above table.
Otherwise, it's a |big_line_break|.

@<Process possible preprocessor command@>=
@{
boolean mcode;

@b
*limit = @' '; /* Terminator for identifier search. */
id_first = loc;

while(isAlpha(*loc)) loc++; /* Find end of identifier. */

if((mcode=is_mcmd(mcmds,id_first,loc)) != 0) return mcode;

loc = id_first; /* Failed to recognize preprocessor command. */
}

@i mem.hweb /* Macros for memory allocation. */

@ Miscellaneous definitions.

@#ifndef _FWEAVE_

	@D MCHECK0(n,reason) mcheck0((unsigned long)(n),(outer_char *)reason)

	@d EVALUATE(val,p0,p1) 
	  {unsigned long nbytes;
	  val_ptr = val_heap = 
	  GET_MEM("val_heap",nbytes=2*((p1)-(p0)),VAL); 
		evaluate(&val,p0,p1); 
	  if(val_heap) FREE_MEM(val_heap,"val_heap",nbytes,VAL);
	  }

	@d DONE_LEVEL (cur_byte >= cur_end) /* Do we need to pop? */

@#endif /* |_FWEAVE_| */

@<Glob...@>=

/* The shorter length here is primarily to keep the stack under control.
Now that |N_MSGBUF| is used  dynamically, maybe this statement isn't
necessary. */ 
#ifdef SMALL_MEMORY
	#define N_MSGBUF 2000
#else
	#define N_MSGBUF 10000
#endif 


@ The following helps insert spaces in the output.
@<Typedef...@>=

@#ifndef _FWEAVE_

	typedef enum
		{
		MISCELLANEOUS, /* ``normal'' state */
		NUM_OR_ID, /* state associated with numbers and identifiers */
		UNBREAKABLE, /* state associated with \.{@@\&} */
		VERBATIM /* state in the middle of a string */
		} OUTPUT_STATE;

@#endif /* |_FWEAVE_| */

@ For debugging and error messages, we need a routine that gives the name
of a control code.
@m CN(code) case code: return (outer_char *)#code
@A
@#if defined _FWEAVE_ || defined _FTANGLE_
#if(part == 0 || part == 1)

@[outer_char *ccode_name FCN((code))
	eight_bits code C1("")@;
{
switch(code)
	{
	CN(begin_FORTRAN);
	CN(begin_RATFOR);
	CN(begin_C);
	CN(ascii_constant);
	CN(big_line_break);
	CN(begin_meta);
	CN(end_meta);
	CN(TeX_string);
	CN(xref_roman);
	CN(xref_typewriter);
	CN(xref_wildcard);
	CN(formatt);
	CN(definition);
	CN(WEB_definition);
	CN(begin_code);
	CN(module_name);
	CN(new_module);
	CN(m_ifdef);
	CN(m_ifndef);
	CN(m_if);
	CN(m_else);
	CN(m_elif);
	CN(m_endif);
	CN(m_undef);

@#ifdef _FTANGLE_
	CN(begin_vcmnt);
	CN(begin_bp);
	CN(insert_bp);
	CN(control_text);
@#endif /* |_FTANGLE_| */

@#ifdef _FWEAVE_
	CN(dont_expand);
	CN(auto_label);
	CN(macro_module_name);
	CN(switch_math_flag);
	CN(underline);
	CN(thin_space);
	CN(math_break);
	CN(line_break);
	CN(ln_break_outdent);
	CN(no_line_break);
	CN(pseudo_semi);
	CN(macro_space);
	CN(copy_mode);
	CN(toggle_output);
	CN(pseudo_expr);
	CN(pseudo_colon);
	CN(trace);
@#endif /* |_FWEAVE_| */
	default: return OC("UNKNOWN");
	}	
}
#endif /* |part == 1| */
@#endif /* |defined _FWEAVE_ || defined _FTANGLE_| */

@ This dummy module avoids warning messages from \FWEAVE\ if the indicated
modules aren't actually used.
@<Unused@>=
@<Get an id...@>@;
@<Process possible ...@>@;