dt_lex.l
来自「Sun Solaris 10 中的 DTrace 组件的源代码。请参看: htt」· L 代码 · 共 794 行 · 第 1/2 页
L
794 行
%{/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident "@(#)dt_lex.l 1.6 04/11/21 SMI"#include <string.h>#include <stdlib.h>#include <stdio.h>#include <assert.h>#include <ctype.h>#include <errno.h>#include <dt_impl.h>#include <dt_grammar.h>#include <dt_parser.h>#include <dt_string.h>/* * We need to undefine lex's input and unput macros so that references to these * call the functions provided at the end of this source file. */#undef input#undef unputstatic int id_or_type(const char *);static int input(void);static void unput(int);/* * We first define a set of labeled states for use in the D lexer and then a * set of regular expressions to simplify things below. The lexer states are: * * S0 - D program clause and expression lexing * S1 - D comments (i.e. skip everything until end of comment) * S2 - D program outer scope (probe specifiers and declarations) * S3 - D control line parsing (i.e. after ^# is seen but before \n) */%}%e 1400 /* maximum nodes */%p 3700 /* maximum positions */%s S0 S1 S2 S3RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?RGX_WS [\f\n\r\t\v ]RGX_STR ([^"\\\n]|\\[^"\n]|\\\")*RGX_CHR ([^'\\\n]|\\[^'\n]|\\')*RGX_INTERP ^[\f\t\v ]*#!.*RGX_CTL ^[\f\t\v ]*#%%%{/* * We insert a special prologue into yylex() itself: if the pcb contains a * context token, we return that prior to running the normal lexer. This * allows libdtrace to force yacc into one of our two parsing contexts: * parsing a D expression (DT_CTX_DEXPR) or a D program (DT_CTX_DPROG). * Once the token is returned, we clear it so this only happens once. */if (yypcb->pcb_token != 0) { int tok = yypcb->pcb_token; yypcb->pcb_token = 0; return (tok);}%}<S0>auto return (DT_KEY_AUTO);<S0>break return (DT_KEY_BREAK);<S0>case return (DT_KEY_CASE);<S0>char return (DT_KEY_CHAR);<S0>const return (DT_KEY_CONST);<S0>continue return (DT_KEY_CONTINUE);<S0>counter return (DT_KEY_COUNTER);<S0>default return (DT_KEY_DEFAULT);<S0>do return (DT_KEY_DO);<S0>double return (DT_KEY_DOUBLE);<S0>else return (DT_KEY_ELSE);<S0>enum return (DT_KEY_ENUM);<S0>extern return (DT_KEY_EXTERN);<S0>float return (DT_KEY_FLOAT);<S0>for return (DT_KEY_FOR);<S0>goto return (DT_KEY_GOTO);<S0>if return (DT_KEY_IF);<S0>import return (DT_KEY_IMPORT);<S0>inline return (DT_KEY_INLINE);<S0>int return (DT_KEY_INT);<S0>long return (DT_KEY_LONG);<S0>offsetof return (DT_TOK_OFFSETOF);<S0>probe return (DT_KEY_PROBE);<S0>provider return (DT_KEY_PROVIDER);<S0>register return (DT_KEY_REGISTER);<S0>restrict return (DT_KEY_RESTRICT);<S0>return return (DT_KEY_RETURN);<S0>self return (DT_KEY_SELF);<S0>short return (DT_KEY_SHORT);<S0>signed return (DT_KEY_SIGNED);<S0>sizeof return (DT_TOK_SIZEOF);<S0>static return (DT_KEY_STATIC);<S0>string return (DT_KEY_STRING);<S0>stringof return (DT_TOK_STRINGOF);<S0>struct return (DT_KEY_STRUCT);<S0>switch return (DT_KEY_SWITCH);<S0>this return (DT_KEY_THIS);<S0>translator return (DT_KEY_XLATOR);<S0>typedef return (DT_KEY_TYPEDEF);<S0>union return (DT_KEY_UNION);<S0>unsigned return (DT_KEY_UNSIGNED);<S0>void return (DT_KEY_VOID);<S0>volatile return (DT_KEY_VOLATILE);<S0>while return (DT_KEY_WHILE);<S0>xlate return (DT_TOK_XLATE);<S2>auto { yybegin(YYS_EXPR); return (DT_KEY_AUTO); }<S2>char { yybegin(YYS_EXPR); return (DT_KEY_CHAR); }<S2>const { yybegin(YYS_EXPR); return (DT_KEY_CONST); }<S2>counter { yybegin(YYS_DEFINE); return (DT_KEY_COUNTER); }<S2>double { yybegin(YYS_EXPR); return (DT_KEY_DOUBLE); }<S2>enum { yybegin(YYS_EXPR); return (DT_KEY_ENUM); }<S2>extern { yybegin(YYS_EXPR); return (DT_KEY_EXTERN); }<S2>float { yybegin(YYS_EXPR); return (DT_KEY_FLOAT); }<S2>import { yybegin(YYS_EXPR); return (DT_KEY_IMPORT); }<S2>inline { yybegin(YYS_DEFINE); return (DT_KEY_INLINE); }<S2>int { yybegin(YYS_EXPR); return (DT_KEY_INT); }<S2>long { yybegin(YYS_EXPR); return (DT_KEY_LONG); }<S2>provider { yybegin(YYS_DEFINE); return (DT_KEY_PROVIDER); }<S2>register { yybegin(YYS_EXPR); return (DT_KEY_REGISTER); }<S2>restrict { yybegin(YYS_EXPR); return (DT_KEY_RESTRICT); }<S2>self { yybegin(YYS_EXPR); return (DT_KEY_SELF); }<S2>short { yybegin(YYS_EXPR); return (DT_KEY_SHORT); }<S2>signed { yybegin(YYS_EXPR); return (DT_KEY_SIGNED); }<S2>static { yybegin(YYS_EXPR); return (DT_KEY_STATIC); }<S2>string { yybegin(YYS_EXPR); return (DT_KEY_STRING); }<S2>struct { yybegin(YYS_EXPR); return (DT_KEY_STRUCT); }<S2>this { yybegin(YYS_EXPR); return (DT_KEY_THIS); }<S2>translator { yybegin(YYS_DEFINE); return (DT_KEY_XLATOR); }<S2>typedef { yybegin(YYS_EXPR); return (DT_KEY_TYPEDEF); }<S2>union { yybegin(YYS_EXPR); return (DT_KEY_UNION); }<S2>unsigned { yybegin(YYS_EXPR); return (DT_KEY_UNSIGNED); }<S2>void { yybegin(YYS_EXPR); return (DT_KEY_VOID); }<S2>volatile { yybegin(YYS_EXPR); return (DT_KEY_VOLATILE); }<S0>"$$"[0-9]+ { int i = atoi(yytext + 2); char *v = ""; /* * A macro argument reference substitutes the text of * an argument in place of the current token. When we * see $$<d> we fetch the saved string from pcb_sargv * (or use the default argument if the option has been * set and the argument hasn't been specified) and * return a token corresponding to this string. */ if (i < 0 || (i >= yypcb->pcb_sargc && !(yypcb->pcb_cflags & DTRACE_C_DEFARG))) { xyerror(D_MACRO_UNDEF, "macro argument %s is " "not defined\n", yytext); } if (i < yypcb->pcb_sargc) { v = yypcb->pcb_sargv[i]; /* get val from pcb */ yypcb->pcb_sflagv[i] |= DT_IDFLG_REF; } if ((yylval.l_str = strdup(v)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); (void) stresc2chr(yylval.l_str); return (DT_TOK_STRING); }<S0>"$"[0-9]+ { int i = atoi(yytext + 1); char *p, *v = "0"; /* * A macro argument reference substitutes the text of * one identifier or integer pattern for another. When * we see $<d> we fetch the saved string from pcb_sargv * (or use the default argument if the option has been * set and the argument hasn't been specified) and * return a token corresponding to this string. */ if (i < 0 || (i >= yypcb->pcb_sargc && !(yypcb->pcb_cflags & DTRACE_C_DEFARG))) { xyerror(D_MACRO_UNDEF, "macro argument %s is " "not defined\n", yytext); } if (i < yypcb->pcb_sargc) { v = yypcb->pcb_sargv[i]; /* get val from pcb */ yypcb->pcb_sflagv[i] |= DT_IDFLG_REF; } /* * If the macro text is not a valid integer or ident, * then we treat it as a string. The string may be * optionally enclosed in quotes, which we strip. */ if (strbadidnum(v)) { size_t len = strlen(v); if (len != 1 && *v == '"' && v[len - 1] == '"') yylval.l_str = strndup(v + 1, len - 2); else yylval.l_str = strndup(v, len); if (yylval.l_str == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); (void) stresc2chr(yylval.l_str); return (DT_TOK_STRING); } /* * If the macro text is not a string an begins with a * digit or a +/- sign, process it as an integer token. */ if (isdigit(v[0]) || v[0] == '-' || v[0] == '+') { if (isdigit(v[0])) yyintprefix = 0; else yyintprefix = *v++; errno = 0; yylval.l_int = strtoull(v, &p, 0); (void) strncpy(yyintsuffix, p, sizeof (yyintsuffix)); yyintdecimal = *v != '0'; if (errno == ERANGE) { xyerror(D_MACRO_OFLOW, "macro argument" " %s constant %s results in integer" " overflow\n", yytext, v); } return (DT_TOK_INT); } return (id_or_type(v)); }<S0>"$$"{RGX_IDENT} { dt_ident_t *idp = dt_idhash_lookup( yypcb->pcb_hdl->dt_macros, yytext + 2); char s[16]; /* enough for UINT_MAX + \0 */ if (idp == NULL) { xyerror(D_MACRO_UNDEF, "macro variable %s " "is not defined\n", yytext); } /* * For the moment, all current macro variables are of * type id_t (refer to dtrace_update() for details). */ (void) snprintf(s, sizeof (s), "%u", idp->di_id); if ((yylval.l_str = strdup(s)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); return (DT_TOK_STRING); }<S0>"$"{RGX_IDENT} { dt_ident_t *idp = dt_idhash_lookup( yypcb->pcb_hdl->dt_macros, yytext + 1); if (idp == NULL) { xyerror(D_MACRO_UNDEF, "macro variable %s " "is not defined\n", yytext); } /* * For the moment, all current macro variables are of * type id_t (refer to dtrace_update() for details). */ yylval.l_int = (intmax_t)(int)idp->di_id; yyintprefix = 0; yyintsuffix[0] = '\0'; yyintdecimal = 1; return (DT_TOK_INT); }<S0>{RGX_IDENT} { return (id_or_type(yytext)); }<S0>{RGX_AGG} { if ((yylval.l_str = strdup(yytext)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); return (DT_TOK_AGG); }<S0>"@" { if ((yylval.l_str = strdup("@_")) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); return (DT_TOK_AGG); }<S0>{RGX_INT} |<S2>{RGX_INT} |<S3>{RGX_INT} { char *p; errno = 0; yylval.l_int = strtoull(yytext, &p, 0); yyintprefix = 0; (void) strncpy(yyintsuffix, p, sizeof (yyintsuffix)); yyintdecimal = yytext[0] != '0'; if (errno == ERANGE) { xyerror(D_INT_OFLOW, "constant %s results in " "integer overflow\n", yytext); } if (*p != '\0' && strchr("uUlL", *p) == NULL) { xyerror(D_INT_DIGIT, "constant %s contains " "invalid digit %c\n", yytext, *p); } if ((YYSTATE) != S3) return (DT_TOK_INT); yypragma = dt_node_link(yypragma, dt_node_int(yylval.l_int)); }<S0>{RGX_FP} yyerror("floating-point constants are not permitted\n");<S0>\"{RGX_STR}$ |<S3>\"{RGX_STR}$ xyerror(D_STR_NL, "newline encountered in string literal");<S0>\"{RGX_STR}\" |<S3>\"{RGX_STR}\" { /* * Quoted string -- convert C escape sequences and * return the string as a token. */ yylval.l_str = strndup(yytext + 1, yyleng - 2); if (yylval.l_str == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); (void) stresc2chr(yylval.l_str); if ((YYSTATE) != S3) return (DT_TOK_STRING); yypragma = dt_node_link(yypragma, dt_node_string(yylval.l_str)); }<S0>'{RGX_CHR}$ xyerror(D_CHR_NL, "newline encountered in character constant");<S0>'{RGX_CHR}' { char *s, *p, *q; size_t nbytes; /* * Character constant -- convert C escape sequences and * return the character as an integer immediate value. */ if (yyleng == 2) xyerror(D_CHR_NULL, "empty character constant"); s = yytext + 1; yytext[yyleng - 1] = '\0'; nbytes = stresc2chr(s); yylval.l_int = 0; yyintprefix = 0; yyintsuffix[0] = '\0'; yyintdecimal = 1; if (nbytes > sizeof (yylval.l_int)) { xyerror(D_CHR_OFLOW, "character constant is " "too long"); }#ifdef _LITTLE_ENDIAN p = ((char *)&yylval.l_int) + nbytes - 1; for (q = s; nbytes != 0; nbytes--) *p-- = *q++;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?