File: tc2null.c

package info (click to toggle)
troffcvt 1.04%2Brepack1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 3,416 kB
  • sloc: ansic: 13,110; makefile: 6,847; perl: 1,583; cpp: 333; sh: 215
file content (549 lines) | stat: -rw-r--r-- 11,360 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
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
/*
 * tc2null - read output from troffcvt and do nothing with it.
 *
 * Actually, it's not quite true that nothing is done: unrecognized
 * tokens are flagged, so tc2null in a way serves as a diagnostic
 * program.
 *
 * The main use of this "translator" is to serve as a starting point
 * for building troffcvt postprocessors.
 *
 * The table-handling machinery doesn't actually generate any output, but
 * it does extract table information from the input stream and keep track
 * of the current position within the table.  As such, this machinery
 * serves as an example for how other postprocessors might process tables.  
 * Some modifications will likely be necessary, of course.  See the exiting
 * postprocessors to get an idea of the kind of modifications that were
 * necessary for them.
 *
 * 20 Apr 92	Paul DuBois	dubois@primate.wisc.edu
 *
 * 20 Apr 92 V1.00
 * - Created.
 * 20 May 97
 * - Added tblcvt support.
 */

# ifdef	THINK_C
# include	<console.h>
# endif /* THINK_C */
# include	<stdio.h>
# include	<ctype.h>

# include	"etm.h"
# include	"memmgr.h"

# include	"tcread.h"
# include	"tctbl.h"


static void	ReadFile (void);
static void	ControlLine (void);
static void	PlainText (void);
static void	SpecialText (void);
static void	CenterFillAdjust (void);

static void	TableBegin (short argc, char **argv);
static void	TableEnd (void);
static void	TableColumnInfo (short argc, char **argv);
static void	TableRowBegin (short argc, char **argv);
static void	TableRowEnd (void);
static void	TableRowLine (short argc, char **argv);
static void	TableCellInfo (short argc, char **argv);
static void	TableCellBegin (short argc, char **argv);
static void	TableCellEnd (void);
static void	TableEmptyCell (void);
static void	TableSpannedCell (void);
static void	TableCellLine (short argc, char **argv);
static void	CellHSpanInit (void);


int	echo = 0;


/*
 * Per-table values
 */

static short	tblCols = 0;		/* number of columns in table */
static short	tblRows = 0;		/* number of rows in table */
static short	centerTbl= 0;		/* non-zero if table is centered */

/*
 * Per-column values
 */

static long	colWidth[tblMaxCol];	/* column width */
static long	colSep[tblMaxCol];	/* column separation */
static short	colEqWidth[tblMaxCol];	/* column is equal-width? */

/*
 * Per-cell values.  For the span stuff, the flag is set when in a span
 * (a set of > 1 cells that are merged together), the size is the number
 * of cells that the span comprises, and the idx is the index of the current
 * cell within the span (range is 0..size-1).
 */

static char	cellType[tblMaxCol];		/* cell type */
static short	cellVSpanFlag[tblMaxCol];	/* cell vspan flag */
static short	cellVSpanSize[tblMaxCol];	/* cell vspan extent */
static short	cellVSpanIdx[tblMaxCol];	/* cell vspan counter */
static short	cellHSpan[tblMaxCol];		/* cell hspan extent */
static short	cellHSpanFlag;			/* cell hspan flag */
static short	cellHSpanSize;			/* cell hspan extent */
static short	cellHSpanIdx;			/* cell hspan counter */
static char	cellVAdjust[tblMaxCol];		/* cell vertical adjust */
static short	cellBorder[tblMaxCol];		/* cell borders */

/*
 * Counters for keeping track of position within table.
 * tblColIdx counts horizontally during processing of \table-column-info
 * lines, during \table-cell-info lines, and while processing each row of
 * table data.  tblRowIdx counts rows of table data.
 */

static short	tblColIdx = 0;
static short	tblRowIdx = 0;


int
main (int argc, char *argv[])
{
	ETMInit (NULL);

# ifdef	THINK_C
	argc = ccommand (&argv);
# endif /* THINK_C */

	--argc;
	++argv;
	while (argc > 0 && argv[0][0] == '-')
	{
		if (strcmp (argv[0], "-E") == 0)
			echo = 1;
		else
			ETMPanic ("Unknown option: %s", argv[0]);
		--argc;
		++argv;
	}

	TCRInit ();

	if (argc == 0)		/* stdin */
		ReadFile ();
	else while (argc > 0)
	{
		if (freopen (argv[0], "r", stdin) == (FILE *) NULL)
			ETMMsg ("Cannot open: %s", argv[0]);
		else
			ReadFile ();
		--argc;
		++argv;
	}

	ETMEnd ();
	exit (0);
	/*NOTREACHED*/
}


static void
ReadFile (void)
{
int	i;

	while (TCRGetToken () != tcrEOF)
	{
		if (echo)
		{
			printf ("class %d maj %d min %d <%s>\n",
				tcrClass, tcrMajor, tcrMinor, tcrArgv[0]);
			if (tcrClass == tcrControl || tcrClass == tcrSText)
			{
				for (i = 1; i < tcrArgc; i++)
					printf ("\t<%s>\n", tcrArgv[i]);
			}
		}
		switch (tcrClass)
		{
		case tcrControl:	ControlLine (); break;
		case tcrText:		PlainText (); break;
		case tcrSText:		SpecialText (); break;
		default:	ETMPanic ("ReadFile: unknown class %d",
							tcrClass);
		}
	}
}


static void
ControlLine (void)
{
	switch (tcrMajor)
	{
	default:
		ETMMsg ("ControlLine: bad control major code: %d <%s>",
						tcrMajor, tcrArgv[0]);
		break;
	case tcrCUnknown:
		ETMMsg ("ControlLine: unknown control token: <%s>",
						tcrArgv[0]);
		break;
	case tcrCFA:
		CenterFillAdjust ();
		break;
	case tcrComment:
	case tcrSetupBegin:
	case tcrSetupEnd:
	case tcrPass:
	case tcrInputLine:
	case tcrOther:
	case tcrResolution:
	case tcrBreak:
	case tcrFont:
	case tcrPointSize:
	case tcrSpacing:
	case tcrLineSpacing:
	case tcrOffset:
	case tcrIndent:
	case tcrTempIndent:
	case tcrLineLength:
	case tcrPageLength:
	case tcrPageNumber:
	case tcrTitleLength:
	case tcrTitleBegin:
	case tcrTitleEnd:
	case tcrSpace:
	case tcrUnderline:
	case tcrCUnderline:
	case tcrNoUnderline:
	case tcrULineFont:
	case tcrBracketBegin:
	case tcrBracketEnd:
	case tcrBreakSpread:
	case tcrExtraSpace:
	case tcrLine:
	case tcrMark:
	case tcrMotion:
	case tcrBeginOverstrike:
	case tcrOverstrikeEnd:
	case tcrBeginPage:
	case tcrZeroWidth:
	case tcrSpaceSize:
	case tcrConstantWidth:
	case tcrNoConstantWidth:
	case tcrNeed:
	case tcrEmbolden:
	case tcrSEmbolden:
	case tcrResetTabs:
	case tcrFirstTab:
	case tcrNextTab:
	case tcrHyphenate:
	case tcrDiversionBegin:
	case tcrDiversionAppend:
	case tcrDiversionEnd:
	case tcrTabChar:
	case tcrLeaderChar:
		break;
	case tcrTableBegin:
		TableBegin (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrTableEnd:
		TableEnd ();
		break;
	case tcrColumnInfo:
		TableColumnInfo (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrRowBegin:
		TableRowBegin (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrRowEnd:
		TableRowEnd ();
		break;
	case tcrRowLine:
		TableRowLine (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrCellInfo:
		TableCellInfo (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrCellBegin:
		TableCellBegin (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrCellEnd:
		TableCellEnd ();
		break;
	case tcrCellLine:
		TableCellLine (tcrArgc - 1, &tcrArgv[1]);
		break;
	case tcrEmptyCell:
		TableEmptyCell ();
		break;
	case tcrSpannedCell:
		TableSpannedCell ();
		break;
	}
}


static void
PlainText (void)
{
	if (tcrMajor != '\n' && tcrMajor != '\r')
	{
		/* do something with character */
	}
}


/*
 * The switch below lists all the known builtin special characters.
 * Those that aren't builtin will have a major code of tcrSTUnknown;
 * this will include those characters listed in the actions file.
 * It may be just as easy to skip the switch and handle all special
 * characters uniformly, e.g., by looking up their name in a translation
 * table for an output sequence.
 */

static void
SpecialText (void)
{
	switch (tcrMajor)
	{
	default:
		printf ("bad special text major code: %d <%s>\n",
						tcrMajor, tcrArgv[0]);
		break;
	case tcrSTUnknown:
		/* handle non-builtin special characters here */
		break;
	case tcrBackslash:
	case tcrAtSign:
	case tcrLSglQuote:
	case tcrRSglQuote:
	case tcrLDblQuote:
	case tcrRDblQuote:
	case tcrZeroSpace:
	case tcrTwelfthSpace:
	case tcrSixthSpace:
	case tcrDigitSpace:
	case tcrHardSpace:
	case tcrMinus:
	case tcrGraveAccent:
	case tcrAcuteAccent:
	case tcrBackspace:
	case tcrOptHyphen:
	case tcrTab:
	case tcrLeader:
	case tcrFieldBegin:
	case tcrFieldEnd:
	case tcrFieldPad:
		break;
	}
}


static void
CenterFillAdjust (void)
{
	switch (tcrMinor)
	{
	default:
		ETMMsg ("CenterFillAdjust: bad minor code %d <%s>",
						tcrMinor, tcrArgv[0]);
		break;
	case tcrCenter:
	case tcrNofill:
	case tcrAdjFull:
	case tcrAdjLeft:
	case tcrAdjRight:
	case tcrAdjCenter:
		break;
	}
}


/*
 * Table element routines
 */

static void
TableBegin (short argc, char **argv)
{
	if (argc != 8)
		ETMPanic ("TableBegin: wrong number of args: %hd", argc);
	tblCols = StrToShort (argv[tblColsArg]);
	tblRows = StrToShort (argv[tblRowsArg]);

	if (tblCols == 0)
		ETMPanic ("TableBegin: zero column table");
	if (tblCols > tblMaxCol)
		ETMPanic ("TableBegin: too many table columns (%hd), max = %d",
						tblCols, tblMaxCol);

	/* determine whether or not to center the table */
	centerTbl = argv[tblAlignArg][0] == 'C'? 1 : 0;

	tblColIdx = 0;
	tblRowIdx = 0;
}


static void
TableEnd (void)
{
}


static void
TableColumnInfo (short argc, char **argv)
{
	if (argc != 3)
		ETMPanic ("TableColumnInfo: wrong number of args: %hd", argc);
	if (tblColIdx >= tblMaxCol)
		ETMPanic ("TableColumnInfo: logic error");

	/*
	 * For separation and width, 0 means "none specified".
	 */
	colSep[tblColIdx] = StrToLong (argv[colSepArg]);
	colWidth[tblColIdx] = StrToLong (argv[colWidthArg]);

	colEqWidth[tblColIdx] = (argv[colEqWidthArg][0] == 'y' ? 1 : 0);

	++tblColIdx;
}


/*
 * Begin a table row.
 */

static void
TableRowBegin (short argc, char **argv)
{
	/*
	 * Reset tblColIdx for use by \table-cell-info controls
	 */
	tblColIdx = 0;
}


static void
TableRowEnd (void)
{
	++tblRowIdx;	/* done with row, bump counter */
}


static void
TableRowLine (short argc, char **argv)
{
	++tblRowIdx;	/* done with row, bump counter */
}


static void
TableCellInfo (short argc, char **argv)
{
char	buf[bufSiz];
short	vspan;

	if (argc != 5)
		ETMPanic ("TableCellInfo: wrong number of args: %hd", argc);
	if (tblColIdx >= tblMaxCol)
		ETMPanic ("TableCellInfo: logic error");

	cellType[tblColIdx] = argv[cellTypeArg][0];

	vspan = StrToShort (argv[cellVSpanArg]);
	if (vspan == 1)			/* not part of a vspan */
	{
		cellVSpanFlag[tblColIdx] = 0;
	}
	else if (vspan > 1)		/* part of a vspan -- first cell */
	{
		cellVSpanFlag[tblColIdx] = 1;
		cellVSpanSize[tblColIdx] = vspan;
		cellVSpanIdx[tblColIdx] = 0;
	}
	else				/* part of a vspan -- not first cell */
	{
		++cellVSpanIdx[tblColIdx];
	}

	cellHSpan[tblColIdx] = StrToShort (argv[cellHSpanArg]);
	cellVAdjust[tblColIdx] = StrToShort (argv[cellVAdjustArg]);
	cellBorder[tblColIdx] = StrToShort (argv[cellBorderArg]);

	/*
	 * Bump cell index.
	 * Reset if we've reached the end, so it'll be correct for
	 * \table-cell-begin, \table-empty-cell, \table-spanned-cell,
	 * \table-cell-line.
	 */

	++tblColIdx;
	if (tblColIdx >= tblCols)
		tblColIdx = 0;
}


static void
TableCellBegin (short argc, char **argv)
{
	CellHSpanInit ();
}


static void
TableCellEnd (void)
{
	++tblColIdx;
}


static void
TableEmptyCell (void)
{
	CellHSpanInit ();
	++tblColIdx;
}


static void
TableSpannedCell (void)
{
	CellHSpanInit ();
	++tblColIdx;
}


static void
TableCellLine (short argc, char **argv)
{
	CellHSpanInit ();
	++tblColIdx;
}


static void
CellHSpanInit (void)
{
short	hspan;

	hspan = cellHSpan[tblColIdx];
	if (hspan == 1)			/* not part of a hspan */
	{
		cellHSpanFlag = 0;
	}
	else if (hspan > 1)		/* part of a hspan -- first cell */
	{
		cellHSpanFlag = 1;
		cellHSpanSize = hspan;
		cellHSpanIdx = 0;
	}
	else				/* part of a hspan -- not first cell */
	{
		++cellHSpanIdx;
	}
}