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