Subversion Repositories Kolibri OS

Rev

Rev 9278 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9278 navichok26 1
/*
2
** This program was written by Richard Verhoeven (NL:5482ZX35)
3
** at the Eindhoven University of Technology. Email: rcb5@win.tue.nl
4
**
5
** Permission is granted to distribute, modify and use this program
6
** as long as this comment is not removed or changed.
7
*/
8
 
9
/* BSD mandoc stuff added by Michael Hamilton. */
10
 
11
/* This program is rather buggy, but in spite of that it often works.
12
   Improved things a little - April 1997 & January 1998 & Dec 2001 -
13
   aeb@cwi.nl. */
14
 
15
/* some code added by Tsukasa Hamnao. */
16
 
17
#include 
18
#include 
19
#include 
20
#include 
9280 turbocat 21
#include 
9278 navichok26 22
 
23
#ifdef _KOLIBRI
24
#include 
25
#include 
26
#else
27
#include 
28
#include 
29
#endif
30
 
31
#include "defs.h"
32
static char version[] = "1.6f-1";
33
 
34
/* BSD mandoc Bd/Ed example(?) blocks */
35
#define BD_LITERAL  1
36
#define BD_INDENT   2
37
 
9280 turbocat 38
#define SIZE(a)    (sizeof(a)/sizeof(*a))
9278 navichok26 39
 
40
static char NEWLINE[2]="\n";
41
static char idxlabel[6] = "ixAAA";
42
 
43
#ifdef _KOLIBRI
44
    #define INDEXFILE "/tmp0/1/manindex.list"
45
#else
46
    #define INDEXFILE "./manindex.list"
47
#endif
48
 
49
char *fname;
9280 turbocat 50
//char *directory;
9278 navichok26 51
FILE *idxfile;
52
 
53
char eqndelimopen=0, eqndelimclose=0;
54
char escapesym='\\', nobreaksym='\'', controlsym='.', fieldsym=0, padsym=0;
55
 
56
char *buffer=NULL;
57
int buffpos=0, buffmax=0;
58
int scaninbuff=0;
59
int still_dd=0;
60
int tabstops[20] = { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96 };
61
int maxtstop=12;
62
int curpos=0;
63
 
64
static char *scan_troff(char *c, int san, char **result);
65
static char *scan_troff_mandoc(char *c, int san, char **result);
66
 
67
static char **argument=NULL;
68
 
69
static char charb[3];
70
 
71
FILE *out;
72
 
73
static char *
74
expand_char(int nr)
75
{
9280 turbocat 76
    STRDEF *h;
9278 navichok26 77
 
9280 turbocat 78
    if (!nr)
79
        return NULL;
9278 navichok26 80
 
9280 turbocat 81
    h = chardef;
82
    if (h->nr != V('*','*')) {
83
        fprintf(out, "chardef corrupted\n");
84
        exit(1);
85
    }
9278 navichok26 86
 
9280 turbocat 87
    for (h = chardef; h; h = h->next)
88
        if (h->nr == nr) {
89
            curpos += h->slen;
90
            return h->st;
91
        }
92
    charb[0] = nr/256;
93
    charb[1] = nr%256;
94
    charb[2] = 0;
95
    curpos += 2;
96
    return charb;
9278 navichok26 97
}
98
 
99
static char *
100
expand_string(int nr)
101
{
9280 turbocat 102
    STRDEF *h;
9278 navichok26 103
 
9280 turbocat 104
    if (!nr)
105
        return NULL;
106
    for (h = strdef; h; h = h->next)
107
        if (h->nr == nr) {
108
            curpos += h->slen;
109
            return h->st;
110
        }
111
    return NULL;
9278 navichok26 112
}
113
 
114
 
115
static char outbuffer[1024];
116
static int obp=0;
9280 turbocat 117
static int no_newline_output=0;        /* boolean, set by \c */
9278 navichok26 118
static int newline_for_fun=0;
119
static int output_possible=0;
120
static int out_length=0;
121
 
122
static void
123
add_links(char *c)
124
{
125
    /*
126
    ** Add the links to the output.
127
    ** At the moment the following are recognized:
128
    **
129
    ** name(*)                 -> ../man?/name.*
130
    ** method://string         -> method://string
131
    ** www.host.name           -> http://www.host.name
132
    ** ftp.host.name           -> ftp://ftp.host.name
133
    ** name@host               -> mailto:name@host
134
    **                 -> file:/usr/include/name.h   (guess)
135
    **
136
    ** Other possible links to add in the future:
137
    **
138
    ** /dir/dir/file  -> file:/dir/dir/file
139
    */
140
    int i,j,nr;
141
    char *f, *g, *h;
142
    char *idtest[6]; /* url, mailto, www, ftp, manpage, include file */
143
 
144
    out_length+=strlen(c);
145
 
146
    nr=0;
147
    idtest[0]=strstr(c+1,"://");
148
    /* idtest[1]=strchr(c+1,'@'); */
149
    idtest[1]=NULL; /* don't create mailto links. */
150
    idtest[2]=strstr(c,"www.");
151
    idtest[3]=strstr(c,"ftp.");
152
    idtest[4]=strchr(c+1,'(');
153
    idtest[5]=strstr(c+1,".h>");
154
    for (i=0; i<6; i++) nr += (idtest[i]!=NULL);
155
    while (nr) {
9280 turbocat 156
    j=-1;
157
    for (i=0; i<6; i++)
158
        if (idtest[i] && (j<0 || idtest[i]
159
    switch (j) {
160
    case 5: /*  */
161
        f=idtest[5];
162
        h=f+2;
163
        g=f;
164
        while (g>c && g[-1]!=';') g--;
165
        if (g!=c) {
166
        char t;
167
        t=*g;
168
        *g=0;
169
        fprintf(out, "%s",c);
170
        *g=t;*h=0;
171
        include_file_html(g);
172
        c=f+6;
173
        } else {
174
        f[5]=0;
175
        fprintf(out, "%s",c);
176
        f[5]=';';
177
        c=f+5;
178
        }
179
        break;
180
    case 4:            /* manpage? */
181
        f=idtest[j];
182
        /* find section - accept (1), (3F), (3Xt), (n), (l) */
183
        g=strchr(f,')');
184
        if (g && g-f<7    /* section has length at most 5, like 3Xlib */
185
                        /* preceded by name or html markup */
186
          && (isalnum(f[-1]) || f[-1]=='>')
9278 navichok26 187
                                /* section is n or l or starts with a digit */
9280 turbocat 188
          && strchr("123456789nl", f[1])
189
          && (g-f == 2 || (g-f == 3 && isdigit(f[1]) && isalpha(f[2]))
190
                       || (f[2] == 'X' && isdigit(f[1])))
191
           ) {
192
        /* this might be a link */
193
        h=f-1;
194
        /* skip html markup */
195
        while (h>c && *h=='>') {
196
            while (h!=c && *h!='<') h--;
197
            if (h!=c) h--;
198
        }
199
        if (isalnum(*h)) {
200
            char t,te,tg,*e;
201
            e=h+1;
202
            while (h>c && (isalnum(h[-1]) || h[-1]=='_' ||
203
                    h[-1]=='-' || h[-1]=='.' || h[-1]==':'))
204
            h--;
205
            t=*h; *h=0;
206
            fprintf(out, "%s", c);
207
            *h=t;
208
            tg=*g; *g=0;
209
            te=*e; *e=0;
210
            man_page_html(f+1, h);     /* section, page */
211
            *e=te;
212
            *g=tg;
213
            c=e;
214
        }
215
        }
216
        *f=0;
217
        fprintf(out, "%s", c);
218
        *f='(';
219
        idtest[4]=f-1;
220
        c=f;
221
        break; /* manpage */
222
    case 3: /* ftp */
223
    case 2: /* www */
224
        g=f=idtest[j];
225
        while (*g && (isalnum(*g) || *g=='_' || *g=='-' || *g=='+' ||
226
              *g=='.')) g++;
227
        if (g[-1]=='.') g--;
228
        if (g-f>4) {
229
        char t;
230
        t=*f; *f=0;
231
        fprintf(out, "%s",c);
232
        *f=t; t=*g;*g=0;
233
        if (j==3)
234
             ftp_html(f);
235
        else
236
             www_html(f);
237
        *g=t;
238
        c=g;
239
        } else {
240
        f[3]=0;
241
        fprintf(out, "%s",c);
242
        c=f+3;
243
        f[3]='.';
244
        }
245
        break;
246
    case 1: /* mailto */
247
        g=f=idtest[1];
248
        while (g>c && (isalnum(g[-1]) || g[-1]=='_' || g[-1]=='-' ||
249
               g[-1]=='+' || g[-1]=='.' || g[-1]=='%')) g--;
250
        h=f+1;
251
        while (*h && (isalnum(*h) || *h=='_' || *h=='-' || *h=='+' ||
252
              *h=='.')) h++;
253
        if (h[-1]=='.') h--;
254
        if (h-f>4 && f-g>1) {
255
        char t;
256
        t=*g;
257
        *g=0;
258
        fprintf(out, "%s",c);
259
        *g=t;t=*h;*h=0;
260
        mailto_html(g);
261
        *h=t;
262
        c=h;
263
        } else {
264
        *f=0;
265
        fprintf(out, "%s",c);
266
        *f='@';
267
        idtest[1]=c;
268
        c=f;
269
        }
270
        break;
271
    case 0: /* url */
272
        g=f=idtest[0];
273
        while (g>c && isalpha(g[-1]) && islower(g[-1])) g--;
274
        h=f+3;
275
        while (*h && !isspace(*h) && *h!='<' && *h!='>' && *h!='"' &&
276
           *h!='&') h++;
277
        if (f-g>2 && f-g<7 && h-f>3) {
278
        char t;
279
        t=*g;
280
        *g=0;
281
        fprintf(out, "%s", c);
282
        *g=t; t=*h; *h=0;
283
        url_html(g);
284
        *h=t;
285
        c=h;
286
        } else {
287
        f[1]=0;
288
        fprintf(out, "%s", c);
289
        f[1]='/';
290
        c=f+1;
291
        }
292
        break;
293
    default:
294
        break;
9278 navichok26 295
    }
9280 turbocat 296
    nr=0;
297
    if (idtest[0] && idtest[0]
298
    if (idtest[1] && idtest[1]
299
    if (idtest[2] && idtest[2]
300
    if (idtest[3] && idtest[3]
301
    if (idtest[4] && idtest[4]
302
    if (idtest[5] && idtest[5]
303
    for (i=0; i<6; i++) nr += (idtest[i]!=NULL);
304
    }
9278 navichok26 305
    fprintf(out, "%s", c);
306
}
307
 
308
int current_font=0;
309
int current_size=0;
310
int fillout = 1;
311
 
312
/*
313
 * Kludge: remove \a - in the context
314
 *   .TH NAME 2 date "Version" "Title"
315
 * we got output \aTitle\a.
316
 */
317
static void
318
out_html(char *c) {
9280 turbocat 319
    if (!c)
320
        return;
321
    if (no_newline_output) {    /* remove \n if present */
322
        int i=0;
323
        while (c[i]) {
324
            if (!no_newline_output)
325
                c[i-1]=c[i];
326
            if (c[i]=='\n')
327
                no_newline_output=0;
328
            i++;
329
        }
330
        if (!no_newline_output)
331
            c[i-1]=0;
332
    }
333
    if (scaninbuff) {
334
        while (*c) {
335
            if (buffpos >= buffmax) {
336
                buffer = xrealloc(buffer, buffmax*2);
337
                buffmax = buffmax*2;
338
            }
339
            if (*c != '\a')
340
                buffer[buffpos++] = *c;
341
            c++;
342
        }
343
    } else if (output_possible) {
344
        while (*c) {
345
            if (*c != '\a')
346
                outbuffer[obp++] = *c;
347
            if (*c == '\n' || obp > 1000) {
348
                outbuffer[obp] = 0;
349
                add_links(outbuffer);
350
                obp = 0;
351
            }
352
            c++;
353
        }
354
    }
9278 navichok26 355
}
356
 
357
/* --------------------------------------------------------------- */
358
/* All references to dl_set and itemdepth are here.                */
359
/* --------------------------------------------------------------- */
360
static int itemdepth=0;
361
static int dl_set[30]= { 0 };
9280 turbocat 362
#define noDL  0
363
#define DL    1
364
#define UL    2
365
#define OL    3
9278 navichok26 366
static char *dl_open[4] = { "", "
\n", "
    ", "
      " };
367
static char *dl_close[4] = { "", "\n", "", "" };
368
 
369
static inline void
370
dl_begin(void) {
371
     if (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == noDL) {
9280 turbocat 372
      out_html(dl_open[DL]);
373
      dl_set[itemdepth]=DL;
9278 navichok26 374
     }
375
     out_html("
");
376
}
377
 
378
static inline void
379
dl_end(void) {
380
     if (itemdepth < SIZE(dl_set)) {
9280 turbocat 381
      int type = dl_set[itemdepth];
382
      if (type == DL) {
383
           out_html(dl_close[type]);
384
           dl_set[itemdepth]=noDL;
385
      }
9278 navichok26 386
     }
387
}
388
 
389
static inline void
390
dl_newlevel(void) {
391
     itemdepth++;
392
     if (itemdepth < SIZE(dl_set))
9280 turbocat 393
      dl_set[itemdepth]=noDL;
9278 navichok26 394
     out_html("
");
395
}
396
 
397
static inline void
398
dl_endlevel(void) {
399
     if (itemdepth) {
9280 turbocat 400
      dl_end();
401
      out_html("\n");
402
      itemdepth--;
9278 navichok26 403
     }
404
}
405
 
406
static inline void
407
dl_down(void) {
408
     while (itemdepth)
9280 turbocat 409
      dl_endlevel();
9278 navichok26 410
     dl_end();
411
}
412
 
413
static inline int
414
dl_type(int type) {
415
     return (itemdepth < SIZE(dl_set) && dl_set[itemdepth] == type);
416
}
417
 
418
static inline void
419
dl_newlevel_type(int type) {
420
     itemdepth++;
421
     if (itemdepth < SIZE(dl_set)) {
9280 turbocat 422
      dl_set[itemdepth]=type;
423
      out_html(dl_open[type]);
9278 navichok26 424
     }
425
}
426
 
427
static inline void
428
dl_endlevel_type(void) {
429
     if (itemdepth) {
9280 turbocat 430
      if (itemdepth < SIZE(dl_set))
431
           out_html(dl_close[dl_set[itemdepth]]);
432
      itemdepth--;
9278 navichok26 433
     }
434
}
435
/* --------------------------------------------------------------- */
436
/* This stuff is broken.
437
It generates
438
   
TIOCLINUX, subcode=0
439
   Dump the screen.
440
   argp points to a
441
from
442
   .IP "\fBTIOCLINUX, subcode=0"
443
   Dump the screen.
444
   \fIargp\fP points to a
445
Bug 1: incorrect nesting:  is needed before 
.
446
Bug 2: incorrect font: after the .IP things are roman again.
447
*/
448
 
449
#define FO0 ""
450
#define FC0 ""
451
#define FO1 ""
452
#define FC1 ""
453
#define FO2 ""
454
#define FC2 ""
455
#define FO3 ""
456
#define FC3 ""
457
 
9280 turbocat 458
char *switchfont[16] = { "", FC0 FO1, FC0 FO2, FC0 FO3,
459
                         FC1 FO0, "", FC1 FO2, FC1 FO3,
460
                         FC2 FO0, FC2 FO1, ""     , FC2 FO3,
461
                         FC3 FO0, FC3 FO1, FC3 FO2, ""};
9278 navichok26 462
 
463
static char *
464
change_to_font(int nr)
465
{
466
  int i;
467
  switch (nr) {
468
  case '0': nr++;
469
  case '1': case '2': case '3': case '4':
470
       nr = nr-'1'; break;
471
  case V('C','W'): nr=3; break;
472
  case 'L': nr=3; break;
473
  case 'B': nr=2; break;
474
  case 'I': nr=1; break;
475
  case 0: case 1: case 2: case 3:
476
       break;
477
  case 'P': case 'R':
478
  default: nr=0; break;
479
  }
480
  i= current_font*4+nr%4;
481
  current_font=nr%4;
482
  return switchfont[i];
483
}
484
 
485
static char sizebuf[200];
486
 
487
static char *
488
change_to_size(int nr)
489
{
490
  int i;
491
  switch (nr) {
492
  case '0': case '1': case '2': case '3': case '4': case '5': case '6':
493
  case '7': case '8': case '9': nr=nr-'0'; break;
494
  case '\0': break;
495
  default: nr=current_size+nr; if (nr>9) nr=9; if (nr< -9) nr=-9; break;
496
  }
497
  if (nr==current_size) return "";
498
  i=current_font;
499
  sizebuf[0]=0;
500
  strcat(sizebuf, change_to_font(0));
501
  if (current_size) strcat(sizebuf, "");
502
  current_size=nr;
503
  if (nr) {
504
    int l;
505
    strcat(sizebuf, "
506
    l=strlen(sizebuf);
507
    if (nr>0) sizebuf[l++]='+'; else sizebuf[l++]='-',nr=-nr;
508
    sizebuf[l++]=nr+'0';
509
    sizebuf[l++]='"';
510
    sizebuf[l++]='>';
511
    sizebuf[l]=0;
512
  }
513
  strcat(sizebuf, change_to_font(i));
514
  return sizebuf;
515
}
516
 
517
int asint=0;
518
int intresult=0;
519
 
520
#define SKIPEOL while (*c && *c++!='\n')
521
 
522
static int skip_escape=0;
523
static int single_escape=0;
524
 
525
static char *
526
scan_escape(char *c) {
527
    char *h=NULL;
528
    char b[5];
529
    INTDEF *intd;
530
    int exoutputp,exskipescape;
531
    int i,j;
532
 
533
    intresult=0;
534
    switch (*c) {
535
    case 'e': h="\\"; curpos++;break;
536
    case '0':
537
    case ' ': h=" ";curpos++; break;
538
    case '|': h=""; break;
539
    case '"': SKIPEOL; c--; h=""; break;
540
    case '$':
9280 turbocat 541
    if (argument) {
542
        c++;
543
        i=(*c -'1');
544
        if (!(h=argument[i])) h="";
545
    }
546
    break;
9278 navichok26 547
    case 'z':
9280 turbocat 548
    c++;
549
    if (*c=='\\') { c=scan_escape(c+1); c--;h=""; }
550
    else {
551
        b[0]=*c;
552
        b[1]=0;
553
        h="";
554
    }
555
    break;
9278 navichok26 556
    case 'k': c++; if (*c=='(') c+=2;
557
    case '^':
558
    case '!':
559
    case '%':
560
    case 'a':
561
    case 'd':
562
    case 'r':
563
    case 'u':
564
    case '\n':
565
    case '&': h=""; break;
566
    case '(':
9280 turbocat 567
    c++;
568
    i= c[0]*256+c[1];
569
    c++;
570
    h = expand_char(i);
571
    break;
9278 navichok26 572
    case '*':
9280 turbocat 573
    c++;
574
    if (*c=='(') {
575
        c++;
576
        i= c[0]*256+c[1];
577
        c++;
578
    } else
579
        i= *c *256+' ';
580
    h = expand_string(i);
581
    break;
9278 navichok26 582
    case 'f':
9280 turbocat 583
    c++;
584
    if (*c=='\\') {
585
        c++;
586
        c=scan_escape(c);
587
        c--;
588
        i=intresult;
589
    } else     if (*c != '(')
590
        i=*c;
591
    else {
592
        c++;
593
        i=c[0]*256+c[1];
594
        c++;
595
    }
596
    if (!skip_escape) h=change_to_font(i); else h="";
597
    break;
9278 navichok26 598
    case 's':
9280 turbocat 599
    c++;
600
    j=0;i=0;
601
    if (*c=='-') {j= -1; c++;} else if (*c=='+') {j=1; c++;}
602
    if (*c=='0') c++; else if (*c=='\\') {
603
        c++;
604
        c=scan_escape(c);
605
        i=intresult; if (!j) j=1;
606
    } else
607
        while (isdigit(*c) && (!i || (!j && i<4))) i=i*10+(*c++)-'0';
608
    if (!j) { j=1; if (i) i=i-10; }
609
    if (!skip_escape) h=change_to_size(i*j); else h="";
610
    c--;
611
    break;
9278 navichok26 612
    case 'n':
9280 turbocat 613
    c++;
614
    j=0;
615
    switch (*c) {
616
    case '+': j=1; c++; break;
617
    case '-': j=-1; c++; break;
618
    default: break;
619
    }
620
    if (*c=='(') {
621
        c++;
622
        i=V(c[0],c[1]);
623
        c=c+1;
624
    } else {
625
        i=V(c[0],' ');
626
    }
627
    intd=intdef;
628
    while (intd && intd->nr!=i) intd=intd->next;
629
    if (intd) {
630
        intd->val=intd->val+j*intd->incr;
631
        intresult=intd->val;
632
    } else {
633
        switch (i) {
634
        case V('.','s'): intresult=current_size; break;
635
        case V('.','f'): intresult=current_font; break;
636
        default: intresult=0; break;
637
        }
638
    }
639
    h="";
640
    break;
9278 navichok26 641
    case 'w':
9280 turbocat 642
    c++;
643
    i=*c;
644
    c++;
645
    exoutputp=output_possible;
646
    exskipescape=skip_escape;
647
    output_possible=0;
648
    skip_escape=1;
649
    j=0;
650
    while (*c!=i) {
651
        j++;
652
        if (*c==escapesym) c=scan_escape(c+1); else c++;
653
    }
654
    output_possible=exoutputp;
655
    skip_escape=exskipescape;
656
    intresult=j;
657
    break;
9278 navichok26 658
    case 'l': h="
"; curpos=0;
659
    case 'b':
660
    case 'v':
661
    case 'x':
662
    case 'o':
663
    case 'L':
664
    case 'h':
9280 turbocat 665
    c++;
666
    i=*c;
667
    c++;
668
    exoutputp=output_possible;
669
    exskipescape=skip_escape;
670
    output_possible=0;
671
    skip_escape=1;
672
    while (*c != i)
673
        if (*c==escapesym) c=scan_escape(c+1);
674
        else c++;
675
    output_possible=exoutputp;
676
    skip_escape=exskipescape;
677
    break;
9278 navichok26 678
    case 'c': no_newline_output=1; break;
679
    case '{': newline_for_fun++; h="";break;
680
    case '}': if (newline_for_fun) newline_for_fun--; h="";break;
681
    case 'p': h="
\n";curpos=0; break;
682
    case 't': h="\t";curpos=(curpos+8)&0xfff8; break;
683
    case '<': h="<";curpos++; break;
684
    case '>': h=">";curpos++; break;
685
    case '\\': if (single_escape) { c--; break;}
686
    default: b[0]=*c; b[1]=0; h=b; curpos++; break;
687
    }
688
    c++;
689
    if (!skip_escape) out_html(h);
690
    return c;
691
}
692
 
693
typedef struct TABLEITEM TABLEITEM;
694
 
695
struct TABLEITEM {
696
    char *contents;
697
    int size,align,valign,colspan,rowspan,font,vleft,vright,space,width;
698
    TABLEITEM *next;
699
};
700
 
701
static TABLEITEM emptyfield = {NULL,0,0,0,1,1,0,0,0,0,0,NULL};
702
typedef struct TABLEROW TABLEROW;
703
 
704
struct TABLEROW {
705
    TABLEITEM *first;
706
    TABLEROW *prev, *next;
707
};
708
 
709
static char *tableopt[]= { "center", "expand", "box", "allbox", "doublebox",
9280 turbocat 710
               "tab", "linesize", "delim", NULL };
9278 navichok26 711
static int tableoptl[] = { 6,6,3,6,9,3,8,5,0};
712
 
713
 
714
static void clear_table(TABLEROW *table)
715
{
716
    TABLEROW *tr1,*tr2;
717
    TABLEITEM *ti1,*ti2;
718
 
719
    tr1=table;
720
    while (tr1->prev) tr1=tr1->prev;
721
    while (tr1) {
9280 turbocat 722
    ti1=tr1->first;
723
    while (ti1) {
724
        ti2=ti1->next;
725
        if (ti1->contents) free(ti1->contents);
726
        free(ti1);
727
        ti1=ti2;
9278 navichok26 728
    }
9280 turbocat 729
    tr2=tr1;
730
    tr1=tr1->next;
731
    free(tr2);
732
    }
9278 navichok26 733
}
734
 
735
char *scan_expression(char *c, int *result);
736
 
737
static char *scan_format(char *c, TABLEROW **result, int *maxcol)
738
{
739
    TABLEROW *layout, *currow;
740
    TABLEITEM *curfield;
741
    int i,j;
742
    if (*result) {
9280 turbocat 743
    clear_table(*result);
9278 navichok26 744
    }
745
    layout= currow=(TABLEROW*) xmalloc(sizeof(TABLEROW));
746
    currow->next=currow->prev=NULL;
747
    currow->first=curfield=(TABLEITEM*) xmalloc(sizeof(TABLEITEM));
748
    *curfield=emptyfield;
749
    while (*c && *c!='.') {
9280 turbocat 750
    switch (*c) {
751
    case 'C': case 'c': case 'N': case 'n':
752
    case 'R': case 'r': case 'A': case 'a':
753
    case 'L': case 'l': case 'S': case 's':
754
    case '^': case '_':
755
        if (curfield->align) {
756
        curfield->next=(TABLEITEM*)xmalloc(sizeof(TABLEITEM));
757
        curfield=curfield->next;
758
        *curfield=emptyfield;
759
        }
760
        curfield->align=toupper(*c);
761
        c++;
762
        break;
763
    case 'i': case 'I': case 'B': case 'b':
764
        curfield->font = toupper(*c);
765
        c++;
766
        break;
767
    case 'f': case 'F':
768
        c++;
769
        curfield->font = toupper(*c);
770
        c++;
771
        if (!isspace(*c)) c++;
772
        break;
773
    case 't': case 'T': curfield->valign='t'; c++; break;
774
    case 'p': case 'P':
775
        c++;
776
        i=j=0;
777
        if (*c=='+') { j=1; c++; }
778
        if (*c=='-') { j=-1; c++; }
779
        while (isdigit(*c)) i=i*10+(*c++)-'0';
780
        if (j) curfield->size= i*j; else curfield->size=j-10;
781
        break;
782
    case 'v': case 'V':
783
    case 'w': case 'W':
784
//        c=scan_expression(c+2,&curfield->width);
9278 navichok26 785
             c++;
9280 turbocat 786
         if (*c == '(') {
787
            c=scan_expression(c+1,&curfield->width);
788
         } else {
789
             i=0;
790
             while (isdigit(*c)) i=i*10+(*c++)-'0';
791
            curfield->width=i;
792
         }
793
        break;
794
    case '|':
795
        if (curfield->align) curfield->vleft++;
796
        else curfield->vright++;
797
        c++;
798
        break;
799
    case 'e': case 'E':
800
        c++;
801
        break;
802
    case '0': case '1': case '2': case '3': case '4':
803
    case '5': case '6': case '7': case '8': case '9':
804
        i=0;
805
        while (isdigit(*c)) i=i*10+(*c++)-'0';
806
        curfield->space=i;
807
        break;
808
    case ',': case '\n':
809
        currow->next=(TABLEROW*)xmalloc(sizeof(TABLEROW));
810
        currow->next->prev=currow;
811
        currow=currow->next;
812
        currow->next=NULL;
813
        curfield=currow->first=(TABLEITEM*)xmalloc(sizeof(TABLEITEM));
814
        *curfield=emptyfield;
815
        c++;
816
        break;
817
    default:
818
        c++;
819
        break;
9278 navichok26 820
    }
9280 turbocat 821
    }
9278 navichok26 822
    if (*c=='.') while (*c++!='\n');
823
    *maxcol=0;
824
    currow=layout;
825
    while (currow) {
9280 turbocat 826
    curfield=layout->first;
827
    i=0;
828
    while (curfield) {
829
        i++;
830
        curfield=curfield->next;
9278 navichok26 831
    }
9280 turbocat 832
    if (i>*maxcol) *maxcol=i;
833
    currow=currow->next;
834
    }
9278 navichok26 835
    *result=layout;
836
    return c;
837
}
838
 
839
static TABLEROW *
840
next_row(TABLEROW *tr)
841
{
842
    if (tr->next) {
9280 turbocat 843
    tr=tr->next;
844
    if (!tr->next) next_row(tr);
845
    return tr;
9278 navichok26 846
    } else {
9280 turbocat 847
    TABLEITEM *ti, *ti2;
848
    tr->next=(TABLEROW*)xmalloc(sizeof(TABLEROW));
849
    tr->next->prev=tr;
850
    ti=tr->first;
851
    tr=tr->next;
852
    tr->next=NULL;
853
    if (ti) tr->first=ti2=(TABLEITEM*) xmalloc(sizeof(TABLEITEM));
854
    else tr->first=ti2=NULL;
855
    while (ti!=ti2) {
856
        *ti2=*ti;
857
        ti2->contents=NULL;
858
        if ((ti=ti->next)) {
859
        ti2->next=(TABLEITEM*) xmalloc(sizeof(TABLEITEM));
860
        }
861
        ti2=ti2->next;
9278 navichok26 862
    }
9280 turbocat 863
    return tr;
864
    }
9278 navichok26 865
}
866
 
867
char itemreset[20]="\\fR\\s0";
868
 
869
static char *
870
scan_table(char *c) {
871
    char *h;
872
    char *g;
873
    int center=0, expand=0, box=0, border=0, linesize=1;
874
    int i,j,maxcol=0, finished=0;
875
    int oldfont, oldsize,oldfillout;
876
    char itemsep='\t';
877
    TABLEROW *layout=NULL, *currow;
878
    TABLEITEM *curfield;
9280 turbocat 879
    while (*c++!='\n');        /* skip TS */
9278 navichok26 880
    h=c;
881
    if (*h=='.') return c-1;
882
    oldfont=current_font;
883
    oldsize=current_size;
884
    oldfillout=fillout;
885
    out_html(change_to_font(0));
886
    out_html(change_to_size(0));
887
    if (!fillout) {
9280 turbocat 888
    fillout=1;
889
    out_html("
");
9278 navichok26 890
    }
891
    while (*h && *h!='\n') h++;
892
    if (h[-1]==';') {
9280 turbocat 893
    /* scan table options */
894
    while (c
895
        while (isspace(*c)) c++;
896
        for (i=0; tableopt[i] && strncmp(tableopt[i],c,tableoptl[i]);i++);
897
        c=c+tableoptl[i];
898
        switch (i) {
899
        case 0: center=1; break;
900
        case 1: expand=1; break;
901
        case 2: box=1; break;
902
        case 3: border=1; break;
903
        case 4: box=2; break;
904
        case 5: while (*c++!='('); itemsep=*c++; break;
905
        case 6: while (*c++!='('); linesize=0;
906
        while (isdigit(*c)) linesize=linesize*10+(*c++)-'0';
907
        break;
908
        case 7: while (*c!=')') c++;
909
        default: break;
910
        }
911
        c++;
9278 navichok26 912
    }
9280 turbocat 913
    c=h+1;
914
    }
9278 navichok26 915
    /* scan layout */
916
    c=scan_format(c,&layout, &maxcol);
917
    currow=layout;
918
    next_row(currow);
919
    curfield=layout->first;
920
    i=0;
921
    while (!finished && *c) {
9280 turbocat 922
    /* search item */
923
    h=c;
924
    if ((*c=='_' || *c=='=') && (c[1]==itemsep || c[1]=='\n')) {
925
        if (c[-1]=='\n' && c[1]=='\n') {
926
        if (currow->prev) {
927
            currow->prev->next=(TABLEROW*) xmalloc(sizeof(TABLEROW));
928
            currow->prev->next->next=currow;
929
            currow->prev->next->prev=currow->prev;
930
            currow->prev=currow->prev->next;
931
        } else {
932
            currow->prev=layout=(TABLEROW*) xmalloc(sizeof(TABLEROW));
933
            currow->prev->prev=NULL;
934
            currow->prev->next=currow;
935
        }
936
        curfield=currow->prev->first=
937
            (TABLEITEM*) xmalloc(sizeof(TABLEITEM));
938
        *curfield=emptyfield;
939
        curfield->align=*c;
940
        curfield->colspan=maxcol;
941
        curfield=currow->first;
942
        c=c+2;
943
        } else {
944
        if (curfield) {
945
            curfield->align=*c;
946
            do {
947
            curfield=curfield->next;
948
            } while (curfield && curfield->align=='S');
949
        }
950
        if (c[1]=='\n') {
951
            currow=next_row(currow);
952
            curfield=currow->first;
953
        }
954
        c=c+2;
955
        }
956
    } else if (*c=='T' && c[1]=='{') {
957
        h=c+2;
958
        c=strstr(h,"\nT}");
959
        c++;
960
        *c=0;
961
        g=NULL;
962
        scan_troff(h, 0, &g);
963
        scan_troff(itemreset, 0, &g);
964
        *c='T';
965
        c+=3;
966
        if (curfield) {
967
        curfield->contents=g;
968
        do {
969
            curfield=curfield->next;
970
        } while (curfield && curfield->align=='S');
971
        } else
972
        if (g) free(g);
973
        if (c[-1]=='\n') {
974
        currow=next_row(currow);
975
        curfield=currow->first;
976
        }
977
    } else if (*c=='.' && c[1]=='T' && c[2]=='&' && c[-1]=='\n') {
978
        TABLEROW *hr;
979
        while (*c++!='\n');
980
        hr=currow;
981
        currow=currow->prev;
982
        hr->prev=NULL;
983
        c=scan_format(c,&hr, &i);
984
        hr->prev=currow;
985
        currow->next=hr;
986
        currow=hr;
987
        next_row(currow);
988
        curfield=currow->first;
989
    } else if (*c=='.' && c[1]=='T' && c[2]=='E' && c[-1]=='\n') {
990
        finished=1;
991
        while (*c++!='\n');
992
        if (currow->prev)
993
        currow->prev->next=NULL;
994
        currow->prev=NULL;
995
        clear_table(currow);
996
    } else if (*c=='.' && c[-1]=='\n' && !isdigit(c[1])) {
997
        /* skip troff request inside table (usually only .sp ) */
998
        while (*c++!='\n');
999
    } else {
1000
        h=c;
1001
        while (*c && (*c!=itemsep || c[-1]=='\\') &&
1002
           (*c!='\n' || c[-1]=='\\')) c++;
1003
        i=0;
1004
        if (*c==itemsep) {i=1; *c='\n'; }
1005
        if (h[0]=='\\' && h[2]=='\n' &&
1006
        (h[1]=='_' || h[1]=='^')) {
1007
        if (curfield) {
1008
            curfield->align=h[1];
1009
            do {
1010
            curfield=curfield->next;
1011
            } while (curfield && curfield->align=='S');
1012
        }
1013
        h=h+3;
1014
        } else {
1015
        g=NULL;
1016
        h=scan_troff(h,1,&g);
1017
        scan_troff(itemreset,0,&g);
1018
        if (curfield) {
1019
            curfield->contents=g;
1020
            do {
1021
            curfield=curfield->next;
1022
            } while (curfield && curfield->align=='S');
1023
        } else if (g) free(g);
1024
        }
1025
        if (i) *c=itemsep;
1026
        c=h;
1027
        if (c[-1]=='\n') {
1028
        currow=next_row(currow);
1029
        curfield=currow->first;
1030
        }
9278 navichok26 1031
    }
9280 turbocat 1032
    }
9278 navichok26 1033
    /* calculate colspan and rowspan */
1034
#if 0
1035
    currow=layout;
1036
    while (currow->next) currow=currow->next;
1037
    while (currow) {
9280 turbocat 1038
    TABLEITEM *ti, *ti1=NULL, *ti2=NULL;
1039
    ti=currow->first;
1040
    if (currow->prev) ti1=currow->prev->first;
1041
    while (ti) {
1042
        switch (ti->align) {
1043
        case 'S':
1044
        if (ti2) {
1045
            ti2->colspan++;
1046
            if (ti2->rowspanrowspan) ti2->rowspan=ti->rowspan;
1047
        }
1048
        break;
1049
        case '^':
1050
        if (ti1) ti1->rowspan++;
1051
        default:
1052
        if (!ti2) ti2=ti;
1053
        else {
1054
            do {
1055
            ti2=ti2->next;
1056
            } while (ti2 && curfield->align=='S');
1057
        }
1058
        break;
1059
        }
1060
        ti=ti->next;
1061
        if (ti1) ti1=ti1->next;
9278 navichok26 1062
    }
9280 turbocat 1063
    currow=currow->prev;
1064
    }
9278 navichok26 1065
#endif
1066
    /* produce html output */
1067
    if (center) out_html("
");
1068
    if (box==2) out_html("");");\n");
");
1069
    out_html("
1070
    if (box || border) {
9280 turbocat 1071
    out_html(" BORDER");
1072
    if (!border) out_html(">
1073
    if (expand) out_html(" WIDTH=100%");
9278 navichok26 1074
    }
1075
    out_html(">\n");
1076
    currow=layout;
1077
    while (currow) {
9280 turbocat 1078
    j=0;
1079
    out_html("
1080
    curfield=currow->first;
1081
    while (curfield) {
1082
        if (curfield->align!='S' && curfield->align!='^') {
1083
        out_html("
1084
        switch (curfield->align) {
1085
        case 'N':
1086
            curfield->space+=4;
1087
        case 'R':
1088
            out_html(" ALIGN=right");
1089
            break;
1090
        case 'C':
1091
            out_html(" ALIGN=center");
1092
        default:
1093
            break;
1094
        }
1095
        if (!curfield->valign && curfield->rowspan>1)
1096
            out_html(" VALIGN=center");
1097
        if (curfield->colspan>1) {
1098
            char buf[5];
1099
            out_html(" COLSPAN=");
1100
            sprintf(buf, "%i", curfield->colspan);
1101
            out_html(buf);
1102
        }
1103
        if (curfield->rowspan>1) {
1104
            char buf[5];
1105
            out_html(" ROWSPAN=");
1106
            sprintf(buf, "%i", curfield->rowspan);
1107
            out_html(buf);
1108
        }
1109
        j=j+curfield->colspan;
1110
        out_html(">");
1111
        if (curfield->size) out_html(change_to_size(curfield->size));
1112
        if (curfield->font) out_html(change_to_font(curfield->font));
1113
        switch (curfield->align) {
1114
        case '=': out_html("

"); break;
1115
        case '_': out_html("
"); break;
1116
        default:
1117
            if (curfield->contents) out_html(curfield->contents);
1118
            break;
1119
        }
1120
        if (curfield->space)
1121
            for (i=0; ispace;i++) out_html(" ");
1122
        if (curfield->font) out_html(change_to_font(0));
1123
        if (curfield->size) out_html(change_to_size(0));
1124
        if (j>=maxcol && curfield->align>'@' && curfield->align!='_')
1125
            out_html("
");
1126
        out_html("
1127
        }
1128
        curfield=curfield->next;
9278 navichok26 1129
    }
9280 turbocat 1130
    out_html("
1131
    currow=currow->next;
1132
    }
9278 navichok26 1133
    if (box && !border) out_html("
");
1134
    out_html("
"); 1135
    if (box==2) out_html("");
1136
    if (center) out_html("\n");
1137
    else out_html("\n");
1138
    if (!oldfillout) out_html("
");
1139
    fillout=oldfillout;
1140
    out_html(change_to_size(oldsize));
1141
    out_html(change_to_font(oldfont));
1142
    return c;
1143
}
1144
 
1145
char *scan_expression(char *c, int *result) {
1146
    int value=0,value2,sign=1,opex=0;
1147
    char oper='c';
1148
 
1149
    if (*c=='!') {
9280 turbocat 1150
    c=scan_expression(c+1, &value);
1151
    value= (!value);
9278 navichok26 1152
    } else if (*c=='n') {
9280 turbocat 1153
    c++;
1154
    value=nroff;
9278 navichok26 1155
    } else if (*c=='t') {
9280 turbocat 1156
    c++;
1157
    value=1-nroff;
9278 navichok26 1158
    } else if (*c=='\'' || *c=='"' || *c<' ' || (*c=='\\' && c[1]=='(')) {
9280 turbocat 1159
    /* ?string1?string2?
1160
    ** test if string1 equals string2.
1161
    */
1162
    char *st1=NULL, *st2=NULL, *h;
1163
    char *tcmp=NULL;
1164
    char sep;
1165
    sep=*c;
1166
    if (sep=='\\') {
1167
        tcmp=c;
1168
        c=c+3;
1169
    }
1170
    c++;
1171
    h=c;
1172
    while (*c!= sep && (!tcmp || strncmp(c,tcmp,4))) c++;
1173
    *c='\n';
1174
    scan_troff(h, 1, &st1);
1175
    *c=sep;
1176
    if (tcmp) c=c+3;
1177
    c++;
1178
    h=c;
1179
    while (*c!=sep && (!tcmp || strncmp(c,tcmp,4))) c++;
1180
    *c='\n';
1181
    scan_troff(h,1,&st2);
1182
    *c=sep;
1183
    if (!st1 && !st2) value=1;
1184
    else if (!st1 || !st2) value=0;
1185
    else value=(!strcmp(st1, st2));
1186
    if (st1) free(st1);
1187
    if (st2) free(st2);
1188
    if (tcmp) c=c+3;
1189
    c++;
9278 navichok26 1190
    } else {
9280 turbocat 1191
    while (*c && !isspace(*c) && *c!=')') {
1192
        opex=0;
1193
        switch (*c) {
1194
        case '(':
1195
        c=scan_expression(c+1, &value2);
1196
        value2=sign*value2;
1197
        opex=1;
1198
        break;
1199
        case '.':
1200
        case '0': case '1':
1201
        case '2': case '3':
1202
        case '4': case '5':
1203
        case '6': case '7':
1204
        case '8': case '9': {
1205
        int num=0,denum=1;
1206
        value2=0;
1207
        while (isdigit(*c)) value2=value2*10+((*c++)-'0');
1208
        if (*c=='.') {
1209
            c++;
1210
            while (isdigit(*c)) {
1211
            num=num*10+((*c++)-'0');
1212
            denum=denum*10;
1213
            }
1214
        }
1215
        if (isalpha(*c)) {
1216
            /* scale indicator */
1217
            switch (*c) {
1218
            case 'i': /* inch -> 10pt */
1219
            value2=value2*10+(num*10+denum/2)/denum;
1220
            num=0;
1221
            break;
1222
            default:
1223
            break;
1224
            }
1225
            c++;
1226
        }
1227
        value2=value2+(num+denum/2)/denum;
1228
        value2=sign*value2;
1229
        opex=1;
1230
        break;
1231
        }
1232
        case '\\':
1233
        c=scan_escape(c+1);
1234
        value2=intresult*sign;
1235
        if (isalpha(*c)) c++; /* scale indicator */
1236
        opex=1;
1237
        break;
1238
        case '-':
1239
        if (oper) { sign=-1; c++; break; }
1240
        case '>':
1241
        case '<':
1242
        case '+':
1243
        case '/':
1244
        case '*':
1245
        case '%':
1246
        case '&':
1247
        case '=':
1248
        case ':':
1249
        if (c[1]=='=') oper=(*c++) +16; else oper=*c;
1250
        c++;
1251
        break;
1252
        default: c++; break;
1253
        }
1254
        if (opex) {
1255
        sign=1;
1256
        switch (oper) {
1257
        case 'c': value=value2; break;
1258
        case '-': value=value-value2; break;
1259
        case '+': value=value+value2; break;
1260
        case '*': value=value*value2; break;
1261
        case '/': if (value2) value=value/value2; break;
1262
        case '%': if (value2) value=value%value2; break;
1263
        case '<': value=(value
        
        
           
           
           1264
           
        case '>': value=(value>value2); break;
1265
        case '>'+16: value=(value>=value2); break;
1266
        case '<'+16: value=(value<=value2); break;
1267
        case '=': case '='+16: value=(value==value2); break;
1268
        case '&': value = (value && value2); break;
1269
        case ':': value = (value || value2); break;
1270
        default: fprintf(stderr,
1271
                 "man2html: Unknown operator %c.\n", oper);
1272
        }
1273
        oper=0;
1274
        }
9278 navichok26 1275
    }
9280 turbocat 1276
    if (*c==')') c++;
1277
    }
9278 navichok26 1278
    *result=value;
1279
    return c;
1280
}
1281
 
1282
static void
1283
trans_char(char *c, char s, char t) {
9280 turbocat 1284
    char *sl = c;
1285
    int slash = 0;
9278 navichok26 1286
 
9280 turbocat 1287
    while (*sl && (*sl != '\n' || slash)) {
1288
        if (!slash) {
1289
            if (*sl == escapesym)
1290
                slash = 1;
1291
            else if (*sl == s)
1292
                *sl = t;
1293
        } else
1294
            slash = 0;
1295
        sl++;
1296
    }
9278 navichok26 1297
}
1298
 
1299
/*
1300
 * Read STR until end-of-line (not preceded by \).
1301
 * Find whitespace separated words, and store starts in WORDS of lth MAXN.
1302
 * Return number of words in N.
1303
 * Replace each end-of-word by the character EOW (usually \n or 0).
1304
 * Return pointer to last char seen (either \n or 0).
1305
 *
1306
 * A part \"... is skipped.
1307
 * Quotes not preceded by \ are replaced by \a.
1308
 */
1309
static char *
1310
fill_words(char *str, char *words[], int maxn, int *n, char eow) {
9280 turbocat 1311
    char *s = str;
1312
    int backslash = 0;
1313
    int skipspace = 0;    /* 1 if space is not end-of-word */
9278 navichok26 1314
 
9280 turbocat 1315
    *n = 0;
1316
    words[*n] = s;
1317
    while (*s && (*s != '\n' || backslash)) {
1318
        if (!backslash) {
1319
            if (*s == '"') {
1320
                *s = '\a';
1321
                skipspace = !skipspace;
1322
            } else if (*s == escapesym) {
1323
                backslash = 1;
1324
            } else if ((*s == ' ' || *s == '\t') && !skipspace) {
1325
                *s = eow;
1326
                if (words[*n] != s && *n < maxn-1)
1327
                    (*n)++;
1328
                words[*n] = s+1;
1329
            }
1330
        } else {
1331
            if (*s == '"') {
1332
                s--;
1333
                *s = eow;
1334
                if (words[*n] != s && *n < maxn-1)
1335
                    (*n)++;
1336
                s++;
1337
                while (*s && *s != '\n') s++;
1338
                words[*n] = s;
1339
                s--;
1340
            }
1341
            backslash = 0;
1342
        }
1343
        s++;
1344
    }
1345
    if (s != words[*n])
1346
        (*n)++;
1347
    return s;
9278 navichok26 1348
}
1349
 
1350
 
1351
char *section_list[] = {
1352
    "1", "User Commands ",
1353
    "1C", "User Commands",
1354
    "1G", "User Commands",
1355
    "1S", "User Commands",
1356
    "1V", "User Commands ",
1357
    "2", "System Calls",
1358
    "2V", "System Calls",
1359
    "3", "C Library Functions",
1360
    "3C", "Compatibility Functions",
1361
    "3F", "Fortran Library Routines",
1362
    "3K", "Kernel VM Library Functions",
1363
    "3L", "Lightweight Processes Library",
1364
    "3M", "Mathematical Library",
1365
    "3N", "Network Functions",
1366
    "3R", "RPC Services Library",
1367
    "3S", "Standard I/O Functions",
1368
    "3V", "C Library Functions",
1369
    "3X", "Miscellaneous Library Functions",
1370
    "4", "Devices and Network Interfaces",
1371
    "4F", "Protocol Families",
1372
    "4I", "Devices and Network Interfaces",
1373
    "4M", "Devices and Network Interfaces",
1374
    "4N", "Devices and Network Interfaces",
1375
    "4P", "Protocols",
1376
    "4S", "Devices and Network Interfaces",
1377
    "4V", "Devices and Network Interfaces",
1378
    "5", "File Formats",
1379
    "5V", "File Formats",
1380
    "6", "Games and Demos",
1381
    "7", "Environments, Tables, and Troff Macros",
1382
    "7V", "Environments, Tables, and Troff Macros",
1383
    "8", "Maintenance Commands",
1384
    "8C", "Maintenance Commands",
1385
    "8S", "Maintenance Commands",
1386
    "8V", "Maintenance Commands",
1387
    "L", "Local Commands",
1388
/* for Solaris:
1389
    "1", "User Commands",
1390
    "1B", "SunOS/BSD Compatibility Package Commands",
1391
    "1b", "SunOS/BSD Compatibility Package Commands",
1392
    "1C", "Communication Commands ",
1393
    "1c", "Communication Commands",
1394
    "1F", "FMLI Commands ",
1395
    "1f", "FMLI Commands",
1396
    "1G", "Graphics and CAD Commands ",
1397
    "1g", "Graphics and CAD Commands ",
1398
    "1M", "Maintenance Commands",
1399
    "1m", "Maintenance Commands",
1400
    "1S", "SunOS Specific Commands",
1401
    "1s", "SunOS Specific Commands",
1402
    "2", "System Calls",
1403
    "3", "C Library Functions",
1404
    "3B", "SunOS/BSD Compatibility Library Functions",
1405
    "3b", "SunOS/BSD Compatibility Library Functions",
1406
    "3C", "C Library Functions",
1407
    "3c", "C Library Functions",
1408
    "3E", "C Library Functions",
1409
    "3e", "C Library Functions",
1410
    "3F", "Fortran Library Routines",
1411
    "3f", "Fortran Library Routines",
1412
    "3G", "C Library Functions",
1413
    "3g", "C Library Functions",
1414
    "3I", "Wide Character Functions",
1415
    "3i", "Wide Character Functions",
1416
    "3K", "Kernel VM Library Functions",
1417
    "3k", "Kernel VM Library Functions",
1418
    "3L", "Lightweight Processes Library",
1419
    "3l", "Lightweight Processes Library",
1420
    "3M", "Mathematical Library",
1421
    "3m", "Mathematical Library",
1422
    "3N", "Network Functions",
1423
    "3n", "Network Functions",
1424
    "3R", "Realtime Library",
1425
    "3r", "Realtime Library",
1426
    "3S", "Standard I/O Functions",
1427
    "3s", "Standard I/O Functions",
1428
    "3T", "Threads Library",
1429
    "3t", "Threads Library",
1430
    "3W", "C Library Functions",
1431
    "3w", "C Library Functions",
1432
    "3X", "Miscellaneous Library Functions",
1433
    "3x", "Miscellaneous Library Functions",
1434
    "4", "File Formats",
1435
    "4B", "SunOS/BSD Compatibility Package File Formats",
1436
    "4b", "SunOS/BSD Compatibility Package File Formats",
1437
    "5", "Headers, Tables, and Macros",
1438
    "6", "Games and Demos",
1439
    "7", "Special Files",
1440
    "7B", "SunOS/BSD Compatibility Special Files",
1441
    "7b", "SunOS/BSD Compatibility Special Files",
1442
    "8", "Maintenance Procedures",
1443
    "8C", "Maintenance Procedures",
1444
    "8c", "Maintenance Procedures",
1445
    "8S", "Maintenance Procedures",
1446
    "8s", "Maintenance Procedures",
1447
    "9", "DDI and DKI",
1448
    "9E", "DDI and DKI Driver Entry Points",
1449
    "9e", "DDI and DKI Driver Entry Points",
1450
    "9F", "DDI and DKI Kernel Functions",
1451
    "9f", "DDI and DKI Kernel Functions",
1452
    "9S", "DDI and DKI Data Structures",
1453
    "9s", "DDI and DKI Data Structures",
1454
    "L", "Local Commands",
1455
*/
1456
    NULL, "Misc. Reference Manual Pages",
1457
    NULL, NULL
1458
};
1459
 
1460
static char *
1461
section_name(char *c)
1462
{
1463
    int i=0;
1464
 
1465
    if (!c) return "";
1466
    while (section_list[i] && strcmp(c,section_list[i])) i=i+2;
1467
    if (section_list[i+1]) return section_list[i+1];
1468
    else return c;
1469
}
1470
 
1471
int manidxlen = 0;
1472
char *manidx = NULL;
1473
int subs = 0;
9280 turbocat 1474
int mip = 0;    /* current offset in manidx[] */
9278 navichok26 1475
char label[5]="lbAA";
1476
 
1477
static void
1478
manidx_need(int m) {
9280 turbocat 1479
    if (mip + m >= manidxlen) {
1480
        manidxlen += 10000;
1481
        manidx = xrealloc(manidx, manidxlen);
1482
    }
9278 navichok26 1483
}
1484
 
1485
static void
1486
add_to_index(int level, char *item)
1487
{
1488
    char *c = NULL;
1489
 
1490
    label[3]++;
1491
    if (label[3]>'Z') {
9280 turbocat 1492
    label[3]='A';
1493
    label[2]++;
9278 navichok26 1494
    }
1495
 
1496
    if (level != subs) {
9280 turbocat 1497
    manidx_need(6);
1498
    if (subs) {
1499
        strcpy(manidx+mip, "\n");
1500
        mip += 6;
1501
    } else {
1502
        strcpy(manidx+mip, "
\n");
1503
        mip += 5;
9278 navichok26 1504
    }
9280 turbocat 1505
    }
9278 navichok26 1506
    subs = level;
1507
 
1508
    scan_troff(item, 1, &c);
1509
    manidx_need(100 + strlen(c));
1510
    sprintf(manidx+mip, "
%s
\n", label, c);
1511
    if (c) free(c);
1512
    while (manidx[mip]) mip++;
1513
}
1514
 
1515
static char *
1516
skip_till_newline(char *c)
1517
{
1518
    int lvl=0;
1519
 
1520
    while (*c && (*c!='\n' || lvl>0)) {
9280 turbocat 1521
    if (*c=='\\') {
1522
        c++;
1523
        if (*c=='}') lvl--; else if (*c=='{') lvl++;
9278 navichok26 1524
    }
1525
    c++;
9280 turbocat 1526
    }
1527
    c++;
9278 navichok26 1528
    if (lvl<0 && newline_for_fun) {
9280 turbocat 1529
    newline_for_fun = newline_for_fun+lvl;
1530
    if (newline_for_fun<0) newline_for_fun=0;
9278 navichok26 1531
    }
1532
    return c;
1533
}
1534
 
1535
int ifelseval=0;
1536
 
1537
static char *
1538
scan_request(char *c) {
1539
                                  /* BSD Mandoc stuff - by Michael Hamilton */
1540
    static int mandoc_synopsis=0; /* True if we are in the synopsis section */
1541
    static int mandoc_command=0;  /* True if this is mandoc page */
1542
    static int mandoc_bd_options; /* Only copes with non-nested Bd's */
1543
    static int inXo=0;
1544
 
1545
    int i,j,mode = 0;
1546
    char *h;
1547
    char *wordlist[20];
1548
    int words;
1549
    char *sl;
1550
    STRDEF *owndef;
1551
 
1552
    while (*c == ' ' || *c == '\t')
9280 turbocat 1553
        c++;
9278 navichok26 1554
    if (c[0] == '\n')
9280 turbocat 1555
        return c+1;
9278 navichok26 1556
    if (c[1] == '\n')
9280 turbocat 1557
        j = 1;
9278 navichok26 1558
    else
9280 turbocat 1559
        j = 2;
9278 navichok26 1560
    while (c[j] == ' ' || c[j] == '\t')
9280 turbocat 1561
        j++;
9278 navichok26 1562
    if (c[0] == escapesym) {
9280 turbocat 1563
    /* some pages use .\" .\$1 .\} */
1564
    /* .\$1 is too difficult/stupid */
1565
    if (c[1] == '$')
1566
        c = skip_till_newline(c);
1567
    else
1568
        c = scan_escape(c+1);
9278 navichok26 1569
    } else {
9280 turbocat 1570
    i=V(c[0],c[1]);
1571
    switch (i) {
1572
    case V('a','b'):
1573
        h=c+j;
1574
        while (*h && *h !='\n') h++;
1575
        *h=0;
1576
        if (scaninbuff && buffpos) {
1577
        buffer[buffpos]=0;
1578
        fprintf(out, "%s\n", buffer);
1579
        }
1580
        fprintf(stderr, "%s\n", c+2);        /* XXX */
1581
        exit(0);
1582
        break;
1583
    case V('d','i'):
1584
        {
1585
        STRDEF *de;
1586
        c=c+j;
1587
        i=V(c[0],c[1]);
1588
        if (*c == '\n') { c++;break; }
1589
        while (*c && *c!='\n') c++;
1590
        c++;
1591
        h=c;
1592
        while (*c && strncmp(c,".di",3)) while (*c && *c++!='\n');
1593
        *c=0;
1594
        de=strdef;
1595
        while (de && de->nr !=i) de=de->next;
1596
        if (!de) {
1597
            de=(STRDEF*) xmalloc(sizeof(STRDEF));
1598
            de->nr=i;
1599
            de->slen=0;
1600
            de->next=strdef;
1601
            de->st=NULL;
1602
            strdef=de;
1603
        } else {
1604
            if (de->st) free(de->st);
1605
            de->slen=0;
1606
            de->st=NULL;
1607
        }
1608
        scan_troff(h,0,&de->st);
1609
        *c='.';
1610
        while (*c && *c++!='\n');
1611
        break;
1612
        }
1613
    case V('d','s'):
1614
        mode=1;
1615
    case V('a','s'):
1616
        {
1617
        STRDEF *de;
1618
        int oldcurpos=curpos;
1619
        c=c+j;
1620
        while (*c == ' ') c++;
1621
        i=V(c[0],c[1]);
1622
        j=0;
1623
        while (c[j] && c[j]!='\n') j++;
1624
        if (j<3) { c=c+j; break; }
1625
        if (c[1] == ' ') c=c+1; else c=c+2;
1626
        while (isspace(*c)) c++;
1627
        if (*c == '"') c++;
1628
        de=strdef;
1629
        while (de && de->nr != i) de=de->next;
1630
        single_escape=1;
1631
        curpos=0;
1632
        if (!de) {
1633
            char *h;
1634
            de=(STRDEF*) xmalloc(sizeof(STRDEF));
1635
            de->nr=i;
1636
            de->slen=0;
1637
            de->next=strdef;
1638
            de->st=NULL;
1639
            strdef=de;
1640
            h=NULL;
1641
            c=scan_troff(c, 1, &h);
1642
            de->st=h;
1643
            de->slen=curpos;
1644
        } else {
1645
            if (mode) {        /* .ds */
1646
            char *h=NULL;
1647
            c=scan_troff(c, 1, &h);
1648
            free(de->st);    /* segfault XXX */
1649
            de->slen=curpos;
1650
            de->st=h;
1651
            } else {        /* .as */
1652
            c=scan_troff(c,1,&de->st);     /* XXX */
1653
            de->slen+=curpos;
1654
            }
1655
        }
1656
        single_escape=0;
1657
        curpos=oldcurpos;
1658
        }
1659
        break;
1660
    case V('b','r'):
1661
        if (still_dd) out_html("
");
1662
        else out_html("
\n");
1663
        curpos=0;
1664
        c=c+j;
1665
        if (c[0] == escapesym) { c=scan_escape(c+1); }
1666
        c=skip_till_newline(c);break;
1667
    case V('c','2'):
1668
        c=c+j;
1669
        if (*c!='\n') { nobreaksym=*c; }
1670
        else nobreaksym='\'';
1671
        c=skip_till_newline(c);
1672
        break;
1673
    case V('c','c'):
1674
        c=c+j;
1675
        if (*c!='\n') { controlsym=*c; }
1676
        else controlsym='.';
1677
        c=skip_till_newline(c);
1678
        break;
1679
    case V('c','e'):
1680
        c=c+j;
1681
        if (*c == '\n') { i=1; }
1682
        else {
1683
        i=0;
1684
        while ('0'<=*c && *c<='9') {
1685
            i=i*10+*c-'0';
1686
            c++;
1687
        }
1688
        }
1689
        c=skip_till_newline(c);
1690
        /* center next i lines */
1691
        if (i>0) {
1692
        out_html("
\n");
1693
        while (i && *c) {
1694
            char *line=NULL;
1695
            c=scan_troff(c,1, &line);
1696
            if (line && strncmp(line, "
", 4)) {
1697
            out_html(line);
1698
            out_html("
\n");
1699
            i--;
1700
            }
1701
        }
1702
        out_html("\n");
1703
        curpos=0;
1704
        }
1705
        break;
1706
    case V('e','c'):
1707
        c=c+j;
1708
        if (*c!='\n') { escapesym=*c; }
1709
        else escapesym='\\';
1710
        break;
1711
        c=skip_till_newline(c);
1712
    case V('e','o'):
1713
        escapesym=0;
1714
        c=skip_till_newline(c);
1715
        break;
1716
    case V('e','x'):
1717
        exit(0);
1718
        break;
1719
    case V('f','c'):
1720
        c=c+j;
1721
        if  (*c == '\n') {
1722
        fieldsym=padsym=0;
1723
        } else {
1724
        fieldsym=c[0];
1725
        padsym=c[1];
1726
        }
1727
        c=skip_till_newline(c);
1728
        break;
1729
    case V('f','i'):
1730
        if (!fillout) {
1731
        out_html(change_to_font(0));
1732
        out_html(change_to_size('0'));
1733
        out_html("
\n");
1734
        }
1735
        curpos=0;
1736
        fillout=1;
1737
        c=skip_till_newline(c);
1738
        break;
1739
    case V('f','t'):
1740
        c=c+j;
1741
        if (*c == '\n') {
1742
        out_html(change_to_font(0));
1743
        } else {
1744
        if (*c == escapesym) {
1745
            int fn;
1746
            c=scan_expression(c, &fn);
1747
            c--;
1748
            out_html(change_to_font(fn));
1749
        } else {
1750
            out_html(change_to_font(*c));
1751
            c++;
1752
        }
1753
        }
1754
        c=skip_till_newline(c);
1755
        break;
1756
    case V('e','l'):
1757
        /* .el anything : else part of if else */
1758
        if (ifelseval) {
1759
        c=c+j;
1760
        c[-1]='\n';
1761
        c=scan_troff(c,1,NULL);
1762
        } else
1763
        c=skip_till_newline(c+j);
1764
        break;
1765
    case V('i','e'):
1766
        /* .ie c anything : then part of if else */
1767
    case V('i','f'):
1768
        /* .if c anything
1769
         * .if !c anything
1770
         * .if N anything
1771
         * .if !N anything
1772
         * .if 'string1'string2' anything
1773
         * .if !'string1'string2' anything
1774
         */
1775
        c=c+j;
1776
        c=scan_expression(c, &i);
1777
        ifelseval=!i;
1778
        if (i) {
1779
        *c='\n';
1780
        c++;
1781
        c=scan_troff(c,1,NULL);
1782
        } else
1783
        c=skip_till_newline(c);
1784
        break;
1785
    case V('i','g'):    /* .ig: ignore until .. */
1786
        {
1787
        char *endwith="..\n";
1788
        i=3;
1789
        c=c+j;
1790
        while (*c == ' ') c++;
1791
        if (*c == escapesym && c[1] == '"')
1792
            while (*c != '\n') c++;
1793
        if (*c!='\n') {    /* .ig yy: ignore until .yy, then call .yy */
1794
            endwith=c-1;i=1;
1795
            c[-1]='.';
1796
            while (*c && *c!='\n') c++,i++;
1797
        }
1798
        c++;
1799
        while (*c && strncmp(c,endwith,i))
1800
             while (*c && *c++!='\n');
1801
        while (*c && *c++!='\n');
1802
        break;
1803
        }
1804
    case V('n','f'):
1805
        if (fillout) {
1806
        out_html(change_to_font(0));
1807
        out_html(change_to_size('0'));
1808
        out_html("
\n");
1809
        }
1810
        curpos=0;
1811
        fillout=0;
1812
        c=skip_till_newline(c);
1813
        break;
1814
    case V('p','s'):
1815
        c=c+j;
1816
        if (*c == '\n') {
1817
        out_html(change_to_size('0'));
1818
        } else {
1819
        j=0;i=0;
1820
        if (*c == '-') { j= -1;c++; } else if (*c == '+') { j=1;c++;}
1821
        c=scan_expression(c, &i);
1822
        if (!j) { j=1; if (i>5) i=i-10; }
1823
        out_html(change_to_size(i*j));
1824
        }
1825
        c=skip_till_newline(c);
1826
        break;
1827
    case V('s','p'):
1828
        c=c+j;
1829
        if (fillout) out_html("

"); else {

1830
        out_html(NEWLINE);
1831
        NEWLINE[0]='\n';
1832
        }
1833
        curpos=0;
1834
        c=skip_till_newline(c);
1835
        break;
1836
    case V('s','o'):
1837
        {
1838
        FILE *f;
1839
        int l; char *buf;
1840
        char *name = NULL;
9278 navichok26 1841
 
9280 turbocat 1842
        curpos=0;
1843
        c += j;            /* skip .so part and whitespace */
1844
        if (*c == '/') {
1845
            h = c;
1846
        } else {        /* .so man3/cpow.3 -> ../man3/cpow.3 */
1847
            h = c-3;
1848
            h[0] = '.';
1849
            h[1] = '.';
1850
            h[2] = '/';
1851
        }
1852
        while (*c != '\n') c++;
1853
        while (c[-1] == ' ') c--;
1854
        while (*c != '\n') *c++ = 0;
1855
        *c = 0;
1856
        scan_troff(h,1, &name);
1857
        if (name[3] == '/') h=name+3; else h=name;
1858
        l = 0;
9278 navichok26 1859
#ifdef _KOLIBRI
9280 turbocat 1860
        ksys_bdfe_t bdfe;
1861
        _ksys_file_get_info(h, &bdfe);
1862
        l = bdfe.size;
9278 navichok26 1863
#else
1864
        struct stat stbuf;
9280 turbocat 1865
        if (stat(h, &stbuf)!=-1) l=stbuf.st_size;
9278 navichok26 1866
#endif
1867
 
9280 turbocat 1868
        buf = (char*) xmalloc((l+4)*sizeof(char));
9278 navichok26 1869
#if NOCGI
1870
                if (!out_length) {
9280 turbocat 1871
            char *t,*s;
1872
            t=strrchr(fname, '/');
1873
            if (!t) t=fname;
1874
            //fprintf(stderr, "ln -s %s.html %s.html\n", h, t);
1875
            s=strrchr(t, '.');if (!s) s=t;
1876
            fprintf(out," Manpage of %s\n"
1877
               "\n"
1878
               "See the manpage for %s.\n"
1879
               "\n",
1880
               s, h, h);
1881
        } else
9278 navichok26 1882
#endif
1883
                {
9280 turbocat 1884
            /* this works alright, except for section 3 */
1885
            if (!l || !(f = fopen(h,"r"))) {
1886
             fprintf(stderr,
1887
                "man2html: unable to open or read file %s\n", h);
1888
             out_html("
"
1889
                  "man2html: unable to open or read file\n");
1890
             out_html(h);
1891
             out_html("\n");
1892
            } else {
1893
            i=fread(buf+1,1,l,f);
1894
            fclose(f);
1895
            buf[0]=buf[l]='\n';
1896
            buf[l+1]=buf[l+2]=0;
1897
            scan_troff(buf+1,0,NULL);
1898
            }
1899
            if (buf) free(buf);
1900
        }
1901
        *c++='\n';
1902
        break;
1903
        }
1904
    case V('t','a'):
1905
        c=c+j;
1906
        j=0;
1907
        while (*c!='\n') {
1908
        sl=scan_expression(c, &tabstops[j]);
1909
        if (*c == '-' || *c == '+') tabstops[j]+=tabstops[j-1];
1910
        c=sl;
1911
        while (*c == ' ' || *c == '\t') c++;
1912
        if (j+1 < SIZE(tabstops))
1913
            j++;
1914
        }
1915
        maxtstop=j;
1916
        curpos=0;
1917
        break;
1918
    case V('t','i'):
9278 navichok26 1919
#if 0
9280 turbocat 1920
        dl_down();
9278 navichok26 1921
#endif
9280 turbocat 1922
        out_html("
\n");
1923
        c=c+j;
1924
        c=scan_expression(c, &j);
1925
        for (i=0; i
        
        
           
           
           1926
           
        curpos=j;
1927
        c=skip_till_newline(c);
1928
        break;
1929
    case V('t','m'):
1930
        c=c+j;
1931
        h=c;
1932
        while (*c!='\n') c++;
1933
        *c=0;
1934
        fprintf(stderr,"%s\n", h);        /* XXX */
1935
        *c='\n';
1936
        break;
1937
    case V('B',' '):
1938
    case V('B','\n'):
1939
    case V('I',' '):
1940
    case V('I','\n'):
9278 navichok26 1941
            /* parse one line in a certain font */
9280 turbocat 1942
        out_html(change_to_font(*c));
1943
        trans_char(c, '"', '\a');
1944
        c=c+j;
1945
        if (*c == '\n') c++;
1946
        c=scan_troff(c, 1, NULL);
1947
        out_html(change_to_font('R'));
1948
        out_html(NEWLINE);
1949
        if (fillout) curpos++; else curpos=0;
1950
        break;
1951
    case V('O','P'):  /* groff manpages use this construction */
9278 navichok26 1952
            /* .OP a b : [ a b ] */
9280 turbocat 1953
        mode=1;
1954
        c[0]='B'; c[1]='I';
1955
        out_html(change_to_font('R'));
1956
        out_html("[");
1957
        curpos++;
1958
    case V('B','R'):
1959
    case V('B','I'):
1960
    case V('I','B'):
1961
    case V('I','R'):
1962
    case V('R','B'):
1963
    case V('R','I'):
1964
        {
1965
        char font[2];
1966
        font[0] = c[0]; font[1] = c[1];
1967
        c = c+j;
1968
        if (*c == '\n') c++;
1969
        sl = fill_words(c, wordlist, SIZE(wordlist), &words, '\n');
1970
        c = sl+1;
1971
        /* .BR name (section)
1972
        ** indicates a link. It will be added in the output routine.
1973
        */
1974
        for (i=0; i
        
        
           
           
           1975
           
            if (mode) { out_html(" "); curpos++; }
1976
            wordlist[i][-1]=' ';
1977
            out_html(change_to_font(font[i&1]));
1978
            scan_troff(wordlist[i],1,NULL);
1979
        }
1980
        out_html(change_to_font('R'));
1981
        if (mode) { out_html(" ]"); curpos++;}
1982
        out_html(NEWLINE); if (!fillout) curpos=0; else curpos++;
1983
        }
1984
        break;
1985
    case V('D','T'):
1986
        maxtstop = SIZE(tabstops);
1987
        for (j=0; j
        
        
           
           
           1988
           
        tabstops[j]=(j+1)*8;
1989
        c=skip_till_newline(c); break;
1990
    case V('I','P'):
1991
        sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n');
1992
        c = sl+1;
1993
        dl_begin();
9278 navichok26 1994
            if (words) {
9280 turbocat 1995
        scan_troff(wordlist[0], 1,NULL);
1996
        }
1997
        out_html("
");
1998
        curpos = 0;
1999
        break;
2000
    case V('T','P'):
2001
        dl_begin();
2002
        c=skip_till_newline(c);
2003
        /* somewhere a definition ends with '.TP' */
2004
        if (!*c) still_dd=1; else {
2005
        c=scan_troff(c,1,NULL);
2006
        out_html("
");
2007
        }
2008
        curpos=0;
2009
        break;
2010
    case V('I','X'):
9278 navichok26 2011
            /* general index */
9280 turbocat 2012
        sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n');
2013
        c = sl+1;
2014
        j = 4;
2015
        while (idxlabel[j] == 'Z') idxlabel[j--]='A';
2016
        idxlabel[j]++;
9278 navichok26 2017
#ifdef MAKEINDEX
9280 turbocat 2018
        if (idxfile) {
2019
         fprintf(idxfile, "%s@%s@", fname, idxlabel);
2020
         for (j=0; j
        
        
           
           
           2021
           
              h=NULL;
2022
              scan_troff(wordlist[j], 1, &h);
2023
              fprintf(idxfile, "_\b@%s", h);
2024
              free(h);
2025
         }
2026
         fprintf(idxfile,"\n");
2027
        }
9278 navichok26 2028
#endif
2029
            out_html("
        
        
           9280
           turbocat
           2030
           
        out_html(idxlabel);
2031
        /* this will not work in mosaic (due to a bug).
2032
        ** Adding ' ' between '>' and '<' solves it, but creates
2033
        ** some space. A normal space does not work.
2034
        */
2035
        out_html("\">");
2036
        break;
2037
    case V('L','P'):
2038
    case V('P','P'):
2039
        dl_end();
2040
        if (fillout) out_html("

\n"); else {

2041
        out_html(NEWLINE);
2042
        NEWLINE[0]='\n';
2043
        }
2044
        curpos=0;
2045
        c=skip_till_newline(c);
2046
        break;
2047
    case V('H','P'):
2048
        dl_begin();
2049
        still_dd=1;
2050
        c=skip_till_newline(c);
2051
        curpos=0;
2052
        break;
2053
    case V('P','D'):
2054
         c=skip_till_newline(c);
2055
         break;
2056
    case V('R','s'):        /* BSD mandoc */
2057
    case V('R','S'):
2058
        sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n');
2059
        j = 1;
2060
        if (words>0) scan_expression(wordlist[0], &j);
2061
        if (j>=0) {
2062
        dl_newlevel();
2063
        c=skip_till_newline(c);
2064
        curpos=0;
2065
        break;
2066
        }
2067
    case V('R','e'):        /* BSD mandoc */
2068
    case V('R','E'):
2069
        dl_endlevel();
2070
        c=skip_till_newline(c);
2071
        curpos=0;
2072
        break;
2073
    case V('S','B'):
2074
        out_html(change_to_size(-1));
2075
        out_html(change_to_font('B'));
2076
        c=scan_troff(c+j, 1, NULL);
2077
        out_html(change_to_font('R'));
2078
        out_html(change_to_size('0'));
2079
        break;
2080
    case V('S','M'):
2081
        c=c+j;
2082
        if (*c == '\n') c++;
2083
        out_html(change_to_size(-1));
2084
        trans_char(c,'"','\a');
2085
        c=scan_troff(c,1,NULL);
2086
        out_html(change_to_size('0'));
2087
        break;
2088
    case V('S','s'):        /* BSD mandoc */
2089
        mandoc_command = 1;
2090
    case V('S','S'):
2091
        mode=1;
2092
        goto sh_below;
2093
    case V('S','h'):        /* BSD mandoc */
2094
        mandoc_command = 1;
2095
    case V('S','H'):
2096
    sh_below:
2097
        c=c+j;
2098
        if (*c == '\n') c++;
2099
        dl_down();
2100
        out_html(change_to_font(0));
2101
        out_html(change_to_size(0));
2102
        if (!fillout) {
2103
        fillout=1;
2104
        out_html("
");
2105
        }
2106
        trans_char(c,'"', '\a');
2107
        add_to_index(mode, c);
2108
        out_html("
        
        
           
           
           2109
           
        out_html(label);
2110
        /*   for mosaic users */
2111
        if (mode) out_html("\"> \n

");

2112
        else out_html("\"> \n

");

2113
        mandoc_synopsis = (strncmp(c, "SYNOPSIS", 8) == 0);
2114
        c = (mandoc_command ? scan_troff_mandoc : scan_troff)(c,1,NULL);
2115
        if (mode) out_html("\n");
2116
        else out_html("\n");
2117
        curpos=0;
2118
        break;
2119
    case V('T','S'):
2120
        c=scan_table(c);
2121
        break;
2122
    case V('D','t'):        /* BSD mandoc */
2123
        mandoc_command = 1;
2124
    case V('T','H'):
2125
        if (!output_possible) {
2126
        sl = fill_words(c+j, wordlist, SIZE(wordlist), &words, 0);
2127
        *sl = 0;
2128
        if (words > 1) {
2129
            output_possible=1;
2130
            out_html("Manpage of ");</pre></td>
        </tr>
        <tr valign="middle">
           <td></td>
           <td></td>
           <td><a name="l2131">2131</a></td>
           <td class="code"><pre>            out_html(wordlist[0]);</pre></td>
        </tr>
        <tr valign="middle">
           <td></td>
           <td></td>
           <td><a name="l2132">2132</a></td>
           <td class="code"><pre>            out_html("\n");
9278 navichok26 2133
            out_html("\n");
2134
            out_html("\n

");

9280 turbocat 2135
            out_html(wordlist[0]);
2136
            out_html("\nSection: ");
2137
            if (words>4)
2138
            out_html(wordlist[4]);
2139
            else
2140
            out_html(section_name(wordlist[1]));
2141
            out_html(" (");
2142
            out_html(wordlist[1]);
2143
            if (words>2) {
2144
            out_html(")
Updated: ");
2145
            scan_troff(wordlist[2], 1, NULL);
2146
            } else out_html(")");
2147
            out_html("
Index\n");
2148
            man_page_html(0,0);    /* Return to Main Contents */
2149
            *sl='\n';
2150
            out_html("
\n");
2151
            if (mandoc_command) out_html("
BSD mandoc
");
2152
        }
2153
        c = sl+1;
2154
        } else
2155
        c = skip_till_newline(c);
2156
        curpos=0;
2157
        break;
2158
    case V('T','X'):
2159
        sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n');
2160
        *sl=0;
2161
        out_html(change_to_font('I'));
2162
        if (words>1) wordlist[1][-1]=0;
2163
        c=lookup_abbrev(wordlist[0]);
2164
        curpos+=strlen(c);
2165
        out_html(c);
2166
        out_html(change_to_font('R'));
2167
        if (words>1)
2168
        out_html(wordlist[1]);
2169
        *sl='\n';
2170
        c=sl+1;
2171
        break;
2172
    case V('r','m'):
9278 navichok26 2173
            /* .rm xx : Remove request, macro or string */
9280 turbocat 2174
    case V('r','n'):
9278 navichok26 2175
            /* .rn xx yy : Rename request, macro or string xx to yy */
9280 turbocat 2176
        {
2177
        STRDEF *de;
2178
        c=c+j;
2179
        i=V(c[0],c[1]);
2180
        c=c+2;
2181
        while (isspace(*c) && *c!='\n') c++;
2182
        j=V(c[0],c[1]);
2183
        while (*c && *c!='\n') c++;
2184
        c++;
2185
        de=strdef;
2186
        while (de && de->nr!=j) de=de->next;
2187
        if (de) {
2188
            if (de->st) free(de->st);
2189
            de->nr=0;
2190
        }
2191
        de=strdef;
2192
        while (de && de->nr!=i) de=de->next;
2193
        if (de) de->nr=j;
2194
        break;
2195
        }
2196
    case V('n','x'):
9278 navichok26 2197
            /* .nx filename : next file. */
9280 turbocat 2198
    case V('i','n'):
9278 navichok26 2199
            /* .in +-N : Indent */
9280 turbocat 2200
        c=skip_till_newline(c);
2201
        break;
2202
    case V('n','r'):
9278 navichok26 2203
            /* .nr R +-N M: define and set number register R by +-N;
9280 turbocat 2204
        **  auto-increment by M
2205
        */
2206
        {
2207
        INTDEF *intd;
2208
        c=c+j;
2209
        i=V(c[0],c[1]);
2210
        c=c+2;
2211
        intd=intdef;
2212
        while (intd && intd->nr!=i) intd=intd->next;
2213
        if (!intd) {
2214
            intd = (INTDEF*) xmalloc(sizeof(INTDEF));
2215
            intd->nr=i;
2216
            intd->val=0;
2217
            intd->incr=0;
2218
            intd->next=intdef;
2219
            intdef=intd;
2220
        }
2221
        while (*c == ' ' || *c == '\t') c++;
2222
        c=scan_expression(c,&intd->val);
2223
        if (*c!='\n') {
2224
            while (*c == ' ' || *c == '\t') c++;
2225
            c=scan_expression(c,&intd->incr);
2226
        }
2227
        c=skip_till_newline(c);
2228
        break;
2229
        }
2230
    case V('a','m'):
9278 navichok26 2231
            /* .am xx yy : append to a macro. */
2232
            /* define or handle as .ig yy */
9280 turbocat 2233
        mode=1;
2234
    case V('d','e'):
9278 navichok26 2235
            /* .de xx yy : define or redefine macro xx; end at .yy (..) */
2236
            /* define or handle as .ig yy */
9280 turbocat 2237
        {
2238
        STRDEF *de;
2239
        int olen=0;
2240
        c=c+j;
2241
        sl=fill_words(c, wordlist, SIZE(wordlist), &words, '\n');
2242
        i=V(c[0],c[1]);j=2;
2243
        if (words == 1) wordlist[1]=".."; else {
2244
            wordlist[1]--;
2245
            wordlist[1][0]='.';
2246
            j=3;
2247
        }
2248
        c=sl+1;
2249
        sl=c;
2250
        while (*c && strncmp(c,wordlist[1],j)) c=skip_till_newline(c);
2251
        de=defdef;
2252
        while (de && de->nr!= i) de=de->next;
2253
        if (mode && de) olen=strlen(de->st);
2254
        j=olen+c-sl;
2255
        h= (char*) xmalloc((j*2+4)*sizeof(char));
2256
        if (h) {
2257
            for (j=0; j
        
        
           
           
           2258
           
            h[j]=de->st[j];
2259
            if (!j || h[j-1]!='\n')
2260
            h[j++]='\n';
2261
            while (sl!=c) {
2262
            if (sl[0] == '\\' && sl[1] == '\\') {
2263
                h[j++]='\\'; sl++;
2264
            } else
2265
                h[j++]=*sl;
2266
            sl++;
2267
            }
2268
            h[j]=0;
2269
            if (de) {
2270
            if (de->st) free(de->st);
2271
            de->st=h;
2272
            } else {
2273
            de = (STRDEF*) xmalloc(sizeof(STRDEF));
2274
            de->nr=i;
2275
            de->next=defdef;
2276
            de->st=h;
2277
            defdef=de;
2278
            }
2279
        }
2280
        }
2281
        c=skip_till_newline(c);
2282
        break;
9278 navichok26 2283
 
9280 turbocat 2284
    /* ----- BSD mandoc stuff below ----- */
2285
    case V('U','x'):    /* BSD mandoc */
2286
        c=c+j;
2287
        out_html("UNIX");
2288
        c=skip_till_newline(c);
2289
        break;
2290
    case V('A','t'):    /* BSD mandoc - called with arg V */
2291
        c=c+j;
2292
        out_html("AT&T System");
2293
        break;
2294
    case V('B','l'):    /* BSD mandoc */
2295
    {
2296
        char *nl, t=0 /* just for gcc */;
2297
        c=c+j;
2298
        nl = strchr(c,'\n');
2299
        if (nl) {
2300
         t = *nl;
2301
         *nl = 0;
2302
        }
2303
        if (strstr(c, "-bullet")) /* HTML Unnumbered List */
2304
         dl_newlevel_type(UL);
2305
        else if (strstr(c, "-enum")) /* HTML Ordered List */
2306
         dl_newlevel_type(OL);
2307
        else             /* HTML Descriptive List */
2308
         dl_newlevel_type(DL);
2309
        if (nl)
2310
         *nl = t;
2311
        if (fillout) out_html("

\n"); else {

2312
         out_html(NEWLINE);
2313
         NEWLINE[0]='\n';
2314
        }
2315
        curpos=0;
2316
        c=skip_till_newline(c);
2317
        break;
2318
    }
2319
    case V('E','l'):    /* BSD mandoc */
2320
         c=c+j;
2321
         dl_endlevel_type();
2322
         if (fillout) out_html("

\n"); else {

2323
          out_html(NEWLINE);
2324
          NEWLINE[0]='\n';
2325
         }
2326
         curpos=0;
2327
         c=skip_till_newline(c);
2328
         break;
2329
    case V('I','t'):    /* BSD mandoc */
2330
         c=c+j;
2331
         if (dl_type(DL)) {
2332
          out_html("
");
2333
          out_html(change_to_font('B'));
2334
          if (*c == '\n') {
2335
               /* Don't allow embedded comms after a newline */
2336
               c++;
2337
               c=scan_troff(c,1,NULL);
2338
          } else {
2339
               /* Do allow embedded comms on the same line. */
2340
               c=scan_troff_mandoc(c,1,NULL);
2341
          }
2342
          out_html(change_to_font('R'));
2343
          out_html(NEWLINE);
2344
          if (inXo)
2345
               still_dd = 1;
2346
          else
2347
               out_html("
");
2348
         } else if (dl_type(UL) || dl_type(OL)) {
2349
          out_html("
  • ");
  • 2350
              c=scan_troff_mandoc(c,1,NULL);
    2351
              out_html(NEWLINE);
    2352
             }
    2353
             if (fillout) curpos++; else curpos=0;
    2354
             break;
    2355
        case V('X','o'):    /* BSD mandoc */
    2356
             c=c+j;
    2357
             inXo = 1;
    2358
             break;
    2359
        case V('X','c'):    /* BSD mandoc - Xc closes an Xo */
    2360
             c=c+j;
    2361
             if (inXo) {
    2362
              if (still_dd)
    2363
                   out_html("
    ");
    2364
              inXo = 0;
    2365
             }
    2366
             break;
    2367
        case V('S','m'):    /* BSD mandoc - called with arg on/off */
    2368
             c=skip_till_newline(c);
    2369
             break;
    2370
        case V('B','k'):    /* BSD mandoc */
    2371
        case V('E','k'):    /* BSD mandoc */
    2372
        case V('D','d'):    /* BSD mandoc */
    2373
        case V('O','s'):    /* BSD mandoc */
    2374
             trans_char(c,'"','\a');
    2375
             c=c+j;
    2376
             if (*c == '\n') c++;
    2377
             c=scan_troff_mandoc(c, 1, NULL);
    2378
             out_html(NEWLINE);
    2379
             if (fillout) curpos++; else curpos=0;
    2380
             break;
    2381
        case V('B','t'):    /* BSD mandoc */
    2382
             trans_char(c,'"','\a');
    2383
             c=c+j;
    2384
             out_html(" is currently in beta test.");
    2385
             if (fillout) curpos++; else curpos=0;
    2386
             break;
    2387
        case V('B','x'):    /* BSD mandoc */
    2388
             trans_char(c,'"','\a');
    2389
             c=c+j;
    2390
             if (*c == '\n') c++;
    2391
             out_html("BSD ");
    2392
             c=scan_troff_mandoc(c, 1, NULL);
    2393
             if (fillout) curpos++; else curpos=0;
    2394
             break;
    2395
        case V('D','l'):    /* BSD mandoc */
    2396
             c=c+j;
    2397
             out_html(NEWLINE);
    2398
             out_html("
    ");
    2399
             out_html(change_to_font('L'));
    2400
             if (*c == '\n') c++;
    2401
             c=scan_troff_mandoc(c, 1, NULL);
    2402
             out_html(change_to_font('R'));
    2403
             out_html("");
    2404
             if (fillout) curpos++; else curpos=0;
    2405
             break;
    2406
        case V('B','d'):    /* BSD mandoc */
    2407
        {            /* Seems like a kind of example/literal mode */
    2408
             char *nl, t=0 /* just for gcc */;
    2409
             c=c+j;
    2410
             nl = strchr(c,'\n');
    2411
             if (nl) {
    2412
              t = *nl;
    2413
              *nl = 0;
    2414
             }
    2415
             out_html(NEWLINE);
    2416
             mandoc_bd_options = 0; /* Remember options for terminating Bl */
    2417
             if (strstr(c, "-offset indent")) {
    2418
              mandoc_bd_options |= BD_INDENT;
    2419
              out_html("
    \n");
    2420
             }
    2421
             if (strstr(c, "-literal") || strstr(c, "-unfilled")) {
    2422
              if (fillout) {
    2423
                   mandoc_bd_options |= BD_LITERAL;
    2424
                   out_html(change_to_font(0));
    2425
                   out_html(change_to_size('0'));
    2426
                   out_html("
    \n");
    2427
              }
    2428
              curpos=0;
    2429
              fillout=0;
    2430
             }
    2431
             if (nl)
    2432
              *nl = t;
    2433
             c=skip_till_newline(c);
    2434
             break;
    2435
        }
    2436
        case V('E','d'):    /* BSD mandoc */
    2437
             if (mandoc_bd_options & BD_LITERAL) {
    2438
              if (!fillout) {
    2439
                   out_html(change_to_font(0));
    2440
                   out_html(change_to_size('0'));
    2441
                   out_html("
    \n");
    2442
              }
    2443
             }
    2444
             if (mandoc_bd_options & BD_INDENT)
    2445
              out_html("\n");
    2446
             curpos=0;
    2447
             fillout=1;
    2448
             c=skip_till_newline(c);
    2449
             break;
    2450
        case V('B','e'):    /* BSD mandoc */
    2451
             c=c+j;
    2452
             if (fillout) out_html("

    "); else {

    2453
              out_html(NEWLINE);
    2454
              NEWLINE[0]='\n';
    2455
             }
    2456
             curpos=0;
    2457
             c=skip_till_newline(c);
    2458
             break;
    2459
        case V('X','r'):    /* BSD mandoc */
    2460
        {
    2461
             /* Translate xyz 1 to xyz(1)
    2462
              * Allow for multiple spaces.  Allow the section to be missing.
    2463
              */
    2464
             char buff[100];
    2465
             char *bufptr;
    2466
             trans_char(c,'"','\a');
    2467
             bufptr = buff;
    2468
             c = c+j;
    2469
             if (*c == '\n') c++; /* Skip spaces */
    2470
             while (isspace(*c) && *c != '\n') c++;
    2471
             while (isalnum(*c) && bufptr < buff + SIZE(buff)-4) {
    2472
              /* Copy the xyz part */
    2473
              *bufptr++ = *c++;
    2474
             }
    2475
             while (isspace(*c) && *c != '\n') c++;    /* Skip spaces */
    2476
             if (isdigit(*c)) { /* Convert the number if there is one */
    2477
              *bufptr++ = '(';
    2478
              while (isalnum(*c) && bufptr < buff + SIZE(buff)-3) {
    2479
                   *bufptr++ = *c++;
    2480
              }
    2481
              *bufptr++ = ')';
    2482
             }
    2483
             while (*c != '\n' && bufptr < buff + SIZE(buff)-2) {
    2484
              /* Copy the remainder */
    2485
              if (!isspace(*c)) {
    2486
                   *bufptr++ = *c;
    2487
              }
    2488
              c++;
    2489
             }
    2490
             *bufptr++ = '\n';
    2491
             *bufptr = 0;
    2492
             scan_troff_mandoc(buff, 1, NULL);
    2493
             out_html(NEWLINE);
    2494
             if (fillout) curpos++; else curpos=0;
    2495
        }
    2496
        break;
    2497
        case V('F','l'):    /* BSD mandoc */
    2498
             trans_char(c,'"','\a');
    2499
             c=c+j;
    2500
             out_html("-");
    2501
             if (*c!='\n') {
    2502
              out_html(change_to_font('B'));
    2503
              c=scan_troff_mandoc(c, 1, NULL);
    2504
              out_html(change_to_font('R'));
    2505
             }
    2506
             out_html(NEWLINE);
    2507
             if (fillout) curpos++; else curpos=0;
    2508
             break;
    2509
        case V('P','a'):    /* BSD mandoc */
    2510
        case V('P','f'):    /* BSD mandoc */
    2511
             trans_char(c,'"','\a');
    2512
             c=c+j;
    2513
             if (*c == '\n') c++;
    2514
             c=scan_troff_mandoc(c, 1, NULL);
    2515
             out_html(NEWLINE);
    2516
             if (fillout) curpos++; else curpos=0;
    2517
             break;
    2518
        case V('P','p'):    /* BSD mandoc */
    2519
             if (fillout) out_html("

    \n"); else {

    2520
              out_html(NEWLINE);
    2521
              NEWLINE[0]='\n';
    2522
             }
    2523
             curpos=0;
    2524
             c=skip_till_newline(c);
    2525
             break;
    2526
        case V('D','q'):    /* BSD mandoc */
    2527
             trans_char(c,'"','\a');
    2528
             c=c+j;
    2529
             if (*c == '\n') c++;
    2530
             out_html("``");
    2531
             c=scan_troff_mandoc(c, 1, NULL);
    2532
             out_html("''");
    2533
             out_html(NEWLINE);
    2534
             if (fillout) curpos++; else curpos=0;
    2535
             break;
    2536
        case V('O','p'):    /* BSD mandoc */
    2537
             trans_char(c,'"','\a');
    2538
             c=c+j;
    2539
             if (*c == '\n') c++;
    2540
             out_html(change_to_font('R'));
    2541
             out_html("[");
    2542
             c=scan_troff_mandoc(c, 1, NULL);
    2543
             out_html(change_to_font('R'));
    2544
             out_html("]");
    2545
             out_html(NEWLINE);
    2546
             if (fillout) curpos++; else curpos=0;
    2547
             break;
    2548
        case V('O','o'):    /* BSD mandoc */
    2549
             trans_char(c,'"','\a');
    2550
             c=c+j;
    2551
             if (*c == '\n') c++;
    2552
             out_html(change_to_font('R'));
    2553
             out_html("[");
    2554
             c=scan_troff_mandoc(c, 1, NULL);
    2555
             if (fillout) curpos++; else curpos=0;
    2556
             break;
    2557
        case V('O','c'):    /* BSD mandoc */
    2558
             trans_char(c,'"','\a');
    2559
             c=c+j;
    2560
             c=scan_troff_mandoc(c, 1, NULL);
    2561
             out_html(change_to_font('R'));
    2562
             out_html("]");
    2563
             if (fillout) curpos++; else curpos=0;
    2564
             break;
    2565
        case V('P','q'):    /* BSD mandoc */
    2566
             trans_char(c,'"','\a');
    2567
             c=c+j;
    2568
             if (*c == '\n') c++;
    2569
             out_html("(");
    2570
             c=scan_troff_mandoc(c, 1, NULL);
    2571
             out_html(")");
    2572
             out_html(NEWLINE);
    2573
             if (fillout) curpos++; else curpos=0;
    2574
             break;
    2575
        case V('Q','l'):    /* BSD mandoc */
    2576
        {            /* Single quote first word in the line */
    2577
             char *sp;
    2578
             trans_char(c,'"','\a');
    2579
             c=c+j;
    2580
             if (*c == '\n') c++;
    2581
             sp = c;
    2582
             do {        /* Find first whitespace after the
    2583
                     * first word that isn't a mandoc macro
    2584
                     */
    2585
              while (*sp && isspace(*sp)) sp++;
    2586
              while (*sp && !isspace(*sp)) sp++;
    2587
             } while (*sp && isupper(*(sp-2)) && islower(*(sp-1)));
    9278 navichok26 2588
     
    9280 turbocat 2589
                /* Use a newline to mark the end of text to
    2590
                 * be quoted
    2591
                 */
    2592
             if (*sp) *sp = '\n';
    2593
             out_html("`");    /* Quote the text */
    2594
             c=scan_troff_mandoc(c, 1, NULL);
    2595
             out_html("'");
    2596
             out_html(NEWLINE);
    2597
             if (fillout) curpos++; else curpos=0;
    2598
             break;
    2599
        }
    2600
        case V('S','q'):    /* BSD mandoc */
    2601
             trans_char(c,'"','\a');
    2602
             c=c+j;
    2603
             if (*c == '\n') c++;
    2604
             out_html("`");
    2605
             c=scan_troff_mandoc(c, 1, NULL);
    2606
             out_html("'");
    2607
             out_html(NEWLINE);
    2608
             if (fillout) curpos++; else curpos=0;
    2609
             break;
    2610
        case V('A','r'):    /* BSD mandoc */
    2611
             /* parse one line in italics */
    2612
             out_html(change_to_font('I'));
    2613
             trans_char(c,'"','\a');
    2614
             c=c+j;
    2615
             if (*c == '\n') {    /* An empty Ar means "file ..." */
    2616
              out_html("file ...");
    2617
             } else {
    2618
              c=scan_troff_mandoc(c, 1, NULL);
    2619
             }
    2620
             out_html(change_to_font('R'));
    2621
             out_html(NEWLINE);
    2622
             if (fillout) curpos++; else curpos=0;
    2623
             break;
    2624
        case V('A','d'):    /* BSD mandoc */
    2625
        case V('E','m'):    /* BSD mandoc */
    2626
        case V('V','a'):    /* BSD mandoc */
    2627
             /* parse one line in italics */
    2628
             out_html(change_to_font('I'));
    2629
             trans_char(c,'"','\a');
    2630
             c=c+j;
    2631
             if (*c == '\n') c++;
    2632
             c=scan_troff_mandoc(c, 1, NULL);
    2633
             out_html(change_to_font('R'));
    2634
             out_html(NEWLINE);
    2635
             if (fillout) curpos++; else curpos=0;
    2636
             break;
    2637
        case V('N','d'):    /* BSD mandoc */
    2638
             trans_char(c,'"','\a');
    2639
             c=c+j;
    2640
             if (*c == '\n') c++;
    2641
             out_html(" - ");
    2642
             c=scan_troff_mandoc(c, 1, NULL);
    2643
             out_html(NEWLINE);
    2644
             if (fillout) curpos++; else curpos=0;
    2645
             break;
    2646
        case V('N','m'):    /* BSD mandoc */
    2647
        {
    2648
             static char *mandoc_name = 0;
    2649
             trans_char(c,'"','\a');
    2650
             c=c+j;
    2651
             if (mandoc_synopsis) {
    2652
              /*
    2653
               * Break lines only in the Synopsis.
    2654
               * The Synopsis section seems to be treated
    2655
               * as a special case - Bummer!
    2656
               */
    2657
              static int count = 0; /* Don't break on the first Nm */
    2658
              if (count) {
    2659
                   out_html("
    ");
    2660
              } else {
    2661
                   char *end, t=0 /* just for gcc */;
    2662
                   end = strchr(c, '\n');
    2663
                   if (end) {
    2664
                    t = *end;
    2665
                    *end = 0;
    2666
                   }
    2667
                   if (mandoc_name)
    2668
                    free(mandoc_name);
    2669
                   mandoc_name = xstrdup(c);
    2670
                   if (end)
    2671
                    *end = t;
    2672
              }
    2673
              count++;
    2674
             }
    2675
             out_html(change_to_font('B'));
    2676
             while (*c == ' ' || *c == '\t') c++;
    2677
             if (*c == '\n') {
    2678
              /*
    2679
               * If Nm has no argument, use one from an earlier
    2680
               * Nm command that did have one.  Hope there aren't
    2681
               * too many commands that do this.
    2682
               */
    2683
              if (mandoc_name)
    2684
                   out_html(mandoc_name);
    2685
             } else {
    2686
              c=scan_troff_mandoc(c, 1, NULL);
    2687
             }
    2688
             out_html(change_to_font('R'));
    2689
             out_html(NEWLINE);
    2690
             if (fillout) curpos++; else curpos=0;
    2691
             break;
    2692
        }
    2693
        case V('C','d'):    /* BSD mandoc */
    2694
        case V('C','m'):    /* BSD mandoc */
    2695
        case V('I','c'):    /* BSD mandoc */
    2696
        case V('M','s'):    /* BSD mandoc */
    2697
        case V('O','r'):    /* BSD mandoc */
    2698
        case V('S','y'):    /* BSD mandoc */
    2699
             /* parse one line in bold */
    2700
             out_html(change_to_font('B'));
    2701
             trans_char(c,'"','\a');
    2702
             c=c+j;
    2703
             if (*c == '\n') c++;
    2704
             c=scan_troff_mandoc(c, 1, NULL);
    2705
             out_html(change_to_font('R'));
    2706
             out_html(NEWLINE);
    2707
             if (fillout) curpos++; else curpos=0;
    2708
             break;
    2709
        case V('D','v'):    /* BSD mandoc */
    2710
        case V('E','v'):    /* BSD mandoc */
    2711
        case V('F','r'):    /* BSD mandoc */
    2712
        case V('L','i'):    /* BSD mandoc */
    2713
        case V('N','o'):    /* BSD mandoc */
    2714
        case V('N','s'):    /* BSD mandoc */
    2715
        case V('T','n'):    /* BSD mandoc */
    2716
        case V('n','N'):    /* BSD mandoc */
    2717
             trans_char(c,'"','\a');
    2718
             c=c+j;
    2719
             if (*c == '\n') c++;
    2720
             out_html(change_to_font('B'));
    2721
             c=scan_troff_mandoc(c, 1, NULL);
    2722
             out_html(change_to_font('R'));
    2723
             out_html(NEWLINE);
    2724
             if (fillout) curpos++; else curpos=0;
    2725
             break;
    2726
        case V('%','A'):    /* BSD mandoc biblio stuff */
    2727
        case V('%','D'):
    2728
        case V('%','N'):
    2729
        case V('%','O'):
    2730
        case V('%','P'):
    2731
        case V('%','Q'):
    2732
        case V('%','V'):
    2733
             c=c+j;
    2734
             if (*c == '\n') c++;
    2735
             c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */
    2736
             if (fillout) curpos++; else curpos=0;
    2737
             break;
    2738
        case V('%','B'):
    2739
        case V('%','J'):
    2740
        case V('%','R'):
    2741
        case V('%','T'):
    2742
             c=c+j;
    2743
             out_html(change_to_font('I'));
    2744
             if (*c == '\n') c++;
    2745
             c=scan_troff(c, 1, NULL); /* Don't allow embedded mandoc coms */
    2746
             out_html(change_to_font('R'));
    2747
             if (fillout) curpos++; else curpos=0;
    2748
             break;
    9278 navichok26 2749
            /* ----- end of BSD mandoc stuff ----- */
    2750
     
    9280 turbocat 2751
         default:
    9278 navichok26 2752
                 /* search macro database of self-defined macros */
    9280 turbocat 2753
             owndef = defdef;
    2754
            while (owndef && owndef->nr!=i) owndef=owndef->next;
    2755
            if (owndef) {
    2756
            char **oldargument;
    2757
            int deflen;
    2758
            int onff;
    2759
            sl=fill_words(c+j, wordlist, SIZE(wordlist), &words, '\n');
    2760
            c=sl+1;
    2761
            *sl=0;
    2762
            for (i=1; i
            
            
               
               
               2763
               
                wordlist[i][-1]=0;
    2764
            for (i=0; i
            
            
               
               
               2765
               
                char *h=NULL;
    2766
                if (mandoc_command)
    2767
                 scan_troff_mandoc(wordlist[i],1,&h);
    2768
                else
    2769
                 scan_troff(wordlist[i],1,&h);
    2770
                wordlist[i]=h;
    2771
            }
    2772
            for (i=words; i
            
            
               
               
               2773
               
                wordlist[i]=NULL;
    2774
            deflen = strlen(owndef->st);
    2775
            owndef->st[deflen+1]='a';
    2776
            for (i=0; (owndef->st[deflen+2+i] = owndef->st[i]); i++);
    2777
            oldargument=argument;
    2778
            argument=wordlist;
    2779
            onff=newline_for_fun;
    2780
            if (mandoc_command)
    2781
                 scan_troff_mandoc(owndef->st+deflen+2, 0, NULL);
    2782
            else
    2783
                 scan_troff(owndef->st+deflen+2, 0, NULL);
    2784
            newline_for_fun=onff;
    2785
            argument=oldargument;
    2786
            for (i=0; i
            
            
               
               
               2787
               
            *sl='\n';
    2788
            } else if (mandoc_command &&
    2789
                   ((isupper(*c) && islower(c[1]))
    2790
                || (islower(*c) && isupper(c[1])))) {
    2791
             /*
    2792
              * Let through any BSD mandoc commands that haven't
    2793
              * been dealt with.
    2794
              * I don't want to miss anything out of the text.
    2795
              */
    9278 navichok26 2796
                   char buf[4];
    2797
                   strncpy(buf,c,2);
    2798
                   buf[2] = ' ';
    2799
                   buf[3] = 0;
    2800
                   out_html(buf);  /* Print the command (it might just be text). */
    2801
                   c=c+j;
    2802
                   trans_char(c,'"','\a');
    9280 turbocat 2803
                   if (*c == '\n') c++;     /* really? */
    9278 navichok26 2804
                   out_html(change_to_font('R'));
    2805
                   c=scan_troff(c, 1, NULL);
    2806
                   out_html(NEWLINE);
    2807
                   if (fillout) curpos++; else curpos=0;
    9280 turbocat 2808
            } else
    2809
            c=skip_till_newline(c);
    2810
            break;
    9278 navichok26 2811
        }
    9280 turbocat 2812
        }
    9278 navichok26 2813
        if (fillout) { out_html(NEWLINE); curpos++; }
    2814
        NEWLINE[0]='\n';
    2815
        return c;
    2816
    }
    2817
     
    2818
    static int contained_tab=0;
    2819
    static int mandoc_line=0;/* Signals whether to look for embedded mandoc cmds */
    2820
     
    2821
    static char *
    2822
    scan_troff(char *c, int san, char **result) {   /* san : stop at newline */
    2823
        char *h;
    2824
        char intbuff[500];
    2825
        int ibp=0;
    2826
    #define FLUSHIBP  if (ibp) { intbuff[ibp]=0; out_html(intbuff); ibp=0; }
    2827
        char *exbuffer;
    2828
        int exbuffpos, exbuffmax, exscaninbuff, exnewline_for_fun;
    2829
        int usenbsp = 0;
    2830
     
    2831
        exbuffer = buffer;
    2832
        exbuffpos = buffpos;
    2833
        exbuffmax = buffmax;
    2834
        exnewline_for_fun = newline_for_fun;
    2835
        exscaninbuff = scaninbuff;
    2836
        newline_for_fun = 0;
    2837
        if (result) {
    9280 turbocat 2838
        if (*result) {
    2839
            buffer = *result;
    2840
            buffpos = strlen(buffer);
    2841
            buffmax = buffpos;
    2842
        } else {
    2843
            buffer = (char *) xmalloc(1000*sizeof(char));
    2844
            buffpos = 0;
    2845
            buffmax = 1000;
    9278 navichok26 2846
        }
    9280 turbocat 2847
        scaninbuff = 1;
    2848
        }
    9278 navichok26 2849
        h = c;
    2850
        /* start scanning */
    2851
        while (*h && (!san || newline_for_fun || *h != '\n')) {
    9280 turbocat 2852
        if (*h == escapesym) {
    2853
            h++;
    2854
            FLUSHIBP;
    2855
            h = scan_escape(h);
    2856
        } else if (*h == controlsym && h[-1] == '\n') {
    2857
            h++;
    2858
            FLUSHIBP;
    2859
            h = scan_request(h);
    2860
            if (san && h[-1] == '\n') h--;
    2861
        } else if (mandoc_line
    2862
               && *(h) && isupper(*(h))
    2863
               && *(h+1) && islower(*(h+1))
    2864
               && *(h+2) && isspace(*(h+2))) {
    2865
             /* BSD imbedded command eg ".It Fl Ar arg1 Fl Ar arg2" */
    2866
             FLUSHIBP;
    2867
             h = scan_request(h);
    2868
             if (san && h[-1] == '\n') h--;
    2869
        } else if (*h == nobreaksym && h[-1] == '\n') {
    2870
            h++;
    2871
            FLUSHIBP;
    2872
            h = scan_request(h);
    2873
            if (san && h[-1] == '\n') h--;
    2874
        } else {
    2875
            if (h[-1] == '\n' && still_dd && isalnum(*h)) {
    2876
            /* sometimes a .HP request is not followed by a .br request */
    2877
            FLUSHIBP;
    2878
            out_html("
    ");
    2879
            curpos=0;
    2880
            still_dd=0;
    2881
            }
    2882
            switch (*h) {
    2883
            case '&':
    2884
            intbuff[ibp++]='&';
    2885
            intbuff[ibp++]='a';
    2886
            intbuff[ibp++]='m';
    2887
            intbuff[ibp++]='p';
    2888
            intbuff[ibp++]=';';
    2889
            curpos++;
    2890
            break;
    2891
            case '<':
    2892
            intbuff[ibp++]='&';
    2893
            intbuff[ibp++]='l';
    2894
            intbuff[ibp++]='t';
    2895
            intbuff[ibp++]=';';
    2896
            curpos++;
    2897
            break;
    2898
            case '>':
    2899
            intbuff[ibp++]='&';
    2900
            intbuff[ibp++]='g';
    2901
            intbuff[ibp++]='t';
    2902
            intbuff[ibp++]=';';
    2903
            curpos++;
    2904
            break;
    2905
            case '"':
    2906
            intbuff[ibp++]='&';
    2907
            intbuff[ibp++]='q';
    2908
            intbuff[ibp++]='u';
    2909
            intbuff[ibp++]='o';
    2910
            intbuff[ibp++]='t';
    2911
            intbuff[ibp++]=';';
    2912
            curpos++;
    2913
            break;
    2914
            case '\n':
    2915
            if (h[-1] == '\n' && fillout) {
    2916
                intbuff[ibp++]='<';
    2917
                intbuff[ibp++]='P';
    2918
                intbuff[ibp++]='>';
    2919
            }
    2920
            if (contained_tab && fillout) {
    2921
                intbuff[ibp++]='<';
    2922
                intbuff[ibp++]='B';
    2923
                intbuff[ibp++]='R';
    2924
                intbuff[ibp++]='>';
    2925
            }
    2926
            contained_tab=0;
    2927
            curpos=0;
    2928
            usenbsp=0;
    2929
            intbuff[ibp++]='\n';
    2930
            break;
    2931
            case '\t':
    2932
            {
    2933
                int curtab=0;
    2934
                contained_tab=1;
    2935
                FLUSHIBP;
    2936
                /* like a typewriter, not like TeX */
    2937
                tabstops[SIZE(tabstops)-1] = curpos+1;
    2938
                while (curtab < maxtstop && tabstops[curtab] <= curpos)
    2939
                curtab++;
    2940
                if (curtab < maxtstop) {
    2941
                if (!fillout) {
    2942
                    while (curpos
            
            
               
               
               2943
               
                    intbuff[ibp++]=' ';
    2944
                    if (ibp>480) { FLUSHIBP; }
    2945
                    curpos++;
    2946
                    }
    2947
                } else {
    2948
                    out_html("");
    2949
                    while (curpos < tabstops[curtab]) {
    2950
                    out_html(" ");
    2951
                    curpos++;
    2952
                    }
    2953
                    out_html("");
    2954
                }
    2955
                }
    2956
            }
    2957
            break;
    2958
            default:
    2959
            if (*h == ' ' && (h[-1] == '\n' || usenbsp)) {
    2960
                FLUSHIBP;
    2961
                if (!usenbsp && fillout) {
    2962
                out_html("
    ");
    2963
                curpos=0;
    2964
                }
    2965
                usenbsp=fillout;
    2966
                if (usenbsp) out_html(" "); else intbuff[ibp++]=' ';
    2967
            } else if (*h > 31 && *h < 127) {
    2968
                intbuff[ibp++]=*h;
    2969
            } else if (((unsigned char)(*h)) > 127) {
    9278 navichok26 2970
    #ifdef NO_8BIT
    9280 turbocat 2971
                intbuff[ibp++]='&';
    2972
                intbuff[ibp++]='#';
    2973
                intbuff[ibp++]='0'+((unsigned char)(*h))/100;
    2974
                intbuff[ibp++]='0'+(((unsigned char)(*h))%100)/10;
    2975
                intbuff[ibp++]='0'+((unsigned char)(*h))%10;
    2976
                intbuff[ibp++]=';';
    9278 navichok26 2977
    #else
    9280 turbocat 2978
                intbuff[ibp++]=*h;
    9278 navichok26 2979
    #endif
    9280 turbocat 2980
            }
    2981
            curpos++;
    2982
            break;
    2983
            }
    2984
            if (ibp>480) FLUSHIBP;
    2985
            h++;
    9278 navichok26 2986
        }
    9280 turbocat 2987
        }
    9278 navichok26 2988
        FLUSHIBP;
    2989
        if (buffer) buffer[buffpos]=0;
    2990
        if (san && *h) h++;
    2991
        newline_for_fun=exnewline_for_fun;
    2992
        if (result) {
    9280 turbocat 2993
        *result = buffer;
    2994
        buffer=exbuffer;
    2995
        buffpos=exbuffpos;
    2996
        buffmax=exbuffmax;
    2997
        scaninbuff=exscaninbuff;
    9278 navichok26 2998
        }
    2999
        return h;
    3000
    }
    3001
     
    3002
    static char *scan_troff_mandoc(char *c, int san, char **result) {
    3003
         char *ret, *end = c;
    3004
         int oldval = mandoc_line;
    3005
         mandoc_line = 1;
    3006
         while (*end && *end != '\n') {
    9280 turbocat 3007
          end++;
    9278 navichok26 3008
         }
    3009
     
    3010
         if (end > c + 2
    9280 turbocat 3011
         && ispunct(*(end - 1))
    3012
         && isspace(*(end - 2)) && *(end - 2) != '\n') {
    3013
          /*
    3014
           * Don't format lonely punctuation. E.g. in "xyz ," format
    3015
           * the xyz and then append the comma removing the space.
    3016
           */
    3017
          *(end - 2) = '\n';
    3018
          ret = scan_troff(c, san, result);
    3019
          *(end - 2) = *(end - 1);
    3020
          *(end - 1) = ' ';
    9278 navichok26 3021
         } else {
    9280 turbocat 3022
          ret = scan_troff(c, san, result);
    9278 navichok26 3023
         }
    3024
         mandoc_line = oldval;
    3025
         return ret;
    3026
    }
    3027
     
    3028
    STRDEF *foundpages=NULL;
    3029
     
    3030
    #define BUFSMSG 1024
    3031
    static void
    3032
    error_page(char *s, char *t, ...) {
    9280 turbocat 3033
        va_list p;
    3034
        char buf[BUFSMSG];
    3035
        char notify_buf[BUFSMSG+5];
    3036
        va_start(p, t);
    3037
        vsnprintf(buf, BUFSMSG, t, p);
    3038
        va_end(p);
    9278 navichok26 3039
    #ifdef _KOLIBRI
    9280 turbocat 3040
        snprintf(notify_buf, BUFSMSG+5, "'%s' -E", buf);
    3041
        _ksys_exec("/sys/@notify", buf);
    9278 navichok26 3042
    #else
    9280 turbocat 3043
        printf("%s %s\n", s, buf);
    9278 navichok26 3044
    #endif
    9280 turbocat 3045
        exit(0);
    9278 navichok26 3046
    }
    3047
     
    3048
    char *
    3049
    xstrdup(const char *s) {
    3050
         char *p = strdup(s);
    3051
         if (p == NULL)
    9280 turbocat 3052
          error_page("Out of memory",
    3053
                 "Sorry, out of memory, aborting...\n");
    9278 navichok26 3054
         return p;
    3055
    }
    3056
     
    3057
    void *
    3058
    xmalloc(size_t size) {
    3059
         void *p = malloc(size);
    3060
         if (p == NULL)
    9280 turbocat 3061
          error_page("Out of memory",
    3062
                 "Sorry, out of memory, aborting...\n");
    9278 navichok26 3063
         return p;
    3064
    }
    3065
     
    3066
    void *
    3067
    xrealloc(void *ptr, size_t size) {
    3068
         void *p = realloc(ptr,size);
    3069
         if (p == NULL)
    9280 turbocat 3070
          error_page("Out of memory",
    3071
                 "Sorry, out of memory, aborting...\n");
    9278 navichok26 3072
         return p;
    3073
    }
    3074
     
    3075
    static void
    3076
    usage(void) {
    9280 turbocat 3077
    #ifdef _KOLIBRI
    3078
         _ksys_exec("/sys/@notify", "'Usage: man2html in_file [out_file.html]' -I");
    3079
    #else
    3080
         puts("Usage: man2html in_file [out_file.html]");
    3081
    #endif
    3082
         exit(0);
    9278 navichok26 3083
    }
    3084
     
    9280 turbocat 3085
    #if 0
    9278 navichok26 3086
    static void
    3087
    goto_dir(char *path, char **dir, char **name) {
    3088
         char *s, *t, *u;
    3089
     
    3090
         s = xstrdup(path);
    3091
         t = strrchr(s, '/');
    3092
         if (t) {
    9280 turbocat 3093
          *t = 0;
    3094
          u = strrchr(s, '/');
    3095
          *t = '/';
    3096
          if (u) {
    3097
              *u = 0;
    9278 navichok26 3098
    #ifdef _KOLIBRI
    9280 turbocat 3099
              setcwd(s);
    9278 navichok26 3100
    #else
    9280 turbocat 3101
              chdir(s);
    9278 navichok26 3102
    #endif
    9280 turbocat 3103
              if (dir)
    3104
                  *dir = s;
    3105
              if (name)
    3106
                   *name = u+1;
    9278 navichok26 3107
    #if 0
    9280 turbocat 3108
               else  /* complain or not - this need not be fatal */
    3109
                error_page("Error", "man2html: could not chdir to %s", s);
    9278 navichok26 3110
    #endif
    9280 turbocat 3111
          }
    9278 navichok26 3112
         }
    3113
    }
    9280 turbocat 3114
    #endif
    9278 navichok26 3115
     
    9280 turbocat 3116
    char
    3117
    *temp_file_name(char* in_path){
    3118
        char* in_name = basename(in_path);
    3119
        #define PST_SIZE 5
    3120
        const char* pst = ".html";
    3121
    #ifdef _KOLIBRI
    3122
        #define TMP_PATH_SIZE 9
    3123
        const char* tmp_path = "/tmp0/1/";
    3124
    #else
    3125
        #define TMP_PATH_SIZE 2
    3126
        const char* tmp_path = "./";
    3127
    #endif
    3128
        char* full_name = xmalloc((TMP_PATH_SIZE+strlen(in_name)+PST_SIZE+1)*sizeof(char));
    3129
        strcpy(full_name, tmp_path);
    3130
        strcat(full_name, in_name);
    3131
        strcat(full_name, pst);
    3132
        return full_name;
    3133
    }
    3134
     
    9278 navichok26 3135
    int
    3136
    main(int argc, char **argv) {
    3137
        FILE *f;
    3138
        int l, c;
    3139
        char *buf, *filename, *fnam = NULL;
    3140
        char *outfilename;
    9280 turbocat 3141
     
    3142
        if (argc < 2){
    3143
            usage();
    3144
        }
    3145
     
    9278 navichok26 3146
        /* Find filename */
    9280 turbocat 3147
        if (argc > 1) {
    3148
            fnam = argv[1];
    3149
            outfilename = temp_file_name(fnam);
    3150
        }
    9278 navichok26 3151
        if (argc > 2) {
    9280 turbocat 3152
            outfilename = argv[2];
    9278 navichok26 3153
        }
    3154
     
    3155
        if ((out = fopen(outfilename, "w")) == NULL) {
    9280 turbocat 3156
            error_page("Error!", "Cannot open file %s", outfilename);
    3157
            return 0;
    3158
        }
    9278 navichok26 3159
     
    3160
        filename = fnam;
    9280 turbocat 3161
        //directory = 0;
    9278 navichok26 3162
     
    3163
        /* Open input file */
    9280 turbocat 3164
         //goto_dir(fnam, &directory, &fnam);
    9278 navichok26 3165
     
    9280 turbocat 3166
         f = fopen(fnam, "r");
    3167
         if (f == NULL)
    3168
              error_page("File not found", "Could not open %s\n", filename);
    3169
         fname = fnam;
    9278 navichok26 3170
     
    3171
        /* Read entire file into buf[1..l] */
    3172
    #define XTRA 5
    3173
        /* buf has 1 extra byte at the start, and XTRA extra bytes at the end */
    3174
        int ct;
    3175
     
    3176
        l = 0;
    3177
     
    3178
    #ifdef _KOLIBRI
    3179
        ksys_bdfe_t bdfe;
    3180
        _ksys_file_get_info(filename, &bdfe);
    3181
        l = bdfe.size;
    3182
    #else
    9280 turbocat 3183
        struct stat stbuf;
    3184
        if (stat(filename, &stbuf) != -1) l=stbuf.st_size;
    9278 navichok26 3185
    #endif
    3186
     
    3187
        buf = (char *) xmalloc((l+1+XTRA)*sizeof(char));
    3188
        ct = fread(buf+1,1,l,f);
    3189
        if (ct < l)
    9280 turbocat 3190
            l = ct;
    9278 navichok26 3191
        fclose(f);
    3192
     
    3193
        buf[0] = '\n';
    3194
        buf[l+1] = '\n';
    3195
        buf[l+2] = buf[l+3] = 0;
    3196
     
    3197
    #ifdef MAKEINDEX
    3198
        idxfile = fopen(INDEXFILE, "a");
    3199
    #endif
    3200
        stdinit();
    3201
        scan_troff(buf+1,0,NULL);
    3202
        dl_down();
    3203
        out_html(change_to_font(0));
    3204
        out_html(change_to_size(0));
    3205
        if (!fillout) {
    9280 turbocat 3206
        fillout=1;
    3207
        out_html("
    ");
    9278 navichok26 3208
        }
    3209
        out_html(NEWLINE);
    3210
        if (output_possible) {
    9280 turbocat 3211
        /*   for mosaic users */
    3212
        fprintf(out, "
    \n 

    Index

    \n
    \n");
    3213
        manidx[mip]=0;
    3214
        fprintf(out, "%s", manidx);
    3215
        if (subs) fprintf(out,"\n");
    3216
        fprintf(out, "\n");
    3217
        print_sig();
    3218
        fprintf(out, "\n\n");
    9278 navichok26 3219
        } else {
    9280 turbocat 3220
        if (!filename)
    3221
             filename = fname;
    3222
        if (*filename == '/')
    3223
             error_page("Invalid Manpage",
    3224
               "The requested file %s is not a valid (unformatted) "
    3225
               "man page.\nIf the file is a formatted manpage, "
    3226
               "you could try to load the\n"
    3227
               "plain file.\n",
    3228
               filename, filename);
    3229
        else
    3230
             error_page("Invalid Manpage",
    3231
               "The requested file %s is not a valid (unformatted) "
    3232
               "man page.", filename);
    9278 navichok26 3233
        }
    3234
        if (idxfile)
    9280 turbocat 3235
            fclose(idxfile);
    9278 navichok26 3236
        if (buf)
    9280 turbocat 3237
            free(buf);
    3238
    #ifdef _KOLIBRI
    3239
        if(argc==2){
    3240
            _ksys_exec("/sys/network/webview", outfilename);
    3241
        }
    3242
    #endif
    9278 navichok26 3243
        return 0;
    3244
    }