1 /* yat2m.c - Yet Another Texi 2 Man converter
2 * Copyright (C) 2005 g10 Code GmbH
3 * Copyright (C) 2006, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
20 This is a simple textinfo to man page converter. It needs some
21 special markup in th e texinfo and tries best to get a create man
22 page. It has been designed for the GnuPG man pages and thus only
23 a few texinfo commands are supported.
25 To use this you need to add the following macros into your texinfo
37 They are used by yat2m to select parts of the Texinfo which should
38 go into the man page. These macros need to be used without leading
39 left space. Processing starts after a "manpage" macro has been
40 seen. "mansect" identifies the section and yat2m make sure to
41 emit the sections in the proper order. Note that @mansect skips
42 the next input line if that line begins with @section, @subsection or
45 To insert verbatim troff markup, the following texinfo code may be
52 alternativly a special comment may be used:
54 @c man:.B whatever you want
56 This is useful in case you need just one line. If you want to
57 include parts only in the man page but keep the texinfo
58 translation you may use:
61 stuff to be rendered only on man pages
64 or to exclude stuff from man pages:
67 stuff not to be rendered on man pages
70 the keyword @section is ignored, however @subsection gets rendered
71 as ".SS". @menu is completely skipped. Several man pages may be
72 extracted from one file, either using the --store or the --select
92 /* The maximum length of a line including the linefeed and one extra
100 static const char *opt_source
;
101 static const char *opt_release
;
102 static const char *opt_select
;
103 static const char *opt_include
;
104 static int opt_store
;
106 /* The only define we understand is -D gpgone. Thus we need a simple
107 boolean tro track it. */
108 static int gpgone_defined
;
110 /* Flag to keep track whether any error occurred. */
111 static int any_error
;
114 /* Object to keep macro definitions. */
117 struct macro_s
*next
;
118 char *value
; /* Malloced value. */
121 typedef struct macro_s
*macro_t
;
123 /* List of all defined macros. */
124 static macro_t macrolist
;
127 /* Object to store one line of content. */
130 struct line_buffer_s
*next
;
131 int verbatim
; /* True if LINE contains verbatim data. The default
132 is Texinfo source. */
135 typedef struct line_buffer_s
*line_buffer_t
;
138 /* Object to collect the data of a section. */
139 struct section_buffer_s
141 char *name
; /* Malloced name of the section. This may be
142 NULL to indicate this slot is not used. */
143 line_buffer_t lines
; /* Linked list with the lines of the section. */
144 line_buffer_t
*lines_tail
; /* Helper for faster appending to the
146 line_buffer_t last_line
; /* Points to the last line appended. */
148 typedef struct section_buffer_s
*section_buffer_t
;
150 /* Variable to keep info about the current page together. */
153 /* Filename of the current page or NULL if no page is active. Malloced. */
156 /* Number of allocated elements in SECTIONS below. */
158 /* Array with the data of the sections. */
159 section_buffer_t sections
;
164 /* The list of standard section names. COMMANDS and ASSUAN are GnuPG
166 static const char * const standard_sections
[] =
167 { "NAME", "SYNOPSIS", "DESCRIPTION",
168 "RETURN VALUE", "EXIT STATUS", "ERROR HANDLING", "ERRORS",
169 "COMMANDS", "OPTIONS", "USAGE", "EXAMPLES", "FILES",
170 "ENVIRONMENT", "DIAGNOSTICS", "SECURITY", "CONFORMING TO",
171 "ASSUAN", "NOTES", "BUGS", "AUTHOR", "SEE ALSO", NULL
};
174 /*-- Local prototypes. --*/
175 static void proc_texi_buffer (FILE *fp
, const char *line
, size_t len
,
176 int *table_level
, int *eol_action
);
180 /* Print diagnostic message and exit with failure. */
182 die (const char *format
, ...)
187 fprintf (stderr
, "%s: ", PGM
);
189 va_start (arg_ptr
, format
);
190 vfprintf (stderr
, format
, arg_ptr
);
198 /* Print diagnostic message. */
200 err (const char *format
, ...)
205 if (strncmp (format
, "%s:%d:", 6))
206 fprintf (stderr
, "%s: ", PGM
);
208 va_start (arg_ptr
, format
);
209 vfprintf (stderr
, format
, arg_ptr
);
215 /* Print diagnostic message. */
217 inf (const char *format
, ...)
222 fprintf (stderr
, "%s: ", PGM
);
224 va_start (arg_ptr
, format
);
225 vfprintf (stderr
, format
, arg_ptr
);
234 void *p
= malloc (n
);
236 die ("out of core: %s", strerror (errno
));
241 xcalloc (size_t n
, size_t m
)
243 void *p
= calloc (n
, m
);
245 die ("out of core: %s", strerror (errno
));
250 xrealloc (void *old
, size_t n
)
252 void *p
= realloc (old
, n
);
254 die ("out of core: %s", strerror (errno
));
259 xstrdup (const char *string
)
261 void *p
= malloc (strlen (string
)+1);
263 die ("out of core: %s", strerror (errno
));
269 /* Uppercase the ascii characters in STRING. */
271 ascii_strupr (char *string
)
275 for (p
= string
; *p
; p
++)
282 /* Return the current date as an ISO string. */
286 static char buffer
[11+5];
288 time_t atime
= time (NULL
);
291 strcpy (buffer
, "????" "-??" "-??");
294 tp
= gmtime (&atime
);
295 sprintf (buffer
,"%04d-%02d-%02d",
296 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
);
303 /* Return a section buffer for the section NAME. Allocate a new buffer
304 if this is a new section. Keep track of the sections in THEPAGE.
305 This function may reallocate the section array in THEPAGE. */
306 static section_buffer_t
307 get_section_buffer (const char *name
)
310 section_buffer_t sect
;
312 /* If there is no section we put everything into the required NAME
313 section. Given that this is the first one listed it is likely
314 that error are easily visible. */
318 for (i
=0; i
< thepage
.n_sections
; i
++)
320 sect
= thepage
.sections
+ i
;
321 if (sect
->name
&& !strcmp (name
, sect
->name
))
324 for (i
=0; i
< thepage
.n_sections
; i
++)
325 if (!thepage
.sections
[i
].name
)
327 if (i
< thepage
.n_sections
)
328 sect
= thepage
.sections
+ i
;
331 /* We need to allocate or reallocate the section array. */
332 size_t old_n
= thepage
.n_sections
;
336 thepage
.sections
= xcalloc (new_n
, sizeof *thepage
.sections
);
339 thepage
.sections
= xrealloc (thepage
.sections
,
341 * sizeof *thepage
.sections
));
342 memset (thepage
.sections
+ old_n
, 0,
343 new_n
* sizeof *thepage
.sections
);
345 thepage
.n_sections
+= new_n
;
347 /* Setup the tail pointers. */
348 for (i
=old_n
; i
< thepage
.n_sections
; i
++)
350 sect
= thepage
.sections
+ i
;
351 sect
->lines_tail
= §
->lines
;
353 sect
= thepage
.sections
+ old_n
;
356 /* Store the name. */
357 assert (!sect
->name
);
358 sect
->name
= xstrdup (name
);
364 /* Add the content of LINE to the section named SECTNAME. */
366 add_content (const char *sectname
, char *line
, int verbatim
)
368 section_buffer_t sect
;
371 sect
= get_section_buffer (sectname
);
372 if (sect
->last_line
&& !sect
->last_line
->verbatim
== !verbatim
)
374 /* Lets append that line to the last one. We do this to keep
375 all lines of the same kind (i.e.verbatim or not) together in
379 lb
= sect
->last_line
;
380 n1
= strlen (lb
->line
);
381 n
= n1
+ 1 + strlen (line
) + 1;
382 lb
->line
= xrealloc (lb
->line
, n
);
383 strcpy (lb
->line
+n1
, "\n");
384 strcpy (lb
->line
+n1
+1, line
);
388 lb
= xcalloc (1, sizeof *lb
);
389 lb
->verbatim
= verbatim
;
390 lb
->line
= xstrdup (line
);
391 sect
->last_line
= lb
;
392 *sect
->lines_tail
= lb
;
393 sect
->lines_tail
= &lb
->next
;
398 /* Prepare for a new man page using the filename NAME. */
400 start_page (char *name
)
403 inf ("starting page `%s'", name
);
404 assert (!thepage
.name
);
405 thepage
.name
= xstrdup (name
);
406 thepage
.n_sections
= 0;
410 /* Write the .TH entry of the current page. Return -1 if there is a
411 problem with the page. */
417 fputs (".\\\" Created from Texinfo source by yat2m " VERSION
"\n", fp
);
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, "\\(aq", "\\(aq" },
455 { "file", 0, "\\(oq\\fI","\\fR\\(cq" },
456 { "env", 0, "\\(oq\\fI","\\fR\\(cq" },
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
);
689 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
698 /* Do something with the Texinfo line LINE. */
700 parse_texi_line (FILE *fp
, const char *line
, int *table_level
)
704 /* A quick test whether there are any texinfo commands. */
705 if (!strchr (line
, '@'))
711 proc_texi_buffer (fp
, line
, strlen (line
), table_level
, &eol_action
);
716 /* Write all the lines LINES to FP. */
718 write_content (FILE *fp
, line_buffer_t lines
)
723 for (line
= lines
; line
; line
= line
->next
)
727 fputs (line
->line
, fp
);
732 /* fputs ("TEXI---", fp); */
733 /* fputs (line->line, fp); */
734 /* fputs ("---\n", fp); */
735 parse_texi_line (fp
, line
->line
, &table_level
);
743 is_standard_section (const char *name
)
748 for (i
=0; (s
=standard_sections
[i
]); i
++)
749 if (!strcmp (s
, name
))
755 /* Finish a page; that is sort the data and write it out to the file. */
760 section_buffer_t sect
= NULL
;
766 return; /* No page active. */
769 inf ("finishing page `%s'", thepage
.name
);
773 if (!strcmp (opt_select
, thepage
.name
))
775 inf ("selected `%s'", thepage
.name
);
780 fp
= fopen ( "/dev/null", "w" );
782 die ("failed to open /dev/null: %s\n", strerror (errno
));
787 inf ("writing `%s'", thepage
.name
);
788 fp
= fopen ( thepage
.name
, "w" );
790 die ("failed to create `%s': %s\n", thepage
.name
, strerror (errno
));
798 for (idx
=0; (s
=standard_sections
[idx
]); idx
++)
800 for (i
=0; i
< thepage
.n_sections
; i
++)
802 sect
= thepage
.sections
+ i
;
803 if (sect
->name
&& !strcmp (s
, sect
->name
))
806 if (i
== thepage
.n_sections
)
811 fprintf (fp
, ".SH %s\n", sect
->name
);
812 write_content (fp
, sect
->lines
);
813 /* Now continue with all non standard sections directly
814 following this one. */
815 for (i
++; i
< thepage
.n_sections
; i
++)
817 sect
= thepage
.sections
+ i
;
818 if (sect
->name
&& is_standard_section (sect
->name
))
822 fprintf (fp
, ".SH %s\n", sect
->name
);
823 write_content (fp
, sect
->lines
);
836 /* FIXME: Cleanup the content. */
842 /* Parse one Texinfo file and create manpages according to the
843 embedded instructions. */
845 parse_file (const char *fname
, FILE *fp
, char **section_name
, int in_pause
)
849 /* Fixme: The following state variables don't carry over to include
852 int skip_to_end
= 0; /* Used to skip over menu entries. */
853 int skip_sect_line
= 0; /* Skip after @mansect. */
854 int ifset_nesting
= 0; /* How often a ifset has been seen. */
855 int ifclear_nesting
= 0; /* How often a ifclear has been seen. */
856 int in_gpgone
= 0; /* Keep track of "@ifset gpgone" parts. */
857 int not_in_gpgone
= 0; /* Keep track of "@ifclear gpgone" parts. */
858 int not_in_man
= 0; /* Keep track of "@ifclear isman" parts. */
860 /* Helper to define a macro. */
861 char *macroname
= NULL
;
862 char *macrovalue
= NULL
;
863 size_t macrovaluesize
= 0;
864 size_t macrovalueused
= 0;
866 line
= xmalloc (LINESIZE
);
867 while (fgets (line
, LINESIZE
, fp
))
869 size_t n
= strlen (line
);
874 if (!n
|| line
[n
-1] != '\n')
876 err ("%s:%d: trailing linefeed missing, line too long or "
877 "embedded Nul character", fname
, lnr
);
884 for (p
=line
+1, n
=1; *p
&& *p
!= ' ' && *p
!= '\t'; p
++)
886 while (*p
== ' ' || *p
== '\t')
892 /* Take action on macro. */
895 if (n
== 4 && !memcmp (line
, "@end", 4)
896 && (line
[4]==' '||line
[4]=='\t'||!line
[4])
897 && !strncmp (p
, "macro", 5)
898 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
903 macrovalue
[--macrovalueused
] = 0; /* Kill the last LF. */
904 macrovalue
[macrovalueused
] = 0; /* Terminate macro. */
905 macrovalue
= xrealloc (macrovalue
, macrovalueused
+1);
907 for (m
= macrolist
; m
; m
= m
->next
)
908 if (!strcmp (m
->name
, macroname
))
914 m
= xcalloc (1, sizeof *m
+ strlen (macroname
));
915 strcpy (m
->name
, macroname
);
919 m
->value
= macrovalue
;
926 if (macrovalueused
+ strlen (line
) + 2 >= macrovaluesize
)
928 macrovaluesize
+= strlen (line
) + 256;
929 macrovalue
= xrealloc (macrovalue
, macrovaluesize
);
931 strcpy (macrovalue
+macrovalueused
, line
);
932 macrovalueused
+= strlen (line
);
933 macrovalue
[macrovalueused
++] = '\n';
939 if (n
>= 5 && !memcmp (line
, "@node", 5)
940 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
942 /* Completey ignore @node lines. */
950 if (!strncmp (line
, "@section", 8)
951 || !strncmp (line
, "@subsection", 11)
952 || !strncmp (line
, "@chapheading", 12))
956 /* We only parse lines we need and ignore the rest. There are a
957 few macros used to control this as well as one @ifset
958 command. Parts we know about are saved away into containers
959 separate for each section. */
961 /* First process ifset/ifclear commands. */
964 if (n
== 6 && !memcmp (line
, "@ifset", 6)
965 && (line
[6]==' '||line
[6]=='\t'))
969 if (!strncmp (p
, "manverb", 7) && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
972 err ("%s:%d: nested \"@ifset manverb\"", fname
, lnr
);
974 in_verbatim
= ifset_nesting
;
976 else if (!strncmp (p
, "gpgone", 6)
977 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
980 err ("%s:%d: nested \"@ifset gpgone\"", fname
, lnr
);
982 in_gpgone
= ifset_nesting
;
986 else if (n
== 4 && !memcmp (line
, "@end", 4)
987 && (line
[4]==' '||line
[4]=='\t')
988 && !strncmp (p
, "ifset", 5)
989 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
991 if (in_verbatim
&& ifset_nesting
== in_verbatim
)
993 if (in_gpgone
&& ifset_nesting
== in_gpgone
)
999 err ("%s:%d: unbalanced \"@end ifset\"", fname
, lnr
);
1002 else if (n
== 8 && !memcmp (line
, "@ifclear", 8)
1003 && (line
[8]==' '||line
[8]=='\t'))
1007 if (!strncmp (p
, "gpgone", 6)
1008 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
1011 err ("%s:%d: nested \"@ifclear gpgone\"", fname
, lnr
);
1013 not_in_gpgone
= ifclear_nesting
;
1016 else if (!strncmp (p
, "isman", 5)
1017 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
1020 err ("%s:%d: nested \"@ifclear isman\"", fname
, lnr
);
1022 not_in_man
= ifclear_nesting
;
1027 else if (n
== 4 && !memcmp (line
, "@end", 4)
1028 && (line
[4]==' '||line
[4]=='\t')
1029 && !strncmp (p
, "ifclear", 7)
1030 && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
1032 if (not_in_gpgone
&& ifclear_nesting
== not_in_gpgone
)
1034 if (not_in_man
&& ifclear_nesting
== not_in_man
)
1037 if (ifclear_nesting
)
1040 err ("%s:%d: unbalanced \"@end ifclear\"", fname
, lnr
);
1045 /* Take action on ifset/ifclear. */
1046 if ( (in_gpgone
&& !gpgone_defined
)
1047 || (not_in_gpgone
&& gpgone_defined
)
1051 /* Process commands. */
1055 && n
== 4 && !memcmp (line
, "@end", 4)
1056 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1060 else if (in_verbatim
)
1064 else if (n
== 6 && !memcmp (line
, "@macro", 6))
1066 macroname
= xstrdup (p
);
1067 macrovalue
= xmalloc ((macrovaluesize
= 1024));
1070 else if (n
== 8 && !memcmp (line
, "@manpage", 8))
1072 free (*section_name
);
1073 *section_name
= NULL
;
1078 else if (n
== 8 && !memcmp (line
, "@mansect", 8))
1081 err ("%s:%d: section outside of a man page", fname
, lnr
);
1084 free (*section_name
);
1085 *section_name
= ascii_strupr (xstrdup (p
));
1090 else if (n
== 9 && !memcmp (line
, "@manpause", 9))
1093 err ("%s:%d: pausing outside of a man section", fname
, lnr
);
1095 err ("%s:%d: already pausing", fname
, lnr
);
1099 else if (n
== 8 && !memcmp (line
, "@mancont", 8))
1102 err ("%s:%d: continue outside of a man section", fname
, lnr
);
1104 err ("%s:%d: continue while not pausing", fname
, lnr
);
1108 else if (n
== 5 && !memcmp (line
, "@menu", 5)
1109 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
1113 else if (n
== 8 && !memcmp (line
, "@include", 8)
1114 && (line
[8]==' '||line
[8]=='\t'||!line
[8]))
1116 char *incname
= xstrdup (p
);
1117 FILE *incfp
= fopen (incname
, "r");
1119 if (!incfp
&& opt_include
&& *opt_include
&& *p
!= '/')
1122 incname
= xmalloc (strlen (opt_include
) + 1
1124 strcpy (incname
, opt_include
);
1125 if ( incname
[strlen (incname
)-1] != '/' )
1126 strcat (incname
, "/");
1127 strcat (incname
, p
);
1128 incfp
= fopen (incname
, "r");
1132 err ("can't open include file `%s':%s",
1133 incname
, strerror (errno
));
1136 parse_file (incname
, incfp
, section_name
, in_pause
);
1141 else if (n
== 4 && !memcmp (line
, "@bye", 4)
1142 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1146 else if (!skip_to_end
)
1149 else if (!skip_to_end
)
1152 if (got_line
&& in_verbatim
)
1153 add_content (*section_name
, line
, 1);
1154 else if (got_line
&& thepage
.name
&& *section_name
&& !in_pause
)
1155 add_content (*section_name
, line
, 0);
1159 err ("%s:%d: read error: %s", fname
, lnr
, strerror (errno
));
1167 top_parse_file (const char *fname
, FILE *fp
)
1169 char *section_name
= NULL
; /* Name of the current section or NULL
1170 if not in a section. */
1173 macro_t m
= macrolist
->next
;
1179 parse_file (fname
, fp
, §ion_name
, 0);
1180 free (section_name
);
1186 main (int argc
, char **argv
)
1197 while (argc
&& last_argc
!= argc
)
1200 if (!strcmp (*argv
, "--"))
1205 else if (!strcmp (*argv
, "--help"))
1208 "Usage: " PGM
" [OPTION] [FILE]\n"
1209 "Extract man pages from a Texinfo source.\n\n"
1210 " --source NAME use NAME as source field\n"
1211 " --release STRING use STRING as the release field\n"
1212 " --store write output using @manpage name\n"
1213 " --select NAME only output pages with @manpage NAME\n"
1214 " --verbose enable extra informational output\n"
1215 " --debug enable additional debug output\n"
1216 " --help display this help and exit\n"
1217 " -I DIR also search in include DIR\n"
1218 " -D gpgone the only useable define\n\n"
1219 "With no FILE, or when FILE is -, read standard input.\n\n"
1220 "Report bugs to <bugs@g10code.com>.");
1223 else if (!strcmp (*argv
, "--version"))
1225 puts (PGM
" " VERSION
"\n"
1226 "Copyright (C) 2005 g10 Code GmbH\n"
1227 "This program comes with ABSOLUTELY NO WARRANTY.\n"
1228 "This is free software, and you are welcome to redistribute it\n"
1229 "under certain conditions. See the file COPYING for details.");
1232 else if (!strcmp (*argv
, "--verbose"))
1237 else if (!strcmp (*argv
, "--quiet"))
1242 else if (!strcmp (*argv
, "--debug"))
1244 verbose
= debug
= 1;
1247 else if (!strcmp (*argv
, "--source"))
1256 else if (!strcmp (*argv
, "--release"))
1261 opt_release
= *argv
;
1265 else if (!strcmp (*argv
, "--store"))
1270 else if (!strcmp (*argv
, "--select"))
1275 opt_select
= strrchr (*argv
, '/');
1283 else if (!strcmp (*argv
, "-I"))
1288 opt_include
= *argv
;
1292 else if (!strcmp (*argv
, "-D"))
1297 if (!strcmp (*argv
, "gpgone"))
1305 die ("usage: " PGM
" [OPTION] [FILE] (try --help for more information)\n");
1307 /* Start processing. */
1308 if (argc
&& strcmp (*argv
, "-"))
1310 FILE *fp
= fopen (*argv
, "rb");
1312 die ("%s:0: can't open file: %s", *argv
, strerror (errno
));
1313 top_parse_file (*argv
, fp
);
1317 top_parse_file ("-", stdin
);
1325 compile-command: "gcc -Wall -g -Wall -o yat2m yat2m.c"