macro.lex.l 7.82 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5
%{
/*
 * Help Viewer
 *
 * Copyright 1996 Ulrich Schmid
6
 * Copyright 2002 Eric Pouech
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
21 22
 */
%}
23
%option nounput interactive 8bit
24
%x quote
Alexandre Julliard's avatar
Alexandre Julliard committed
25
%{
26
#include <assert.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27 28
#include "macro.h"

29 30 31 32
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(winhelp);

Alexandre Julliard's avatar
Alexandre Julliard committed
33
static LPCSTR  macroptr;
Alexandre Julliard's avatar
Alexandre Julliard committed
34
static LPSTR   strptr;
35 36
static int     quote_stack[32];
static int     quote_stk_idx = 0;
37
struct lexret  yylval;
Alexandre Julliard's avatar
Alexandre Julliard committed
38 39 40 41 42 43

#define YY_INPUT(buf,result,max_size)\
  if ((result = *macroptr ? 1 : 0)) buf[0] = *macroptr++;

%}
%%
44 45

[-+]?[0-9]+             yylval.integer = strtol(yytext, NULL, 10);	return INTEGER;
Alexandre Julliard's avatar
Alexandre Julliard committed
46 47
[-+]?0[xX][0-9a-f]+	yylval.integer = strtol(yytext, NULL, 16);	return INTEGER;

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
[a-zA-Z][_0-9a-zA-Z]*   return MACRO_Lookup(yytext, &yylval);

\`	    |
\"	    |
\'          |
<quote>\`   |
<quote>\"   |
<quote>\'   {
    if (quote_stk_idx == 0 ||
        (yytext[0] == '\"' && quote_stack[quote_stk_idx - 1] != '\"') ||
        (yytext[0] == '`'))
    {
        /* opening a new one */
        if (quote_stk_idx == 0)
        {
            strptr = HeapAlloc(GetProcessHeap(), 0, strlen(macroptr) + 1);
            yylval.string = strptr;
            BEGIN(quote);
        }
        else *strptr++ = yytext[0];
        quote_stack[quote_stk_idx++] = yytext[0];
        assert(quote_stk_idx < sizeof(quote_stack) / sizeof(quote_stack[0]));
    }
    else
    {
        if (yytext[0] == '`') assert(0);
        /* close the current quote */
        if (--quote_stk_idx == 0)
        {
            BEGIN INITIAL;
            *strptr++ = '\0';
            return STRING;
        }
        else *strptr++ = yytext[0];
    }
}
Alexandre Julliard's avatar
Alexandre Julliard committed
84

85 86 87
<quote>.                *strptr++ = yytext[0];
<quote>\\.	        *strptr++ = yytext[1];
<quote><<EOF>>	        return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
88 89

" "
90
.			return yytext[0];
Alexandre Julliard's avatar
Alexandre Julliard committed
91
%%
92 93 94

#if 0
/* all code for testing macros */
Alexandre Julliard's avatar
Alexandre Julliard committed
95 96 97
#include "winhelp.h"
static CHAR szTestMacro[256];

98
static LRESULT CALLBACK MACRO_TestDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
Alexandre Julliard's avatar
Alexandre Julliard committed
99
{
100
    if (msg == WM_COMMAND && wParam == IDOK)
Alexandre Julliard's avatar
Alexandre Julliard committed
101
    {
102 103 104
        GetDlgItemText(hDlg, 99, szTestMacro, sizeof(szTestMacro));
        EndDialog(hDlg, IDOK);
        return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
105
    }
106
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
107 108
}

109
void macro_test(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
110
{
111 112 113 114 115 116 117 118 119 120 121 122 123
    WNDPROC lpfnDlg = MakeProcInstance(MACRO_TestDialogProc, Globals.hInstance);
    DialogBox(Globals.hInstance, STRING_DIALOG_TEST, Globals.active_win->hMainWnd, (DLGPROC)lpfnDlg);
    FreeProcInstance(lpfnDlg);
    macro = szTestMacro;
}
#endif

/* small helper function for debug messages */
static const char* ts(int t)
{
    static char c[2] = {0,0};

    switch (t)
Alexandre Julliard's avatar
Alexandre Julliard committed
124
    {
125 126 127 128 129 130 131
    case EMPTY: return "EMPTY";
    case VOID_FUNCTION: return "VOID_FUNCTION";
    case BOOL_FUNCTION: return "BOOL_FUNCTION";
    case INTEGER: return "INTEGER";
    case STRING: return "STRING";
    case IDENTIFIER: return "IDENTIFIER";
    default: c[0] = (char)t; return c;
Alexandre Julliard's avatar
Alexandre Julliard committed
132
    }
133
}
Alexandre Julliard's avatar
Alexandre Julliard committed
134

135
static int MACRO_CallBoolFunc(FARPROC fn, const char* args, void** ret);
Alexandre Julliard's avatar
Alexandre Julliard committed
136

137 138 139 140 141 142 143 144 145 146
/******************************************************************
 *		MACRO_CheckArgs
 *
 * checks number of arguments against prototype, and stores arguments on
 * stack pa for later call
 * returns -1 on error, otherwise the number of pushed parameters
 */
static int MACRO_CheckArgs(void* pa[], unsigned max, const char* args)
{
    int         t;
147
    int         len = 0, idx = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
148

149 150 151 152 153
    WINE_TRACE("Checking %s\n", args);

    if (yylex() != '(') {WINE_WARN("missing (\n");return -1;}

    if (*args)
154
    {
155
        len = strlen(args);
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        for (;;)
        {
            t = yylex();
            WINE_TRACE("Got %s <=> %c\n", ts(t), *args);

            switch (*args)
            {
            case 'S': 
                if (t != STRING)
                {WINE_WARN("missing S\n");return -1;}
                pa[idx] = (void*)yylval.string;  
                break;
            case 'U':
            case 'I':
                if (t != INTEGER)
                {WINE_WARN("missing U\n");return -1;}   
                pa[idx] = (void*)yylval.integer; 
                break;
            case 'B':
                if (t != BOOL_FUNCTION) 
                {WINE_WARN("missing B\n");return -1;}   
177
                if (MACRO_CallBoolFunc(yylval.function, yylval.proto, &pa[idx]) == 0)
178 179 180 181 182 183 184 185
                    return -1;
                break;
            default: 
                WINE_WARN("unexpected %s while args is %c\n", ts(t), *args);
                return -1;
            }
            idx++;
            if (*++args == '\0') break;
186 187 188 189
            t = yylex();
            if (t == ')') goto CheckArgs_end;
            if (t != ',') {WINE_WARN("missing ,\n");return -1;}
            if (idx >= max) {WINE_FIXME("stack overflow (%d)\n", max);return -1;}
190
        }
191
    }
192
    if (yylex() != ')') {WINE_WARN("missing )\n");return -1;}
193 194 195

CheckArgs_end:
    while (len > idx) pa[--len] = NULL;
196 197 198 199 200 201 202 203 204
    return idx;
}

/******************************************************************
 *		MACRO_CallBoolFunc
 *
 * Invokes boolean function fn, which arguments are defined by args
 * stores bool result into ret
 */
205
static int MACRO_CallBoolFunc(FARPROC fn, const char* args, void** ret)
206 207 208 209
{
    void*       pa[2];
    int         idx = MACRO_CheckArgs(pa, sizeof(pa)/sizeof(pa[0]), args);

210 211
    if (idx < 0) return 0;
    if (!fn)     return 1;
212 213 214

    WINE_TRACE("calling with %u pmts\n", idx);

215
    switch (strlen(args))
216 217 218 219 220 221 222
    {
    case 0: *ret = (void*)(fn)();          break;
    case 1: *ret = (void*)(fn)(pa[0]);     break;
    default: WINE_FIXME("NIY\n");
    }

    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
223 224
}

225 226 227 228 229
/******************************************************************
 *		MACRO_CallVoidFunc
 *
 *
 */
230
static int MACRO_CallVoidFunc(FARPROC fn, const char* args)
Alexandre Julliard's avatar
Alexandre Julliard committed
231
{
232 233 234
    void*       pa[6];
    int         idx = MACRO_CheckArgs(pa, sizeof(pa)/sizeof(pa[0]), args);

235 236
    if (idx < 0) return 0;
    if (!fn)     return 1;
237

238
    WINE_TRACE("calling %p with %u pmts\n", fn, idx);
239

240
    switch (strlen(args))
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    {
    case 0: (fn)();                                     break;
    case 1: (fn)(pa[0]);                                break;
    case 2: (fn)(pa[0],pa[1]);                          break;
    case 3: (fn)(pa[0],pa[1],pa[2]);                    break;
    case 4: (fn)(pa[0],pa[1],pa[2],pa[3]);              break;
    case 5: (fn)(pa[0],pa[1],pa[2],pa[3],pa[4]);        break;
    case 6: (fn)(pa[0],pa[1],pa[2],pa[3],pa[4],pa[5]);  break;
    default: WINE_FIXME("NIY\n");
    }

    return 1;
}

BOOL MACRO_ExecuteMacro(LPCSTR macro)
{
    int t;

    WINE_TRACE("%s\n", wine_dbgstr_a(macro));

    macroptr = macro;

    while ((t = yylex()) != EMPTY)
    {
        switch (t)
        {
        case VOID_FUNCTION:
            WINE_TRACE("got type void func(%s)\n", yylval.proto);
269
            MACRO_CallVoidFunc(yylval.function, yylval.proto);
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
            break;
        case BOOL_FUNCTION:
            WINE_WARN("got type bool func(%s)\n", yylval.proto);
            break;
        default:
            WINE_WARN("got unexpected type %s\n", ts(t));
            return 0;
        }
        switch (t = yylex())
        {
        case EMPTY:     return 1;
        case ';':       break;
        default:        return 0;
        }
    }

286 287
    HeapFree(GetProcessHeap(), 0, strptr);
    strptr = NULL;
288
    quote_stk_idx = 0;
289 290

    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
291
}
Alexandre Julliard's avatar
Alexandre Julliard committed
292 293 294 295

#ifndef yywrap
int yywrap(void) { return 1; }
#endif