1 /* yat2m.c - Yet Another Texi 2 Man converter
2 * Copyright (C) 2005, 2013 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 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.
104 #define VERSION "1.0"
106 /* The maximum length of a line including the linefeed and one extra
108 #define LINESIZE 1024
110 /* Number of allowed condition nestings. */
111 #define MAX_CONDITION_NESTING 10
117 static const char *opt_source;
118 static const char *opt_release;
119 static const char *opt_select;
120 static const char *opt_include;
121 static int opt_store;
123 /* Flag to keep track whether any error occurred. */
124 static int any_error;
127 /* Object to keep macro definitions. */
130 struct macro_s *next;
131 char *value; /* Malloced value. */
134 typedef struct macro_s *macro_t;
136 /* List of all defined macros. */
137 static macro_t macrolist;
139 /* List of global macro names. The value part is not used. */
140 static macro_t predefinedmacrolist;
142 /* Object to keep track of @isset and @ifclear. */
145 int manverb; /* "manverb" needs special treatment. */
146 int isset; /* This is an @isset condition. */
147 char name[1]; /* Name of the condition macro. */
149 typedef struct condition_s *condition_t;
151 /* The stack used to evaluate conditions. And the current states. */
152 static condition_t condition_stack[MAX_CONDITION_NESTING];
153 static int condition_stack_idx;
154 static int cond_is_active; /* State of ifset/ifclear */
155 static int cond_in_verbatim; /* State of "manverb". */
158 /* Object to store one line of content. */
161 struct line_buffer_s *next;
162 int verbatim; /* True if LINE contains verbatim data. The default
163 is Texinfo source. */
166 typedef struct line_buffer_s *line_buffer_t;
169 /* Object to collect the data of a section. */
170 struct section_buffer_s
172 char *name; /* Malloced name of the section. This may be
173 NULL to indicate this slot is not used. */
174 line_buffer_t lines; /* Linked list with the lines of the section. */
175 line_buffer_t *lines_tail; /* Helper for faster appending to the
177 line_buffer_t last_line; /* Points to the last line appended. */
179 typedef struct section_buffer_s *section_buffer_t;
181 /* Variable to keep info about the current page together. */
184 /* Filename of the current page or NULL if no page is active. Malloced. */
187 /* Number of allocated elements in SECTIONS below. */
189 /* Array with the data of the sections. */
190 section_buffer_t sections;
195 /* The list of standard section names. COMMANDS and ASSUAN are GnuPG
197 static const char * const standard_sections[] =
198 { "NAME", "SYNOPSIS", "DESCRIPTION",
199 "RETURN VALUE", "EXIT STATUS", "ERROR HANDLING", "ERRORS",
200 "COMMANDS", "OPTIONS", "USAGE", "EXAMPLES", "FILES",
201 "ENVIRONMENT", "DIAGNOSTICS", "SECURITY", "CONFORMING TO",
202 "ASSUAN", "NOTES", "BUGS", "AUTHOR", "SEE ALSO", NULL };
205 /*-- Local prototypes. --*/
206 static void proc_texi_buffer (FILE *fp, const char *line, size_t len,
207 int *table_level, int *eol_action);
211 /* Print diagnostic message and exit with failure. */
213 die (const char *format, ...)
218 fprintf (stderr, "%s: ", PGM);
220 va_start (arg_ptr, format);
221 vfprintf (stderr, format, arg_ptr);
229 /* Print diagnostic message. */
231 err (const char *format, ...)
236 if (strncmp (format, "%s:%d:", 6))
237 fprintf (stderr, "%s: ", PGM);
239 va_start (arg_ptr, format);
240 vfprintf (stderr, format, arg_ptr);
246 /* Print diagnostic message. */
248 inf (const char *format, ...)
253 fprintf (stderr, "%s: ", PGM);
255 va_start (arg_ptr, format);
256 vfprintf (stderr, format, arg_ptr);
265 void *p = malloc (n);
267 die ("out of core: %s", strerror (errno));
272 xcalloc (size_t n, size_t m)
274 void *p = calloc (n, m);
276 die ("out of core: %s", strerror (errno));
281 xrealloc (void *old, size_t n)
283 void *p = realloc (old, n);
285 die ("out of core: %s", strerror (errno));
290 xstrdup (const char *string)
292 void *p = malloc (strlen (string)+1);
294 die ("out of core: %s", strerror (errno));
300 /* Uppercase the ascii characters in STRING. */
302 ascii_strupr (char *string)
306 for (p = string; *p; p++)
313 /* Return the current date as an ISO string. */
317 static char buffer[11+5];
319 time_t atime = time (NULL);
322 strcpy (buffer, "????" "-??" "-??");
325 tp = gmtime (&atime);
326 sprintf (buffer,"%04d-%02d-%02d",
327 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
333 /* Add NAME to the list of predefined macros which are global for all
336 add_predefined_macro (const char *name)
340 for (m=predefinedmacrolist; m; m = m->next)
341 if (!strcmp (m->name, name))
345 m = xcalloc (1, sizeof *m + strlen (name));
346 strcpy (m->name, name);
347 m->next = predefinedmacrolist;
348 predefinedmacrolist = m;
353 /* Create or update a macro with name MACRONAME and set its values TO
354 MACROVALUE. Note that ownership of the macro value is transferred
357 set_macro (const char *macroname, char *macrovalue)
361 for (m=macrolist; m; m = m->next)
362 if (!strcmp (m->name, macroname))
368 m = xcalloc (1, sizeof *m + strlen (macroname));
369 strcpy (m->name, macroname);
373 m->value = macrovalue;
378 /* Return true if the macro NAME is set, i.e. not the empty string and
379 not evaluating to 0. */
381 macro_set_p (const char *name)
385 for (m = macrolist; m ; m = m->next)
386 if (!strcmp (m->name, name))
388 if (!m || !m->value || !*m->value)
390 if ((*m->value & 0x80) || !isdigit (*m->value))
391 return 1; /* Not a digit but some other string. */
392 return !!atoi (m->value);
396 /* Evaluate the current conditions. */
398 evaluate_conditions (const char *fname, int lnr)
402 /* for (i=0; i < condition_stack_idx; i++) */
403 /* inf ("%s:%d: stack[%d] %s %s %c", */
404 /* fname, lnr, i, condition_stack[i]->isset? "set":"clr", */
405 /* condition_stack[i]->name, */
406 /* (macro_set_p (condition_stack[i]->name) */
407 /* ^ !condition_stack[i]->isset)? 't':'f'); */
410 cond_in_verbatim = 0;
411 if (condition_stack_idx)
413 for (i=0; i < condition_stack_idx; i++)
415 if (condition_stack[i]->manverb)
416 cond_in_verbatim = (macro_set_p (condition_stack[i]->name)
417 ^ !condition_stack[i]->isset);
418 else if (!(macro_set_p (condition_stack[i]->name)
419 ^ !condition_stack[i]->isset))
427 /* inf ("%s:%d: active=%d verbatim=%d", */
428 /* fname, lnr, cond_is_active, cond_in_verbatim); */
432 /* Push a condition with condition macro NAME onto the stack. If
433 ISSET is true, a @isset condition is pushed. */
435 push_condition (const char *name, int isset, const char *fname, int lnr)
440 if (condition_stack_idx >= MAX_CONDITION_NESTING)
442 err ("%s:%d: condition nested too deep", fname, lnr);
446 if (!strcmp (name, "manverb"))
450 err ("%s:%d: using \"@ifclear manverb\" is not allowed", fname, lnr);
456 cond = xcalloc (1, sizeof *cond + strlen (name));
457 cond->manverb = manverb;
459 strcpy (cond->name, name);
461 condition_stack[condition_stack_idx++] = cond;
462 evaluate_conditions (fname, lnr);
466 /* Remove the last condition from the stack. ISSET is used for error
469 pop_condition (int isset, const char *fname, int lnr)
471 if (!condition_stack_idx)
473 err ("%s:%d: unbalanced \"@end %s\"",
474 fname, lnr, isset?"isset":"isclear");
477 condition_stack_idx--;
478 free (condition_stack[condition_stack_idx]);
479 condition_stack[condition_stack_idx] = NULL;
480 evaluate_conditions (fname, lnr);
485 /* Return a section buffer for the section NAME. Allocate a new buffer
486 if this is a new section. Keep track of the sections in THEPAGE.
487 This function may reallocate the section array in THEPAGE. */
488 static section_buffer_t
489 get_section_buffer (const char *name)
492 section_buffer_t sect;
494 /* If there is no section we put everything into the required NAME
495 section. Given that this is the first one listed it is likely
496 that error are easily visible. */
500 for (i=0; i < thepage.n_sections; i++)
502 sect = thepage.sections + i;
503 if (sect->name && !strcmp (name, sect->name))
506 for (i=0; i < thepage.n_sections; i++)
507 if (!thepage.sections[i].name)
509 if (i < thepage.n_sections)
510 sect = thepage.sections + i;
513 /* We need to allocate or reallocate the section array. */
514 size_t old_n = thepage.n_sections;
518 thepage.sections = xcalloc (new_n, sizeof *thepage.sections);
521 thepage.sections = xrealloc (thepage.sections,
523 * sizeof *thepage.sections));
524 memset (thepage.sections + old_n, 0,
525 new_n * sizeof *thepage.sections);
527 thepage.n_sections += new_n;
529 /* Setup the tail pointers. */
530 for (i=old_n; i < thepage.n_sections; i++)
532 sect = thepage.sections + i;
533 sect->lines_tail = §->lines;
535 sect = thepage.sections + old_n;
538 /* Store the name. */
539 assert (!sect->name);
540 sect->name = xstrdup (name);
546 /* Add the content of LINE to the section named SECTNAME. */
548 add_content (const char *sectname, char *line, int verbatim)
550 section_buffer_t sect;
553 sect = get_section_buffer (sectname);
554 if (sect->last_line && !sect->last_line->verbatim == !verbatim)
556 /* Lets append that line to the last one. We do this to keep
557 all lines of the same kind (i.e.verbatim or not) together in
561 lb = sect->last_line;
562 n1 = strlen (lb->line);
563 n = n1 + 1 + strlen (line) + 1;
564 lb->line = xrealloc (lb->line, n);
565 strcpy (lb->line+n1, "\n");
566 strcpy (lb->line+n1+1, line);
570 lb = xcalloc (1, sizeof *lb);
571 lb->verbatim = verbatim;
572 lb->line = xstrdup (line);
573 sect->last_line = lb;
574 *sect->lines_tail = lb;
575 sect->lines_tail = &lb->next;
580 /* Prepare for a new man page using the filename NAME. */
582 start_page (char *name)
585 inf ("starting page '%s'", name);
586 assert (!thepage.name);
587 thepage.name = xstrdup (name);
588 thepage.n_sections = 0;
592 /* Write the .TH entry of the current page. Return -1 if there is a
593 problem with the page. */
599 fputs (".\\\" Created from Texinfo source by yat2m " VERSION "\n", fp);
601 name = ascii_strupr (xstrdup (thepage.name));
602 p = strrchr (name, '.');
605 err ("no section name in man page '%s'", thepage.name);
610 fprintf (fp, ".TH %s %s %s \"%s\" \"%s\"\n",
611 name, p, isodatestring (), opt_release, opt_source);
616 /* Process the texinfo command COMMAND (without the leading @) and
617 write output if needed to FP. REST is the remainer of the line
618 which should either point to an opening brace or to a white space.
619 The function returns the number of characters already processed
620 from REST. LEN is the usable length of REST. TABLE_LEVEL is used to
621 control the indentation of tables. */
623 proc_texi_cmd (FILE *fp, const char *command, const char *rest, size_t len,
624 int *table_level, int *eol_action)
627 const char *name; /* Name of the command. */
628 int what; /* What to do with this command. */
629 const char *lead_in; /* String to print with a opening brace. */
630 const char *lead_out;/* String to print with the closing brace. */
632 { "command", 0, "\\fB", "\\fR" },
633 { "code", 0, "\\fB", "\\fR" },
634 { "sc", 0, "\\fB", "\\fR" },
635 { "var", 0, "\\fI", "\\fR" },
636 { "samp", 0, "\\(aq", "\\(aq" },
637 { "file", 0, "\\(oq\\fI","\\fR\\(cq" },
638 { "env", 0, "\\(oq\\fI","\\fR\\(cq" },
641 { "option", 0, "\\fB", "\\fR" },
642 { "example", 1, ".RS 2\n.nf\n" },
643 { "smallexample", 1, ".RS 2\n.nf\n" },
647 { "xref", 0, "see: [", "]" },
648 { "pxref", 0, "see: [", "]" },
649 { "uref", 0, "(\\fB", "\\fR)" },
650 { "footnote",0, " ([", "])" },
651 { "emph", 0, "\\fI", "\\fR" },
660 { "subsection", 6, "\n.SS " },
662 { "item", 2, ".TP\n.B " },
663 { "itemx", 2, ".TP\n.B " },
666 { "bullet", 0, "* " },
668 { "quotation",1, ".RS\n\\fB" },
674 const char *lead_out = NULL;
677 for (i=0; cmdtbl[i].name && strcmp (cmdtbl[i].name, command); i++)
681 s = cmdtbl[i].lead_in;
684 lead_out = cmdtbl[i].lead_out;
685 switch (cmdtbl[i].what)
687 case 1: /* Throw away the entire line. */
688 s = memchr (rest, '\n', len);
689 return s? (s-rest)+1 : len;
690 case 2: /* Handle @item. */
692 case 3: /* Handle table. */
693 if (++(*table_level) > 1)
695 /* Now throw away the entire line. */
696 s = memchr (rest, '\n', len);
697 return s? (s-rest)+1 : len;
699 case 4: /* Handle end. */
700 for (s=rest, n=len; n && (*s == ' ' || *s == '\t'); s++, n--)
702 if (n >= 5 && !memcmp (s, "table", 5)
703 && (!n || s[5] == ' ' || s[5] == '\t' || s[5] == '\n'))
705 if ((*table_level)-- > 1)
708 else if (n >= 7 && !memcmp (s, "example", 7)
709 && (!n || s[7] == ' ' || s[7] == '\t' || s[7] == '\n'))
711 fputs (".fi\n.RE\n", fp);
713 else if (n >= 12 && !memcmp (s, "smallexample", 12)
714 && (!n || s[12] == ' ' || s[12] == '\t' || s[12] == '\n'))
716 fputs (".fi\n.RE\n", fp);
718 else if (n >= 9 && !memcmp (s, "quotation", 9)
719 && (!n || s[9] == ' ' || s[9] == '\t' || s[9] == '\n'))
721 fputs ("\\fR\n.RE\n", fp);
723 /* Now throw away the entire line. */
724 s = memchr (rest, '\n', len);
725 return s? (s-rest)+1 : len;
726 case 5: /* Handle special comments. */
727 for (s=rest, n=len; n && (*s == ' ' || *s == '\t'); s++, n--)
729 if (n >= 4 && !memcmp (s, "man:", 4))
731 for (s+=4, n-=4; n && *s != '\n'; n--, s++)
735 /* Now throw away the entire line. */
736 s = memchr (rest, '\n', len);
737 return s? (s-rest)+1 : len;
752 for (m = macrolist; m ; m = m->next)
753 if (!strcmp (m->name, command))
757 proc_texi_buffer (fp, m->value, strlen (m->value),
758 table_level, eol_action);
759 ignore_args = 1; /* Parameterized macros are not yet supported. */
762 inf ("texinfo command '%s' not supported (%.*s)", command,
763 ((s = memchr (rest, '\n', len)), (s? (s-rest) : len)), rest);
768 /* Find matching closing brace. */
769 for (s=rest+1, n=1, i=1; i && *s && n < len; s++, n++)
776 err ("closing brace for command '%s' not found", command);
779 if (n > 2 && !ignore_args)
780 proc_texi_buffer (fp, rest+1, n-2, table_level, eol_action);
786 fputs (lead_out, fp);
793 /* Process the string LINE with LEN bytes of Texinfo content. */
795 proc_texi_buffer (FILE *fp, const char *line, size_t len,
796 int *table_level, int *eol_action)
804 for (s=line; *s && len; s++, len--)
812 case '@': case '{': case '}':
813 putc (*s, fp); in_cmd = 0;
815 case ':': /* Not ending a sentence flag. */
818 case '.': case '!': case '?': /* Ending a sentence. */
819 putc (*s, fp); in_cmd = 0;
821 case ' ': case '\t': case '\n': /* Non collapsing spaces. */
822 putc (*s, fp); in_cmd = 0;
826 cmdbuf[cmdidx++] = *s;
831 else if (*s == '{' || *s == ' ' || *s == '\t' || *s == '\n')
834 n = proc_texi_cmd (fp, cmdbuf, s, len, table_level, eol_action);
840 else if (cmdidx < sizeof cmdbuf -1)
841 cmdbuf[cmdidx++] = *s;
844 err ("texinfo command too long - ignored");
854 case 1: /* Create a dummy paragraph. */
855 fputs ("\n\\ \n", fp);
871 n = proc_texi_cmd (fp, cmdbuf, s, len, table_level, eol_action);
880 /* Do something with the Texinfo line LINE. */
882 parse_texi_line (FILE *fp, const char *line, int *table_level)
886 /* A quick test whether there are any texinfo commands. */
887 if (!strchr (line, '@'))
893 proc_texi_buffer (fp, line, strlen (line), table_level, &eol_action);
898 /* Write all the lines LINES to FP. */
900 write_content (FILE *fp, line_buffer_t lines)
905 for (line = lines; line; line = line->next)
909 fputs (line->line, fp);
914 /* fputs ("TEXI---", fp); */
915 /* fputs (line->line, fp); */
916 /* fputs ("---\n", fp); */
917 parse_texi_line (fp, line->line, &table_level);
925 is_standard_section (const char *name)
930 for (i=0; (s=standard_sections[i]); i++)
931 if (!strcmp (s, name))
937 /* Finish a page; that is sort the data and write it out to the file. */
942 section_buffer_t sect = NULL;
948 return; /* No page active. */
951 inf ("finishing page '%s'", thepage.name);
955 if (!strcmp (opt_select, thepage.name))
957 inf ("selected '%s'", thepage.name );
962 fp = fopen ( "/dev/null", "w" );
964 die ("failed to open /dev/null: %s\n", strerror (errno));
969 inf ("writing '%s'", thepage.name );
970 fp = fopen ( thepage.name, "w" );
972 die ("failed to create '%s': %s\n", thepage.name, strerror (errno));
980 for (idx=0; (s=standard_sections[idx]); idx++)
982 for (i=0; i < thepage.n_sections; i++)
984 sect = thepage.sections + i;
985 if (sect->name && !strcmp (s, sect->name))
988 if (i == thepage.n_sections)
993 fprintf (fp, ".SH %s\n", sect->name);
994 write_content (fp, sect->lines);
995 /* Now continue with all non standard sections directly
996 following this one. */
997 for (i++; i < thepage.n_sections; i++)
999 sect = thepage.sections + i;
1000 if (sect->name && is_standard_section (sect->name))
1004 fprintf (fp, ".SH %s\n", sect->name);
1005 write_content (fp, sect->lines);
1016 free (thepage.name);
1017 thepage.name = NULL;
1018 /* FIXME: Cleanup the content. */
1024 /* Parse one Texinfo file and create manpages according to the
1025 embedded instructions. */
1027 parse_file (const char *fname, FILE *fp, char **section_name, int in_pause)
1031 /* Fixme: The following state variables don't carry over to include
1033 int skip_to_end = 0; /* Used to skip over menu entries. */
1034 int skip_sect_line = 0; /* Skip after @mansect. */
1035 int item_indent = 0; /* How far is the current @item indented. */
1037 /* Helper to define a macro. */
1038 char *macroname = NULL;
1039 char *macrovalue = NULL;
1040 size_t macrovaluesize = 0;
1041 size_t macrovalueused = 0;
1043 line = xmalloc (LINESIZE);
1044 while (fgets (line, LINESIZE, fp))
1046 size_t n = strlen (line);
1051 if (!n || line[n-1] != '\n')
1053 err ("%s:%d: trailing linefeed missing, line too long or "
1054 "embedded Nul character", fname, lnr);
1059 /* Kludge to allow indentation of tables. */
1060 for (p=line; *p == ' ' || *p == '\t'; p++)
1064 if (*p == '@' && !strncmp (p+1, "item", 4))
1065 item_indent = p - line; /* Set a new indent level. */
1066 else if (p - line < item_indent)
1067 item_indent = 0; /* Switch off indention. */
1071 memmove (line, line+item_indent, n - item_indent + 1);
1079 for (p=line+1, n=1; *p && *p != ' ' && *p != '\t'; p++)
1081 while (*p == ' ' || *p == '\t')
1087 /* Take action on macro. */
1090 if (n == 4 && !memcmp (line, "@end", 4)
1091 && (line[4]==' '||line[4]=='\t'||!line[4])
1092 && !strncmp (p, "macro", 5)
1093 && (p[5]==' '||p[5]=='\t'||!p[5]))
1096 macrovalue[--macrovalueused] = 0; /* Kill the last LF. */
1097 macrovalue[macrovalueused] = 0; /* Terminate macro. */
1098 macrovalue = xrealloc (macrovalue, macrovalueused+1);
1100 set_macro (macroname, macrovalue);
1107 if (macrovalueused + strlen (line) + 2 >= macrovaluesize)
1109 macrovaluesize += strlen (line) + 256;
1110 macrovalue = xrealloc (macrovalue, macrovaluesize);
1112 strcpy (macrovalue+macrovalueused, line);
1113 macrovalueused += strlen (line);
1114 macrovalue[macrovalueused++] = '\n';
1120 if (n >= 5 && !memcmp (line, "@node", 5)
1121 && (line[5]==' '||line[5]=='\t'||!line[5]))
1123 /* Completey ignore @node lines. */
1131 if (!strncmp (line, "@section", 8)
1132 || !strncmp (line, "@subsection", 11)
1133 || !strncmp (line, "@chapheading", 12))
1137 /* We only parse lines we need and ignore the rest. There are a
1138 few macros used to control this as well as one @ifset
1139 command. Parts we know about are saved away into containers
1140 separate for each section. */
1142 /* First process ifset/ifclear commands. */
1145 if (n == 6 && !memcmp (line, "@ifset", 6)
1146 && (line[6]==' '||line[6]=='\t'))
1148 for (p=line+7; *p == ' ' || *p == '\t'; p++)
1152 err ("%s:%d: name missing after \"@ifset\"", fname, lnr);
1155 for (pend=p; *pend && *pend != ' ' && *pend != '\t'; pend++)
1157 *pend = 0; /* Ignore rest of the line. */
1158 push_condition (p, 1, fname, lnr);
1161 else if (n == 8 && !memcmp (line, "@ifclear", 8)
1162 && (line[8]==' '||line[8]=='\t'))
1164 for (p=line+9; *p == ' ' || *p == '\t'; p++)
1168 err ("%s:%d: name missing after \"@ifsclear\"", fname, lnr);
1171 for (pend=p; *pend && *pend != ' ' && *pend != '\t'; pend++)
1173 *pend = 0; /* Ignore rest of the line. */
1174 push_condition (p, 0, fname, lnr);
1177 else if (n == 4 && !memcmp (line, "@end", 4)
1178 && (line[4]==' '||line[4]=='\t')
1179 && !strncmp (p, "ifset", 5)
1180 && (p[5]==' '||p[5]=='\t'||!p[5]))
1182 pop_condition (1, fname, lnr);
1185 else if (n == 4 && !memcmp (line, "@end", 4)
1186 && (line[4]==' '||line[4]=='\t')
1187 && !strncmp (p, "ifclear", 7)
1188 && (p[7]==' '||p[7]=='\t'||!p[7]))
1190 pop_condition (0, fname, lnr);
1195 /* Take action on ifset/ifclear. */
1196 if (!cond_is_active)
1199 /* Process commands. */
1203 && n == 4 && !memcmp (line, "@end", 4)
1204 && (line[4]==' '||line[4]=='\t'||!line[4]))
1208 else if (cond_in_verbatim)
1212 else if (n == 6 && !memcmp (line, "@macro", 6))
1214 macroname = xstrdup (p);
1215 macrovalue = xmalloc ((macrovaluesize = 1024));
1218 else if (n == 8 && !memcmp (line, "@manpage", 8))
1220 free (*section_name);
1221 *section_name = NULL;
1226 else if (n == 8 && !memcmp (line, "@mansect", 8))
1229 err ("%s:%d: section outside of a man page", fname, lnr);
1232 free (*section_name);
1233 *section_name = ascii_strupr (xstrdup (p));
1238 else if (n == 9 && !memcmp (line, "@manpause", 9))
1241 err ("%s:%d: pausing outside of a man section", fname, lnr);
1243 err ("%s:%d: already pausing", fname, lnr);
1247 else if (n == 8 && !memcmp (line, "@mancont", 8))
1250 err ("%s:%d: continue outside of a man section", fname, lnr);
1252 err ("%s:%d: continue while not pausing", fname, lnr);
1256 else if (n == 5 && !memcmp (line, "@menu", 5)
1257 && (line[5]==' '||line[5]=='\t'||!line[5]))
1261 else if (n == 8 && !memcmp (line, "@include", 8)
1262 && (line[8]==' '||line[8]=='\t'||!line[8]))
1264 char *incname = xstrdup (p);
1265 FILE *incfp = fopen (incname, "r");
1267 if (!incfp && opt_include && *opt_include && *p != '/')
1270 incname = xmalloc (strlen (opt_include) + 1
1272 strcpy (incname, opt_include);
1273 if ( incname[strlen (incname)-1] != '/' )
1274 strcat (incname, "/");
1275 strcat (incname, p);
1276 incfp = fopen (incname, "r");
1280 err ("can't open include file '%s':%s",
1281 incname, strerror (errno));
1284 parse_file (incname, incfp, section_name, in_pause);
1289 else if (n == 4 && !memcmp (line, "@bye", 4)
1290 && (line[4]==' '||line[4]=='\t'||!line[4]))
1294 else if (!skip_to_end)
1297 else if (!skip_to_end)
1300 if (got_line && cond_in_verbatim)
1301 add_content (*section_name, line, 1);
1302 else if (got_line && thepage.name && *section_name && !in_pause)
1303 add_content (*section_name, line, 0);
1307 err ("%s:%d: read error: %s", fname, lnr, strerror (errno));
1315 top_parse_file (const char *fname, FILE *fp)
1317 char *section_name = NULL; /* Name of the current section or NULL
1318 if not in a section. */
1323 macro_t next = macrolist->next;
1324 free (macrolist->value);
1328 for (m=predefinedmacrolist; m; m = m->next)
1329 set_macro (m->name, xstrdup ("1"));
1331 cond_in_verbatim = 0;
1333 parse_file (fname, fp, §ion_name, 0);
1334 free (section_name);
1340 main (int argc, char **argv)
1347 /* Define default macros. The trick is that these macros are not
1348 defined when using the actual texinfo renderer. */
1349 add_predefined_macro ("isman");
1350 add_predefined_macro ("manverb");
1352 /* Option parsing. */
1357 while (argc && last_argc != argc )
1360 if (!strcmp (*argv, "--"))
1365 else if (!strcmp (*argv, "--help"))
1368 "Usage: " PGM " [OPTION] [FILE]\n"
1369 "Extract man pages from a Texinfo source.\n\n"
1370 " --source NAME use NAME as source field\n"
1371 " --release STRING use STRING as the release field\n"
1372 " --store write output using @manpage name\n"
1373 " --select NAME only output pages with @manpage NAME\n"
1374 " --verbose enable extra informational output\n"
1375 " --debug enable additional debug output\n"
1376 " --help display this help and exit\n"
1377 " -I DIR also search in include DIR\n"
1378 " -D gpgone the only useable define\n\n"
1379 "With no FILE, or when FILE is -, read standard input.\n\n"
1380 "Report bugs to <bugs@g10code.com>.");
1383 else if (!strcmp (*argv, "--version"))
1385 puts (PGM " " VERSION "\n"
1386 "Copyright (C) 2005 g10 Code GmbH\n"
1387 "This program comes with ABSOLUTELY NO WARRANTY.\n"
1388 "This is free software, and you are welcome to redistribute it\n"
1389 "under certain conditions. See the file COPYING for details.");
1392 else if (!strcmp (*argv, "--verbose"))
1397 else if (!strcmp (*argv, "--quiet"))
1402 else if (!strcmp (*argv, "--debug"))
1404 verbose = debug = 1;
1407 else if (!strcmp (*argv, "--source"))
1416 else if (!strcmp (*argv, "--release"))
1421 opt_release = *argv;
1425 else if (!strcmp (*argv, "--store"))
1430 else if (!strcmp (*argv, "--select"))
1435 opt_select = strrchr (*argv, '/');
1443 else if (!strcmp (*argv, "-I"))
1448 opt_include = *argv;
1452 else if (!strcmp (*argv, "-D"))
1457 add_predefined_macro (*argv);
1464 die ("usage: " PGM " [OPTION] [FILE] (try --help for more information)\n");
1466 /* Start processing. */
1467 if (argc && strcmp (*argv, "-"))
1469 FILE *fp = fopen (*argv, "rb");
1471 die ("%s:0: can't open file: %s", *argv, strerror (errno));
1472 top_parse_file (*argv, fp);
1476 top_parse_file ("-", stdin);
1484 compile-command: "gcc -Wall -g -Wall -o yat2m yat2m.c"