shell32: DragQueryFile doesn't count the null terminator.
[wine/wine-kai.git] / programs / winhelp / macro.lex.l
blob1ff76cee019bd9a9e0bf13de0f5115cd022ee352
1 %{
2 /*
3  * Help Viewer
4  *
5  * Copyright 1996 Ulrich Schmid
6  * Copyright 2002 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 nounput interactive 8bit
24 %x quote
26 #include <assert.h>
27 #include "macro.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(winhelp);
33 static LPCSTR  macroptr;
34 static LPSTR   strptr;
35 static int     quote_stack[32];
36 static unsigned int quote_stk_idx = 0;
37 struct lexret  yylval;
39 #define YY_INPUT(buf,result,max_size)\
40   if ((result = *macroptr ? 1 : 0)) buf[0] = *macroptr++;
45 [-+]?[0-9]+             yylval.integer = strtol(yytext, NULL, 10);      return INTEGER;
46 [-+]?0[xX][0-9a-f]+     yylval.integer = strtol(yytext, NULL, 16);      return INTEGER;
48 [a-zA-Z][_0-9a-zA-Z]*   return MACRO_Lookup(yytext, &yylval);
50 \`          |
51 \"          |
52 \'          |
53 <quote>\`   |
54 <quote>\"   |
55 <quote>\'   {
56     if (quote_stk_idx == 0 ||
57         (yytext[0] == '\"' && quote_stack[quote_stk_idx - 1] != '\"') ||
58         (yytext[0] == '`'))
59     {
60         /* opening a new one */
61         if (quote_stk_idx == 0)
62         {
63             strptr = HeapAlloc(GetProcessHeap(), 0, strlen(macroptr) + 1);
64             yylval.string = strptr;
65             BEGIN(quote);
66         }
67         else *strptr++ = yytext[0];
68         quote_stack[quote_stk_idx++] = yytext[0];
69         assert(quote_stk_idx < sizeof(quote_stack) / sizeof(quote_stack[0]));
70     }
71     else
72     {
73         if (yytext[0] == '`') assert(0);
74         /* close the current quote */
75         if (--quote_stk_idx == 0)
76         {
77             BEGIN INITIAL;
78             *strptr++ = '\0';
79             return STRING;
80         }
81         else *strptr++ = yytext[0];
82     }
85 <quote>.                *strptr++ = yytext[0];
86 <quote>\\.              *strptr++ = yytext[1];
87 <quote><<EOF>>          return 0;
89 " "
90 .                       return yytext[0];
93 #if 0
94 /* all code for testing macros */
95 #include "winhelp.h"
96 static CHAR szTestMacro[256];
98 static LRESULT CALLBACK MACRO_TestDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
100     if (msg == WM_COMMAND && wParam == IDOK)
101     {
102         GetDlgItemText(hDlg, 99, szTestMacro, sizeof(szTestMacro));
103         EndDialog(hDlg, IDOK);
104         return TRUE;
105     }
106     return FALSE;
109 void macro_test(void)
111     WNDPROC lpfnDlg = MakeProcInstance(MACRO_TestDialogProc, Globals.hInstance);
112     DialogBox(Globals.hInstance, STRING_DIALOG_TEST, Globals.active_win->hMainWnd, (DLGPROC)lpfnDlg);
113     FreeProcInstance(lpfnDlg);
114     macro = szTestMacro;
116 #endif
118 /* small helper function for debug messages */
119 static const char* ts(int t)
121     static char c[2] = {0,0};
123     switch (t)
124     {
125     case EMPTY: return "EMPTY";
126     case VOID_FUNCTION: return "VOID_FUNCTION";
127     case BOOL_FUNCTION: return "BOOL_FUNCTION";
128     case INTEGER: return "INTEGER";
129     case STRING: return "STRING";
130     case IDENTIFIER: return "IDENTIFIER";
131     default: c[0] = (char)t; return c;
132     }
135 static int MACRO_CallBoolFunc(FARPROC fn, const char* args, void** ret);
137 /******************************************************************
138  *              MACRO_CheckArgs
140  * checks number of arguments against prototype, and stores arguments on
141  * stack pa for later call
142  * returns -1 on error, otherwise the number of pushed parameters
143  */
144 static int MACRO_CheckArgs(void* pa[], unsigned max, const char* args)
146     int t;
147     unsigned int len = 0, idx = 0;
149     WINE_TRACE("Checking %s\n", args);
151     if (yylex() != '(') {WINE_WARN("missing (\n");return -1;}
153     if (*args)
154     {
155         len = strlen(args);
156         for (;;)
157         {
158             t = yylex();
159             WINE_TRACE("Got %s <=> %c\n", ts(t), *args);
161             switch (*args)
162             {
163             case 'S': 
164                 if (t != STRING)
165                 {WINE_WARN("missing S\n");return -1;}
166                 pa[idx] = (void*)yylval.string;  
167                 break;
168             case 'U':
169             case 'I':
170                 if (t != INTEGER)
171                 {WINE_WARN("missing U\n");return -1;}   
172                 pa[idx] = (void*)yylval.integer; 
173                 break;
174             case 'B':
175                 if (t != BOOL_FUNCTION) 
176                 {WINE_WARN("missing B\n");return -1;}   
177                 if (MACRO_CallBoolFunc(yylval.function, yylval.proto, &pa[idx]) == 0)
178                     return -1;
179                 break;
180             default: 
181                 WINE_WARN("unexpected %s while args is %c\n", ts(t), *args);
182                 return -1;
183             }
184             idx++;
185             if (*++args == '\0') break;
186             t = yylex();
187             if (t == ')') goto CheckArgs_end;
188             if (t != ',') {WINE_WARN("missing ,\n");return -1;}
189             if (idx >= max) {WINE_FIXME("stack overflow (%d)\n", max);return -1;}
190         }
191     }
192     if (yylex() != ')') {WINE_WARN("missing )\n");return -1;}
194 CheckArgs_end:
195     while (len > idx) pa[--len] = NULL;
196     return idx;
199 /******************************************************************
200  *              MACRO_CallBoolFunc
202  * Invokes boolean function fn, which arguments are defined by args
203  * stores bool result into ret
204  */
205 static int MACRO_CallBoolFunc(FARPROC fn, const char* args, void** ret)
207     void*       pa[2];
208     int         idx = MACRO_CheckArgs(pa, sizeof(pa)/sizeof(pa[0]), args);
210     if (idx < 0) return 0;
211     if (!fn)     return 1;
213     WINE_TRACE("calling with %u pmts\n", idx);
215     switch (strlen(args))
216     {
217     case 0: *ret = (void*)(fn)();          break;
218     case 1: *ret = (void*)(fn)(pa[0]);     break;
219     default: WINE_FIXME("NIY\n");
220     }
222     return 1;
225 /******************************************************************
226  *              MACRO_CallVoidFunc
229  */
230 static int MACRO_CallVoidFunc(FARPROC fn, const char* args)
232     void*       pa[6];
233     int         idx = MACRO_CheckArgs(pa, sizeof(pa)/sizeof(pa[0]), args);
235     if (idx < 0) return 0;
236     if (!fn)     return 1;
238     WINE_TRACE("calling %p with %u pmts\n", fn, idx);
240     switch (strlen(args))
241     {
242     case 0: (fn)();                                     break;
243     case 1: (fn)(pa[0]);                                break;
244     case 2: (fn)(pa[0],pa[1]);                          break;
245     case 3: (fn)(pa[0],pa[1],pa[2]);                    break;
246     case 4: (fn)(pa[0],pa[1],pa[2],pa[3]);              break;
247     case 5: (fn)(pa[0],pa[1],pa[2],pa[3],pa[4]);        break;
248     case 6: (fn)(pa[0],pa[1],pa[2],pa[3],pa[4],pa[5]);  break;
249     default: WINE_FIXME("NIY\n");
250     }
252     return 1;
255 BOOL MACRO_ExecuteMacro(LPCSTR macro)
257     int t;
259     WINE_TRACE("%s\n", wine_dbgstr_a(macro));
261     macroptr = macro;
263     while ((t = yylex()) != EMPTY)
264     {
265         switch (t)
266         {
267         case VOID_FUNCTION:
268             WINE_TRACE("got type void func(%s)\n", yylval.proto);
269             MACRO_CallVoidFunc(yylval.function, yylval.proto);
270             break;
271         case BOOL_FUNCTION:
272             WINE_WARN("got type bool func(%s)\n", yylval.proto);
273             break;
274         default:
275             WINE_WARN("got unexpected type %s\n", ts(t));
276             return 0;
277         }
278         switch (t = yylex())
279         {
280         case EMPTY:     return 1;
281         case ';':       break;
282         default:        return 0;
283         }
284     }
286     HeapFree(GetProcessHeap(), 0, strptr);
287     strptr = NULL;
288     quote_stk_idx = 0;
290     return 1;
293 #ifndef yywrap
294 int yywrap(void) { return 1; }
295 #endif