1c3d31fe1Smrg 
2c3d31fe1Smrg /* Install modified versions of certain ANSI-incompatible system header
3c3d31fe1Smrg    files which are fixed to work correctly with ANSI C and placed in a
4c3d31fe1Smrg    directory that GCC will search.
5c3d31fe1Smrg 
6c3d31fe1Smrg    Copyright (C) 1999, 2000, 2001, 2004, 2009 Free Software Foundation, Inc.
7c3d31fe1Smrg 
8c3d31fe1Smrg This file is part of GCC.
9c3d31fe1Smrg 
10c3d31fe1Smrg GCC is free software; you can redistribute it and/or modify
11c3d31fe1Smrg it under the terms of the GNU General Public License as published by
12c3d31fe1Smrg the Free Software Foundation; either version 3, or (at your option)
13c3d31fe1Smrg any later version.
14c3d31fe1Smrg 
15c3d31fe1Smrg GCC is distributed in the hope that it will be useful,
16c3d31fe1Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
17c3d31fe1Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18c3d31fe1Smrg GNU General Public License for more details.
19c3d31fe1Smrg 
20c3d31fe1Smrg You should have received a copy of the GNU General Public License
21c3d31fe1Smrg along with GCC; see the file COPYING3.  If not see
22c3d31fe1Smrg <http://www.gnu.org/licenses/>.  */
23c3d31fe1Smrg 
24c3d31fe1Smrg #include "fixlib.h"
25c3d31fe1Smrg 
26c3d31fe1Smrg /* * * * * * * * * * * * *
27c3d31fe1Smrg 
28c3d31fe1Smrg    load_file_data loads all the contents of a file into malloc-ed memory.
29c3d31fe1Smrg    Its argument is the file pointer of the file to read in; the returned
30c3d31fe1Smrg    result is the NUL terminated contents of the file.  The file
31c3d31fe1Smrg    is presumed to be an ASCII text file containing no NULs.  */
32c3d31fe1Smrg 
33c3d31fe1Smrg char *
load_file_data(FILE * fp)34c3d31fe1Smrg load_file_data (FILE* fp)
35c3d31fe1Smrg {
36c3d31fe1Smrg   char *pz_data = (char*)NULL;
37c3d31fe1Smrg   int    space_left = -1;  /* allow for terminating NUL */
38c3d31fe1Smrg   size_t space_used = 0;
39c3d31fe1Smrg 
40c3d31fe1Smrg   if (fp == (FILE*)NULL)
41c3d31fe1Smrg     return pz_data;
42c3d31fe1Smrg 
43c3d31fe1Smrg   do
44c3d31fe1Smrg     {
45c3d31fe1Smrg       size_t  size_read;
46c3d31fe1Smrg 
47c3d31fe1Smrg       if (space_left < 1024)
48c3d31fe1Smrg         {
49c3d31fe1Smrg           space_left += 4096;
50c3d31fe1Smrg 	  pz_data = XRESIZEVEC (char, pz_data, space_left + space_used + 1 );
51c3d31fe1Smrg         }
52c3d31fe1Smrg       size_read = fread (pz_data + space_used, 1, space_left, fp);
53c3d31fe1Smrg 
54c3d31fe1Smrg       if (size_read == 0)
55c3d31fe1Smrg         {
56c3d31fe1Smrg           if (feof (fp))
57c3d31fe1Smrg             break;
58c3d31fe1Smrg 
59c3d31fe1Smrg           if (ferror (fp))
60c3d31fe1Smrg             {
61c3d31fe1Smrg               int err = errno;
62c3d31fe1Smrg               if (err != EISDIR)
63c3d31fe1Smrg                 fprintf (stderr, "error %d (%s) reading input\n", err,
64c3d31fe1Smrg                          xstrerror (err));
65c3d31fe1Smrg               free ((void *) pz_data);
66c3d31fe1Smrg               return (char *) NULL;
67c3d31fe1Smrg             }
68c3d31fe1Smrg         }
69c3d31fe1Smrg 
70c3d31fe1Smrg       space_left -= size_read;
71c3d31fe1Smrg       space_used += size_read;
72c3d31fe1Smrg     } while (! feof (fp));
73c3d31fe1Smrg 
74c3d31fe1Smrg   pz_data = XRESIZEVEC (char, pz_data, space_used+1 );
75c3d31fe1Smrg   pz_data[ space_used ] = NUL;
76c3d31fe1Smrg 
77c3d31fe1Smrg   return pz_data;
78c3d31fe1Smrg }
79c3d31fe1Smrg 
80c3d31fe1Smrg #ifdef IS_CXX_HEADER_NEEDED
81c3d31fe1Smrg t_bool
is_cxx_header(tCC * fname,tCC * text)82c3d31fe1Smrg is_cxx_header (tCC* fname, tCC* text)
83c3d31fe1Smrg {
84c3d31fe1Smrg   /*  First, check to see if the file is in a C++ directory */
85c3d31fe1Smrg   for (;;)
86c3d31fe1Smrg     {
87c3d31fe1Smrg       switch (*(fname++))
88c3d31fe1Smrg         {
89c3d31fe1Smrg         case 'C': /* check for "CC/" */
90c3d31fe1Smrg           if ((fname[0] == 'C') && (fname[1] == '/'))
91c3d31fe1Smrg             return BOOL_TRUE;
92c3d31fe1Smrg           break;
93c3d31fe1Smrg 
94c3d31fe1Smrg         case 'x': /* check for "xx/" */
95c3d31fe1Smrg           if ((fname[0] == 'x') && (fname[1] == '/'))
96c3d31fe1Smrg             return BOOL_TRUE;
97c3d31fe1Smrg           break;
98c3d31fe1Smrg 
99c3d31fe1Smrg         case '+': /* check for "++" */
100c3d31fe1Smrg           if (fname[0] == '+')
101c3d31fe1Smrg             return BOOL_TRUE;
102c3d31fe1Smrg           break;
103c3d31fe1Smrg 
104c3d31fe1Smrg         case NUL:
105c3d31fe1Smrg           goto not_cxx_name;
106c3d31fe1Smrg         }
107c3d31fe1Smrg     } not_cxx_name:;
108c3d31fe1Smrg 
109c3d31fe1Smrg   /* Or it might contain one of several phrases which indicate C++ code.
110c3d31fe1Smrg      Currently recognized are:
111c3d31fe1Smrg      extern "C++"
112c3d31fe1Smrg      -*- (Mode: )? C++ -*-   (emacs mode marker)
113c3d31fe1Smrg      template <
114c3d31fe1Smrg    */
115c3d31fe1Smrg     {
116c3d31fe1Smrg       tSCC cxxpat[] = "\
117c3d31fe1Smrg extern[ \t]*\"C\\+\\+\"|\
118c3d31fe1Smrg -\\*-[ \t]*([mM]ode:[ \t]*)?[cC]\\+\\+[; \t]*-\\*-|\
119c3d31fe1Smrg template[ \t]*<|\
120c3d31fe1Smrg ^[ \t]*class[ \t]|\
121c3d31fe1Smrg (public|private|protected):|\
122c3d31fe1Smrg ^[ \t]*#[ \t]*pragma[ \t]+(interface|implementation)\
123c3d31fe1Smrg ";
124c3d31fe1Smrg       static regex_t cxxre;
125c3d31fe1Smrg       static int compiled;
126c3d31fe1Smrg 
127c3d31fe1Smrg       if (!compiled)
128c3d31fe1Smrg 	compile_re (cxxpat, &cxxre, 0, "contents check", "is_cxx_header");
129c3d31fe1Smrg 
130c3d31fe1Smrg       if (xregexec (&cxxre, text, 0, 0, 0) == 0)
131c3d31fe1Smrg 	return BOOL_TRUE;
132c3d31fe1Smrg     }
133c3d31fe1Smrg 
134c3d31fe1Smrg   return BOOL_FALSE;
135c3d31fe1Smrg }
136c3d31fe1Smrg #endif /* CXX_TYPE_NEEDED */
137c3d31fe1Smrg 
138c3d31fe1Smrg #ifdef SKIP_QUOTE_NEEDED
139c3d31fe1Smrg /*
140c3d31fe1Smrg  *  Skip over a quoted string.  Single quote strings may
141c3d31fe1Smrg  *  contain multiple characters if the first character is
142c3d31fe1Smrg  *  a backslash.  Especially a backslash followed by octal digits.
143c3d31fe1Smrg  *  We are not doing a correctness syntax check here.
144c3d31fe1Smrg  */
145c3d31fe1Smrg tCC*
skip_quote(char q,char * text)146c3d31fe1Smrg skip_quote(char q, char* text )
147c3d31fe1Smrg {
148c3d31fe1Smrg   for (;;)
149c3d31fe1Smrg     {
150c3d31fe1Smrg       char ch = *(text++);
151c3d31fe1Smrg       switch (ch)
152c3d31fe1Smrg         {
153c3d31fe1Smrg         case '\\':
154c3d31fe1Smrg           text++; /* skip over whatever character follows */
155c3d31fe1Smrg           break;
156c3d31fe1Smrg 
157c3d31fe1Smrg         case '"':
158c3d31fe1Smrg         case '\'':
159c3d31fe1Smrg           if (ch != q)
160c3d31fe1Smrg             break;
161c3d31fe1Smrg           /*FALLTHROUGH*/
162c3d31fe1Smrg 
163c3d31fe1Smrg         case '\n':
164c3d31fe1Smrg         case NUL:
165c3d31fe1Smrg           goto skip_done;
166c3d31fe1Smrg         }
167c3d31fe1Smrg     } skip_done:;
168c3d31fe1Smrg 
169c3d31fe1Smrg   return text;
170c3d31fe1Smrg }
171c3d31fe1Smrg #endif /* SKIP_QUOTE_NEEDED */
172c3d31fe1Smrg 
173c3d31fe1Smrg /* * * * * * * * * * * * *
174c3d31fe1Smrg 
175c3d31fe1Smrg    Compile one regular expression pattern for later use.  PAT contains
176c3d31fe1Smrg    the pattern, RE points to a regex_t structure (which should have
177c3d31fe1Smrg    been bzeroed).  MATCH is 1 if we need to know where the regex
178c3d31fe1Smrg    matched, 0 if not. If xregcomp fails, prints an error message and
179c3d31fe1Smrg    aborts; E1 and E2 are strings to shove into the error message.
180c3d31fe1Smrg 
181c3d31fe1Smrg    The patterns we search for are all egrep patterns.
182c3d31fe1Smrg    REG_EXTENDED|REG_NEWLINE produces identical regex syntax/semantics
183c3d31fe1Smrg    to egrep (verified from 4.4BSD Programmer's Reference Manual).  */
184c3d31fe1Smrg void
compile_re(tCC * pat,regex_t * re,int match,tCC * e1,tCC * e2)185c3d31fe1Smrg compile_re( tCC* pat, regex_t* re, int match, tCC* e1, tCC* e2 )
186c3d31fe1Smrg {
187c3d31fe1Smrg   tSCC z_bad_comp[] = "fixincl ERROR:  cannot compile %s regex for %s\n\
188c3d31fe1Smrg \texpr = `%s'\n\terror %s\n";
189c3d31fe1Smrg   int flags, err;
190c3d31fe1Smrg 
191c3d31fe1Smrg   flags = (match ? REG_EXTENDED|REG_NEWLINE
192c3d31fe1Smrg 	   : REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
193c3d31fe1Smrg   err = xregcomp (re, pat, flags);
194c3d31fe1Smrg 
195c3d31fe1Smrg   if (err)
196c3d31fe1Smrg     {
197c3d31fe1Smrg       char rerrbuf[1024];
198c3d31fe1Smrg       regerror (err, re, rerrbuf, 1024);
199c3d31fe1Smrg       fprintf (stderr, z_bad_comp, e1, e2, pat, rerrbuf);
200c3d31fe1Smrg       exit (EXIT_FAILURE);
201c3d31fe1Smrg     }
202c3d31fe1Smrg }
203c3d31fe1Smrg 
204c3d31fe1Smrg /* * * * * * * * * * * * *
205c3d31fe1Smrg 
206c3d31fe1Smrg    Helper routine and data for the machine_name test and fix.  */
207c3d31fe1Smrg 
208c3d31fe1Smrg tSCC mn_label_pat[] = "^[ \t]*#[ \t]*(if|ifdef|ifndef)[ \t]+";
209c3d31fe1Smrg static regex_t mn_label_re;
210c3d31fe1Smrg static regex_t mn_name_re;
211c3d31fe1Smrg 
212c3d31fe1Smrg static int mn_compiled = 0;
213c3d31fe1Smrg 
214c3d31fe1Smrg t_bool
mn_get_regexps(regex_t ** label_re,regex_t ** name_re,tCC * who)215c3d31fe1Smrg mn_get_regexps(regex_t** label_re, regex_t** name_re, tCC* who )
216c3d31fe1Smrg {
217c3d31fe1Smrg   if (! pz_mn_name_pat)
218c3d31fe1Smrg     return BOOL_FALSE;
219c3d31fe1Smrg 
220c3d31fe1Smrg   if (! mn_compiled)
221c3d31fe1Smrg     {
222c3d31fe1Smrg       compile_re (mn_label_pat, &mn_label_re, 1, "label pattern", who);
223c3d31fe1Smrg       compile_re (pz_mn_name_pat, &mn_name_re, 1, "name pattern", who);
224c3d31fe1Smrg       mn_compiled++;
225c3d31fe1Smrg     }
226c3d31fe1Smrg   *label_re = &mn_label_re;
227c3d31fe1Smrg   *name_re = &mn_name_re;
228c3d31fe1Smrg   return BOOL_TRUE;
229c3d31fe1Smrg }
230c3d31fe1Smrg 
231c3d31fe1Smrg 
232c3d31fe1Smrg #ifdef SEPARATE_FIX_PROC
233c3d31fe1Smrg 
234c3d31fe1Smrg char*
make_raw_shell_str(char * pz_d,tCC * pz_s,size_t smax)235c3d31fe1Smrg make_raw_shell_str( char* pz_d, tCC* pz_s, size_t smax )
236c3d31fe1Smrg {
237c3d31fe1Smrg   tSCC zQ[] = "'\\''";
238c3d31fe1Smrg   size_t     dtaSize;
239c3d31fe1Smrg   char*      pz_d_start = pz_d;
240c3d31fe1Smrg 
241c3d31fe1Smrg   smax--; /* adjust for trailing NUL */
242c3d31fe1Smrg 
243c3d31fe1Smrg   dtaSize = strlen( pz_s ) + 3;
244c3d31fe1Smrg 
245c3d31fe1Smrg   {
246c3d31fe1Smrg     const char* pz = pz_s - 1;
247c3d31fe1Smrg 
248c3d31fe1Smrg     for (;;) {
249c3d31fe1Smrg       pz = strchr( pz+1, '\'' );
250c3d31fe1Smrg       if (pz == (char*)NULL)
251c3d31fe1Smrg         break;
252c3d31fe1Smrg       dtaSize += sizeof( zQ )-1;
253c3d31fe1Smrg     }
254c3d31fe1Smrg   }
255c3d31fe1Smrg   if (dtaSize > smax)
256c3d31fe1Smrg     return (char*)NULL;
257c3d31fe1Smrg 
258c3d31fe1Smrg   *(pz_d++) = '\'';
259c3d31fe1Smrg 
260c3d31fe1Smrg   for (;;) {
261c3d31fe1Smrg     if ((size_t) (pz_d - pz_d_start) >= smax)
262c3d31fe1Smrg       return (char*)NULL;
263c3d31fe1Smrg     switch (*(pz_d++) = *(pz_s++)) {
264c3d31fe1Smrg     case NUL:
265c3d31fe1Smrg       goto loopDone;
266c3d31fe1Smrg 
267c3d31fe1Smrg     case '\'':
268c3d31fe1Smrg       if ((size_t) (pz_d - pz_d_start) >= smax - sizeof( zQ )-1)
269c3d31fe1Smrg 	return (char*)NULL;
270c3d31fe1Smrg       strcpy( pz_d-1, zQ );
271c3d31fe1Smrg       pz_d += sizeof( zQ )-2;
272c3d31fe1Smrg     }
273c3d31fe1Smrg   } loopDone:;
274c3d31fe1Smrg   pz_d[-1] = '\'';
275c3d31fe1Smrg   *pz_d    = NUL;
276c3d31fe1Smrg 
277c3d31fe1Smrg   return pz_d;
278c3d31fe1Smrg }
279c3d31fe1Smrg 
280c3d31fe1Smrg #endif
281*6a5c9aabSmrg 
282*6a5c9aabSmrg #if defined(__MINGW32__)
283*6a5c9aabSmrg void
fix_path_separators(char * p)284*6a5c9aabSmrg fix_path_separators (char* p)
285*6a5c9aabSmrg {
286*6a5c9aabSmrg     while (p != NULL)
287*6a5c9aabSmrg       {
288*6a5c9aabSmrg         p = strchr (p, '\\');
289*6a5c9aabSmrg         if (p != NULL)
290*6a5c9aabSmrg           {
291*6a5c9aabSmrg             *p = '/';
292*6a5c9aabSmrg             ++p;
293*6a5c9aabSmrg           }
294*6a5c9aabSmrg       }
295*6a5c9aabSmrg }
296*6a5c9aabSmrg 
297*6a5c9aabSmrg /* Count number of needle character ocurrences in str */
298*6a5c9aabSmrg static int
count_occurrences_of_char(char * str,char needle)299*6a5c9aabSmrg count_occurrences_of_char (char* str, char needle)
300*6a5c9aabSmrg {
301*6a5c9aabSmrg   int cnt = 0;
302*6a5c9aabSmrg 
303*6a5c9aabSmrg   while (str)
304*6a5c9aabSmrg     {
305*6a5c9aabSmrg        str = strchr (str, needle);
306*6a5c9aabSmrg        if (str)
307*6a5c9aabSmrg          {
308*6a5c9aabSmrg            ++str;
309*6a5c9aabSmrg            ++cnt;
310*6a5c9aabSmrg          }
311*6a5c9aabSmrg     }
312*6a5c9aabSmrg 
313*6a5c9aabSmrg   return cnt;
314*6a5c9aabSmrg }
315*6a5c9aabSmrg 
316*6a5c9aabSmrg /* On Mingw32, system function will just start cmd by default.
317*6a5c9aabSmrg    Call system function, but prepend ${CONFIG_SHELL} or ${SHELL} -c to the command,
318*6a5c9aabSmrg    replace newlines with '$'\n'', enclose command with double quotes
319*6a5c9aabSmrg    and escape special characters which were originally enclosed in single quotes.
320*6a5c9aabSmrg  */
321*6a5c9aabSmrg int
system_with_shell(char * s)322*6a5c9aabSmrg system_with_shell (char* s)
323*6a5c9aabSmrg {
324*6a5c9aabSmrg   static const char z_shell_start_args[] = " -c \"";
325*6a5c9aabSmrg   static const char z_shell_end_args[] = "\"";
326*6a5c9aabSmrg   static const char z_shell_newline[] = "'$'\\n''";
327*6a5c9aabSmrg 
328*6a5c9aabSmrg   /* Use configured shell if present */
329*6a5c9aabSmrg   char *env_shell = getenv ("CONFIG_SHELL");
330*6a5c9aabSmrg   int newline_cnt = count_occurrences_of_char (s, '\n');
331*6a5c9aabSmrg   int escapes_cnt  = count_occurrences_of_char( s, '\\')
332*6a5c9aabSmrg                       + count_occurrences_of_char (s, '"')
333*6a5c9aabSmrg                       + count_occurrences_of_char (s, '`');
334*6a5c9aabSmrg   char *long_cmd;
335*6a5c9aabSmrg   char *cmd_endp;
336*6a5c9aabSmrg   int sys_result;
337*6a5c9aabSmrg   char *s_scan;
338*6a5c9aabSmrg   int in_quotes;
339*6a5c9aabSmrg 
340*6a5c9aabSmrg   if (env_shell == NULL)
341*6a5c9aabSmrg     env_shell = getenv ("SHELL");
342*6a5c9aabSmrg 
343*6a5c9aabSmrg   /* If neither CONFIGURED_SHELL nor SHELL is set, just call standard system function */
344*6a5c9aabSmrg   if (env_shell == NULL)
345*6a5c9aabSmrg     return system (s);
346*6a5c9aabSmrg 
347*6a5c9aabSmrg   /* Allocate enough memory to fit newly created command string */
348*6a5c9aabSmrg   long_cmd = XNEWVEC (char, strlen (env_shell)
349*6a5c9aabSmrg                       + strlen (z_shell_start_args)
350*6a5c9aabSmrg                       + strlen (s)
351*6a5c9aabSmrg                       + newline_cnt * (strlen (z_shell_newline) - 1)
352*6a5c9aabSmrg                       + escapes_cnt
353*6a5c9aabSmrg                       + strlen (z_shell_end_args)
354*6a5c9aabSmrg                       + 1);
355*6a5c9aabSmrg 
356*6a5c9aabSmrg   /* Start with ${SHELL} */
357*6a5c9aabSmrg   strcpy (long_cmd, env_shell);
358*6a5c9aabSmrg   cmd_endp = long_cmd + strlen (long_cmd);
359*6a5c9aabSmrg 
360*6a5c9aabSmrg   /* Opening quote */
361*6a5c9aabSmrg   strcpy (cmd_endp, z_shell_start_args);
362*6a5c9aabSmrg   cmd_endp += strlen (z_shell_start_args);
363*6a5c9aabSmrg 
364*6a5c9aabSmrg   /* Replace newlines and escape special chars */
365*6a5c9aabSmrg   in_quotes = 0;
366*6a5c9aabSmrg   for (s_scan = s; *s_scan; ++s_scan)
367*6a5c9aabSmrg     {
368*6a5c9aabSmrg       switch (*s_scan)
369*6a5c9aabSmrg         {
370*6a5c9aabSmrg           case '\n':
371*6a5c9aabSmrg             if (in_quotes)
372*6a5c9aabSmrg               {
373*6a5c9aabSmrg                 /* Replace newline inside quotes with '$'\n'' */
374*6a5c9aabSmrg                 strcpy (cmd_endp, z_shell_newline);
375*6a5c9aabSmrg                 cmd_endp += strlen (z_shell_newline);
376*6a5c9aabSmrg               }
377*6a5c9aabSmrg             else
378*6a5c9aabSmrg               {
379*6a5c9aabSmrg                 /* Replace newlines outside quotes with ; and merge subsequent newlines */
380*6a5c9aabSmrg                 *(cmd_endp++) = ';';
381*6a5c9aabSmrg                 *(cmd_endp++) = ' ';
382*6a5c9aabSmrg                 while (*(s_scan + 1) == '\n' || *(s_scan + 1) == ' ' || *(s_scan + 1) == '\t')
383*6a5c9aabSmrg                   ++s_scan;
384*6a5c9aabSmrg               }
385*6a5c9aabSmrg             break;
386*6a5c9aabSmrg           case '\'':
387*6a5c9aabSmrg             /* Escape single quote and toggle in_quotes flag */
388*6a5c9aabSmrg             in_quotes = !in_quotes;
389*6a5c9aabSmrg             *(cmd_endp++) = *s_scan;
390*6a5c9aabSmrg             break;
391*6a5c9aabSmrg           case '\\':
392*6a5c9aabSmrg           case '`':
393*6a5c9aabSmrg             /* Escape backslash and backtick inside quotes */
394*6a5c9aabSmrg             if (in_quotes)
395*6a5c9aabSmrg                *(cmd_endp++) = '\\';
396*6a5c9aabSmrg             *(cmd_endp++) = *s_scan;
397*6a5c9aabSmrg             break;
398*6a5c9aabSmrg           case '"':
399*6a5c9aabSmrg             /* Escape double quotes always */
400*6a5c9aabSmrg             *(cmd_endp++) = '\\';
401*6a5c9aabSmrg             *(cmd_endp++) = *s_scan;
402*6a5c9aabSmrg             break;
403*6a5c9aabSmrg           default:
404*6a5c9aabSmrg             *(cmd_endp++) = *s_scan;
405*6a5c9aabSmrg         }
406*6a5c9aabSmrg     }
407*6a5c9aabSmrg 
408*6a5c9aabSmrg   /* Closing quote */
409*6a5c9aabSmrg   strcpy (cmd_endp, z_shell_end_args);
410*6a5c9aabSmrg 
411*6a5c9aabSmrg   sys_result = system (long_cmd);
412*6a5c9aabSmrg 
413*6a5c9aabSmrg   free (long_cmd);
414*6a5c9aabSmrg 
415*6a5c9aabSmrg   return sys_result;
416*6a5c9aabSmrg }
417*6a5c9aabSmrg 
418*6a5c9aabSmrg #endif /* defined(__MINGW32__) */
419