parser.l 14.5 KB
Newer Older
1
/* -*-C-*-
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 * IDL Compiler
 *
 * Copyright 2002 Ove Kaaven
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
19 20 21
 */

%option stack
22
%option noinput nounput noyy_top_state
23
%option 8bit never-interactive prefix="parser_"
24 25 26 27

nl	\r?\n
ws	[ \f\t\r]
cident	[a-zA-Z_][0-9a-zA-Z_]*
28 29 30
u_suffix	(u|U)
l_suffix	(l|L)
int	[0-9]+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)?
31
hexd	[0-9a-fA-F]
32
hex	0(x|X){hexd}+({l_suffix}?{u_suffix}?|{u_suffix}?{l_suffix}?)?
33
uuid	{hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
34
double	[0-9]+\.[0-9]+([eE][+-]?[0-9]+)*
35 36

%x QUOTE
37
%x WSTRQUOTE
38 39
%x ATTR
%x PP_LINE
40 41 42

%{

43 44
#include "config.h"

45 46 47 48 49
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
Huw Davies's avatar
Huw Davies committed
50
#include <errno.h>
51
#include <limits.h>
52

53 54 55
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#else
56
#define YY_NO_UNISTD_H
57
#endif
58 59 60 61

#include "widl.h"
#include "utils.h"
#include "parser.h"
62
#include "wine/wpp.h"
63

64
#include "parser.tab.h"
65 66 67 68 69 70 71 72 73 74 75

extern char *temp_name;

static void addcchar(char c);
static char *get_buffered_cstring(void);

static char *cbuffer;
static int cbufidx;
static int cbufalloc = 0;

static int kw_token(const char *kw);
76
static int attr_token(const char *kw);
77 78 79 80

#define MAX_IMPORT_DEPTH 10
struct {
  YY_BUFFER_STATE state;
81 82
  char *input_name;
  int   line_number;
83 84 85 86
  char *temp_name;
} import_stack[MAX_IMPORT_DEPTH];
int import_stack_ptr = 0;

87 88 89 90 91 92 93 94 95 96 97 98 99
/* converts an integer in string form to an unsigned long and prints an error
 * on overflow */
static unsigned long xstrtoul(const char *nptr, char **endptr, int base)
{
    unsigned long l;

    errno = 0;
    l = strtoul(nptr, endptr, base);
    if (l == ULONG_MAX && errno == ERANGE)
        error_loc("integer constant %s is too large\n", nptr);
    return l;
}

100
UUID *parse_uuid(const char *u)
101
{
102
  UUID* uuid = xmalloc(sizeof(UUID));
103 104
  char b[3];
  /* it would be nice to use UuidFromStringA */
105 106 107
  uuid->Data1 = strtoul(u, NULL, 16);
  uuid->Data2 = strtoul(u+9, NULL, 16);
  uuid->Data3 = strtoul(u+14, NULL, 16);
108
  b[2] = 0;
109 110 111 112 113 114 115 116
  memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16);
  memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16);
  memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16);
  memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16);
  memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16);
  memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16);
  memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16);
  memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16);
117 118 119
  return uuid;
}

120 121 122 123 124 125 126 127
%}

/*
 **************************************************************************
 * The flexer starts here
 **************************************************************************
 */
%%
128 129
<INITIAL,ATTR>^{ws}*\#{ws}*	yy_push_state(PP_LINE);
<PP_LINE>[^\n]*         {
130 131 132 133 134
                            int lineno;
                            char *cptr, *fname;
                            yy_pop_state();
                            lineno = (int)strtol(yytext, &cptr, 10);
                            if(!lineno)
135
                                error_loc("Malformed '#...' line-directive; invalid linenumber\n");
136 137
                            fname = strchr(cptr, '"');
                            if(!fname)
138
                                error_loc("Malformed '#...' line-directive; missing filename\n");
139 140 141
                            fname++;
                            cptr = strchr(fname, '"');
                            if(!cptr)
142
                                error_loc("Malformed '#...' line-directive; missing terminating \"\n");
143 144 145 146 147
                            *cptr = '\0';
                            line_number = lineno - 1;  /* We didn't read the newline */
                            free( input_name );
                            input_name = xstrdup(fname);
                        }
148
<INITIAL,ATTR>\"	yy_push_state(QUOTE); cbufidx = 0;
149 150
<QUOTE>\"		{
				yy_pop_state();
151
				parser_lval.str = get_buffered_cstring();
152 153
				return aSTRING;
			}
154 155 156 157 158 159 160 161 162 163
<INITIAL,ATTR>L\"	yy_push_state(WSTRQUOTE);
<WSTRQUOTE>\"		{
				yy_pop_state();
				parser_lval.str = get_buffered_cstring();
				return aWSTRING;
			}
<QUOTE,WSTRQUOTE>\\\\	|
<QUOTE,WSTRQUOTE>\\\"	addcchar(yytext[1]);
<QUOTE,WSTRQUOTE>\\.	addcchar('\\'); addcchar(yytext[1]);
<QUOTE,WSTRQUOTE>.	addcchar(yytext[0]);
164 165 166 167
<INITIAL,ATTR>\[	yy_push_state(ATTR); return '[';
<ATTR>\]		yy_pop_state(); return ']';
<ATTR>{cident}		return attr_token(yytext);
<ATTR>{uuid}			{
168
				parser_lval.uuid = parse_uuid(yytext);
169 170
				return aUUID;
			}
171
<INITIAL,ATTR>{hex}	{
172
				parser_lval.num = xstrtoul(yytext, NULL, 0);
173 174
				return aHEXNUM;
			}
175
<INITIAL,ATTR>{int}	{
176
				parser_lval.num = xstrtoul(yytext, NULL, 0);
177 178
				return aNUM;
			}
179 180 181 182
<INITIAL>{double}	{
				parser_lval.dbl = strtod(yytext, NULL);
				return aDOUBLE;
			}
183
SAFEARRAY{ws}*/\(	return tSAFEARRAY;
184
{cident}		return kw_token(yytext);
185 186 187 188
<INITIAL,ATTR>\n	line_number++;
<INITIAL,ATTR>{ws}
<INITIAL,ATTR>\<\<	return SHL;
<INITIAL,ATTR>\>\>	return SHR;
189
<INITIAL,ATTR>\-\>	return MEMBERPTR;
190 191 192 193 194 195
<INITIAL,ATTR>==	return EQUALITY;
<INITIAL,ATTR>!=	return INEQUALITY;
<INITIAL,ATTR>\>=	return GREATEREQUAL;
<INITIAL,ATTR>\<=	return LESSEQUAL;
<INITIAL,ATTR>\|\|	return LOGICALOR;
<INITIAL,ATTR>&&	return LOGICALAND;
196
<INITIAL,ATTR>.		return yytext[0];
197
<<EOF>>			{
198
				if (import_stack_ptr)
199
					return aEOF;
200 201 202 203
				else yyterminate();
			}
%%

204 205
#ifndef parser_wrap
int parser_wrap(void)
206 207 208 209 210
{
	return 1;
}
#endif

211
struct keyword {
212 213
	const char *kw;
	int token;
214 215
};

216
/* This table MUST be alphabetically sorted on the kw field */
217
static const struct keyword keywords[] = {
218
	{"FALSE",			tFALSE},
219
	{"NULL",			tNULL},
220
	{"TRUE",			tTRUE},
221
	{"__cdecl",			tCDECL},
222
	{"__fastcall",			tFASTCALL},
223
	{"__int64",			tINT64},
224
	{"__pascal",			tPASCAL},
225
	{"__stdcall",			tSTDCALL},
226 227 228
	{"_cdecl",			tCDECL},
	{"_fastcall",			tFASTCALL},
	{"_pascal",			tPASCAL},
229 230 231 232
	{"_stdcall",			tSTDCALL},
	{"boolean",			tBOOLEAN},
	{"byte",			tBYTE},
	{"case",			tCASE},
233
	{"cdecl",			tCDECL},
234 235 236 237 238
	{"char",			tCHAR},
	{"coclass",			tCOCLASS},
	{"const",			tCONST},
	{"cpp_quote",			tCPPQUOTE},
	{"default",			tDEFAULT},
239
	{"dispinterface",		tDISPINTERFACE},
240 241
	{"double",			tDOUBLE},
	{"enum",			tENUM},
242
	{"error_status_t",		tERRORSTATUST},
243 244
	{"extern",			tEXTERN},
	{"float",			tFLOAT},
245
	{"handle_t",			tHANDLET},
246
	{"hyper",			tHYPER},
247 248
	{"import",			tIMPORT},
	{"importlib",			tIMPORTLIB},
249
	{"inline",			tINLINE},
250 251
	{"int",				tINT},
	{"interface",			tINTERFACE},
252
	{"library",			tLIBRARY},
253
	{"long",			tLONG},
254 255
	{"methods",			tMETHODS},
	{"module",			tMODULE},
256
	{"pascal",			tPASCAL},
257
	{"properties",			tPROPERTIES},
258
	{"register",			tREGISTER},
259 260 261
	{"short",			tSHORT},
	{"signed",			tSIGNED},
	{"sizeof",			tSIZEOF},
262
        {"small",			tSMALL},
263
	{"static",			tSTATIC},
264
	{"stdcall",			tSTDCALL},
265 266 267 268 269 270 271 272
	{"struct",			tSTRUCT},
	{"switch",			tSWITCH},
	{"typedef",			tTYPEDEF},
	{"union",			tUNION},
	{"unsigned",			tUNSIGNED},
	{"void",			tVOID},
	{"wchar_t",			tWCHAR},
};
273
#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
274

275 276 277
/* keywords only recognized in attribute lists
 * This table MUST be alphabetically sorted on the kw field
 */
278 279 280 281 282 283 284 285 286 287 288 289
static const struct keyword attr_keywords[] =
{
        {"aggregatable",                tAGGREGATABLE},
        {"allocate",                    tALLOCATE},
        {"appobject",                   tAPPOBJECT},
        {"async",                       tASYNC},
        {"async_uuid",                  tASYNCUUID},
        {"auto_handle",                 tAUTOHANDLE},
        {"bindable",                    tBINDABLE},
        {"broadcast",                   tBROADCAST},
        {"byte_count",                  tBYTECOUNT},
        {"call_as",                     tCALLAS},
290 291 292
        {"callback",                    tCALLBACK},
        {"code",                        tCODE},
        {"comm_status",                 tCOMMSTATUS},
293 294 295
        {"context_handle",              tCONTEXTHANDLE},
        {"context_handle_noserialize",  tCONTEXTHANDLENOSERIALIZE},
        {"context_handle_serialize",    tCONTEXTHANDLENOSERIALIZE},
296
        {"control",                     tCONTROL},
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
        {"defaultcollelem",             tDEFAULTCOLLELEM},
        {"defaultvalue",                tDEFAULTVALUE},
        {"defaultvtable",               tDEFAULTVTABLE},
        {"displaybind",                 tDISPLAYBIND},
        {"dllname",                     tDLLNAME},
        {"dual",                        tDUAL},
        {"endpoint",                    tENDPOINT},
        {"entry",                       tENTRY},
        {"explicit_handle",             tEXPLICITHANDLE},
        {"handle",                      tHANDLE},
        {"helpcontext",                 tHELPCONTEXT},
        {"helpfile",                    tHELPFILE},
        {"helpstring",                  tHELPSTRING},
        {"helpstringcontext",           tHELPSTRINGCONTEXT},
        {"helpstringdll",               tHELPSTRINGDLL},
        {"hidden",                      tHIDDEN},
        {"id",                          tID},
        {"idempotent",                  tIDEMPOTENT},
        {"iid_is",                      tIIDIS},
        {"immediatebind",               tIMMEDIATEBIND},
        {"implicit_handle",             tIMPLICITHANDLE},
        {"in",                          tIN},
319
        {"in_line",                     tIN_LINE},
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
        {"input_sync",                  tINPUTSYNC},
        {"lcid",                        tLCID},
        {"length_is",                   tLENGTHIS},
        {"local",                       tLOCAL},
        {"nonbrowsable",                tNONBROWSABLE},
        {"noncreatable",                tNONCREATABLE},
        {"nonextensible",               tNONEXTENSIBLE},
        {"object",                      tOBJECT},
        {"odl",                         tODL},
        {"oleautomation",               tOLEAUTOMATION},
        {"optional",                    tOPTIONAL},
        {"out",                         tOUT},
        {"pointer_default",             tPOINTERDEFAULT},
        {"propget",                     tPROPGET},
        {"propput",                     tPROPPUT},
        {"propputref",                  tPROPPUTREF},
        {"ptr",                         tPTR},
        {"public",                      tPUBLIC},
        {"range",                       tRANGE},
        {"readonly",                    tREADONLY},
        {"ref",                         tREF},
        {"requestedit",                 tREQUESTEDIT},
        {"restricted",                  tRESTRICTED},
        {"retval",                      tRETVAL},
        {"size_is",                     tSIZEIS},
        {"source",                      tSOURCE},
346
        {"strict_context_handle",       tSTRICTCONTEXTHANDLE},
347 348 349 350 351 352 353 354 355 356 357 358 359
        {"string",                      tSTRING},
        {"switch_is",                   tSWITCHIS},
        {"switch_type",                 tSWITCHTYPE},
        {"transmit_as",                 tTRANSMITAS},
        {"unique",                      tUNIQUE},
        {"uuid",                        tUUID},
        {"v1_enum",                     tV1ENUM},
        {"vararg",                      tVARARG},
        {"version",                     tVERSION},
        {"wire_marshal",                tWIREMARSHAL},
};


360
#define KWP(p) ((const struct keyword *)(p))
361 362 363 364 365

static int kw_cmp_func(const void *s1, const void *s2)
{
	return strcmp(KWP(s1)->kw, KWP(s2)->kw);
}
366 367 368

static int kw_token(const char *kw)
{
369 370 371
	struct keyword key, *kwp;
	key.kw = kw;
	kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
372
	if (kwp) {
373
		parser_lval.str = xstrdup(kwp->kw);
374 375
		return kwp->token;
	}
376
	parser_lval.str = xstrdup(kw);
377 378 379
	return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
}

380 381 382 383 384 385 386 387 388 389 390 391 392
static int attr_token(const char *kw)
{
        struct keyword key, *kwp;
        key.kw = kw;
        kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]),
                      sizeof(attr_keywords[0]), kw_cmp_func);
        if (kwp) {
            parser_lval.str = xstrdup(kwp->kw);
            return kwp->token;
        }
        return kw_token(kw);
}

393 394 395 396 397 398 399
static void addcchar(char c)
{
	if(cbufidx >= cbufalloc)
	{
		cbufalloc += 1024;
		cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
		if(cbufalloc > 65536)
400
			parser_warning("Reallocating string buffer larger than 64kB\n");
401 402 403 404 405 406 407 408 409 410
	}
	cbuffer[cbufidx++] = c;
}

static char *get_buffered_cstring(void)
{
	addcchar(0);
	return xstrdup(cbuffer);
}

411
void pop_import(void)
412 413 414 415 416 417 418 419 420 421 422
{
	int ptr = import_stack_ptr-1;

	fclose(yyin);
	yy_delete_buffer( YY_CURRENT_BUFFER );
	yy_switch_to_buffer( import_stack[ptr].state );
	if (temp_name) {
		unlink(temp_name);
		free(temp_name);
	}
	temp_name = import_stack[ptr].temp_name;
423 424
	input_name = import_stack[ptr].input_name;
	line_number = import_stack[ptr].line_number;
425 426 427 428 429 430 431 432
	import_stack_ptr--;
}

struct imports {
	char *name;
	struct imports *next;
} *first_import;

433
int do_import(char *fname)
434 435
{
	FILE *f;
436
	char *path;
437 438 439 440 441 442 443
	struct imports *import;
	int ptr = import_stack_ptr;
	int ret;

	import = first_import;
	while (import && strcmp(import->name, fname))
		import = import->next;
444
	if (import) return 0; /* already imported */
445 446 447 448 449 450

	import = xmalloc(sizeof(struct imports));
	import->name = xstrdup(fname);
	import->next = first_import;
	first_import = import;

451 452 453 454 455
        /* don't search for a file name with a path in the include directories,
         * for compatibility with MIDL */
        if (strchr( fname, '/' ) || strchr( fname, '\\' ))
            path = strdup( fname );
        else if (!(path = wpp_find_include( fname, input_name )))
456
            error_loc("Unable to open include file %s\n", fname);
457 458

	import_stack[ptr].temp_name = temp_name;
459 460
	import_stack[ptr].input_name = input_name;
	import_stack[ptr].line_number = line_number;
461
	import_stack_ptr++;
462 463
        input_name = path;
        line_number = 1;
464

465
        ret = wpp_parse_temp( path, NULL, &temp_name );
466 467 468
        if (ret) exit(1);

	if((f = fopen(temp_name, "r")) == NULL)
469
		error_loc("Unable to open %s\n", temp_name);
470 471 472

	import_stack[ptr].state = YY_CURRENT_BUFFER;
	yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
473
	return 1;
474 475 476 477 478 479 480 481 482
}

void abort_import(void)
{
	int ptr;

	for (ptr=0; ptr<import_stack_ptr; ptr++)
		unlink(import_stack[ptr].temp_name);
}