1 /*
2  * Copyright (C) 1991,1992,1994 NEC Corporation.
3  */
4 /*
5  * modify by k-chinen@is.aist-nara.ac.jp, 1994
6  */
7 
8 #ifndef	lint
9 
10 
11 #endif
12 
13 #include <stdio.h>
14 #include <ctype.h>
15 #define	PLAIN2MAIN
16 #include "plain2.h"
17 #include "macro.h"
18 
19 #ifdef HTML
20 #define	PLAIN2_USAGE_1	"\
21 usage: plain2 [options] [files ...]\n\n\
22   ---- parser options ----		   ---- output options ----(default)\n\
23 -table=dd: table factor	 [0-100](def=50) -roff:	    troff output\n\
24 -exam=dd:  example factor[0-100](def=50) -ms/-mm:   troff macro	       (mm)\n\
25 -indsec:   sections can be indented      -tex:      tex output\n\
26 -ktable:enable JIS keisen table		 -tstyle=ss:tex style\n\
27 -ref:	   figure/picture reference	 -html:     HTML output\n\
28 					 -htmlonce: HTML (one path) output\n\
29 					 -here:	    HTML table/picture ref.\n\
30 					 -renum:    renumbering only\n\
31  					 -[no]listd:list decoration    (on)\n\
32   ---- Others ----			 -[no]space:spacing            (on)\n\
33 -v:	   verbose output		 -[no]pre:  preamble block     (on)\n\
34 -dLevel:   debug level			 -[no]acursec: section numbers (off)\n\
35   ----- experimental ----		 -raw:      quote special chars(off)\n\
36 -pt=Size:  font size			 -jis:      JIS code output\n\
37  					 -sjis:     Shift-JIS code input/output\n\
38  					 -f file:   output customization\n\n"
39 #define	VERSION	"plain2 r2.54 1994/04 by A.Uchida NEC Corporation\n\
40 \t(HTML output) by k-chinen@is.aist-nara.ac.jp, NAIST\n\
41 \t(unofficial patch 98/08/13 by N.Nide)"
42 #else
43 #define	PLAIN2_USAGE_1	"\
44 usage: plain2 [options] [files ...]\n\
45   ---- parser options ----		   ---- output options ----(default)\n\
46 -table=dd: table factor	 [0-100](def=50) -roff:	    troff output\n\
47 -exam=dd:  example factor[0-100](def=50) -ms/-mm:   troff macro	       (mm)\n\
48 -indsec:   sections can be indented      -tex:      tex output\n\
49 -ktable:enable JIS keisen table		 -tstyle=ss:tex style\n\
50 -ref:	   figure/picture reference	 -renum:    renumbering only\n\
51  					 -[no]listd:list decoration    (on)\n\
52   ---- Others ----			 -[no]space:spacing            (on)\n\
53 -v:	   verbose output		 -[no]pre:  preamble block     (on)\n\
54 -dLevel:   debug level			 -[no]acursec: section numbers (off)\n\
55   ----- experimental ----		 -raw:      quote special chars(off)\n\
56 -pt=Size:  font size			 -jis:      JIS code output\n\
57  					 -sjis:     Shift-JIS code input/output\n\
58  					 -f file:   output customization\n"
59 #define	VERSION	"plain2 r2.54 1994/04 by A.Uchida NEC Corporation\n\
60 \t(HTML output) by k-chinen@is.aist-nara.ac.jp, NAIST"
61 #endif
62 
63 extern char	*getenv();
64 extern char	*optarg;
65 extern int	optind;
66 extern struct macDefs	roffMacros[], roffMsMacros[];
67 extern struct macDefs	texMacros[];
68 #ifdef HTML
69 extern struct macDefs   htmlMacros[];
70 #endif
71 
72 /*
73  * Default parameters for Parsing
74  */
75 int tableEnabled    =  1;
76 int jisTableEnabled =  0;
77 int indentedSecnum  =  0;
78 int tableFactor	    = 50;
79 int examFactor	    = 50;
80 int removePaging    =  0;
81 int crossRefer      =  0;
82 int inlineHint	    =  1;
83 int roffMacro	    = MM_MACRO;
84 int renumber	    =  0;
85 /*
86  * Output parameters
87  */
88 int pageWidth	    = DEF_PAGE_WIDTH;
89 int rawOutput	    =  0;
90 int halfCooked	    =  0;
91 int inputCode	    = CODE_EUC;
92 int outputCode	    = CODE_EUC;
93 int preamble	    =  1;
94 int accurateSecnum  =  0;
95 int listDecor	    =  1;
96 int reflectSpace    =  1;
97 int texQuote	    =  0;
98 int fontSize	    = 10;
99 int fontSpecified   =  0;
100 int verbose	    =  0;
101 #ifdef HTML
102 int htmlOnce        =  0;
103 int htmlHere        =  0;
104 #endif
105 char *plain2Lib	    = NULL;
106 char *macroName	    = NULL;
107 char *texStyle	    = DEFAULT_STY; /* Nide */
108 struct outDev *put  = &roffPut;
109 int useJverb	    =  0; /* Nide */
110 
111 FILE	*inFile;
112 struct text	 **texts;
113 struct text	 *textTop;
114 struct textBlock *pageBp;
115 int	textLines;
116 int	textBegin;
117 int	rightMargin;
118 int	japaneseText;
119 int	titleStyle;
120 int	anySection = 0;
121 char	*fname;
122 int	acceptOutOption;
123 #ifdef	DEBUG
124 int	debug;
125 #endif
126 
127 #ifdef	__TURBOC__
128 extern unsigned _stklen = 32768U;
129 #endif
130 
131 int stflag = 1;
132 
main(argc,argv)133 main(argc, argv)
134 int	 argc;
135 char	 **argv;
136 {
137 	int	argind;
138 	/*
139 	 * Get options from Environment
140 	 *	or from the file specified by Env. variable
141 	 *
142 	 *  Parameters are set by ..
143 	 *	1) Default value
144 	 *	2) Environment (value itself or file)
145 	 *	3) Option line of each input files
146 	 */
147 	clearMacro();
148 	plain2Lib = getenv(PLAIN2_LIB);
149 	acceptOutOption = 1;
150 	envOption();
151 	if (getOption(argc, argv)) {
152 		(void)fprintf(stderr, PLAIN2_USAGE_1);
153 		(void)fprintf(stderr, "%s\n", VERSION);
154 		exit (2);
155 	}
156 	if (put != &texPut) useJverb = 0;
157 	if (macroName)
158 		macroFile(macroName);
159 	saveParseDefaults();
160 	tblParseInit();
161 #ifdef	PICTURE
162 	picParseInit();
163 #endif
164 	ftitleInit();
165 	MSG1("%s\n", VERSION);
166 	argind = optind;		/* optind will be used afterward */
167 	if (argind >= argc) {
168 		fname = "stdin";
169 		inFile = stdin;
170 		doPlain2();
171 	}
172 	else while (argind < argc) {
173 		if ((inFile = fopen(argv[argind], "r")) == NULL) {
174 			(void)fprintf(stderr, "%s  cannot open\n",
175 				      argv[argind]);
176 			exit(1);
177 		}
178 		else {
179 			fname = strsave(argv[argind]);
180 		}
181 		doPlain2();
182 		acceptOutOption = 0;
183 		argind++;
184 	}
185 	if (anySection)
186 		putMacro(M_SECTION_END);
187 	if (preamble)
188 		putMacro(M_DOC_END);
189 	exit(0);
190 }
191 
192  /* "a4j,12pt" -> "a4,12pt" etc. Return value can be free'ed afterward */
styleConv(s,nttflag)193 char	*styleConv(s, nttflag)
194 char	*s;
195 int	nttflag;
196 {
197 	char	*buf, *p;
198 	int	sty_appeared = 0;
199 
200 	if(NULL == (p = buf = malloc(strlen(s)*3/2+6+1))){ /* 6 for ",jverb" */
201 		fprintf(stderr, "PANIC(malloc in styleConv)\n");
202 		exit(2);
203 	}
204 	while(*s){
205 		while(isspace(*s)) *p++ = *s++;
206 		if(*s) sty_appeared = 1;
207 		if((*s == 'a' || *s == 'b') && (s[1] == '4' || s[1] == '5')){
208 			if(nttflag){
209 				if(s[2] == 'j' && (!s[3] || s[3] == ',')){
210 					strncpy(p, s, 2), p += 2, s += 3;
211 				}
212 			} else {
213 				if(!s[2] || s[2] == ','){
214 					strncpy(p, s, 2), p += 2, s += 2;
215 					*p++ = 'j';
216 				}
217 			}
218 		}
219 		while(*s) if(',' == (*p++ = *s++)) break;
220 	}
221 	if(useJverb){
222 		if(sty_appeared) *p++ = ',';
223 		strcpy(p, "jverb"), p += 5;
224 	}
225 	*p = '\0';
226 	return buf;
227 }
228 #define nttSty(s)   styleConv(s, 1)
229 #define asciiSty(s) styleConv(s, 0)
230 
231 /*
232  * Do parse & output
233  */
doPlain2()234 doPlain2()
235 {
236 	static	int	firstTime = 1;
237 
238 	restoreParseDefaults();
239 	readAndStoreFile();
240 	MSG2("Input %d lines from \"%s\"\n", textLines, fname);
241 	if (textLines <= 1)
242 		exit(0);
243 	analyzeLines(1, textLines);
244 	textBegin = getTitleBlock(1, textLines);
245 
246 	if (firstTime) {
247 		firstTime = 0;
248 #ifdef HTML
249 		if (put == &htmlPut) {
250 			initMacroDefs(htmlMacros);
251 			/* sorry, nothing is change this "if" */
252 			if (halfCooked) {
253 				htmlSetTrans(0);
254 			}
255 			else {
256 				htmlSetTrans(1);
257 			}
258 		}
259                 else
260 #endif
261 		if (put == &roffPut) {
262 			if (roffMacro == MS_MACRO)
263 				initMacroDefs(roffMsMacros);
264 			initMacroDefs(roffMacros);
265 		}
266 		else if (put == &texPut) {
267 			initMacroDefs(texMacros);
268 			if (halfCooked) {
269 				texSetTrans(0);
270 			}
271 			else {
272 				texSetTrans(1);
273 			}
274 		}
275 		if (preamble) {
276 		  if (stflag)  {
277 			char	*p = nttSty(texStyle), *q = asciiSty(texStyle);
278 
279 			putMacro(M_DOC_BEGIN, (long)fontSize, p, q);
280 			free(p), free(q);
281 		  }
282 		  else {
283 			char *p = asciiSty(texStyle), *q = asciiSty(texStyle);
284 
285 			putMacro(M_DOC_BEGIN, (long)fontSize, p, q);
286 			free(p), free(q);
287 		  }
288 		}
289 	}
290 
291 	hint(textBegin, textLines);
292 	MSG0("[blank]");
293 	spacing(textBegin, textLines);
294 	if (removePaging) {
295 		MSG0("[paging]");
296 		headerFooter(textBegin, textLines);
297 	}
298 	MSG0("[section]");
299 	section(textBegin, textLines, 0);
300 	MSG0("[appendix]");
301 	appendix(textBegin, textLines);
302 	MSG0("[quotation]");
303 	quotedText(textBegin, textLines);
304 	MSG0("[list]");
305 	list(textBegin, textLines);
306 	MSG0("[fig title]");
307 	figTitle(textBegin, textLines);
308 #ifdef	PICTURE
309 	MSG0("[picture]");
310 	applyOnRegion2(textBegin, textLines, 0, markIfPicture);
311 	applyOnSpaced(textBegin, textLines, markIfPicture);
312 #endif
313 	if (tableEnabled) {
314 		MSG0("[table]");
315 		applyOnRegion(textBegin, textLines, markIfTable);
316 	}
317 	MSG0("[justified]");
318 	justified(textBegin, textLines);
319 	MSG0("[example]");
320 	applyOnRegion(textBegin, textLines, markIfExample);
321 	MSG0("[section]");
322 	section(textBegin, textLines, 1);
323 	MSG0("[plaintext]");
324 	plainText(textBegin, textLines);
325 	joinBlocks(textBegin, textLines, TB_EXAMPLE);
326 	joinBlocks(textBegin, textLines, TB_PICTURE);
327 	joinBlocks(textBegin, textLines, TB_CENTER);
328 	makeTitledBlock(textBegin, textLines);
329 	fixListRegion(textBegin, textLines);
330 	MSG0("\n");
331 	if (renumber)
332 		renumDocument();
333 	else
334 		outputDocument();
335 #ifdef	DEBUG
336 	{
337 		int	i;
338 		for (i = textBegin; i < textLines; i++)
339 			if (texts[i]->printed == 0)
340 				fprintf(stderr, "ERROR(Not Printed:%d)%s\n",
341 					i, texts[i]->body);
342 	}
343 #endif
344 	freeAll();
345 }
freeAll()346 freeAll()
347 {
348 	int	l = 1;
349 	int	i;
350 	struct	textBlock	*tbp;
351 	while (l <= textLines) {
352 		if (tbp = texts[l]->block) {
353 			for (i = l; i < tbp->rend; i++) {
354 				free((char *)texts[i]->body);
355 				free((char *)texts[i]);
356 			}
357 			l = tbp->rend;
358 			free((char *)tbp);
359 		}
360 		else
361 			l++;
362 	}
363 	free((char *)texts);
364 }
365 #define	OUTPUT_OPTION(opt) {\
366 	if (!acceptOutOption) {\
367 		illegopt=opt;\
368 		goto dontOutOpt;\
369 	}\
370  }\
371 
getOption(xargc,xargv)372 getOption(xargc, xargv)
373 int	xargc;
374 char	**xargv;
375 {
376 	int	c;
377 	char	*illegopt;
378 	optind = 1;
379 	while ((c = getopt(xargc, xargv,
380 			   "X:j:l:s:vd:f:r:a:c:i:k:h:t:e:p:v:n:m:o:")) != -1)
381 		switch (c) {
382 		    case 'j':
383 #if	INTERNAL_CODE == CODE_EUC
384 			if (strcmp(optarg, "is") == 0) {
385 				OUTPUT_OPTION("-jis");
386 				outputCode = CODE_JIS;
387 			}
388 			else
389 #endif
390 		    /* Add Nide (need jverb,sty to use this option) */
391 			if (strcmp(optarg, "verb") == 0) {
392 				OUTPUT_OPTION("-jverb");
393 				useJverb = 1;
394 			}
395 			else
396 		    /* Add Nide end */
397 				goto usage;
398 			break;
399 		    case 'l':
400 			if (strncmp(optarg, "istd", 4) == 0) {
401 				OUTPUT_OPTION("-listd");
402 				listDecor = 1;
403 			}
404 			break;
405 		    case 's':
406 #if	INTERNAL_CODE == CODE_EUC
407 			if (strcmp(optarg, "jis") == 0) {
408 				OUTPUT_OPTION("-sjis");
409 				outputCode = CODE_SJIS;
410 				inputCode  = CODE_SJIS;
411 			}
412 			else if (strcmp(optarg, "trict") == 0) {
413 					stflag = 0;
414 			}
415 #endif
416 				if (strcmp(optarg, "pace") == 0) {
417 					OUTPUT_OPTION("-space");
418 					reflectSpace = 1;
419 				}
420 				else if (strcmp(optarg, "trict") == 0) {
421 					stflag = 0;
422 				}
423 				else goto usage;
424 			break;
425 		    case 'e':
426 #if	INTERNAL_CODE == CODE_EUC
427 			if (strcmp(optarg, "uc") == 0) {
428 				OUTPUT_OPTION("-euc");
429 				outputCode = CODE_EUC;
430 			}
431 			else
432 #endif
433 				if (strncmp(optarg, "xam=", 4) == 0) {
434 					examFactor = atoi(optarg+4);
435 					if (examFactor < 0 || examFactor >100){
436 						goto usage;
437 					}
438 				}
439 				else goto usage;
440 			break;
441 		    case 'v':
442 			OUTPUT_OPTION("-v");
443 			verbose = 1;
444 			break;
445 		    case 'p':
446 			if (strcmp(optarg, "re") == 0) {
447 				OUTPUT_OPTION("-pre");
448 				preamble = 1;
449 			}
450 			else if (strncmp(optarg, "t=", 2) == 0) {
451 				if ((fontSize = atoi(optarg + 2)) == 0)
452 					goto usage;
453 				fontSpecified = 1;
454 			}
455 			else goto usage;
456 			break;
457 		    case 'm':
458 			if (*optarg == 's') {
459 				OUTPUT_OPTION("-ms");
460 				roffMacro = MS_MACRO;
461 				put = &roffPut;
462 			}
463 			else if (*optarg == 'm') {
464 				OUTPUT_OPTION("-mm");
465 				roffMacro = MM_MACRO;
466 				put = &roffPut;
467 			}
468 			else	goto usage;
469 			break;
470 		    case 'r':
471 			if (strcmp(optarg, "aw") == 0) {
472 				OUTPUT_OPTION("-raw");
473 				rawOutput = 1;
474 			}
475 			else if (strcmp(optarg, "enum") == 0) {
476 				OUTPUT_OPTION("-renum");
477 				renumber = 1;
478 				preamble = 0;
479 			}
480 			else if (strcmp(optarg, "off") == 0) {
481 				OUTPUT_OPTION("-roff");
482 				put = &roffPut;
483 			}
484 			else if (strncmp(optarg, "mpage", 4) == 0)
485 				removePaging = 1;
486 			else if (strcmp(optarg, "ef") == 0) {
487 				crossRefer = 1;
488 			}
489 			else	goto usage;
490 			break;
491 		    case 'f':
492 			macroName = optarg;
493 			break;
494 		    case 'a':
495 			if (strcmp(optarg, "cursec") == 0) {
496 				OUTPUT_OPTION("-acursec");
497 				accurateSecnum = 1;
498 			}
499 			else	goto usage;
500 			break;
501 		    case 'i':
502 			if (strcmp(optarg, "ndsec") == 0) {
503 				indentedSecnum = 1;
504 			}
505 			else if (strcmp(optarg, "nline") == 0) {
506 				inlineHint = 1;
507 			}
508 			else	goto usage;
509 			break;
510 		    case 'k':
511 #ifdef	KANJI
512 			if (strncmp(optarg, "table", 5) == 0) {
513 				jisTableEnabled = 1;
514 			}
515 			else
516 #endif
517 				goto usage;
518 			break;
519 		    case 'h':
520 			if (strcmp(optarg, "alfraw") == 0) {
521 				OUTPUT_OPTION("-alfraw");
522 				halfCooked = 1;
523 			}
524 #ifdef HTML
525 			else if (strcmp(optarg, "tmlonce") == 0) {
526 				OUTPUT_OPTION("-htmlonce");
527 				htmlOnce = 1;
528 				put = &htmlPut;
529 			}
530 			else if (strcmp(optarg, "tml") == 0) {
531 				OUTPUT_OPTION("-html");
532 				htmlOnce = 0;
533 				put = &htmlPut;
534 			}
535 			else if (strcmp(optarg, "ere") == 0) {
536 				OUTPUT_OPTION("-here");
537 				htmlHere = 1;
538 			}
539 #endif
540 			else	goto usage;
541 			break;
542 		    case 't':
543 			if (strncmp(optarg, "able=", 5) == 0) {
544 				if ((tableFactor = atoi(optarg+5)) == 0)
545 					tableEnabled = 0;
546 				if (tableFactor < 0 || tableFactor > 100) {
547 					goto usage;
548 				}
549 			}
550 			else if (strcmp(optarg, "exq") == 0) {
551 				OUTPUT_OPTION("-texq");
552 				texQuote = 1;
553 				put = &texPut;
554 			}
555 			else if (strcmp(optarg, "ex") == 0) {
556 				OUTPUT_OPTION("-tex");
557 				put = &texPut;
558 			}
559 			else if (strncmp(optarg, "style=", 6) == 0) {
560 				OUTPUT_OPTION("-tstyle");
561 				texStyle = strsave(optarg + 6);
562 			}
563 			else	goto usage;
564 			break;
565 		    case 'n':
566 			if (strcmp(optarg, "opre") == 0) {
567 				OUTPUT_OPTION("-nopre");
568 				preamble = 0;
569 			}
570 			else if (strcmp(optarg, "ospace") == 0) {
571 				OUTPUT_OPTION("-nospace");
572 				reflectSpace = 0;
573 			}
574 			else if (strcmp(optarg, "oacursec") == 0) {
575 				OUTPUT_OPTION("-noacursec");
576 				accurateSecnum = 0;
577 			}
578 			else if (strcmp(optarg, "olistd") == 0) {
579 				OUTPUT_OPTION("-nolistd");
580 				listDecor = 0;
581 			}
582 			else if (strcmp(optarg, "oinline") == 0) {
583 				inlineHint = 0;
584 			}
585 			else goto usage;
586 			break;
587 #ifdef	DEBUG
588 		    case 'd':
589 			if ((debug = atoi(optarg)) == 0)
590 				goto usage;
591 			break;
592 #endif
593 		    case '?':
594 		    usage:
595 			return -1;
596 		    dontOutOpt:
597 			fprintf(stderr,
598 				"ERROR: Output option \"%s\" ignored.\n", illegopt);
599 			return -1;
600 		}
601 	return 0;
602 }
603 /*
604  * Build "argc", "argv[]" from string and call getOption
605  */
606 #define	MAX_ARGC	32
optionLine(s)607 optionLine(s)
608 char	*s;
609 {
610 	static	int	xargc;
611 	static	char	*xargv[MAX_ARGC];
612 	int	inStr;
613 	inStr = 0;
614 	xargc = 1;
615 	while(*s) {
616 		if (!inStr && !isspace(*s)) {
617 			xargv[xargc] = s;
618 			xargc++;
619 			if (xargc >= MAX_ARGC) {
620 				(void)fprintf(stderr, "Too many options\n");
621 				return -1;
622 			}
623 			inStr = 1;
624 		}
625 		if (isspace(*s)) {
626 			*s = '\0';
627 			inStr = 0;
628 		}
629 		s++;
630 	}
631 	xargv[0] = "";
632 	if (getOption(xargc, xargv)
633 	    || optind < xargc)
634 		return -1;
635 	return 0;
636 }
637 /*
638  * Get option from Environment variable
639  */
envOption()640 envOption()
641 {
642 	char	*plainEnv;
643 	char	buf[MAX_LINE_LEN];
644 	FILE	*initf;
645 	if ((plainEnv = getenv(PLAIN2_ENV)) == NULL)
646 		return 0;
647 	if ((initf = fopen(plainEnv, "r")) == NULL) {
648 		char	envOpt[MAX_LINE_LEN];
649 		strcpy(envOpt, plainEnv);
650 		if (optionLine(envOpt)) {
651 			(void)fprintf(stderr,
652 				      "Illegal option in Environment %s\n",
653 				      PLAIN2_ENV);
654 			(void)fprintf(stderr,"%s\n", plainEnv);
655 			exit(1);
656 		}
657 	}
658 	else {
659 		int	line = 1;
660 		while (fgets(buf, MAX_LINE_LEN, initf) != NULL) {
661 			line++;
662 			if (optionLine(buf)) {
663 				(void)fprintf(stderr,
664 					      "illegal option in file %s at line %d\n",
665 					      plainEnv, line);
666 				(void)fprintf(stderr,"%s\n", buf);
667 				exit(1);
668 			}
669 		}
670 		fclose(initf);
671 	}
672 	return 0;
673 }
674 /*
675  * Save & Restore Parameters for Parsing
676  */
677 static int defJapaneseText;
678 static int defTableEnabled;
679 static int defJisTableEnabled;
680 static int defIndentedSecnum ;
681 static int defRawOutput;
682 static int defTableFactor;
683 static int defExamFactor;
684 /*
685  * Parsing paramters
686  *	1) Environment (from Env. variable itself  or from the specified file)
687  *	2) Command argument option
688  *
689  * And "option" line of each files
690  */
saveParseDefaults()691 saveParseDefaults()
692 {
693 	defJapaneseText	   = japaneseText;
694 	defTableEnabled	   = tableEnabled;
695 	defJisTableEnabled = jisTableEnabled;
696 	defIndentedSecnum  = indentedSecnum;
697 	defRawOutput	   = rawOutput;
698 	defTableFactor	   = tableFactor;
699 	defExamFactor	   = examFactor;
700 }
restoreParseDefaults()701 restoreParseDefaults()
702 {
703 	japaneseText	= defJapaneseText;
704 	tableEnabled	= defTableEnabled;
705 	jisTableEnabled = defJisTableEnabled;
706 	indentedSecnum	= defIndentedSecnum;
707 	rawOutput	= defRawOutput;
708 	tableFactor	= defTableFactor;
709 	examFactor	= defExamFactor;
710 }
711 
712