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