1 /* yat2m.c - Yet Another Texi 2 Man converter
2 * Copyright (C) 2005, 2013, 2015, 2016, 2017 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 <https://www.gnu.org/licenses/>.
20 This is a simple texinfo 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.
91 Note that @* does only work correctly if used at the end of an
108 # define MY_GCC_VERSION (__GNUC__ * 10000 \
109 + __GNUC_MINOR__ * 100 \
110 + __GNUC_PATCHLEVEL__)
112 # define MY_GCC_VERSION 0
115 #if MY_GCC_VERSION >= 20500
116 # define ATTR_PRINTF(f, a) __attribute__ ((format(printf,f,a)))
117 # define ATTR_NR_PRINTF(f, a) __attribute__ ((noreturn, format(printf,f,a)))
119 # define ATTR_PRINTF(f, a)
120 # define ATTR_NR_PRINTF(f, a)
122 #if MY_GCC_VERSION >= 30200
123 # define ATTR_MALLOC __attribute__ ((__malloc__))
131 #ifdef PACKAGE_VERSION
132 # define VERSION PACKAGE_VERSION
134 # define VERSION "1.0"
137 /* The maximum length of a line including the linefeed and one extra
139 #define LINESIZE 1024
141 /* Number of allowed condition nestings. */
142 #define MAX_CONDITION_NESTING 10
148 static const char *opt_source;
149 static const char *opt_release;
150 static const char *opt_date;
151 static const char *opt_select;
152 static const char *opt_include;
153 static int opt_store;
155 /* Flag to keep track whether any error occurred. */
156 static int any_error;
159 /* Object to keep macro definitions. */
162 struct macro_s *next;
163 char *value; /* Malloced value. */
166 typedef struct macro_s *macro_t;
168 /* List of all defined macros. */
169 static macro_t macrolist;
171 /* List of variables set by @set. */
172 static macro_t variablelist;
174 /* List of global macro names. The value part is not used. */
175 static macro_t predefinedmacrolist;
177 /* Object to keep track of @isset and @ifclear. */
180 int manverb; /* "manverb" needs special treatment. */
181 int isset; /* This is an @isset condition. */
182 char name[1]; /* Name of the condition macro. */
184 typedef struct condition_s *condition_t;
186 /* The stack used to evaluate conditions. And the current states. */
187 static condition_t condition_stack[MAX_CONDITION_NESTING];
188 static int condition_stack_idx;
189 static int cond_is_active; /* State of ifset/ifclear */
190 static int cond_in_verbatim; /* State of "manverb". */
193 /* Object to store one line of content. */
196 struct line_buffer_s *next;
197 int verbatim; /* True if LINE contains verbatim data. The default
198 is Texinfo source. */
201 typedef struct line_buffer_s *line_buffer_t;
204 /* Object to collect the data of a section. */
205 struct section_buffer_s
207 char *name; /* Malloced name of the section. This may be
208 NULL to indicate this slot is not used. */
209 line_buffer_t lines; /* Linked list with the lines of the section. */
210 line_buffer_t *lines_tail; /* Helper for faster appending to the
212 line_buffer_t last_line; /* Points to the last line appended. */
214 typedef struct section_buffer_s *section_buffer_t;
216 /* Variable to keep info about the current page together. */
219 /* Filename of the current page or NULL if no page is active. Malloced. */
222 /* Number of allocated elements in SECTIONS below. */
224 /* Array with the data of the sections. */
225 section_buffer_t sections;
230 /* The list of standard section names. COMMANDS and ASSUAN are GnuPG
232 static const char * const standard_sections[] =
233 { "NAME", "SYNOPSIS", "DESCRIPTION",
234 "RETURN VALUE", "EXIT STATUS", "ERROR HANDLING", "ERRORS",
235 "COMMANDS", "OPTIONS", "USAGE", "EXAMPLES", "FILES",
236 "ENVIRONMENT", "DIAGNOSTICS", "SECURITY", "CONFORMING TO",
237 "ASSUAN", "NOTES", "BUGS", "AUTHOR", "SEE ALSO", NULL };
240 /*-- Local prototypes. --*/
241 static void proc_texi_buffer (FILE *fp, const char *line, size_t len,
242 int *table_level, int *eol_action);
244 static void die (const char *format, ...) ATTR_NR_PRINTF(1,2);
245 static void err (const char *format, ...) ATTR_PRINTF(1,2);
246 static void inf (const char *format, ...) ATTR_PRINTF(1,2);
247 static void *xmalloc (size_t n) ATTR_MALLOC;
248 static void *xcalloc (size_t n, size_t m) ATTR_MALLOC;
254 /* Print diagnostic message and exit with failure. */
256 die (const char *format, ...)
261 fprintf (stderr, "%s: ", PGM);
263 va_start (arg_ptr, format);
264 vfprintf (stderr, format, arg_ptr);
272 /* Print diagnostic message. */
274 err (const char *format, ...)
279 if (strncmp (format, "%s:%d:", 6))
280 fprintf (stderr, "%s: ", PGM);
282 va_start (arg_ptr, format);
283 vfprintf (stderr, format, arg_ptr);
289 /* Print diagnostic message. */
291 inf (const char *format, ...)
296 fprintf (stderr, "%s: ", PGM);
298 va_start (arg_ptr, format);
299 vfprintf (stderr, format, arg_ptr);
308 void *p = malloc (n);
310 die ("out of core: %s", strerror (errno));
315 xcalloc (size_t n, size_t m)
317 void *p = calloc (n, m);
319 die ("out of core: %s", strerror (errno));
324 xrealloc (void *old, size_t n)
326 void *p = realloc (old, n);
328 die ("out of core: %s", strerror (errno));
333 xstrdup (const char *string)
335 void *p = malloc (strlen (string)+1);
337 die ("out of core: %s", strerror (errno));
343 /* Uppercase the ascii characters in STRING. */
345 ascii_strupr (char *string)
349 for (p = string; *p; p++)
356 /* Return the current date as an ISO string. */
360 static char buffer[36];
364 if (opt_date && *opt_date)
365 atime = strtoul (opt_date, NULL, 10);
369 strcpy (buffer, "????" "-??" "-??");
372 tp = gmtime (&atime);
373 sprintf (buffer,"%04d-%02d-%02d",
374 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
380 /* Add NAME to the list of predefined macros which are global for all
383 add_predefined_macro (const char *name)
387 for (m=predefinedmacrolist; m; m = m->next)
388 if (!strcmp (m->name, name))
392 m = xcalloc (1, sizeof *m + strlen (name));
393 strcpy (m->name, name);
394 m->next = predefinedmacrolist;
395 predefinedmacrolist = m;
400 /* Create or update a macro with name MACRONAME and set its values TO
401 MACROVALUE. Note that ownership of the macro value is transferred
404 set_macro (const char *macroname, char *macrovalue)
408 for (m=macrolist; m; m = m->next)
409 if (!strcmp (m->name, macroname))
415 m = xcalloc (1, sizeof *m + strlen (macroname));
416 strcpy (m->name, macroname);
420 m->value = macrovalue;
425 /* Create or update a variable with name and value given in NAMEANDVALUE. */
427 set_variable (char *nameandvalue)
433 for (p = nameandvalue; *p && *p != ' ' && *p != '\t'; p++)
440 while (*p == ' ' || *p == '\t')
445 for (m=variablelist; m; m = m->next)
446 if (!strcmp (m->name, nameandvalue))
452 m = xcalloc (1, sizeof *m + strlen (nameandvalue));
453 strcpy (m->name, nameandvalue);
454 m->next = variablelist;
457 m->value = xstrdup (value);
461 /* Return true if the macro or variable NAME is set, i.e. not the
462 empty string and not evaluating to 0. */
464 macro_set_p (const char *name)
468 for (m = macrolist; m ; m = m->next)
469 if (!strcmp (m->name, name))
472 for (m = variablelist; m ; m = m->next)
473 if (!strcmp (m->name, name))
475 if (!m || !m->value || !*m->value)
477 if ((*m->value & 0x80) || !isdigit (*m->value))
478 return 1; /* Not a digit but some other string. */
479 return !!atoi (m->value);
483 /* Evaluate the current conditions. */
485 evaluate_conditions (const char *fname, int lnr)
492 /* for (i=0; i < condition_stack_idx; i++) */
493 /* inf ("%s:%d: stack[%d] %s %s %c", */
494 /* fname, lnr, i, condition_stack[i]->isset? "set":"clr", */
495 /* condition_stack[i]->name, */
496 /* (macro_set_p (condition_stack[i]->name) */
497 /* ^ !condition_stack[i]->isset)? 't':'f'); */
500 cond_in_verbatim = 0;
501 if (condition_stack_idx)
503 for (i=0; i < condition_stack_idx; i++)
505 if (condition_stack[i]->manverb)
506 cond_in_verbatim = (macro_set_p (condition_stack[i]->name)
507 ^ !condition_stack[i]->isset);
508 else if (!(macro_set_p (condition_stack[i]->name)
509 ^ !condition_stack[i]->isset))
517 /* inf ("%s:%d: active=%d verbatim=%d", */
518 /* fname, lnr, cond_is_active, cond_in_verbatim); */
522 /* Push a condition with condition macro NAME onto the stack. If
523 ISSET is true, a @isset condition is pushed. */
525 push_condition (const char *name, int isset, const char *fname, int lnr)
530 if (condition_stack_idx >= MAX_CONDITION_NESTING)
532 err ("%s:%d: condition nested too deep", fname, lnr);
536 if (!strcmp (name, "manverb"))
540 err ("%s:%d: using \"@ifclear manverb\" is not allowed", fname, lnr);
546 cond = xcalloc (1, sizeof *cond + strlen (name));
547 cond->manverb = manverb;
549 strcpy (cond->name, name);
551 condition_stack[condition_stack_idx++] = cond;
552 evaluate_conditions (fname, lnr);
556 /* Remove the last condition from the stack. ISSET is used for error
559 pop_condition (int isset, const char *fname, int lnr)
561 if (!condition_stack_idx)
563 err ("%s:%d: unbalanced \"@end %s\"",
564 fname, lnr, isset?"isset":"isclear");
567 condition_stack_idx--;
568 free (condition_stack[condition_stack_idx]);
569 condition_stack[condition_stack_idx] = NULL;
570 evaluate_conditions (fname, lnr);
575 /* Return a section buffer for the section NAME. Allocate a new buffer
576 if this is a new section. Keep track of the sections in THEPAGE.
577 This function may reallocate the section array in THEPAGE. */
578 static section_buffer_t
579 get_section_buffer (const char *name)
582 section_buffer_t sect;
584 /* If there is no section we put everything into the required NAME
585 section. Given that this is the first one listed it is likely
586 that error are easily visible. */
590 for (i=0; i < thepage.n_sections; i++)
592 sect = thepage.sections + i;
593 if (sect->name && !strcmp (name, sect->name))
596 for (i=0; i < thepage.n_sections; i++)
597 if (!thepage.sections[i].name)
599 if (thepage.n_sections && i < thepage.n_sections)
600 sect = thepage.sections + i;
603 /* We need to allocate or reallocate the section array. */
604 size_t old_n = thepage.n_sections;
608 thepage.sections = xcalloc (new_n, sizeof *thepage.sections);
611 thepage.sections = xrealloc (thepage.sections,
613 * sizeof *thepage.sections));
614 memset (thepage.sections + old_n, 0,
615 new_n * sizeof *thepage.sections);
617 thepage.n_sections += new_n;
619 /* Setup the tail pointers. */
620 for (i=old_n; i < thepage.n_sections; i++)
622 sect = thepage.sections + i;
623 sect->lines_tail = §->lines;
625 sect = thepage.sections + old_n;
628 /* Store the name. */
629 assert (!sect->name);
630 sect->name = xstrdup (name);
636 /* Add the content of LINE to the section named SECTNAME. */
638 add_content (const char *sectname, char *line, int verbatim)
640 section_buffer_t sect;
643 sect = get_section_buffer (sectname);
644 if (sect->last_line && !sect->last_line->verbatim == !verbatim)
646 /* Lets append that line to the last one. We do this to keep
647 all lines of the same kind (i.e.verbatim or not) together in
651 lb = sect->last_line;
652 n1 = strlen (lb->line);
653 n = n1 + 1 + strlen (line) + 1;
654 lb->line = xrealloc (lb->line, n);
655 strcpy (lb->line+n1, "\n");
656 strcpy (lb->line+n1+1, line);
660 lb = xcalloc (1, sizeof *lb);
661 lb->verbatim = verbatim;
662 lb->line = xstrdup (line);
663 sect->last_line = lb;
664 *sect->lines_tail = lb;
665 sect->lines_tail = &lb->next;
670 /* Prepare for a new man page using the filename NAME. */
672 start_page (char *name)
675 inf ("starting page '%s'", name);
676 assert (!thepage.name);
677 thepage.name = xstrdup (name);
678 thepage.n_sections = 0;
682 /* Write the .TH entry of the current page. Return -1 if there is a
683 problem with the page. */
689 fputs (".\\\" Created from Texinfo source by yat2m " VERSION "\n", fp);
691 name = ascii_strupr (xstrdup (thepage.name));
692 p = strrchr (name, '.');
695 err ("no section name in man page '%s'", thepage.name);
700 fprintf (fp, ".TH %s %s %s \"%s\" \"%s\"\n",
701 name, p, isodatestring (), opt_release, opt_source);
707 /* Process the texinfo command COMMAND (without the leading @) and
708 write output if needed to FP. REST is the remainer of the line
709 which should either point to an opening brace or to a white space.
710 The function returns the number of characters already processed
711 from REST. LEN is the usable length of REST. TABLE_LEVEL is used to
712 control the indentation of tables. */
714 proc_texi_cmd (FILE *fp, const char *command, const char *rest, size_t len,
715 int *table_level, int *eol_action)
718 const char *name; /* Name of the command. */
719 int what; /* What to do with this command. */
720 const char *lead_in; /* String to print with a opening brace. */
721 const char *lead_out;/* String to print with the closing brace. */
723 { "command", 0, "\\fB", "\\fR" },
724 { "code", 0, "\\fB", "\\fR" },
725 { "url", 0, "\\fB", "\\fR" },
726 { "sc", 0, "\\fB", "\\fR" },
727 { "var", 0, "\\fI", "\\fR" },
728 { "samp", 0, "\\(aq", "\\(aq" },
729 { "file", 0, "\\(oq\\fI","\\fR\\(cq" },
730 { "env", 0, "\\(oq\\fI","\\fR\\(cq" },
733 { "option", 0, "\\fB", "\\fR" },
734 { "example", 1, ".RS 2\n.nf\n" },
735 { "smallexample", 1, ".RS 2\n.nf\n" },
739 { "ref", 0, "[", "]" },
740 { "xref", 0, "See: [", "]" },
741 { "pxref", 0, "see: [", "]" },
742 { "uref", 0, "(\\fB", "\\fR)" },
743 { "footnote",0, " ([", "])" },
744 { "emph", 0, "\\fI", "\\fR" },
754 { "subsection", 6, "\n.SS " },
756 { "item", 2, ".TP\n.B " },
757 { "itemx", 2, ".TQ\n.B " },
760 { "bullet", 0, "* " },
764 { "quotation",1, ".RS\n\\fB" },
771 const char *lead_out = NULL;
774 for (i=0; cmdtbl[i].name && strcmp (cmdtbl[i].name, command); i++)
778 s = cmdtbl[i].lead_in;
781 lead_out = cmdtbl[i].lead_out;
782 switch (cmdtbl[i].what)
784 case 1: /* Throw away the entire line. */
785 s = memchr (rest, '\n', len);
786 return s? (s-rest)+1 : len;
787 case 2: /* Handle @item. */
789 case 3: /* Handle table. */
790 if (++(*table_level) > 1)
792 /* Now throw away the entire line. */
793 s = memchr (rest, '\n', len);
794 return s? (s-rest)+1 : len;
796 case 4: /* Handle end. */
797 for (s=rest, n=len; n && (*s == ' ' || *s == '\t'); s++, n--)
799 if (n >= 5 && !memcmp (s, "table", 5)
800 && (!n || s[5] == ' ' || s[5] == '\t' || s[5] == '\n'))
802 if ((*table_level)-- > 1)
807 else if (n >= 7 && !memcmp (s, "example", 7)
808 && (!n || s[7] == ' ' || s[7] == '\t' || s[7] == '\n'))
810 fputs (".fi\n.RE\n", fp);
812 else if (n >= 12 && !memcmp (s, "smallexample", 12)
813 && (!n || s[12] == ' ' || s[12] == '\t' || s[12] == '\n'))
815 fputs (".fi\n.RE\n", fp);
817 else if (n >= 9 && !memcmp (s, "quotation", 9)
818 && (!n || s[9] == ' ' || s[9] == '\t' || s[9] == '\n'))
820 fputs ("\\fR\n.RE\n", fp);
822 /* Now throw away the entire line. */
823 s = memchr (rest, '\n', len);
824 return s? (s-rest)+1 : len;
825 case 5: /* Handle special comments. */
826 for (s=rest, n=len; n && (*s == ' ' || *s == '\t'); s++, n--)
828 if (n >= 4 && !memcmp (s, "man:", 4))
830 for (s+=4, n-=4; n && *s != '\n'; n--, s++)
834 /* Now throw away the entire line. */
835 s = memchr (rest, '\n', len);
836 return s? (s-rest)+1 : len;
847 err ("opening brace for command '%s' missing", command);
852 /* Find closing brace. */
853 for (s=rest+1, n=1; *s && n < len; s++, n++)
858 err ("closing brace for command '%s' not found", command);
863 size_t rlen = s - (rest + 1);
866 for (m = variablelist; m; m = m->next)
868 if (strlen (m->name) == rlen
869 && !strncmp (m->name, rest+1, rlen))
873 fputs (m->value, fp);
875 inf ("texinfo variable '%.*s' is not set",
888 for (m = macrolist; m ; m = m->next)
889 if (!strcmp (m->name, command))
893 proc_texi_buffer (fp, m->value, strlen (m->value),
894 table_level, eol_action);
895 ignore_args = 1; /* Parameterized macros are not yet supported. */
898 inf ("texinfo command '%s' not supported (%.*s)", command,
899 (int)((s = memchr (rest, '\n', len)), (s? (s-rest) : len)), rest);
904 /* Find matching closing brace. */
905 for (s=rest+1, n=1, i=1; i && *s && n < len; s++, n++)
912 err ("closing brace for command '%s' not found", command);
915 if (n > 2 && !ignore_args)
916 proc_texi_buffer (fp, rest+1, n-2, table_level, eol_action);
922 fputs (lead_out, fp);
929 /* Process the string LINE with LEN bytes of Texinfo content. */
931 proc_texi_buffer (FILE *fp, const char *line, size_t len,
932 int *table_level, int *eol_action)
940 for (s=line; *s && len; s++, len--)
948 case '@': case '{': case '}':
949 putc (*s, fp); in_cmd = 0;
951 case ':': /* Not ending a sentence flag. */
954 case '.': case '!': case '?': /* Ending a sentence. */
955 putc (*s, fp); in_cmd = 0;
957 case ' ': case '\t': case '\n': /* Non collapsing spaces. */
958 putc (*s, fp); in_cmd = 0;
962 cmdbuf[cmdidx++] = *s;
967 else if (*s == '{' || *s == ' ' || *s == '\t' || *s == '\n')
970 n = proc_texi_cmd (fp, cmdbuf, s, len, table_level, eol_action);
976 else if (cmdidx < sizeof cmdbuf -1)
977 cmdbuf[cmdidx++] = *s;
980 err ("texinfo command too long - ignored");
990 case 1: /* Create a dummy paragraph. */
991 fputs ("\n\\ \n", fp);
1007 n = proc_texi_cmd (fp, cmdbuf, s, len, table_level, eol_action);
1011 /* in_cmd = 0; -- doc only */
1016 /* Do something with the Texinfo line LINE. */
1018 parse_texi_line (FILE *fp, const char *line, int *table_level)
1022 /* A quick test whether there are any texinfo commands. */
1023 if (!strchr (line, '@'))
1029 proc_texi_buffer (fp, line, strlen (line), table_level, &eol_action);
1034 /* Write all the lines LINES to FP. */
1036 write_content (FILE *fp, line_buffer_t lines)
1039 int table_level = 0;
1041 for (line = lines; line; line = line->next)
1045 fputs (line->line, fp);
1050 /* fputs ("TEXI---", fp); */
1051 /* fputs (line->line, fp); */
1052 /* fputs ("---\n", fp); */
1053 parse_texi_line (fp, line->line, &table_level);
1061 is_standard_section (const char *name)
1066 for (i=0; (s=standard_sections[i]); i++)
1067 if (!strcmp (s, name))
1073 /* Finish a page; that is sort the data and write it out to the file. */
1078 section_buffer_t sect = NULL;
1084 return; /* No page active. */
1087 inf ("finishing page '%s'", thepage.name);
1091 if (!strcmp (opt_select, thepage.name))
1093 inf ("selected '%s'", thepage.name );
1098 fp = fopen ( "/dev/null", "w" );
1100 die ("failed to open /dev/null: %s\n", strerror (errno));
1105 inf ("writing '%s'", thepage.name );
1106 fp = fopen ( thepage.name, "w" );
1108 die ("failed to create '%s': %s\n", thepage.name, strerror (errno));
1116 for (idx=0; (s=standard_sections[idx]); idx++)
1118 for (i=0; i < thepage.n_sections; i++)
1120 sect = thepage.sections + i;
1121 if (sect->name && !strcmp (s, sect->name))
1124 if (i == thepage.n_sections)
1129 fprintf (fp, ".SH %s\n", sect->name);
1130 write_content (fp, sect->lines);
1131 /* Now continue with all non standard sections directly
1132 following this one. */
1133 for (i++; i < thepage.n_sections; i++)
1135 sect = thepage.sections + i;
1136 if (sect->name && is_standard_section (sect->name))
1140 fprintf (fp, ".SH %s\n", sect->name);
1141 write_content (fp, sect->lines);
1152 free (thepage.name);
1153 thepage.name = NULL;
1154 /* FIXME: Cleanup the content. */
1160 /* Parse one Texinfo file and create manpages according to the
1161 embedded instructions. */
1163 parse_file (const char *fname, FILE *fp, char **section_name, int in_pause)
1167 /* Fixme: The following state variables don't carry over to include
1169 int skip_to_end = 0; /* Used to skip over menu entries. */
1170 int skip_sect_line = 0; /* Skip after @mansect. */
1171 int item_indent = 0; /* How far is the current @item indented. */
1173 /* Helper to define a macro. */
1174 char *macroname = NULL;
1175 char *macrovalue = NULL;
1176 size_t macrovaluesize = 0;
1177 size_t macrovalueused = 0;
1179 line = xmalloc (LINESIZE);
1180 while (fgets (line, LINESIZE, fp))
1182 size_t n = strlen (line);
1187 if (!n || line[n-1] != '\n')
1189 err ("%s:%d: trailing linefeed missing, line too long or "
1190 "embedded Nul character", fname, lnr);
1195 /* Kludge to allow indentation of tables. */
1196 for (p=line; *p == ' ' || *p == '\t'; p++)
1200 if (*p == '@' && !strncmp (p+1, "item", 4))
1201 item_indent = p - line; /* Set a new indent level. */
1202 else if (p - line < item_indent)
1203 item_indent = 0; /* Switch off indention. */
1207 memmove (line, line+item_indent, n - item_indent + 1);
1215 for (p=line+1, n=1; *p && *p != ' ' && *p != '\t'; p++)
1217 while (*p == ' ' || *p == '\t')
1223 /* Take action on macro. */
1226 if (n == 4 && !memcmp (line, "@end", 4)
1227 && (line[4]==' '||line[4]=='\t'||!line[4])
1228 && !strncmp (p, "macro", 5)
1229 && (p[5]==' '||p[5]=='\t'||!p[5]))
1232 macrovalue[--macrovalueused] = 0; /* Kill the last LF. */
1233 macrovalue[macrovalueused] = 0; /* Terminate macro. */
1234 macrovalue = xrealloc (macrovalue, macrovalueused+1);
1236 set_macro (macroname, macrovalue);
1243 if (macrovalueused + strlen (line) + 2 >= macrovaluesize)
1245 macrovaluesize += strlen (line) + 256;
1246 macrovalue = xrealloc (macrovalue, macrovaluesize);
1248 strcpy (macrovalue+macrovalueused, line);
1249 macrovalueused += strlen (line);
1250 macrovalue[macrovalueused++] = '\n';
1256 if (n >= 5 && !memcmp (line, "@node", 5)
1257 && (line[5]==' '||line[5]=='\t'||!line[5]))
1259 /* Completey ignore @node lines. */
1267 if (!strncmp (line, "@section", 8)
1268 || !strncmp (line, "@subsection", 11)
1269 || !strncmp (line, "@chapheading", 12))
1273 /* We only parse lines we need and ignore the rest. There are a
1274 few macros used to control this as well as one @ifset
1275 command. Parts we know about are saved away into containers
1276 separate for each section. */
1278 /* First process ifset/ifclear commands. */
1281 if (n == 6 && !memcmp (line, "@ifset", 6)
1282 && (line[6]==' '||line[6]=='\t'))
1284 for (p=line+7; *p == ' ' || *p == '\t'; p++)
1288 err ("%s:%d: name missing after \"@ifset\"", fname, lnr);
1291 for (pend=p; *pend && *pend != ' ' && *pend != '\t'; pend++)
1293 *pend = 0; /* Ignore rest of the line. */
1294 push_condition (p, 1, fname, lnr);
1297 else if (n == 8 && !memcmp (line, "@ifclear", 8)
1298 && (line[8]==' '||line[8]=='\t'))
1300 for (p=line+9; *p == ' ' || *p == '\t'; p++)
1304 err ("%s:%d: name missing after \"@ifsclear\"", fname, lnr);
1307 for (pend=p; *pend && *pend != ' ' && *pend != '\t'; pend++)
1309 *pend = 0; /* Ignore rest of the line. */
1310 push_condition (p, 0, fname, lnr);
1313 else if (n == 4 && !memcmp (line, "@end", 4)
1314 && (line[4]==' '||line[4]=='\t')
1315 && !strncmp (p, "ifset", 5)
1316 && (p[5]==' '||p[5]=='\t'||!p[5]))
1318 pop_condition (1, fname, lnr);
1321 else if (n == 4 && !memcmp (line, "@end", 4)
1322 && (line[4]==' '||line[4]=='\t')
1323 && !strncmp (p, "ifclear", 7)
1324 && (p[7]==' '||p[7]=='\t'||!p[7]))
1326 pop_condition (0, fname, lnr);
1331 /* Take action on ifset/ifclear. */
1332 if (!cond_is_active)
1335 /* Process commands. */
1339 && n == 4 && !memcmp (line, "@end", 4)
1340 && (line[4]==' '||line[4]=='\t'||!line[4]))
1344 else if (cond_in_verbatim)
1348 else if (n == 6 && !memcmp (line, "@macro", 6))
1350 macroname = xstrdup (p);
1351 macrovalue = xmalloc ((macrovaluesize = 1024));
1354 else if (n == 4 && !memcmp (line, "@set", 4))
1358 else if (n == 8 && !memcmp (line, "@manpage", 8))
1360 free (*section_name);
1361 *section_name = NULL;
1366 else if (n == 8 && !memcmp (line, "@mansect", 8))
1369 err ("%s:%d: section outside of a man page", fname, lnr);
1372 free (*section_name);
1373 *section_name = ascii_strupr (xstrdup (p));
1378 else if (n == 9 && !memcmp (line, "@manpause", 9))
1381 err ("%s:%d: pausing outside of a man section", fname, lnr);
1383 err ("%s:%d: already pausing", fname, lnr);
1387 else if (n == 8 && !memcmp (line, "@mancont", 8))
1390 err ("%s:%d: continue outside of a man section", fname, lnr);
1392 err ("%s:%d: continue while not pausing", fname, lnr);
1396 else if (n == 5 && !memcmp (line, "@menu", 5)
1397 && (line[5]==' '||line[5]=='\t'||!line[5]))
1401 else if (n == 8 && !memcmp (line, "@include", 8)
1402 && (line[8]==' '||line[8]=='\t'||!line[8]))
1404 char *incname = xstrdup (p);
1405 FILE *incfp = fopen (incname, "r");
1407 if (!incfp && opt_include && *opt_include && *p != '/')
1410 incname = xmalloc (strlen (opt_include) + 1
1412 strcpy (incname, opt_include);
1413 if ( incname[strlen (incname)-1] != '/' )
1414 strcat (incname, "/");
1415 strcat (incname, p);
1416 incfp = fopen (incname, "r");
1420 err ("can't open include file '%s': %s",
1421 incname, strerror (errno));
1424 parse_file (incname, incfp, section_name, in_pause);
1429 else if (n == 4 && !memcmp (line, "@bye", 4)
1430 && (line[4]==' '||line[4]=='\t'||!line[4]))
1434 else if (!skip_to_end)
1437 else if (!skip_to_end)
1440 if (got_line && cond_in_verbatim)
1441 add_content (*section_name, line, 1);
1442 else if (got_line && thepage.name && *section_name && !in_pause)
1443 add_content (*section_name, line, 0);
1447 err ("%s:%d: read error: %s", fname, lnr, strerror (errno));
1455 top_parse_file (const char *fname, FILE *fp)
1457 char *section_name = NULL; /* Name of the current section or NULL
1458 if not in a section. */
1463 macro_t next = macrolist->next;
1464 free (macrolist->value);
1468 while (variablelist)
1470 macro_t next = variablelist->next;
1471 free (variablelist->value);
1472 free (variablelist);
1473 variablelist = next;
1475 for (m=predefinedmacrolist; m; m = m->next)
1476 set_macro (m->name, xstrdup ("1"));
1478 cond_in_verbatim = 0;
1480 parse_file (fname, fp, §ion_name, 0);
1481 free (section_name);
1487 main (int argc, char **argv)
1495 /* Define default macros. The trick is that these macros are not
1496 defined when using the actual texinfo renderer. */
1497 add_predefined_macro ("isman");
1498 add_predefined_macro ("manverb");
1500 /* Option parsing. */
1505 while (argc && last_argc != argc )
1508 if (!strcmp (*argv, "--"))
1513 else if (!strcmp (*argv, "--help"))
1516 "Usage: " PGM " [OPTION] [FILE]\n"
1517 "Extract man pages from a Texinfo source.\n\n"
1518 " --source NAME use NAME as source field\n"
1519 " --release STRING use STRING as the release field\n"
1520 " --date EPOCH use EPOCH as publication date\n"
1521 " --store write output using @manpage name\n"
1522 " --select NAME only output pages with @manpage NAME\n"
1523 " --verbose enable extra informational output\n"
1524 " --debug enable additional debug output\n"
1525 " --help display this help and exit\n"
1526 " -I DIR also search in include DIR\n"
1527 " -D gpgone the only usable define\n\n"
1528 "With no FILE, or when FILE is -, read standard input.\n\n"
1529 "Report bugs to <https://bugs.gnupg.org>.");
1532 else if (!strcmp (*argv, "--version"))
1534 puts (PGM " " VERSION "\n"
1535 "Copyright (C) 2005, 2017 g10 Code GmbH\n"
1536 "This program comes with ABSOLUTELY NO WARRANTY.\n"
1537 "This is free software, and you are welcome to redistribute it\n"
1538 "under certain conditions. See the file COPYING for details.");
1541 else if (!strcmp (*argv, "--verbose"))
1546 else if (!strcmp (*argv, "--quiet"))
1551 else if (!strcmp (*argv, "--debug"))
1553 verbose = debug = 1;
1556 else if (!strcmp (*argv, "--source"))
1565 else if (!strcmp (*argv, "--release"))
1570 opt_release = *argv;
1574 else if (!strcmp (*argv, "--date"))
1583 else if (!strcmp (*argv, "--store"))
1588 else if (!strcmp (*argv, "--select"))
1593 opt_select = strrchr (*argv, '/');
1601 else if (!strcmp (*argv, "-I"))
1606 opt_include = *argv;
1610 else if (!strcmp (*argv, "-D"))
1615 add_predefined_macro (*argv);
1622 die ("usage: " PGM " [OPTION] [FILE] (try --help for more information)\n");
1624 /* Take care of supplied timestamp for reproducible builds. See
1625 * https://reproducible-builds.org/specs/source-date-epoch/ */
1626 if (!opt_date && (s = getenv ("SOURCE_DATE_EPOCH")) && *s)
1629 /* Start processing. */
1630 if (argc && strcmp (*argv, "-"))
1632 FILE *fp = fopen (*argv, "rb");
1634 die ("%s:0: can't open file: %s", *argv, strerror (errno));
1635 top_parse_file (*argv, fp);
1639 top_parse_file ("-", stdin);
1647 compile-command: "gcc -Wall -g -Wall -o yat2m yat2m.c"