wine/dlls/msi/cond.y
2004-03-16 03:23:43 +00:00

398 lines
8.2 KiB
Plaintext

%{
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2003 Mike McCormack for CodeWeavers
*
* 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
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "msi.h"
#include "msiquery.h"
#define YYLEX_PARAM info
#define YYPARSE_PARAM info
static int COND_error(char *str);
WINE_DEFAULT_DEBUG_CHANNEL(msi);
typedef struct tag_yyinput
{
MSIHANDLE hInstall;
LPCWSTR str;
INT n;
INT start;
MSICONDITION result;
} COND_input;
static LPWSTR COND_GetString( COND_input *info );
static int COND_lex( void *COND_lval, COND_input *info);
typedef INT (*comp_int)(INT a, INT b);
static INT comp_lt(INT a, INT b);
static INT comp_gt(INT a, INT b);
static INT comp_le(INT a, INT b);
static INT comp_ge(INT a, INT b);
static INT comp_eq(INT a, INT b);
static INT comp_ne(INT a, INT b);
%}
%pure-parser
%union
{
LPWSTR string;
INT value;
comp_int fn_comp_int;
}
%token COND_SPACE COND_EOF COND_SPACE
%token COND_OR COND_AND COND_NOT
%token COND_LT COND_GT COND_LE COND_GE COND_EQ COND_NE
%token COND_LPAR COND_RPAR
%token COND_PERCENT COND_DOLLARS COND_QUESTION COND_AMPER COND_EXCLAM
%token COND_IDENT COND_NUMBER
%nonassoc COND_EOF COND_ERROR
%type <value> expression boolean_term boolean_factor term value symbol integer
%type <string> identifier
%type <fn_comp_int> comparison_op
%%
condition:
expression
{
COND_input* cond = (COND_input*) info;
cond->result = $1;
}
;
expression:
boolean_term
{
$$ = $1;
}
| boolean_term COND_OR expression
{
$$ = $1 || $3;
}
;
boolean_term:
boolean_factor
{
$$ = $1;
}
| boolean_factor COND_AND term
{
$$ = $1 && $3;
}
;
boolean_factor:
term
{
$$ = $1;
}
| COND_NOT term
{
$$ = ! $2;
}
;
term:
value
{
$$ = $1;
}
| value comparison_op value
{
$$ = $2( $1, $3 );
}
| COND_LPAR expression COND_RPAR
{
$$ = $2;
}
;
comparison_op:
COND_LT
{
$$ = comp_lt;
}
| COND_GT
{
$$ = comp_gt;
}
| COND_LE
{
$$ = comp_le;
}
| COND_GE
{
$$ = comp_ge;
}
| COND_EQ
{
$$ = comp_eq;
}
| COND_NE
{
$$ = comp_ne;
}
;
value:
symbol
{
$$ = $1;
}
| integer
{
$$ = $1;
}
;
symbol:
COND_DOLLARS identifier
{
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetComponentStateW(cond->hInstall, $2, &install, &action );
$$ = action;
}
| COND_QUESTION identifier
{
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetComponentStateW(cond->hInstall, $2, &install, &action );
$$ = install;
}
| COND_AMPER identifier
{
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetFeatureStateW(cond->hInstall, $2, &install, &action );
$$ = action;
}
| COND_EXCLAM identifier
{
COND_input* cond = (COND_input*) info;
INSTALLSTATE install = INSTALLSTATE_UNKNOWN, action = INSTALLSTATE_UNKNOWN;
MsiGetFeatureStateW(cond->hInstall, $2, &install, &action );
$$ = install;
}
;
identifier:
COND_IDENT
{
COND_input* cond = (COND_input*) info;
$$ = COND_GetString(cond);
if( !$$ )
YYABORT;
}
| COND_PERCENT identifier
{
UINT len = GetEnvironmentVariableW( $2, NULL, 0 );
if( len++ )
{
$$ = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
if( $$ )
GetEnvironmentVariableW( $2, $$, len );
}
HeapFree( GetProcessHeap(), 0, $2 );
}
;
integer:
COND_NUMBER
{
COND_input* cond = (COND_input*) info;
LPWSTR szNum = COND_GetString(cond);
if( !szNum )
YYABORT;
$$ = atoiW( szNum );
HeapFree( GetProcessHeap(), 0, szNum );
}
;
%%
static INT comp_lt(INT a, INT b)
{
return (a < b);
}
static INT comp_gt(INT a, INT b)
{
return (a > b);
}
static INT comp_le(INT a, INT b)
{
return (a <= b);
}
static INT comp_ge(INT a, INT b)
{
return (a >= b);
}
static INT comp_eq(INT a, INT b)
{
return (a == b);
}
static INT comp_ne(INT a, INT b)
{
return (a != b);
}
static int COND_IsAlpha( WCHAR x )
{
return( ( ( x >= 'A' ) && ( x <= 'Z' ) ) ||
( ( x >= 'a' ) && ( x <= 'z' ) ) );
}
static int COND_IsNumber( WCHAR x )
{
return( ( x >= '0' ) && ( x <= '9' ) );
}
static int COND_IsIdent( WCHAR x )
{
return( COND_IsAlpha( x ) || COND_IsNumber( x ) || ( x == '_' ) );
}
static int COND_lex( void *COND_lval, COND_input *cond )
{
WCHAR ch;
cond->start = cond->n;
ch = cond->str[cond->n];
if( !ch )
return COND_EOF;
cond->n++;
switch( ch )
{
case '(': return COND_LPAR;
case ')': return COND_RPAR;
case '&': return COND_AMPER;
case '!': return COND_EXCLAM;
case '$': return COND_DOLLARS;
case '?': return COND_QUESTION;
case '%': return COND_PERCENT;
case ' ': return COND_SPACE;
}
if( COND_IsAlpha( ch ) )
{
ch = cond->str[cond->n];
while( COND_IsIdent( ch ) )
ch = cond->str[cond->n++];
return COND_IDENT;
}
if( COND_IsNumber( ch ) )
{
ch = cond->str[cond->n];
while( COND_IsNumber( ch ) )
ch = cond->str[cond->n++];
return COND_NUMBER;
}
return COND_ERROR;
}
static LPWSTR COND_GetString( COND_input *cond )
{
int len;
LPWSTR str;
len = cond->n - cond->start;
str = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof (WCHAR) );
if( str )
strncpyW( str, &cond->str[cond->start], len );
return str;
}
static int COND_error(char *str)
{
return 0;
}
MSICONDITION WINAPI MsiEvaluateConditionW( MSIHANDLE hInstall, LPCWSTR szCondition )
{
COND_input cond;
MSICONDITION r;
cond.hInstall = hInstall;
cond.str = szCondition;
cond.n = 0;
cond.start = 0;
cond.result = MSICONDITION_ERROR;
if( !COND_parse( &cond ) )
r = cond.result;
else
r = MSICONDITION_ERROR;
return r;
}
MSICONDITION WINAPI MsiEvaluateConditionA( MSIHANDLE hInstall, LPCSTR szCondition )
{
LPWSTR szwCond = NULL;
MSICONDITION r;
if( szCondition )
{
UINT len = MultiByteToWideChar( CP_ACP, 0, szCondition, -1, NULL, 0 );
szwCond = HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) );
MultiByteToWideChar( CP_ACP, 0, szCondition, -1, szwCond, len );
}
r = MsiEvaluateConditionW( hInstall, szwCond );
if( szwCond )
HeapFree( GetProcessHeap(), 0, szwCond );
return r;
}