4 * Copyright 1998,2000 Bertho A. Stultiens
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but 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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
36 #define SUPPRESS_YACC_ERROR_MESSAGE
38 static void generic_msg(const char *s
, const char *t
, va_list ap
)
40 fprintf(stderr
, "%s:%d:%d: %s: ", input_name
? input_name
: "stdin", line_number
, char_number
, t
);
41 vfprintf(stderr
, s
, ap
);
45 * The yyerror routine should not exit because we use the error-token
46 * to determine the syntactic error in the source. However, YACC
47 * uses the same routine to print an error just before the error
49 * The extra routine 'xyyerror' is used to exit after giving a real
52 int mcy_error(const char *s
, ...)
54 #ifndef SUPPRESS_YACC_ERROR_MESSAGE
57 generic_msg(s
, "Yacc error", ap
);
63 int xyyerror(const char *s
, ...)
67 generic_msg(s
, "Error", ap
);
73 int mcy_warning(const char *s
, ...)
77 generic_msg(s
, "Warning", ap
);
82 void internal_error(const char *file
, int line
, const char *s
, ...)
86 fprintf(stderr
, "Internal error (please report) %s %d: ", file
, line
);
87 vfprintf(stderr
, s
, ap
);
92 void fatal_perror( const char *msg
, ... )
95 va_start( valist
, msg
);
96 fprintf(stderr
, "Error: ");
97 vfprintf( stderr
, msg
, valist
);
103 void error(const char *s
, ...)
107 fprintf(stderr
, "Error: ");
108 vfprintf(stderr
, s
, ap
);
113 void warning(const char *s
, ...)
117 fprintf(stderr
, "Warning: ");
118 vfprintf(stderr
, s
, ap
);
122 char *dup_basename(const char *name
, const char *ext
)
125 int extlen
= strlen(ext
);
132 slash
= strrchr(name
, '/');
136 namelen
= strlen(name
);
138 /* +4 for later extension and +1 for '\0' */
139 base
= xmalloc(namelen
+4 +1);
141 if(!strcasecmp(name
+ namelen
-extlen
, ext
))
143 base
[namelen
- extlen
] = '\0';
148 void *xmalloc(size_t size
)
156 error("Virtual memory exhausted.\n");
158 memset(res
, 0x55, size
);
163 void *xrealloc(void *p
, size_t size
)
168 res
= realloc(p
, size
);
171 error("Virtual memory exhausted.\n");
176 char *xstrdup(const char *str
)
181 s
= xmalloc(strlen(str
)+1);
182 return strcpy(s
, str
);
185 char *strmake( const char* fmt
, ... )
193 char *p
= xmalloc( size
);
195 n
= vsnprintf( p
, size
, fmt
, ap
);
197 if (n
== -1) size
*= 2;
198 else if ((size_t)n
>= size
) size
= n
+ 1;
204 int strendswith( const char *str
, const char *end
)
208 return l
>= m
&& !strcmp( str
+ l
- m
, end
);
211 int unistrlen(const WCHAR
*s
)
214 for(n
= 0; *s
; n
++, s
++)
219 WCHAR
*unistrcpy(WCHAR
*dst
, const WCHAR
*src
)
228 WCHAR
*xunistrdup(const WCHAR
* str
)
233 s
= xmalloc((unistrlen(str
)+1) * sizeof(WCHAR
));
234 return unistrcpy(s
, str
);
237 int unistricmp(const WCHAR
*s1
, const WCHAR
*s2
)
241 static const char warn
[] = "Don't know the uppercase equivalent of non ascii characters;"
242 "comparison might yield wrong results";
245 if((*s1
& 0xffff) > 0x7f || (*s2
& 0xffff) > 0x7f)
255 i
= toupper(*s1
++) - toupper(*s2
++);
260 if((*s1
& 0xffff) > 0x7f || (*s2
& 0xffff) > 0x7f)
267 return toupper(*s1
) - toupper(*s2
);
270 int unistrcmp(const WCHAR
*s1
, const WCHAR
*s2
)
283 WCHAR
*utf8_to_unicode( const char *src
, int srclen
, int *dstlen
)
285 static const char utf8_length
[128] =
287 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
288 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
289 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
290 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
291 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
292 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
293 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
294 3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0 /* 0xf0-0xff */
296 static const unsigned char utf8_mask
[4] = { 0x7f, 0x1f, 0x0f, 0x07 };
298 const char *srcend
= src
+ srclen
;
302 dst
= ret
= xmalloc( (srclen
+ 1) * sizeof(WCHAR
) );
305 unsigned char ch
= *src
++;
306 if (ch
< 0x80) /* special fast case for 7-bit ASCII */
311 len
= utf8_length
[ch
- 0x80];
312 if (len
&& src
+ len
<= srcend
)
314 res
= ch
& utf8_mask
[len
];
318 if ((ch
= *src
^ 0x80) >= 0x40) break;
319 res
= (res
<< 6) | ch
;
321 if (res
< 0x10) break;
323 if ((ch
= *src
^ 0x80) >= 0x40) break;
324 res
= (res
<< 6) | ch
;
325 if (res
>= 0x110000 >> 6) break;
327 if (res
< 0x20) break;
328 if (res
>= 0xd800 >> 6 && res
<= 0xdfff >> 6) break;
330 if ((ch
= *src
^ 0x80) >= 0x40) break;
331 res
= (res
<< 6) | ch
;
333 if (res
< 0x80) break;
334 if (res
<= 0xffff) *dst
++ = res
;
338 *dst
++ = 0xd800 | (res
>> 10);
339 *dst
++ = 0xdc00 | (res
& 0x3ff);
351 char *unicode_to_utf8( const WCHAR
*src
, int srclen
, int *dstlen
)
355 dst
= ret
= xmalloc( srclen
* 3 + 1 );
356 for ( ; srclen
; srclen
--, src
++)
358 unsigned int ch
= *src
;
360 if (ch
< 0x80) /* 0x00-0x7f: 1 byte */
365 if (ch
< 0x800) /* 0x80-0x7ff: 2 bytes */
367 dst
[1] = 0x80 | (ch
& 0x3f);
373 if (ch
>= 0xd800 && ch
<= 0xdbff && srclen
> 1 && src
[1] >= 0xdc00 && src
[1] <= 0xdfff)
375 /* 0x10000-0x10ffff: 4 bytes */
376 ch
= 0x10000 + ((ch
& 0x3ff) << 10) + (src
[1] & 0x3ff);
377 dst
[3] = 0x80 | (ch
& 0x3f);
379 dst
[2] = 0x80 | (ch
& 0x3f);
381 dst
[1] = 0x80 | (ch
& 0x3f);
389 if (ch
>= 0xd800 && ch
<= 0xdfff) ch
= 0xfffd; /* invalid surrogate pair */
391 /* 0x800-0xffff: 3 bytes */
392 dst
[2] = 0x80 | (ch
& 0x3f);
394 dst
[1] = 0x80 | (ch
& 0x3f);
406 int is_valid_codepage(int id
)
408 return IsValidCodePage( id
);
411 WCHAR
*codepage_to_unicode( int codepage
, const char *src
, int srclen
, int *dstlen
)
413 WCHAR
*dst
= xmalloc( (srclen
+ 1) * sizeof(WCHAR
) );
414 DWORD ret
= MultiByteToWideChar( codepage
, MB_ERR_INVALID_CHARS
, src
, srclen
, dst
, srclen
);
415 if (!ret
) return NULL
;
425 unsigned short codepage
;
426 unsigned short unidef
;
427 unsigned short trans_unidef
;
428 unsigned short *cp2uni
;
429 unsigned short *dbcs_offsets
;
432 static struct nls_info nlsinfo
[128];
434 static void init_nls_info( struct nls_info
*info
, unsigned short *ptr
)
436 unsigned short hdr_size
= ptr
[0];
438 info
->codepage
= ptr
[1];
439 info
->unidef
= ptr
[4];
440 info
->trans_unidef
= ptr
[6];
442 info
->cp2uni
= ++ptr
;
444 if (*ptr
++) ptr
+= 256; /* glyph table */
445 info
->dbcs_offsets
= *ptr
? ptr
+ 1 : NULL
;
448 static const struct nls_info
*get_nls_info( unsigned int codepage
)
451 unsigned short *data
;
456 for (i
= 0; i
< ARRAY_SIZE(nlsinfo
) && nlsinfo
[i
].codepage
; i
++)
457 if (nlsinfo
[i
].codepage
== codepage
) return &nlsinfo
[i
];
459 assert( i
< ARRAY_SIZE(nlsinfo
) );
461 for (i
= 0; nlsdirs
[i
]; i
++)
463 path
= strmake( "%s/c_%03u.nls", nlsdirs
[i
], codepage
);
464 if ((fd
= open( path
, O_RDONLY
)) != -1) break;
467 if (!nlsdirs
[i
]) return NULL
;
470 data
= xmalloc( st
.st_size
);
471 if (read( fd
, data
, st
.st_size
) != st
.st_size
) error( "failed to load %s\n", path
);
474 init_nls_info( &nlsinfo
[i
], data
);
478 int is_valid_codepage(int cp
)
480 return cp
== CP_UTF8
|| get_nls_info( cp
);
483 WCHAR
*codepage_to_unicode( int codepage
, const char *src
, int srclen
, int *dstlen
)
485 const struct nls_info
*info
= get_nls_info( codepage
);
487 WCHAR dbch
, *dst
= xmalloc( (srclen
+ 1) * sizeof(WCHAR
) );
489 if (!info
) error( "codepage %u not supported\n", codepage
);
491 if (info
->dbcs_offsets
)
493 for (i
= 0; srclen
; i
++, srclen
--, src
++)
495 unsigned short off
= info
->dbcs_offsets
[(unsigned char)*src
];
498 if (srclen
== 1) return NULL
;
499 dbch
= (src
[0] << 8) | (unsigned char)src
[1];
502 dst
[i
] = info
->dbcs_offsets
[off
+ (unsigned char)*src
];
503 if (dst
[i
] == info
->unidef
&& dbch
!= info
->trans_unidef
) return NULL
;
507 dst
[i
] = info
->cp2uni
[(unsigned char)*src
];
508 if (dst
[i
] == info
->unidef
&& *src
!= info
->trans_unidef
) return NULL
;
514 for (i
= 0; i
< srclen
; i
++)
516 dst
[i
] = info
->cp2uni
[(unsigned char)src
[i
]];
517 if (dst
[i
] == info
->unidef
&& src
[i
] != info
->trans_unidef
) return NULL
;
527 /*******************************************************************
530 * Function for writing to a memory buffer.
533 int byte_swapped
= 0;
534 unsigned char *output_buffer
;
535 size_t output_buffer_pos
;
536 size_t output_buffer_size
;
538 static void check_output_buffer_space( size_t size
)
540 if (output_buffer_pos
+ size
>= output_buffer_size
)
542 output_buffer_size
= max( output_buffer_size
* 2, output_buffer_pos
+ size
);
543 output_buffer
= xrealloc( output_buffer
, output_buffer_size
);
547 void init_output_buffer(void)
549 output_buffer_size
= 1024;
550 output_buffer_pos
= 0;
551 output_buffer
= xmalloc( output_buffer_size
);
554 void flush_output_buffer( const char *name
)
556 int fd
= open( name
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_BINARY
, 0666 );
557 if (fd
== -1) error( "Error creating %s\n", name
);
558 if (write( fd
, output_buffer
, output_buffer_pos
) != output_buffer_pos
)
559 error( "Error writing to %s\n", name
);
561 free( output_buffer
);
564 void put_data( const void *data
, size_t size
)
566 check_output_buffer_space( size
);
567 memcpy( output_buffer
+ output_buffer_pos
, data
, size
);
568 output_buffer_pos
+= size
;
571 void put_byte( unsigned char val
)
573 check_output_buffer_space( 1 );
574 output_buffer
[output_buffer_pos
++] = val
;
577 void put_word( unsigned short val
)
579 if (byte_swapped
) val
= (val
<< 8) | (val
>> 8);
580 put_data( &val
, sizeof(val
) );
583 void put_dword( unsigned int val
)
586 val
= ((val
<< 24) | ((val
<< 8) & 0x00ff0000) | ((val
>> 8) & 0x0000ff00) | (val
>> 24));
587 put_data( &val
, sizeof(val
) );
590 void align_output( unsigned int align
)
592 size_t size
= align
- (output_buffer_pos
% align
);
594 if (size
== align
) return;
595 check_output_buffer_space( size
);
596 memset( output_buffer
+ output_buffer_pos
, 0, size
);
597 output_buffer_pos
+= size
;