Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/man/mantohtml.c
1090 views
1
/*
2
* Man page to HTML conversion program.
3
*
4
* Copyright 2007-2017 by Apple Inc.
5
* Copyright 2004-2006 by Easy Software Products.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8
*/
9
10
/*
11
* Include necessary headers.
12
*/
13
14
#include <cups/string-private.h>
15
#include <cups/array-private.h>
16
#include <unistd.h>
17
18
19
/*
20
* Local globals...
21
*/
22
23
static const char /* Start/end tags for fonts */
24
* const start_fonts[] = { "", "<b>", "<i>" },
25
* const end_fonts[] = { "", "</b>", "</i>" };
26
27
28
/*
29
* Local functions...
30
*/
31
32
static void html_alternate(const char *s, const char *first, const char *second, FILE *fp);
33
static void html_fputs(const char *s, int *font, FILE *fp);
34
static void html_putc(int ch, FILE *fp);
35
static void strmove(char *d, const char *s);
36
37
38
/*
39
* 'main()' - Convert a man page to HTML.
40
*/
41
42
int /* O - Exit status */
43
main(int argc, /* I - Number of command-line args */
44
char *argv[]) /* I - Command-line arguments */
45
{
46
FILE *infile, /* Input file */
47
*outfile; /* Output file */
48
char line[1024], /* Line from file */
49
*lineptr, /* Pointer into line */
50
anchor[1024], /* Anchor */
51
name[1024], /* Man page name */
52
ddpost[256]; /* Tagged list post markup */
53
int section = -1, /* Man page section */
54
pre = 0, /* Preformatted */
55
font = 0, /* Current font */
56
linenum = 0; /* Current line number */
57
float list_indent = 0.0f, /* Current list indentation */
58
nested_indent = 0.0f; /* Nested list indentation, if any */
59
const char *list = NULL, /* Current list, if any */
60
*nested = NULL; /* Nested list, if any */
61
const char *post = NULL; /* Text to add after the current line */
62
63
64
/*
65
* Check arguments...
66
*/
67
68
if (argc > 3)
69
{
70
fputs("Usage: mantohtml [filename.man [filename.html]]\n", stderr);
71
return (1);
72
}
73
74
/*
75
* Open files as needed...
76
*/
77
78
if (argc > 1)
79
{
80
if ((infile = fopen(argv[1], "r")) == NULL)
81
{
82
perror(argv[1]);
83
return (1);
84
}
85
}
86
else
87
infile = stdin;
88
89
if (argc > 2)
90
{
91
if ((outfile = fopen(argv[2], "w")) == NULL)
92
{
93
perror(argv[2]);
94
fclose(infile);
95
return (1);
96
}
97
}
98
else
99
outfile = stdout;
100
101
/*
102
* Read from input and write the output...
103
*/
104
105
fputs("<!DOCTYPE HTML>\n"
106
"<html>\n"
107
"<!-- SECTION: Man Pages -->\n"
108
"<head>\n"
109
"\t<link rel=\"stylesheet\" type=\"text/css\" "
110
"href=\"../cups-printable.css\">\n", outfile);
111
112
anchor[0] = '\0';
113
114
while (fgets(line, sizeof(line), infile))
115
{
116
size_t linelen = strlen(line); /* Length of line */
117
118
if (linelen > 0 && line[linelen - 1] == '\n')
119
line[linelen - 1] = '\0';
120
121
linenum ++;
122
123
if (line[0] == '.')
124
{
125
/*
126
* Strip leading whitespace...
127
*/
128
129
while (line[1] == ' ' || line[1] == '\t')
130
strmove(line + 1, line + 2);
131
132
/*
133
* Process man page commands...
134
*/
135
136
if (!strncmp(line, ".TH ", 4) && section < 0)
137
{
138
/*
139
* Grab man page title...
140
*/
141
142
sscanf(line + 4, "%s%d", name, &section);
143
144
fprintf(outfile,
145
"\t<title>%s(%d)</title>\n"
146
"</head>\n"
147
"<body>\n"
148
"<h1 class=\"title\">%s(%d)</h1>\n"
149
"%s",
150
name, section, name, section, start_fonts[font]);
151
}
152
else if (section < 0)
153
continue;
154
else if (!strncmp(line, ".SH ", 4) || !strncmp(line, ".SS ", 4))
155
{
156
/*
157
* Grab heading...
158
*/
159
160
int first = 1;
161
162
fputs(end_fonts[font], outfile);
163
font = 0;
164
165
if (list)
166
{
167
fprintf(outfile, "</%s>\n", list);
168
list = NULL;
169
}
170
171
if (line[2] == 'H')
172
fputs("<h2 class=\"title\"><a name=\"", outfile);
173
else
174
fputs("<h3><a name=\"", outfile);
175
176
if (anchor[0])
177
{
178
fputs(anchor, outfile);
179
anchor[0] = '\0';
180
}
181
else
182
{
183
for (lineptr = line + 4; *lineptr; lineptr ++)
184
if (*lineptr == '\"')
185
continue;
186
else if (isalnum(*lineptr & 255))
187
html_putc(*lineptr, outfile);
188
else
189
html_putc('_', outfile);
190
}
191
192
fputs("\">", outfile);
193
194
for (lineptr = line + 4; *lineptr; lineptr ++)
195
{
196
if (*lineptr == '\"')
197
continue;
198
else if (*lineptr == ' ')
199
{
200
html_putc(' ', outfile);
201
202
first = 1;
203
}
204
else
205
{
206
if (first)
207
html_putc(*lineptr, outfile);
208
else
209
html_putc(tolower(*lineptr & 255), outfile);
210
211
first = 0;
212
}
213
}
214
215
if (line[2] == 'H')
216
fputs("</a></h2>\n", outfile);
217
else
218
fputs("</a></h3>\n", outfile);
219
}
220
else if (!strncmp(line, ".B ", 3))
221
{
222
/*
223
* Grab bold text...
224
*/
225
226
fputs(end_fonts[font], outfile);
227
font = 0;
228
229
if (anchor[0])
230
fprintf(outfile, "<a name=\"%s\">", anchor);
231
232
html_alternate(line + 3, "b", "b", outfile);
233
234
if (anchor[0])
235
{
236
fputs("</a>", outfile);
237
anchor[0] = '\0';
238
}
239
240
if (post)
241
{
242
fputs(post, outfile);
243
post = NULL;
244
}
245
}
246
else if (!strncmp(line, ".I ", 3))
247
{
248
/*
249
* Grab italic text...
250
*/
251
252
fputs(end_fonts[font], outfile);
253
font = 0;
254
255
if (anchor[0])
256
fprintf(outfile, "<a name=\"%s\">", anchor);
257
258
html_alternate(line + 3, "i", "i", outfile);
259
260
if (anchor[0])
261
{
262
fputs("</a>", outfile);
263
anchor[0] = '\0';
264
}
265
266
if (post)
267
{
268
fputs(post, outfile);
269
post = NULL;
270
}
271
}
272
else if (!strncmp(line, ".BI ", 4))
273
{
274
/*
275
* Alternating bold and italic text...
276
*/
277
278
fputs(end_fonts[font], outfile);
279
font = 0;
280
281
if (anchor[0])
282
fprintf(outfile, "<a name=\"%s\">", anchor);
283
284
html_alternate(line + 4, "b", "i", outfile);
285
286
if (anchor[0])
287
{
288
fputs("</a>", outfile);
289
anchor[0] = '\0';
290
}
291
292
if (post)
293
{
294
fputs(post, outfile);
295
post = NULL;
296
}
297
}
298
else if (!strncmp(line, ".BR ", 4))
299
{
300
/*
301
* Alternating bold and roman (plain) text...
302
*/
303
304
fputs(end_fonts[font], outfile);
305
font = 0;
306
307
if (anchor[0])
308
fprintf(outfile, "<a name=\"%s\">", anchor);
309
310
html_alternate(line + 4, "b", NULL, outfile);
311
312
if (anchor[0])
313
{
314
fputs("</a>", outfile);
315
anchor[0] = '\0';
316
}
317
318
if (post)
319
{
320
fputs(post, outfile);
321
post = NULL;
322
}
323
}
324
else if (!strncmp(line, ".IB ", 4))
325
{
326
/*
327
* Alternating italic and bold text...
328
*/
329
330
fputs(end_fonts[font], outfile);
331
font = 0;
332
333
if (anchor[0])
334
fprintf(outfile, "<a name=\"%s\">", anchor);
335
336
html_alternate(line + 4, "i", "b", outfile);
337
338
if (anchor[0])
339
{
340
fputs("</a>", outfile);
341
anchor[0] = '\0';
342
}
343
344
if (post)
345
{
346
fputs(post, outfile);
347
post = NULL;
348
}
349
}
350
else if (!strncmp(line, ".IR ", 4))
351
{
352
/*
353
* Alternating italic and roman (plain) text...
354
*/
355
356
fputs(end_fonts[font], outfile);
357
font = 0;
358
359
if (anchor[0])
360
fprintf(outfile, "<a name=\"%s\">", anchor);
361
362
html_alternate(line + 4, "i", NULL, outfile);
363
364
if (anchor[0])
365
{
366
fputs("</a>", outfile);
367
anchor[0] = '\0';
368
}
369
370
if (post)
371
{
372
fputs(post, outfile);
373
post = NULL;
374
}
375
}
376
else if (!strncmp(line, ".RB ", 4))
377
{
378
/*
379
* Alternating roman (plain) and bold text...
380
*/
381
382
fputs(end_fonts[font], outfile);
383
font = 0;
384
385
if (anchor[0])
386
fprintf(outfile, "<a name=\"%s\">", anchor);
387
388
html_alternate(line + 4, NULL, "b", outfile);
389
390
if (anchor[0])
391
{
392
fputs("</a>", outfile);
393
anchor[0] = '\0';
394
}
395
396
if (post)
397
{
398
fputs(post, outfile);
399
post = NULL;
400
}
401
}
402
else if (!strncmp(line, ".RI ", 4))
403
{
404
/*
405
* Alternating roman (plain) and italic text...
406
*/
407
408
fputs(end_fonts[font], outfile);
409
font = 0;
410
411
if (anchor[0])
412
fprintf(outfile, "<a name=\"%s\">", anchor);
413
414
html_alternate(line + 4, NULL, "i", outfile);
415
416
if (anchor[0])
417
{
418
fputs("</a>", outfile);
419
anchor[0] = '\0';
420
}
421
422
if (post)
423
{
424
fputs(post, outfile);
425
post = NULL;
426
}
427
}
428
else if (!strncmp(line, ".SB ", 4))
429
{
430
/*
431
* Alternating small and bold text...
432
*/
433
434
fputs(end_fonts[font], outfile);
435
font = 0;
436
437
if (anchor[0])
438
fprintf(outfile, "<a name=\"%s\">", anchor);
439
440
html_alternate(line + 4, "small", "b", outfile);
441
442
if (anchor[0])
443
{
444
fputs("</a>", outfile);
445
anchor[0] = '\0';
446
}
447
448
if (post)
449
{
450
fputs(post, outfile);
451
post = NULL;
452
}
453
}
454
else if (!strncmp(line, ".SM ", 4))
455
{
456
/*
457
* Small text...
458
*/
459
460
fputs(end_fonts[font], outfile);
461
font = 0;
462
463
if (anchor[0])
464
fprintf(outfile, "<a name=\"%s\">", anchor);
465
466
html_alternate(line + 4, "small", "small", outfile);
467
468
if (anchor[0])
469
{
470
fputs("</a>", outfile);
471
anchor[0] = '\0';
472
}
473
474
if (post)
475
{
476
fputs(post, outfile);
477
post = NULL;
478
}
479
}
480
else if (!strcmp(line, ".LP") || !strcmp(line, ".PP") || !strcmp(line, ".P"))
481
{
482
/*
483
* New paragraph...
484
*/
485
486
fputs(end_fonts[font], outfile);
487
font = 0;
488
489
if (list)
490
{
491
fprintf(outfile, "</%s>\n", list);
492
list = NULL;
493
}
494
495
fputs("<p>", outfile);
496
497
if (anchor[0])
498
{
499
fprintf(outfile, "<a name=\"%s\"></a>", anchor);
500
anchor[0] = '\0';
501
}
502
}
503
else if (!strcmp(line, ".RS") || !strncmp(line, ".RS ", 4))
504
{
505
/*
506
* Indent...
507
*/
508
509
float amount = 3.0; /* Indentation */
510
511
if (line[3])
512
amount = (float)atof(line + 4);
513
514
fputs(end_fonts[font], outfile);
515
font = 0;
516
517
if (list)
518
{
519
nested = list;
520
list = NULL;
521
nested_indent = list_indent;
522
list_indent = 0.0f;
523
}
524
525
fprintf(outfile, "<div style=\"margin-left: %.1fem;\">\n", amount - nested_indent);
526
}
527
else if (!strcmp(line, ".RE"))
528
{
529
/*
530
* Unindent...
531
*/
532
533
fputs(end_fonts[font], outfile);
534
font = 0;
535
536
fputs("</div>\n", outfile);
537
538
if (nested)
539
{
540
list = nested;
541
nested = NULL;
542
543
list_indent = nested_indent;
544
nested_indent = 0.0f;
545
}
546
}
547
else if (!strcmp(line, ".HP") || !strncmp(line, ".HP ", 4))
548
{
549
/*
550
* Hanging paragraph...
551
*
552
* .HP i
553
*/
554
555
float amount = 3.0; /* Indentation */
556
557
if (line[3])
558
amount = (float)atof(line + 4);
559
560
fputs(end_fonts[font], outfile);
561
font = 0;
562
563
if (list)
564
{
565
fprintf(outfile, "</%s>\n", list);
566
list = NULL;
567
}
568
569
fprintf(outfile, "<p style=\"margin-left: %.1fem; text-indent: %.1fem\">", amount, -amount);
570
571
if (anchor[0])
572
{
573
fprintf(outfile, "<a name=\"%s\"></a>", anchor);
574
anchor[0] = '\0';
575
}
576
577
if (line[1] == 'T')
578
post = "<br>\n";
579
}
580
else if (!strcmp(line, ".TP") || !strncmp(line, ".TP ", 4))
581
{
582
/*
583
* Tagged list...
584
*
585
* .TP i
586
*/
587
588
float amount = 3.0; /* Indentation */
589
590
if (line[3])
591
amount = (float)atof(line + 4);
592
593
fputs(end_fonts[font], outfile);
594
font = 0;
595
596
if (list && strcmp(list, "dl"))
597
{
598
fprintf(outfile, "</%s>\n", list);
599
list = NULL;
600
}
601
602
if (!list)
603
{
604
fputs("<dl class=\"man\">\n", outfile);
605
list = "dl";
606
list_indent = amount;
607
}
608
609
fputs("<dt>", outfile);
610
snprintf(ddpost, sizeof(ddpost), "<dd style=\"margin-left: %.1fem\">", amount);
611
post = ddpost;
612
613
if (anchor[0])
614
{
615
fprintf(outfile, "<a name=\"%s\"></a>", anchor);
616
anchor[0] = '\0';
617
}
618
}
619
else if (!strncmp(line, ".IP ", 4))
620
{
621
/*
622
* Indented paragraph...
623
*
624
* .IP x i
625
*/
626
627
float amount = 3.0; /* Indentation */
628
const char *newlist = NULL; /* New list style */
629
const char *newtype = NULL; /* New list numbering type */
630
631
fputs(end_fonts[font], outfile);
632
font = 0;
633
634
lineptr = line + 4;
635
while (isspace(*lineptr & 255))
636
lineptr ++;
637
638
if (!strncmp(lineptr, "\\(bu", 4) || !strncmp(lineptr, "\\(em", 4))
639
{
640
/*
641
* Bullet list...
642
*/
643
644
newlist = "ul";
645
}
646
else if (isdigit(*lineptr & 255))
647
{
648
/*
649
* Numbered list...
650
*/
651
652
newlist = "ol";
653
}
654
else if (islower(*lineptr & 255))
655
{
656
/*
657
* Lowercase alpha list...
658
*/
659
660
newlist = "ol";
661
newtype = "a";
662
}
663
else if (isupper(*lineptr & 255))
664
{
665
/*
666
* Lowercase alpha list...
667
*/
668
669
newlist = "ol";
670
newtype = "A";
671
}
672
673
while (!isspace(*lineptr & 255))
674
lineptr ++;
675
while (isspace(*lineptr & 255))
676
lineptr ++;
677
678
if (isdigit(*lineptr & 255))
679
amount = (float)atof(lineptr);
680
681
if (newlist && list && strcmp(newlist, list))
682
{
683
fprintf(outfile, "</%s>\n", list);
684
list = NULL;
685
}
686
687
if (newlist && !list)
688
{
689
if (newtype)
690
fprintf(outfile, "<%s type=\"%s\">\n", newlist, newtype);
691
else
692
fprintf(outfile, "<%s>\n", newlist);
693
694
list = newlist;
695
}
696
697
if (list)
698
fprintf(outfile, "<li style=\"margin-left: %.1fem;\">", amount);
699
else
700
fprintf(outfile, "<p style=\"margin-left: %.1fem;\">", amount);
701
702
if (anchor[0])
703
{
704
fprintf(outfile, "<a name=\"%s\"></a>", anchor);
705
anchor[0] = '\0';
706
}
707
}
708
else if (!strncmp(line, ".br", 3))
709
{
710
/*
711
* Grab line break...
712
*/
713
714
fputs("<br>\n", outfile);
715
}
716
else if (!strncmp(line, ".de ", 4))
717
{
718
/*
719
* Define macro - ignore...
720
*/
721
722
while (fgets(line, sizeof(line), infile))
723
{
724
linenum ++;
725
726
if (!strncmp(line, "..", 2))
727
break;
728
}
729
}
730
else if (!strncmp(line, ".ds ", 4) || !strncmp(line, ".rm ", 4) ||
731
!strncmp(line, ".tr ", 4) || !strncmp(line, ".hy ", 4) ||
732
!strncmp(line, ".IX ", 4) || !strncmp(line, ".PD", 3) ||
733
!strncmp(line, ".Sp", 3))
734
{
735
/*
736
* Ignore unused commands...
737
*/
738
}
739
else if (!strncmp(line, ".Vb", 3) || !strncmp(line, ".nf", 3) || !strncmp(line, ".EX", 3))
740
{
741
/*
742
* Start preformatted...
743
*/
744
745
fputs(end_fonts[font], outfile);
746
font = 0;
747
748
// if (list)
749
// {
750
// fprintf(outfile, "</%s>\n", list);
751
// list = NULL;
752
// }
753
754
pre = 1;
755
fputs("<pre class=\"man\">\n", outfile);
756
}
757
else if (!strncmp(line, ".Ve", 3) || !strncmp(line, ".fi", 3) || !strncmp(line, ".EE", 3))
758
{
759
/*
760
* End preformatted...
761
*/
762
763
fputs(end_fonts[font], outfile);
764
font = 0;
765
766
if (pre)
767
{
768
pre = 0;
769
fputs("</pre>\n", outfile);
770
}
771
}
772
else if (!strncmp(line, ".\\}", 3))
773
{
774
/*
775
* Ignore close block...
776
*/
777
}
778
else if (!strncmp(line, ".ie", 3) || !strncmp(line, ".if", 3) ||
779
!strncmp(line, ".el", 3))
780
{
781
/*
782
* If/else - ignore...
783
*/
784
785
if (strchr(line, '{') != NULL)
786
{
787
/*
788
* Skip whole block...
789
*/
790
791
while (fgets(line, sizeof(line), infile))
792
{
793
linenum ++;
794
795
if (strchr(line, '}') != NULL)
796
break;
797
}
798
}
799
}
800
#if 0
801
else if (!strncmp(line, ". ", 4))
802
{
803
/*
804
* Grab ...
805
*/
806
}
807
#endif /* 0 */
808
else if (!strncmp(line, ".\\\"#", 4))
809
{
810
/*
811
* Anchor for HTML output...
812
*/
813
814
strlcpy(anchor, line + 4, sizeof(anchor));
815
}
816
else if (strncmp(line, ".\\\"", 3))
817
{
818
/*
819
* Unknown...
820
*/
821
822
if ((lineptr = strchr(line, ' ')) != NULL)
823
*lineptr = '\0';
824
else if ((lineptr = strchr(line, '\n')) != NULL)
825
*lineptr = '\0';
826
827
fprintf(stderr, "mantohtml: Unknown man page command \'%s\' on line %d.\n", line, linenum);
828
}
829
830
/*
831
* Skip continuation lines...
832
*/
833
834
lineptr = line + strlen(line) - 1;
835
if (lineptr >= line && *lineptr == '\\')
836
{
837
while (fgets(line, sizeof(line), infile))
838
{
839
linenum ++;
840
lineptr = line + strlen(line) - 2;
841
842
if (lineptr < line || *lineptr != '\\')
843
break;
844
}
845
}
846
}
847
else
848
{
849
/*
850
* Process man page text...
851
*/
852
853
if (pre == 1)
854
{
855
pre ++;
856
if (!line[0])
857
continue; // Skip initial blank line
858
}
859
860
html_fputs(line, &font, outfile);
861
putc('\n', outfile);
862
863
if (post)
864
{
865
fputs(post, outfile);
866
post = NULL;
867
}
868
}
869
}
870
871
fprintf(outfile, "%s\n", end_fonts[font]);
872
font = 0;
873
874
if (list)
875
{
876
fprintf(outfile, "</%s>\n", list);
877
list = NULL;
878
}
879
880
fputs("</body>\n"
881
"</html>\n", outfile);
882
883
/*
884
* Close files...
885
*/
886
887
if (infile != stdin)
888
fclose(infile);
889
890
if (outfile != stdout)
891
fclose(outfile);
892
893
/*
894
* Return with no errors...
895
*/
896
897
return (0);
898
}
899
900
901
/*
902
* 'html_alternate()' - Alternate words between two styles of text.
903
*/
904
905
static void
906
html_alternate(const char *s, /* I - String */
907
const char *first, /* I - First style or NULL */
908
const char *second, /* I - Second style of NULL */
909
FILE *fp) /* I - File */
910
{
911
int i = 0; /* Which style */
912
int quote = 0; /* Saw quote? */
913
int dolinks, /* Do hyperlinks to other man pages? */
914
link = 0; /* Doing a link now? */
915
916
917
/*
918
* Skip leading whitespace...
919
*/
920
921
while (isspace(*s & 255))
922
s ++;
923
924
dolinks = first && !strcmp(first, "b") && !second;
925
926
while (*s)
927
{
928
if (!i && dolinks)
929
{
930
/*
931
* See if we need to make a link to a man page...
932
*/
933
934
const char *end; /* End of current word */
935
const char *next; /* Start of next word */
936
937
for (end = s; *end && !isspace(*end & 255); end ++);
938
for (next = end; isspace(*next & 255); next ++);
939
940
if (isalnum(*s & 255) && *next == '(')
941
{
942
// "name (section)" - see if the man file is available locally...
943
char name[1024], // Name
944
manfile[1024], // Man page filename
945
manurl[1024]; // Man page URL
946
947
strlcpy(name, s, sizeof(name));
948
if ((size_t)(end - s) < sizeof(name))
949
name[end - s] = '\0';
950
951
snprintf(manurl, sizeof(manurl), "man-%s.html?TOPIC=Man+Pages", name);
952
snprintf(manfile, sizeof(manfile), "%s.%d", name, atoi(next + 1));
953
if (!access(manfile, 0))
954
{
955
// Local man page, do a link...
956
fprintf(fp, "<a href=\"%s\">", manurl);
957
link = 1;
958
}
959
}
960
}
961
962
if (!i && first)
963
fprintf(fp, "<%s>", first);
964
else if (i && second)
965
fprintf(fp, "<%s>", second);
966
967
while ((!isspace(*s & 255) || quote) && *s)
968
{
969
if (*s == '\"')
970
quote = !quote;
971
972
if (*s == '\\' && s[1])
973
{
974
s ++;
975
html_putc(*s++, fp);
976
}
977
else
978
html_putc(*s++, fp);
979
}
980
981
if (!i && first)
982
fprintf(fp, "</%s>", first);
983
else if (i && second)
984
fprintf(fp, "</%s>", second);
985
986
if (i && link)
987
{
988
fputs("</a>", fp);
989
link = 0;
990
}
991
992
i = 1 - i;
993
994
/*
995
* Skip trailing whitespace...
996
*/
997
998
while (isspace(*s & 255))
999
s ++;
1000
}
1001
1002
putc('\n', fp);
1003
}
1004
1005
/*
1006
* 'html_fputs()' - Output a string, quoting as needed HTML entities.
1007
*/
1008
1009
static void
1010
html_fputs(const char *s, /* I - String */
1011
int *font, /* IO - Font */
1012
FILE *fp) /* I - File */
1013
{
1014
while (*s)
1015
{
1016
if (*s == '\\')
1017
{
1018
s ++;
1019
if (!*s)
1020
break;
1021
1022
if (*s == 'f')
1023
{
1024
int newfont; /* New font */
1025
1026
s ++;
1027
if (!*s)
1028
break;
1029
1030
if (!font)
1031
{
1032
s ++;
1033
continue;
1034
}
1035
1036
switch (*s++)
1037
{
1038
case 'R' :
1039
case 'P' :
1040
newfont = 0;
1041
break;
1042
1043
case 'b' :
1044
case 'B' :
1045
newfont = 1;
1046
break;
1047
1048
case 'i' :
1049
case 'I' :
1050
newfont = 2;
1051
break;
1052
1053
default :
1054
fprintf(stderr, "mantohtml: Unknown font \"\\f%c\" ignored.\n", s[-1]);
1055
newfont = *font;
1056
break;
1057
}
1058
1059
if (newfont != *font)
1060
{
1061
fputs(end_fonts[*font], fp);
1062
*font = newfont;
1063
fputs(start_fonts[*font], fp);
1064
}
1065
}
1066
else if (*s == '*')
1067
{
1068
/*
1069
* Substitute macro...
1070
*/
1071
1072
s ++;
1073
if (!*s)
1074
break;
1075
1076
switch (*s++)
1077
{
1078
case 'R' :
1079
fputs("&reg;", fp);
1080
break;
1081
1082
case '(' :
1083
if (!strncmp(s, "lq", 2))
1084
fputs("&ldquo;", fp);
1085
else if (!strncmp(s, "rq", 2))
1086
fputs("&rdquo;", fp);
1087
else if (!strncmp(s, "Tm", 2))
1088
fputs("<sup>TM</sup>", fp);
1089
else
1090
fprintf(stderr, "mantohtml: Unknown macro \"\\*(%2s\" ignored.\n", s);
1091
1092
if (*s)
1093
s ++;
1094
if (*s)
1095
s ++;
1096
break;
1097
1098
default :
1099
fprintf(stderr, "mantohtml: Unknown macro \"\\*%c\" ignored.\n", s[-1]);
1100
break;
1101
}
1102
}
1103
else if (*s == '(')
1104
{
1105
if (!strncmp(s, "(em", 3))
1106
{
1107
fputs("&mdash;", fp);
1108
s += 3;
1109
}
1110
else if (!strncmp(s, "(en", 3))
1111
{
1112
fputs("&ndash;", fp);
1113
s += 3;
1114
}
1115
else
1116
{
1117
putc(*s, fp);
1118
s ++;
1119
}
1120
}
1121
else if (*s == '[')
1122
{
1123
/*
1124
* Substitute escaped character...
1125
*/
1126
1127
s ++;
1128
if (!strncmp(s, "co]", 3))
1129
fputs("&copy;", fp);
1130
else if (!strncmp(s, "de]", 3))
1131
fputs("&deg;", fp);
1132
else if (!strncmp(s, "rg]", 3))
1133
fputs("&reg;", fp);
1134
else if (!strncmp(s, "tm]", 3))
1135
fputs("<sup>TM</sup>", fp);
1136
1137
if (*s)
1138
s ++;
1139
if (*s)
1140
s ++;
1141
if (*s)
1142
s ++;
1143
}
1144
else if (isdigit(s[0]) && isdigit(s[1]) &&
1145
isdigit(s[2]))
1146
{
1147
fprintf(fp, "&#%d;", ((s[0] - '0') * 8 + s[1] - '0') * 8 + s[2] - '0');
1148
s += 3;
1149
}
1150
else
1151
{
1152
if (*s != '\\' && *s != '\"' && *s != '\'' && *s != '-')
1153
{
1154
fprintf(stderr, "mantohtml: Unrecognized escape \"\\%c\" ignored.\n", *s);
1155
html_putc('\\', fp);
1156
}
1157
1158
html_putc(*s++, fp);
1159
}
1160
}
1161
else if (!strncmp(s, "http://", 7) || !strncmp(s, "https://", 8) || !strncmp(s, "ftp://", 6))
1162
{
1163
/*
1164
* Embed URL...
1165
*/
1166
1167
char temp[1024], // Temporary string
1168
*tempptr; // Pointer into temporary string
1169
1170
for (tempptr = temp; *s && !isspace(*s & 255) && tempptr < (temp + sizeof(temp) - 1); s ++)
1171
{
1172
if (strchr(",.)", *s) && strchr(",. \n\r\t", s[1]))
1173
{
1174
// End of URL
1175
break;
1176
}
1177
else if (*s == '\\' && s[1])
1178
{
1179
// Escaped character
1180
s ++;
1181
*tempptr++ = *s;
1182
}
1183
else
1184
{
1185
// Regular character...
1186
*tempptr++ = *s;
1187
}
1188
}
1189
1190
*tempptr = '\0';
1191
fprintf(fp, "<a href=\"%s\">%s</a>", temp, temp);
1192
}
1193
else
1194
html_putc(*s++ & 255, fp);
1195
}
1196
}
1197
1198
1199
/*
1200
* 'html_putc()' - Put a single character, using entities as needed.
1201
*/
1202
1203
static void
1204
html_putc(int ch, /* I - Character */
1205
FILE *fp) /* I - File */
1206
{
1207
if (ch == '&')
1208
fputs("&amp;", fp);
1209
else if (ch == '<')
1210
fputs("&lt;", fp);
1211
else
1212
putc(ch, fp);
1213
}
1214
1215
1216
/*
1217
* 'strmove()' - Move characters within a string.
1218
*/
1219
1220
static void
1221
strmove(char *d, /* I - Destination */
1222
const char *s) /* I - Source */
1223
{
1224
while (*s)
1225
*d++ = *s++;
1226
1227
*d = '\0';
1228
}
1229
1230