Reactos
1/*
2 * Utility routines
3 *
4 * Copyright 1998 Bertho A. Stultiens
5 * Copyright 2002 Ove Kaaven
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include "config.h"
23
24#include <assert.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <stdarg.h>
28#include <string.h>
29#include <ctype.h>
30
31#include "widl.h"
32#include "utils.h"
33#include "parser.h"
34
35void error_at( const struct location *where, const char *s, ... )
36{
37 char buffer[1024];
38
39 va_list ap;
40 va_start( ap, s );
41 vsnprintf( buffer, sizeof(buffer), s, ap );
42 va_end( ap );
43
44 parser_error( where, buffer );
45 exit( 1 );
46}
47
48void error(const char *s, ...)
49{
50 va_list ap;
51 va_start(ap, s);
52 fprintf(stderr, "error: ");
53 vfprintf(stderr, s, ap);
54 va_end(ap);
55 exit(2);
56}
57
58void warning(const char *s, ...)
59{
60 va_list ap;
61 va_start(ap, s);
62 fprintf(stderr, "warning: ");
63 vfprintf(stderr, s, ap);
64 va_end(ap);
65}
66
67void warning_at( const struct location *where, const char *s, ... )
68{
69 char buffer[1024];
70
71 va_list ap;
72 va_start( ap, s );
73 vsnprintf( buffer, sizeof(buffer), s, ap );
74 va_end( ap );
75
76 parser_warning( where, buffer );
77}
78
79void chat(const char *s, ...)
80{
81 if(debuglevel & DEBUGLEVEL_CHAT)
82 {
83 va_list ap;
84 va_start(ap, s);
85 fprintf(stderr, "chat: ");
86 vfprintf(stderr, s, ap);
87 va_end(ap);
88 }
89}
90
91size_t widl_getline(char **linep, size_t *lenp, FILE *fp)
92{
93 char *line = *linep;
94 size_t len = *lenp;
95 size_t n = 0;
96
97 if (!line)
98 {
99 len = 64;
100 line = xmalloc(len);
101 }
102
103 while (fgets(&line[n], len - n, fp))
104 {
105 n += strlen(&line[n]);
106 if (line[n - 1] == '\n')
107 break;
108 else if (n == len - 1)
109 {
110 len *= 2;
111 line = xrealloc(line, len);
112 }
113 }
114
115 *linep = line;
116 *lenp = len;
117 return n;
118}
119
120size_t strappend(char **buf, size_t *len, size_t pos, const char* fmt, ...)
121{
122 size_t size;
123 va_list ap;
124 char *ptr;
125 int n;
126
127 assert( buf && len );
128 assert( (*len == 0 && *buf == NULL) || (*len != 0 && *buf != NULL) );
129
130 if (*buf)
131 {
132 size = *len;
133 ptr = *buf;
134 }
135 else
136 {
137 size = 100;
138 ptr = xmalloc( size );
139 }
140
141 for (;;)
142 {
143 va_start( ap, fmt );
144 n = vsnprintf( ptr + pos, size - pos, fmt, ap );
145 va_end( ap );
146 if (n == -1) size *= 2;
147 else if (pos + (size_t)n >= size) size = pos + n + 1;
148 else break;
149 ptr = xrealloc( ptr, size );
150 }
151
152 *len = size;
153 *buf = ptr;
154 return n;
155}
156
157/*******************************************************************
158 * buffer management
159 *
160 * Function for writing to a memory buffer.
161 */
162
163unsigned char *output_buffer;
164size_t output_buffer_pos;
165size_t output_buffer_size;
166
167static struct resource
168{
169 unsigned char *data;
170 size_t size;
171} resources[16];
172static unsigned int nb_resources;
173
174static inline void put_resource_id( const char *str )
175{
176 if (str[0] != '#')
177 {
178 while (*str)
179 {
180 unsigned char ch = *str++;
181 put_word( toupper(ch) );
182 }
183 put_word( 0 );
184 }
185 else
186 {
187 put_word( 0xffff );
188 put_word( atoi( str + 1 ));
189 }
190}
191
192void add_output_to_resources( const char *type, const char *name )
193{
194 size_t data_size = output_buffer_pos;
195 size_t header_size = 5 * sizeof(unsigned int) + 2 * sizeof(unsigned short);
196
197 assert( nb_resources < ARRAY_SIZE( resources ));
198
199 if (type[0] != '#') header_size += (strlen( type ) + 1) * sizeof(unsigned short);
200 else header_size += 2 * sizeof(unsigned short);
201 if (name[0] != '#') header_size += (strlen( name ) + 1) * sizeof(unsigned short);
202 else header_size += 2 * sizeof(unsigned short);
203
204 header_size = (header_size + 3) & ~3;
205 align_output( 4 );
206 check_output_buffer_space( header_size );
207 resources[nb_resources].size = header_size + output_buffer_pos;
208 memmove( output_buffer + header_size, output_buffer, output_buffer_pos );
209
210 output_buffer_pos = 0;
211 put_dword( data_size ); /* ResSize */
212 put_dword( header_size ); /* HeaderSize */
213 put_resource_id( type ); /* ResType */
214 put_resource_id( name ); /* ResName */
215 align_output( 4 );
216 put_dword( 0 ); /* DataVersion */
217 put_word( 0 ); /* Memory options */
218 put_word( 0 ); /* Language */
219 put_dword( 0 ); /* Version */
220 put_dword( 0 ); /* Characteristics */
221
222 resources[nb_resources++].data = output_buffer;
223 init_output_buffer();
224}
225
226void flush_output_resources( const char *name )
227{
228 unsigned int i;
229
230 /* all output must have been saved with add_output_to_resources() first */
231 assert( !output_buffer_pos );
232
233 put_dword( 0 ); /* ResSize */
234 put_dword( 32 ); /* HeaderSize */
235 put_word( 0xffff ); /* ResType */
236 put_word( 0x0000 );
237 put_word( 0xffff ); /* ResName */
238 put_word( 0x0000 );
239 put_dword( 0 ); /* DataVersion */
240 put_word( 0 ); /* Memory options */
241 put_word( 0 ); /* Language */
242 put_dword( 0 ); /* Version */
243 put_dword( 0 ); /* Characteristics */
244
245 for (i = 0; i < nb_resources; i++)
246 {
247 put_data( resources[i].data, resources[i].size );
248 free( resources[i].data );
249 }
250 flush_output_buffer( name );
251 nb_resources = 0;
252}
253
254/* pointer-sized word */
255void put_pword( unsigned int val )
256{
257 if (pointer_size == 8) put_qword( val );
258 else put_dword( val );
259}
260
261void put_str( int indent, const char *format, ... )
262{
263 int n;
264 va_list args;
265
266 check_output_buffer_space( 4 * indent );
267 memset( output_buffer + output_buffer_pos, ' ', 4 * indent );
268 output_buffer_pos += 4 * indent;
269
270 for (;;)
271 {
272 size_t size = output_buffer_size - output_buffer_pos;
273 va_start( args, format );
274 n = vsnprintf( (char *)output_buffer + output_buffer_pos, size, format, args );
275 va_end( args );
276 if (n == -1) size *= 2;
277 else if ((size_t)n >= size) size = n + 1;
278 else
279 {
280 output_buffer_pos += n;
281 return;
282 }
283 check_output_buffer_space( size );
284 }
285}