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