Ove Kaaven 34e2f87f8f Handle encapsulated unions in a cleaner (and less buggy) way. Emit the
names "DUMMYUNIONNAME" and "DUMMYSTRUCTNAME" for anonymous unions and
structs. Support const and extern definitions. Retain tokens (and
whether numbers are hex or not) used for computing constant
expressions, so that the full expression can be written to the header
file instead of the computed integer result of the expression. Parse
the sizeof() operator.  Compute and remember constant definitions and
enum values so they can be used in expressions. Improved identifier
lookup speed. Fixed some bugs.
2002-11-30 01:49:46 +00:00

368 lines
7.9 KiB
Plaintext

/*
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
%option stack
%option never-interactive
nl \r?\n
ws [ \f\t\r]
cident [a-zA-Z_][0-9a-zA-Z_]*
int [0-9]+
hexd [0-9a-fA-F]
hex 0x{hexd}+
uuid {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12}
%x QUOTE
%{
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "widl.h"
#include "utils.h"
#include "parser.h"
#include "../wpp/wpp.h"
#include "y.tab.h"
#define YY_USE_PROTOS
#define YY_NO_UNPUT
#define YY_NO_TOP_STATE
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);
#define MAX_IMPORT_DEPTH 10
struct {
YY_BUFFER_STATE state;
char *temp_name;
} import_stack[MAX_IMPORT_DEPTH];
int import_stack_ptr = 0;
static void pop_import(void);
static uuid_t* parse_uuid(const char*u)
{
uuid_t* uuid = xmalloc(sizeof(uuid_t));
char b[3];
/* it would be nice to use UuidFromStringA */
uuid->Data1 = strtol(u, NULL, 16);
uuid->Data2 = strtol(u+9, NULL, 16);
uuid->Data3 = strtol(u+14, NULL, 16);
b[2] = 0;
memcpy(b, u+19, 2); uuid->Data4[0] = strtol(b, NULL, 16);
memcpy(b, u+21, 2); uuid->Data4[1] = strtol(b, NULL, 16);
memcpy(b, u+24, 2); uuid->Data4[2] = strtol(b, NULL, 16);
memcpy(b, u+26, 2); uuid->Data4[3] = strtol(b, NULL, 16);
memcpy(b, u+28, 2); uuid->Data4[4] = strtol(b, NULL, 16);
memcpy(b, u+30, 2); uuid->Data4[5] = strtol(b, NULL, 16);
memcpy(b, u+32, 2); uuid->Data4[6] = strtol(b, NULL, 16);
memcpy(b, u+34, 2); uuid->Data4[7] = strtol(b, NULL, 16);
return uuid;
}
%}
/*
**************************************************************************
* The flexer starts here
**************************************************************************
*/
%%
^#.*
\" yy_push_state(QUOTE); cbufidx = 0;
<QUOTE>\" {
yy_pop_state();
yylval.str = get_buffered_cstring();
return aSTRING;
}
<QUOTE>\\\\ |
<QUOTE>\\\" addcchar(yytext[1]);
<QUOTE>\\. addcchar('\\'); addcchar(yytext[1]);
<QUOTE>. addcchar(yytext[0]);
{uuid} {
yylval.uuid = parse_uuid(yytext);
return aUUID;
}
{hex} {
yylval.num = strtol(yytext, NULL, 0);
return aHEXNUM;
}
{int} {
yylval.num = strtol(yytext, NULL, 0);
return aNUM;
}
{cident} return kw_token(yytext);
\n
{ws}
\<\< return SHL;
\>\> return SHR;
. return yytext[0];
<<EOF>> {
if (import_stack_ptr) {
pop_import();
return aEOF;
}
else yyterminate();
}
%%
#ifndef yywrap
int yywrap(void)
{
return 1;
}
#endif
static struct keyword {
const char *kw;
int token;
int val;
} keywords[] = {
{"__cdecl", tCDECL},
{"__int64", tINT64},
{"__stdcall", tSTDCALL},
{"_stdcall", tSTDCALL},
{"aggregatable", tAGGREGATABLE},
{"allocate", tALLOCATE},
{"appobject", tAPPOBJECT},
{"arrays", tARRAYS},
{"async", tASYNC},
{"async_uuid", tASYNCUUID},
{"auto_handle", tAUTOHANDLE},
{"bindable", tBINDABLE},
{"boolean", tBOOLEAN},
{"broadcast", tBROADCAST},
{"byte", tBYTE},
{"byte_count", tBYTECOUNT},
{"call_as", tCALLAS},
{"callback", tCALLBACK},
{"case", tCASE},
{"char", tCHAR},
{"coclass", tCOCLASS},
{"code", tCODE},
{"comm_status", tCOMMSTATUS},
{"const", tCONST},
{"context_handle", tCONTEXTHANDLE},
{"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE},
{"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE},
{"control", tCONTROL},
{"cpp_quote", tCPPQUOTE},
/* ... */
{"default", tDEFAULT},
/* ... */
{"double", tDOUBLE},
/* ... */
{"enum", tENUM},
/* ... */
{"extern", tEXTERN},
/* ... */
{"float", tFLOAT},
/* ... */
{"hyper", tHYPER},
/* ... */
{"iid_is", tIIDIS},
/* ... */
{"import", tIMPORT},
{"importlib", tIMPORTLIB},
{"in", tIN},
{"include", tINCLUDE},
{"in_line", tINLINE},
{"int", tINT},
/* ... */
{"interface", tINTERFACE},
/* ... */
{"length_is", tLENGTHIS},
/* ... */
{"local", tLOCAL},
{"long", tLONG},
/* ... */
{"object", tOBJECT},
{"odl", tODL},
{"oleautomation", tOLEAUTOMATION},
/* ... */
{"out", tOUT},
/* ... */
{"pointer_default", tPOINTERDEFAULT},
/* ... */
{"ref", tREF},
/* ... */
{"short", tSHORT},
{"signed", tSIGNED},
{"size_is", tSIZEIS},
{"sizeof", tSIZEOF},
/* ... */
{"string", tSTRING},
{"struct", tSTRUCT},
{"switch", tSWITCH},
{"switch_is", tSWITCHIS},
{"switch_type", tSWITCHTYPE},
/* ... */
{"typedef", tTYPEDEF},
{"union", tUNION},
/* ... */
{"unique", tUNIQUE},
{"unsigned", tUNSIGNED},
/* ... */
{"uuid", tUUID},
{"v1_enum", tV1ENUM},
/* ... */
{"version", tVERSION},
{"void", tVOID},
{"wchar_t", tWCHAR},
{"wire_marshal", tWIREMARSHAL}
};
#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0]))
#define KWP(p) ((struct keyword *)(p))
static int kw_cmp_func(const void *s1, const void *s2)
{
return strcmp(KWP(s1)->kw, KWP(s2)->kw);
}
#define KW_BSEARCH
static int kw_token(const char *kw)
{
struct keyword key, *kwp;
key.kw = kw;
#ifdef KW_BSEARCH
kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func);
#else
{
int i;
for (kwp=NULL, i=0; i < NKEYWORDS; i++)
if (!kw_cmp_func(&key, &keywords[i])) {
kwp = &keywords[i];
break;
}
}
#endif
if (kwp) return kwp->token;
yylval.str = xstrdup(kw);
return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER;
}
static void addcchar(char c)
{
if(cbufidx >= cbufalloc)
{
cbufalloc += 1024;
cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0]));
if(cbufalloc > 65536)
yywarning("Reallocating string buffer larger than 64kB");
}
cbuffer[cbufidx++] = c;
}
static char *get_buffered_cstring(void)
{
addcchar(0);
return xstrdup(cbuffer);
}
static void pop_import(void)
{
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;
import_stack_ptr--;
}
struct imports {
char *name;
struct imports *next;
} *first_import;
int do_import(char *fname)
{
FILE *f;
char *hname, *path;
struct imports *import;
int ptr = import_stack_ptr;
int ret;
if (!parse_only) {
hname = dup_basename(fname, ".idl");
strcat(hname, ".h");
fprintf(header, "#include \"%s\"\n", hname);
free(hname);
}
import = first_import;
while (import && strcmp(import->name, fname))
import = import->next;
if (import) return 0; /* already imported */
import = xmalloc(sizeof(struct imports));
import->name = xstrdup(fname);
import->next = first_import;
first_import = import;
if (!(path = wpp_find_include( fname, 1 )))
yyerror("Unable to open include file %s", fname);
import_stack[ptr].temp_name = temp_name;
import_stack_ptr++;
ret = wpp_parse_temp( path, NULL, &temp_name );
free( path );
if (ret) exit(1);
if((f = fopen(temp_name, "r")) == NULL)
yyerror("Unable to open %s", temp_name);
import_stack[ptr].state = YY_CURRENT_BUFFER;
yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE));
return 1;
}
void abort_import(void)
{
int ptr;
for (ptr=0; ptr<import_stack_ptr; ptr++)
unlink(import_stack[ptr].temp_name);
}