diff options
147 files changed, 3508 insertions, 0 deletions
| diff --git a/glcpp/.gitignore b/glcpp/.gitignore new file mode 100644 index 0000000000..077db8d8e1 --- /dev/null +++ b/glcpp/.gitignore @@ -0,0 +1,7 @@ +glcpp +glcpp-lex.c +glcpp-parse.c +glcpp-parse.h +*.o +*~ +tests/*.out diff --git a/glcpp/Makefile b/glcpp/Makefile new file mode 100644 index 0000000000..3fb44ac3b2 --- /dev/null +++ b/glcpp/Makefile @@ -0,0 +1,25 @@ +# Debug symbols by default, but let the user avoid that with something +# like "make CFLAGS=-O2" +CFLAGS = -g + +# But we use 'override' here so that "make CFLAGS=-O2" will still have +# all the warnings enabled. +override CFLAGS += -Wall -Wextra -Wwrite-strings -Wswitch-enum -Wno-unused + +glcpp: glcpp.o glcpp-lex.o glcpp-parse.o hash_table.o xtalloc.o +	gcc -o $@ -ltalloc -lm $^ + +%.c %.h: %.y +	bison --debug --defines=$*.h --output=$*.c $^ + +%.c: %.l +	flex --prefix=glcpp_ --outfile=$@ $< + +glcpp-lex.c: glcpp-parse.h + +test: glcpp +	@(cd tests; ./glcpp-test) + +clean: +	rm -f glcpp glcpp-lex.c glcpp-parse.c *.o *~ +	rm -f tests/*.out tests/*~ diff --git a/glcpp/README b/glcpp/README new file mode 100644 index 0000000000..ab42a3ffe1 --- /dev/null +++ b/glcpp/README @@ -0,0 +1,30 @@ +glcpp -- GLSL "C" preprocessor + +This is a simple preprocessor designed to provide the preprocessing +needs of the GLSL language. The requirements for this preprocessor are +specified in the GLSL 1.30 specification availble from: + +http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.30.08.pdf + +This specification is not precise on some semantics, (for example, +#define and #if), defining these merely "as is standard for C++ +preprocessors". To fill in these details, I've been using the C99 +standard (for which I had a convenient copy) as available from: + +http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf + +Known limitations +----------------- +Macro invocations cannot include embedded newlines. + +The __LINE__, __FILE__, and __VERSION__ macros are not yet supported. + +The argument of the 'defined' operator cannot yet include enclosing +parentheses. + +The #error, #pragma, #extension, #version, and #line macros are not +yet supported. + +A file that ends with a function-like macro name as the last +non-whitespace token will result in a parse error, (where it should be +passed through as is).
\ No newline at end of file diff --git a/glcpp/glcpp-lex.l b/glcpp/glcpp-lex.l new file mode 100644 index 0000000000..0d9a75415a --- /dev/null +++ b/glcpp/glcpp-lex.l @@ -0,0 +1,202 @@ +%{ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <string.h> + +#include "glcpp.h" +#include "glcpp-parse.h" +%} + +%option reentrant noyywrap +%option extra-type="glcpp_parser_t *" + +SPACE		[[:space:]] +NONSPACE	[^[:space:]] +NEWLINE		[\n] +HSPACE		[ \t] +HASH		^{HSPACE}*#{HSPACE}* +IDENTIFIER	[_a-zA-Z][_a-zA-Z0-9]* +PUNCTUATION	[][(){}.&*~!/%<>^|;,=+-] +OTHER		[^][(){}.&*~!/%<>^|;,=#[:space:]+-]+ + +DECIMAL_INTEGER		[1-9][0-9]*[uU]? +OCTAL_INTEGER		0[0-7]*[uU]? +HEXADECIMAL_INTEGER	0[xX][0-9a-fA-F]+[uU]? + +NON_STARS_THEN_STARS	[^*]*[*]+ + +%% + +	/* Single-line comments */ +"//"[^\n]+\n { +	return NEWLINE; +} + +	/* Multi-line comments */ +"/*"({NON_STARS_THEN_STARS}[^*/])*{NON_STARS_THEN_STARS}"/" { +	if (yyextra->space_tokens) +		return SPACE; +} + +{HASH}if/.*\n { +	yyextra->lexing_if = 1; +	yyextra->space_tokens = 0; +	return HASH_IF; +} + +{HASH}elif/.*\n { +	yyextra->lexing_if = 1; +	yyextra->space_tokens = 0; +	return HASH_ELIF; +} + +{HASH}else/.*\n { +	yyextra->space_tokens = 0; +	return HASH_ELSE; +} + +{HASH}endif/.*\n { +	yyextra->space_tokens = 0; +	return HASH_ENDIF; +} + +	/* When skipping (due to an #if 0 or similar) consume anything +	 * up to a newline. We do this less priroty than any +	 * #if-related directive (#if, #elif, #else, #endif), but with +	 * more priority than any other directive or token to avoid +	 * any side-effects from skipped content. +	 * +	 * We use the lexing_if flag to avoid skipping any part of an +	 * if conditional expression. */ +[^\n]+/\n { +	if (yyextra->lexing_if || +	    yyextra->skip_stack == NULL || +	    yyextra->skip_stack->type == SKIP_NO_SKIP) +	{ +		REJECT; +	} +} + +{HASH}define{HSPACE}+/{IDENTIFIER}"(" { +	yyextra->space_tokens = 0; +	return HASH_DEFINE_FUNC; +} + +{HASH}define { +	yyextra->space_tokens = 0; +	return HASH_DEFINE_OBJ; +} + +{HASH}undef { +	yyextra->space_tokens = 0; +	return HASH_UNDEF; +} + +{HASH} { +	yyextra->space_tokens = 0; +	return HASH; +} + +{DECIMAL_INTEGER} { +	yylval.str = xtalloc_strdup (yyextra, yytext); +	return INTEGER_STRING; +} + +{OCTAL_INTEGER} { +	yylval.str = xtalloc_strdup (yyextra, yytext); +	return INTEGER_STRING; +} + +{HEXADECIMAL_INTEGER} { +	yylval.str = xtalloc_strdup (yyextra, yytext); +	return INTEGER_STRING; +} + +"<<"  { +	return LEFT_SHIFT; +} + +">>" { +	return RIGHT_SHIFT; +} + +"<=" { +	return LESS_OR_EQUAL; +} + +">=" { +	return GREATER_OR_EQUAL; +} + +"==" { +	return EQUAL; +} + +"!=" { +	return NOT_EQUAL; +} + +"&&" { +	return AND; +} + +"||" { +	return OR; +} + +"##" { +	return PASTE; +} + +"defined" { +	return DEFINED; +} + +{IDENTIFIER} { +	yylval.str = xtalloc_strdup (yyextra, yytext); +	return IDENTIFIER; +} + +{PUNCTUATION} { +	return yytext[0]; +} + +{OTHER}+ { +	yylval.str = xtalloc_strdup (yyextra, yytext); +	return OTHER; +} + +{HSPACE}+ { +	if (yyextra->space_tokens) { +		return SPACE; +	} +} + +\n { +	yyextra->lexing_if = 0; +	return NEWLINE; +} + +%% diff --git a/glcpp/glcpp-parse.y b/glcpp/glcpp-parse.y new file mode 100644 index 0000000000..807cf59509 --- /dev/null +++ b/glcpp/glcpp-parse.y @@ -0,0 +1,1602 @@ +%{ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <inttypes.h> + +#include "glcpp.h" + +static void +yyerror (void *scanner, const char *error); + +static void +_define_object_macro (glcpp_parser_t *parser, +		      const char *macro, +		      token_list_t *replacements); + +static void +_define_function_macro (glcpp_parser_t *parser, +			const char *macro, +			string_list_t *parameters, +			token_list_t *replacements); + +static string_list_t * +_string_list_create (void *ctx); + +static void +_string_list_append_item (string_list_t *list, const char *str); + +static void +_string_list_append_list (string_list_t *list, string_list_t *tail); + +static int +_string_list_contains (string_list_t *list, const char *member, int *index); + +static int +_string_list_length (string_list_t *list); + +static argument_list_t * +_argument_list_create (void *ctx); + +static void +_argument_list_append (argument_list_t *list, token_list_t *argument); + +static int +_argument_list_length (argument_list_t *list); + +static token_list_t * +_argument_list_member_at (argument_list_t *list, int index); + +/* Note: This function talloc_steal()s the str pointer. */ +static token_t * +_token_create_str (void *ctx, int type, char *str); + +static token_t * +_token_create_ival (void *ctx, int type, int ival); + +static token_list_t * +_token_list_create (void *ctx); + +/* Note: This function adds a talloc_reference() to token. + * + * You may want to talloc_unlink any current reference if you no + * longer need it. */ +static void +_token_list_append (token_list_t *list, token_t *token); + +static void +_token_list_append_list (token_list_t *list, token_list_t *tail); + +static int +_token_list_length (token_list_t *list); + +static active_list_t * +_active_list_push (active_list_t *list, +		   const char *identifier, +		   token_node_t *marker); + +static active_list_t * +_active_list_pop (active_list_t *list); + +int +_active_list_contains (active_list_t *list, const char *identifier); + +static void +_glcpp_parser_evaluate_defined (glcpp_parser_t *parser, +				token_list_t *list); + +static void +_glcpp_parser_expand_token_list (glcpp_parser_t *parser, +				 token_list_t *list); + +static void +_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, +					 token_list_t *list); + +static void +_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition); + +static void +_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type, +				    int condition); + +static void +_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser); + +#define yylex glcpp_parser_lex + +static int +glcpp_parser_lex (glcpp_parser_t *parser); + +static void +glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list); + +%} + +%parse-param {glcpp_parser_t *parser} +%lex-param {glcpp_parser_t *parser} + +%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH HASH_DEFINE_FUNC HASH_DEFINE_OBJ HASH_ELIF HASH_ELSE HASH_ENDIF HASH_IF HASH_IFDEF HASH_IFNDEF HASH_UNDEF IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING NEWLINE OTHER PLACEHOLDER SPACE +%token PASTE +%type <ival> expression INTEGER operator SPACE +%type <str> IDENTIFIER INTEGER_STRING OTHER +%type <string_list> identifier_list +%type <token> preprocessing_token +%type <token_list> pp_tokens replacement_list text_line +%left OR +%left AND +%left '|' +%left '^' +%left '&' +%left EQUAL NOT_EQUAL +%left '<' '>' LESS_OR_EQUAL GREATER_OR_EQUAL +%left LEFT_SHIFT RIGHT_SHIFT +%left '+' '-' +%left '*' '/' '%' +%right UNARY + +%% + +input: +	/* empty */ +|	input line +; + +line: +	control_line { +		printf ("\n"); +	} +|	text_line { +		_glcpp_parser_print_expanded_token_list (parser, $1); +		printf ("\n"); +		talloc_free ($1); +	} +|	expanded_line +|	HASH non_directive +; + +expanded_line: +	IF_EXPANDED expression NEWLINE { +		_glcpp_parser_skip_stack_push_if (parser, $2); +	} +|	ELIF_EXPANDED expression NEWLINE { +		_glcpp_parser_skip_stack_change_if (parser, "elif", $2); +	} +; + +control_line: +	HASH_DEFINE_OBJ	IDENTIFIER replacement_list NEWLINE { +		_define_object_macro (parser, $2, $3); +	} +|	HASH_DEFINE_FUNC IDENTIFIER '(' ')' replacement_list NEWLINE { +		_define_function_macro (parser, $2, NULL, $5); +	} +|	HASH_DEFINE_FUNC IDENTIFIER '(' identifier_list ')' replacement_list NEWLINE { +		_define_function_macro (parser, $2, $4, $6); +	} +|	HASH_UNDEF IDENTIFIER NEWLINE { +		macro_t *macro = hash_table_find (parser->defines, $2); +		if (macro) { +			/* XXX: Need hash table to support a real way +			 * to remove an element rather than prefixing +			 * a new node with data of NULL like this. */ +			hash_table_insert (parser->defines, NULL, $2); +			talloc_free (macro); +		} +		talloc_free ($2); +	} +|	HASH_IF pp_tokens NEWLINE { +		token_list_t *expanded; +		token_t *token; + +		expanded = _token_list_create (parser); +		token = _token_create_ival (parser, IF_EXPANDED, IF_EXPANDED); +		_token_list_append (expanded, token); +		talloc_unlink (parser, token); +		_glcpp_parser_evaluate_defined (parser, $2); +		_glcpp_parser_expand_token_list (parser, $2); +		_token_list_append_list (expanded, $2); +		glcpp_parser_lex_from (parser, expanded); +	} +|	HASH_IFDEF IDENTIFIER NEWLINE { +		macro_t *macro = hash_table_find (parser->defines, $2); +		talloc_free ($2); +		_glcpp_parser_skip_stack_push_if (parser, macro != NULL); +	} +|	HASH_IFNDEF IDENTIFIER NEWLINE { +		macro_t *macro = hash_table_find (parser->defines, $2); +		talloc_free ($2); +		_glcpp_parser_skip_stack_push_if (parser, macro == NULL); +	} +|	HASH_ELIF pp_tokens NEWLINE { +		token_list_t *expanded; +		token_t *token; + +		expanded = _token_list_create (parser); +		token = _token_create_ival (parser, ELIF_EXPANDED, ELIF_EXPANDED); +		_token_list_append (expanded, token); +		talloc_unlink (parser, token); +		_glcpp_parser_evaluate_defined (parser, $2); +		_glcpp_parser_expand_token_list (parser, $2); +		_token_list_append_list (expanded, $2); +		glcpp_parser_lex_from (parser, expanded); +	} +|	HASH_ELSE NEWLINE { +		_glcpp_parser_skip_stack_change_if (parser, "else", 1); +	} +|	HASH_ENDIF NEWLINE { +		_glcpp_parser_skip_stack_pop (parser); +	} +|	HASH NEWLINE +; + +expression: +	INTEGER_STRING { +		if (strlen ($1) >= 3 && strncmp ($1, "0x", 2) == 0) { +			$$ = strtoll ($1 + 2, NULL, 16); +		} else if ($1[0] == '0') { +			$$ = strtoll ($1, NULL, 8); +		} else { +			$$ = strtoll ($1, NULL, 10); +		} +	} +|	INTEGER { +		$$ = $1; +	} +|	expression OR expression { +		$$ = $1 || $3; +	} +|	expression AND expression { +		$$ = $1 && $3; +	} +|	expression '|' expression { +		$$ = $1 | $3; +	} +|	expression '^' expression { +		$$ = $1 ^ $3; +	} +|	expression '&' expression { +		$$ = $1 & $3; +	} +|	expression NOT_EQUAL expression { +		$$ = $1 != $3; +	} +|	expression EQUAL expression { +		$$ = $1 == $3; +	} +|	expression GREATER_OR_EQUAL expression { +		$$ = $1 >= $3; +	} +|	expression LESS_OR_EQUAL expression { +		$$ = $1 <= $3; +	} +|	expression '>' expression { +		$$ = $1 > $3; +	} +|	expression '<' expression { +		$$ = $1 < $3; +	} +|	expression RIGHT_SHIFT expression { +		$$ = $1 >> $3; +	} +|	expression LEFT_SHIFT expression { +		$$ = $1 << $3; +	} +|	expression '-' expression { +		$$ = $1 - $3; +	} +|	expression '+' expression { +		$$ = $1 + $3; +	} +|	expression '%' expression { +		$$ = $1 % $3; +	} +|	expression '/' expression { +		$$ = $1 / $3; +	} +|	expression '*' expression { +		$$ = $1 * $3; +	} +|	'!' expression %prec UNARY { +		$$ = ! $2; +	} +|	'~' expression %prec UNARY { +		$$ = ~ $2; +	} +|	'-' expression %prec UNARY { +		$$ = - $2; +	} +|	'+' expression %prec UNARY { +		$$ = + $2; +	} +|	'(' expression ')' { +		$$ = $2; +	} +; + +identifier_list: +	IDENTIFIER { +		$$ = _string_list_create (parser); +		_string_list_append_item ($$, $1); +		talloc_steal ($$, $1); +	} +|	identifier_list ',' IDENTIFIER { +		$$ = $1;	 +		_string_list_append_item ($$, $3); +		talloc_steal ($$, $3); +	} +; + +text_line: +	NEWLINE { $$ = NULL; } +|	pp_tokens NEWLINE +; + +non_directive: +	pp_tokens NEWLINE +; + +replacement_list: +	/* empty */ { $$ = NULL; } +|	pp_tokens +; + +pp_tokens: +	preprocessing_token { +		parser->space_tokens = 1; +		$$ = _token_list_create (parser); +		_token_list_append ($$, $1); +		talloc_unlink (parser, $1); +	} +|	pp_tokens preprocessing_token { +		$$ = $1; +		_token_list_append ($$, $2); +		talloc_unlink (parser, $2); +	} +; + +preprocessing_token: +	IDENTIFIER { +		$$ = _token_create_str (parser, IDENTIFIER, $1); +	} +|	INTEGER_STRING { +		$$ = _token_create_str (parser, INTEGER_STRING, $1); +	} +|	operator { +		$$ = _token_create_ival (parser, $1, $1); +	} +|	OTHER { +		$$ = _token_create_str (parser, OTHER, $1); +	} +|	SPACE { +		$$ = _token_create_ival (parser, SPACE, SPACE); +	} +; + +operator: +	'['			{ $$ = '['; } +|	']'			{ $$ = ']'; } +|	'('			{ $$ = '('; } +|	')'			{ $$ = ')'; } +|	'{'			{ $$ = '{'; } +|	'}'			{ $$ = '}'; } +|	'.'			{ $$ = '.'; } +|	'&'			{ $$ = '&'; } +|	'*'			{ $$ = '*'; } +|	'+'			{ $$ = '+'; } +|	'-'			{ $$ = '-'; } +|	'~'			{ $$ = '~'; } +|	'!'			{ $$ = '!'; } +|	'/'			{ $$ = '/'; } +|	'%'			{ $$ = '%'; } +|	LEFT_SHIFT		{ $$ = LEFT_SHIFT; } +|	RIGHT_SHIFT		{ $$ = RIGHT_SHIFT; } +|	'<'			{ $$ = '<'; } +|	'>'			{ $$ = '>'; } +|	LESS_OR_EQUAL		{ $$ = LESS_OR_EQUAL; } +|	GREATER_OR_EQUAL	{ $$ = GREATER_OR_EQUAL; } +|	EQUAL			{ $$ = EQUAL; } +|	NOT_EQUAL		{ $$ = NOT_EQUAL; } +|	'^'			{ $$ = '^'; } +|	'|'			{ $$ = '|'; } +|	AND			{ $$ = AND; } +|	OR			{ $$ = OR; } +|	';'			{ $$ = ';'; } +|	','			{ $$ = ','; } +|	'='			{ $$ = '='; } +|	PASTE			{ $$ = PASTE; } +|	DEFINED			{ $$ = DEFINED; } +; + +%% + +string_list_t * +_string_list_create (void *ctx) +{ +	string_list_t *list; + +	list = xtalloc (ctx, string_list_t); +	list->head = NULL; +	list->tail = NULL; + +	return list; +} + +void +_string_list_append_list (string_list_t *list, string_list_t *tail) +{ +	if (list->head == NULL) { +		list->head = tail->head; +	} else { +		list->tail->next = tail->head; +	} + +	list->tail = tail->tail; +} + +void +_string_list_append_item (string_list_t *list, const char *str) +{ +	string_node_t *node; + +	node = xtalloc (list, string_node_t); +	node->str = xtalloc_strdup (node, str); + +	node->next = NULL; + +	if (list->head == NULL) { +		list->head = node; +	} else { +		list->tail->next = node; +	} + +	list->tail = node; +} + +int +_string_list_contains (string_list_t *list, const char *member, int *index) +{ +	string_node_t *node; +	int i; + +	if (list == NULL) +		return 0; + +	for (i = 0, node = list->head; node; i++, node = node->next) { +		if (strcmp (node->str, member) == 0) { +			if (index) +				*index = i; +			return 1; +		} +	} + +	return 0; +} + +int +_string_list_length (string_list_t *list) +{ +	int length = 0; +	string_node_t *node; + +	if (list == NULL) +		return 0; + +	for (node = list->head; node; node = node->next) +		length++; + +	return length; +} + +argument_list_t * +_argument_list_create (void *ctx) +{ +	argument_list_t *list; + +	list = xtalloc (ctx, argument_list_t); +	list->head = NULL; +	list->tail = NULL; + +	return list; +} + +void +_argument_list_append (argument_list_t *list, token_list_t *argument) +{ +	argument_node_t *node; + +	node = xtalloc (list, argument_node_t); +	node->argument = argument; + +	node->next = NULL; + +	if (list->head == NULL) { +		list->head = node; +	} else { +		list->tail->next = node; +	} + +	list->tail = node; +} + +int +_argument_list_length (argument_list_t *list) +{ +	int length = 0; +	argument_node_t *node; + +	if (list == NULL) +		return 0; + +	for (node = list->head; node; node = node->next) +		length++; + +	return length; +} + +token_list_t * +_argument_list_member_at (argument_list_t *list, int index) +{ +	argument_node_t *node; +	int i; + +	if (list == NULL) +		return NULL; + +	node = list->head; +	for (i = 0; i < index; i++) { +		node = node->next; +		if (node == NULL) +			break; +	} + +	if (node) +		return node->argument; + +	return NULL; +} + +/* Note: This function talloc_steal()s the str pointer. */ +token_t * +_token_create_str (void *ctx, int type, char *str) +{ +	token_t *token; + +	token = xtalloc (ctx, token_t); +	token->type = type; +	token->value.str = talloc_steal (token, str); + +	return token; +} + +token_t * +_token_create_ival (void *ctx, int type, int ival) +{ +	token_t *token; + +	token = xtalloc (ctx, token_t); +	token->type = type; +	token->value.ival = ival; + +	return token; +} + +token_list_t * +_token_list_create (void *ctx) +{ +	token_list_t *list; + +	list = xtalloc (ctx, token_list_t); +	list->head = NULL; +	list->tail = NULL; +	list->non_space_tail = NULL; + +	return list; +} + +void +_token_list_append (token_list_t *list, token_t *token) +{ +	token_node_t *node; + +	node = xtalloc (list, token_node_t); +	node->token = xtalloc_reference (list, token); + +	node->next = NULL; + +	if (list->head == NULL) { +		list->head = node; +	} else { +		list->tail->next = node; +	} + +	list->tail = node; +	if (token->type != SPACE) +		list->non_space_tail = node; +} + +void +_token_list_append_list (token_list_t *list, token_list_t *tail) +{ +	if (tail == NULL || tail->head == NULL) +		return; + +	if (list->head == NULL) { +		list->head = tail->head; +	} else { +		list->tail->next = tail->head; +	} + +	list->tail = tail->tail; +	list->non_space_tail = tail->non_space_tail; +} + +token_list_t * +_token_list_copy (void *ctx, token_list_t *other) +{ +	token_list_t *copy; +	token_node_t *node; + +	if (other == NULL) +		return NULL; + +	copy = _token_list_create (ctx); +	for (node = other->head; node; node = node->next) +		_token_list_append (copy, node->token); + +	return copy; +} + +void +_token_list_trim_trailing_space (token_list_t *list) +{ +	token_node_t *tail, *next; + +	if (list->non_space_tail) { +		tail = list->non_space_tail->next; +		list->non_space_tail->next = NULL; +		list->tail = list->non_space_tail; + +		while (tail) { +			next = tail->next; +			talloc_free (tail); +			tail = next; +		} +	} +} + +static int +_token_list_length (token_list_t *list) +{ +	int length = 0; +	token_node_t *node; + +	if (list == NULL) +		return 0; + +	for (node = list->head; node; node = node->next) +		length++; + +	return length; +} + +static void +_token_print (token_t *token) +{ +	if (token->type < 256) { +		printf ("%c", token->type); +		return; +	} + +	switch (token->type) { +	case INTEGER: +		printf ("%" PRIxMAX, token->value.ival); +		break; +	case IDENTIFIER: +	case INTEGER_STRING: +	case OTHER: +		printf ("%s", token->value.str); +		break; +	case SPACE: +		printf (" "); +		break; +	case LEFT_SHIFT: +		printf ("<<"); +		break; +	case RIGHT_SHIFT: +		printf (">>"); +		break; +	case LESS_OR_EQUAL: +		printf ("<="); +		break; +	case GREATER_OR_EQUAL: +		printf (">="); +		break; +	case EQUAL: +		printf ("=="); +		break; +	case NOT_EQUAL: +		printf ("!="); +		break; +	case AND: +		printf ("&&"); +		break; +	case OR: +		printf ("||"); +		break; +	case PASTE: +		printf ("##"); +		break; +	case COMMA_FINAL: +		printf (","); +		break; +	case PLACEHOLDER: +		/* Nothing to print. */ +		break; +	default: +		fprintf (stderr, "Error: Don't know how to print token type %d\n", token->type); +		break; +	} +} + +/* Return a new token (talloc()ed off of 'token') formed by pasting + * 'token' and 'other'. Note that this function may return 'token' or + * 'other' directly rather than allocating anything new. + * + * Caution: Only very cursory error-checking is performed to see if + * the final result is a valid single token. */ +static token_t * +_token_paste (token_t *token, token_t *other) +{ +	/* Pasting a placeholder onto anything makes no change. */ +	if (other->type == PLACEHOLDER) +		return token; + +	/* When 'token' is a placeholder, just return 'other'. */ +	if (token->type == PLACEHOLDER) +		return other; + +	/* A very few single-character punctuators can be combined +	 * with another to form a multi-character punctuator. */ +	switch (token->type) { +	case '<': +		if (other->type == '<') +			return _token_create_ival (token, LEFT_SHIFT, LEFT_SHIFT); +		else if (other->type == '=') +			return _token_create_ival (token, LESS_OR_EQUAL, LESS_OR_EQUAL); +		break; +	case '>': +		if (other->type == '>') +			return _token_create_ival (token, RIGHT_SHIFT, RIGHT_SHIFT); +		else if (other->type == '=') +			return _token_create_ival (token, GREATER_OR_EQUAL, GREATER_OR_EQUAL); +		break; +	case '=': +		if (other->type == '=') +			return _token_create_ival (token, EQUAL, EQUAL); +		break; +	case '!': +		if (other->type == '=') +			return _token_create_ival (token, NOT_EQUAL, NOT_EQUAL); +		break; +	case '&': +		if (other->type == '&') +			return _token_create_ival (token, AND, AND); +		break; +	case '|': +		if (other->type == '|') +			return _token_create_ival (token, OR, OR); +		break; +	} + +	/* Two string-valued tokens can usually just be mashed +	 * together. +	 * +	 * XXX: This isn't actually legitimate. Several things here +	 * should result in a diagnostic since the result cannot be a +	 * valid, single pre-processing token. For example, pasting +	 * "123" and "abc" is not legal, but we don't catch that +	 * here. */ +	if ((token->type == IDENTIFIER || token->type == OTHER || token->type == INTEGER_STRING) && +	    (other->type == IDENTIFIER || other->type == OTHER || other->type == INTEGER_STRING)) +	{ +		char *str; + +		str = xtalloc_asprintf (token, "%s%s", +					token->value.str, other->value.str); +		return _token_create_str (token, token->type, str); +	} + +	printf ("Error: Pasting \""); +	_token_print (token); +	printf ("\" and \""); +	_token_print (other); +	printf ("\" does not give a valid preprocessing token.\n"); + +	return token; +} + +static void +_token_list_print (token_list_t *list) +{ +	token_node_t *node; + +	if (list == NULL) +		return; + +	for (node = list->head; node; node = node->next) +		_token_print (node->token); +} + +void +yyerror (void *scanner, const char *error) +{ +	fprintf (stderr, "Parse error: %s\n", error); +} + +glcpp_parser_t * +glcpp_parser_create (void) +{ +	glcpp_parser_t *parser; + +	parser = xtalloc (NULL, glcpp_parser_t); + +	glcpp_lex_init_extra (parser, &parser->scanner); +	parser->defines = hash_table_ctor (32, hash_table_string_hash, +					   hash_table_string_compare); +	parser->active = NULL; +	parser->lexing_if = 0; +	parser->space_tokens = 1; +	parser->newline_as_space = 0; +	parser->in_control_line = 0; +	parser->paren_count = 0; + +	parser->skip_stack = NULL; + +	parser->lex_from_list = NULL; +	parser->lex_from_node = NULL; + +	return parser; +} + +int +glcpp_parser_parse (glcpp_parser_t *parser) +{ +	return yyparse (parser); +} + +void +glcpp_parser_destroy (glcpp_parser_t *parser) +{ +	if (parser->skip_stack) +		fprintf (stderr, "Error: Unterminated #if\n"); +	glcpp_lex_destroy (parser->scanner); +	hash_table_dtor (parser->defines); +	talloc_free (parser); +} + +/* Replace any occurences of DEFINED tokens in 'list' with either a + * '0' or '1' INTEGER token depending on whether the next token in the + * list is defined or not. */ +static void +_glcpp_parser_evaluate_defined (glcpp_parser_t *parser, +				token_list_t *list) +{ +	token_node_t *node, *next; +	macro_t *macro; + +	if (list == NULL) +		return; + +	for (node = list->head; node; node = node->next) { +		if (node->token->type != DEFINED) +			continue; +		next = node->next; +		while (next && next->token->type == SPACE) +			next = next->next; +		if (next == NULL || next->token->type != IDENTIFIER) { +			fprintf (stderr, "Error: operator \"defined\" requires an identifier\n"); +			exit (1); +		} +		macro = hash_table_find (parser->defines, +					 next->token->value.str); + +		node->token->type = INTEGER; +		node->token->value.ival = (macro != NULL); +		node->next = next->next; +	} +} +	 +typedef enum function_status +{ +	FUNCTION_STATUS_SUCCESS, +	FUNCTION_NOT_A_FUNCTION, +	FUNCTION_UNBALANCED_PARENTHESES +} function_status_t; + +/* Find a set of function-like macro arguments by looking for a + * balanced set of parentheses. + * + * When called, 'node' should be the opening-parenthesis token, (or + * perhaps preceeding SPACE tokens). Upon successful return *last will + * be the last consumed node, (corresponding to the closing right + * parenthesis). + * + * Return values: + * + *   FUNCTION_STATUS_SUCCESS: + * + *	Successfully parsed a set of function arguments.	 + * + *   FUNCTION_NOT_A_FUNCTION: + * + *	Macro name not followed by a '('. This is not an error, but + *	simply that the macro name should be treated as a non-macro. + * + *   FUNCTION_UNBALANCED_PARENTHESES + * + *	Macro name is not followed by a balanced set of parentheses. + */ +static function_status_t +_arguments_parse (argument_list_t *arguments, +		  token_node_t *node, +		  token_node_t **last) +{ +	token_list_t *argument; +	int paren_count; + +	node = node->next; + +	/* Ignore whitespace before first parenthesis. */ +	while (node && node->token->type == SPACE) +		node = node->next; + +	if (node == NULL || node->token->type != '(') +		return FUNCTION_NOT_A_FUNCTION; + +	node = node->next; + +	argument = _token_list_create (arguments); +	_argument_list_append (arguments, argument); + +	for (paren_count = 1; node; node = node->next) { +		if (node->token->type == '(') +		{ +			paren_count++; +		} +		else if (node->token->type == ')') +		{ +			paren_count--; +			if (paren_count == 0) +				break; +		} + +		if (node->token->type == ',' && +			 paren_count == 1) +		{ +			_token_list_trim_trailing_space (argument); +			argument = _token_list_create (arguments); +			_argument_list_append (arguments, argument); +		} +		else { +			if (argument->head == NULL) { +				/* Don't treat initial whitespace as +				 * part of the arguement. */ +				if (node->token->type == SPACE) +					continue; +			} +			_token_list_append (argument, node->token); +		} +	} + +	if (paren_count) +		return FUNCTION_UNBALANCED_PARENTHESES; + +	*last = node; + +	return FUNCTION_STATUS_SUCCESS; +} + +/* This is a helper function that's essentially part of the + * implementation of _glcpp_parser_expand_node. It shouldn't be called + * except for by that function. + * + * Returns NULL if node is a simple token with no expansion, (that is, + * although 'node' corresponds to an identifier defined as a + * function-like macro, it is not followed with a parenthesized + * argument list). + * + * Compute the complete expansion of node (which is a function-like + * macro) and subsequent nodes which are arguments. + * + * Returns the token list that results from the expansion and sets + * *last to the last node in the list that was consumed by the + * expansion. Specificallty, *last will be set as follows: as the + * token of the closing right parenthesis. + */ +static token_list_t * +_glcpp_parser_expand_function (glcpp_parser_t *parser, +			       token_node_t *node, +			       token_node_t **last) +			        +{ +	macro_t *macro; +	const char *identifier; +	argument_list_t *arguments; +	function_status_t status; +	token_list_t *substituted; +	int parameter_index; + +	identifier = node->token->value.str; + +	macro = hash_table_find (parser->defines, identifier); + +	assert (macro->is_function); + +	arguments = _argument_list_create (parser); +	status = _arguments_parse (arguments, node, last); + +	switch (status) { +	case FUNCTION_STATUS_SUCCESS: +		break; +	case FUNCTION_NOT_A_FUNCTION: +		return NULL; +	case FUNCTION_UNBALANCED_PARENTHESES: +		fprintf (stderr, "Error: Macro %s call has unbalanced parentheses\n", +			 identifier); +		exit (1); +		return NULL; +	} + +	if (macro->replacements == NULL) { +		talloc_free (arguments); +		return _token_list_create (parser); +	} + +	if (! ((_argument_list_length (arguments) ==  +		_string_list_length (macro->parameters)) || +	       (_string_list_length (macro->parameters) == 0 && +		_argument_list_length (arguments) == 1 && +		arguments->head->argument->head == NULL))) +	{ +		fprintf (stderr, +			 "Error: macro %s invoked with %d arguments (expected %d)\n", +			 identifier, +			 _argument_list_length (arguments), +			 _string_list_length (macro->parameters)); +		return NULL; +	} + +	/* Perform argument substitution on the replacement list. */ +	substituted = _token_list_create (arguments); + +	for (node = macro->replacements->head; node; node = node->next) +	{ +		if (node->token->type == IDENTIFIER && +		    _string_list_contains (macro->parameters, +					   node->token->value.str, +					   ¶meter_index)) +		{ +			token_list_t *argument; +			argument = _argument_list_member_at (arguments, +							     parameter_index); +			/* Before substituting, we expand the argument +			 * tokens, or append a placeholder token for +			 * an empty argument. */ +			if (argument->head) { +				_glcpp_parser_expand_token_list (parser, +								 argument); +				_token_list_append_list (substituted, argument); +			} else { +				token_t *new_token; + +				new_token = _token_create_ival (substituted, +								PLACEHOLDER, +								PLACEHOLDER); +				_token_list_append (substituted, new_token); +			} +		} else { +			_token_list_append (substituted, node->token); +		} +	} + +	/* After argument substitution, and before further expansion +	 * below, implement token pasting. */ + +	_token_list_trim_trailing_space (substituted); + +	node = substituted->head; +	while (node) +	{ +		token_node_t *next_non_space; + +		/* Look ahead for a PASTE token, skipping space. */ +		next_non_space = node->next; +		while (next_non_space && next_non_space->token->type == SPACE) +			next_non_space = next_non_space->next; + +		if (next_non_space == NULL) +			break; + +		if (next_non_space->token->type != PASTE) { +			node = next_non_space; +			continue; +		} + +		/* Now find the next non-space token after the PASTE. */ +		next_non_space = next_non_space->next; +		while (next_non_space && next_non_space->token->type == SPACE) +			next_non_space = next_non_space->next; + +		if (next_non_space == NULL) { +			fprintf (stderr, "Error: '##' cannot appear at either end of a macro expansion\n"); +			return NULL; +		} + +		node->token = _token_paste (node->token, next_non_space->token); +		node->next = next_non_space->next; +		if (next_non_space == substituted->tail) +			substituted->tail = node; + +		node = node->next; +	} + +	substituted->non_space_tail = substituted->tail; + +	return substituted; +} + +/* Compute the complete expansion of node, (and subsequent nodes after + * 'node' in the case that 'node' is a function-like macro and + * subsequent nodes are arguments). + * + * Returns NULL if node is a simple token with no expansion. + * + * Otherwise, returns the token list that results from the expansion + * and sets *last to the last node in the list that was consumed by + * the expansion. Specificallty, *last will be set as follows: + * + *	As 'node' in the case of object-like macro expansion. + * + *	As the token of the closing right parenthesis in the case of + *	function-like macro expansion. + */ +static token_list_t * +_glcpp_parser_expand_node (glcpp_parser_t *parser, +			   token_node_t *node, +			   token_node_t **last) +{ +	token_t *token = node->token; +	const char *identifier; +	macro_t *macro; + +	/* We only expand identifiers */ +	if (token->type != IDENTIFIER) { +		/* We change any COMMA into a COMMA_FINAL to prevent +		 * it being mistaken for an argument separator +		 * later. */ +		if (token->type == ',') { +			token->type = COMMA_FINAL; +			token->value.ival = COMMA_FINAL; +		} + +		return NULL; +	} + +	/* Look up this identifier in the hash table. */ +	identifier = token->value.str; +	macro = hash_table_find (parser->defines, identifier); + +	/* Not a macro, so no expansion needed. */ +	if (macro == NULL) +		return NULL; + +	/* Finally, don't expand this macro if we're already actively +	 * expanding it, (to avoid infinite recursion). */ +	if (_active_list_contains (parser->active, identifier)) { +		/* We change the token type here from IDENTIFIER to +		 * OTHER to prevent any future expansion of this +		 * unexpanded token. */ +		char *str; +		token_list_t *expansion; +		token_t *final; + +		str = xtalloc_strdup (parser, token->value.str); +		final = _token_create_str (parser, OTHER, str); +		expansion = _token_list_create (parser); +		_token_list_append (expansion, final); +		*last = node; +		return expansion; +	} + +	if (! macro->is_function) +	{ +		*last = node; + +		if (macro->replacements == NULL) +			return _token_list_create (parser); + +		return _token_list_copy (parser, macro->replacements); +	} + +	return _glcpp_parser_expand_function (parser, node, last); +} + +/* Push a new identifier onto the active list, returning the new list. + * + * Here, 'marker' is the token node that appears in the list after the + * expansion of 'identifier'. That is, when the list iterator begins + * examinging 'marker', then it is time to pop this node from the + * active stack. + */ +active_list_t * +_active_list_push (active_list_t *list, +		   const char *identifier, +		   token_node_t *marker) +{ +	active_list_t *node; + +	node = xtalloc (list, active_list_t); +	node->identifier = xtalloc_strdup (node, identifier); +	node->marker = marker; +	node->next = list; + +	return node; +} + +active_list_t * +_active_list_pop (active_list_t *list) +{ +	active_list_t *node = list; + +	if (node == NULL) +		return NULL; + +	node = list->next; +	talloc_free (list); + +	return node; +} + +int +_active_list_contains (active_list_t *list, const char *identifier) +{ +	active_list_t *node; + +	if (list == NULL) +		return 0; + +	for (node = list; node; node = node->next) +		if (strcmp (node->identifier, identifier) == 0) +			return 1; + +	return 0; +} + +/* Walk over the token list replacing nodes with their expansion. + * Whenever nodes are expanded the walking will walk over the new + * nodes, continuing to expand as necessary. The results are placed in + * 'list' itself; + */ +static void +_glcpp_parser_expand_token_list (glcpp_parser_t *parser, +				 token_list_t *list) +{ +	token_node_t *node_prev; +	token_node_t *node, *last; +	token_list_t *expansion; + +	if (list == NULL) +		return; + +	_token_list_trim_trailing_space (list); + +	node_prev = NULL; +	node = list->head; + +	while (node) { + +		while (parser->active && parser->active->marker == node) +			parser->active = _active_list_pop (parser->active); + +		/* Find the expansion for node, which will replace all +		 * nodes from node to last, inclusive. */ +		expansion = _glcpp_parser_expand_node (parser, node, &last); +		if (expansion) { +			token_node_t *n; + +			for (n = node; n != last->next; n = n->next) +				while (parser->active && +				       parser->active->marker == n) +				{ +					parser->active = _active_list_pop (parser->active); +				} + +			parser->active = _active_list_push (parser->active, +							    node->token->value.str, +							    last->next); +			 +			/* Splice expansion into list, supporting a +			 * simple deletion if the expansion is +			 * empty. */ +			if (expansion->head) { +				if (node_prev) +					node_prev->next = expansion->head; +				else +					list->head = expansion->head; +				expansion->tail->next = last->next; +				if (last == list->tail) +					list->tail = expansion->tail; +			} else { +				if (node_prev) +					node_prev->next = last->next; +				else +					list->head = last->next; +				if (last == list->tail) +					list->tail == NULL; +			} +		} else { +			node_prev = node; +		} +		node = node_prev ? node_prev->next : list->head; +	} + +	while (parser->active) +		parser->active = _active_list_pop (parser->active); + +	list->non_space_tail = list->tail; +} + +void +_glcpp_parser_print_expanded_token_list (glcpp_parser_t *parser, +					 token_list_t *list) +{ +	if (list == NULL) +		return; + +	_glcpp_parser_expand_token_list (parser, list); + +	_token_list_trim_trailing_space (list); + +	_token_list_print (list); +} + +void +_check_for_reserved_macro_name (const char *identifier) +{ +	/* According to the GLSL specification, macro names starting with "__" +	 * or "GL_" are reserved for future use.  So, don't allow them. +	 */ +	if (strncmp(identifier, "__", 2) == 0) { +		fprintf (stderr, "Error: Macro names starting with \"__\" are reserved.\n"); +		exit(1); +	} +	if (strncmp(identifier, "GL_", 3) == 0) { +		fprintf (stderr, "Error: Macro names starting with \"GL_\" are reserved.\n"); +		exit(1); +	} +} + +void +_define_object_macro (glcpp_parser_t *parser, +		      const char *identifier, +		      token_list_t *replacements) +{ +	macro_t *macro; + +	_check_for_reserved_macro_name(identifier); + +	macro = xtalloc (parser, macro_t); + +	macro->is_function = 0; +	macro->parameters = NULL; +	macro->identifier = talloc_strdup (macro, identifier); +	macro->replacements = talloc_steal (macro, replacements); + +	hash_table_insert (parser->defines, macro, identifier); +} + +void +_define_function_macro (glcpp_parser_t *parser, +			const char *identifier, +			string_list_t *parameters, +			token_list_t *replacements) +{ +	macro_t *macro; + +	_check_for_reserved_macro_name(identifier); + +	macro = xtalloc (parser, macro_t); + +	macro->is_function = 1; +	macro->parameters = talloc_steal (macro, parameters); +	macro->identifier = talloc_strdup (macro, identifier); +	macro->replacements = talloc_steal (macro, replacements); + +	hash_table_insert (parser->defines, macro, identifier); +} + +static int +glcpp_parser_lex (glcpp_parser_t *parser) +{ +	token_node_t *node; +	int ret; + +	if (parser->lex_from_list == NULL) { +		ret = glcpp_lex (parser->scanner); + +		/* XXX: This ugly block of code exists for the sole +		 * purpose of converting a NEWLINE token into a SPACE +		 * token, but only in the case where we have seen a +		 * function-like macro name, but have not yet seen its +		 * closing parenthesis. +		 * +		 * There's perhaps a more compact way to do this with +		 * mid-rule actions in the grammar. +		 * +		 * I'm definitely not pleased with the complexity of +		 * this code here. +		 */ +		if (parser->newline_as_space) +		{ +			if (ret == '(') { +				parser->paren_count++; +			} else if (ret == ')') { +				parser->paren_count--; +				if (parser->paren_count == 0) +					parser->newline_as_space = 0; +			} else if (ret == NEWLINE) { +				ret = SPACE; +			} else if (ret != SPACE) { +				if (parser->paren_count == 0) +					parser->newline_as_space = 0; +			} +		} +		else if (parser->in_control_line) +		{ +			if (ret == NEWLINE) +				parser->in_control_line = 0; +		} +		else if (ret == HASH_DEFINE_OBJ || ret == HASH_DEFINE_FUNC || +			   ret == HASH_UNDEF || ret == HASH_IF || +			   ret == HASH_IFDEF || ret == HASH_IFNDEF || +			   ret == HASH_ELIF || ret == HASH_ELSE || +			   ret == HASH_ENDIF || ret == HASH) +		{ +			parser->in_control_line = 1; +		} +		else if (ret == IDENTIFIER) +		{ +			macro_t *macro; +			macro = hash_table_find (parser->defines, +						 yylval.str); +			if (macro && macro->is_function) { +				parser->newline_as_space = 1; +				parser->paren_count = 0; +			} +		} + +		return ret; +	} + +	node = parser->lex_from_node; + +	if (node == NULL) { +		talloc_free (parser->lex_from_list); +		parser->lex_from_list = NULL; +		return NEWLINE; +	} + +	yylval = node->token->value; +	ret = node->token->type; + +	parser->lex_from_node = node->next; + +	return ret; +} + +static void +glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list) +{ +	token_node_t *node; + +	assert (parser->lex_from_list == NULL); + +	/* Copy list, eliminating any space tokens. */ +	parser->lex_from_list = _token_list_create (parser); + +	for (node = list->head; node; node = node->next) { +		if (node->token->type == SPACE) +			continue; +		_token_list_append (parser->lex_from_list, node->token); +	} + +	talloc_free (list); + +	parser->lex_from_node = parser->lex_from_list->head; + +	/* It's possible the list consisted of nothing but whitespace. */ +	if (parser->lex_from_node == NULL) { +		talloc_free (parser->lex_from_list); +		parser->lex_from_list = NULL; +	} +} + +static void +_glcpp_parser_skip_stack_push_if (glcpp_parser_t *parser, int condition) +{ +	skip_type_t current = SKIP_NO_SKIP; +	skip_node_t *node; + +	if (parser->skip_stack) +		current = parser->skip_stack->type; + +	node = xtalloc (parser, skip_node_t); + +	if (current == SKIP_NO_SKIP) { +		if (condition) +			node->type = SKIP_NO_SKIP; +		else +			node->type = SKIP_TO_ELSE; +	} else { +		node->type = SKIP_TO_ENDIF; +	} + +	node->next = parser->skip_stack; +	parser->skip_stack = node; +} + +static void +_glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, const char *type, +				    int condition) +{ +	if (parser->skip_stack == NULL) { +		fprintf (stderr, "Error: %s without #if\n", type); +		exit (1); +	} + +	if (parser->skip_stack->type == SKIP_TO_ELSE) { +		if (condition) +			parser->skip_stack->type = SKIP_NO_SKIP; +	} else { +		parser->skip_stack->type = SKIP_TO_ENDIF; +	} +} + +static void +_glcpp_parser_skip_stack_pop (glcpp_parser_t *parser) +{ +	skip_node_t *node; + +	if (parser->skip_stack == NULL) { +		fprintf (stderr, "Error: #endif without #if\n"); +		exit (1); +	} + +	node = parser->skip_stack; +	parser->skip_stack = node->next; +	talloc_free (node); +} diff --git a/glcpp/glcpp.c b/glcpp/glcpp.c new file mode 100644 index 0000000000..fcdc4ed8a0 --- /dev/null +++ b/glcpp/glcpp.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "glcpp.h" + +extern int yydebug; + +int +main (void) +{ +	glcpp_parser_t *parser; +	int ret; + +	parser = glcpp_parser_create (); + +	ret = glcpp_parser_parse (parser); + +	glcpp_parser_destroy (parser); + +	return ret; +} diff --git a/glcpp/glcpp.h b/glcpp/glcpp.h new file mode 100644 index 0000000000..4459daa4f3 --- /dev/null +++ b/glcpp/glcpp.h @@ -0,0 +1,195 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef GLCPP_H +#define GLCPP_H + +#include <stdint.h> + +#include <talloc.h> + +#include "hash_table.h" + +#define yyscan_t void* + +/* Some data types used for parser values. */ + +typedef struct string_node { +	const char *str; +	struct string_node *next; +} string_node_t; + +typedef struct string_list { +	string_node_t *head; +	string_node_t *tail; +} string_list_t; + +typedef struct token token_t; +typedef struct token_list token_list_t; + +typedef union YYSTYPE +{ +	intmax_t ival; +	char *str; +	string_list_t *string_list; +	token_t *token; +	token_list_t *token_list; +} YYSTYPE; + +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 + +struct token { +	int type; +	YYSTYPE value; +}; + +typedef struct token_node { +	token_t *token; +	struct token_node *next; +} token_node_t; + +struct token_list { +	token_node_t *head; +	token_node_t *tail; +	token_node_t *non_space_tail; +}; + +typedef struct argument_node { +	token_list_t *argument; +	struct argument_node *next; +} argument_node_t; + +typedef struct argument_list { +	argument_node_t *head; +	argument_node_t *tail; +} argument_list_t; + +typedef struct glcpp_parser glcpp_parser_t; + +typedef enum { +	TOKEN_CLASS_IDENTIFIER, +	TOKEN_CLASS_IDENTIFIER_FINALIZED, +	TOKEN_CLASS_FUNC_MACRO, +	TOKEN_CLASS_OBJ_MACRO +} token_class_t; + +token_class_t +glcpp_parser_classify_token (glcpp_parser_t *parser, +			     const char *identifier, +			     int *parameter_index); + +typedef struct { +	int is_function; +	string_list_t *parameters; +	const char *identifier; +	token_list_t *replacements; +} macro_t; + +typedef struct expansion_node { +	macro_t *macro; +	token_node_t *replacements; +	struct expansion_node *next; +} expansion_node_t; + +typedef enum skip_type { +	SKIP_NO_SKIP, +	SKIP_TO_ELSE, +	SKIP_TO_ENDIF +} skip_type_t; + +typedef struct skip_node { +	skip_type_t type; +	struct skip_node *next; +} skip_node_t; + +typedef struct active_list { +	const char *identifier; +	token_node_t *marker; +	struct active_list *next; +} active_list_t; + +struct glcpp_parser { +	yyscan_t scanner; +	struct hash_table *defines; +	active_list_t *active; +	int lexing_if; +	int space_tokens; +	int newline_as_space; +	int in_control_line; +	int paren_count; +	skip_node_t *skip_stack; +	token_list_t *lex_from_list; +	token_node_t *lex_from_node; +}; + +glcpp_parser_t * +glcpp_parser_create (void); + +int +glcpp_parser_parse (glcpp_parser_t *parser); + +void +glcpp_parser_destroy (glcpp_parser_t *parser); + +/* Generated by glcpp-lex.l to glcpp-lex.c */ + +int +glcpp_lex_init_extra (glcpp_parser_t *parser, yyscan_t* scanner); + +int +glcpp_lex (yyscan_t scanner); + +int +glcpp_lex_destroy (yyscan_t scanner); + +/* Generated by glcpp-parse.y to glcpp-parse.c */ + +int +yyparse (glcpp_parser_t *parser); + +/* xtalloc - wrappers around talloc to check for out-of-memory */ + +#define xtalloc(ctx, type) (type *)xtalloc_named_const(ctx, sizeof(type), #type) + +#define xtalloc_size(ctx, size) xtalloc_named_const(ctx, size, __location__) + +void * +xtalloc_named_const (const void *context, size_t size, const char *name); + +char * +xtalloc_strdup (const void *t, const char *p); + +char * +xtalloc_strndup (const void *t, const char *p, size_t n); + +char * +xtalloc_asprintf (const void *t, const char *fmt, ...); + +void * +_xtalloc_reference_loc (const void *context, +			const void *ptr, const char *location); + +#define xtalloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_xtalloc_reference_loc((ctx),(ptr), __location__) + +#endif diff --git a/glcpp/hash_table.c b/glcpp/hash_table.c new file mode 100644 index 0000000000..e89a2564d7 --- /dev/null +++ b/glcpp/hash_table.c @@ -0,0 +1,159 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file hash_table.c + * \brief Implementation of a generic, opaque hash table data type. + * + * \author Ian Romanick <ian.d.romanick@intel.com> + */ + +#include "main/imports.h" +#include "main/simple_list.h" +#include "hash_table.h" + +struct node { +   struct node *next; +   struct node *prev; +}; + +struct hash_table { +    hash_func_t    hash; +    hash_compare_func_t  compare; + +    unsigned num_buckets; +    struct node buckets[1]; +}; + + +struct hash_node { +    struct node link; +    const void *key; +    void *data; +}; + + +struct hash_table * +hash_table_ctor(unsigned num_buckets, hash_func_t hash, +                hash_compare_func_t compare) +{ +    struct hash_table *ht; +    unsigned i; + + +    if (num_buckets < 16) { +        num_buckets = 16; +    } + +    ht = _mesa_malloc(sizeof(*ht) + ((num_buckets - 1)  +				     * sizeof(ht->buckets[0]))); +    if (ht != NULL) { +        ht->hash = hash; +        ht->compare = compare; +        ht->num_buckets = num_buckets; + +        for (i = 0; i < num_buckets; i++) { +            make_empty_list(& ht->buckets[i]); +        } +    } + +    return ht; +} + + +void +hash_table_dtor(struct hash_table *ht) +{ +   hash_table_clear(ht); +   _mesa_free(ht); +} + + +void +hash_table_clear(struct hash_table *ht) +{ +   struct node *node; +   struct node *temp; +   unsigned i; + + +   for (i = 0; i < ht->num_buckets; i++) { +      foreach_s(node, temp, & ht->buckets[i]) { +	 remove_from_list(node); +	 _mesa_free(node); +      } + +      assert(is_empty_list(& ht->buckets[i])); +   } +} + + +void * +hash_table_find(struct hash_table *ht, const void *key) +{ +    const unsigned hash_value = (*ht->hash)(key); +    const unsigned bucket = hash_value % ht->num_buckets; +    struct node *node; + +    foreach(node, & ht->buckets[bucket]) { +       struct hash_node *hn = (struct hash_node *) node; + +       if ((*ht->compare)(hn->key, key) == 0) { +	  return hn->data; +       } +    } + +    return NULL; +} + + +void +hash_table_insert(struct hash_table *ht, void *data, const void *key) +{ +    const unsigned hash_value = (*ht->hash)(key); +    const unsigned bucket = hash_value % ht->num_buckets; +    struct hash_node *node; + +    node = _mesa_calloc(sizeof(*node)); + +    node->data = data; +    node->key = key; + +    insert_at_head(& ht->buckets[bucket], & node->link); +} + + +unsigned +hash_table_string_hash(const void *key) +{ +    const char *str = (const char *) key; +    unsigned hash = 5381; + + +    while (*str != '\0') { +        hash = (hash * 33) + *str; +        str++; +    } + +    return hash; +} diff --git a/glcpp/hash_table.h b/glcpp/hash_table.h new file mode 100644 index 0000000000..b9dd343dee --- /dev/null +++ b/glcpp/hash_table.h @@ -0,0 +1,125 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file hash_table.h + * \brief Implementation of a generic, opaque hash table data type. + * + * \author Ian Romanick <ian.d.romanick@intel.com> + */ + +#ifndef HASH_TABLE_H +#define HASH_TABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <string.h> + +struct hash_table; + +typedef unsigned (*hash_func_t)(const void *key); +typedef int (*hash_compare_func_t)(const void *key1, const void *key2); + +/** + * Hash table constructor + * + * Creates a hash table with the specified number of buckets.  The supplied + * \c hash and \c compare routines are used when adding elements to the table + * and when searching for elements in the table. + * + * \param num_buckets  Number of buckets (bins) in the hash table. + * \param hash         Function used to compute hash value of input keys. + * \param compare      Function used to compare keys. + */ +extern struct hash_table *hash_table_ctor(unsigned num_buckets, +    hash_func_t hash, hash_compare_func_t compare); + + +/** + * Release all memory associated with a hash table + * + * \warning + * This function cannot release memory occupied either by keys or data. + */ +extern void hash_table_dtor(struct hash_table *ht); + + +/** + * Flush all entries from a hash table + * + * \param ht  Table to be cleared of its entries. + */ +extern void hash_table_clear(struct hash_table *ht); + + +/** + * Search a hash table for a specific element + * + * \param ht   Table to be searched + * \param key  Key of the desired element + * + * \return + * The \c data value supplied to \c hash_table_insert when the element with + * the matching key was added.  If no matching key exists in the table, + * \c NULL is returned. + */ +extern void *hash_table_find(struct hash_table *ht, const void *key); + + +/** + * Add an element to a hash table + */ +extern void hash_table_insert(struct hash_table *ht, void *data, +    const void *key); + + +/** + * Compute hash value of a string + * + * Computes the hash value of a string using the DJB2 algorithm developed by + * Professor Daniel J. Bernstein.  It was published on comp.lang.c once upon + * a time.  I was unable to find the original posting in the archives. + * + * \param key  Pointer to a NUL terminated string to be hashed. + * + * \sa hash_table_string_compare + */ +extern unsigned hash_table_string_hash(const void *key); + + +/** + * Compare two strings used as keys + * + * This is just a macro wrapper around \c strcmp. + * + * \sa hash_table_string_hash + */ +#define hash_table_string_compare ((hash_compare_func_t) strcmp) + +#ifdef __cplusplus +}; +#endif + +#endif /* HASH_TABLE_H */ diff --git a/glcpp/main/imports.h b/glcpp/main/imports.h new file mode 100644 index 0000000000..d2197342c0 --- /dev/null +++ b/glcpp/main/imports.h @@ -0,0 +1,6 @@ +#include <assert.h> +#include <stdlib.h> + +#define _mesa_malloc(x)   malloc(x) +#define _mesa_free(x)     free(x) +#define _mesa_calloc(x)   calloc(1,x) diff --git a/glcpp/main/simple_list.h b/glcpp/main/simple_list.h new file mode 100644 index 0000000000..5ef39e14cc --- /dev/null +++ b/glcpp/main/simple_list.h @@ -0,0 +1,235 @@ +/** + * \file simple_list.h + * Simple macros for type-safe, intrusive lists. + * + *  Intended to work with a list sentinal which is created as an empty + *  list.  Insert & delete are O(1). + *   + * \author + *  (C) 1997, Keith Whitwell + */ + +/* + * Mesa 3-D graphics library + * Version:  3.5 + * + * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _SIMPLE_LIST_H +#define _SIMPLE_LIST_H + +struct simple_node { +   struct simple_node *next; +   struct simple_node *prev; +}; + +/** + * Remove an element from list. + * + * \param elem element to remove. + */ +#define remove_from_list(elem)			\ +do {						\ +   (elem)->next->prev = (elem)->prev;		\ +   (elem)->prev->next = (elem)->next;		\ +} while (0) + +/** + * Insert an element to the list head. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_head(list, elem)		\ +do {						\ +   (elem)->prev = list;				\ +   (elem)->next = (list)->next;			\ +   (list)->next->prev = elem;			\ +   (list)->next = elem;				\ +} while(0) + +/** + * Insert an element to the list tail. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_tail(list, elem)		\ +do {						\ +   (elem)->next = list;				\ +   (elem)->prev = (list)->prev;			\ +   (list)->prev->next = elem;			\ +   (list)->prev = elem;				\ +} while(0) + +/** + * Move an element to the list head. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_head(list, elem)		\ +do {						\ +   remove_from_list(elem);			\ +   insert_at_head(list, elem);			\ +} while (0) + +/** + * Move an element to the list tail. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_tail(list, elem)		\ +do {						\ +   remove_from_list(elem);			\ +   insert_at_tail(list, elem);			\ +} while (0) + +/** + * Consatinate a cyclic list to a list + * + * Appends the sequence of nodes starting with \c tail to the list \c head. + * A "cyclic list" is a list that does not have a sentinal node.  This means + * that the data pointed to by \c tail is an actual node, not a dataless + * sentinal.  Note that if \c tail constist of a single node, this macro + * behaves identically to \c insert_at_tail + * + * \param head Head of the list to be appended to.  This may or may not + *             be a cyclic list. + * \param tail Head of the cyclic list to be appended to \c head. + * \param temp Temporary \c simple_list used by the macro + * + * \sa insert_at_tail + */ +#define concat_list_and_cycle(head, tail, temp)	\ +do {						\ +   (head)->prev->next = (tail);			\ +   (tail)->prev->next = (head);			\ +   (temp) = (head)->prev;			\ +   (head)->prev = (tail)->prev;			\ +   (tail)->prev = (temp);			\ +} while (0) + +#define concat_list(head, next_list)		\ +do {						\ +   (next_list)->next->prev = (head)->prev;	\ +   (next_list)->prev->next = (head);		\ +   (head)->prev->next = (next_list)->next;	\ +   (head)->prev = (next_list)->prev;		\ +} while (0) + +/** + * Make a empty list empty. + * + * \param sentinal list (sentinal element). + */ +#define make_empty_list(sentinal)		\ +do {						\ +   (sentinal)->next = sentinal;			\ +   (sentinal)->prev = sentinal;			\ +} while (0) + +/** + * Get list first element. + * + * \param list list. + * + * \return pointer to first element. + */ +#define first_elem(list)       ((list)->next) + +/** + * Get list last element. + * + * \param list list. + * + * \return pointer to last element. + */ +#define last_elem(list)        ((list)->prev) + +/** + * Get next element. + * + * \param elem element. + * + * \return pointer to next element. + */ +#define next_elem(elem)        ((elem)->next) + +/** + * Get previous element. + * + * \param elem element. + * + * \return pointer to previous element. + */ +#define prev_elem(elem)        ((elem)->prev) + +/** + * Test whether element is at end of the list. + *  + * \param list list. + * \param elem element. + *  + * \return non-zero if element is at end of list, or zero otherwise. + */ +#define at_end(list, elem)     ((elem) == (list)) + +/** + * Test if a list is empty. + *  + * \param list list. + *  + * \return non-zero if list empty, or zero otherwise. + */ +#define is_empty_list(list)    ((list)->next == (list)) + +/** + * Walk through the elements of a list. + * + * \param ptr pointer to the current element. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach(ptr, list)     \ +        for( ptr=(list)->next ;  ptr!=list ;  ptr=(ptr)->next ) + +/** + * Walk through the elements of a list. + * + * Same as #foreach but lets you unlink the current value during a list + * traversal.  Useful for freeing a list, element by element. + *  + * \param ptr pointer to the current element. + * \param t temporary pointer. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach_s(ptr, t, list)   \ +        for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) + +#endif diff --git a/glcpp/tests/000-content-with-spaces.c b/glcpp/tests/000-content-with-spaces.c new file mode 100644 index 0000000000..696cb3a74f --- /dev/null +++ b/glcpp/tests/000-content-with-spaces.c @@ -0,0 +1 @@ +this is  four 	tokens diff --git a/glcpp/tests/000-content-with-spaces.c.expected b/glcpp/tests/000-content-with-spaces.c.expected new file mode 100644 index 0000000000..a7fc918c90 --- /dev/null +++ b/glcpp/tests/000-content-with-spaces.c.expected @@ -0,0 +1 @@ +this is four tokens diff --git a/glcpp/tests/001-define.c b/glcpp/tests/001-define.c new file mode 100644 index 0000000000..cbf2fee0e7 --- /dev/null +++ b/glcpp/tests/001-define.c @@ -0,0 +1,2 @@ +#define foo 1 +foo diff --git a/glcpp/tests/001-define.c.expected b/glcpp/tests/001-define.c.expected new file mode 100644 index 0000000000..a464d9da74 --- /dev/null +++ b/glcpp/tests/001-define.c.expected @@ -0,0 +1,2 @@ + +1 diff --git a/glcpp/tests/002-define-chain.c b/glcpp/tests/002-define-chain.c new file mode 100644 index 0000000000..87d75c6875 --- /dev/null +++ b/glcpp/tests/002-define-chain.c @@ -0,0 +1,3 @@ +#define foo 1 +#define bar foo +bar diff --git a/glcpp/tests/002-define-chain.c.expected b/glcpp/tests/002-define-chain.c.expected new file mode 100644 index 0000000000..c6c9ee38a9 --- /dev/null +++ b/glcpp/tests/002-define-chain.c.expected @@ -0,0 +1,3 @@ + + +1 diff --git a/glcpp/tests/003-define-chain-reverse.c b/glcpp/tests/003-define-chain-reverse.c new file mode 100644 index 0000000000..a18b724eca --- /dev/null +++ b/glcpp/tests/003-define-chain-reverse.c @@ -0,0 +1,3 @@ +#define bar foo +#define foo 1 +bar diff --git a/glcpp/tests/003-define-chain-reverse.c.expected b/glcpp/tests/003-define-chain-reverse.c.expected new file mode 100644 index 0000000000..c6c9ee38a9 --- /dev/null +++ b/glcpp/tests/003-define-chain-reverse.c.expected @@ -0,0 +1,3 @@ + + +1 diff --git a/glcpp/tests/004-define-recursive.c b/glcpp/tests/004-define-recursive.c new file mode 100644 index 0000000000..2ac56ea3dc --- /dev/null +++ b/glcpp/tests/004-define-recursive.c @@ -0,0 +1,6 @@ +#define foo bar +#define bar baz +#define baz foo +foo +bar +baz diff --git a/glcpp/tests/004-define-recursive.c.expected b/glcpp/tests/004-define-recursive.c.expected new file mode 100644 index 0000000000..2d07687f8c --- /dev/null +++ b/glcpp/tests/004-define-recursive.c.expected @@ -0,0 +1,6 @@ + + + +foo +bar +baz diff --git a/glcpp/tests/005-define-composite-chain.c b/glcpp/tests/005-define-composite-chain.c new file mode 100644 index 0000000000..f5521df968 --- /dev/null +++ b/glcpp/tests/005-define-composite-chain.c @@ -0,0 +1,3 @@ +#define foo 1 +#define bar a foo +bar diff --git a/glcpp/tests/005-define-composite-chain.c.expected b/glcpp/tests/005-define-composite-chain.c.expected new file mode 100644 index 0000000000..892975c268 --- /dev/null +++ b/glcpp/tests/005-define-composite-chain.c.expected @@ -0,0 +1,3 @@ + + +a 1 diff --git a/glcpp/tests/006-define-composite-chain-reverse.c b/glcpp/tests/006-define-composite-chain-reverse.c new file mode 100644 index 0000000000..4bb91a1221 --- /dev/null +++ b/glcpp/tests/006-define-composite-chain-reverse.c @@ -0,0 +1,3 @@ +#define bar a foo +#define foo 1 +bar diff --git a/glcpp/tests/006-define-composite-chain-reverse.c.expected b/glcpp/tests/006-define-composite-chain-reverse.c.expected new file mode 100644 index 0000000000..892975c268 --- /dev/null +++ b/glcpp/tests/006-define-composite-chain-reverse.c.expected @@ -0,0 +1,3 @@ + + +a 1 diff --git a/glcpp/tests/007-define-composite-recursive.c b/glcpp/tests/007-define-composite-recursive.c new file mode 100644 index 0000000000..5784565bdf --- /dev/null +++ b/glcpp/tests/007-define-composite-recursive.c @@ -0,0 +1,6 @@ +#define foo a bar +#define bar b baz +#define baz c foo +foo +bar +baz diff --git a/glcpp/tests/007-define-composite-recursive.c.expected b/glcpp/tests/007-define-composite-recursive.c.expected new file mode 100644 index 0000000000..0b0b477d9d --- /dev/null +++ b/glcpp/tests/007-define-composite-recursive.c.expected @@ -0,0 +1,6 @@ + + + +a b c foo +b c a bar +c a b baz diff --git a/glcpp/tests/008-define-empty.c b/glcpp/tests/008-define-empty.c new file mode 100644 index 0000000000..b1bd17ec21 --- /dev/null +++ b/glcpp/tests/008-define-empty.c @@ -0,0 +1,2 @@ +#define foo +foo diff --git a/glcpp/tests/008-define-empty.c.expected b/glcpp/tests/008-define-empty.c.expected new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/glcpp/tests/008-define-empty.c.expected @@ -0,0 +1,2 @@ + + diff --git a/glcpp/tests/009-undef.c b/glcpp/tests/009-undef.c new file mode 100644 index 0000000000..3fc1fb4424 --- /dev/null +++ b/glcpp/tests/009-undef.c @@ -0,0 +1,4 @@ +#define foo 1 +foo +#undef foo +foo diff --git a/glcpp/tests/009-undef.c.expected b/glcpp/tests/009-undef.c.expected new file mode 100644 index 0000000000..9c0b35a451 --- /dev/null +++ b/glcpp/tests/009-undef.c.expected @@ -0,0 +1,4 @@ + +1 + +foo diff --git a/glcpp/tests/010-undef-re-define.c b/glcpp/tests/010-undef-re-define.c new file mode 100644 index 0000000000..32ff73798b --- /dev/null +++ b/glcpp/tests/010-undef-re-define.c @@ -0,0 +1,6 @@ +#define foo 1 +foo +#undef foo +foo +#define foo 2 +foo diff --git a/glcpp/tests/010-undef-re-define.c.expected b/glcpp/tests/010-undef-re-define.c.expected new file mode 100644 index 0000000000..5970f49028 --- /dev/null +++ b/glcpp/tests/010-undef-re-define.c.expected @@ -0,0 +1,6 @@ + +1 + +foo + +2 diff --git a/glcpp/tests/011-define-func-empty.c b/glcpp/tests/011-define-func-empty.c new file mode 100644 index 0000000000..d9ce13c228 --- /dev/null +++ b/glcpp/tests/011-define-func-empty.c @@ -0,0 +1,2 @@ +#define foo() +foo() diff --git a/glcpp/tests/011-define-func-empty.c.expected b/glcpp/tests/011-define-func-empty.c.expected new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/glcpp/tests/011-define-func-empty.c.expected @@ -0,0 +1,2 @@ + + diff --git a/glcpp/tests/012-define-func-no-args.c b/glcpp/tests/012-define-func-no-args.c new file mode 100644 index 0000000000..c2bb730b11 --- /dev/null +++ b/glcpp/tests/012-define-func-no-args.c @@ -0,0 +1,2 @@ +#define foo() bar +foo() diff --git a/glcpp/tests/012-define-func-no-args.c.expected b/glcpp/tests/012-define-func-no-args.c.expected new file mode 100644 index 0000000000..9f075f2600 --- /dev/null +++ b/glcpp/tests/012-define-func-no-args.c.expected @@ -0,0 +1,2 @@ + +bar diff --git a/glcpp/tests/013-define-func-1-arg-unused.c b/glcpp/tests/013-define-func-1-arg-unused.c new file mode 100644 index 0000000000..f78fb8b118 --- /dev/null +++ b/glcpp/tests/013-define-func-1-arg-unused.c @@ -0,0 +1,2 @@ +#define foo(x) 1 +foo(bar) diff --git a/glcpp/tests/013-define-func-1-arg-unused.c.expected b/glcpp/tests/013-define-func-1-arg-unused.c.expected new file mode 100644 index 0000000000..a464d9da74 --- /dev/null +++ b/glcpp/tests/013-define-func-1-arg-unused.c.expected @@ -0,0 +1,2 @@ + +1 diff --git a/glcpp/tests/014-define-func-2-arg-unused.c b/glcpp/tests/014-define-func-2-arg-unused.c new file mode 100644 index 0000000000..11feb2624b --- /dev/null +++ b/glcpp/tests/014-define-func-2-arg-unused.c @@ -0,0 +1,2 @@ +#define foo(x,y) 1 +foo(bar,baz) diff --git a/glcpp/tests/014-define-func-2-arg-unused.c.expected b/glcpp/tests/014-define-func-2-arg-unused.c.expected new file mode 100644 index 0000000000..a464d9da74 --- /dev/null +++ b/glcpp/tests/014-define-func-2-arg-unused.c.expected @@ -0,0 +1,2 @@ + +1 diff --git a/glcpp/tests/015-define-object-with-parens.c b/glcpp/tests/015-define-object-with-parens.c new file mode 100644 index 0000000000..558da9c617 --- /dev/null +++ b/glcpp/tests/015-define-object-with-parens.c @@ -0,0 +1,4 @@ +#define foo ()1 +foo() +#define bar ()2 +bar() diff --git a/glcpp/tests/015-define-object-with-parens.c.expected b/glcpp/tests/015-define-object-with-parens.c.expected new file mode 100644 index 0000000000..a70321a4c5 --- /dev/null +++ b/glcpp/tests/015-define-object-with-parens.c.expected @@ -0,0 +1,4 @@ + +()1() + +()2() diff --git a/glcpp/tests/016-define-func-1-arg.c b/glcpp/tests/016-define-func-1-arg.c new file mode 100644 index 0000000000..a2e2404c7c --- /dev/null +++ b/glcpp/tests/016-define-func-1-arg.c @@ -0,0 +1,2 @@ +#define foo(x) ((x)+1) +foo(bar) diff --git a/glcpp/tests/016-define-func-1-arg.c.expected b/glcpp/tests/016-define-func-1-arg.c.expected new file mode 100644 index 0000000000..6bfe04f738 --- /dev/null +++ b/glcpp/tests/016-define-func-1-arg.c.expected @@ -0,0 +1,2 @@ + +((bar)+1) diff --git a/glcpp/tests/017-define-func-2-args.c b/glcpp/tests/017-define-func-2-args.c new file mode 100644 index 0000000000..c725383527 --- /dev/null +++ b/glcpp/tests/017-define-func-2-args.c @@ -0,0 +1,2 @@ +#define foo(x,y) ((x)*(y)) +foo(bar,baz) diff --git a/glcpp/tests/017-define-func-2-args.c.expected b/glcpp/tests/017-define-func-2-args.c.expected new file mode 100644 index 0000000000..f7a2b8c26c --- /dev/null +++ b/glcpp/tests/017-define-func-2-args.c.expected @@ -0,0 +1,2 @@ + +((bar)*(baz)) diff --git a/glcpp/tests/018-define-func-macro-as-parameter.c b/glcpp/tests/018-define-func-macro-as-parameter.c new file mode 100644 index 0000000000..668130b8f9 --- /dev/null +++ b/glcpp/tests/018-define-func-macro-as-parameter.c @@ -0,0 +1,3 @@ +#define x 0 +#define foo(x) x +foo(1) diff --git a/glcpp/tests/018-define-func-macro-as-parameter.c.expected b/glcpp/tests/018-define-func-macro-as-parameter.c.expected new file mode 100644 index 0000000000..c6c9ee38a9 --- /dev/null +++ b/glcpp/tests/018-define-func-macro-as-parameter.c.expected @@ -0,0 +1,3 @@ + + +1 diff --git a/glcpp/tests/019-define-func-1-arg-multi.c b/glcpp/tests/019-define-func-1-arg-multi.c new file mode 100644 index 0000000000..c4e62b2550 --- /dev/null +++ b/glcpp/tests/019-define-func-1-arg-multi.c @@ -0,0 +1,2 @@ +#define foo(x) (x) +foo(this is more than one word) diff --git a/glcpp/tests/019-define-func-1-arg-multi.c.expected b/glcpp/tests/019-define-func-1-arg-multi.c.expected new file mode 100644 index 0000000000..1e89b8cfd0 --- /dev/null +++ b/glcpp/tests/019-define-func-1-arg-multi.c.expected @@ -0,0 +1,2 @@ + +(this is more than one word) diff --git a/glcpp/tests/020-define-func-2-arg-multi.c b/glcpp/tests/020-define-func-2-arg-multi.c new file mode 100644 index 0000000000..3049ad1546 --- /dev/null +++ b/glcpp/tests/020-define-func-2-arg-multi.c @@ -0,0 +1,2 @@ +#define foo(x,y) x,two fish,red fish,y +foo(one fish, blue fish) diff --git a/glcpp/tests/020-define-func-2-arg-multi.c.expected b/glcpp/tests/020-define-func-2-arg-multi.c.expected new file mode 100644 index 0000000000..19f59f5ecb --- /dev/null +++ b/glcpp/tests/020-define-func-2-arg-multi.c.expected @@ -0,0 +1,2 @@ + +one fish,two fish,red fish,blue fish diff --git a/glcpp/tests/021-define-func-compose.c b/glcpp/tests/021-define-func-compose.c new file mode 100644 index 0000000000..21ddd0e65f --- /dev/null +++ b/glcpp/tests/021-define-func-compose.c @@ -0,0 +1,3 @@ +#define bar(x) (1+(x)) +#define foo(y) (2*(y)) +foo(bar(3)) diff --git a/glcpp/tests/021-define-func-compose.c.expected b/glcpp/tests/021-define-func-compose.c.expected new file mode 100644 index 0000000000..87f51f0bac --- /dev/null +++ b/glcpp/tests/021-define-func-compose.c.expected @@ -0,0 +1,3 @@ + + +(2*((1+(3)))) diff --git a/glcpp/tests/022-define-func-arg-with-parens.c b/glcpp/tests/022-define-func-arg-with-parens.c new file mode 100644 index 0000000000..c20d73a4a2 --- /dev/null +++ b/glcpp/tests/022-define-func-arg-with-parens.c @@ -0,0 +1,2 @@ +#define foo(x) (x) +foo(argument(including parens)for the win) diff --git a/glcpp/tests/022-define-func-arg-with-parens.c.expected b/glcpp/tests/022-define-func-arg-with-parens.c.expected new file mode 100644 index 0000000000..1dfc6698bb --- /dev/null +++ b/glcpp/tests/022-define-func-arg-with-parens.c.expected @@ -0,0 +1,2 @@ + +(argument(including parens)for the win) diff --git a/glcpp/tests/023-define-extra-whitespace.c b/glcpp/tests/023-define-extra-whitespace.c new file mode 100644 index 0000000000..7ebfed6516 --- /dev/null +++ b/glcpp/tests/023-define-extra-whitespace.c @@ -0,0 +1,8 @@ +#define noargs() 1  +# define onearg(foo) foo  + # define  twoargs( x , y ) x y  +	#	define	threeargs(	a	,	b	,	c	) a b c  +noargs ( )  +onearg ( 2 )  +twoargs ( 3 , 4 )  +threeargs ( 5 , 6 , 7 )  diff --git a/glcpp/tests/023-define-extra-whitespace.c.expected b/glcpp/tests/023-define-extra-whitespace.c.expected new file mode 100644 index 0000000000..9c58275d0f --- /dev/null +++ b/glcpp/tests/023-define-extra-whitespace.c.expected @@ -0,0 +1,8 @@ + + + + +1 +2 +3 4 +5 6 7 diff --git a/glcpp/tests/024-define-chain-to-self-recursion.c b/glcpp/tests/024-define-chain-to-self-recursion.c new file mode 100644 index 0000000000..e788adce30 --- /dev/null +++ b/glcpp/tests/024-define-chain-to-self-recursion.c @@ -0,0 +1,3 @@ +#define  foo foo +#define  bar foo +bar diff --git a/glcpp/tests/024-define-chain-to-self-recursion.c.expected b/glcpp/tests/024-define-chain-to-self-recursion.c.expected new file mode 100644 index 0000000000..15600af546 --- /dev/null +++ b/glcpp/tests/024-define-chain-to-self-recursion.c.expected @@ -0,0 +1,3 @@ + + +foo diff --git a/glcpp/tests/025-func-macro-as-non-macro.c b/glcpp/tests/025-func-macro-as-non-macro.c new file mode 100644 index 0000000000..b433671d1b --- /dev/null +++ b/glcpp/tests/025-func-macro-as-non-macro.c @@ -0,0 +1,2 @@ +#define foo(bar) bar +foo bar diff --git a/glcpp/tests/025-func-macro-as-non-macro.c.expected b/glcpp/tests/025-func-macro-as-non-macro.c.expected new file mode 100644 index 0000000000..4a59f0520e --- /dev/null +++ b/glcpp/tests/025-func-macro-as-non-macro.c.expected @@ -0,0 +1,2 @@ + +foo bar diff --git a/glcpp/tests/026-define-func-extra-newlines.c b/glcpp/tests/026-define-func-extra-newlines.c new file mode 100644 index 0000000000..0d83740530 --- /dev/null +++ b/glcpp/tests/026-define-func-extra-newlines.c @@ -0,0 +1,6 @@ +#define foo(a) bar + +foo +( +1 +) diff --git a/glcpp/tests/026-define-func-extra-newlines.c.expected b/glcpp/tests/026-define-func-extra-newlines.c.expected new file mode 100644 index 0000000000..5e3c70f2cc --- /dev/null +++ b/glcpp/tests/026-define-func-extra-newlines.c.expected @@ -0,0 +1,3 @@ + + +bar diff --git a/glcpp/tests/027-define-chain-obj-to-func.c b/glcpp/tests/027-define-chain-obj-to-func.c new file mode 100644 index 0000000000..5ccb52caba --- /dev/null +++ b/glcpp/tests/027-define-chain-obj-to-func.c @@ -0,0 +1,3 @@ +#define failure() success +#define foo failure() +foo diff --git a/glcpp/tests/027-define-chain-obj-to-func.c.expected b/glcpp/tests/027-define-chain-obj-to-func.c.expected new file mode 100644 index 0000000000..94c15f9505 --- /dev/null +++ b/glcpp/tests/027-define-chain-obj-to-func.c.expected @@ -0,0 +1,3 @@ + + +success diff --git a/glcpp/tests/028-define-chain-obj-to-non-func.c b/glcpp/tests/028-define-chain-obj-to-non-func.c new file mode 100644 index 0000000000..44962a7187 --- /dev/null +++ b/glcpp/tests/028-define-chain-obj-to-non-func.c @@ -0,0 +1,3 @@ +#define success() failure +#define foo success +foo diff --git a/glcpp/tests/028-define-chain-obj-to-non-func.c.expected b/glcpp/tests/028-define-chain-obj-to-non-func.c.expected new file mode 100644 index 0000000000..94c15f9505 --- /dev/null +++ b/glcpp/tests/028-define-chain-obj-to-non-func.c.expected @@ -0,0 +1,3 @@ + + +success diff --git a/glcpp/tests/029-define-chain-obj-to-func-with-args.c b/glcpp/tests/029-define-chain-obj-to-func-with-args.c new file mode 100644 index 0000000000..261f7d28fc --- /dev/null +++ b/glcpp/tests/029-define-chain-obj-to-func-with-args.c @@ -0,0 +1,3 @@ +#define bar(failure) failure +#define foo bar(success) +foo diff --git a/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected b/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected new file mode 100644 index 0000000000..94c15f9505 --- /dev/null +++ b/glcpp/tests/029-define-chain-obj-to-func-with-args.c.expected @@ -0,0 +1,3 @@ + + +success diff --git a/glcpp/tests/030-define-chain-obj-to-func-compose.c b/glcpp/tests/030-define-chain-obj-to-func-compose.c new file mode 100644 index 0000000000..e56fbefd62 --- /dev/null +++ b/glcpp/tests/030-define-chain-obj-to-func-compose.c @@ -0,0 +1,4 @@ +#define baz(failure) failure +#define bar(failure) failure +#define foo bar(baz(success)) +foo diff --git a/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected b/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected new file mode 100644 index 0000000000..bed826e783 --- /dev/null +++ b/glcpp/tests/030-define-chain-obj-to-func-compose.c.expected @@ -0,0 +1,4 @@ + + + +success diff --git a/glcpp/tests/031-define-chain-func-to-func-compose.c b/glcpp/tests/031-define-chain-func-to-func-compose.c new file mode 100644 index 0000000000..3f4c8744df --- /dev/null +++ b/glcpp/tests/031-define-chain-func-to-func-compose.c @@ -0,0 +1,4 @@ +#define baz(failure) failure +#define bar(failure) failure +#define foo() bar(baz(success)) +foo() diff --git a/glcpp/tests/031-define-chain-func-to-func-compose.c.expected b/glcpp/tests/031-define-chain-func-to-func-compose.c.expected new file mode 100644 index 0000000000..bed826e783 --- /dev/null +++ b/glcpp/tests/031-define-chain-func-to-func-compose.c.expected @@ -0,0 +1,4 @@ + + + +success diff --git a/glcpp/tests/032-define-func-self-recurse.c b/glcpp/tests/032-define-func-self-recurse.c new file mode 100644 index 0000000000..b3ac70f499 --- /dev/null +++ b/glcpp/tests/032-define-func-self-recurse.c @@ -0,0 +1,2 @@ +#define foo(a) foo(2*(a)) +foo(3) diff --git a/glcpp/tests/032-define-func-self-recurse.c.expected b/glcpp/tests/032-define-func-self-recurse.c.expected new file mode 100644 index 0000000000..983f941740 --- /dev/null +++ b/glcpp/tests/032-define-func-self-recurse.c.expected @@ -0,0 +1,2 @@ + +foo(2*(3)) diff --git a/glcpp/tests/033-define-func-self-compose.c b/glcpp/tests/033-define-func-self-compose.c new file mode 100644 index 0000000000..f65e48286c --- /dev/null +++ b/glcpp/tests/033-define-func-self-compose.c @@ -0,0 +1,2 @@ +#define foo(a) foo(2*(a)) +foo(foo(3)) diff --git a/glcpp/tests/033-define-func-self-compose.c.expected b/glcpp/tests/033-define-func-self-compose.c.expected new file mode 100644 index 0000000000..0818362364 --- /dev/null +++ b/glcpp/tests/033-define-func-self-compose.c.expected @@ -0,0 +1,2 @@ + +foo(2*(foo(2*(3)))) diff --git a/glcpp/tests/034-define-func-self-compose-non-func.c b/glcpp/tests/034-define-func-self-compose-non-func.c new file mode 100644 index 0000000000..209a5f7e07 --- /dev/null +++ b/glcpp/tests/034-define-func-self-compose-non-func.c @@ -0,0 +1,2 @@ +#define foo(bar) bar +foo(foo) diff --git a/glcpp/tests/034-define-func-self-compose-non-func.c.expected b/glcpp/tests/034-define-func-self-compose-non-func.c.expected new file mode 100644 index 0000000000..3f808fe665 --- /dev/null +++ b/glcpp/tests/034-define-func-self-compose-non-func.c.expected @@ -0,0 +1,2 @@ + +foo diff --git a/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c b/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c new file mode 100644 index 0000000000..c307fbe830 --- /dev/null +++ b/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c @@ -0,0 +1,2 @@ +#define foo(bar) bar +foo(1+foo) diff --git a/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected b/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected new file mode 100644 index 0000000000..09dfdd64e9 --- /dev/null +++ b/glcpp/tests/035-define-func-self-compose-non-func-multi-token-argument.c.expected @@ -0,0 +1,2 @@ + +1+foo diff --git a/glcpp/tests/036-define-func-non-macro-multi-token-argument.c b/glcpp/tests/036-define-func-non-macro-multi-token-argument.c new file mode 100644 index 0000000000..b21ff33673 --- /dev/null +++ b/glcpp/tests/036-define-func-non-macro-multi-token-argument.c @@ -0,0 +1,3 @@ +#define bar success +#define foo(x) x +foo(more bar) diff --git a/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected b/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected new file mode 100644 index 0000000000..580ed9599c --- /dev/null +++ b/glcpp/tests/036-define-func-non-macro-multi-token-argument.c.expected @@ -0,0 +1,3 @@ + + +more success diff --git a/glcpp/tests/037-finalize-unexpanded-macro.c b/glcpp/tests/037-finalize-unexpanded-macro.c new file mode 100644 index 0000000000..b3a2f37f1b --- /dev/null +++ b/glcpp/tests/037-finalize-unexpanded-macro.c @@ -0,0 +1,3 @@ +#define expand(x) expand(x once) +#define foo(x) x +foo(expand(just)) diff --git a/glcpp/tests/037-finalize-unexpanded-macro.c.expected b/glcpp/tests/037-finalize-unexpanded-macro.c.expected new file mode 100644 index 0000000000..e804d7e4f9 --- /dev/null +++ b/glcpp/tests/037-finalize-unexpanded-macro.c.expected @@ -0,0 +1,3 @@ + + +expand(just once) diff --git a/glcpp/tests/038-func-arg-with-commas.c b/glcpp/tests/038-func-arg-with-commas.c new file mode 100644 index 0000000000..1407c7d6e3 --- /dev/null +++ b/glcpp/tests/038-func-arg-with-commas.c @@ -0,0 +1,2 @@ +#define foo(x) success +foo(argument (with,embedded , commas) -- tricky) diff --git a/glcpp/tests/038-func-arg-with-commas.c.expected b/glcpp/tests/038-func-arg-with-commas.c.expected new file mode 100644 index 0000000000..6544adb3a2 --- /dev/null +++ b/glcpp/tests/038-func-arg-with-commas.c.expected @@ -0,0 +1,2 @@ + +success diff --git a/glcpp/tests/039-func-arg-obj-macro-with-comma.c b/glcpp/tests/039-func-arg-obj-macro-with-comma.c new file mode 100644 index 0000000000..0f7fe632b5 --- /dev/null +++ b/glcpp/tests/039-func-arg-obj-macro-with-comma.c @@ -0,0 +1,3 @@ +#define foo(a) (a) +#define bar two,words +foo(bar) diff --git a/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected b/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected new file mode 100644 index 0000000000..8a15397a03 --- /dev/null +++ b/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected @@ -0,0 +1,3 @@ + + +(two,words) diff --git a/glcpp/tests/040-token-pasting.c b/glcpp/tests/040-token-pasting.c new file mode 100644 index 0000000000..caab3ba736 --- /dev/null +++ b/glcpp/tests/040-token-pasting.c @@ -0,0 +1,2 @@ +#define paste(a,b) a ## b +paste(one , token) diff --git a/glcpp/tests/040-token-pasting.c.expected b/glcpp/tests/040-token-pasting.c.expected new file mode 100644 index 0000000000..48e836ec3f --- /dev/null +++ b/glcpp/tests/040-token-pasting.c.expected @@ -0,0 +1,2 @@ + +onetoken diff --git a/glcpp/tests/041-if-0.c b/glcpp/tests/041-if-0.c new file mode 100644 index 0000000000..2cab677d3e --- /dev/null +++ b/glcpp/tests/041-if-0.c @@ -0,0 +1,5 @@ +success_1 +#if 0 +failure +#endif +success_2 diff --git a/glcpp/tests/041-if-0.c.expected b/glcpp/tests/041-if-0.c.expected new file mode 100644 index 0000000000..8b506b32d5 --- /dev/null +++ b/glcpp/tests/041-if-0.c.expected @@ -0,0 +1,5 @@ +success_1 + + + +success_2 diff --git a/glcpp/tests/042-if-1.c b/glcpp/tests/042-if-1.c new file mode 100644 index 0000000000..874a25cf41 --- /dev/null +++ b/glcpp/tests/042-if-1.c @@ -0,0 +1,5 @@ +success_1 +#if 1 +success_2 +#endif +success_3 diff --git a/glcpp/tests/042-if-1.c.expected b/glcpp/tests/042-if-1.c.expected new file mode 100644 index 0000000000..a6ae9465a9 --- /dev/null +++ b/glcpp/tests/042-if-1.c.expected @@ -0,0 +1,5 @@ +success_1 + +success_2 + +success_3 diff --git a/glcpp/tests/043-if-0-else.c b/glcpp/tests/043-if-0-else.c new file mode 100644 index 0000000000..323351f9db --- /dev/null +++ b/glcpp/tests/043-if-0-else.c @@ -0,0 +1,7 @@ +success_1 +#if 0 +failure +#else +success_2 +#endif +success_3 diff --git a/glcpp/tests/043-if-0-else.c.expected b/glcpp/tests/043-if-0-else.c.expected new file mode 100644 index 0000000000..3d7e6be96c --- /dev/null +++ b/glcpp/tests/043-if-0-else.c.expected @@ -0,0 +1,7 @@ +success_1 + + + +success_2 + +success_3 diff --git a/glcpp/tests/044-if-1-else.c b/glcpp/tests/044-if-1-else.c new file mode 100644 index 0000000000..28dfc25c6f --- /dev/null +++ b/glcpp/tests/044-if-1-else.c @@ -0,0 +1,7 @@ +success_1 +#if 1 +success_2 +#else +failure +#endif +success_3 diff --git a/glcpp/tests/044-if-1-else.c.expected b/glcpp/tests/044-if-1-else.c.expected new file mode 100644 index 0000000000..4a31e1cfa9 --- /dev/null +++ b/glcpp/tests/044-if-1-else.c.expected @@ -0,0 +1,7 @@ +success_1 + +success_2 + + + +success_3 diff --git a/glcpp/tests/045-if-0-elif.c b/glcpp/tests/045-if-0-elif.c new file mode 100644 index 0000000000..e50f686d46 --- /dev/null +++ b/glcpp/tests/045-if-0-elif.c @@ -0,0 +1,11 @@ +success_1 +#if 0 +failure_1 +#elif 0 +failure_2 +#elif 1 +success_3 +#elif 1 +failure_3 +#endif +success_4 diff --git a/glcpp/tests/045-if-0-elif.c.expected b/glcpp/tests/045-if-0-elif.c.expected new file mode 100644 index 0000000000..a9bb1588e4 --- /dev/null +++ b/glcpp/tests/045-if-0-elif.c.expected @@ -0,0 +1,11 @@ +success_1 + + + + + +success_3 + + + +success_4 diff --git a/glcpp/tests/046-if-1-elsif.c b/glcpp/tests/046-if-1-elsif.c new file mode 100644 index 0000000000..130515a01e --- /dev/null +++ b/glcpp/tests/046-if-1-elsif.c @@ -0,0 +1,11 @@ +success_1 +#if 1 +success_2 +#elif 0 +failure_1 +#elif 1 +failure_2 +#elif 0 +failure_3 +#endif +success_3 diff --git a/glcpp/tests/046-if-1-elsif.c.expected b/glcpp/tests/046-if-1-elsif.c.expected new file mode 100644 index 0000000000..a4995713ca --- /dev/null +++ b/glcpp/tests/046-if-1-elsif.c.expected @@ -0,0 +1,11 @@ +success_1 + +success_2 + + + + + + + +success_3 diff --git a/glcpp/tests/047-if-elif-else.c b/glcpp/tests/047-if-elif-else.c new file mode 100644 index 0000000000..e8f0838a9e --- /dev/null +++ b/glcpp/tests/047-if-elif-else.c @@ -0,0 +1,11 @@ +success_1 +#if 0 +failure_1 +#elif 0 +failure_2 +#elif 0 +failure_3 +#else +success_2 +#endif +success_3 diff --git a/glcpp/tests/047-if-elif-else.c.expected b/glcpp/tests/047-if-elif-else.c.expected new file mode 100644 index 0000000000..54d3086119 --- /dev/null +++ b/glcpp/tests/047-if-elif-else.c.expected @@ -0,0 +1,11 @@ +success_1 + + + + + + + +success_2 + +success_3 diff --git a/glcpp/tests/048-if-nested.c b/glcpp/tests/048-if-nested.c new file mode 100644 index 0000000000..fc4679c3be --- /dev/null +++ b/glcpp/tests/048-if-nested.c @@ -0,0 +1,11 @@ +success_1 +#if 0 +failure_1 +#if 1 +failure_2 +#else +failure_3 +#endif +failure_4 +#endif +success_2 diff --git a/glcpp/tests/048-if-nested.c.expected b/glcpp/tests/048-if-nested.c.expected new file mode 100644 index 0000000000..8beb9c32c3 --- /dev/null +++ b/glcpp/tests/048-if-nested.c.expected @@ -0,0 +1,11 @@ +success_1 + + + + + + + + + +success_2 diff --git a/glcpp/tests/049-if-expression-precedence.c b/glcpp/tests/049-if-expression-precedence.c new file mode 100644 index 0000000000..833ea03882 --- /dev/null +++ b/glcpp/tests/049-if-expression-precedence.c @@ -0,0 +1,5 @@ +#if 1 + 2 * 3 + - (25 % 17 - + 1) +failure with operator precedence +#else +success +#endif diff --git a/glcpp/tests/049-if-expression-precedence.c.expected b/glcpp/tests/049-if-expression-precedence.c.expected new file mode 100644 index 0000000000..729bdd15f8 --- /dev/null +++ b/glcpp/tests/049-if-expression-precedence.c.expected @@ -0,0 +1,5 @@ + + + +success + diff --git a/glcpp/tests/050-if-defined.c b/glcpp/tests/050-if-defined.c new file mode 100644 index 0000000000..34f0f95140 --- /dev/null +++ b/glcpp/tests/050-if-defined.c @@ -0,0 +1,17 @@ +#if defined foo +failure_1 +#else +success_1 +#endif +#define foo +#if defined foo +success_2 +#else +failure_2 +#endif +#undef foo +#if defined foo +failure_3 +#else +success_3 +#endif diff --git a/glcpp/tests/050-if-defined.c.expected b/glcpp/tests/050-if-defined.c.expected new file mode 100644 index 0000000000..737eb8d940 --- /dev/null +++ b/glcpp/tests/050-if-defined.c.expected @@ -0,0 +1,17 @@ + + + +success_1 + + + +success_2 + + + + + + + +success_3 + diff --git a/glcpp/tests/051-if-relational.c b/glcpp/tests/051-if-relational.c new file mode 100644 index 0000000000..c3db488e0d --- /dev/null +++ b/glcpp/tests/051-if-relational.c @@ -0,0 +1,35 @@ +#if 3 < 2 +failure_1 +#else +success_1 +#endif + +#if 3 >= 2 +success_2 +#else +failure_2 +#endif + +#if 2 + 3 <= 5 +success_3 +#else +failure_3 +#endif + +#if 3 - 2 == 1 +success_3 +#else +failure_3 +#endif + +#if 1 > 3 +failure_4 +#else +success_4 +#endif + +#if 1 != 5 +success_5 +#else +failure_5 +#endif diff --git a/glcpp/tests/051-if-relational.c.expected b/glcpp/tests/051-if-relational.c.expected new file mode 100644 index 0000000000..652fefdd43 --- /dev/null +++ b/glcpp/tests/051-if-relational.c.expected @@ -0,0 +1,35 @@ + + + +success_1 + + + +success_2 + + + + + +success_3 + + + + + +success_3 + + + + + + + +success_4 + + + +success_5 + + + diff --git a/glcpp/tests/052-if-bitwise.c b/glcpp/tests/052-if-bitwise.c new file mode 100644 index 0000000000..2d8e45eb61 --- /dev/null +++ b/glcpp/tests/052-if-bitwise.c @@ -0,0 +1,20 @@ +#if (0xaaaaaaaa | 0x55555555) != 4294967295 +failure_1 +#else +success_1 +#endif +#if (0x12345678 ^ 0xfdecba98) == 4023971040 +success_2 +#else +failure_2 +#endif +#if (~ 0xdeadbeef) != -3735928560 +failure_3 +#else +success_3 +#endif +#if (0667 & 0733) == 403 +success_4 +#else +failure_4 +#endif diff --git a/glcpp/tests/052-if-bitwise.c.expected b/glcpp/tests/052-if-bitwise.c.expected new file mode 100644 index 0000000000..44e52b206e --- /dev/null +++ b/glcpp/tests/052-if-bitwise.c.expected @@ -0,0 +1,20 @@ + + + +success_1 + + +success_2 + + + + + + +success_3 + + +success_4 + + + diff --git a/glcpp/tests/053-if-divide-and-shift.c b/glcpp/tests/053-if-divide-and-shift.c new file mode 100644 index 0000000000..d24c54a88d --- /dev/null +++ b/glcpp/tests/053-if-divide-and-shift.c @@ -0,0 +1,15 @@ +#if (15 / 2) != 7 +failure_1 +#else +success_1 +#endif +#if (1 << 12) == 4096 +success_2 +#else +failure_2 +#endif +#if (31762 >> 8) != 124 +failure_3 +#else +success_3 +#endif diff --git a/glcpp/tests/053-if-divide-and-shift.c.expected b/glcpp/tests/053-if-divide-and-shift.c.expected new file mode 100644 index 0000000000..7e78e0454e --- /dev/null +++ b/glcpp/tests/053-if-divide-and-shift.c.expected @@ -0,0 +1,15 @@ + + + +success_1 + + +success_2 + + + + + + +success_3 + diff --git a/glcpp/tests/054-if-with-macros.c b/glcpp/tests/054-if-with-macros.c new file mode 100644 index 0000000000..3da79a0d96 --- /dev/null +++ b/glcpp/tests/054-if-with-macros.c @@ -0,0 +1,34 @@ +#define one 1 +#define two 2 +#define three 3 +#define five 5 +#if five < two +failure_1 +#else +success_1 +#endif +#if three >= two +success_2 +#else +failure_2 +#endif +#if two + three <= five +success_3 +#else +failure_3 +#endif +#if five - two == three +success_4 +#else +failure_4 +#endif +#if one > three +failure_5 +#else +success_5 +#endif +#if one != five +success_6 +#else +failure_6 +#endif diff --git a/glcpp/tests/054-if-with-macros.c.expected b/glcpp/tests/054-if-with-macros.c.expected new file mode 100644 index 0000000000..70f737c90a --- /dev/null +++ b/glcpp/tests/054-if-with-macros.c.expected @@ -0,0 +1,34 @@ + + + + + + + +success_1 + + +success_2 + + + + +success_3 + + + + +success_4 + + + + + + +success_5 + + +success_6 + + + diff --git a/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c b/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c new file mode 100644 index 0000000000..00f2c2346d --- /dev/null +++ b/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c @@ -0,0 +1,3 @@ +#define failure() success +#define foo failure +foo() diff --git a/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected b/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected new file mode 100644 index 0000000000..94c15f9505 --- /dev/null +++ b/glcpp/tests/055-define-chain-obj-to-func-parens-in-text.c.expected @@ -0,0 +1,3 @@ + + +success diff --git a/glcpp/tests/056-macro-argument-with-comma.c b/glcpp/tests/056-macro-argument-with-comma.c new file mode 100644 index 0000000000..58701d1f25 --- /dev/null +++ b/glcpp/tests/056-macro-argument-with-comma.c @@ -0,0 +1,4 @@ +#define bar with,embedded,commas +#define function(x) success +#define foo function +foo(bar) diff --git a/glcpp/tests/056-macro-argument-with-comma.c.expected b/glcpp/tests/056-macro-argument-with-comma.c.expected new file mode 100644 index 0000000000..bed826e783 --- /dev/null +++ b/glcpp/tests/056-macro-argument-with-comma.c.expected @@ -0,0 +1,4 @@ + + + +success diff --git a/glcpp/tests/057-empty-arguments.c b/glcpp/tests/057-empty-arguments.c new file mode 100644 index 0000000000..6140232865 --- /dev/null +++ b/glcpp/tests/057-empty-arguments.c @@ -0,0 +1,6 @@ +#define zero() success +zero() +#define one(x) success +one() +#define two(x,y) success +two(,) diff --git a/glcpp/tests/057-empty-arguments.c.expected b/glcpp/tests/057-empty-arguments.c.expected new file mode 100644 index 0000000000..7d97e15e29 --- /dev/null +++ b/glcpp/tests/057-empty-arguments.c.expected @@ -0,0 +1,6 @@ + +success + +success + +success diff --git a/glcpp/tests/058-token-pasting-empty-arguments.c b/glcpp/tests/058-token-pasting-empty-arguments.c new file mode 100644 index 0000000000..8ac260c76b --- /dev/null +++ b/glcpp/tests/058-token-pasting-empty-arguments.c @@ -0,0 +1,5 @@ +#define paste(x,y) x ## y +paste(a,b) +paste(a,) +paste(,b) +paste(,) diff --git a/glcpp/tests/058-token-pasting-empty-arguments.c.expected b/glcpp/tests/058-token-pasting-empty-arguments.c.expected new file mode 100644 index 0000000000..e0967a1b95 --- /dev/null +++ b/glcpp/tests/058-token-pasting-empty-arguments.c.expected @@ -0,0 +1,5 @@ + +ab +a +b + diff --git a/glcpp/tests/059-token-pasting-integer.c b/glcpp/tests/059-token-pasting-integer.c new file mode 100644 index 0000000000..37b895a423 --- /dev/null +++ b/glcpp/tests/059-token-pasting-integer.c @@ -0,0 +1,4 @@ +#define paste(x,y) x ## y +paste(1,2) +paste(1,000) +paste(identifier,2) diff --git a/glcpp/tests/059-token-pasting-integer.c.expected b/glcpp/tests/059-token-pasting-integer.c.expected new file mode 100644 index 0000000000..f1288aa7cb --- /dev/null +++ b/glcpp/tests/059-token-pasting-integer.c.expected @@ -0,0 +1,4 @@ + +12 +1000 +identifier2 diff --git a/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c b/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c new file mode 100644 index 0000000000..ed80ea879c --- /dev/null +++ b/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c @@ -0,0 +1,3 @@ +#define double(a) a*2 +#define foo double( +foo 5) diff --git a/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected b/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected new file mode 100644 index 0000000000..3e5501aa6e --- /dev/null +++ b/glcpp/tests/060-left-paren-in-macro-right-paren-in-text.c.expected @@ -0,0 +1,3 @@ + + +5*2 diff --git a/glcpp/tests/061-define-chain-obj-to-func-multi.c b/glcpp/tests/061-define-chain-obj-to-func-multi.c new file mode 100644 index 0000000000..6dbfd1f62d --- /dev/null +++ b/glcpp/tests/061-define-chain-obj-to-func-multi.c @@ -0,0 +1,5 @@ +#define foo(x) success +#define bar foo +#define baz bar +#define joe baz +joe (failure) diff --git a/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected b/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected new file mode 100644 index 0000000000..15eb64b97f --- /dev/null +++ b/glcpp/tests/061-define-chain-obj-to-func-multi.c.expected @@ -0,0 +1,5 @@ + + + + +success diff --git a/glcpp/tests/062-if-0-skips-garbage.c b/glcpp/tests/062-if-0-skips-garbage.c new file mode 100644 index 0000000000..d9e439bb89 --- /dev/null +++ b/glcpp/tests/062-if-0-skips-garbage.c @@ -0,0 +1,5 @@ +#define foo(a,b) +#if 0 +foo(bar) +foo( +#endif diff --git a/glcpp/tests/062-if-0-skips-garbage.c.expected b/glcpp/tests/062-if-0-skips-garbage.c.expected new file mode 100644 index 0000000000..3f2ff2d6cc --- /dev/null +++ b/glcpp/tests/062-if-0-skips-garbage.c.expected @@ -0,0 +1,5 @@ + + + + + diff --git a/glcpp/tests/063-comments.c b/glcpp/tests/063-comments.c new file mode 100644 index 0000000000..e641d2f0f9 --- /dev/null +++ b/glcpp/tests/063-comments.c @@ -0,0 +1,20 @@ +/* this is a comment */ +// so is this +// */ +f = g/**//h; +/*//*/l(); +m = n//**/o ++ p; +/* this +comment spans +multiple lines and +contains *** stars +and slashes / *** / +and other stuff. +****/ +more code here +/* Test that /* nested +   comments */ +are not treated like comments. +/*/ this is a comment */ +/*/*/ diff --git a/glcpp/tests/063-comments.c.expected b/glcpp/tests/063-comments.c.expected new file mode 100644 index 0000000000..4998d76cc2 --- /dev/null +++ b/glcpp/tests/063-comments.c.expected @@ -0,0 +1,13 @@ +  + + +f = g /h; + l(); +m = n ++ p; +  +more code here +  +are not treated like comments. +  +  diff --git a/glcpp/tests/071-punctuator.c b/glcpp/tests/071-punctuator.c new file mode 100644 index 0000000000..959d682598 --- /dev/null +++ b/glcpp/tests/071-punctuator.c @@ -0,0 +1 @@ +a = b diff --git a/glcpp/tests/071-punctuator.c.expected b/glcpp/tests/071-punctuator.c.expected new file mode 100644 index 0000000000..959d682598 --- /dev/null +++ b/glcpp/tests/071-punctuator.c.expected @@ -0,0 +1 @@ +a = b diff --git a/glcpp/tests/072-token-pasting-same-line.c b/glcpp/tests/072-token-pasting-same-line.c new file mode 100644 index 0000000000..e421e9d5e2 --- /dev/null +++ b/glcpp/tests/072-token-pasting-same-line.c @@ -0,0 +1,2 @@ +#define paste(x) success_ ## x +paste(1) paste(2) paste(3) diff --git a/glcpp/tests/072-token-pasting-same-line.c.expected b/glcpp/tests/072-token-pasting-same-line.c.expected new file mode 100644 index 0000000000..7b80af7e46 --- /dev/null +++ b/glcpp/tests/072-token-pasting-same-line.c.expected @@ -0,0 +1,2 @@ + +success_1 success_2 success_3 diff --git a/glcpp/tests/099-c99-example.c b/glcpp/tests/099-c99-example.c new file mode 100644 index 0000000000..d1976b1f26 --- /dev/null +++ b/glcpp/tests/099-c99-example.c @@ -0,0 +1,17 @@ +#define  x      3 +#define  f(a)   f(x * (a)) +#undef   x +#define  x      2 +#define  g      f +#define  z      z[0] +#define  h      g(~ +#define  m(a)   a(w) +#define  w      0,1 +#define  t(a)   a +#define  p()    int +#define  q(x)   x +#define  r(x,y) x ## y +f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); +g(x +(3,4)-w) | h 5) & m +       (f)^m(m); +p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,)}; diff --git a/glcpp/tests/099-c99-example.c.expected b/glcpp/tests/099-c99-example.c.expected new file mode 100644 index 0000000000..352bbff48f --- /dev/null +++ b/glcpp/tests/099-c99-example.c.expected @@ -0,0 +1,16 @@ + + + + + + + + + + + + + +f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); +f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); +int i[] = { 1, 23, 4, 5, }; diff --git a/glcpp/tests/glcpp-test b/glcpp/tests/glcpp-test new file mode 100755 index 0000000000..396f6e175e --- /dev/null +++ b/glcpp/tests/glcpp-test @@ -0,0 +1,7 @@ +#!/bin/sh + +for test in *.c; do +    echo "Testing $test" +    ../glcpp < $test > $test.out +    diff -u $test.expected $test.out +done diff --git a/glcpp/xtalloc.c b/glcpp/xtalloc.c new file mode 100644 index 0000000000..656ac2d6cb --- /dev/null +++ b/glcpp/xtalloc.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <talloc.h> + +void * +xtalloc_named_const (const void *context, size_t size, const char *name) +{ +	void *ret; + +	ret = talloc_named_const (context, size, name); +	if (ret == NULL) { +		fprintf (stderr, "Out of memory.\n"); +		exit (1); +	} + +	return ret; +} + +char * +xtalloc_strdup (const void *t, const char *p) +{ +	char *ret; + +	ret = talloc_strdup (t, p); +	if (ret == NULL) { +		fprintf (stderr, "Out of memory.\n"); +		exit (1); +	} + +	return ret; +} + +char * +xtalloc_strndup (const void *t, const char *p, size_t n) +{ +	char *ret; + +	ret = talloc_strndup (t, p, n); +	if (ret == NULL) { +		fprintf (stderr, "Out of memory.\n"); +		exit (1); +	} + +	return ret; +} + +char * +xtalloc_asprintf (const void *t, const char *fmt, ...) +{ +	va_list ap; +	char *ret; + +	va_start(ap, fmt); + +	ret = talloc_vasprintf(t, fmt, ap); +	if (ret == NULL) { +		fprintf (stderr, "Out of memory.\n"); +		exit (1); +	} + +	va_end(ap); +	return ret; +} + +void * +_xtalloc_reference_loc (const void *context, +			const void *ptr, const char *location) +{ +	void *ret; + +	ret = _talloc_reference_loc (context, ptr, location); +	if (ret == NULL) { +		fprintf (stderr, "Out of memory.\n"); +		exit (1); +	} + +	return ret; +} | 
