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 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 follwing 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 name
= ascii_strupr (xstrdup (thepage
.name
));
418 p
= strrchr (name
, '.');
421 err ("no section name in man page `%s'", thepage
.name
);
426 fprintf (fp
, ".TH %s %s %s \"%s\" \"%s\"\n",
427 name
, p
, isodatestring (), opt_release
, opt_source
);
432 /* Process the texinfo command COMMAND (without the leading @) and
433 write output if needed to FP. REST is the remainer of the line
434 which should either point to an opening brace or to a white space.
435 The function returns the number of characters already processed
436 from REST. LEN is the usable length of REST. TABLE_LEVEL is used to
437 control the indentation of tables. */
439 proc_texi_cmd (FILE *fp
, const char *command
, const char *rest
, size_t len
,
440 int *table_level
, int *eol_action
)
443 const char *name
; /* Name of the command. */
444 int what
; /* What to do with this command. */
445 const char *lead_in
; /* String to print with a opening brace. */
446 const char *lead_out
;/* String to print with the closing brace. */
448 { "command", 0, "\\fB", "\\fR" },
449 { "code", 0, "\\fB", "\\fR" },
450 { "sc", 0, "\\fB", "\\fR" },
451 { "var", 0, "\\fI", "\\fR" },
452 { "samp", 0, "'", "'" },
453 { "file", 0, "`\\fI","\\fR'" },
454 { "env", 0, "`\\fI","\\fR'" },
457 { "option", 0, "\\fB", "\\fR" },
458 { "example", 1, ".RS 2\n.nf\n" },
459 { "smallexample", 1, ".RS 2\n.nf\n" },
463 { "xref", 0, "see: [", "]" },
464 { "pxref", 0, "see: [", "]" },
465 { "uref", 0, "(\\fB", "\\fR)" },
466 { "footnote",0, " ([", "])" },
467 { "emph", 0, "\\fI", "\\fR" },
476 { "subsection", 6, "\n.SS " },
478 { "item", 2, ".TP\n.B " },
479 { "itemx", 2, ".TP\n.B " },
482 { "bullet", 0, "* " },
484 { "quotation",1, ".RS\n\\fB" },
490 const char *lead_out
= NULL
;
493 for (i
=0; cmdtbl
[i
].name
&& strcmp (cmdtbl
[i
].name
, command
); i
++)
497 s
= cmdtbl
[i
].lead_in
;
500 lead_out
= cmdtbl
[i
].lead_out
;
501 switch (cmdtbl
[i
].what
)
503 case 1: /* Throw away the entire line. */
504 s
= memchr (rest
, '\n', len
);
505 return s
? (s
-rest
)+1 : len
;
506 case 2: /* Handle @item. */
508 case 3: /* Handle table. */
509 if (++(*table_level
) > 1)
511 /* Now throw away the entire line. */
512 s
= memchr (rest
, '\n', len
);
513 return s
? (s
-rest
)+1 : len
;
515 case 4: /* Handle end. */
516 for (s
=rest
, n
=len
; n
&& (*s
== ' ' || *s
== '\t'); s
++, n
--)
518 if (n
>= 5 && !memcmp (s
, "table", 5)
519 && (!n
|| s
[5] == ' ' || s
[5] == '\t' || s
[5] == '\n'))
521 if ((*table_level
)-- > 1)
524 else if (n
>= 7 && !memcmp (s
, "example", 7)
525 && (!n
|| s
[7] == ' ' || s
[7] == '\t' || s
[7] == '\n'))
527 fputs (".fi\n.RE\n", fp
);
529 else if (n
>= 12 && !memcmp (s
, "smallexample", 12)
530 && (!n
|| s
[12] == ' ' || s
[12] == '\t' || s
[12] == '\n'))
532 fputs (".fi\n.RE\n", fp
);
534 else if (n
>= 9 && !memcmp (s
, "quotation", 9)
535 && (!n
|| s
[9] == ' ' || s
[9] == '\t' || s
[9] == '\n'))
537 fputs ("\\fR\n.RE\n", fp
);
539 /* Now throw away the entire line. */
540 s
= memchr (rest
, '\n', len
);
541 return s
? (s
-rest
)+1 : len
;
542 case 5: /* Handle special comments. */
543 for (s
=rest
, n
=len
; n
&& (*s
== ' ' || *s
== '\t'); s
++, n
--)
545 if (n
>= 4 && !memcmp (s
, "man:", 4))
547 for (s
+=4, n
-=4; n
&& *s
!= '\n'; n
--, s
++)
551 /* Now throw away the entire line. */
552 s
= memchr (rest
, '\n', len
);
553 return s
? (s
-rest
)+1 : len
;
568 for (m
= macrolist
; m
; m
= m
->next
)
569 if (!strcmp (m
->name
, command
))
573 proc_texi_buffer (fp
, m
->value
, strlen (m
->value
),
574 table_level
, eol_action
);
575 ignore_args
= 1; /* Parameterized macros are not yet supported. */
578 inf ("texinfo command `%s' not supported (%.*s)", command
,
579 ((s
= memchr (rest
, '\n', len
)), (s
? (s
-rest
) : len
)), rest
);
584 /* Find matching closing brace. */
585 for (s
=rest
+1, n
=1, i
=1; i
&& *s
&& n
< len
; s
++, n
++)
592 err ("closing brace for command `%s' not found", command
);
595 if (n
> 2 && !ignore_args
)
596 proc_texi_buffer (fp
, rest
+1, n
-2, table_level
, eol_action
);
602 fputs (lead_out
, fp
);
609 /* Process the string LINE with LEN bytes of Texinfo content. */
611 proc_texi_buffer (FILE *fp
, const char *line
, size_t len
,
612 int *table_level
, int *eol_action
)
620 for (s
=line
; *s
&& len
; s
++, len
--)
628 case '@': case '{': case '}':
629 putc (*s
, fp
); in_cmd
= 0;
631 case ':': /* Not ending a sentence flag. */
634 case '.': case '!': case '?': /* Ending a sentence. */
635 putc (*s
, fp
); in_cmd
= 0;
637 case ' ': case '\t': case '\n': /* Non collapsing spaces. */
638 putc (*s
, fp
); in_cmd
= 0;
642 cmdbuf
[cmdidx
++] = *s
;
647 else if (*s
== '{' || *s
== ' ' || *s
== '\t' || *s
== '\n')
650 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
656 else if (cmdidx
< sizeof cmdbuf
-1)
657 cmdbuf
[cmdidx
++] = *s
;
660 err ("texinfo command too long - ignored");
670 case 1: /* Create a dummy paragraph. */
671 fputs ("\n\\ \n", fp
);
685 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
694 /* Do something with the Texinfo line LINE. */
696 parse_texi_line (FILE *fp
, const char *line
, int *table_level
)
700 /* A quick test whether there are any texinfo commands. */
701 if (!strchr (line
, '@'))
707 proc_texi_buffer (fp
, line
, strlen (line
), table_level
, &eol_action
);
712 /* Write all the lines LINES to FP. */
714 write_content (FILE *fp
, line_buffer_t lines
)
719 for (line
= lines
; line
; line
= line
->next
)
723 fputs (line
->line
, fp
);
728 /* fputs ("TEXI---", fp); */
729 /* fputs (line->line, fp); */
730 /* fputs ("---\n", fp); */
731 parse_texi_line (fp
, line
->line
, &table_level
);
739 is_standard_section (const char *name
)
744 for (i
=0; (s
=standard_sections
[i
]); i
++)
745 if (!strcmp (s
, name
))
751 /* Finish a page; that is sort the data and write it out to the file. */
756 section_buffer_t sect
= NULL
;
762 return; /* No page active. */
765 inf ("finishing page `%s'", thepage
.name
);
769 if (!strcmp (opt_select
, thepage
.name
))
771 inf ("selected `%s'", thepage
.name
);
776 fp
= fopen ( "/dev/null", "w" );
778 die ("failed to open /dev/null: %s\n", strerror (errno
));
783 inf ("writing `%s'", thepage
.name
);
784 fp
= fopen ( thepage
.name
, "w" );
786 die ("failed to create `%s': %s\n", thepage
.name
, strerror (errno
));
794 for (idx
=0; (s
=standard_sections
[idx
]); idx
++)
796 for (i
=0; i
< thepage
.n_sections
; i
++)
798 sect
= thepage
.sections
+ i
;
799 if (sect
->name
&& !strcmp (s
, sect
->name
))
802 if (i
== thepage
.n_sections
)
807 fprintf (fp
, ".SH %s\n", sect
->name
);
808 write_content (fp
, sect
->lines
);
809 /* Now continue with all non standard sections directly
810 following this one. */
811 for (i
++; i
< thepage
.n_sections
; i
++)
813 sect
= thepage
.sections
+ i
;
814 if (sect
->name
&& is_standard_section (sect
->name
))
818 fprintf (fp
, ".SH %s\n", sect
->name
);
819 write_content (fp
, sect
->lines
);
832 /* FIXME: Cleanup the content. */
838 /* Parse one Texinfo file and create manpages according to the
839 embedded instructions. */
841 parse_file (const char *fname
, FILE *fp
, char **section_name
, int in_pause
)
845 /* Fixme: The follwing state variables don't carry over to include
848 int skip_to_end
= 0; /* Used to skip over menu entries. */
849 int skip_sect_line
= 0; /* Skip after @mansect. */
850 int ifset_nesting
= 0; /* How often a ifset has been seen. */
851 int ifclear_nesting
= 0; /* How often a ifclear has been seen. */
852 int in_gpgone
= 0; /* Keep track of "@ifset gpgone" parts. */
853 int not_in_gpgone
= 0; /* Keep track of "@ifclear gpgone" parts. */
854 int not_in_man
= 0; /* Keep track of "@ifclear isman" parts. */
856 /* Helper to define a macro. */
857 char *macroname
= NULL
;
858 char *macrovalue
= NULL
;
859 size_t macrovaluesize
= 0;
860 size_t macrovalueused
= 0;
862 line
= xmalloc (LINESIZE
);
863 while (fgets (line
, LINESIZE
, fp
))
865 size_t n
= strlen (line
);
870 if (!n
|| line
[n
-1] != '\n')
872 err ("%s:%d: trailing linefeed missing, line too long or "
873 "embedded Nul character", fname
, lnr
);
880 for (p
=line
+1, n
=1; *p
&& *p
!= ' ' && *p
!= '\t'; p
++)
882 while (*p
== ' ' || *p
== '\t')
888 /* Take action on macro. */
891 if (n
== 4 && !memcmp (line
, "@end", 4)
892 && (line
[4]==' '||line
[4]=='\t'||!line
[4])
893 && !strncmp (p
, "macro", 5)
894 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
899 macrovalue
[--macrovalueused
] = 0; /* Kill the last LF. */
900 macrovalue
[macrovalueused
] = 0; /* Terminate macro. */
901 macrovalue
= xrealloc (macrovalue
, macrovalueused
+1);
903 for (m
= macrolist
; m
; m
= m
->next
)
904 if (!strcmp (m
->name
, macroname
))
910 m
= xcalloc (1, sizeof *m
+ strlen (macroname
));
911 strcpy (m
->name
, macroname
);
915 m
->value
= macrovalue
;
922 if (macrovalueused
+ strlen (line
) + 2 >= macrovaluesize
)
924 macrovaluesize
+= strlen (line
) + 256;
925 macrovalue
= xrealloc (macrovalue
, macrovaluesize
);
927 strcpy (macrovalue
+macrovalueused
, line
);
928 macrovalueused
+= strlen (line
);
929 macrovalue
[macrovalueused
++] = '\n';
935 if (n
>= 5 && !memcmp (line
, "@node", 5)
936 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
938 /* Completey ignore @node lines. */
946 if (!strncmp (line
, "@section", 8)
947 || !strncmp (line
, "@subsection", 11)
948 || !strncmp (line
, "@chapheading", 12))
952 /* We only parse lines we need and ignore the rest. There are a
953 few macros used to control this as well as one @ifset
954 command. Parts we know about are saved away into containers
955 separate for each section. */
957 /* First process ifset/ifclear commands. */
960 if (n
== 6 && !memcmp (line
, "@ifset", 6)
961 && (line
[6]==' '||line
[6]=='\t'))
965 if (!strncmp (p
, "manverb", 7) && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
968 err ("%s:%d: nested \"@ifset manverb\"", fname
, lnr
);
970 in_verbatim
= ifset_nesting
;
972 else if (!strncmp (p
, "gpgone", 6)
973 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
976 err ("%s:%d: nested \"@ifset gpgone\"", fname
, lnr
);
978 in_gpgone
= ifset_nesting
;
982 else if (n
== 4 && !memcmp (line
, "@end", 4)
983 && (line
[4]==' '||line
[4]=='\t')
984 && !strncmp (p
, "ifset", 5)
985 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
987 if (in_verbatim
&& ifset_nesting
== in_verbatim
)
989 if (in_gpgone
&& ifset_nesting
== in_gpgone
)
995 err ("%s:%d: unbalanced \"@end ifset\"", fname
, lnr
);
998 else if (n
== 8 && !memcmp (line
, "@ifclear", 8)
999 && (line
[8]==' '||line
[8]=='\t'))
1003 if (!strncmp (p
, "gpgone", 6)
1004 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
1007 err ("%s:%d: nested \"@ifclear gpgone\"", fname
, lnr
);
1009 not_in_gpgone
= ifclear_nesting
;
1012 else if (!strncmp (p
, "isman", 5)
1013 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
1016 err ("%s:%d: nested \"@ifclear isman\"", fname
, lnr
);
1018 not_in_man
= ifclear_nesting
;
1023 else if (n
== 4 && !memcmp (line
, "@end", 4)
1024 && (line
[4]==' '||line
[4]=='\t')
1025 && !strncmp (p
, "ifclear", 7)
1026 && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
1028 if (not_in_gpgone
&& ifclear_nesting
== not_in_gpgone
)
1030 if (not_in_man
&& ifclear_nesting
== not_in_man
)
1033 if (ifclear_nesting
)
1036 err ("%s:%d: unbalanced \"@end ifclear\"", fname
, lnr
);
1041 /* Take action on ifset/ifclear. */
1042 if ( (in_gpgone
&& !gpgone_defined
)
1043 || (not_in_gpgone
&& gpgone_defined
)
1047 /* Process commands. */
1051 && n
== 4 && !memcmp (line
, "@end", 4)
1052 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1056 else if (in_verbatim
)
1060 else if (n
== 6 && !memcmp (line
, "@macro", 6))
1062 macroname
= xstrdup (p
);
1063 macrovalue
= xmalloc ((macrovaluesize
= 1024));
1066 else if (n
== 8 && !memcmp (line
, "@manpage", 8))
1068 free (*section_name
);
1069 *section_name
= NULL
;
1074 else if (n
== 8 && !memcmp (line
, "@mansect", 8))
1077 err ("%s:%d: section outside of a man page", fname
, lnr
);
1080 free (*section_name
);
1081 *section_name
= ascii_strupr (xstrdup (p
));
1086 else if (n
== 9 && !memcmp (line
, "@manpause", 9))
1089 err ("%s:%d: pausing outside of a man section", fname
, lnr
);
1091 err ("%s:%d: already pausing", fname
, lnr
);
1095 else if (n
== 8 && !memcmp (line
, "@mancont", 8))
1098 err ("%s:%d: continue outside of a man section", fname
, lnr
);
1100 err ("%s:%d: continue while not pausing", fname
, lnr
);
1104 else if (n
== 5 && !memcmp (line
, "@menu", 5)
1105 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
1109 else if (n
== 8 && !memcmp (line
, "@include", 8)
1110 && (line
[8]==' '||line
[8]=='\t'||!line
[8]))
1112 char *incname
= xstrdup (p
);
1113 FILE *incfp
= fopen (incname
, "r");
1115 if (!incfp
&& opt_include
&& *opt_include
&& *p
!= '/')
1118 incname
= xmalloc (strlen (opt_include
) + 1
1120 strcpy (incname
, opt_include
);
1121 if ( incname
[strlen (incname
)-1] != '/' )
1122 strcat (incname
, "/");
1123 strcat (incname
, p
);
1124 incfp
= fopen (incname
, "r");
1128 err ("can't open include file `%s':%s",
1129 incname
, strerror (errno
));
1132 parse_file (incname
, incfp
, section_name
, in_pause
);
1137 else if (n
== 4 && !memcmp (line
, "@bye", 4)
1138 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1142 else if (!skip_to_end
)
1145 else if (!skip_to_end
)
1148 if (got_line
&& in_verbatim
)
1149 add_content (*section_name
, line
, 1);
1150 else if (got_line
&& thepage
.name
&& *section_name
&& !in_pause
)
1151 add_content (*section_name
, line
, 0);
1155 err ("%s:%d: read error: %s", fname
, lnr
, strerror (errno
));
1163 top_parse_file (const char *fname
, FILE *fp
)
1165 char *section_name
= NULL
; /* Name of the current section or NULL
1166 if not in a section. */
1169 macro_t m
= macrolist
->next
;
1175 parse_file (fname
, fp
, §ion_name
, 0);
1176 free (section_name
);
1182 main (int argc
, char **argv
)
1193 while (argc
&& last_argc
!= argc
)
1196 if (!strcmp (*argv
, "--"))
1201 else if (!strcmp (*argv
, "--help"))
1204 "Usage: " PGM
" [OPTION] [FILE]\n"
1205 "Extract man pages from a Texinfo source.\n\n"
1206 " --source NAME use NAME as source field\n"
1207 " --release STRING use STRING as the release field\n"
1208 " --store write output using @manpage name\n"
1209 " --select NAME only output pages with @manpage NAME\n"
1210 " --verbose enable extra informational output\n"
1211 " --debug enable additional debug output\n"
1212 " --help display this help and exit\n"
1213 " -I DIR also search in include DIR\n"
1214 " -D gpgone the only useable define\n\n"
1215 "With no FILE, or when FILE is -, read standard input.\n\n"
1216 "Report bugs to <bugs@g10code.com>.");
1219 else if (!strcmp (*argv
, "--version"))
1221 puts (PGM
" " VERSION
"\n"
1222 "Copyright (C) 2005 g10 Code GmbH\n"
1223 "This program comes with ABSOLUTELY NO WARRANTY.\n"
1224 "This is free software, and you are welcome to redistribute it\n"
1225 "under certain conditions. See the file COPYING for details.");
1228 else if (!strcmp (*argv
, "--verbose"))
1233 else if (!strcmp (*argv
, "--quiet"))
1238 else if (!strcmp (*argv
, "--debug"))
1240 verbose
= debug
= 1;
1243 else if (!strcmp (*argv
, "--source"))
1252 else if (!strcmp (*argv
, "--release"))
1257 opt_release
= *argv
;
1261 else if (!strcmp (*argv
, "--store"))
1266 else if (!strcmp (*argv
, "--select"))
1271 opt_select
= strrchr (*argv
, '/');
1279 else if (!strcmp (*argv
, "-I"))
1284 opt_include
= *argv
;
1288 else if (!strcmp (*argv
, "-D"))
1293 if (!strcmp (*argv
, "gpgone"))
1301 die ("usage: " PGM
" [OPTION] [FILE] (try --help for more information)\n");
1303 /* Start processing. */
1304 if (argc
&& strcmp (*argv
, "-"))
1306 FILE *fp
= fopen (*argv
, "rb");
1308 die ("%s:0: can't open file: %s", *argv
, strerror (errno
));
1309 top_parse_file (*argv
, fp
);
1313 top_parse_file ("-", stdin
);
1321 compile-command: "gcc -Wall -g -Wall -o yat2m yat2m.c"