comparison help2html/mhh6.syn @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 /*
2 * October 30, 2007. mhh6: use C, not C++.
3 *
4 * Sept 5, 2006. mhh5.syn modified for XML_OUTPUT option.
5 *
6 * June 20, 2001. mhh5.syn
7 * Modifying mhh4 to create HTML output
8 * (mhh4 sorts a help.src file case-insensitively by title line while
9 * cleaning it up a bit.)
10 *
11 * June 16 2001
12 * Unlike mhh3b, mhh4 stores and sorts title *lines*, not titles,
13 * from help.src. Another AgStringDirectory has been added to hold
14 * topic bodies.
15 *
16 * Change mhh3b.syn to store title lines in string dicts.
17 * Change mhh3a.syn to use AgStringDictionary for titles.
18 * Jun 8/01 Change mhh3.syn to add main and some reduc. procedures
19 *
20 * June 8, 2001 - mhh3.syn now parses Jerry's current help.src (b8)
21 * with no conflicts or keyword anomalies but spaces (and tabs) are
22 * not allowed in blank lines. Why the eof line tolerates spaces is
23 * something of a mystery.
24 */
25
26 // -- CONFIGURATION SECTION ----------------------------
27 [
28 pointer input
29 no cr // no carr. ret. in output parser
30 parser file name = "#.c"
31 line numbers
32 ]
33 //------------------------------------------------------
34
35
36 eof = 0
37 char = ~eof
38 lead title char = char - blank - tab - ',' - bullet - '\n' - '\r'
39 title char = char - ',' - bullet - '\n' - '\r'
40 lead topic char = char - blank - tab - bullet - '\n' - '\r'
41 text char = char - bullet - '\n' - '\r'
42 table char = char - tab - '\n' - '\r'
43
44 blank = 0x20
45 tab = 9
46 bullet = 7
47
48 //blank line
49 // -> blank?..., '\n'
50 blank line
51 -> '\n' /* Don't allow spaces in line */
52 -> '\r','\n'
53
54 eof line
55 -> blank?..., eof
56
57 eol
58 -> '\n'
59 -> '\r','\n'
60
61 (void) help sourcefile $ // ** Grammar token **
62 -> topic..., blank line?, eof line
63
64
65 topic
66 -> blank line?..., title line, eol, blank line?..., topic lines,
67 end topic
68
69 title line
70 -> title line too = {
71 title_line_count++;
72 // buffer_append(&titleLine, "</h3>\n<p>");
73 saveTitleLine();
74 }
75
76 title line too
77 -> title = title_count++, putTitle();
78 -> title line too, ',', blank?..., title = title_count++, appendTitle();
79
80 title
81 -> lead title char:c =
82 buffer_start(&title, c), buffer_start(&title1, toupper(c));
83 -> title, title char:c =
84 buffer_add(&title, c), buffer_add(&title1, toupper(c));
85
86 end topic
87 -> "##", blank?..., eol
88 -> "\n##", blank?..., eol
89 -> "\r\n##", blank?..., eol
90
91 topic lines
92 -> topic lines too = { saveTopicBody(); }
93
94 topic lines too
95 -> text parag =buffer_append(&topicBody,"\n");
96 -> topic lines too, blank line..., parag=buffer_append(&topicBody,"\n");
97
98 parag
99 -> text parag
100 -> table parag
101 -> list1 parag = finishList(Tlist1);
102 -> list2 parag = finishList(Tlist2);
103 -> listtab parag = finishList(Tlisttab);
104 -> code parag
105
106
107 text parag
108 -> partial text parag
109 -> partial text parag, table parag
110 -> text block, list1 parag = finishList(Tlist1);
111 -> text block, listtab parag = finishList(Tlisttab);
112 -> text block, code parag
113 -> text block, code parag, text block
114
115
116 partial text parag
117 -> text block
118 -> partial text parag, table parag, text block
119
120
121
122 text block
123 -> !buffer_append(&topicBody, "<p>");,
124 first text line, other text line?... =
125 buffer_append(&topicBody, "</p>");
126
127
128 table parag
129 -> table parag too = buffer_append(&topicBody, "\n</table>\n\n");
130
131 table parag too
132 -> first table line
133 -> table parag too, other table line
134
135
136 list1 parag
137 -> list1 block, list1 block?...
138
139 list1 block
140 -> first list1 line, other list1 line?... =
141 buffer_append(&topicBody, "</li>\n");
142 -> first list1 line, other list1 line?..., table parag =
143 buffer_append(&topicBody, "</li>\n");
144 -> first list1 line, other list1 line?..., code parag =
145 buffer_append(&topicBody, "</li>\n");
146
147
148 list2 parag
149 -> first list2 line, other list2 line?... =
150 buffer_append(&topicBody, "</li>\n");
151
152 listtab parag
153 -> listtab block, listtab block?...
154
155 listtab block
156 -> first listtab line, other listtab line?... =
157 buffer_append(&topicBody, "</li>\n");
158 -> first listtab line, other listtab line?..., table parag =
159 buffer_append(&topicBody, "</li>\n");
160
161 code parag
162 -> code parag too =
163 buffer_append(&topicBody, "\n</pre>");
164
165 code parag too
166 -> first code line
167 -> code parag too, other code line
168
169
170 first text line
171 -> lead topic char:c, text frag?, eol = {
172 total1sttextline++;
173 appendEnd(c);
174 }
175 -> blank, lead topic char:c, text frag?,eol = {
176 total1sttextlineb++;
177 buffer_add(&topicBody, 0x20);
178 appendEnd(c);
179 }
180 other text line
181 -> lead topic char:c, text frag?, eol = appendEnd(c);
182
183
184 //################# OLD ####################################################
185 //first table line
186 // -> tab seq, blank seq?, lead topic char:c, text frag?, '\n' = {
187 // total1sttableline++;
188 // buffer_append(&topicBody, "\n<pre> ");
189 // appendEnd(c);
190 // buffer_clear(&tabFrag);
191 // buffer_clear(&blankFrag);
192 // }
193 //
194 //other table line
195 // -> tab seq, blank seq?, lead topic char:c, text frag?, '\n' = {
196 // buffer_append(&topicBody, " ");
197 // appendEnd(c);
198 // buffer_clear(&tabFrag);
199 // buffer_clear(&blankFrag);
200 // }
201 //############################################################################
202
203
204
205
206 first table line
207 -> first table line body, eol =
208 buffer_append(&topicBody, "</td></tr>");
209
210 first table line body
211 -> tab seq, blank seq?, lead topic char:c, table frag? = {
212 total1sttableline++;
213 buffer_append(&topicBody,
214 "\n\n<table cellpadding=\"7\" cellspacing=\"2\" >\n<tr><td> ");
215 appendTableCell(c);
216 buffer_clear(&tabFrag);
217 buffer_clear(&blankFrag);
218 }
219
220 -> first table line body, tab seq, blank seq?, lead topic char:c,
221 table frag? = {
222 buffer_append(&topicBody, "</td>\n<td> ");
223 appendTableCell(c);
224 buffer_clear(&tabFrag);
225 buffer_clear(&blankFrag);
226 }
227
228 other table line
229 -> other table line body, eol =
230 buffer_append(&topicBody, "</td></tr>");
231
232 other table line body
233 -> tab seq, blank seq?, lead topic char:c, table frag? = {
234 buffer_append(&topicBody, "\n\n<tr><td> ");
235 appendTableCell(c);
236 buffer_clear(&tabFrag);
237 buffer_clear(&blankFrag);
238 }
239
240 -> other table line body, tab seq, blank seq?, lead topic char:c,
241 table frag? = {
242 buffer_append(&topicBody, "</td>\n<td> ");
243 appendTableCell(c);
244 buffer_clear(&tabFrag);
245 buffer_clear(&blankFrag);
246 }
247
248
249
250 first list1 line
251 -> bullet, blank, lead topic char:c, text frag?, eol = {
252 total1stlist1line++;
253 if (intstack_top(&paragType) != Tlist1) {
254 intstack_push(&paragType, Tlist1);
255 buffer_append(&topicBody, "\n<ul>");
256 }
257 buffer_append(&topicBody, "\n<li>");
258 buffer_add(&topicBody, 0x20);
259 appendEnd(c);
260 }
261
262 other list1 line
263 -> lead topic char:c, text frag?, eol = appendEnd(c);
264
265
266 first list2 line
267 -> bullet, blank, blank, lead topic char:c, text frag?, eol = {
268 total1stlist2line++;
269 if (intstack_top(&paragType) != Tlist2) {
270 intstack_push(&paragType, Tlist2);
271 buffer_append(&topicBody, "\n<ul>");
272 }
273 buffer_append(&topicBody, "\n<li>");
274 buffer_append(&topicBody, " ");
275 appendEnd(c);
276 }
277
278 other list2 line
279 -> lead topic char:c, text frag?, eol = appendEnd(c);
280
281
282 first listtab line
283 -> bullet, tab:t, lead topic char:c, text frag?, eol = {
284 total1stlisttabline++;
285 if (intstack_top(&paragType) != Tlisttab) {
286 intstack_push(&paragType, Tlisttab);
287 buffer_append(&topicBody, "\n<ul>");
288 }
289 buffer_append(&topicBody, "\n<li>");
290 buffer_add(&topicBody, t);
291 appendEnd(c);
292 }
293
294 other listtab line
295 -> lead topic char:c, text frag?, eol = appendEnd(c);
296
297
298
299 first code line
300 -> " ", lead topic char:c, text frag?, eol = {
301 total1stcodeline++;
302 buffer_append(&topicBody, "\n<pre> ");
303 appendEnd(c);
304 }
305 -> " ", lead topic char:c, text frag?, eol = {
306 total1stcodeline++;
307 buffer_append(&topicBody, "\n<pre> ");
308 appendEnd(c);
309 }
310 -> " ", lead topic char:c, text frag?, eol = {
311 total1stcodeline++;
312 buffer_append(&topicBody, "\n<pre> ");
313 appendEnd(c);
314 }
315 -> " ", lead topic char:c, text frag?, eol = {
316 total1stcodeline++;
317 buffer_append(&topicBody, "\n<pre> ");
318 appendEnd(c);
319 }
320 -> " ", lead topic char:c, text frag?, eol = {
321 total1stcodeline++;
322 buffer_append(&topicBody, "\n<pre> ");
323 appendEnd(c);
324 }
325 -> " ", lead topic char:c, text frag?, eol = {
326 total1stcodeline++;
327 buffer_append(&topicBody, "\n<pre> ");
328 appendEnd(c);
329 }
330 -> " ", lead topic char:c, text frag?, eol = {
331 total1stcodeline++;
332 buffer_append(&topicBody, "\n<pre> ");
333 appendEnd(c);
334 }
335
336
337 other code line
338 -> " ", lead topic char:c, text frag?, eol = {
339 buffer_append(&topicBody, " ");
340 appendEnd(c);
341 }
342 -> " ", lead topic char:c, text frag?, eol = {
343 buffer_append(&topicBody, " ");
344 appendEnd(c);
345 }
346 -> " ", lead topic char:c, text frag?, eol = {
347 buffer_append(&topicBody, " ");
348 appendEnd(c);
349 }
350 -> " ", lead topic char:c, text frag?, eol = {
351 buffer_append(&topicBody, " ");
352 appendEnd(c);
353 }
354 -> " ", lead topic char:c, text frag?, eol = {
355 buffer_append(&topicBody, " ");
356 appendEnd(c);
357 }
358 -> " ", lead topic char:c, text frag?, eol = {
359 buffer_append(&topicBody, " ");
360 appendEnd(c);
361 }
362 -> " ", lead topic char:c, text frag?, eol = {
363 buffer_append(&topicBody, " ");
364 appendEnd(c);
365 }
366
367 text frag
368 -> text char:c = buffer_start(&topicFrag, c);
369 -> text frag, text char:c = buffer_add(&topicFrag, c);
370
371 table frag
372 -> table char:c = buffer_start(&topicFrag, c);
373 -> table frag, table char:c = buffer_add(&topicFrag, c);
374
375
376 tab seq
377 -> tab:t = buffer_start(&tabFrag, t);
378 -> tab seq, tab:t = buffer_add(&tabFrag, t);
379
380 blank seq
381 -> blank = buffer_start(&blankFrag, 0x20);
382 -> blank seq, blank = buffer_add(&blankFrag, 0x20);
383
384
385
386
387 { /* ----- Embedded C --------------------------------------------*/
388
389
390 #include <stdio.h>
391 #include <string.h>
392 #include <malloc.h>
393 #include <assert.h>
394 #include <ctype.h>
395 #include <assert.h>
396 #include <err.h>
397 #include "uintarray.h"
398 #include "support.h"
399 #include "buffer.h"
400 #include "stringdict.h"
401 #include "must.h"
402
403 int verbose = 0;
404
405 int total1sttextline = 0;
406 int total1sttextlineb = 0;
407 int total1sttableline = 0;
408 int total1stlist1line = 0;
409 int total1stlist2line = 0;
410 int total1stlisttabline = 0;
411 int total1stcodeline = 0;
412
413 int title_count =0;
414 int title_line_count = 0;
415
416 char *helpentStr;
417 struct buffer title;
418 struct buffer title1;
419 struct buffer titleLine;
420 struct buffer titleLine1;
421 struct stringdict *titleDict;
422 struct stringdict *titleDict1; // upper case
423 struct stringdict *titleLineDict;
424 struct stringdict *titleLineDict1; // upper case
425 struct buffer topicFrag;
426 struct buffer tabFrag;
427 struct buffer blankFrag;
428 struct buffer topicBody;
429 struct stringdict *topicBodyDict;
430 struct uintarray titleToTitleLine;
431 struct intstack paragType;
432
433 enum paragTypes {Tnone=0, Ttext=1, Ttable=2, Tlist1=3, Tlist2=4,
434 Tlisttab=5, Tcode=6};
435
436 char *charToEntity(const char *instring);
437 void putTitle(void);
438 void appendTitle(void);
439 void saveTitleLine(void);
440 void appendEnd(int c);
441 void removeFinalNewline(void);
442 void saveTopicBody(void);
443 void printDict(const struct stringdict *dictionary);
444 void writeSortedHtml(FILE *output);
445 void writeFullTopics(FILE *output, const struct stringdict *dictionary,
446 const struct stringdict *dictionary1,
447 const struct stringdict *dictionaryb);
448 void writeTitles(FILE *output, const struct stringdict *dictionary,
449 const struct stringdict *dictionary1);
450 int processLinkString(FILE *filein, FILE *fileout);
451
452
453 // replace &, <, > in S with entities
454 char *charToEntity(const char *s) {
455 char *ret;
456 int i, j, len=0;
457
458 for (i=0; s[i]; i++) {
459 if (s[i] == '&') len += 5; /* &amp; */
460 else if (s[i] == '<') len += 4; /* &lt; */
461 else if (s[i] == '>') len += 4; /* &gt; */
462 else len++;
463 }
464
465 ret = malloc(len+1);
466 if (!ret) {
467 errx(1, "Out of memory");
468 }
469
470 for (i=j=0; s[i]; i++) {
471 if (s[i] == '&') { strcpy(ret+j, "&amp;"); j += 5; }
472 else if (s[i] == '<' ) { strcpy(ret+j, "&lt;"); j += 4; }
473 else if (s[i] == '>' ) { strcpy(ret+j, "&gt;"); j += 4; }
474 else ret[j++] = s[i];
475 }
476 ret[j] = 0;
477
478 return ret;
479 }
480
481 // Save title both ways, make map entry for title<--->title line
482 void saveTitle(void) {
483 if (stringdict_exists(titleDict, title.text)) {
484 fprintf( stderr, "Warning: Repeated title %s\n", title.text );
485 }
486 #if 0
487 else if (!strcmp(title.text, "Secret of Life")) {
488 // Do not save "Secret of Life" title
489 return;
490 }
491 #endif
492 else {
493 // Save title in dictionary
494 unsigned titleIndex = stringdict_intern(titleDict, title.text);
495
496 // Save title in upper case dictionary
497 stringdict_intern(titleDict1, title1.text);
498
499 // count() should give next index
500 unsigned titleLineIndex = stringdict_count(titleLineDict);
501
502 // use an array for this (the keys are array indexes anyway)
503 if (titleIndex >= uintarray_num(&titleToTitleLine)) {
504 unsigned x, old = uintarray_num(&titleToTitleLine);
505 uintarray_setsize(&titleToTitleLine, titleIndex+1);
506 for (x=old; x<titleIndex; x++) {
507 uintarray_set(&titleToTitleLine, x, (unsigned) -1);
508 }
509 }
510 // Store indices in map
511 uintarray_set(&titleToTitleLine, titleIndex, titleLineIndex);
512 }
513 }
514
515
516 void putTitle(void) {
517 // Save title itself in both reg. and upper case title dicts
518 saveTitle();
519 buffer_append(&titleLine, title.text);
520 buffer_append(&titleLine1, title1.text);
521 }
522
523
524 void appendTitle() {
525 // Save title itself in both reg. and upper case title dicts
526 saveTitle();
527 buffer_append(&titleLine, ", ");
528 buffer_append(&titleLine1, ", ");
529 buffer_append(&titleLine, title.text);
530 buffer_append(&titleLine1, title1.text);
531 }
532
533
534 void saveTitleLine() {
535 #if 0
536 static int foundSoL=0;
537 if (stringdict_count(titleLineDict)==0 &&
538 strcmp(titleLine.text, "Secret of Life")!=0 && foundSoL==0) {
539 fprintf(stderr, "Warning: Secret of Life does not lead file!\n");
540 }
541 #endif
542
543 #if 0
544 if (!strcmp(titleLine.text, "Secret of Life")) {
545 // Don't save title line in dicts.
546 // Should be at beginning of help file
547 assert(stringdict_count(titleLineDict)==0);
548 foundSoL = 1;
549 if (verbose) {
550 printf( "\n Found Secret of Life!\n\n" );
551 }
552 }
553 else
554 #endif
555 if ( stringdict_exists(titleLineDict, titleLine.text) ) {
556 fprintf( stderr, "Warning: Repeated title line %s\n",
557 titleLine.text );
558 }
559 else {
560 // Save title line in dictionary
561 stringdict_intern(titleLineDict, titleLine.text);
562 // Save title line in upper case dictionary
563 stringdict_intern(titleLineDict1, titleLine1.text);
564 }
565 buffer_clear(&titleLine);
566 buffer_clear(&titleLine1);
567 }
568
569
570 // Append the latter part of the line
571 void appendEnd(int c) {
572 buffer_add(&topicBody, c);
573 buffer_append(&topicBody, topicFrag.text);
574 buffer_append(&topicBody, "\n" );
575 buffer_clear(&topicFrag);
576 }
577
578 // Append a cell to the table row
579 void appendTableCell(int c) {
580 // Could insert <pre> </pre> or <code> </code> tags here for cell
581 buffer_append(&topicBody, "<code> " );
582 buffer_add(&topicBody, c);
583 buffer_append(&topicBody, topicFrag.text);
584 buffer_append(&topicBody, "</code>" );
585 //buffer_append(&topicBody, "\n" );
586 buffer_clear(&topicFrag);
587 }
588
589 void removeFinalNewline(void) {
590 int x = topicBody.len;
591 assert(topicBody.text[x-2]=='\n' && topicBody.text[x-1]=='\n');
592 topicBody.text[x-1] = 0;
593 }
594
595 void saveTopicBody(void) {
596 #if 0
597 // do not save Secret of Life topic body
598 if (stringdict_count(titleLineDict) != 0) {
599 #endif
600 // save topic body
601 stringdict_intern(topicBodyDict, topicBody.text);
602 #if 0
603 }
604 #endif
605 buffer_clear(&topicBody);
606 }
607
608 /*
609 void startTable(void) {
610 // If we don't currently have table, start a new one
611 if (paragType.top() != Ttable) {
612 // Start table
613 paragType.push( Ttable );
614 }
615 }
616 */
617
618 void finishList(int listtype){
619 //printf( "\nfinishList() - top type = %d, listtype = %d, "
620 // "stack size = %d\n"
621 // " titleLineDict size = %d\n",
622 // paragType.top(), listtype, paragType.size(),
623 // titleLineDict.size() );
624 assert(intstack_top(&paragType) == listtype);
625 intstack_pop(&paragType);
626 buffer_append(&topicBody, "\n</ul>");
627 }
628
629 void printDict(const struct stringdict *dictionary) {
630 unsigned i;
631 for (i=0; i<stringdict_count(dictionary); i++) {
632 printf("%4d: %s\n", i, stringdict_getbynum(dictionary, i));
633 }
634 }
635
636 char *SqueezeWS(const char *Input) {
637 /* return a (strdup()-like) copy of Input, with whitespace squeezed out */
638 char *copy;
639 int cnt, outcnt;
640
641 copy = must_malloc(strlen(Input)+1);
642
643 for (cnt=0, outcnt=0; Input[cnt]; cnt++) {
644 unsigned char ch = Input[cnt];
645 if (!isspace(ch)) {
646 copy[outcnt]=ch;
647 outcnt++;
648 }
649 }
650 copy[outcnt]=0;
651
652 return copy;
653 }
654
655 void writeFullTopics(FILE *output,
656 const struct stringdict *dictionary, /* title lines */
657 const struct stringdict *dictionary1, /* UC titlelines*/
658 const struct stringdict *dictionaryb) /* topic bodies */
659 {
660 unsigned i;
661
662 #if 0
663 /* Write "Secret of Life" topic at beginning of topics */
664 //fprintf(output, "Secret of Life>\n\n");
665 //fprintf(output, "No help message for this topic.\n##\n");
666 #endif
667
668 assert( stringdict_count(dictionary) == stringdict_count(dictionary1) );
669 struct permutation *perm = mySort(dictionary1); // Sort dictionary1
670
671
672 /* Write out topics in a definition list <dl> */
673 fprintf( output, "\n\n<dl>\n\n" );
674
675 // write dictionary, sorted according to dict1
676 for (i = 0; i < stringdict_count(dictionary); i++) {
677 //fprintf(output, "<dt><b><a name=\"%04d\">%s</a></b></dt>\n"
678 // "<dd>%s\n</dd><br/>\n\n",
679 // perm->v[i],
680 // stringdict_getbynum(dictionary, perm->v[i]),
681 // stringdict_getbynum(dictionaryb, perm->v[i]) );
682
683 char *anchorname=SqueezeWS(stringdict_getbynum(dictionary, perm->v[i]));
684 fprintf(output, "<dt><b><a name=\"%s\">%s</a></b></dt>\n"
685 "<dd>%s\n</dd>\n\n",
686 anchorname,
687 stringdict_getbynum(dictionary, perm->v[i]),
688 stringdict_getbynum(dictionaryb, perm->v[i]) );
689 free(anchorname);
690 }
691 fprintf( output, "\n\n</dl>\n\n" );
692 permutation_destroy(perm);
693 }
694
695 void writeTitles(FILE *output,
696 const struct stringdict *dictionary, /* titles */
697 const struct stringdict *dictionary1) /* uppercase titles */
698 {
699 assert( stringdict_count(dictionary) == stringdict_count(dictionary1) );
700 struct permutation *perm = mySort(dictionary1); // Sort dictionary1
701
702 /* Write 2-column table of titles */
703 /*
704 // n_t is true title count w/o Secret of Life
705 int n_t = stringdict_count(dictionary);
706 // we better have some titles
707 assert( n_t >= 2 );
708 // n_t1 is #titles in 1st column
709 int n_t1 = n_t%2 ? n_t/2 +1 : n_t/2;
710 // n_t2 is #titles in 2nd column
711 int n_t2 = n_t%2;
712 int i;
713 fprintf( output, "\n\n<table width=\"100%%\" "
714 "style=\"margin-left: auto ; margin-right: auto\" \n"
715 " cellpadding=\"15\" cellspacing=\"5\" >\n"
716 "<tr align=\"left\">\n"
717 "<td valign=\"top\" style=\"white-space: nowrap\">"
718 "\n\n\n");
719
720 // Write out dictionary sorted acc. to dictionary1
721 // write out the first half, sorted
722 for (i = 0; i < n_t1; i++) {
723 fprintf(output, " \xA9%s\xAA\n<br/>",
724 stringdict_getbynum(dictionary, perm->v[i]));
725 }
726
727 fprintf(output, "</td>\n\n");
728 fprintf(output, "<td valign=\"top\" style=\"white-space: nowrap\">\n\n");
729
730 // write out the last half, sorted
731 for ( i = n_t1; i < n_t; i++) {
732 fprintf(output, " \xA9%s\xAA\n<br/>",
733 stringdict_getbynum(dictionary, perm->v[i]));
734 }
735
736 fprintf(output, "</td>\n</tr>\n</table>\n\n<hr><br/><br/>\n\n" );
737 */
738
739 /* Write 1-column list of titles */
740
741 // n_t is true title count w/o Secret of Life
742 unsigned n_t = stringdict_count(dictionary);
743 // we better have some titles
744 assert( n_t >= 2 );
745 unsigned i;
746
747 fprintf(output, "<h2>Help Topic Index</h2>\n\n" );
748 // Write out the index, sorted acc. to dictionary1
749 for (i = 0; i < n_t; i++) {
750 fprintf(output, "\xA9%s\xAA\n<br/>",
751 stringdict_getbynum(dictionary, perm->v[i]));
752 }
753 }
754
755 void writeSortedHtml( FILE *output ) {
756 /* Leading HTML */
757
758 #ifdef XML_OUTPUT
759 fprintf(output, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
760 "<?xml-stylesheet type=\"text/xsl\" href=\"../ag_web.xml\"?>\n"
761 "\n"
762 "<body rootdir=\"..\" navname=\"Documentation: AnaGram Help\">\n");
763
764 #else
765 fprintf(output, "<html>\n<head>\n");
766 fprintf(output, "<title>AnaGram Help Topics - HTML version</title>\n");
767 fprintf(output, "</head>\n\n\n");
768 fprintf(output, "<body bgcolor=\"#ffffff\" text=\"#000000\"");
769 fprintf(output, " link=\"#0033CC\" vlink=\"#CC0033\" alink=\"#CC0099\">");
770 fprintf(output, "\n\n\n");
771 #endif
772
773 /* Write page title */
774 #ifdef XML_OUTPUT
775 fprintf(output, "<h1>AnaGram Help</h1>\n\n");
776 #else
777 fprintf(output, "<hr><h2>AnaGram Help Topics - HTML Version</h2><hr>\n\n");
778 #endif
779 /* Write 2-column table of titles */
780 writeTitles( output, titleDict, titleDict1 );
781
782 /* Write full topics in single- column table */
783 //fprintf( output, "\n\n<table width=\"100%%\">\n<tr><td>\n<p>\n\n");
784 //writeFullTopics( output, titleLineDict, titleLineDict1, topicBodyDict );
785 //fprintf( output, "</td></tr>\n</table>\n" );
786
787 /* Write full topics directly to the output page */
788 writeFullTopics( output, titleLineDict, titleLineDict1, topicBodyDict );
789
790 #ifdef XML_OUTPUT
791 fprintf(output,"\n</body>\n");
792 #else
793 /* Ending HTML */
794 fprintf( output, "\n<p><br/><address><a "
795 "NAME=\"copyright\">AnaGram Help Topics, HTML version.</a>\n"
796 "<br> Copyright &copy; Parsifal Software, 2001.<br>\n"
797 "All Rights Reserved.</address>"
798 "\n\n</body>\n</html>\n\n" );
799 #endif
800 }
801
802 int processLinkString( FILE *filein, FILE *fileout ) {
803 struct buffer linkString; // lower case
804 struct buffer linkString1; // upper case version
805 unsigned index;
806 int c;
807 int wspaceFlag =0;
808
809 buffer_init(&linkString);
810 buffer_init(&linkString1);
811
812 while ( (c=fgetc(filein)) != EOF ) {
813
814 if ( c != 0xAA) { // test for end of link char
815 if ( c == 0x20 || c == 0x0D || c == 0x0A ) {
816 // don't append these chars
817 wspaceFlag = 1;
818 }
819 else {
820 if (wspaceFlag) {
821 // Replace space, cr, lf with single space
822 buffer_add(&linkString, 0x20);
823 buffer_add(&linkString1, toupper(0x20));
824 }
825 buffer_add(&linkString, c);
826 buffer_add(&linkString1, toupper(c));
827 wspaceFlag = 0;
828 }
829 }
830 else {
831 // end of link - look up using upper case string
832 if (!stringdict_exists(titleDict1, linkString1.text)) {
833 // try match w/o final S
834 if ( linkString1.text[linkString1.len - 1] == 'S' ) {
835 linkString1.text[linkString1.len - 1] = 0;
836 if (stringdict_exists(titleDict1, linkString1.text)) {
837 goto matched; // Eccch - a goto!
838 }
839 }
840
841 fprintf(stderr, "Can't find this link in titleDict1: %s\n",
842 linkString1.text);
843 return 21;
844 }
845
846 /* find corresp. index in title line direc. */
847 matched:
848
849 index = stringdict_findbyname(titleDict1, linkString1.text);
850
851 unsigned ilink = uintarray_get(&titleToTitleLine, index);
852 assert(ilink != (unsigned) -1);
853
854 // Write out string, linked to title line
855 char *linkname=SqueezeWS(stringdict_getbynum(titleLineDict, ilink));
856 //fprintf(fileout, "<a href=\"#%04d\">%s</a>", ilink, linkString.text);
857 fprintf( fileout, "<a href=\"#%s\">%s</a>", linkname, linkString.text);
858 free(linkname);
859
860 buffer_cleanup(&linkString);
861 buffer_cleanup(&linkString1);
862
863 return 0; // normal return - have found and written link
864 }
865 }
866 // Error - unexpected end of file
867 fprintf(stderr, "Error: EOF detected while searching for end of link.\n");
868 fprintf(stderr, " Current link string is: %s\n", linkString.text );
869 return 23;
870 }
871
872 static void init(void) {
873 buffer_init(&title);
874 buffer_init(&title1);
875 buffer_init(&titleLine);
876 buffer_init(&titleLine1);
877 titleDict = stringdict_create();
878 titleDict1 = stringdict_create();
879 titleLineDict = stringdict_create();
880 titleLineDict1 = stringdict_create();
881 topicBodyDict = stringdict_create();
882 buffer_init(&topicFrag);
883 buffer_init(&tabFrag);
884 buffer_init(&blankFrag);
885 buffer_init(&topicBody);
886 intstack_init(&paragType);
887 uintarray_init(&titleToTitleLine);
888 }
889
890 /* -- Main Program -- */
891
892 int main(int argc, char *argv[]) {
893
894 FILE *input;
895
896 long fileLength;
897 size_t stringLength;
898 char *helpsrcString;
899
900 init();
901
902 if (verbose) {
903 printf( "\n This program reads a help.src-type file, "
904 "replaces &, <, > with entities,\n"
905 "sorts in a case-insensitive manner and writes "
906 "to output file as HTML\n"
907 "with a preceding list of the help topics. \n\n" );
908 }
909
910 /* Check for enough arguments */
911 if (argc != 3) {
912 fprintf(stderr, "Usage: mhh6 helpdata.src help.html\n");
913 return 1;
914 }
915
916 /* Open input file */
917 input = fopen(argv[1],"r");
918 if (input == NULL) {
919 fprintf(stderr, "Cannot open %s\n", argv[1]);
920 return 2;
921 }
922
923 /* find out how big the input file is */
924 if (fseek(input, SEEK_SET, SEEK_END)) {
925 fprintf(stderr, "Strange problems with %s\n", argv[1]);
926 return 3;
927 }
928 fileLength = ftell(input);
929 if (fileLength < 0 ) { // -1L is error return
930 fprintf(stderr, "Error getting file length (%ld) of %s\n",
931 fileLength, argv[1]);
932 return 4;
933 }
934
935 /* fseek to beginning of file */
936 if (fseek(input, 0, SEEK_SET)) {
937 fprintf(stderr, "Strange problems with %s\n", argv[1]);
938 return 5;
939 }
940
941 /* Allocate storage for input string */
942 helpsrcString = must_malloc(fileLength + 1);
943
944 /* read file */
945 stringLength = fread(helpsrcString, 1, (unsigned)fileLength, input);
946 if (stringLength == 0) {
947 fprintf(stderr, "Unable to read %s\n", argv[1]);
948 free(helpsrcString);
949 fclose(input);
950 return 7;
951 }
952 // Terminate string with null
953 helpsrcString[stringLength] = 0;
954
955 /* first, replace < > & with entities */
956 helpentStr = charToEntity( helpsrcString );
957
958 /* no more need for input string or file */
959 free(helpsrcString);
960 fclose(input);
961
962 /* initialize stack of parag types */
963 intstack_push(&paragType, Tnone);
964
965 /* call parser */
966 PCB.pointer = (unsigned char *)(const char *)helpentStr;
967 mhh6();
968
969 /* Print file statistics */
970 if (verbose) {
971 printf("No. of title lines in line dict.= %d\n",
972 stringdict_count(titleLineDict) );
973 printDict(titleLineDict); // print title lines
974 printf( "\n\n" );
975
976 printf( "title count = %d, includes Secret of Life \n\n", title_count );
977 printf( "title line count = %d, includes Secret of Life \n\n",
978 title_line_count );
979 printf( "total1sttextline = %d, \n", total1sttextline );
980 printf( "total1sttextlineb = %d \n", total1sttextlineb );
981 printf( "total1sttableline = %d \n", total1sttableline );
982 printf( "total1stlist1line = %d \n", total1stlist1line );
983 printf( "total1stlist2line = %d \n", total1stlist2line );
984 printf( "total1stlisttabline = %d \n", total1stlisttabline );
985 printf( "total1stcodeline = %d \n", total1stcodeline );
986 }
987
988 /* check for error */
989 if (verbose) {
990 printf( "PCB.exit_flag = %d (%d for success)\n", PCB.exit_flag,
991 AG_SUCCESS_CODE);
992 }
993 if (PCB.exit_flag != AG_SUCCESS_CODE) {
994 fprintf(stderr, "File %s: error at line %d, column %d\n",
995 argv[1],
996 PCB.line,
997 PCB.column);
998 return 8;
999 }
1000
1001 // Write sorted title lines & topics as HTML to intermediate file
1002 FILE *intermed;
1003 const char *filename = "intermed.html";
1004 /* Open intermediate file */
1005 intermed = fopen(filename ,"w+"); // create intermediate text file
1006 if (intermed == NULL) {
1007 fprintf(stderr, "Cannot open %s\n", filename);
1008 return 9;
1009 }
1010 if (verbose) {
1011 printf( "Writing sorted title lines & topic bodies to "
1012 "intermediate file in HTML format...\n");
1013 }
1014 writeSortedHtml(intermed);
1015 rewind(intermed);
1016
1017 /* Create output HTML file, inserting links */
1018 FILE *output;
1019 /* Open output file */
1020 output = fopen(argv[2] ,"w");
1021 if (output == NULL) {
1022 fprintf(stderr, "Cannot open %s\n", argv[2]);
1023 return 10;
1024 }
1025
1026 if (verbose) {
1027 printf( "Writing output file with HTML links...\n");
1028 }
1029
1030 int c = 0;
1031 int ctest = 0;
1032
1033 while ( (c=fgetc(intermed)) != EOF ){
1034
1035 if ( c == 0xA9 ) { // begins link string
1036 // printf( "\n Found beginning of link" );
1037 int itest = processLinkString(intermed, output);
1038 if (itest !=0) return itest; // error return
1039 }
1040 else {
1041 ctest = fputc( c, output ); // write out current character
1042 if (ctest == EOF) return 11;
1043 }
1044 }
1045
1046 fclose(intermed);
1047 fclose(output);
1048
1049
1050 /* done */
1051 if (verbose) {
1052 printf( "All done.\n" );
1053 }
1054 return 0; // normal return
1055
1056 } /* -- End of main() function -- */
1057
1058 } /* ---- End of embedded C ----------------------------------------- */
1059
1060