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