1 %top{
2 /*
3  * Copyright (c) 2002, 2004, 2005, 2006, 2008 Tama Communications Corporation
4  *
5  * This file is part of GNU GLOBAL.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /*
22  * scanner for php source code.
23  */
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 #include <stdio.h>
28 #ifdef STDC_HEADERS
29 #include <stdlib.h>
30 #endif
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #include <strings.h>
35 #endif
36 #include "global.h"
37 #include "anchor.h"
38 #include "common.h"
39 #include "incop.h"
40 #include "htags.h"
41 #include "../libparser/php_res.h"
42 
43 #define lex_symbol_generation_rule(x) php_ ## x
44 #include "lexcommon.h"
45 
46 #ifdef ECHO
47 #undef ECHO
48 #endif
49 #define ECHO	echos(LEXTEXT)
50 
51 #define YY_USER_ACTION DEFAULT_YY_USER_ACTION
52 #define LEFT_BRACE '('
53 
54 static int pre_here_document;
55 static char end_of_here_document[IDENTLEN];
56 
57 }
58  /* Definitions */
59 H		0[Xx][0-9A-Fa-f]+
60 N		[0-9]+
61 L		{N}L?
62 D1		{N}\.{N}([Ee][+-]?{N})?
63 D2		\.{N}([Ee][+-]?{N})?
64 NUMBER		-?({L}|{D1}|{D2})
65 ALPHA		[a-zA-Z_\x80-\xff]
66 ALPHANUM	[a-zA-Z_\x80-\xff0-9]
67 WORD		{ALPHA}{ALPHANUM}*
68 
69 %start	PHP C_COMMENT CPP_COMMENT SHELL_COMMENT STRING LITERAL HEREDOCUMENT PREPROCESSOR_LINE
70 %option 8bit noyywrap noyy_top_state stack never-interactive prefix="php_"
71 %%
72  /* Start PHP */
73 <INITIAL>"<?="		{ put_string(LEXTEXT); BEGIN PHP; }
74 <INITIAL>"<?"		{ put_string(LEXTEXT); BEGIN PHP; }
75 <INITIAL>"<?php"	{ put_string(LEXTEXT); BEGIN PHP; }
76 <INITIAL>"<%"		{ put_string(LEXTEXT); BEGIN PHP; }
77 <INITIAL>"<script[ \t]+language=(\")?php(\")?>" { put_string(LEXTEXT); BEGIN PHP; }
78  /* Ignore HTML */
79 <INITIAL>.              put_string(LEXTEXT);
80  /* End of PHP */
81 <PHP>"?>"		{ put_string(LEXTEXT); BEGIN INITIAL; }
82 <PHP>"%>"               { put_string(LEXTEXT); BEGIN INITIAL; }
83 <PHP>"</script>"        { put_string(LEXTEXT); BEGIN INITIAL; }
84 
85  /* Comment */
86 <PHP>"/*"	{ echos(comment_begin); ECHO; yy_push_state(C_COMMENT); }
87 <C_COMMENT>"*/"	{ ECHO; echos(comment_end); yy_pop_state(); }
88 <C_COMMENT>.	{ put_char(LEXTEXT[0]); }
89 <PHP>"#"        { echos(comment_begin); ECHO; yy_push_state(SHELL_COMMENT); }
90 <PHP>"//"	{ echos(comment_begin); ECHO; yy_push_state(CPP_COMMENT); }
91 
92  /* String */
93 <PHP>\"		{ ECHO; yy_push_state(STRING); }
94 <STRING>\"	{ ECHO; yy_pop_state(); }
95 <STRING>\\.	{ put_char(LEXTEXT[0]); put_char(LEXTEXT[1]); }
96 
97  /* Literal */
98 <PHP>\'		{ ECHO; yy_push_state(LITERAL); }
99 <LITERAL>\'	{ ECHO; yy_pop_state(); }
100 <LITERAL>\\.	{ put_char(LEXTEXT[0]); put_char(LEXTEXT[1]); }
101 
102  /* Here document */
103 <PHP><<<{WORD} {
104 		/* extract word and save */
105 		if (LEXLENG - 3 > IDENTLEN)
106 			die("Too long name '%s'.", LEXTEXT + 3);
107 		strcpy(end_of_here_document, LEXTEXT + 3);
108 		put_string("<<<");
109 		put_reserved_word(end_of_here_document);
110 		/* begin here document from the next line */
111 		pre_here_document = 1;
112 	}
113 <HEREDOCUMENT>^[ \t]*{WORD} {
114 		const char *keyword = strtrim((const char *)LEXTEXT, TRIM_HEAD, NULL);
115 		put_reserved_word(LEXTEXT);
116 		if (!strcmp(end_of_here_document, keyword)) {
117 			end_of_here_document[0] = '\0';
118 			yy_pop_state();
119 		}
120 	}
121 <PHP>^[ \t]*(include|require|require_once) {
122 		int c;
123 
124 		put_reserved_word(LEXTEXT);
125 		/*
126 		 * include  ('aaa/bbb.h');
127 		 * include   'aaa/bbb.h';
128 		 *        ^
129 		 */
130 		while ((c = input()) && c != EOF && c != '\n' && isspace(c))
131 			echoc(c);
132 		if (c == EOF)
133 			c = '\n';
134 		if (c == '\n')
135 			unput(c);
136 		else if (c) {
137 			char path[MAXPATHLEN], *p = path, *lim = p + MAXPATHLEN - 1;
138 			int sep = 0;
139 
140 			if (c == LEFT_BRACE) {
141 				c = input();
142 				if (c == EOF)
143 					c = '\n';
144 			}
145 			if (c == '"' || c == '\'')
146 				sep = c;
147 			echoc(c);
148 
149 			/* pick up path name */
150 			while ((c = input()) && c != EOF && c != '\n' && c != sep)
151 				if (p < lim)
152 					*p++ = c;
153 			*p = '\0';
154 			if (c == EOF)
155 				c = '\n';
156 			if (c == sep) {
157 				char tmp[MAXPATHLEN];
158 				char normalized_path[MAXPATHLEN];
159 
160 				snprintf(tmp, sizeof(tmp), "%s/%s", get_current_dir(), path);
161 				/*
162 				 * pick up the file only when it exists.
163 				 */
164 				if (normalize(tmp, get_root_with_slash(), get_cwd(), normalized_path, sizeof(normalized_path))
165 					&& test("f", normalized_path))
166 					put_include_anchor_direct(normalized_path, path);
167 				else
168 					echos(path);
169 				echoc(sep);
170 			} else {
171 				echos(path);
172 				if (c)
173 					unput(c);
174 			}
175 		}
176 	}
177 <PHP>{NUMBER}	ECHO;
178 <PHP,STRING,HEREDOCUMENT>\${WORD} |
179 <PHP,STRING,HEREDOCUMENT>\$\{{WORD}\} {
180 		struct anchor *a = NULL;
181 		const char *p = LEXTEXT + 1;	/* skip '$' */
182 		int brace = 0, i = 0;
183 
184 		/*
185 		 * extract name.
186 		 */
187 		if (*p == '{') {
188 			char buf[IDENTLEN];
189 
190 			brace = 1;
191 			for (p++; *p && *p != '}'; p++) {
192 				buf[i++] = *p;
193 				if (i >= sizeof(buf))
194 					die("Too long name '%s'.", LEXTEXT);
195 			}
196 			buf[i] = '\0';
197 			p = buf;
198 		} else {
199 			i = LEXLENG - 1;
200 		}
201 		if ((a = anchor_get(p, i, 'Y', LINENO)) != NULL) {
202 			echoc('$');
203 			if (brace)
204 				echoc('{');
205 			put_anchor(gettag(a), a->type, LINENO);
206 			if (brace)
207 				echoc('}');
208 			a->done = 1;
209 		} else if (grtags_is_empty) {
210 			echoc('$');
211 			if (brace)
212 				echoc('{');
213 			put_anchor_force(LEXTEXT, LEXLENG, LINENO);
214 			if (brace)
215 				echoc('}');
216 		} else {
217 			ECHO;
218 		}
219 	}
220 <PHP>{WORD} {
221 		struct anchor *a = NULL;
222 		if (php_reserved_word(LEXTEXT, LEXLENG))
223 			put_reserved_word(LEXTEXT);
224 		else {
225 			a = anchor_get(LEXTEXT, LEXLENG, 0, LINENO);
226 			if (a) {
227 				put_anchor(gettag(a), a->type, LINENO);
228 				a->done = 1;
229 			} else if (grtags_is_empty) {
230 				put_anchor_force(LEXTEXT, LEXLENG, LINENO);
231 			} else {
232 				ECHO;
233 			}
234 		}
235 	}
236 <PHP>[{}]	{ put_brace(LEXTEXT); }
237  /* New line */
238 \n		{
239 			DEFAULT_END_OF_LINE_ACTION
240 			if (pre_here_document == 1) {
241 				pre_here_document = 0;
242 				yy_push_state(HEREDOCUMENT);
243 			}
244 		}
245 .		{ put_char(LEXTEXT[0]); }
246 
247 %%
248 void
249 php_parser_init(FILE *ip)
250 {
251 	BEGIN(INITIAL);
252 	DEFAULT_BEGIN_OF_FILE_ACTION
253 }
254