1 /* mkheader.c - Create a header file for libgpg-error
2 * Copyright (C) 2010 Free Software Foundation, Inc.
3 * Copyright (C) 2014 g10 Code GmbH
5 * This file is free software; as a special exception the author gives
6 * unlimited permission to copy and/or distribute it, with or without
7 * modifications, as long as this notice is preserved.
9 * This file is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
11 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 #define PGM "mkheader"
25 static const char *host_os;
26 static const char *host_triplet;
28 static const char *hdr_version;
29 static const char *hdr_version_number;
32 /* Write LINE to stdout. The function is allowed to modify LINE. */
34 write_str (char *line)
36 if (fputs (line, stdout) == EOF)
38 fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
44 write_line (char *line)
46 if (puts (line) == EOF)
48 fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
54 /* Write SOURCE or CODES line to stdout. The function is allowed to
55 modify LINE. Trailing white space is already removed. Passing
56 NULL resets the internal state. */
58 write_sources_or_codes (char *line)
74 if (!strchr ("0123456789", *line))
79 p1 = strtok (line, " \t");
80 p2 = p1? strtok (NULL, " \t") : NULL;
82 if (p1 && p2 && strchr ("0123456789", *p1) && *p2)
93 /* Write system errnos to stdout. The function is allowed to
94 modify LINE. Trailing white space is already removed. Passing
95 NULL resets the internal state. */
97 write_errnos_in (char *line)
111 if (!state && strchr ("0123456789", *line))
113 else if (state == 1 && !strchr ("0123456789", *line))
119 p1 = strtok (line, " \t");
120 p2 = p1? strtok (NULL, " \t") : NULL;
122 if (p1 && p2 && strchr ("0123456789", *p1) && *p2)
124 write_str (" GPG_ERR_");
126 write_str (" = GPG_ERR_SYSTEM_ERROR | ");
133 /* Create the full file name for NAME and return a newly allocated
134 string with it. If name contains a '&' and REPL is not NULL
135 replace '&' with REPL. */
137 mk_include_name (const char *name, const char *repl)
143 incfname = malloc (strlen (srcdir) + strlen (name)
144 + (repl?strlen (repl):0) + 1);
147 fputs (PGM ": out of core\n", stderr);
151 if (*name == '.' && name[1] == '/')
154 strcpy (incfname, srcdir);
155 p = incfname + strlen (incfname);
156 for (s=name; *s; s++)
158 if (*s == '&' && repl)
162 repl = NULL; /* Replace only once. */
172 /* Include the file NAME from the source directory. The included file
173 is not further expanded. It may have comments indicated by a
174 double hash mark at the begin of a line. OUTF is called for each
175 read line and passed a buffer with the content of line sans line
176 line endings. If NAME is prefixed with "./" it is included from
177 the current directory and not from the source directory. */
179 include_file (const char *fname, int lnr, const char *name, void (*outf)(char*))
187 repl_flag = !!strchr (name, '&');
188 incfname = mk_include_name (name, repl_flag? host_triplet : NULL);
189 fp = fopen (incfname, "r");
190 if (!fp && repl_flag)
192 /* Try again using the OS string. */
194 incfname = mk_include_name (name, host_os);
195 fp = fopen (incfname, "r");
199 fprintf (stderr, "%s:%d: error including `%s': %s\n",
200 fname, lnr, incfname, strerror (errno));
205 fprintf (stderr,"%s:%d: note: including '%s'\n",
206 fname, lnr, incfname);
209 while (fgets (line, LINESIZE, fp))
211 size_t n = strlen (line);
214 if (!n || line[n-1] != '\n')
217 "%s:%d: trailing linefeed missing, line too long or "
218 "embedded nul character\n", incfname, inclnr);
219 fprintf (stderr,"%s:%d: note: file '%s' included from here\n",
220 fname, lnr, incfname);
224 while (line[n] == ' ' || line[n] == '\t' || line[n] == '\r')
232 if (line[0] == '#' && line[1] == '#')
234 if (!strncmp (line+2, "EOF##", 5))
235 break; /* Forced EOF. */
242 fprintf (stderr, "%s:%d: error reading `%s': %s\n",
243 fname, lnr, incfname, strerror (errno));
251 /* Try to include the file NAME. Returns true if it does not
254 try_include_file (const char *fname, int lnr, const char *name,
261 repl_flag = !!strchr (name, '&');
262 incfname = mk_include_name (name, repl_flag? host_triplet : NULL);
263 rc = access (incfname, R_OK);
267 incfname = mk_include_name (name, host_os);
268 rc = access (incfname, R_OK);
271 include_file (fname, lnr, name, outf);
279 write_special (const char *fname, int lnr, const char *tag)
281 if (!strcmp (tag, "version"))
284 fputs (hdr_version, stdout);
288 else if (!strcmp (tag, "version-number"))
290 fputs (hdr_version_number, stdout);
293 else if (!strcmp (tag, "include:err-sources"))
295 write_sources_or_codes (NULL);
296 include_file (fname, lnr, "err-sources.h.in", write_sources_or_codes);
298 else if (!strcmp (tag, "include:err-codes"))
300 write_sources_or_codes (NULL);
301 include_file (fname, lnr, "err-codes.h.in", write_sources_or_codes);
303 else if (!strcmp (tag, "include:errnos"))
305 include_file (fname, lnr, "errnos.in", write_errnos_in);
307 else if (!strcmp (tag, "include:os-add"))
309 if (!strcmp (host_os, "mingw32"))
311 include_file (fname, lnr, "w32-add.h", write_line);
313 else if (!strcmp (host_os, "mingw32ce"))
315 include_file (fname, lnr, "w32-add.h", write_line);
316 include_file (fname, lnr, "w32ce-add.h", write_line);
319 else if (!strcmp (tag, "include:lock-obj"))
321 if (try_include_file (fname, lnr, "./lock-obj-pub.native.h", write_line))
322 include_file (fname, lnr, "syscfg/lock-obj-pub.&.h", write_line);
325 return 0; /* Unknown tag. */
327 return 1; /* Tag processed. */
332 main (int argc, char **argv)
337 const char *fname, *s;
348 " host_os host_triplet template.h version version_number\n",
353 host_triplet = argv[1];
355 hdr_version = argv[3];
356 hdr_version_number = argv[4];
358 srcdir = malloc (strlen (fname) + 2 + 1);
361 fputs (PGM ": out of core\n", stderr);
364 strcpy (srcdir, fname);
365 p1 = strrchr (srcdir, '/');
369 strcpy (srcdir, "./");
371 fp = fopen (fname, "r");
374 fprintf (stderr, "%s:%d: can't open file: %s",
375 fname, lnr, strerror (errno));
379 while (fgets (line, LINESIZE, fp))
381 size_t n = strlen (line);
384 if (!n || line[n-1] != '\n')
387 "%s:%d: trailing linefeed missing, line too long or "
388 "embedded nul character\n", fname, lnr);
393 p1 = strchr (line, '@');
394 p2 = p1? strchr (p1+1, '@') : NULL;
395 if (!p1 || !p2 || p2-p1 == 1)
402 fputs (line, stdout);
404 if (!strcmp (p1, "configure_input"))
406 s = strrchr (fname, '/');
407 printf ("Do not edit. Generated from %s for %s.",
408 s? s+1 : fname, host_triplet);
412 else if (!write_special (fname, lnr, p1))
424 fprintf (stderr, "%s:%d: error reading file: %s\n",
425 fname, lnr, strerror (errno));
430 "Loc" "al Variables:\n"
431 "buffer-read-only: t\n"
437 fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));