1 /*************************************************
2 * xfpt - Simple ASCII->Docbook processor *
3 *************************************************/
5 /* Copyright (c) University of Cambridge, 2012 */
6 /* Written by Philip Hazel. */
8 /* This module contains the main program and initialization functions. */
14 /*************************************************
16 *************************************************/
18 static uschar *xfpt_filename = NULL;
19 static uschar *out_filename = NULL;
24 /*************************************************
26 *************************************************/
32 "Usage: xfpt [-help]\n"
33 " [-o <output-file>]\n"
34 " [-S <share-directory>]\n"
42 /*************************************************
43 * Command line argument decoding *
44 *************************************************/
46 /* Arguments: as for main()
51 xfpt_decode_arg(int argc, char **argv)
54 for (i = 1; i < argc; i++)
56 uschar *arg = US argv[i];
57 if (*arg != '-') break;
58 if (Ustrcmp(arg, "-o") == 0)
60 out_filename = US argv[++i];
61 if (out_filename == NULL) { usage(); return FALSE; }
63 else if (Ustrcmp(arg, "-S") == 0)
65 xfpt_share = US argv[++i];
66 if (xfpt_share == NULL) { usage(); return FALSE; }
68 else if (Ustrcmp(arg, "-help") == 0 || Ustrcmp(arg, "--help") == 0)
73 else if (Ustrcmp(arg, "-v") == 0)
75 (void)fprintf(stdout, "xpft version %s\n", xfpt_version);
80 (void)fprintf(stderr, "xfpt: unknown option \"%s\"\n", arg);
86 /* Require there to be either 0 or 1 command line argument left. */
94 /* This will set NULL if there is no file name. If there is a file name and no
95 output file is specified, default it to the input name with a .xml extension. */
97 xfpt_filename = US argv[i];
98 if (xfpt_filename != NULL && out_filename == NULL)
101 int len = Ustrlen(xfpt_filename);
102 out_filename = misc_malloc(len + 5);
103 Ustrcpy(out_filename, xfpt_filename);
104 if ((p = Ustrrchr(out_filename, '.')) != NULL) len = p - out_filename;
105 Ustrcpy(out_filename + len, ".xml");
113 /*************************************************
114 * Entry point and main program *
115 *************************************************/
118 main(int argc, char **argv)
120 BOOL para_unfinished[MAXNEST+1];
124 if (!xfpt_decode_arg(argc, argv)) return EXIT_FAILURE;
126 inbuffer = misc_malloc(INBUFFSIZE);
127 parabuffer = misc_malloc(PARABUFFSIZE);
129 /* Set up the first file */
131 istackbase = istack = misc_malloc(sizeof(istackstr));
133 istack->linenumber = 0;
136 from_type[from_type_ptr] = FROM_FILE;
138 if (xfpt_filename == NULL)
140 istack->file = stdin;
141 Ustrcpy(istack->filename, US"(stdin)");
145 Ustrcpy(istack->filename, xfpt_filename);
146 istack->file = Ufopen(xfpt_filename, "rb");
147 if (istack->file == NULL)
148 error(0, istack->filename, strerror(errno)); /* Hard */
151 /* Set up the output file. */
153 if (out_filename == NULL || Ustrcmp(out_filename, "-") == 0)
159 outfile = Ufopen(out_filename, "wb");
161 error(0, out_filename, strerror(errno)); /* Hard error */
164 /* Process the input */
167 para_unfinished[0] = FALSE;
169 while ((p = read_nextline()) != NULL)
171 if (*p == '.') dot_process(p); else switch (literal_state)
182 (void)fprintf(outfile, "%s", CS p);
188 while (isspace(*q)) q++;
192 p = read_paragraph(p, &nest_info);
193 if (!para_unfinished[nest_level])
195 (void)fprintf(outfile, "<");
196 para_process(US"para&xfpt.rev;");
197 (void)fprintf(outfile, ">\n");
201 if (nest_info == NEST_BEGIN)
203 if (nest_level >= MAXNEST) error(27); else
205 nest_literal_stack[nest_level] = literal_state;
206 para_unfinished[nest_level++] = TRUE;
209 else (void)fprintf(outfile, "</para>\n");
211 para_unfinished[nest_level] = FALSE;
213 if (nest_info == NEST_END)
215 if (nest_level <= 0) error(28);
216 else literal_state = nest_literal_stack[--nest_level];
223 /* Empty the stack of pushed texts, close the output, and we are done. */
225 while (pushed != NULL)
227 if (!suppress_warnings)
229 if (pushed->check != 0)
233 "** Warning: one or more items were left unclosed at the end of processing.\n"
234 " The numbers are the lines in the original file %s from where\n"
235 " the items were generated:\n",
236 ((xfpt_filename == NULL)? "(stdin)" : (char *)xfpt_filename));
237 if (pushed->macname == NULL)
238 fprintf(stderr, "%d: %s\n", pushed->check, pushed->string);
240 fprintf(stderr, "%d: .%s\n", pushed->check, pushed->macname);
244 fprintf(stderr, "... too many to list\n");
245 suppress_warnings = TRUE;
249 para_process(pushed->string);
250 (void)fprintf(outfile, "\n");
251 pushed = pushed->next;
254 (void)fclose(outfile);