1 /* yat2m.c - Yet Another Texi 2 Man converter
2 * Copyright (C) 2005 g10 Code GmbH
3 * Copyright (C) 2006 2006 Free Software Foundation, Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 This is a simple textinfo to man page converter. It needs some
23 special markup in th e texinfo and tries best to get a create man
24 page. It has been designed for the GnuPG man pages and thus only
25 a few texinfo commands are supported.
27 To use this you need to add the following macros into your texinfo
39 They are used by yat2m to select parts of the Texinfo which should
40 go into the man page. These macros need to be used without leading
41 left space. Processing starts after a "manpage" macro has been
42 seen. "mansect" identifies the section and yat2m make sure to
43 emit the sections in the proper order. Note that @mansect skips
44 the next input line if that line begins with @section, @subsection or
47 To insert verbatim troff markup, the follwing texinfo code may be
54 alternativly a special comment may be used:
56 @c man:.B whatever you want
58 This is useful in case you need just one line. If you want to
59 include parts only in the man page but keep the texinfo
60 translation you may use:
63 stuff to be rendered only on man pages
66 or to exclude stuff from man pages:
69 stuff not to be rendered on man pages
72 the keyword @section is ignored, however @subsection gets rendered
73 as ".SS". @menu is completely skipped. Several man pages may be
74 extracted from one file, either using the --store or the --select
94 /* The maximum length of a line including the linefeed and one extra
102 static const char *opt_source
;
103 static const char *opt_release
;
104 static const char *opt_select
;
105 static const char *opt_include
;
106 static int opt_store
;
108 /* The only define we understand is -D gpgone. Thus we need a simple
109 boolean tro track it. */
110 static int gpgone_defined
;
112 /* Flag to keep track whether any error occurred. */
113 static int any_error
;
116 /* Object to keep macro definitions. */
119 struct macro_s
*next
;
120 char *value
; /* Malloced value. */
123 typedef struct macro_s
*macro_t
;
125 /* List of all defined macros. */
126 static macro_t macrolist
;
129 /* Object to store one line of content. */
132 struct line_buffer_s
*next
;
133 int verbatim
; /* True if LINE contains verbatim data. The default
134 is Texinfo source. */
137 typedef struct line_buffer_s
*line_buffer_t
;
140 /* Object to collect the data of a section. */
141 struct section_buffer_s
143 char *name
; /* Malloced name of the section. This may be
144 NULL to indicate this slot is not used. */
145 line_buffer_t lines
; /* Linked list with the lines of the section. */
146 line_buffer_t
*lines_tail
; /* Helper for faster appending to the
148 line_buffer_t last_line
; /* Points to the last line appended. */
150 typedef struct section_buffer_s
*section_buffer_t
;
152 /* Variable to keep info about the current page together. */
155 /* Filename of the current page or NULL if no page is active. Malloced. */
158 /* Number of allocated elements in SECTIONS below. */
160 /* Array with the data of the sections. */
161 section_buffer_t sections
;
166 /* The list of standard section names. COMMANDS and ASSUAN are GnuPG
168 static const char * const standard_sections
[] =
169 { "NAME", "SYNOPSIS", "DESCRIPTION",
170 "RETURN VALUE", "EXIT STATUS", "ERROR HANDLING", "ERRORS",
171 "COMMANDS", "OPTIONS", "USAGE", "EXAMPLES", "FILES",
172 "ENVIRONMENT", "DIAGNOSTICS", "SECURITY", "CONFORMING TO",
173 "ASSUAN", "NOTES", "BUGS", "AUTHOR", "SEE ALSO", NULL
};
176 /*-- Local prototypes. --*/
177 static void proc_texi_buffer (FILE *fp
, const char *line
, size_t len
,
178 int *table_level
, int *eol_action
);
182 /* Print diagnostic message and exit with failure. */
184 die (const char *format
, ...)
189 fprintf (stderr
, "%s: ", PGM
);
191 va_start (arg_ptr
, format
);
192 vfprintf (stderr
, format
, arg_ptr
);
200 /* Print diagnostic message. */
202 err (const char *format
, ...)
207 if (strncmp (format
, "%s:%d:", 6))
208 fprintf (stderr
, "%s: ", PGM
);
210 va_start (arg_ptr
, format
);
211 vfprintf (stderr
, format
, arg_ptr
);
217 /* Print diagnostic message. */
219 inf (const char *format
, ...)
224 fprintf (stderr
, "%s: ", PGM
);
226 va_start (arg_ptr
, format
);
227 vfprintf (stderr
, format
, arg_ptr
);
236 void *p
= malloc (n
);
238 die ("out of core: %s", strerror (errno
));
243 xcalloc (size_t n
, size_t m
)
245 void *p
= calloc (n
, m
);
247 die ("out of core: %s", strerror (errno
));
252 xrealloc (void *old
, size_t n
)
254 void *p
= realloc (old
, n
);
256 die ("out of core: %s", strerror (errno
));
261 xstrdup (const char *string
)
263 void *p
= malloc (strlen (string
)+1);
265 die ("out of core: %s", strerror (errno
));
271 /* Uppercase the ascii characters in STRING. */
273 ascii_strupr (char *string
)
277 for (p
= string
; *p
; p
++)
284 /* Return the current date as an ISO string. */
288 static char buffer
[11+5];
290 time_t atime
= time (NULL
);
293 strcpy (buffer
, "????" "-??" "-??");
296 tp
= gmtime (&atime
);
297 sprintf (buffer
,"%04d-%02d-%02d",
298 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
);
305 /* Return a section buffer for the section NAME. Allocate a new buffer
306 if this is a new section. Keep track of the sections in THEPAGE.
307 This function may reallocate the section array in THEPAGE. */
308 static section_buffer_t
309 get_section_buffer (const char *name
)
312 section_buffer_t sect
;
314 /* If there is no section we put everything into the required NAME
315 section. Given that this is the first one listed it is likely
316 that error are easily visible. */
320 for (i
=0; i
< thepage
.n_sections
; i
++)
322 sect
= thepage
.sections
+ i
;
323 if (sect
->name
&& !strcmp (name
, sect
->name
))
326 for (i
=0; i
< thepage
.n_sections
; i
++)
327 if (!thepage
.sections
[i
].name
)
329 if (i
< thepage
.n_sections
)
330 sect
= thepage
.sections
+ i
;
333 /* We need to allocate or reallocate the section array. */
334 size_t old_n
= thepage
.n_sections
;
338 thepage
.sections
= xcalloc (new_n
, sizeof *thepage
.sections
);
341 thepage
.sections
= xrealloc (thepage
.sections
,
343 * sizeof *thepage
.sections
));
344 memset (thepage
.sections
+ old_n
, 0,
345 new_n
* sizeof *thepage
.sections
);
347 thepage
.n_sections
+= new_n
;
349 /* Setup the tail pointers. */
350 for (i
=old_n
; i
< thepage
.n_sections
; i
++)
352 sect
= thepage
.sections
+ i
;
353 sect
->lines_tail
= §
->lines
;
355 sect
= thepage
.sections
+ old_n
;
358 /* Store the name. */
359 assert (!sect
->name
);
360 sect
->name
= xstrdup (name
);
366 /* Add the content of LINE to the section named SECTNAME. */
368 add_content (const char *sectname
, char *line
, int verbatim
)
370 section_buffer_t sect
;
373 sect
= get_section_buffer (sectname
);
374 if (sect
->last_line
&& !sect
->last_line
->verbatim
== !verbatim
)
376 /* Lets append that line to the last one. We do this to keep
377 all lines of the same kind (i.e.verbatim or not) together in
381 lb
= sect
->last_line
;
382 n1
= strlen (lb
->line
);
383 n
= n1
+ 1 + strlen (line
) + 1;
384 lb
->line
= xrealloc (lb
->line
, n
);
385 strcpy (lb
->line
+n1
, "\n");
386 strcpy (lb
->line
+n1
+1, line
);
390 lb
= xcalloc (1, sizeof *lb
);
391 lb
->verbatim
= verbatim
;
392 lb
->line
= xstrdup (line
);
393 sect
->last_line
= lb
;
394 *sect
->lines_tail
= lb
;
395 sect
->lines_tail
= &lb
->next
;
400 /* Prepare for a new man page using the filename NAME. */
402 start_page (char *name
)
405 inf ("starting page `%s'", name
);
406 assert (!thepage
.name
);
407 thepage
.name
= xstrdup (name
);
408 thepage
.n_sections
= 0;
412 /* Write the .TH entry of the current page. Return -1 if there is a
413 problem with the page. */
419 name
= ascii_strupr (xstrdup (thepage
.name
));
420 p
= strrchr (name
, '.');
423 err ("no section name in man page `%s'", thepage
.name
);
428 fprintf (fp
, ".TH %s %s %s \"%s\" \"%s\"\n",
429 name
, p
, isodatestring (), opt_release
, opt_source
);
434 /* Process the texinfo command COMMAND (without the leading @) and
435 write output if needed to FP. REST is the remainer of the line
436 which should either point to an opening brace or to a white space.
437 The function returns the number of characters already processed
438 from REST. LEN is the usable length of REST. TABLE_LEVEL is used to
439 control the indentation of tables. */
441 proc_texi_cmd (FILE *fp
, const char *command
, const char *rest
, size_t len
,
442 int *table_level
, int *eol_action
)
445 const char *name
; /* Name of the command. */
446 int what
; /* What to do with this command. */
447 const char *lead_in
; /* String to print with a opening brace. */
448 const char *lead_out
;/* String to print with the closing brace. */
450 { "command", 0, "\\fB", "\\fR" },
451 { "code", 0, "\\fB", "\\fR" },
452 { "sc", 0, "\\fB", "\\fR" },
453 { "var", 0, "\\fI", "\\fR" },
454 { "samp", 0, "\n'", "'\n" },
455 { "file", 0, "`\\fI","\\fR'" },
456 { "env", 0, "`\\fI","\\fR'" },
459 { "option", 0, "\\fB", "\\fR" },
460 { "example", 1, ".RS 2\n.nf\n" },
461 { "smallexample", 1, ".RS 2\n.nf\n" },
465 { "xref", 0, "see: [", "]" },
466 { "pxref", 0, "see: [", "]" },
467 { "uref", 0, "(\\fB", "\\fR)" },
468 { "footnote",0, " ([", "])" },
469 { "emph", 0, "\\fI", "\\fR" },
478 { "subsection", 6, "\n.SS " },
480 { "item", 2, ".TP\n.B " },
481 { "itemx", 2, ".TP\n.B " },
484 { "bullet", 0, "* " },
486 { "quotation",1, ".RS\n\\fB" },
492 const char *lead_out
= NULL
;
495 for (i
=0; cmdtbl
[i
].name
&& strcmp (cmdtbl
[i
].name
, command
); i
++)
499 s
= cmdtbl
[i
].lead_in
;
502 lead_out
= cmdtbl
[i
].lead_out
;
503 switch (cmdtbl
[i
].what
)
505 case 1: /* Throw away the entire line. */
506 s
= memchr (rest
, '\n', len
);
507 return s
? (s
-rest
)+1 : len
;
508 case 2: /* Handle @item. */
510 case 3: /* Handle table. */
511 if (++(*table_level
) > 1)
513 /* Now throw away the entire line. */
514 s
= memchr (rest
, '\n', len
);
515 return s
? (s
-rest
)+1 : len
;
517 case 4: /* Handle end. */
518 for (s
=rest
, n
=len
; n
&& (*s
== ' ' || *s
== '\t'); s
++, n
--)
520 if (n
>= 5 && !memcmp (s
, "table", 5)
521 && (!n
|| s
[5] == ' ' || s
[5] == '\t' || s
[5] == '\n'))
523 if ((*table_level
)-- > 1)
526 else if (n
>= 7 && !memcmp (s
, "example", 7)
527 && (!n
|| s
[7] == ' ' || s
[7] == '\t' || s
[7] == '\n'))
529 fputs (".fi\n.RE\n", fp
);
531 else if (n
>= 12 && !memcmp (s
, "smallexample", 12)
532 && (!n
|| s
[12] == ' ' || s
[12] == '\t' || s
[12] == '\n'))
534 fputs (".fi\n.RE\n", fp
);
536 else if (n
>= 9 && !memcmp (s
, "quotation", 9)
537 && (!n
|| s
[9] == ' ' || s
[9] == '\t' || s
[9] == '\n'))
539 fputs ("\\fR\n.RE\n", fp
);
541 /* Now throw away the entire line. */
542 s
= memchr (rest
, '\n', len
);
543 return s
? (s
-rest
)+1 : len
;
544 case 5: /* Handle special comments. */
545 for (s
=rest
, n
=len
; n
&& (*s
== ' ' || *s
== '\t'); s
++, n
--)
547 if (n
>= 4 && !memcmp (s
, "man:", 4))
549 for (s
+=4, n
-=4; n
&& *s
!= '\n'; n
--, s
++)
553 /* Now throw away the entire line. */
554 s
= memchr (rest
, '\n', len
);
555 return s
? (s
-rest
)+1 : len
;
570 for (m
= macrolist
; m
; m
= m
->next
)
571 if (!strcmp (m
->name
, command
))
575 proc_texi_buffer (fp
, m
->value
, strlen (m
->value
),
576 table_level
, eol_action
);
577 ignore_args
= 1; /* Parameterized macros are not yet supported. */
580 inf ("texinfo command `%s' not supported (%.*s)", command
,
581 ((s
= memchr (rest
, '\n', len
)), (s
? (s
-rest
) : len
)), rest
);
586 /* Find matching closing brace. */
587 for (s
=rest
+1, n
=1, i
=1; i
&& *s
&& n
< len
; s
++, n
++)
594 err ("closing brace for command `%s' not found", command
);
597 if (n
> 2 && !ignore_args
)
598 proc_texi_buffer (fp
, rest
+1, n
-2, table_level
, eol_action
);
604 fputs (lead_out
, fp
);
611 /* Process the string LINE with LEN bytes of Texinfo content. */
613 proc_texi_buffer (FILE *fp
, const char *line
, size_t len
,
614 int *table_level
, int *eol_action
)
622 for (s
=line
; *s
&& len
; s
++, len
--)
630 case '@': case '{': case '}':
631 putc (*s
, fp
); in_cmd
= 0;
633 case ':': /* Not ending a sentence flag. */
636 case '.': case '!': case '?': /* Ending a sentence. */
637 putc (*s
, fp
); in_cmd
= 0;
639 case ' ': case '\t': case '\n': /* Non collapsing spaces. */
640 putc (*s
, fp
); in_cmd
= 0;
644 cmdbuf
[cmdidx
++] = *s
;
649 else if (*s
== '{' || *s
== ' ' || *s
== '\t' || *s
== '\n')
652 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
658 else if (cmdidx
< sizeof cmdbuf
-1)
659 cmdbuf
[cmdidx
++] = *s
;
662 err ("texinfo command too long - ignored");
672 case 1: /* Create a dummy paragraph. */
673 fputs ("\n\\ \n", fp
);
687 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
696 /* Do something with the Texinfo line LINE. */
698 parse_texi_line (FILE *fp
, const char *line
, int *table_level
)
702 /* A quick test whether there are any texinfo commands. */
703 if (!strchr (line
, '@'))
709 proc_texi_buffer (fp
, line
, strlen (line
), table_level
, &eol_action
);
714 /* Write all the lines LINES to FP. */
716 write_content (FILE *fp
, line_buffer_t lines
)
721 for (line
= lines
; line
; line
= line
->next
)
725 fputs (line
->line
, fp
);
730 /* fputs ("TEXI---", fp); */
731 /* fputs (line->line, fp); */
732 /* fputs ("---\n", fp); */
733 parse_texi_line (fp
, line
->line
, &table_level
);
741 is_standard_section (const char *name
)
746 for (i
=0; (s
=standard_sections
[i
]); i
++)
747 if (!strcmp (s
, name
))
753 /* Finish a page; that is sort the data and write it out to the file. */
758 section_buffer_t sect
;
764 return; /* No page active. */
767 inf ("finishing page `%s'", thepage
.name
);
771 if (!strcmp (opt_select
, thepage
.name
))
773 inf ("selected `%s'", thepage
.name
);
778 fp
= fopen ( "/dev/null", "w" );
780 die ("failed to open /dev/null: %s\n", strerror (errno
));
785 inf ("writing `%s'", thepage
.name
);
786 fp
= fopen ( thepage
.name
, "w" );
788 die ("failed to create `%s': %s\n", thepage
.name
, strerror (errno
));
796 for (idx
=0; (s
=standard_sections
[idx
]); idx
++)
798 for (i
=0; i
< thepage
.n_sections
; i
++)
800 sect
= thepage
.sections
+ i
;
801 if (sect
->name
&& !strcmp (s
, sect
->name
))
804 if (i
== thepage
.n_sections
)
809 fprintf (fp
, ".SH %s\n", sect
->name
);
810 write_content (fp
, sect
->lines
);
811 /* Now continue with all non standard sections directly
812 following this one. */
813 for (i
++; i
< thepage
.n_sections
; i
++)
815 sect
= thepage
.sections
+ i
;
816 if (sect
->name
&& is_standard_section (sect
->name
))
820 fprintf (fp
, ".SH %s\n", sect
->name
);
821 write_content (fp
, sect
->lines
);
834 /* FIXME: Cleanup the content. */
840 /* Parse one Texinfo file and create manpages according to the
841 embedded instructions. */
843 parse_file (const char *fname
, FILE *fp
, char **section_name
, int in_pause
)
847 /* Fixme: The follwing state variables don't carry over to include
850 int skip_to_end
= 0; /* Used to skip over menu entries. */
851 int skip_sect_line
= 0; /* Skip after @mansect. */
852 int ifset_nesting
= 0; /* How often a ifset has been seen. */
853 int ifclear_nesting
= 0; /* How often a ifclear has been seen. */
854 int in_gpgone
= 0; /* Keep track of "@ifset gpgone" parts. */
855 int not_in_gpgone
= 0; /* Keep track of "@ifclear gpgone" parts. */
856 int not_in_man
= 0; /* Keep track of "@ifclear isman" parts. */
858 /* Helper to define a macro. */
859 char *macroname
= NULL
;
860 char *macrovalue
= NULL
;
861 size_t macrovaluesize
= 0;
862 size_t macrovalueused
= 0;
864 line
= xmalloc (LINESIZE
);
865 while (fgets (line
, LINESIZE
, fp
))
867 size_t n
= strlen (line
);
872 if (!n
|| line
[n
-1] != '\n')
874 err ("%s:%d: trailing linefeed missing, line too long or "
875 "embedded Nul character", fname
, lnr
);
882 for (p
=line
+1, n
=1; *p
&& *p
!= ' ' && *p
!= '\t'; p
++)
884 while (*p
== ' ' || *p
== '\t')
890 /* Take action on macro. */
893 if (n
== 4 && !memcmp (line
, "@end", 4)
894 && (line
[4]==' '||line
[4]=='\t'||!line
[4])
895 && !strncmp (p
, "macro", 5)
896 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
901 macrovalue
[--macrovalueused
] = 0; /* Kill the last LF. */
902 macrovalue
[macrovalueused
] = 0; /* Terminate macro. */
903 macrovalue
= xrealloc (macrovalue
, macrovalueused
+1);
905 for (m
= macrolist
; m
; m
= m
->next
)
906 if (!strcmp (m
->name
, macroname
))
912 m
= xcalloc (1, sizeof *m
+ strlen (macroname
));
913 strcpy (m
->name
, macroname
);
917 m
->value
= macrovalue
;
924 if (macrovalueused
+ strlen (line
) + 2 >= macrovaluesize
)
926 macrovaluesize
+= strlen (line
) + 256;
927 macrovalue
= xrealloc (macrovalue
, macrovaluesize
);
929 strcpy (macrovalue
+macrovalueused
, line
);
930 macrovalueused
+= strlen (line
);
931 macrovalue
[macrovalueused
++] = '\n';
937 if (n
>= 5 && !memcmp (line
, "@node", 5)
938 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
940 /* Completey ignore @node lines. */
948 if (!strncmp (line
, "@section", 8)
949 || !strncmp (line
, "@subsection", 11)
950 || !strncmp (line
, "@chapheading", 12))
954 /* We only parse lines we need and ignore the rest. There are a
955 few macros used to control this as well as one @ifset
956 command. Parts we know about are saved away into containers
957 separate for each section. */
959 /* First process ifset/ifclear commands. */
962 if (n
== 6 && !memcmp (line
, "@ifset", 6)
963 && (line
[6]==' '||line
[6]=='\t'))
967 if (!strncmp (p
, "manverb", 7) && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
970 err ("%s:%d: nested \"@ifset manverb\"", fname
, lnr
);
972 in_verbatim
= ifset_nesting
;
974 else if (!strncmp (p
, "gpgone", 6)
975 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
978 err ("%s:%d: nested \"@ifset gpgone\"", fname
, lnr
);
980 in_gpgone
= ifset_nesting
;
984 else if (n
== 4 && !memcmp (line
, "@end", 4)
985 && (line
[4]==' '||line
[4]=='\t')
986 && !strncmp (p
, "ifset", 5)
987 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
989 if (in_verbatim
&& ifset_nesting
== in_verbatim
)
991 if (in_gpgone
&& ifset_nesting
== in_gpgone
)
997 err ("%s:%d: unbalanced \"@end ifset\"", fname
, lnr
);
1000 else if (n
== 8 && !memcmp (line
, "@ifclear", 8)
1001 && (line
[8]==' '||line
[8]=='\t'))
1005 if (!strncmp (p
, "gpgone", 6)
1006 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
1009 err ("%s:%d: nested \"@ifclear gpgone\"", fname
, lnr
);
1011 not_in_gpgone
= ifclear_nesting
;
1014 else if (!strncmp (p
, "isman", 5)
1015 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
1018 err ("%s:%d: nested \"@ifclear isman\"", fname
, lnr
);
1020 not_in_man
= ifclear_nesting
;
1025 else if (n
== 4 && !memcmp (line
, "@end", 4)
1026 && (line
[4]==' '||line
[4]=='\t')
1027 && !strncmp (p
, "ifclear", 7)
1028 && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
1030 if (not_in_gpgone
&& ifclear_nesting
== not_in_gpgone
)
1032 if (not_in_man
&& ifclear_nesting
== not_in_man
)
1035 if (ifclear_nesting
)
1038 err ("%s:%d: unbalanced \"@end ifclear\"", fname
, lnr
);
1043 /* Take action on ifset/ifclear. */
1044 if ( (in_gpgone
&& !gpgone_defined
)
1045 || (not_in_gpgone
&& gpgone_defined
)
1049 /* Process commands. */
1053 && n
== 4 && !memcmp (line
, "@end", 4)
1054 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1058 else if (in_verbatim
)
1062 else if (n
== 6 && !memcmp (line
, "@macro", 6))
1064 macroname
= xstrdup (p
);
1065 macrovalue
= xmalloc ((macrovaluesize
= 1024));
1068 else if (n
== 8 && !memcmp (line
, "@manpage", 8))
1070 free (*section_name
);
1071 *section_name
= NULL
;
1076 else if (n
== 8 && !memcmp (line
, "@mansect", 8))
1079 err ("%s:%d: section outside of a man page", fname
, lnr
);
1082 free (*section_name
);
1083 *section_name
= ascii_strupr (xstrdup (p
));
1088 else if (n
== 9 && !memcmp (line
, "@manpause", 9))
1091 err ("%s:%d: pausing outside of a man section", fname
, lnr
);
1093 err ("%s:%d: already pausing", fname
, lnr
);
1097 else if (n
== 8 && !memcmp (line
, "@mancont", 8))
1100 err ("%s:%d: continue outside of a man section", fname
, lnr
);
1102 err ("%s:%d: continue while not pausing", fname
, lnr
);
1106 else if (n
== 5 && !memcmp (line
, "@menu", 5)
1107 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
1111 else if (n
== 8 && !memcmp (line
, "@include", 8)
1112 && (line
[8]==' '||line
[8]=='\t'||!line
[8]))
1114 char *incname
= xstrdup (p
);
1115 FILE *incfp
= fopen (incname
, "r");
1117 if (!incfp
&& opt_include
&& *opt_include
&& *p
!= '/')
1120 incname
= xmalloc (strlen (opt_include
) + 1
1122 strcpy (incname
, opt_include
);
1123 if ( incname
[strlen (incname
)-1] != '/' )
1124 strcat (incname
, "/");
1125 strcat (incname
, p
);
1126 incfp
= fopen (incname
, "r");
1130 err ("can't open include file `%s':%s",
1131 incname
, strerror (errno
));
1134 parse_file (incname
, incfp
, section_name
, in_pause
);
1139 else if (n
== 4 && !memcmp (line
, "@bye", 4)
1140 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1144 else if (!skip_to_end
)
1147 else if (!skip_to_end
)
1150 if (got_line
&& in_verbatim
)
1151 add_content (*section_name
, line
, 1);
1152 else if (got_line
&& thepage
.name
&& *section_name
&& !in_pause
)
1153 add_content (*section_name
, line
, 0);
1157 err ("%s:%d: read error: %s", fname
, lnr
, strerror (errno
));
1165 top_parse_file (const char *fname
, FILE *fp
)
1167 char *section_name
= NULL
; /* Name of the current section or NULL
1168 if not in a section. */
1171 macro_t m
= macrolist
->next
;
1177 parse_file (fname
, fp
, §ion_name
, 0);
1178 free (section_name
);
1184 main (int argc
, char **argv
)
1195 while (argc
&& last_argc
!= argc
)
1198 if (!strcmp (*argv
, "--"))
1203 else if (!strcmp (*argv
, "--help"))
1206 "Usage: " PGM
" [OPTION] [FILE]\n"
1207 "Extract man pages from a Texinfo source.\n\n"
1208 " --source NAME use NAME as source field\n"
1209 " --release STRING use STRING as the release field\n"
1210 " --store write output using @manpage name\n"
1211 " --select NAME only output pages with @manpage NAME\n"
1212 " --verbose enable extra informational output\n"
1213 " --debug enable additional debug output\n"
1214 " --help display this help and exit\n"
1215 " -I DIR also search in include DIR\n"
1216 " -D gpgone the only useable define\n\n"
1217 "With no FILE, or when FILE is -, read standard input.\n\n"
1218 "Report bugs to <bugs@g10code.com>.");
1221 else if (!strcmp (*argv
, "--version"))
1223 puts (PGM
" " VERSION
"\n"
1224 "Copyright (C) 2005 g10 Code GmbH\n"
1225 "This program comes with ABSOLUTELY NO WARRANTY.\n"
1226 "This is free software, and you are welcome to redistribute it\n"
1227 "under certain conditions. See the file COPYING for details.");
1230 else if (!strcmp (*argv
, "--verbose"))
1235 else if (!strcmp (*argv
, "--quiet"))
1240 else if (!strcmp (*argv
, "--debug"))
1242 verbose
= debug
= 1;
1245 else if (!strcmp (*argv
, "--source"))
1254 else if (!strcmp (*argv
, "--release"))
1259 opt_release
= *argv
;
1263 else if (!strcmp (*argv
, "--store"))
1268 else if (!strcmp (*argv
, "--select"))
1273 opt_select
= strrchr (*argv
, '/');
1281 else if (!strcmp (*argv
, "-I"))
1286 opt_include
= *argv
;
1290 else if (!strcmp (*argv
, "-D"))
1295 if (!strcmp (*argv
, "gpgone"))
1303 die ("usage: " PGM
" [OPTION] [FILE] (try --help for more information)\n");
1305 /* Start processing. */
1306 if (argc
&& strcmp (*argv
, "-"))
1308 FILE *fp
= fopen (*argv
, "rb");
1310 die ("%s:0: can't open file: %s", *argv
, strerror (errno
));
1311 top_parse_file (*argv
, fp
);
1315 top_parse_file ("-", stdin
);
1323 compile-command: "gcc -Wall -g -Wall -o yat2m yat2m.c"