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