1/* mkw32errmap.c - Generate mapping sources for Windows.
2   Copyright (C) 2010 g10 Code GmbH
3
4   This file is part of libgpg-error.
5
6   libgpg-error is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Lesser General Public License
8   as published by the Free Software Foundation; either version 2.1 of
9   the License, or (at your option) any later version.
10
11   libgpg-error is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef RESOLVE_MACROS
21# include <winerror.h>
22#endif
23#include <stdio.h>
24#include <stdlib.h>
25
26static const char header_gpg_extra_errno_h[] =
27  "/* errno.h - WindowsCE errno.h substitute\n"
28  "   Copyright (C) 2010 g10 Code GmbH\n"
29  "\n"
30  "   This file is free software; as a special exception the author gives\n"
31  "   unlimited permission to copy and/or distribute it, with or without\n"
32  "   modifications, as long as this notice is preserved.\n"
33  "\n"
34  "   This file is distributed in the hope that it will be useful, but\n"
35  "   WITHOUT ANY WARRANTY, to the extent permitted by law; without even\n"
36  "   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\n"
37  "   PURPOSE.\n"
38  "\n"
39  "   +++ Do not edit!  File has been generated by mkw32errmap.c +++\n"
40  "\n"
41  "   This file is intended to be used with ming32ce-gcc to implement an\n"
42  "   errno substitute under WindowsCE.  It must be included via gcc's\n"
43  "   -idirafter option.  The gpg-error-config script emits the\n"
44  "   appropriate option snippet.  The actual implementation of the errno\n"
45  "   related functions are part of libgpg-error.  A separate header file\n"
46  "   is required because errno.h is often included before gpg-error.h.\n"
47  " */\n"
48  "\n"
49  "#ifndef _GPG_ERROR_EXTRA_ERRNO_H\n"
50  "#define _GPG_ERROR_EXTRA_ERRNO_H\n"
51  "\n"
52  "/* Due to peculiarities in W32 we can't implement ERRNO as an\n"
53  "   writable lvalue.  This also allows us to easily find places\n"
54  "   where ERRNO is being written to.  See also gpg_err_set_errno.  */\n"
55  "int _gpg_w32ce_get_errno (void);\n"
56  "#define errno (_gpg_w32ce_get_errno ())\n"
57  "\n";
58static const char footer_gpg_extra_errno_h[] =
59  "\n"
60  "#endif /*_GPG_ERROR_EXTRA_ERRNO_H*/\n";
61
62
63/* The table below is used in two modes.  First we run the host
64   preprocessor over it to generate a new include file.  This include
65   file has the same content but the Windows error macros are
66   resolved.  This is so that we don't need to include winerror.h into
67   the generated errno.h.  The mkw32errmap_marker variable is only
68   here to have something to grep for after preprocessing.  */
69static int mkw32errmap_marker;
70struct table_s
71{
72  int *dummy;
73  const char *name;
74  int w32code;
75  int w32code2;
76};
77
78struct table_s table[] =
79  {
80#ifdef RESOLVE_MACROS
81#define X(a,b,c)                                 \
82    {&mkw32errmap_marker, (a), (b), (c)}
83   X( "EPERM",	ERROR_CANNOT_MAKE               , 0 ),
84   X( "ENOENT",	ERROR_FILE_NOT_FOUND            , ERROR_PATH_NOT_FOUND ),
85   X( "EINTR",	ERROR_INVALID_AT_INTERRUPT_TIME , 0 ),
86   X( "EIO",	ERROR_IO_DEVICE                 , 0 ),
87   X( "ENXIO",	ERROR_FILE_INVALID              , 0 ),
88   X( "EBADF",	ERROR_INVALID_HANDLE            , 0 ),
89   X( "EAGAIN",	ERROR_MORE_DATA                 , WSAEWOULDBLOCK ),
90
91   X( "ENOMEM",	ERROR_NOT_ENOUGH_MEMORY         , 0 ),
92   X( "EACCES",	ERROR_ACCESS_DENIED             , 0 ),
93   X( "EFAULT",	ERROR_PROCESS_ABORTED           , 0 ),
94   X( "EBUSY",	ERROR_BUSY                      , 0 ),
95   X( "EEXIST",	ERROR_FILE_EXISTS               , WSAEADDRINUSE  ),
96
97   X( "EXDEV",	ERROR_NOT_SAME_DEVICE           , 0 ),
98   X( "ENODEV",	ERROR_BAD_DEVICE                , ERROR_DEV_NOT_EXIST ),
99
100   X( "ENOTDIR",ERROR_DIRECTORY                 , 0 ),
101   X( "EINVAL",	ERROR_INVALID_PARAMETER         , 0 ),
102   X( "ENFILE",	ERROR_NO_MORE_FILES             , 0 ),
103   X( "EMFILE",	ERROR_TOO_MANY_OPEN_FILES       , 0 ),
104   X( "ENOSPC",	ERROR_DISK_FULL                 , 0 ),
105   X( "EROFS",	ERROR_WRITE_PROTECT             , 0 ),
106   X( "EPIPE",	ERROR_BROKEN_PIPE               , 0 ),
107   X( "ERANGE",	ERROR_ARITHMETIC_OVERFLOW       , 0 ),
108   X( "EDEADLOCK",ERROR_POSSIBLE_DEADLOCK       , 0 ),
109   X( "ENAMETOOLONG", ERROR_FILENAME_EXCED_RANGE, 0 ),
110   X( "ENOLCK",	ERROR_SHARING_BUFFER_EXCEEDED   , 0 ),
111   X( "ENOSYS",	ERROR_NOT_SUPPORTED             , 0 ),
112   X( "ENOTEMPTY",ERROR_DIR_NOT_EMPTY           , 0 ),
113   X( "ESPIPE",  ERROR_SEEK_ON_DEVICE           , 0 ),
114#if 0 /* FIXME: Find appropriate mappings.  */
115   X( "EILSEQ",		),
116   X( "EDOM",		),
117   X( "EMLINK",		),
118   X( "ESRCH",		), /* No such process */
119   X( "E2BIG",		), /* Arg list too long */
120   X( "ENOEXEC",	), /* Exec format error */
121   X( "ECHILD",		), /* No child processes */
122   X( "EISDIR",		), /* Is a directory */
123   X( "ENOTTY",		), /* Inappropriate I/O control operation */
124   X( "EFBIG",		), /* File too large */
125#endif
126#undef X
127#else /*!RESOLVE_MACROS*/
128# include "mkw32errmap.tab.h"
129#endif /*!RESOLVE_MACROS*/
130   { NULL, 0 }
131  };
132
133
134
135static int
136compare_table (const void *a_v, const void *b_v)
137{
138  const struct table_s *a = a_v;
139  const struct table_s *b = b_v;
140
141  return (a->w32code - b->w32code);
142}
143
144
145int
146main (int argc, char **argv)
147{
148  int idx;
149
150  for (idx=0; table[idx].name; idx++)
151    ;
152  qsort (table, idx, sizeof *table, compare_table);
153
154  if (argc == 2 && !strcmp (argv[1], "--map"))
155    {
156      fputs ("static int\n"
157             "map_w32codes (int err)\n"
158             "{\n"
159             "  switch (err)\n"
160             "    {\n", stdout );
161      for (idx=0; table[idx].name; idx++)
162        if (table[idx].w32code2)
163          printf ("    case %d: return %d;\n",
164                  table[idx].w32code2, table[idx].w32code);
165      fputs ("    default: return err;\n"
166             "    }\n"
167             "}\n", stdout);
168    }
169  else
170    {
171      fputs (header_gpg_extra_errno_h, stdout);
172      for (idx=0; table[idx].name; idx++)
173        printf ("#define %-12s %5d\n", table[idx].name, table[idx].w32code);
174      fputs (footer_gpg_extra_errno_h, stdout);
175    }
176
177  return 0;
178}
179