1 %pointer /* Make yytext a pointer, not an array */ 2 3 %{ 4 /* 5 * CDDL HEADER START 6 * 7 * The contents of this file are subject to the terms of the 8 * Common Development and Distribution License (the "License"). 9 * You may not use this file except in compliance with the License. 10 * 11 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 12 * or http://www.opensolaris.org/os/licensing. 13 * See the License for the specific language governing permissions 14 * and limitations under the License. 15 * 16 * When distributing Covered Code, include this CDDL HEADER in each 17 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 18 * If applicable, add the following below this CDDL HEADER, with the 19 * fields enclosed by brackets "[]" replaced with your own identifying 20 * information: Portions Copyright [yyyy] [name of copyright owner] 21 * 22 * CDDL HEADER END 23 * 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* 29 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/isa_defs.h> 34 35 #include <strings.h> 36 #include <stdarg.h> 37 #include <stdlib.h> 38 #include <stdio.h> 39 #include <errno.h> 40 41 #include <mdb/mdb_types.h> 42 #include <mdb/mdb_debug.h> 43 #include <mdb/mdb_nv.h> 44 #include <mdb/mdb_lex.h> 45 #include <mdb/mdb_frame.h> 46 #include <mdb/mdb_string.h> 47 #include <mdb/mdb_stdlib.h> 48 #include <mdb/mdb_err.h> 49 #include <mdb/mdb.h> 50 51 #include "mdb_grammar.h" 52 53 /* 54 * lex hardcodes yyin and yyout to stdin and stdout, respectively, before we get 55 * control. We've redirected printf and fprintf (see mdb_lex.h) to yyprintf and 56 * yyfprintf, which ignore the FILE * provided by yyout. __iob-based stdin and 57 * stdout are useless in kmdb, since we don't have stdio. We define __iob here 58 * to shut the linker up. 59 */ 60 #ifdef _KMDB 61 FILE __iob[_NFILE]; 62 #endif 63 64 /* 65 * We need to undefine lex's input, unput, and output macros so that references 66 * to these call the functions we provide at the end of this source file, 67 * instead of the default versions based on libc's stdio. 68 */ 69 #ifdef input 70 #undef input 71 #endif 72 73 #ifdef unput 74 #undef unput 75 #endif 76 77 #ifdef output 78 #undef output 79 #endif 80 81 static int input(void); 82 static void unput(int); 83 static void output(int); 84 85 static void string_unquote(char *); 86 87 extern int yydebug; 88 89 /* 90 * This will prevent lex from trying to malloc() and resize our yytext variable, 91 * instead it will just print out an error message and exit(), which seems 92 * a lesser of two evils. 93 */ 94 #define YYISARRAY 95 96 %} 97 98 %o 9000 99 %a 5000 100 101 %s S_SHELLCMD 102 %s S_INITIAL 103 %s S_FMTLIST 104 %s S_ARGLIST 105 %s S_EXPR 106 107 RGX_CMD_CHAR [?%@A-Z\^_`a-z] 108 RGX_SYMBOL [a-zA-Z_.][0-9a-zA-Z_.`]* 109 RGX_SIMPLE_CHAR [^ \t\n;!|"'\$] 110 RGX_CHR_SEQ ([^'\n]|\\[^'\n]|\\')* 111 RGX_STR_SEQ ([^"\\\n]|\\[^"\n]|\\\")* 112 RGX_COMMENT "//".*\n 113 114 %% 115 116 <S_INITIAL>{RGX_COMMENT} | 117 <S_FMTLIST>{RGX_COMMENT} | 118 <S_ARGLIST>{RGX_COMMENT} { 119 /* 120 * Comments are legal in these three states -- if we see one 121 * eat the line and return the newline character. 122 */ 123 BEGIN(S_INITIAL); 124 return ('\n'); 125 } 126 127 <S_INITIAL>"==" | 128 <S_EXPR>"==" return (MDB_TOK_EQUAL); /* Equality operator */ 129 130 <S_INITIAL>"!=" | 131 <S_EXPR>"!=" return (MDB_TOK_NOTEQUAL); /* Inequality operator */ 132 133 <S_INITIAL>"!" | 134 <S_FMTLIST>"!" | 135 <S_ARGLIST>"!" { 136 /* 137 * Shell escapes are legal in all of these states -- switch to 138 * the shell command state and return the ! character. 139 */ 140 BEGIN(S_SHELLCMD); 141 return (yytext[0]); 142 } 143 144 <S_FMTLIST>"|" | 145 <S_ARGLIST>"|" { 146 /* 147 * Pipelines can appear in any of these states -- switch to 148 * the initial state and return the | character. 149 */ 150 BEGIN(S_INITIAL); 151 return (yytext[0]); 152 } 153 154 <S_SHELLCMD>[^;\n]+ { 155 /* 156 * Once in the shell-command state, we return all remaining 157 * characters up to a newline or ';' delimiter as a single 158 * string which will be passed to $SHELL -c. 159 */ 160 yylval.l_string = strdup(yytext); 161 BEGIN(S_INITIAL); 162 return (MDB_TOK_STRING); 163 } 164 165 <S_INITIAL>"::"{RGX_SYMBOL} { 166 /* 167 * Verb ::command-name -- lookup the correspond dcmd and 168 * switch to the argument list state. 169 */ 170 if ((yylval.l_dcmd = mdb_dcmd_lookup(yytext + 2)) == NULL) 171 yyperror("invalid command '%s'", yytext); 172 173 BEGIN(S_ARGLIST); 174 return (MDB_TOK_DCMD); 175 } 176 177 <S_INITIAL>"$<<"|"$<"|"$>" | 178 <S_INITIAL>[\$:]{RGX_CMD_CHAR} { 179 /* 180 * Old-style :c or $c command -- lookup the corresponding dcmd 181 * and switch to the argument list state. 182 */ 183 if ((yylval.l_dcmd = mdb_dcmd_lookup(yytext)) == NULL) 184 yyperror("invalid command '%s'", yytext); 185 186 BEGIN(S_ARGLIST); 187 return (MDB_TOK_DCMD); 188 } 189 190 <S_INITIAL>">/"[a-zA-Z0-9]"/" { 191 /* 192 * Variable assignment with size cast -- append the cast letter 193 * to the argument list, and switch to the argument list state. 194 */ 195 mdb_arg_t arg; 196 197 arg.a_un.a_char = yytext[2]; 198 arg.a_type = MDB_TYPE_CHAR; 199 200 mdb_argvec_append(&mdb.m_frame->f_argvec, &arg); 201 yylval.l_dcmd = mdb_dcmd_lookup(">"); 202 203 BEGIN(S_ARGLIST); 204 return (MDB_TOK_DCMD); 205 } 206 207 <S_INITIAL>">" { 208 /* 209 * Variable assignment -- switch to the argument list state. 210 */ 211 yylval.l_dcmd = mdb_dcmd_lookup(yytext); 212 BEGIN(S_ARGLIST); 213 return (MDB_TOK_DCMD); 214 } 215 216 <S_INITIAL>[/\\?][ \t]*[vwWZlLM] { 217 /* 218 * Format verb followed by write or match signifier -- switch 219 * to the value list state and return the verb character. We 220 * also append the actual format character to the arg list. 221 */ 222 mdb_arg_t arg; 223 224 arg.a_un.a_char = yytext[yyleng - 1]; 225 arg.a_type = MDB_TYPE_CHAR; 226 227 mdb_argvec_append(&mdb.m_frame->f_argvec, &arg); 228 229 BEGIN(S_ARGLIST); 230 return yytext[0]; 231 } 232 233 <S_INITIAL>[/\\@?=] { 234 /* 235 * Format verb -- switch to the format list state and return 236 * the actual verb character verbatim. 237 */ 238 BEGIN(S_FMTLIST); 239 return (yytext[0]); 240 } 241 242 <S_INITIAL>'{RGX_CHR_SEQ}$ | 243 <S_EXPR>'{RGX_CHR_SEQ}$ yyerror("syntax error: ' unmatched"); 244 245 <S_INITIAL>'{RGX_CHR_SEQ}' | 246 <S_EXPR>'{RGX_CHR_SEQ}' { 247 char *s, *p, *q; 248 size_t nbytes; 249 250 /* 251 * If the character sequence is zero-length, return 0. 252 */ 253 if (yyleng == 2) { 254 yylval.l_immediate = 0; 255 return (MDB_TOK_IMMEDIATE); 256 } 257 258 s = yytext + 1; /* Skip past initial quote */ 259 yytext[yyleng - 1] = '\0'; /* Overwrite final quote */ 260 nbytes = stresc2chr(s); /* Convert escapes */ 261 yylval.l_immediate = 0; /* Initialize token value */ 262 263 if (nbytes > sizeof (uintmax_t)) { 264 yyerror("character constant may not exceed %lu bytes\n", 265 (ulong_t)sizeof (uintmax_t)); 266 } 267 268 #ifdef _LITTLE_ENDIAN 269 p = ((char*)&yylval.l_immediate) + nbytes - 1; 270 271 for (q = s; nbytes != 0; nbytes--) 272 *p-- = *q++; 273 #else 274 bcopy(s, ((char *)&yylval.l_immediate) + 275 sizeof (uintmax_t) - nbytes, nbytes); 276 #endif 277 return (MDB_TOK_IMMEDIATE); 278 } 279 280 \"{RGX_STR_SEQ}$ yyerror("syntax error: \" unmatched"); 281 282 \"{RGX_STR_SEQ}\" { 283 /* 284 * Quoted string -- convert C escape sequences and return the 285 * string as a token. 286 */ 287 yylval.l_string = strndup(yytext + 1, yyleng - 2); 288 (void) stresc2chr(yylval.l_string); 289 return (MDB_TOK_STRING); 290 } 291 292 <S_ARGLIST>"$[" | 293 <S_FMTLIST>"$[" { 294 /* 295 * Start of expression -- begin expression state and save the 296 * current state so we can return at the end of the expression. 297 */ 298 mdb.m_frame->f_oldstate = YYSTATE; 299 BEGIN(S_EXPR); 300 return (MDB_TOK_LEXPR); 301 } 302 303 <S_ARGLIST>{RGX_SIMPLE_CHAR}*("'"{RGX_CHR_SEQ}"'"|\"{RGX_STR_SEQ}\"|{RGX_SIMPLE_CHAR}+)* { 304 /* 305 * String token -- create a copy of the string and return it. 306 * We need to handle embedded single and double-quote pairs, 307 * which overcomplicates this slightly. 308 */ 309 yylval.l_string = strdup(yytext); 310 string_unquote(yylval.l_string); 311 return (MDB_TOK_STRING); 312 } 313 314 <S_FMTLIST>[0-9]+ { 315 /* 316 * Immediate value -- in the format list, all immediates 317 * are assumed to be in decimal. 318 */ 319 yylval.l_immediate = strtonum(yytext, 10); 320 return (MDB_TOK_IMMEDIATE); 321 } 322 323 <S_FMTLIST>{RGX_SIMPLE_CHAR} { 324 /* 325 * Non-meta character -- in the format list, we return each 326 * character as a separate token to be added as an argument. 327 */ 328 yylval.l_char = yytext[0]; 329 return (MDB_TOK_CHAR); 330 } 331 332 <S_EXPR>";"|"!"|\n { 333 /* 334 * In the expression state only, we cannot see a command 335 * delimiter or shell escape before we end the expression. 336 */ 337 yyerror("syntax error: $[ unmatched"); 338 } 339 340 <S_EXPR>"]" { 341 /* 342 * End of expression state. Restore the state we were in 343 * before the "$[" which started this expression. 344 */ 345 BEGIN(mdb.m_frame->f_oldstate); 346 return (MDB_TOK_REXPR); 347 } 348 349 <S_INITIAL>"<"{RGX_SYMBOL} | 350 <S_INITIAL>"<"[0-9] | 351 <S_EXPR>"<"{RGX_SYMBOL} | 352 <S_EXPR>"<"[0-9] { 353 /* 354 * Variable reference -- lookup the variable and return a 355 * pointer to it. Referencing undefined variables is an error. 356 */ 357 yylval.l_var = mdb_nv_lookup(&mdb.m_nv, &yytext[1]); 358 359 if (yylval.l_var == NULL) 360 yyerror("variable '%s' is not defined", &yytext[1]); 361 362 return (MDB_TOK_VAR_REF); 363 } 364 365 <S_INITIAL>"<<" | 366 <S_EXPR>"<<" return (MDB_TOK_LSHIFT); /* Logical shift left operator */ 367 368 <S_INITIAL>">>" | 369 <S_EXPR>">>" return (MDB_TOK_RSHIFT); /* Logical shift right operator */ 370 371 <S_INITIAL>"*/"[a-zA-Z0-9]"/" | 372 <S_EXPR>"*/"[a-zA-Z0-9]"/" { 373 switch (yytext[2]) { 374 case 'c': case '1': 375 return (MDB_TOK_COR1_DEREF); 376 case 's': case '2': 377 return (MDB_TOK_COR2_DEREF); 378 case 'i': case '4': 379 #ifdef _ILP32 380 case 'l': 381 #endif 382 return (MDB_TOK_COR4_DEREF); 383 #ifdef _LP64 384 case 'l': 385 #endif 386 case '8': 387 return (MDB_TOK_COR8_DEREF); 388 } 389 yyerror("invalid cast -- %s\n", yytext); 390 } 391 392 <S_INITIAL>"%/"[a-zA-Z0-9]"/" | 393 <S_EXPR>"%/"[a-zA-Z0-9]"/" { 394 switch (yytext[2]) { 395 case 'c': case '1': 396 return (MDB_TOK_OBJ1_DEREF); 397 case 's': case '2': 398 return (MDB_TOK_OBJ2_DEREF); 399 case 'i': case '4': 400 #ifdef _ILP32 401 case 'l': 402 #endif 403 return (MDB_TOK_OBJ4_DEREF); 404 #ifdef _LP64 405 case 'l': 406 #endif 407 case '8': 408 return (MDB_TOK_OBJ8_DEREF); 409 } 410 yyerror("invalid cast -- %s\n", yytext); 411 } 412 413 <S_INITIAL>0[iI][0-1]+ | 414 <S_EXPR>0[iI][0-1]+ { 415 /* 416 * Binary immediate value. 417 */ 418 yylval.l_immediate = strtonum(yytext + 2, 2); 419 return (MDB_TOK_IMMEDIATE); 420 } 421 422 <S_INITIAL>0[oO][0-7]+ | 423 <S_EXPR>0[oO][0-7]+ { 424 /* 425 * Octal immediate value. 426 */ 427 yylval.l_immediate = strtonum(yytext + 2, 8); 428 return (MDB_TOK_IMMEDIATE); 429 } 430 431 <S_INITIAL>0[tT][0-9]+"."[0-9]+ | 432 <S_EXPR>0[tT][0-9]+"."[0-9]+ { 433 #ifdef _KMDB 434 yyerror("floating point not supported\n"); 435 #else 436 /* 437 * Decimal floating point value. 438 */ 439 char *p, c; 440 double d; 441 int i; 442 443 if ((p = strsplit(yytext, '.')) == NULL) 444 yyerror("internal scanning error -- expected '.'\n"); 445 446 d = (double)strtonum(yytext + 2, 10); 447 448 for (i = 0; (c = *p++) != '\0'; i++) 449 d = d * 10 + c - '0'; 450 451 while (i-- != 0) 452 d /= 10; 453 454 yylval.l_immediate = *((uintmax_t *)&d); 455 return (MDB_TOK_IMMEDIATE); 456 #endif 457 } 458 459 <S_INITIAL>0[tT][0-9]+ | 460 <S_EXPR>0[tT][0-9]+ { 461 /* 462 * Decimal immediate value. 463 */ 464 yylval.l_immediate = strtonum(yytext + 2, 10); 465 return (MDB_TOK_IMMEDIATE); 466 } 467 468 <S_INITIAL>0[xX][0-9a-fA-F]+ | 469 <S_EXPR>0[xX][0-9a-fA-F]+ { 470 /* 471 * Hexadecimal value. 472 */ 473 yylval.l_immediate = strtonum(yytext + 2, 16); 474 return (MDB_TOK_IMMEDIATE); 475 } 476 477 <S_INITIAL>[0-9a-fA-F]+ | 478 <S_EXPR>[0-9a-fA-F]+ { 479 GElf_Sym sym; 480 /* 481 * Immediate values without an explicit base are converted 482 * using the default radix (user configurable). However, if 483 * the token does *not* begin with a digit, it is also a 484 * potential symbol (e.g. "f") so we have to check that first. 485 */ 486 if (strchr("0123456789", yytext[0]) == NULL && 487 mdb_tgt_lookup_by_name(mdb.m_target, 488 MDB_TGT_OBJ_EVERY, yytext, &sym, NULL) == 0) 489 yylval.l_immediate = (uintmax_t)sym.st_value; 490 else 491 yylval.l_immediate = strtonum(yytext, mdb.m_radix); 492 return (MDB_TOK_IMMEDIATE); 493 } 494 495 <S_INITIAL>{RGX_SYMBOL} | 496 <S_EXPR>{RGX_SYMBOL} { 497 /* 498 * Symbol -- parser will look up in symbol table. 499 */ 500 yylval.l_string = strdup(yytext); 501 return (MDB_TOK_SYMBOL); 502 } 503 504 ";"|\n { 505 /* 506 * End of command -- return to start state and return literal. 507 */ 508 BEGIN(S_INITIAL); 509 return (yytext[0]); 510 } 511 512 [ \t] ; /* Ignore whitespace */ 513 514 . return (yytext[0]); /* Return anything else */ 515 516 %% 517 518 void 519 mdb_lex_debug(int i) 520 { 521 yydebug = i; 522 } 523 524 void 525 mdb_lex_reset(void) 526 { 527 BEGIN(S_INITIAL); 528 } 529 530 void 531 yydiscard(void) 532 { 533 int c; 534 535 /* 536 * If stdin is a string, pipeline, or tty, throw away all our buffered 537 * data. Otherwise discard characters up to the next likely delimiter. 538 */ 539 if (mdb_iob_isastr(mdb.m_in) || mdb_iob_isatty(mdb.m_in) || 540 mdb_iob_isapipe(mdb.m_in)) 541 mdb_iob_discard(mdb.m_in); 542 else { 543 while ((c = mdb_iob_getc(mdb.m_in)) != (int)EOF) { 544 if (c == ';' || c == '\n') 545 break; 546 } 547 } 548 549 BEGIN(S_INITIAL); 550 } 551 552 static void 553 yyerror_reset(void) 554 { 555 yydiscard(); 556 mdb_argvec_reset(&mdb.m_frame->f_argvec); 557 longjmp(mdb.m_frame->f_pcb, MDB_ERR_PARSE); 558 } 559 560 void 561 yyerror(const char *format, ...) 562 { 563 va_list alist; 564 char *s; 565 566 mdb_iob_printf(mdb.m_err, "%s: ", mdb.m_pname); 567 va_start(alist, format); 568 mdb_iob_vprintf(mdb.m_err, format, alist); 569 va_end(alist); 570 571 if (strchr(format, '\n') == NULL) { 572 if (!mdb_iob_isatty(mdb.m_in)) { 573 mdb_iob_printf(mdb.m_err, " on line %d of %s", 574 yylineno, mdb_iob_name(mdb.m_in)); 575 } 576 577 s = strchr2esc(yytext, strlen(yytext)); 578 mdb_iob_printf(mdb.m_err, " near \"%s\"\n", s); 579 strfree(s); 580 } 581 582 yyerror_reset(); 583 } 584 585 void 586 yyperror(const char *format, ...) 587 { 588 va_list alist; 589 590 va_start(alist, format); 591 vwarn(format, alist); 592 va_end(alist); 593 594 yyerror_reset(); 595 } 596 597 int 598 yywrap(void) 599 { 600 mdb_dprintf(MDB_DBG_PARSER, "yywrap at line %d\n", yylineno); 601 return (1); /* indicate that lex should return a zero token for EOF */ 602 } 603 604 /*PRINTFLIKE2*/ 605 /*ARGSUSED*/ 606 int 607 yyfprintf(FILE *stream, const char *format, ...) 608 { 609 va_list alist; 610 611 va_start(alist, format); 612 mdb_iob_vprintf(mdb.m_err, format, alist); 613 va_end(alist); 614 return (0); 615 } 616 617 /*PRINTFLIKE1*/ 618 int 619 yyprintf(const char *format, ...) 620 { 621 va_list alist; 622 623 va_start(alist, format); 624 mdb_iob_vprintf(mdb.m_err, format, alist); 625 va_end(alist); 626 return (0); 627 } 628 629 static int 630 input(void) 631 { 632 int c = mdb_iob_getc(mdb.m_in); 633 634 if (c == '\n') 635 yylineno++; 636 637 return (c == EOF ? 0 : c); 638 } 639 640 static void 641 unput(int c) 642 { 643 if (c == '\n') 644 yylineno--; 645 646 (void) mdb_iob_ungetc(mdb.m_in, c == 0 ? EOF : c); 647 } 648 649 static void 650 output(int c) 651 { 652 char ch = c; 653 mdb_iob_nputs(mdb.m_out, &ch, sizeof (ch)); 654 } 655 656 static char * 657 string_nextquote(char *s, char q1, char q2) 658 { 659 char c = 0; 660 661 do { 662 if (c != '\\' && (*s == q1 || *s == q2)) 663 return (s); 664 } while ((c = *s++) != '\0'); 665 666 return (NULL); 667 } 668 669 static void 670 string_unquote(char *s) 671 { 672 char *o, *p, *q, c; 673 674 for (o = p = s; (p = string_nextquote(p, '\'', '"')) != NULL; o = p) { 675 /* 676 * If the quote wasn't the first character, advance 677 * the destination buffer past what we skipped. 678 */ 679 if (p > o) { 680 /* Using memmove to prevent possible overlap. */ 681 (void) memmove(s, o, p - o); 682 s += p - o; 683 } 684 685 c = *p; /* Save the current quote */ 686 687 /* 688 * Look ahead and find the matching quote. If none is 689 * found, use yyerror to longjmp out of the lexer. 690 */ 691 if (c == '"') 692 q = string_nextquote(p + 1, c, c); 693 else 694 q = strchr(p + 1, c); 695 696 if (q == NULL) 697 yyerror("syntax error: %c unmatched", c); 698 699 /* 700 * If the string is non-empty, copy it to the destination 701 * and convert escape sequences if *p is double-quote. 702 */ 703 if (q > p + 1) { 704 (void) memmove(s, p + 1, q - p - 1); 705 if (c == '"') { 706 s[q - p - 1] = '\0'; 707 s += stresc2chr(s); 708 } else 709 s += q - p - 1; 710 } 711 712 p = q + 1; /* Advance p past matching quote */ 713 } 714 715 (void) memmove(s, o, strlen(o) + 1); 716 } 717 718 /* 719 * Unfortunately, lex and yacc produces code that is inherently global. They do 720 * not provide routines to save and restore state, instead relying on global 721 * variables. There is one single lex state, so that if a frame switch then 722 * tries to perform any evaluation, the old values are corrupted. This 723 * structure and corresponding function provide a means of preserving lex state 724 * across frame switches. Note that this is tied to the lex implementation, so 725 * if the lex compiler is changed or upgraded to a different format, then this 726 * may need to be altered. This is unavoidable due to the implementation of lex 727 * and yacc. This is essentially a collection of all the global variables 728 * defined by the lex code, excluding those that do not change through the 729 * course of yylex() and yyparse(). 730 */ 731 extern struct yysvf *yylstate[], **yylsp, **yyolsp; extern int yyprevious; 732 extern int *yyfnd; 733 734 extern YYSTYPE *yypv; 735 extern int *yyps; 736 extern int yytmp; 737 extern int yystate; 738 extern int yynerrs; 739 extern int yyerrflag; 740 extern int yychar; 741 extern YYSTYPE yylval; 742 extern YYSTYPE yyval; 743 extern int *yys; 744 extern YYSTYPE *yyv; 745 746 typedef struct mdb_lex_state { 747 /* Variables needed by yylex */ 748 int yyleng; 749 char yytext[YYLMAX]; 750 int yymorfg; 751 int yylineno; 752 void *yyestate; 753 void *yylstate[BUFSIZ]; 754 void *yylsp; 755 void *yyolsp; 756 int *yyfnd; 757 int yyprevious; 758 void *yybgin; 759 /* Variables needed by yyparse */ 760 void *yypv; 761 int *yyps; 762 int yytmp; 763 int yystate; 764 int yynerrs; 765 int yyerrflag; 766 int yychar; 767 YYSTYPE yylval; 768 YYSTYPE yyval; 769 int yys[YYMAXDEPTH]; 770 YYSTYPE yyv[YYMAXDEPTH]; 771 } mdb_lex_state_t; 772 773 void 774 mdb_lex_state_save(mdb_lex_state_t *s) 775 { 776 ASSERT(s != NULL); 777 778 s->yyleng = yyleng; 779 s->yymorfg = yymorfg; 780 s->yylineno = yylineno; 781 s->yyestate = yyestate; 782 bcopy(yylstate, s->yylstate, YYLMAX * sizeof (void *)); 783 s->yylsp = yylsp; 784 s->yyolsp = yyolsp; 785 s->yyfnd = yyfnd; 786 s->yyprevious = yyprevious; 787 s->yybgin = yybgin; 788 789 s->yypv = yypv; 790 s->yyps = yyps; 791 s->yystate = yystate; 792 s->yytmp = yytmp; 793 s->yynerrs = yynerrs; 794 s->yyerrflag = yyerrflag; 795 s->yychar = yychar; 796 s->yylval = yylval; 797 s->yyval = yyval; 798 } 799 800 void 801 mdb_lex_state_restore(mdb_lex_state_t *s) 802 { 803 ASSERT(s != NULL); 804 805 yyleng = s->yyleng; 806 yytext = s->yytext; 807 yymorfg = s->yymorfg; 808 yylineno = s->yylineno; 809 yyestate = s->yyestate; 810 bcopy(s->yylstate, yylstate, YYLMAX * sizeof (void *)); 811 yylsp = s->yylsp; 812 yyolsp = s->yyolsp; 813 yyfnd = s->yyfnd; 814 yyprevious = s->yyprevious; 815 yybgin = s->yybgin; 816 817 yypv = s->yypv; 818 yyps = s->yyps; 819 yystate = s->yystate; 820 yytmp = s->yytmp; 821 yynerrs = s->yynerrs; 822 yyerrflag = s->yyerrflag; 823 yychar = s->yychar; 824 yylval = s->yylval; 825 yyval = s->yyval; 826 yys = s->yys; 827 yyv = s->yyv; 828 } 829 830 /* 831 * Create and initialize the lex/yacc-specific state associated with a frame 832 * structure. We set all fields to known safe values so that 833 * mdb_lex_state_restore() can be used safely before mdb_lex_state_save(). 834 */ 835 void 836 mdb_lex_state_create(mdb_frame_t *f) 837 { 838 f->f_lstate = mdb_alloc(sizeof (mdb_lex_state_t), UM_SLEEP); 839 840 yyleng = 0; 841 yymorfg = 0; 842 /* yytext is fine with garbage in it */ 843 yytext = f->f_lstate->yytext; 844 yylineno = 1; 845 yyestate = NULL; 846 bzero(yylstate, YYLMAX * sizeof (void *)); 847 yylsp = NULL; 848 yyolsp = NULL; 849 yyfnd = 0; 850 yyprevious = YYNEWLINE; 851 yys = f->f_lstate->yys; 852 yyv = f->f_lstate->yyv; 853 mdb_argvec_create(&f->f_argvec); 854 f->f_oldstate = 0; 855 mdb_lex_reset(); /* Responsible for setting yybgin */ 856 } 857 858 void 859 mdb_lex_state_destroy(mdb_frame_t *f) 860 { 861 mdb_free(f->f_lstate, sizeof (mdb_lex_state_t)); 862 f->f_lstate = NULL; 863 mdb_argvec_destroy(&f->f_argvec); 864 } 865