debug.l 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /* -*-C-*-
  2. * Lexical scanner for command line parsing
  3. *
  4. * Copyright 1993 Eric Youngdale
  5. * 2000 Eric Pouech
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20. */
  21. %option noinput nounput always-interactive 8bit prefix="dbg_"
  22. %{
  23. #include "config.h"
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdarg.h>
  27. #define YY_NO_UNISTD_H
  28. #include "debugger.h"
  29. #include "dbg.tab.h"
  30. #undef YY_INPUT
  31. static char** local_lexemes /* = NULL */;
  32. static int next_lexeme /* = 0 */;
  33. static int alloc_lexeme /* = 0 */;
  34. char* lexeme_alloc_size(int size)
  35. {
  36. assert(0 <= next_lexeme && next_lexeme < alloc_lexeme + 1);
  37. if (next_lexeme >= alloc_lexeme)
  38. {
  39. alloc_lexeme += 32;
  40. local_lexemes = dbg_heap_realloc(local_lexemes, alloc_lexeme * sizeof(local_lexemes[0]));
  41. assert(local_lexemes);
  42. }
  43. return local_lexemes[next_lexeme++] = HeapAlloc(GetProcessHeap(), 0, size + 1);
  44. }
  45. static char* lexeme_alloc(const char* lexeme)
  46. {
  47. char* ptr = lexeme_alloc_size(strlen(lexeme) + 1);
  48. return strcpy(ptr, lexeme);
  49. }
  50. void lexeme_flush(void)
  51. {
  52. while (--next_lexeme >= 0) HeapFree(GetProcessHeap(), 0, local_lexemes[next_lexeme]);
  53. next_lexeme = 0;
  54. }
  55. static size_t read_input(const char* pfx, char* buf, int size)
  56. {
  57. int len;
  58. static char* last_line = NULL;
  59. static size_t last_line_idx = 0;
  60. /* try first to fetch the remaining of an existing line */
  61. if (last_line_idx == 0)
  62. {
  63. char* tmp = NULL;
  64. /* no remaining chars to be read from last line, grab a brand new line up to '\n' */
  65. lexeme_flush();
  66. len = input_fetch_entire_line(pfx, &tmp);
  67. if (len < 0) return 0; /* eof */
  68. /* remove carriage return in newline */
  69. if (len >= 2 && tmp[len - 2] == '\r')
  70. {
  71. tmp[len - 2] = '\n';
  72. tmp[len - 1] = '\0';
  73. len--;
  74. }
  75. /* FIXME: should have a pair of buffers, and switch between the two, instead of
  76. * reallocating a new one for each line
  77. */
  78. if (last_line && (len == 0 || (len == 1 && tmp[0] == '\n')))
  79. {
  80. HeapFree(GetProcessHeap(), 0, tmp);
  81. }
  82. else
  83. {
  84. HeapFree(GetProcessHeap(), 0, last_line);
  85. last_line = tmp;
  86. }
  87. }
  88. len = min(strlen(last_line + last_line_idx), size - 1);
  89. memcpy(buf, last_line + last_line_idx, len);
  90. buf[len] = '\0';
  91. if ((last_line_idx += len) >= strlen(last_line))
  92. last_line_idx = 0;
  93. return len;
  94. }
  95. #define YY_INPUT(buf,result,max_size) \
  96. (result = read_input("Wine-dbg>", buf, max_size))
  97. static int syntax_error;
  98. %}
  99. OCTDIGIT [0-7]
  100. DIGIT [0-9]
  101. HEXDIGIT [0-9a-fA-F]
  102. FORMAT [ubcdgiswxa]
  103. IDENTIFIER [_a-zA-Z~?][_a-zA-Z0-9~?@]*
  104. PATHNAME [\\/_a-zA-Z0-9\.~@][\\/\-_a-zA-Z0-9\.~@]*
  105. STRING \"[^\n"]+\"
  106. %s FORMAT_EXPECTED
  107. %s INFO_CMD
  108. %s HELP_CMD
  109. %s BD_CMD
  110. %s LOCAL_CMD
  111. %s SHOW_CMD
  112. %s MODE_CMD
  113. %s MAINT_CMD
  114. %s NOCMD
  115. %s PATH_ACCEPTED
  116. %x PATH_EXPECTED
  117. %x ASTRING_EXPECTED
  118. %x NOPROCESS
  119. %%
  120. /* set to special state when no process is loaded. */
  121. if (!dbg_num_processes() && YYSTATE == INITIAL) {BEGIN(NOPROCESS);}
  122. <<EOF>> { return tEOF; }
  123. <*>\n { BEGIN(INITIAL); syntax_error = 0; return tEOL; }
  124. /* Indicates end of command. Reset state. */
  125. "||" { return OP_LOR; }
  126. "&&" { return OP_LAND; }
  127. "==" { return OP_EQ; }
  128. "!=" { return OP_NE; }
  129. "<=" { return OP_LE; }
  130. ">=" { return OP_GE; }
  131. "<<" { return OP_SHL; }
  132. ">>" { return OP_SHR; }
  133. "->" { return OP_DRF; }
  134. "::" { return OP_SCOPE; }
  135. "[" { return *yytext; }
  136. "]" { return *yytext; }
  137. "0x"{HEXDIGIT}+ { sscanf(yytext, "%lx", &dbg_lval.integer); return tNUM; }
  138. {DIGIT}+ { sscanf(yytext, "%ld", &dbg_lval.integer); return tNUM; }
  139. "'\\''" { dbg_lval.integer = '\''; return tNUM;}
  140. "'\\0"{OCTDIGIT}*"'" { sscanf(yytext + 3, "%lo", &dbg_lval.integer); return tNUM;}
  141. "'\\x"{HEXDIGIT}+"'" { sscanf(yytext + 3, "%lx", &dbg_lval.integer); return tNUM;}
  142. "'\\"[a-z]"'" { dbg_lval.integer = yytext[2] - 'a'; return tNUM;}
  143. "'"."'" { dbg_lval.integer = yytext[1]; return tNUM;}
  144. <FORMAT_EXPECTED>"/"{DIGIT}+{FORMAT} { char* last;
  145. dbg_lval.integer = strtol(yytext+1, &last, 0) << 8;
  146. dbg_lval.integer |= *last;
  147. return tFORMAT; }
  148. <FORMAT_EXPECTED>"/"{FORMAT} { dbg_lval.integer = (1 << 8) | yytext[1]; return tFORMAT; }
  149. {STRING} { dbg_lval.string = lexeme_alloc(yytext + 1); dbg_lval.string[strlen(dbg_lval.string) - 1] = '\0'; return tSTRING; }
  150. <ASTRING_EXPECTED>[^\n]+ { char* p = yytext; while (*p == ' ' || *p == '\t') p++;
  151. dbg_lval.string = lexeme_alloc(p); return tSTRING; }
  152. <INITIAL,NOPROCESS>info|inf|in { BEGIN(INFO_CMD); return tINFO; }
  153. <INITIAL>up { BEGIN(NOCMD); return tUP; }
  154. <INITIAL>down|dow|do { BEGIN(NOCMD); return tDOWN; }
  155. <INITIAL,INFO_CMD>frame|fram|fra|fr { BEGIN(NOCMD); return tFRAME; }
  156. <INITIAL>list|lis|li|l { BEGIN(PATH_ACCEPTED); return tLIST; }
  157. <INITIAL>enable|enabl|enab|ena { BEGIN(BD_CMD); return tENABLE;}
  158. <INITIAL>disable|disabl|disab|disa|dis { BEGIN(BD_CMD); return tDISABLE; }
  159. <INITIAL>disassemble|disassembl|disassemb|disassem|disasse|disass|disas { BEGIN(NOCMD); return tDISASSEMBLE; }
  160. <INITIAL>locally|local { BEGIN(LOCAL_CMD); return tLOCAL; }
  161. <INITIAL,LOCAL_CMD>display|displa|displ|disp { BEGIN(FORMAT_EXPECTED); return tDISPLAY; }
  162. <INFO_CMD,BD_CMD>display|displa|displ|disp|dis|di|d { BEGIN(NOCMD); return tDISPLAY; }
  163. <INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und { BEGIN(NOCMD); return tUNDISPLAY; }
  164. <INITIAL>delete|delet|dele|del { BEGIN(BD_CMD); return tDELETE; }
  165. <INITIAL>thread|threa|thre|thr|th { BEGIN(NOCMD); return tTHREAD; }
  166. <INITIAL,NOPROCESS>quit|qui|qu|q { BEGIN(NOCMD); return tQUIT; }
  167. <INITIAL>set|se { BEGIN(NOCMD); return tSET; }
  168. <INITIAL>x { BEGIN(FORMAT_EXPECTED); return tEXAM; }
  169. <INITIAL,NOPROCESS>help|hel|he|"?" { BEGIN(HELP_CMD); return tHELP; }
  170. <INITIAL,NOPROCESS>backtrace|backtrac|backtra|backt|back|bac|ba|bt { BEGIN(NOCMD); return tBACKTRACE; }
  171. <INITIAL,NOPROCESS>where|wher|whe { BEGIN(NOCMD); return tBACKTRACE; }
  172. <INITIAL>cont|con|co|c { BEGIN(NOCMD); return tCONT; }
  173. <INITIAL>pass|pas|pa { BEGIN(NOCMD); return tPASS; }
  174. <INITIAL>condition|conditio|conditi|condit|condi|cond { BEGIN(NOCMD); return tCOND; }
  175. <INITIAL>step|ste|st|s { BEGIN(NOCMD); return tSTEP; }
  176. <INITIAL>next|nex|ne|n { BEGIN(NOCMD); return tNEXT; }
  177. <INITIAL>stepi|si { BEGIN(NOCMD); return tSTEPI; }
  178. <INITIAL>nexti|ni { BEGIN(NOCMD); return tNEXTI; }
  179. <INITIAL>finish|finis|fini|fin|fi { BEGIN(NOCMD); return tFINISH; }
  180. <INITIAL>abort|abor|abo { BEGIN(NOCMD); return tABORT; }
  181. <INITIAL>print|prin|pri|pr|p { BEGIN(FORMAT_EXPECTED); return tPRINT; }
  182. <INITIAL>show|sho|sh { BEGIN(SHOW_CMD); return tSHOW; }
  183. <INITIAL,NOPROCESS>source|sourc|sour|src { BEGIN(PATH_EXPECTED); return tSOURCE; }
  184. <INITIAL>symbolfile|symbols|symbol|sf { BEGIN(PATH_EXPECTED); return tSYMBOLFILE; }
  185. <INITIAL,INFO_CMD,BD_CMD>break|brea|bre|br|b { BEGIN(PATH_ACCEPTED); return tBREAK; }
  186. <INITIAL,INFO_CMD,BD_CMD>hbreak|hbrea|hbre|hbr|hb { BEGIN(PATH_ACCEPTED); return tHBREAK; }
  187. <INITIAL>watch|watc|wat { BEGIN(NOCMD); return tWATCH; }
  188. <INITIAL>rwatch|rwatc|rwat { BEGIN(NOCMD); return tRWATCH; }
  189. <INITIAL>whatis|whati|what { BEGIN(NOCMD); return tWHATIS; }
  190. <INITIAL,NOPROCESS>run|ru|r { BEGIN(ASTRING_EXPECTED); return tRUN;}
  191. <INITIAL>detach|detac|deta|det { BEGIN(NOCMD); return tDETACH; }
  192. <INITIAL>kill|kil|ki|k { BEGIN(NOCMD); return tKILL; }
  193. <INITIAL,NOPROCESS>maintenance|maint { BEGIN(MAINT_CMD); return tMAINTENANCE; }
  194. <INITIAL>minidump|mdmp { BEGIN(PATH_EXPECTED); return tMINIDUMP; }
  195. <INITIAL>echo { BEGIN(ASTRING_EXPECTED); return tECHO; }
  196. <NOPROCESS>attach|attac|atta|att { BEGIN(NOCMD); return tATTACH; }
  197. <INFO_CMD>share|shar|sha { return tSHARE; }
  198. <MAINT_CMD>module|modul|mod { BEGIN(ASTRING_EXPECTED); return tMODULE; }
  199. <INFO_CMD>locals|local|loca|loc { return tLOCAL; }
  200. <INFO_CMD>class|clas|cla { return tCLASS; }
  201. <INFO_CMD>process|proces|proce|proc { return tPROCESS; }
  202. <INFO_CMD>threads|thread|threa|thre|thr|th { return tTHREAD; }
  203. <INFO_CMD>exception|except|exc|ex { return tEXCEPTION; }
  204. <INFO_CMD>registers|regs|reg|re { return tREGS; }
  205. <INFO_CMD>allregs|allreg|allre { return tALLREGS; }
  206. <INFO_CMD>"all-registers"|"all-regs"|"all-reg"|"all-re" { return tALLREGS; }
  207. <INFO_CMD>segments|segment|segm|seg|se { return tSEGMENTS; }
  208. <INFO_CMD>stack|stac|sta|st { return tSTACK; }
  209. <INFO_CMD>symbol|symbo|symb|sym { BEGIN(ASTRING_EXPECTED); return tSYMBOL; }
  210. <INFO_CMD>maps|map { return tMAPS; }
  211. <INFO_CMD>window|windo|wind|win|wnd { return tWND; }
  212. <HELP_CMD>info|inf|in { return tINFO; }
  213. <MAINT_CMD>type { return tTYPE; }
  214. <INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir {
  215. BEGIN(PATH_EXPECTED); return tDIR; }
  216. char { return tCHAR; }
  217. short { return tSHORT; }
  218. int { return tINT; }
  219. long { return tLONG; }
  220. float { return tFLOAT; }
  221. double { return tDOUBLE; }
  222. unsigned { return tUNSIGNED; }
  223. signed { return tSIGNED; }
  224. struct { return tSTRUCT; }
  225. union { return tUNION; }
  226. enum { return tENUM; }
  227. all { return tALL; }
  228. {IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; }
  229. "$"{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext+1); return tINTVAR; }
  230. <PATH_EXPECTED,PATH_ACCEPTED>{PATHNAME} { dbg_lval.string = lexeme_alloc(yytext); return tPATH; }
  231. [-+<=>|&^()*/%:!~,\.] { return *yytext; }
  232. <*>[ \t\r]+ /* Eat up whitespace and DOS LF */
  233. <NOPROCESS>. { BEGIN(ASTRING_EXPECTED); yyless(0); return tNOPROCESS;}
  234. <*>. { if (syntax_error == 0) { syntax_error++; dbg_printf("Syntax Error (%s)\n", yytext); } }
  235. %%
  236. #ifndef dbg_wrap
  237. int dbg_wrap(void) { return 1; }
  238. #endif