ntdll: Allow NtQueryVolumeInformationFile to make async volume information queries.
[wine.git] / programs / winhlp32 / macro.lex.l
blob08067a4548f663b5ac6d7384d481b3647ecc1aa2
1 %{ /* -*-C-*- */
2 /*
3  * Help Viewer
4  *
5  * Copyright 1996 Ulrich Schmid
6  * Copyright 2002,2008 Eric Pouech
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * 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
21  */
23 %option noinput nounput never-interactive 8bit
24 %x quote
26 #include <assert.h>
27 #include <stdarg.h>
29 #define YY_NO_UNISTD_H
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "winhelp.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(winhelp);
40 struct lex_data {
41     LPCSTR   macroptr;
42     LPSTR    strptr;
43     int      quote_stack[32];
44     unsigned quote_stk_idx;
45     LPSTR    cache_string[32];
46     int      cache_used;
47     WINHELP_WINDOW* window;
49 static struct lex_data* lex_data = NULL;
51 struct lexret  yylval;
53 #define YY_INPUT(buf,result,max_size)\
54   if ((result = *lex_data->macroptr ? 1 : 0)) buf[0] = *lex_data->macroptr++;
59 [-+]?[0-9]+             yylval.integer = strtol(yytext, NULL, 10);      return INTEGER;
60 [-+]?0[xX][0-9a-f]+     yylval.integer = strtol(yytext, NULL, 16);      return INTEGER;
62 [a-zA-Z][_0-9a-zA-Z]*   return MACRO_Lookup(yytext, &yylval);
64 \`          |
65 \"          |
66 \'          |
67 <quote>\`   |
68 <quote>\"   |
69 <quote>\'   {
70     if (lex_data->quote_stk_idx == 0 ||
71         (yytext[0] == '\"' && lex_data->quote_stack[lex_data->quote_stk_idx - 1] != '\"') ||
72         (yytext[0] == '`'))
73     {
74         /* opening a new one */
75         if (lex_data->quote_stk_idx == 0)
76         {
77             assert(lex_data->cache_used < ARRAY_SIZE(lex_data->cache_string));
78             lex_data->strptr = lex_data->cache_string[lex_data->cache_used] = HeapAlloc(GetProcessHeap(), 0, strlen(lex_data->macroptr) + 1);
79             yylval.string = lex_data->strptr;
80             lex_data->cache_used++;
81             BEGIN(quote);
82         }
83         else *lex_data->strptr++ = yytext[0];
84         lex_data->quote_stack[lex_data->quote_stk_idx++] = yytext[0];
85         assert(lex_data->quote_stk_idx < ARRAY_SIZE(lex_data->quote_stack));
86     }
87     else
88     {
89         if (yytext[0] == '`') assert(0);
90         /* close the current quote */
91         if (--lex_data->quote_stk_idx == 0)
92         {
93             BEGIN INITIAL;
94             *lex_data->strptr++ = '\0';
95             return STRING;
96         }
97         else *lex_data->strptr++ = yytext[0];
98     }
101 <quote>.                *lex_data->strptr++ = yytext[0];
102 <quote>\\.              *lex_data->strptr++ = yytext[1];
103 <quote><<EOF>>          return 0;
105 " "
106 .                       return yytext[0];
109 #if 0
110 /* all code for testing macros */
111 #include "winhelp.h"
112 static CHAR szTestMacro[256];
114 static LRESULT CALLBACK MACRO_TestDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
116     if (msg == WM_COMMAND && wParam == IDOK)
117     {
118         GetDlgItemText(hDlg, 99, szTestMacro, sizeof(szTestMacro));
119         EndDialog(hDlg, IDOK);
120         return TRUE;
121     }
122     return FALSE;
125 void macro_test(void)
127     WNDPROC lpfnDlg = MakeProcInstance(MACRO_TestDialogProc, Globals.hInstance);
128     DialogBox(Globals.hInstance, STRING_DIALOG_TEST, Globals.active_win->hMainWnd, (DLGPROC)lpfnDlg);
129     FreeProcInstance(lpfnDlg);
130     macro = szTestMacro;
132 #endif
134 /* small helper function for debug messages */
135 static const char* ts(int t)
137     static char c[2] = {0,0};
139     switch (t)
140     {
141     case EMPTY: return "EMPTY";
142     case VOID_FUNCTION: return "VOID_FUNCTION";
143     case BOOL_FUNCTION: return "BOOL_FUNCTION";
144     case INTEGER: return "INTEGER";
145     case STRING: return "STRING";
146     case IDENTIFIER: return "IDENTIFIER";
147     default: c[0] = (char)t; return c;
148     }
151 static int MACRO_CallBoolFunc(void *fn, const char* args, void** ret);
153 /******************************************************************
154  *              MACRO_CheckArgs
156  * checks number of arguments against prototype, and stores arguments on
157  * stack pa for later call
158  * returns -1 on error, otherwise the number of pushed parameters
159  */
160 static int MACRO_CheckArgs(void* pa[], unsigned max, const char* args)
162     int t;
163     unsigned int len = 0, idx = 0;
165     WINE_TRACE("Checking %s\n", debugstr_a(args));
167     if (yylex() != '(') {WINE_WARN("missing (\n");return -1;}
169     if (*args)
170     {
171         len = strlen(args);
172         for (;;)
173         {
174             t = yylex();
175             WINE_TRACE("Got %s <=> %c\n", debugstr_a(ts(t)), *args);
177             switch (*args)
178             {
179             case 'S': 
180                 if (t != STRING)
181                 {WINE_WARN("missing S\n");return -1;}
182                 pa[idx] = (void*)yylval.string;  
183                 break;
184             case 'U':
185             case 'I':
186                 if (t != INTEGER)
187                 {WINE_WARN("missing U\n");return -1;}   
188                 pa[idx] = LongToPtr(yylval.integer);
189                 break;
190             case 'B':
191                 if (t != BOOL_FUNCTION) 
192                 {WINE_WARN("missing B\n");return -1;}   
193                 if (MACRO_CallBoolFunc(yylval.function, yylval.proto, &pa[idx]) == 0)
194                     return -1;
195                 break;
196             default: 
197                 WINE_WARN("unexpected %s while args is %c\n", debugstr_a(ts(t)), *args);
198                 return -1;
199             }
200             idx++;
201             if (*++args == '\0') break;
202             t = yylex();
203             if (t == ')') goto CheckArgs_end;
204             if (t != ',') {WINE_WARN("missing ,\n");return -1;}
205             if (idx >= max) {WINE_FIXME("stack overflow (%d)\n", max);return -1;}
206         }
207     }
208     if (yylex() != ')') {WINE_WARN("missing )\n");return -1;}
210 CheckArgs_end:
211     while (len > idx) pa[--len] = NULL;
212     return idx;
215 /******************************************************************
216  *              MACRO_CallBoolFunc
218  * Invokes boolean function fn, which arguments are defined by args
219  * stores bool result into ret
220  */
221 static int MACRO_CallBoolFunc(void *fn, const char* args, void** ret)
223     void*       pa[2];
224     int         idx = MACRO_CheckArgs(pa, ARRAY_SIZE(pa), args);
226     if (idx < 0) return 0;
227     if (!fn)     return 1;
229     WINE_TRACE("calling with %u pmts\n", idx);
231     switch (strlen(args))
232     {
233     case 0:
234     {
235         BOOL (WINAPI *func)(void) = fn;
236         *ret = (void *)(ULONG_PTR)func();
237         break;
238     }
239     case 1:
240     {
241         BOOL (WINAPI *func)(void *) = fn;
242         *ret = (void *)(ULONG_PTR)func( pa[0]);
243         break;
244     }
245     default: WINE_FIXME("NIY\n");
246     }
248     return 1;
251 /******************************************************************
252  *              MACRO_CallVoidFunc
255  */
256 static int MACRO_CallVoidFunc(void *fn, const char* args)
258     void*       pa[6];
259     int         idx = MACRO_CheckArgs(pa, ARRAY_SIZE(pa), args);
261     if (idx < 0) return 0;
262     if (!fn)     return 1;
264     WINE_TRACE("calling %p with %u pmts\n", fn, idx);
266     switch (strlen(args))
267     {
268     case 0:
269     {
270         void (WINAPI *func)(void) = fn;
271         func();
272         break;
273     }
274     case 1:
275     {
276         void (WINAPI *func)(void*) = fn;
277         func( pa[0] );
278         break;
279     }
280     case 2:
281     {
282         void (WINAPI *func)(void*,void*) = fn;
283         func( pa[0], pa[1] );
284         break;
285     }
286     case 3:
287     {
288         void (WINAPI *func)(void*,void*,void*) = fn;
289         func( pa[0], pa[1], pa[2] );
290         break;
291     }
292     case 4:
293     {
294         void (WINAPI *func)(void*,void*,void*,void*) = fn;
295         func( pa[0], pa[1], pa[2], pa[3] );
296         break;
297     }
298     case 5:
299     {
300         void (WINAPI *func)(void*,void*,void*,void*,void*) = fn;
301         func( pa[0], pa[1], pa[2], pa[3], pa[4] );
302         break;
303     }
304     case 6:
305     {
306         void (WINAPI *func)(void*,void*,void*,void*,void*,void*) = fn;
307         func( pa[0], pa[1], pa[2], pa[3], pa[4], pa[5] );
308         break;
309     }
310     default: WINE_FIXME("NIY\n");
311     }
313     return 1;
316 BOOL MACRO_ExecuteMacro(WINHELP_WINDOW* window, LPCSTR macro)
318     struct lex_data     curr_lex_data, *prev_lex_data;
319     BOOL ret = TRUE;
320     int t;
322     WINE_TRACE("%s\n", debugstr_a(macro));
324     prev_lex_data = lex_data;
325     lex_data = &curr_lex_data;
327     memset(lex_data, 0, sizeof(*lex_data));
328     lex_data->macroptr = macro;
329     lex_data->window = WINHELP_GrabWindow(window);
331     while ((t = yylex()) != EMPTY)
332     {
333         switch (t)
334         {
335         case VOID_FUNCTION:
336             WINE_TRACE("got type void func(%s)\n", debugstr_a(yylval.proto));
337             MACRO_CallVoidFunc(yylval.function, yylval.proto);
338             break;
339         case BOOL_FUNCTION:
340             WINE_WARN("got type bool func(%s)\n", debugstr_a(yylval.proto));
341             break;
342         default:
343             WINE_WARN("got unexpected type %s\n", debugstr_a(ts(t)));
344             YY_FLUSH_BUFFER;
345             ret = FALSE;
346             goto done;
347         }
348         switch (t = yylex())
349         {
350         case EMPTY:     goto done;
351         case ';':       break;
352         default:        ret = FALSE; YY_FLUSH_BUFFER; goto done;
353         }
354     }
356 done:
357     for (t = 0; t < lex_data->cache_used; t++)
358         HeapFree(GetProcessHeap(), 0, lex_data->cache_string[t]);
359     lex_data = prev_lex_data;
360     WINHELP_ReleaseWindow(window);
362     return ret;
365 WINHELP_WINDOW* MACRO_CurrentWindow(void)
367     return lex_data ? lex_data->window : Globals.active_win;
370 #ifndef yywrap
371 int yywrap(void) { return 1; }
372 #endif