1 /* yat2m.c - Yet Another Texi 2 Man converter
2 * Copyright (C) 2005 g10 Code GmbH
3 * Copyright (C) 2006, 2008, 2011 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
75 If you want to indent tables in the source use this style:
85 Don't change the indentation within a table and keep the same
86 number of white space at the start of the line. yat2m simply
87 detects the number of white spaces in front of an @item and remove
88 this number of spaces from all following lines until a new @item
89 is found or there are less spaces than for the last @item.
104 #define VERSION "1.0"
106 /* The maximum length of a line including the linefeed and one extra
108 #define LINESIZE 1024
114 static const char *opt_source
;
115 static const char *opt_release
;
116 static const char *opt_select
;
117 static const char *opt_include
;
118 static int opt_store
;
120 /* The only define we understand is -D gpgone. Thus we need a simple
121 boolean tro track it. */
122 static int gpgone_defined
;
124 /* Flag to keep track whether any error occurred. */
125 static int any_error
;
128 /* Object to keep macro definitions. */
131 struct macro_s
*next
;
132 char *value
; /* Malloced value. */
135 typedef struct macro_s
*macro_t
;
137 /* List of all defined macros. */
138 static macro_t macrolist
;
141 /* Object to store one line of content. */
144 struct line_buffer_s
*next
;
145 int verbatim
; /* True if LINE contains verbatim data. The default
146 is Texinfo source. */
149 typedef struct line_buffer_s
*line_buffer_t
;
152 /* Object to collect the data of a section. */
153 struct section_buffer_s
155 char *name
; /* Malloced name of the section. This may be
156 NULL to indicate this slot is not used. */
157 line_buffer_t lines
; /* Linked list with the lines of the section. */
158 line_buffer_t
*lines_tail
; /* Helper for faster appending to the
160 line_buffer_t last_line
; /* Points to the last line appended. */
162 typedef struct section_buffer_s
*section_buffer_t
;
164 /* Variable to keep info about the current page together. */
167 /* Filename of the current page or NULL if no page is active. Malloced. */
170 /* Number of allocated elements in SECTIONS below. */
172 /* Array with the data of the sections. */
173 section_buffer_t sections
;
178 /* The list of standard section names. COMMANDS and ASSUAN are GnuPG
180 static const char * const standard_sections
[] =
181 { "NAME", "SYNOPSIS", "DESCRIPTION",
182 "RETURN VALUE", "EXIT STATUS", "ERROR HANDLING", "ERRORS",
183 "COMMANDS", "OPTIONS", "USAGE", "EXAMPLES", "FILES",
184 "ENVIRONMENT", "DIAGNOSTICS", "SECURITY", "CONFORMING TO",
185 "ASSUAN", "NOTES", "BUGS", "AUTHOR", "SEE ALSO", NULL
};
188 /*-- Local prototypes. --*/
189 static void proc_texi_buffer (FILE *fp
, const char *line
, size_t len
,
190 int *table_level
, int *eol_action
);
194 /* Print diagnostic message and exit with failure. */
196 die (const char *format
, ...)
201 fprintf (stderr
, "%s: ", PGM
);
203 va_start (arg_ptr
, format
);
204 vfprintf (stderr
, format
, arg_ptr
);
212 /* Print diagnostic message. */
214 err (const char *format
, ...)
219 if (strncmp (format
, "%s:%d:", 6))
220 fprintf (stderr
, "%s: ", PGM
);
222 va_start (arg_ptr
, format
);
223 vfprintf (stderr
, format
, arg_ptr
);
229 /* Print diagnostic message. */
231 inf (const char *format
, ...)
236 fprintf (stderr
, "%s: ", PGM
);
238 va_start (arg_ptr
, format
);
239 vfprintf (stderr
, format
, arg_ptr
);
248 void *p
= malloc (n
);
250 die ("out of core: %s", strerror (errno
));
255 xcalloc (size_t n
, size_t m
)
257 void *p
= calloc (n
, m
);
259 die ("out of core: %s", strerror (errno
));
264 xrealloc (void *old
, size_t n
)
266 void *p
= realloc (old
, n
);
268 die ("out of core: %s", strerror (errno
));
273 xstrdup (const char *string
)
275 void *p
= malloc (strlen (string
)+1);
277 die ("out of core: %s", strerror (errno
));
283 /* Uppercase the ascii characters in STRING. */
285 ascii_strupr (char *string
)
289 for (p
= string
; *p
; p
++)
296 /* Return the current date as an ISO string. */
300 static char buffer
[11+5];
302 time_t atime
= time (NULL
);
305 strcpy (buffer
, "????" "-??" "-??");
308 tp
= gmtime (&atime
);
309 sprintf (buffer
,"%04d-%02d-%02d",
310 1900+tp
->tm_year
, tp
->tm_mon
+1, tp
->tm_mday
);
317 /* Return a section buffer for the section NAME. Allocate a new buffer
318 if this is a new section. Keep track of the sections in THEPAGE.
319 This function may reallocate the section array in THEPAGE. */
320 static section_buffer_t
321 get_section_buffer (const char *name
)
324 section_buffer_t sect
;
326 /* If there is no section we put everything into the required NAME
327 section. Given that this is the first one listed it is likely
328 that error are easily visible. */
332 for (i
=0; i
< thepage
.n_sections
; i
++)
334 sect
= thepage
.sections
+ i
;
335 if (sect
->name
&& !strcmp (name
, sect
->name
))
338 for (i
=0; i
< thepage
.n_sections
; i
++)
339 if (!thepage
.sections
[i
].name
)
341 if (i
< thepage
.n_sections
)
342 sect
= thepage
.sections
+ i
;
345 /* We need to allocate or reallocate the section array. */
346 size_t old_n
= thepage
.n_sections
;
350 thepage
.sections
= xcalloc (new_n
, sizeof *thepage
.sections
);
353 thepage
.sections
= xrealloc (thepage
.sections
,
355 * sizeof *thepage
.sections
));
356 memset (thepage
.sections
+ old_n
, 0,
357 new_n
* sizeof *thepage
.sections
);
359 thepage
.n_sections
+= new_n
;
361 /* Setup the tail pointers. */
362 for (i
=old_n
; i
< thepage
.n_sections
; i
++)
364 sect
= thepage
.sections
+ i
;
365 sect
->lines_tail
= §
->lines
;
367 sect
= thepage
.sections
+ old_n
;
370 /* Store the name. */
371 assert (!sect
->name
);
372 sect
->name
= xstrdup (name
);
378 /* Add the content of LINE to the section named SECTNAME. */
380 add_content (const char *sectname
, char *line
, int verbatim
)
382 section_buffer_t sect
;
385 sect
= get_section_buffer (sectname
);
386 if (sect
->last_line
&& !sect
->last_line
->verbatim
== !verbatim
)
388 /* Lets append that line to the last one. We do this to keep
389 all lines of the same kind (i.e.verbatim or not) together in
393 lb
= sect
->last_line
;
394 n1
= strlen (lb
->line
);
395 n
= n1
+ 1 + strlen (line
) + 1;
396 lb
->line
= xrealloc (lb
->line
, n
);
397 strcpy (lb
->line
+n1
, "\n");
398 strcpy (lb
->line
+n1
+1, line
);
402 lb
= xcalloc (1, sizeof *lb
);
403 lb
->verbatim
= verbatim
;
404 lb
->line
= xstrdup (line
);
405 sect
->last_line
= lb
;
406 *sect
->lines_tail
= lb
;
407 sect
->lines_tail
= &lb
->next
;
412 /* Prepare for a new man page using the filename NAME. */
414 start_page (char *name
)
417 inf ("starting page '%s'", name
);
418 assert (!thepage
.name
);
419 thepage
.name
= xstrdup (name
);
420 thepage
.n_sections
= 0;
424 /* Write the .TH entry of the current page. Return -1 if there is a
425 problem with the page. */
431 fputs (".\\\" Created from Texinfo source by yat2m " VERSION
"\n", fp
);
433 name
= ascii_strupr (xstrdup (thepage
.name
));
434 p
= strrchr (name
, '.');
437 err ("no section name in man page '%s'", thepage
.name
);
442 fprintf (fp
, ".TH %s %s %s \"%s\" \"%s\"\n",
443 name
, p
, isodatestring (), opt_release
, opt_source
);
448 /* Process the texinfo command COMMAND (without the leading @) and
449 write output if needed to FP. REST is the remainer of the line
450 which should either point to an opening brace or to a white space.
451 The function returns the number of characters already processed
452 from REST. LEN is the usable length of REST. TABLE_LEVEL is used to
453 control the indentation of tables. */
455 proc_texi_cmd (FILE *fp
, const char *command
, const char *rest
, size_t len
,
456 int *table_level
, int *eol_action
)
459 const char *name
; /* Name of the command. */
460 int what
; /* What to do with this command. */
461 const char *lead_in
; /* String to print with a opening brace. */
462 const char *lead_out
;/* String to print with the closing brace. */
464 { "command", 0, "\\fB", "\\fR" },
465 { "code", 0, "\\fB", "\\fR" },
466 { "sc", 0, "\\fB", "\\fR" },
467 { "var", 0, "\\fI", "\\fR" },
468 { "samp", 0, "\\(aq", "\\(aq" },
469 { "file", 0, "\\(oq\\fI","\\fR\\(cq" },
470 { "env", 0, "\\(oq\\fI","\\fR\\(cq" },
473 { "option", 0, "\\fB", "\\fR" },
474 { "example", 1, ".RS 2\n.nf\n" },
475 { "smallexample", 1, ".RS 2\n.nf\n" },
479 { "xref", 0, "see: [", "]" },
480 { "pxref", 0, "see: [", "]" },
481 { "uref", 0, "(\\fB", "\\fR)" },
482 { "footnote",0, " ([", "])" },
483 { "emph", 0, "\\fI", "\\fR" },
492 { "subsection", 6, "\n.SS " },
494 { "item", 2, ".TP\n.B " },
495 { "itemx", 2, ".TP\n.B " },
498 { "bullet", 0, "* " },
500 { "quotation",1, ".RS\n\\fB" },
506 const char *lead_out
= NULL
;
509 for (i
=0; cmdtbl
[i
].name
&& strcmp (cmdtbl
[i
].name
, command
); i
++)
513 s
= cmdtbl
[i
].lead_in
;
516 lead_out
= cmdtbl
[i
].lead_out
;
517 switch (cmdtbl
[i
].what
)
519 case 1: /* Throw away the entire line. */
520 s
= memchr (rest
, '\n', len
);
521 return s
? (s
-rest
)+1 : len
;
522 case 2: /* Handle @item. */
524 case 3: /* Handle table. */
525 if (++(*table_level
) > 1)
527 /* Now throw away the entire line. */
528 s
= memchr (rest
, '\n', len
);
529 return s
? (s
-rest
)+1 : len
;
531 case 4: /* Handle end. */
532 for (s
=rest
, n
=len
; n
&& (*s
== ' ' || *s
== '\t'); s
++, n
--)
534 if (n
>= 5 && !memcmp (s
, "table", 5)
535 && (!n
|| s
[5] == ' ' || s
[5] == '\t' || s
[5] == '\n'))
537 if ((*table_level
)-- > 1)
540 else if (n
>= 7 && !memcmp (s
, "example", 7)
541 && (!n
|| s
[7] == ' ' || s
[7] == '\t' || s
[7] == '\n'))
543 fputs (".fi\n.RE\n", fp
);
545 else if (n
>= 12 && !memcmp (s
, "smallexample", 12)
546 && (!n
|| s
[12] == ' ' || s
[12] == '\t' || s
[12] == '\n'))
548 fputs (".fi\n.RE\n", fp
);
550 else if (n
>= 9 && !memcmp (s
, "quotation", 9)
551 && (!n
|| s
[9] == ' ' || s
[9] == '\t' || s
[9] == '\n'))
553 fputs ("\\fR\n.RE\n", fp
);
555 /* Now throw away the entire line. */
556 s
= memchr (rest
, '\n', len
);
557 return s
? (s
-rest
)+1 : len
;
558 case 5: /* Handle special comments. */
559 for (s
=rest
, n
=len
; n
&& (*s
== ' ' || *s
== '\t'); s
++, n
--)
561 if (n
>= 4 && !memcmp (s
, "man:", 4))
563 for (s
+=4, n
-=4; n
&& *s
!= '\n'; n
--, s
++)
567 /* Now throw away the entire line. */
568 s
= memchr (rest
, '\n', len
);
569 return s
? (s
-rest
)+1 : len
;
584 for (m
= macrolist
; m
; m
= m
->next
)
585 if (!strcmp (m
->name
, command
))
589 proc_texi_buffer (fp
, m
->value
, strlen (m
->value
),
590 table_level
, eol_action
);
591 ignore_args
= 1; /* Parameterized macros are not yet supported. */
594 inf ("texinfo command '%s' not supported (%.*s)", command
,
595 ((s
= memchr (rest
, '\n', len
)), (s
? (s
-rest
) : len
)), rest
);
600 /* Find matching closing brace. */
601 for (s
=rest
+1, n
=1, i
=1; i
&& *s
&& n
< len
; s
++, n
++)
608 err ("closing brace for command '%s' not found", command
);
611 if (n
> 2 && !ignore_args
)
612 proc_texi_buffer (fp
, rest
+1, n
-2, table_level
, eol_action
);
618 fputs (lead_out
, fp
);
625 /* Process the string LINE with LEN bytes of Texinfo content. */
627 proc_texi_buffer (FILE *fp
, const char *line
, size_t len
,
628 int *table_level
, int *eol_action
)
636 for (s
=line
; *s
&& len
; s
++, len
--)
644 case '@': case '{': case '}':
645 putc (*s
, fp
); in_cmd
= 0;
647 case ':': /* Not ending a sentence flag. */
650 case '.': case '!': case '?': /* Ending a sentence. */
651 putc (*s
, fp
); in_cmd
= 0;
653 case ' ': case '\t': case '\n': /* Non collapsing spaces. */
654 putc (*s
, fp
); in_cmd
= 0;
658 cmdbuf
[cmdidx
++] = *s
;
663 else if (*s
== '{' || *s
== ' ' || *s
== '\t' || *s
== '\n')
666 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
672 else if (cmdidx
< sizeof cmdbuf
-1)
673 cmdbuf
[cmdidx
++] = *s
;
676 err ("texinfo command too long - ignored");
686 case 1: /* Create a dummy paragraph. */
687 fputs ("\n\\ \n", fp
);
703 n
= proc_texi_cmd (fp
, cmdbuf
, s
, len
, table_level
, eol_action
);
712 /* Do something with the Texinfo line LINE. */
714 parse_texi_line (FILE *fp
, const char *line
, int *table_level
)
718 /* A quick test whether there are any texinfo commands. */
719 if (!strchr (line
, '@'))
725 proc_texi_buffer (fp
, line
, strlen (line
), table_level
, &eol_action
);
730 /* Write all the lines LINES to FP. */
732 write_content (FILE *fp
, line_buffer_t lines
)
737 for (line
= lines
; line
; line
= line
->next
)
741 fputs (line
->line
, fp
);
746 /* fputs ("TEXI---", fp); */
747 /* fputs (line->line, fp); */
748 /* fputs ("---\n", fp); */
749 parse_texi_line (fp
, line
->line
, &table_level
);
757 is_standard_section (const char *name
)
762 for (i
=0; (s
=standard_sections
[i
]); i
++)
763 if (!strcmp (s
, name
))
769 /* Finish a page; that is sort the data and write it out to the file. */
774 section_buffer_t sect
= NULL
;
780 return; /* No page active. */
783 inf ("finishing page '%s'", thepage
.name
);
787 if (!strcmp (opt_select
, thepage
.name
))
789 inf ("selected '%s'", thepage
.name
);
794 fp
= fopen ( "/dev/null", "w" );
796 die ("failed to open /dev/null: %s\n", strerror (errno
));
801 inf ("writing '%s'", thepage
.name
);
802 fp
= fopen ( thepage
.name
, "w" );
804 die ("failed to create '%s': %s\n", thepage
.name
, strerror (errno
));
812 for (idx
=0; (s
=standard_sections
[idx
]); idx
++)
814 for (i
=0; i
< thepage
.n_sections
; i
++)
816 sect
= thepage
.sections
+ i
;
817 if (sect
->name
&& !strcmp (s
, sect
->name
))
820 if (i
== thepage
.n_sections
)
825 fprintf (fp
, ".SH %s\n", sect
->name
);
826 write_content (fp
, sect
->lines
);
827 /* Now continue with all non standard sections directly
828 following this one. */
829 for (i
++; i
< thepage
.n_sections
; i
++)
831 sect
= thepage
.sections
+ i
;
832 if (sect
->name
&& is_standard_section (sect
->name
))
836 fprintf (fp
, ".SH %s\n", sect
->name
);
837 write_content (fp
, sect
->lines
);
850 /* FIXME: Cleanup the content. */
856 /* Parse one Texinfo file and create manpages according to the
857 embedded instructions. */
859 parse_file (const char *fname
, FILE *fp
, char **section_name
, int in_pause
)
863 /* Fixme: The following state variables don't carry over to include
866 int skip_to_end
= 0; /* Used to skip over menu entries. */
867 int skip_sect_line
= 0; /* Skip after @mansect. */
868 int ifset_nesting
= 0; /* How often a ifset has been seen. */
869 int ifclear_nesting
= 0; /* How often a ifclear has been seen. */
870 int in_gpgone
= 0; /* Keep track of "@ifset gpgone" parts. */
871 int not_in_gpgone
= 0; /* Keep track of "@ifclear gpgone" parts. */
872 int not_in_man
= 0; /* Keep track of "@ifclear isman" parts. */
873 int item_indent
= 0; /* How far is the current @item indented. */
875 /* Helper to define a macro. */
876 char *macroname
= NULL
;
877 char *macrovalue
= NULL
;
878 size_t macrovaluesize
= 0;
879 size_t macrovalueused
= 0;
881 line
= xmalloc (LINESIZE
);
882 while (fgets (line
, LINESIZE
, fp
))
884 size_t n
= strlen (line
);
889 if (!n
|| line
[n
-1] != '\n')
891 err ("%s:%d: trailing linefeed missing, line too long or "
892 "embedded Nul character", fname
, lnr
);
897 /* Kludge to allow indentation of tables. */
898 for (p
=line
; *p
== ' ' || *p
== '\t'; p
++)
902 if (*p
== '@' && !strncmp (p
+1, "item", 4))
903 item_indent
= p
- line
; /* Set a new indent level. */
904 else if (p
- line
< item_indent
)
905 item_indent
= 0; /* Switch off indention. */
909 memmove (line
, line
+item_indent
, n
- item_indent
+ 1);
917 for (p
=line
+1, n
=1; *p
&& *p
!= ' ' && *p
!= '\t'; p
++)
919 while (*p
== ' ' || *p
== '\t')
925 /* Take action on macro. */
928 if (n
== 4 && !memcmp (line
, "@end", 4)
929 && (line
[4]==' '||line
[4]=='\t'||!line
[4])
930 && !strncmp (p
, "macro", 5)
931 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
936 macrovalue
[--macrovalueused
] = 0; /* Kill the last LF. */
937 macrovalue
[macrovalueused
] = 0; /* Terminate macro. */
938 macrovalue
= xrealloc (macrovalue
, macrovalueused
+1);
940 for (m
= macrolist
; m
; m
= m
->next
)
941 if (!strcmp (m
->name
, macroname
))
947 m
= xcalloc (1, sizeof *m
+ strlen (macroname
));
948 strcpy (m
->name
, macroname
);
952 m
->value
= macrovalue
;
959 if (macrovalueused
+ strlen (line
) + 2 >= macrovaluesize
)
961 macrovaluesize
+= strlen (line
) + 256;
962 macrovalue
= xrealloc (macrovalue
, macrovaluesize
);
964 strcpy (macrovalue
+macrovalueused
, line
);
965 macrovalueused
+= strlen (line
);
966 macrovalue
[macrovalueused
++] = '\n';
972 if (n
>= 5 && !memcmp (line
, "@node", 5)
973 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
975 /* Completey ignore @node lines. */
983 if (!strncmp (line
, "@section", 8)
984 || !strncmp (line
, "@subsection", 11)
985 || !strncmp (line
, "@chapheading", 12))
989 /* We only parse lines we need and ignore the rest. There are a
990 few macros used to control this as well as one @ifset
991 command. Parts we know about are saved away into containers
992 separate for each section. */
994 /* First process ifset/ifclear commands. */
997 if (n
== 6 && !memcmp (line
, "@ifset", 6)
998 && (line
[6]==' '||line
[6]=='\t'))
1002 if (!strncmp (p
, "manverb", 7) && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
1005 err ("%s:%d: nested \"@ifset manverb\"", fname
, lnr
);
1007 in_verbatim
= ifset_nesting
;
1009 else if (!strncmp (p
, "gpgone", 6)
1010 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
1013 err ("%s:%d: nested \"@ifset gpgone\"", fname
, lnr
);
1015 in_gpgone
= ifset_nesting
;
1019 else if (n
== 4 && !memcmp (line
, "@end", 4)
1020 && (line
[4]==' '||line
[4]=='\t')
1021 && !strncmp (p
, "ifset", 5)
1022 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
1024 if (in_verbatim
&& ifset_nesting
== in_verbatim
)
1026 if (in_gpgone
&& ifset_nesting
== in_gpgone
)
1032 err ("%s:%d: unbalanced \"@end ifset\"", fname
, lnr
);
1035 else if (n
== 8 && !memcmp (line
, "@ifclear", 8)
1036 && (line
[8]==' '||line
[8]=='\t'))
1040 if (!strncmp (p
, "gpgone", 6)
1041 && (p
[6]==' '||p
[6]=='\t'||!p
[6]))
1044 err ("%s:%d: nested \"@ifclear gpgone\"", fname
, lnr
);
1046 not_in_gpgone
= ifclear_nesting
;
1049 else if (!strncmp (p
, "isman", 5)
1050 && (p
[5]==' '||p
[5]=='\t'||!p
[5]))
1053 err ("%s:%d: nested \"@ifclear isman\"", fname
, lnr
);
1055 not_in_man
= ifclear_nesting
;
1060 else if (n
== 4 && !memcmp (line
, "@end", 4)
1061 && (line
[4]==' '||line
[4]=='\t')
1062 && !strncmp (p
, "ifclear", 7)
1063 && (p
[7]==' '||p
[7]=='\t'||!p
[7]))
1065 if (not_in_gpgone
&& ifclear_nesting
== not_in_gpgone
)
1067 if (not_in_man
&& ifclear_nesting
== not_in_man
)
1070 if (ifclear_nesting
)
1073 err ("%s:%d: unbalanced \"@end ifclear\"", fname
, lnr
);
1078 /* Take action on ifset/ifclear. */
1079 if ( (in_gpgone
&& !gpgone_defined
)
1080 || (not_in_gpgone
&& gpgone_defined
)
1084 /* Process commands. */
1088 && n
== 4 && !memcmp (line
, "@end", 4)
1089 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1093 else if (in_verbatim
)
1097 else if (n
== 6 && !memcmp (line
, "@macro", 6))
1099 macroname
= xstrdup (p
);
1100 macrovalue
= xmalloc ((macrovaluesize
= 1024));
1103 else if (n
== 8 && !memcmp (line
, "@manpage", 8))
1105 free (*section_name
);
1106 *section_name
= NULL
;
1111 else if (n
== 8 && !memcmp (line
, "@mansect", 8))
1114 err ("%s:%d: section outside of a man page", fname
, lnr
);
1117 free (*section_name
);
1118 *section_name
= ascii_strupr (xstrdup (p
));
1123 else if (n
== 9 && !memcmp (line
, "@manpause", 9))
1126 err ("%s:%d: pausing outside of a man section", fname
, lnr
);
1128 err ("%s:%d: already pausing", fname
, lnr
);
1132 else if (n
== 8 && !memcmp (line
, "@mancont", 8))
1135 err ("%s:%d: continue outside of a man section", fname
, lnr
);
1137 err ("%s:%d: continue while not pausing", fname
, lnr
);
1141 else if (n
== 5 && !memcmp (line
, "@menu", 5)
1142 && (line
[5]==' '||line
[5]=='\t'||!line
[5]))
1146 else if (n
== 8 && !memcmp (line
, "@include", 8)
1147 && (line
[8]==' '||line
[8]=='\t'||!line
[8]))
1149 char *incname
= xstrdup (p
);
1150 FILE *incfp
= fopen (incname
, "r");
1152 if (!incfp
&& opt_include
&& *opt_include
&& *p
!= '/')
1155 incname
= xmalloc (strlen (opt_include
) + 1
1157 strcpy (incname
, opt_include
);
1158 if ( incname
[strlen (incname
)-1] != '/' )
1159 strcat (incname
, "/");
1160 strcat (incname
, p
);
1161 incfp
= fopen (incname
, "r");
1165 err ("can't open include file '%s':%s",
1166 incname
, strerror (errno
));
1169 parse_file (incname
, incfp
, section_name
, in_pause
);
1174 else if (n
== 4 && !memcmp (line
, "@bye", 4)
1175 && (line
[4]==' '||line
[4]=='\t'||!line
[4]))
1179 else if (!skip_to_end
)
1182 else if (!skip_to_end
)
1185 if (got_line
&& in_verbatim
)
1186 add_content (*section_name
, line
, 1);
1187 else if (got_line
&& thepage
.name
&& *section_name
&& !in_pause
)
1188 add_content (*section_name
, line
, 0);
1192 err ("%s:%d: read error: %s", fname
, lnr
, strerror (errno
));
1200 top_parse_file (const char *fname
, FILE *fp
)
1202 char *section_name
= NULL
; /* Name of the current section or NULL
1203 if not in a section. */
1206 macro_t next
= macrolist
->next
;
1207 free (macrolist
->value
);
1212 parse_file (fname
, fp
, §ion_name
, 0);
1213 free (section_name
);
1219 main (int argc
, char **argv
)
1230 while (argc
&& last_argc
!= argc
)
1233 if (!strcmp (*argv
, "--"))
1238 else if (!strcmp (*argv
, "--help"))
1241 "Usage: " PGM
" [OPTION] [FILE]\n"
1242 "Extract man pages from a Texinfo source.\n\n"
1243 " --source NAME use NAME as source field\n"
1244 " --release STRING use STRING as the release field\n"
1245 " --store write output using @manpage name\n"
1246 " --select NAME only output pages with @manpage NAME\n"
1247 " --verbose enable extra informational output\n"
1248 " --debug enable additional debug output\n"
1249 " --help display this help and exit\n"
1250 " -I DIR also search in include DIR\n"
1251 " -D gpgone the only useable define\n\n"
1252 "With no FILE, or when FILE is -, read standard input.\n\n"
1253 "Report bugs to <bugs@g10code.com>.");
1256 else if (!strcmp (*argv
, "--version"))
1258 puts (PGM
" " VERSION
"\n"
1259 "Copyright (C) 2005 g10 Code GmbH\n"
1260 "This program comes with ABSOLUTELY NO WARRANTY.\n"
1261 "This is free software, and you are welcome to redistribute it\n"
1262 "under certain conditions. See the file COPYING for details.");
1265 else if (!strcmp (*argv
, "--verbose"))
1270 else if (!strcmp (*argv
, "--quiet"))
1275 else if (!strcmp (*argv
, "--debug"))
1277 verbose
= debug
= 1;
1280 else if (!strcmp (*argv
, "--source"))
1289 else if (!strcmp (*argv
, "--release"))
1294 opt_release
= *argv
;
1298 else if (!strcmp (*argv
, "--store"))
1303 else if (!strcmp (*argv
, "--select"))
1308 opt_select
= strrchr (*argv
, '/');
1316 else if (!strcmp (*argv
, "-I"))
1321 opt_include
= *argv
;
1325 else if (!strcmp (*argv
, "-D"))
1330 if (!strcmp (*argv
, "gpgone"))
1338 die ("usage: " PGM
" [OPTION] [FILE] (try --help for more information)\n");
1340 /* Start processing. */
1341 if (argc
&& strcmp (*argv
, "-"))
1343 FILE *fp
= fopen (*argv
, "rb");
1345 die ("%s:0: can't open file: %s", *argv
, strerror (errno
));
1346 top_parse_file (*argv
, fp
);
1350 top_parse_file ("-", stdin
);
1358 compile-command: "gcc -Wall -g -Wall -o yat2m yat2m.c"