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