6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <assert.h>
31 #include <ctype.h>
32 #include <errno.h>
33
34 #include <dt_impl.h>
35 #include <dt_grammar.h>
36 #include <dt_parser.h>
37 #include <dt_string.h>
38
39 /*
40 * We need to undefine lex's input and unput macros so that references to these
41 * call the functions provided at the end of this source file.
42 */
43 #undef input
44 #undef unput
45
46 static int id_or_type(const char *);
47 static int input(void);
48 static void unput(int);
49
50 /*
51 * We first define a set of labeled states for use in the D lexer and then a
52 * set of regular expressions to simplify things below. The lexer states are:
53 *
54 * S0 - D program clause and expression lexing
55 * S1 - D comments (i.e. skip everything until end of comment)
56 * S2 - D program outer scope (probe specifiers and declarations)
57 * S3 - D control line parsing (i.e. after ^# is seen but before \n)
58 * S4 - D control line scan (locate control directives only and invoke S3)
59 */
60 %}
61
62 %e 1500 /* maximum nodes */
63 %p 3700 /* maximum positions */
64 %n 600 /* maximum states */
65
66 %s S0 S1 S2 S3 S4
67
68 RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
69 RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
70 RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*
71 RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
72 RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
73 RGX_WS [\f\n\r\t\v ]
74 RGX_STR ([^"\\\n]|\\[^"\n]|\\\")*
75 RGX_CHR ([^'\\\n]|\\[^'\n]|\\')*
76 RGX_INTERP ^[\f\t\v ]*#!.*
77 RGX_CTL ^[\f\t\v ]*#
78
79 %%
80
81 %{
82
83 /*
84 * We insert a special prologue into yylex() itself: if the pcb contains a
85 * context token, we return that prior to running the normal lexer. This
86 * allows libdtrace to force yacc into one of our three parsing contexts: D
87 * expression (DT_CTX_DEXPR), D program (DT_CTX_DPROG) or D type (DT_CTX_DTYPE).
88 * Once the token is returned, we clear it so this only happens once.
89 */
119 <S0>offsetof return (DT_TOK_OFFSETOF);
120 <S0>probe return (DT_KEY_PROBE);
121 <S0>provider return (DT_KEY_PROVIDER);
122 <S0>register return (DT_KEY_REGISTER);
123 <S0>restrict return (DT_KEY_RESTRICT);
124 <S0>return return (DT_KEY_RETURN);
125 <S0>self return (DT_KEY_SELF);
126 <S0>short return (DT_KEY_SHORT);
127 <S0>signed return (DT_KEY_SIGNED);
128 <S0>sizeof return (DT_TOK_SIZEOF);
129 <S0>static return (DT_KEY_STATIC);
130 <S0>string return (DT_KEY_STRING);
131 <S0>stringof return (DT_TOK_STRINGOF);
132 <S0>struct return (DT_KEY_STRUCT);
133 <S0>switch return (DT_KEY_SWITCH);
134 <S0>this return (DT_KEY_THIS);
135 <S0>translator return (DT_KEY_XLATOR);
136 <S0>typedef return (DT_KEY_TYPEDEF);
137 <S0>union return (DT_KEY_UNION);
138 <S0>unsigned return (DT_KEY_UNSIGNED);
139 <S0>void return (DT_KEY_VOID);
140 <S0>volatile return (DT_KEY_VOLATILE);
141 <S0>while return (DT_KEY_WHILE);
142 <S0>xlate return (DT_TOK_XLATE);
143
144 <S2>auto { yybegin(YYS_EXPR); return (DT_KEY_AUTO); }
145 <S2>char { yybegin(YYS_EXPR); return (DT_KEY_CHAR); }
146 <S2>const { yybegin(YYS_EXPR); return (DT_KEY_CONST); }
147 <S2>counter { yybegin(YYS_DEFINE); return (DT_KEY_COUNTER); }
148 <S2>double { yybegin(YYS_EXPR); return (DT_KEY_DOUBLE); }
149 <S2>enum { yybegin(YYS_EXPR); return (DT_KEY_ENUM); }
150 <S2>extern { yybegin(YYS_EXPR); return (DT_KEY_EXTERN); }
151 <S2>float { yybegin(YYS_EXPR); return (DT_KEY_FLOAT); }
152 <S2>import { yybegin(YYS_EXPR); return (DT_KEY_IMPORT); }
153 <S2>inline { yybegin(YYS_DEFINE); return (DT_KEY_INLINE); }
154 <S2>int { yybegin(YYS_EXPR); return (DT_KEY_INT); }
155 <S2>long { yybegin(YYS_EXPR); return (DT_KEY_LONG); }
156 <S2>provider { yybegin(YYS_DEFINE); return (DT_KEY_PROVIDER); }
157 <S2>register { yybegin(YYS_EXPR); return (DT_KEY_REGISTER); }
158 <S2>restrict { yybegin(YYS_EXPR); return (DT_KEY_RESTRICT); }
297 dt_ident_t *idp = dt_idhash_lookup(
298 yypcb->pcb_hdl->dt_macros, yytext + 1);
299
300 if (idp == NULL) {
301 xyerror(D_MACRO_UNDEF, "macro variable %s "
302 "is not defined\n", yytext);
303 }
304
305 /*
306 * For the moment, all current macro variables are of
307 * type id_t (refer to dtrace_update() for details).
308 */
309 yylval.l_int = (intmax_t)(int)idp->di_id;
310 yyintprefix = 0;
311 yyintsuffix[0] = '\0';
312 yyintdecimal = 1;
313
314 return (DT_TOK_INT);
315 }
316
317 <S0>{RGX_IDENT} {
318 return (id_or_type(yytext));
319 }
320
321 <S0>{RGX_AGG} {
322 if ((yylval.l_str = strdup(yytext)) == NULL)
323 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
324 return (DT_TOK_AGG);
325 }
326
327 <S0>"@" {
328 if ((yylval.l_str = strdup("@_")) == NULL)
329 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
330 return (DT_TOK_AGG);
331 }
332
333 <S0>{RGX_INT} |
334 <S2>{RGX_INT} |
335 <S3>{RGX_INT} {
336 char *p;
337
|
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26 /*
27 * Copyright (c) 2013 by Delphix. All rights reserved.
28 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
29 */
30
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37
38 #include <dt_impl.h>
39 #include <dt_grammar.h>
40 #include <dt_parser.h>
41 #include <dt_string.h>
42
43 /*
44 * We need to undefine lex's input and unput macros so that references to these
45 * call the functions provided at the end of this source file.
46 */
47 #undef input
48 #undef unput
49
50 static int id_or_type(const char *);
51 static int input(void);
52 static void unput(int);
53
54 /*
55 * We first define a set of labeled states for use in the D lexer and then a
56 * set of regular expressions to simplify things below. The lexer states are:
57 *
58 * S0 - D program clause and expression lexing
59 * S1 - D comments (i.e. skip everything until end of comment)
60 * S2 - D program outer scope (probe specifiers and declarations)
61 * S3 - D control line parsing (i.e. after ^# is seen but before \n)
62 * S4 - D control line scan (locate control directives only and invoke S3)
63 */
64 %}
65
66 %e 1500 /* maximum nodes */
67 %p 4900 /* maximum positions */
68 %n 600 /* maximum states */
69 %a 3000 /* maximum transitions */
70
71 %s S0 S1 S2 S3 S4
72
73 RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
74 RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
75 RGX_ALTIDENT [a-zA-Z_][0-9a-zA-Z_]*
76 RGX_LMID LM[0-9a-fA-F]+`
77 RGX_MOD_IDENT [a-zA-Z_`][0-9a-z.A-Z_`]*`
78 RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*
79 RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
80 RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
81 RGX_WS [\f\n\r\t\v ]
82 RGX_STR ([^"\\\n]|\\[^"\n]|\\\")*
83 RGX_CHR ([^'\\\n]|\\[^'\n]|\\')*
84 RGX_INTERP ^[\f\t\v ]*#!.*
85 RGX_CTL ^[\f\t\v ]*#
86
87 %%
88
89 %{
90
91 /*
92 * We insert a special prologue into yylex() itself: if the pcb contains a
93 * context token, we return that prior to running the normal lexer. This
94 * allows libdtrace to force yacc into one of our three parsing contexts: D
95 * expression (DT_CTX_DEXPR), D program (DT_CTX_DPROG) or D type (DT_CTX_DTYPE).
96 * Once the token is returned, we clear it so this only happens once.
97 */
127 <S0>offsetof return (DT_TOK_OFFSETOF);
128 <S0>probe return (DT_KEY_PROBE);
129 <S0>provider return (DT_KEY_PROVIDER);
130 <S0>register return (DT_KEY_REGISTER);
131 <S0>restrict return (DT_KEY_RESTRICT);
132 <S0>return return (DT_KEY_RETURN);
133 <S0>self return (DT_KEY_SELF);
134 <S0>short return (DT_KEY_SHORT);
135 <S0>signed return (DT_KEY_SIGNED);
136 <S0>sizeof return (DT_TOK_SIZEOF);
137 <S0>static return (DT_KEY_STATIC);
138 <S0>string return (DT_KEY_STRING);
139 <S0>stringof return (DT_TOK_STRINGOF);
140 <S0>struct return (DT_KEY_STRUCT);
141 <S0>switch return (DT_KEY_SWITCH);
142 <S0>this return (DT_KEY_THIS);
143 <S0>translator return (DT_KEY_XLATOR);
144 <S0>typedef return (DT_KEY_TYPEDEF);
145 <S0>union return (DT_KEY_UNION);
146 <S0>unsigned return (DT_KEY_UNSIGNED);
147 <S0>userland return (DT_KEY_USERLAND);
148 <S0>void return (DT_KEY_VOID);
149 <S0>volatile return (DT_KEY_VOLATILE);
150 <S0>while return (DT_KEY_WHILE);
151 <S0>xlate return (DT_TOK_XLATE);
152
153 <S2>auto { yybegin(YYS_EXPR); return (DT_KEY_AUTO); }
154 <S2>char { yybegin(YYS_EXPR); return (DT_KEY_CHAR); }
155 <S2>const { yybegin(YYS_EXPR); return (DT_KEY_CONST); }
156 <S2>counter { yybegin(YYS_DEFINE); return (DT_KEY_COUNTER); }
157 <S2>double { yybegin(YYS_EXPR); return (DT_KEY_DOUBLE); }
158 <S2>enum { yybegin(YYS_EXPR); return (DT_KEY_ENUM); }
159 <S2>extern { yybegin(YYS_EXPR); return (DT_KEY_EXTERN); }
160 <S2>float { yybegin(YYS_EXPR); return (DT_KEY_FLOAT); }
161 <S2>import { yybegin(YYS_EXPR); return (DT_KEY_IMPORT); }
162 <S2>inline { yybegin(YYS_DEFINE); return (DT_KEY_INLINE); }
163 <S2>int { yybegin(YYS_EXPR); return (DT_KEY_INT); }
164 <S2>long { yybegin(YYS_EXPR); return (DT_KEY_LONG); }
165 <S2>provider { yybegin(YYS_DEFINE); return (DT_KEY_PROVIDER); }
166 <S2>register { yybegin(YYS_EXPR); return (DT_KEY_REGISTER); }
167 <S2>restrict { yybegin(YYS_EXPR); return (DT_KEY_RESTRICT); }
306 dt_ident_t *idp = dt_idhash_lookup(
307 yypcb->pcb_hdl->dt_macros, yytext + 1);
308
309 if (idp == NULL) {
310 xyerror(D_MACRO_UNDEF, "macro variable %s "
311 "is not defined\n", yytext);
312 }
313
314 /*
315 * For the moment, all current macro variables are of
316 * type id_t (refer to dtrace_update() for details).
317 */
318 yylval.l_int = (intmax_t)(int)idp->di_id;
319 yyintprefix = 0;
320 yyintsuffix[0] = '\0';
321 yyintdecimal = 1;
322
323 return (DT_TOK_INT);
324 }
325
326 <S0>{RGX_IDENT} |
327 <S0>{RGX_MOD_IDENT}{RGX_IDENT} |
328 <S0>{RGX_MOD_IDENT} {
329 return (id_or_type(yytext));
330 }
331
332 <S0>{RGX_AGG} {
333 if ((yylval.l_str = strdup(yytext)) == NULL)
334 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
335 return (DT_TOK_AGG);
336 }
337
338 <S0>"@" {
339 if ((yylval.l_str = strdup("@_")) == NULL)
340 longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
341 return (DT_TOK_AGG);
342 }
343
344 <S0>{RGX_INT} |
345 <S2>{RGX_INT} |
346 <S3>{RGX_INT} {
347 char *p;
348
|