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 + -
显示快捷键?