Skip to content

Commit

Permalink
Fixes #10301
Browse files Browse the repository at this point in the history
  • Loading branch information
phalcon committed May 11, 2015
1 parent efc2c6f commit f209ecd
Show file tree
Hide file tree
Showing 24 changed files with 376 additions and 380 deletions.
3 changes: 3 additions & 0 deletions ext/clean
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ done
for i in `find . -name "*.gch"`; do
rm -f $i
done
for i in `find . -name ".libs"`; do
rm -fr $i
done
make clean
phpize --clean
17 changes: 12 additions & 5 deletions ext/phalcon/annotations/annot.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
+------------------------------------------------------------------------+
| Phalcon Framework |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) |
| Copyright (c) 2011-2015 Phalcon Team (http://www.phalconphp.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
Expand All @@ -17,6 +17,12 @@
+------------------------------------------------------------------------+
*/

#ifndef PHALCON_ANNOTATIONS_ANNOT_H
#define PHALCON_ANNOTATIONS_ANNOT_H

#include <Zend/zend.h>
#include "scanner.h"

typedef struct _phannot_parser_token {
char *token;
int opcode;
Expand All @@ -28,13 +34,14 @@ typedef struct _phannot_parser_status {
zval *ret;
phannot_scanner_state *scanner_state;
phannot_scanner_token *token;
int status;
zend_uint syntax_error_len;
char *syntax_error;
int status;
} phannot_parser_status;

#define PHANNOT_PARSING_OK 1
#define PHANNOT_PARSING_FAILED 0

extern int phannot_parse_annotations(zval *result, zval *view_code, zval *template_path, zval *line TSRMLS_DC);
int phannot_internal_parse_annotations(zval **result, zval *view_code, zval *template_path, zval *line, zval **error_msg TSRMLS_DC);
int phannot_parse_annotations(zval *result, zval *comment, zval *file_path, zval *line TSRMLS_DC);
int phannot_internal_parse_annotations(zval **result, const char *comment, zend_uint comment_len, const char *file_path, zend_uint line, char **error_msg TSRMLS_DC);

#endif /* PHALCON_ANNOTATIONS_ANNOT_H */
155 changes: 85 additions & 70 deletions ext/phalcon/annotations/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
+------------------------------------------------------------------------+
| Phalcon Framework |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2013 Phalcon Team (http://www.phalconphp.com) |
| Copyright (c) 2011-2015 Phalcon Team (http://www.phalconphp.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
Expand Down Expand Up @@ -31,7 +31,7 @@ const phannot_token_names phannot_tokens[] =
{ ")", PHANNOT_T_PARENTHESES_CLOSE },
{ "{", PHANNOT_T_BRACKET_OPEN },
{ "}", PHANNOT_T_BRACKET_CLOSE },
{ "[", PHANNOT_T_SBRACKET_OPEN },
{ "[", PHANNOT_T_SBRACKET_OPEN },
{ "]", PHANNOT_T_SBRACKET_CLOSE },
{ "ARBITRARY TEXT", PHANNOT_T_ARBITRARY_TEXT },
{ NULL, 0 }
Expand Down Expand Up @@ -73,51 +73,64 @@ static void phannot_parse_with_token(void* phannot_parser, int opcode, int parse
/**
* Creates an error message when it's triggered by the scanner
*/
static void phannot_scanner_error_msg(phannot_parser_status *parser_status, zval **error_msg TSRMLS_DC){
static void phannot_scanner_error_msg(phannot_parser_status *parser_status, char **error_msg TSRMLS_DC){

int error_length;
char *error, *error_part;
phannot_scanner_state *state = parser_status->scanner_state;

MAKE_STD_ZVAL(*error_msg);
if (state->start) {
error_length = 128 + state->start_length + Z_STRLEN_P(state->active_file);
error = emalloc(sizeof(char) * error_length);
if (state->start_length > 16) {
error_part = estrndup(state->start, 16);
snprintf(error, 64 + state->start_length, "Scanning error before '%s...' in %s on line %d", error_part, Z_STRVAL_P(state->active_file), state->active_line);
efree(error_part);
spprintf(error_msg, 0, "Scanning error before '%.16s...' in %s on line %d", state->start, state->active_file, state->active_line);
} else {
snprintf(error, error_length - 1, "Scanning error before '%s' in %s on line %d", state->start, Z_STRVAL_P(state->active_file), state->active_line);
spprintf(error_msg, 0, "Scanning error before '%s' in %s on line %d", state->start, state->active_file, state->active_line);
}
error[error_length - 1] = '\0';
ZVAL_STRING(*error_msg, error, 1);
} else {
error_length = sizeof(char) * (64 + Z_STRLEN_P(state->active_file));
error = emalloc(error_length);
snprintf(error, error_length - 1, "Scanning error near to EOF in %s", Z_STRVAL_P(state->active_file));
ZVAL_STRING(*error_msg, error, 1);
error[error_length - 1] = '\0';
spprintf(error_msg, 0, "Scanning error near to EOF in %s", state->active_file);
}
efree(error);
}

/**
* Receives the comment tokenizes and parses it
*/
int phannot_parse_annotations(zval *result, zval *comment, zval *file_path, zval *line TSRMLS_DC){
int phannot_parse_annotations(zval *result, zval *comment, zval *file_path, zval *line TSRMLS_DC) {

zval *error_msg = NULL;
char *comment_str;
zend_uint comment_len;
char *file_path_str;
zend_uint line_num;

char *error_msg = NULL;

ZVAL_NULL(result);

if (Z_TYPE_P(comment) != IS_STRING) {
ZEPHIR_THROW_EXCEPTION_STR(phalcon_annotations_exception_ce, "Comment must be a string");
return FAILURE;
if (Z_TYPE_P(comment) == IS_STRING) {
comment_str = Z_STRVAL_P(comment);
comment_len = Z_STRLEN_P(comment);
} else {
comment_str = "";
comment_len = 0;
}

if (phannot_internal_parse_annotations(&result, comment, file_path, line, &error_msg TSRMLS_CC) == FAILURE){
ZEPHIR_THROW_EXCEPTION_STRW(phalcon_annotations_exception_ce, Z_STRVAL_P(error_msg));
if (Z_TYPE_P(file_path) == IS_STRING) {
file_path_str = Z_STRVAL_P(file_path);
} else {
file_path_str = "eval";
}

if (Z_TYPE_P(line) == IS_LONG) {
line_num = Z_LVAL_P(line);
} else {
line_num = 0;
}

if (phannot_internal_parse_annotations(&result, comment_str, comment_len, file_path_str, line_num, &error_msg TSRMLS_CC) == FAILURE) {
if (likely(error_msg != NULL)) {
zephir_throw_exception_string(phalcon_annotations_exception_ce, error_msg, strlen(error_msg) TSRMLS_CC);
efree(error_msg);
}
else {
zephir_throw_exception_string(phalcon_annotations_exception_ce, SL("There was an error parsing annotation") TSRMLS_CC);
}

return FAILURE;
}

Expand All @@ -127,8 +140,8 @@ int phannot_parse_annotations(zval *result, zval *comment, zval *file_path, zval
/**
* Remove comment separators from a docblock
*/
void phannot_remove_comment_separators(zval *return_value, char *comment, int length, int *start_lines) {

static void phannot_remove_comment_separators(char **ret, zend_uint *ret_len, const char *comment, zend_uint length, zend_uint *start_lines)
{
int start_mode = 1, j, i, open_parentheses;
smart_str processed_str = {0};
char ch;
Expand Down Expand Up @@ -165,7 +178,7 @@ void phannot_remove_comment_separators(zval *return_value, char *comment, int le

if (open_parentheses == 0) {

if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
if (isalnum(ch) || '_' == ch || '\\' == ch) {
smart_str_appendc(&processed_str, ch);
continue;
}
Expand All @@ -182,15 +195,11 @@ void phannot_remove_comment_separators(zval *return_value, char *comment, int le

if (ch == '(') {
open_parentheses++;
} else {
if (ch == ')') {
open_parentheses--;
} else {
if (ch == '\n') {
(*start_lines)++;
start_mode = 1;
}
}
} else if (ch == ')') {
open_parentheses--;
} else if (ch == '\n') {
(*start_lines)++;
start_mode = 1;
}

if (open_parentheses > 0) {
Expand All @@ -213,56 +222,69 @@ void phannot_remove_comment_separators(zval *return_value, char *comment, int le
smart_str_0(&processed_str);

if (processed_str.len) {
RETURN_STRINGL(processed_str.c, processed_str.len, 0);
*ret = processed_str.c;
*ret_len = processed_str.len;
} else {
RETURN_EMPTY_STRING();
*ret = NULL;
*ret_len = 0;
}
}

/**
* Parses a comment returning an intermediate array representation
*/
int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_path, zval *line, zval **error_msg TSRMLS_DC) {

char *error;
int phannot_internal_parse_annotations(zval **result, const char *comment, zend_uint comment_len, const char *file_path, zend_uint line, char **error_msg TSRMLS_DC)
{
phannot_scanner_state *state;
phannot_scanner_token token;
int scanner_status, status = SUCCESS, start_lines, error_length;
zend_uint start_lines;
int scanner_status, status = SUCCESS;
phannot_parser_status *parser_status = NULL;
void* phannot_parser;
zval processed_comment;
char *processed_comment;
zend_uint processed_comment_len;

*error_msg = NULL;

/**
* Check if the comment has content
*/
if (!Z_STRVAL_P(comment)) {
if (UNEXPECTED(!comment)) {
ZVAL_BOOL(*result, 0);
spprintf(error_msg, 0, "Empty annotation");
return FAILURE;
}

if (Z_STRLEN_P(comment) < 2) {
if (comment_len < 2) {
ZVAL_BOOL(*result, 0);
return SUCCESS;
}

/**
* Remove comment separators
*/
phannot_remove_comment_separators(&processed_comment, Z_STRVAL_P(comment), Z_STRLEN_P(comment), &start_lines);
phannot_remove_comment_separators(&processed_comment, &processed_comment_len, comment, comment_len, &start_lines);

if (Z_STRLEN(processed_comment) < 2) {
if (processed_comment_len < 2) {
ZVAL_BOOL(*result, 0);
efree(Z_STRVAL(processed_comment));
if (processed_comment) {
efree(processed_comment);
}

return SUCCESS;
}

/**
* Start the reentrant parser
*/
phannot_parser = phannot_Alloc(phannot_wrapper_alloc);
if (unlikely(!phannot_parser)) {
ZVAL_BOOL(*result, 0);
return FAILURE;
}

parser_status = emalloc(sizeof(phannot_parser_status));
state = emalloc(sizeof(phannot_scanner_state));
parser_status = emalloc(sizeof(phannot_parser_status) + sizeof(phannot_scanner_state));
state = (phannot_scanner_state*)((char*)parser_status + sizeof(phannot_parser_status));

parser_status->status = PHANNOT_PARSING_OK;
parser_status->scanner_state = state;
Expand All @@ -274,7 +296,7 @@ int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_
* Initialize the scanner state
*/
state->active_token = 0;
state->start = Z_STRVAL(processed_comment);
state->start = processed_comment;
state->start_length = 0;
state->mode = PHANNOT_MODE_RAW;
state->active_file = file_path;
Expand All @@ -285,8 +307,8 @@ int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_
/**
* Possible start line
*/
if (Z_TYPE_P(line) == IS_LONG) {
state->active_line = Z_LVAL_P(line) - start_lines;
if (line) {
state->active_line = line - start_lines;
} else {
state->active_line = 1;
}
Expand All @@ -297,7 +319,7 @@ int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_

state->active_token = token.opcode;

state->start_length = (Z_STRVAL(processed_comment) + Z_STRLEN(processed_comment) - state->start);
state->start_length = processed_comment + processed_comment_len - state->start;

switch (token.opcode) {

Expand Down Expand Up @@ -367,13 +389,7 @@ int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_
default:
parser_status->status = PHANNOT_PARSING_FAILED;
if (!*error_msg) {
error_length = sizeof(char) * (48 + Z_STRLEN_P(state->active_file));
error = emalloc(error_length);
snprintf(error, error_length - 1, "Scanner: unknown opcode %d on in %s line %d", token.opcode, Z_STRVAL_P(state->active_file), state->active_line);
error[error_length - 1] = '\0';
MAKE_STD_ZVAL(*error_msg);
ZVAL_STRING(*error_msg, error, 1);
efree(error);
spprintf(error_msg, 0, "Scanner: unknown opcode %d on in %s line %d", token.opcode, state->active_file, state->active_line);
}
break;
}
Expand Down Expand Up @@ -407,10 +423,11 @@ int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_
status = FAILURE;
if (parser_status->syntax_error) {
if (!*error_msg) {
MAKE_STD_ZVAL(*error_msg);
ZVAL_STRING(*error_msg, parser_status->syntax_error, 1);
*error_msg = parser_status->syntax_error;
}
else {
efree(parser_status->syntax_error);
}
efree(parser_status->syntax_error);
}
}

Expand All @@ -428,10 +445,8 @@ int phannot_internal_parse_annotations(zval **result, zval *comment, zval *file_
}
}

efree(Z_STRVAL(processed_comment));

efree(processed_comment);
efree(parser_status);
efree(state);

return status;
}
1 change: 1 addition & 0 deletions ext/phalcon/annotations/generate
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ fi
re2c -o scanner.c scanner.re && ./lemon -s parser.lemon && cat base.c >> parser.c
sed s/"\#line"/"\/\/"/g scanner.c > xx && mv -f xx scanner.c
sed s/"#line"/"\/\/"/g parser.c > xx && mv -f xx parser.c
sed s/"#define TOKEN"/"#define ATOKEN"/g parser.c > xx && mv -f xx parser.c
sed s/YY/AA/g scanner.c > xx && mv -f xx scanner.c
sed s/yy/aa/g scanner.c > xx && mv -f xx scanner.c
sed s/YY/AA/g parser.c > xx && mv -f xx parser.c
Expand Down
Loading

0 comments on commit f209ecd

Please sign in to comment.