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