~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/tools/winedump/search.c

Version: ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  *  Prototype search and parsing functions
  3  *
  4  *  Copyright 2000 Jon Griffiths
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "config.h"
 22 #include "wine/port.h"
 23 
 24 #include "winedump.h"
 25 
 26 static char *grep_buff = NULL;
 27 static char *fgrep_buff = NULL;
 28 
 29 static int symbol_from_prototype (parsed_symbol *sym, const char *prototype);
 30 static const char *get_type (parsed_symbol *sym, const char *proto, int arg);
 31 
 32 
 33 /*******************************************************************
 34  *         symbol_search
 35  *
 36  * Call Patrik Stridvall's 'function_grep.pl' script to retrieve a
 37  * function prototype from include file(s)
 38  */
 39 int symbol_search (parsed_symbol *sym)
 40 {
 41   static const size_t MAX_RESULT_LEN = 1024;
 42   FILE *grep;
 43   int attempt = 0;
 44 
 45   assert (globals.do_code);
 46   assert (globals.directory);
 47   assert (sym && sym->symbol);
 48 
 49   if (!symbol_is_valid_c (sym))
 50     return - 1;
 51 
 52   if (!grep_buff)
 53     grep_buff = (char *) malloc (MAX_RESULT_LEN);
 54 
 55   if (!fgrep_buff)
 56     fgrep_buff = (char *) malloc (MAX_RESULT_LEN);
 57 
 58   if (!grep_buff || !fgrep_buff)
 59     fatal ("Out of Memory");
 60 
 61   /* Use 'grep' to tell us which possible files the function is in,
 62    * then use 'function_grep.pl' to get the prototype. If this fails the
 63    * first time then give grep a more general query (that doesn't
 64    * require an opening argument brace on the line with the function name).
 65    */
 66   while (attempt < 2)
 67   {
 68     FILE *f_grep;
 69     char *cmd = str_create (4, "grep -d recurse -l \"", sym->symbol,
 70         !attempt ? "[:blank:]*(\" " : "\" ", globals.directory);
 71 
 72     if (VERBOSE)
 73       puts (cmd);
 74 
 75     fflush (NULL); /* See 'man popen' */
 76 
 77     if (!(grep = popen (cmd, "r")))
 78       fatal ("Cannot execute grep -l");
 79     free (cmd);
 80 
 81     while (fgets (grep_buff, MAX_RESULT_LEN, grep))
 82     {
 83       int i;
 84       const char *extension = grep_buff;
 85       for (i = 0; grep_buff[i] && grep_buff[i] != '\n' ; i++) {
 86         if (grep_buff[i] == '.')
 87           extension = &grep_buff[i];
 88       }
 89       grep_buff[i] = '\0';
 90 
 91       /* Definitely not in these: */
 92       if (strcmp(extension,".dll") == 0 ||
 93           strcmp(extension,".lib") == 0 ||
 94           strcmp(extension,".so")  == 0 ||
 95           strcmp(extension,".o")   == 0)
 96         continue;
 97 
 98       if (VERBOSE)
 99         puts (grep_buff);
100 
101       cmd = str_create (5, "function_grep.pl ", sym->symbol,
102                         " \"", grep_buff, "\"");
103 
104       if (VERBOSE)
105         puts (cmd);
106 
107       fflush (NULL); /* See 'man popen' */
108 
109       if (!(f_grep = popen (cmd, "r")))
110         fatal ("Cannot execute function_grep.pl");
111       free (cmd);
112 
113       while (fgets (grep_buff, MAX_RESULT_LEN, f_grep))
114       {
115         char *iter = grep_buff;
116 
117         /* Keep only the first line */
118         symbol_clean_string(grep_buff);
119 
120         for (i = 0; grep_buff[i] && grep_buff[i] != '\n' ; i++)
121           ;
122         grep_buff[i] = '\0';
123 
124         if (VERBOSE)
125           puts (grep_buff);
126 
127         while ((iter = strstr (iter, sym->symbol)))
128         {
129           if (iter > grep_buff && (iter[-1] == ' ' || iter[-1] == '*') &&
130              (iter[strlen (sym->symbol)] == ' ' ||
131               iter[strlen (sym->symbol)] == '('))
132           {
133             if (VERBOSE)
134               printf ("Prototype '%s' looks OK, processing\n", grep_buff);
135 
136             if (!symbol_from_prototype (sym, grep_buff))
137             {
138               pclose (f_grep);
139               pclose (grep);
140               return 0;  /* OK */
141             }
142             if (VERBOSE)
143               puts ("Failed, trying next");
144           }
145           else
146             iter += strlen (sym->symbol);
147         }
148       }
149       pclose (f_grep);
150     }
151     pclose (grep);
152     attempt++;
153   }
154 
155   return -1; /* Not found */
156 }
157 
158 
159 /*******************************************************************
160  *         symbol_from_prototype
161  *
162  * Convert a C prototype into a symbol
163  */
164 static int symbol_from_prototype (parsed_symbol *sym, const char *proto)
165 {
166   const char *iter;
167   int found;
168 
169   proto = get_type (sym, proto, -1); /* Get return type */
170   if (!proto)
171     return -1;
172 
173   iter = str_match (proto, sym->symbol, &found);
174 
175   if (!found)
176   {
177     char *call;
178     /* Calling Convention */
179     iter = strchr (iter, ' ');
180     if (!iter)
181       return -1;
182 
183     call = str_substring (proto, iter);
184 
185     if (!strcasecmp (call, "cdecl") || !strcasecmp (call, "__cdecl"))
186       sym->flags |= SYM_CDECL;
187     else
188       sym->flags |= SYM_STDCALL;
189     free (call);
190     iter = str_match (iter, sym->symbol, &found);
191 
192     if (!found)
193       return -1;
194 
195     if (VERBOSE)
196       printf ("Using %s calling convention\n",
197               sym->flags & SYM_CDECL ? "cdecl" : "stdcall");
198   }
199   else
200     sym->flags = CALLING_CONVENTION;
201 
202   sym->function_name = strdup (sym->symbol);
203   proto = iter;
204 
205   /* Now should be the arguments */
206   if (*proto++ != '(')
207     return -1;
208 
209   for (; *proto == ' '; proto++);
210 
211   if (!strncmp (proto, "void", 4))
212     return 0;
213 
214   do
215   {
216     /* Process next argument */
217     str_match (proto, "...", &sym->varargs);
218     if (sym->varargs)
219       return 0;
220 
221     if (!(proto = get_type (sym, proto, sym->argc)))
222       return -1;
223 
224     sym->argc++;
225 
226     if (*proto == ',')
227       proto++;
228     else if (*proto != ')')
229       return -1;
230 
231   } while (*proto != ')');
232 
233   return 0;
234 }
235 
236 
237 /*******************************************************************
238  *         get_type
239  *
240  * Read a type from a prototype
241  */
242 static const char *get_type (parsed_symbol *sym, const char *proto, int arg)
243 {
244   int is_const, is_volatile, is_struct, is_signed, is_unsigned, ptrs = 0;
245   const char *iter, *type_str, *base_type, *catch_unsigned;
246   char dest_type, *type_str_tmp;
247 
248   assert (sym && sym->symbol);
249   assert (proto && *proto);
250   assert (arg < 0 || (unsigned)arg == sym->argc);
251 
252   type_str = proto;
253 
254   proto = str_match (proto, "const", &is_const);
255   proto = str_match (proto, "volatile", &is_volatile);
256   proto = str_match (proto, "struct", &is_struct);
257   if (!is_struct)
258     proto = str_match (proto, "union", &is_struct);
259 
260   catch_unsigned = proto;
261 
262   proto = str_match (proto, "unsigned", &is_unsigned);
263   proto = str_match (proto, "signed", &is_signed);
264 
265   /* Can have 'unsigned const' or 'const unsigned' etc */
266   if (!is_const)
267     proto = str_match (proto, "const", &is_const);
268   if (!is_volatile)
269     proto = str_match (proto, "volatile", &is_volatile);
270 
271   base_type = proto;
272   iter = str_find_set (proto, " ,*)");
273   if (!iter)
274     return NULL;
275 
276   if (arg < 0 && (is_signed || is_unsigned))
277   {
278     /* Prevent calling convention from being swallowed by 'un/signed' alone */
279     if (strncmp (base_type, "int", 3) && strncmp (base_type, "long", 4) &&
280         strncmp (base_type, "short", 5) && strncmp (base_type, "char", 4))
281     {
282       iter = proto;
283       base_type = catch_unsigned;
284     } else
285       catch_unsigned = NULL;
286   }
287   else
288     catch_unsigned = NULL;
289 
290   /* FIXME: skip const/volatile here too */
291   for (proto = iter; *proto; proto++)
292     if (*proto == '*')
293       ptrs++;
294     else if (*proto != ' ')
295       break;
296 
297   if (!*proto)
298     return NULL;
299 
300   type_str = type_str_tmp = str_substring (type_str, proto);
301   if (iter == base_type || catch_unsigned)
302   {
303     /* 'unsigned' with no type */
304     char *tmp = str_create (2, type_str, " int");
305     free (type_str_tmp);
306     type_str = type_str_tmp = tmp;
307   }
308   symbol_clean_string (type_str);
309 
310   dest_type = symbol_get_type (type_str);
311 
312   if (arg < 0)
313   {
314     sym->return_text = (char*)type_str;
315     sym->return_type = dest_type;
316   }
317   else
318   {
319     sym->arg_type [arg] = dest_type;
320     sym->arg_flag [arg] = is_const ? CT_CONST : is_volatile ? CT_VOLATILE : 0;
321 
322     if (*proto == ',' || *proto == ')')
323       sym->arg_name [arg] = str_create_num (1, arg, "arg");
324     else
325     {
326       iter = str_find_set (proto, " ,)");
327       if (!iter)
328       {
329         free (type_str_tmp);
330         return NULL;
331       }
332       sym->arg_name [arg] = str_substring (proto, iter);
333       proto = iter;
334     }
335     sym->arg_text [arg] = (char*)type_str;
336 
337   }
338   return proto;
339 }
340 
341 
342 #ifdef __GNUC__
343 /*******************************************************************
344  *         search_cleanup
345  *
346  * Free memory used while searching (a niceity)
347  */
348 void search_cleanup (void) __attribute__ ((destructor));
349 void search_cleanup (void)
350 {
351   free (grep_buff);
352   free (fgrep_buff);
353 }
354 #endif
355 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.