diff --git a/src/Makefile b/src/Makefile index d0b775f..f990695 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,15 +1,15 @@ -FILES = parser.c lexer.c ast.c sym_tab.c main.c +FILES = parser/parser.c lexer/lexer.c core/ast.c core/sym_tab.c core/main.c CFLAGS = -g -Wall -pedantic -x c CC = gcc -cppython: $(FILES) ast.h sym_tab.h - $(CC) $(CFLAGS) $(FILES) -o cppython -lfl +cppython: $(FILES) core/ast.h core/sym_tab.h + $(CC) $(CFLAGS) $(FILES) -I core -I lexer -I parser -o cppython -lfl -lexer.c: cppython.lex - flex cppython.lex +lexer/lexer.c: lexer/cppython.lex + flex lexer/cppython.lex -parser.c: cppython.y - bison -d -v cppython.y +parser/parser.c: parser/cppython.y + bison -d -v parser/cppython.y clean: - rm -f *.o *~ lexer.c lexer.h parser.c parser.h parser.output cppython + rm -f *.o *~ lexer/lexer.c lexer/lexer.h parser/parser.c parser/parser.h parser/parser.output cppython diff --git a/src/ast.c b/src/ast.c deleted file mode 100644 index 6eddd39..0000000 --- a/src/ast.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include "ast.h" - -ast_node* create_bin_expr(char *operator, ast_node* left, ast_node* right) { - printf("\nCreating binary expression node: %d %s %d\n", - left->op.integer_expr, operator, right->op.integer_expr); - ast_node* expr = (ast_node*) malloc(sizeof(ast_node)); - expr->op.binary_expr.operator = operator; - expr->op.binary_expr.left = left; - expr->op.binary_expr.right = right; - return expr; -} - -ast_node* create_int_expr(int value) { - printf("\n\nCreating integer expression node: %d\n", value); - ast_node* expr = (ast_node*) malloc(sizeof(ast_node)); - expr->op.integer_expr = value; - return expr; -} - -void create_ast(ast_node* expression) { - ast* ast_obj = (ast*) malloc(sizeof(ast)); - ast_obj->head = expression; - ast_obj->next = NULL; - printf("\nAST created.\n"); -} - -ast_node* show(ast_node* expression) { - printf("\nAssign expression.\n"); - return expression; -} \ No newline at end of file diff --git a/src/core/ast.c b/src/core/ast.c new file mode 100644 index 0000000..c5f174c --- /dev/null +++ b/src/core/ast.c @@ -0,0 +1,75 @@ +#include +#include +#include "ast.h" + +ast_node* create_bin_expr(char *operator, ast_node* left, ast_node* right) { + if (PARSER_VERBOSE) printf("\nCreating binary expression node: .%d. .%s. .%d.\n", + left->op.integer_expr, operator, right->op.integer_expr); + ast_node* expr = (ast_node*) malloc(sizeof(ast_node)); + expr->tag = BINARY_TYPE; + expr->op.binary_expr.operator = operator; + expr->op.binary_expr.left = left; + expr->op.binary_expr.right = right; + return expr; +} + +ast_node* create_int_expr(int value) { + if (PARSER_VERBOSE) printf("\n\nCreating integer expression node: %d\n", value); + ast_node* expr = (ast_node*) malloc(sizeof(ast_node)); + expr->tag = INTEGER_TYPE; + expr->op.integer_expr = value; + return expr; +} + +void create_ast(ast_node* expression) { + if (PARSER_VERBOSE) printf("\nCreating AST.\n"); + root = expression; + return; +} + +void create_empy_ast() { + if (PARSER_VERBOSE) printf("\nCreating empty AST.\n"); + root = NULL; + return; +} + +ast_node* print_exp(ast_node* node) { + if (PARSER_VERBOSE) { + if (node == NULL) { + printf("Empty expression.\n"); + } else { + printf("TAG: %d\n", node->tag); + } + } + return node; +} + +void print_ast(ast_node* node) { + if (node == NULL) { + printf("Empty AST.\n"); + return; + } + + if (PARSER_VERBOSE) printf("TAG: %d\n", node->tag); + + for (int i=0; i < AST_LVL; ++i) printf(" "); + + // terminal leaf + if (node->tag == INTEGER_TYPE) { + printf("INT: %d\n", node->op.integer_expr); + return; + // terminal leaf + } else if (node->tag == VAR_TYPE) { + printf("VAR: %s\n", node->op.variable_expr); + return; + // non terminal node + } else if (node->tag == BINARY_TYPE) { + printf("OP: %s\n", node->op.binary_expr.operator); + AST_LVL += 1; + print_ast(node->op.binary_expr.right); + print_ast(node->op.binary_expr.left); + } else { + printf("Print AST unknown error.\n"); + return; + } +} \ No newline at end of file diff --git a/src/ast.h b/src/core/ast.h similarity index 65% rename from src/ast.h rename to src/core/ast.h index c56ff7f..9704ea8 100644 --- a/src/ast.h +++ b/src/core/ast.h @@ -1,28 +1,35 @@ #ifndef __AST_H__ #define __AST_H__ +int LEX_VERBOSE, PARSER_VERBOSE, MAIN_VERBOSE, AST_LVL; int line, column; +enum TAG { + INTEGER_TYPE=0, + VAR_TYPE, + BINARY_TYPE +}; + typedef struct exp { + int tag; union { int integer_expr; - char *string_expr; char *variable_expr; struct { char *operator; struct exp* left; struct exp* right; } binary_expr; - } op; + } op; } ast_node; -typedef struct expr_list { - ast_node* head; - struct expr_list* next; -} ast; +ast_node* root; + +void print_ast(ast_node* node); +ast_node* print_exp(ast_node* node); +void create_empy_ast(); void create_ast(ast_node* expression); -ast_node* show(ast_node* expression); ast_node* create_int_expr(int value); ast_node* create_bin_expr(char *operator, ast_node* left, ast_node* right); diff --git a/src/main.c b/src/core/main.c similarity index 60% rename from src/main.c rename to src/core/main.c index f964360..b4a5bc7 100644 --- a/src/main.c +++ b/src/core/main.c @@ -5,18 +5,22 @@ int main (int argc, char *argv[]) { printf("Welcome to CPPython interpreter:\n"); + MAIN_VERBOSE = LEX_VERBOSE = PARSER_VERBOSE = AST_LVL = 0; + root = NULL; // init lexer and parser printf("Lexer/parser:\n"); line = column = 1; yyin = fopen(argv[1], "r"); - printf("\nline %d. ", line); + if (MAIN_VERBOSE) printf("\nline %d. ", line); do { yyparse(); } while (!feof(yyin)); fclose(yyin); - printf("\n"); - printf("Lexer and parser finished.\n\n"); + printf("\nLexer and parser finished.\n\n"); + + printf("Abstract Syntax Tree:\n"); + print_ast(root); return 0; } diff --git a/src/sym_tab.c b/src/core/sym_tab.c similarity index 100% rename from src/sym_tab.c rename to src/core/sym_tab.c diff --git a/src/sym_tab.h b/src/core/sym_tab.h similarity index 100% rename from src/sym_tab.h rename to src/core/sym_tab.h diff --git a/src/uthash.h b/src/core/uthash.h similarity index 100% rename from src/uthash.h rename to src/core/uthash.h diff --git a/src/cppython.lex b/src/lexer/cppython.lex similarity index 81% rename from src/cppython.lex rename to src/lexer/cppython.lex index ee56e15..a523393 100644 --- a/src/cppython.lex +++ b/src/lexer/cppython.lex @@ -6,7 +6,7 @@ #include "ast.h" #include "parser.h" - enum TOKENS{ + enum TOKENS { ERROR_TOK=1, NEWLINE_TOK, WHITESPACE_TOK, @@ -26,7 +26,7 @@ }; %} -%option outfile="lexer.c" header-file="lexer.h" +%option outfile="lexer/lexer.c" header-file="lexer/lexer.h" %option nounput %option noinput @@ -96,33 +96,33 @@ NUMBER ({INTEGER}|{FLOAT}) void handle_token(int token) { switch (token) { case INTEGER_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.value = atoi(yytext); break; case SUB_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case ADD_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case MULT_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case DIV_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case NEWLINE_TOK: line += 1; column = 0; // reset column index - printf("\nline %d. ", line); + if (LEX_VERBOSE) printf("\nline %d. ", line); break; case ERROR_TOK: - printf("\nLexerError: line %d, column %d, token '%s' is not recognized\n", - line, column, yytext); + if (LEX_VERBOSE) printf("\nLexerError: line %d, column %d, token '%s' is not recognized\n", + line, column, yytext); exit(1); default: break; // ignore diff --git a/src/lexer.c b/src/lexer/lexer.c similarity index 97% rename from src/lexer.c rename to src/lexer/lexer.c index 713724f..8f3632e 100644 --- a/src/lexer.c +++ b/src/lexer/lexer.c @@ -1,6 +1,6 @@ -#line 2 "lexer.c" +#line 2 "lexer/lexer.c" -#line 4 "lexer.c" +#line 4 "lexer/lexer.c" #define YY_INT_ALIGNED short int @@ -500,15 +500,15 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "cppython.lex" +#line 1 "lexer/cppython.lex" /* tokens mapping */ -#line 4 "cppython.lex" +#line 4 "lexer/cppython.lex" #include #include "sym_tab.h" #include "ast.h" #include "parser.h" - enum TOKENS{ + enum TOKENS { ERROR_TOK=1, NEWLINE_TOK, WHITESPACE_TOK, @@ -526,11 +526,11 @@ char *yytext; MULT_TOK, DIV_TOK }; -#line 530 "lexer.c" +#line 530 "lexer/lexer.c" #define YY_NO_INPUT 1 -#line 34 "cppython.lex" +#line 34 "lexer/cppython.lex" /* regex and token definition */ -#line 534 "lexer.c" +#line 534 "lexer/lexer.c" #define INITIAL 0 @@ -745,12 +745,12 @@ YY_DECL } { -#line 56 "cppython.lex" +#line 56 "lexer/cppython.lex" /* reserved keywords */ -#line 754 "lexer.c" +#line 754 "lexer/lexer.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -809,96 +809,96 @@ YY_DECL case 1: YY_RULE_SETUP -#line 60 "cppython.lex" +#line 60 "lexer/cppython.lex" ; YY_BREAK /* arithmetic expressions */ case 2: YY_RULE_SETUP -#line 64 "cppython.lex" +#line 64 "lexer/cppython.lex" { handle_token(INTEGER_TOK); return INTEGER; }; YY_BREAK case 3: YY_RULE_SETUP -#line 65 "cppython.lex" +#line 65 "lexer/cppython.lex" ; YY_BREAK case 4: YY_RULE_SETUP -#line 66 "cppython.lex" +#line 66 "lexer/cppython.lex" { handle_token(SUB_TOK); return SUB; }; YY_BREAK case 5: YY_RULE_SETUP -#line 67 "cppython.lex" +#line 67 "lexer/cppython.lex" { handle_token(ADD_TOK); return ADD; }; YY_BREAK case 6: YY_RULE_SETUP -#line 68 "cppython.lex" +#line 68 "lexer/cppython.lex" { handle_token(MULT_TOK); return MULT; }; YY_BREAK case 7: YY_RULE_SETUP -#line 69 "cppython.lex" +#line 69 "lexer/cppython.lex" { handle_token(DIV_TOK); return DIV; }; YY_BREAK case 8: YY_RULE_SETUP -#line 70 "cppython.lex" +#line 70 "lexer/cppython.lex" ; YY_BREAK /* conditional and booleans expressions */ case 9: YY_RULE_SETUP -#line 74 "cppython.lex" +#line 74 "lexer/cppython.lex" ; YY_BREAK case 10: YY_RULE_SETUP -#line 75 "cppython.lex" +#line 75 "lexer/cppython.lex" ; YY_BREAK /* structure helpers */ case 11: /* rule 11 can match eol */ YY_RULE_SETUP -#line 79 "cppython.lex" +#line 79 "lexer/cppython.lex" ; YY_BREAK case 12: YY_RULE_SETUP -#line 80 "cppython.lex" +#line 80 "lexer/cppython.lex" ; YY_BREAK /* general */ case 13: /* rule 13 can match eol */ YY_RULE_SETUP -#line 84 "cppython.lex" +#line 84 "lexer/cppython.lex" { handle_token(NEWLINE_TOK); }; YY_BREAK case 14: YY_RULE_SETUP -#line 85 "cppython.lex" +#line 85 "lexer/cppython.lex" ; YY_BREAK case 15: YY_RULE_SETUP -#line 86 "cppython.lex" +#line 86 "lexer/cppython.lex" ; YY_BREAK case 16: YY_RULE_SETUP -#line 87 "cppython.lex" +#line 87 "lexer/cppython.lex" { handle_token(ERROR_TOK); }; /* any character but newline */ YY_BREAK case 17: YY_RULE_SETUP -#line 89 "cppython.lex" +#line 89 "lexer/cppython.lex" ECHO; YY_BREAK -#line 902 "lexer.c" +#line 902 "lexer/lexer.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1866,7 +1866,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 89 "cppython.lex" +#line 89 "lexer/cppython.lex" /* @@ -1878,33 +1878,33 @@ void yyfree (void * ptr ) void handle_token(int token) { switch (token) { case INTEGER_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.value = atoi(yytext); break; case SUB_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case ADD_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case MULT_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case DIV_TOK: - printf("Token: ", yytext); + if (LEX_VERBOSE) printf("Token: ", yytext); yylval.op = yytext; break; case NEWLINE_TOK: line += 1; column = 0; // reset column index - printf("\nline %d. ", line); + if (LEX_VERBOSE) printf("\nline %d. ", line); break; case ERROR_TOK: - printf("\nLexerError: line %d, column %d, token '%s' is not recognized\n", - line, column, yytext); + if (LEX_VERBOSE) printf("\nLexerError: line %d, column %d, token '%s' is not recognized\n", + line, column, yytext); exit(1); default: break; // ignore diff --git a/src/lexer.h b/src/lexer/lexer.h similarity index 98% rename from src/lexer.h rename to src/lexer/lexer.h index c2d5b6b..c8d2c33 100644 --- a/src/lexer.h +++ b/src/lexer/lexer.h @@ -2,9 +2,9 @@ #define yyHEADER_H 1 #define yyIN_HEADER 1 -#line 6 "lexer.h" +#line 6 "lexer/lexer.h" -#line 8 "lexer.h" +#line 8 "lexer/lexer.h" #define YY_INT_ALIGNED short int @@ -466,9 +466,9 @@ extern int yylex (void); #undef yyTABLES_NAME #endif -#line 89 "cppython.lex" +#line 89 "lexer/cppython.lex" -#line 473 "lexer.h" +#line 473 "lexer/lexer.h" #undef yyIN_HEADER #endif /* yyHEADER_H */ diff --git a/src/cppython.y b/src/parser/cppython.y similarity index 64% rename from src/cppython.y rename to src/parser/cppython.y index 38c8e9e..e78150a 100644 --- a/src/cppython.y +++ b/src/parser/cppython.y @@ -6,8 +6,8 @@ void yyerror(char *s); %} -%output "parser.c" -%defines "parser.h" +%output "parser/parser.c" +%defines "parser/parser.h" %define lr.type ielr %start input @@ -28,18 +28,18 @@ %% -input : /* empty */ +input : /* empty */ { create_empy_ast(); } | expr { create_ast($1); } ; -expr : term[L] ADD[C] term[R] { $$ = create_bin_expr($C, $L, $R); } - | term[L] SUB[C] term[R] { $$ = create_bin_expr($C, $L, $R); } - | term[U] { $$ = show($U); } +expr : term[L] ADD[C] term[R] { $$ = create_bin_expr("+", $L, $R); } + | term[L] SUB[C] term[R] { $$ = create_bin_expr("-", $L, $R); } + | term[U] { $$ = print_exp($U); } ; term : factor[L] MULT[C] factor[R] { $$ = create_bin_expr($C, $L, $R); } | factor[L] DIV[C] factor[R] { $$ = create_bin_expr($C, $L, $R); } - | factor[U] { $$ = show($U); } + | factor[U] { $$ = print_exp($U); } ; factor : INTEGER[U] { $$ = create_int_expr($U); } diff --git a/src/parser.c b/src/parser/parser.c similarity index 97% rename from src/parser.c rename to src/parser/parser.c index 7ff1d51..5e77df5 100644 --- a/src/parser.c +++ b/src/parser/parser.c @@ -66,7 +66,7 @@ /* First part of user prologue. */ -#line 1 "cppython.y" +#line 1 "parser/cppython.y" #include #include "ast.h" @@ -74,7 +74,7 @@ int yylex(); void yyerror(char *s); -#line 78 "parser.c" +#line 78 "parser/parser.c" # ifndef YY_CAST # ifdef __cplusplus @@ -107,8 +107,8 @@ /* Use api.header.include to #include this header instead of duplicating it here. */ -#ifndef YY_YY_PARSER_H_INCLUDED -# define YY_YY_PARSER_H_INCLUDED +#ifndef YY_YY_PARSER_PARSER_H_INCLUDED +# define YY_YY_PARSER_PARSER_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -134,13 +134,13 @@ extern int yydebug; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 15 "cppython.y" +#line 15 "parser/cppython.y" int value; char* op; ast_node* expression; -#line 144 "parser.c" +#line 144 "parser/parser.c" }; typedef union YYSTYPE YYSTYPE; @@ -153,7 +153,7 @@ extern YYSTYPE yylval; int yyparse (void); -#endif /* !YY_YY_PARSER_H_INCLUDED */ +#endif /* !YY_YY_PARSER_PARSER_H_INCLUDED */ @@ -1308,56 +1308,62 @@ yyparse (void) YY_REDUCE_PRINT (yyn); switch (yyn) { + case 2: +#line 31 "parser/cppython.y" + { create_empy_ast(); } +#line 1315 "parser/parser.c" + break; + case 3: -#line 32 "cppython.y" +#line 32 "parser/cppython.y" { create_ast((yyvsp[0].expression)); } -#line 1315 "parser.c" +#line 1321 "parser/parser.c" break; case 4: -#line 35 "cppython.y" - { (yyval.expression) = create_bin_expr((yyvsp[-1].op), (yyvsp[-2].expression), (yyvsp[0].expression)); } -#line 1321 "parser.c" +#line 35 "parser/cppython.y" + { (yyval.expression) = create_bin_expr("+", (yyvsp[-2].expression), (yyvsp[0].expression)); } +#line 1327 "parser/parser.c" break; case 5: -#line 36 "cppython.y" - { (yyval.expression) = create_bin_expr((yyvsp[-1].op), (yyvsp[-2].expression), (yyvsp[0].expression)); } -#line 1327 "parser.c" +#line 36 "parser/cppython.y" + { (yyval.expression) = create_bin_expr("-", (yyvsp[-2].expression), (yyvsp[0].expression)); } +#line 1333 "parser/parser.c" break; case 6: -#line 37 "cppython.y" - { (yyval.expression) = show((yyvsp[0].expression)); } -#line 1333 "parser.c" +#line 37 "parser/cppython.y" + { (yyval.expression) = print_exp((yyvsp[0].expression)); } +#line 1339 "parser/parser.c" break; case 7: -#line 40 "cppython.y" +#line 40 "parser/cppython.y" { (yyval.expression) = create_bin_expr((yyvsp[-1].op), (yyvsp[-2].expression), (yyvsp[0].expression)); } -#line 1339 "parser.c" +#line 1345 "parser/parser.c" break; case 8: -#line 41 "cppython.y" +#line 41 "parser/cppython.y" { (yyval.expression) = create_bin_expr((yyvsp[-1].op), (yyvsp[-2].expression), (yyvsp[0].expression)); } -#line 1345 "parser.c" +#line 1351 "parser/parser.c" break; case 9: -#line 42 "cppython.y" - { (yyval.expression) = show((yyvsp[0].expression)); } -#line 1351 "parser.c" +#line 42 "parser/cppython.y" + { (yyval.expression) = print_exp((yyvsp[0].expression)); } +#line 1357 "parser/parser.c" break; case 10: -#line 45 "cppython.y" +#line 45 "parser/cppython.y" { (yyval.expression) = create_int_expr((yyvsp[0].value)); } -#line 1357 "parser.c" +#line 1363 "parser/parser.c" break; -#line 1361 "parser.c" +#line 1367 "parser/parser.c" default: break; } @@ -1589,7 +1595,7 @@ yyparse (void) #endif return yyresult; } -#line 48 "cppython.y" +#line 48 "parser/cppython.y" void yyerror(char *s) { diff --git a/src/parser.h b/src/parser/parser.h similarity index 92% rename from src/parser.h rename to src/parser/parser.h index 776de16..7486c3d 100644 --- a/src/parser.h +++ b/src/parser/parser.h @@ -34,8 +34,8 @@ /* Undocumented macros, especially those whose name start with YY_, are private implementation details. Do not rely on them. */ -#ifndef YY_YY_PARSER_H_INCLUDED -# define YY_YY_PARSER_H_INCLUDED +#ifndef YY_YY_PARSER_PARSER_H_INCLUDED +# define YY_YY_PARSER_PARSER_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 @@ -61,13 +61,13 @@ extern int yydebug; #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { -#line 15 "cppython.y" +#line 15 "parser/cppython.y" int value; char* op; ast_node* expression; -#line 71 "parser.h" +#line 71 "parser/parser.h" }; typedef union YYSTYPE YYSTYPE; @@ -80,4 +80,4 @@ extern YYSTYPE yylval; int yyparse (void); -#endif /* !YY_YY_PARSER_H_INCLUDED */ +#endif /* !YY_YY_PARSER_PARSER_H_INCLUDED */ diff --git a/src/parser.output b/src/parser/parser.output similarity index 100% rename from src/parser.output rename to src/parser/parser.output diff --git a/tests/utarray.h b/tests/utarray.h deleted file mode 100644 index 6b62018..0000000 --- a/tests/utarray.h +++ /dev/null @@ -1,247 +0,0 @@ -/* -Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a dynamic array implementation using macros - */ -#ifndef UTARRAY_H -#define UTARRAY_H - -#define UTARRAY_VERSION 2.1.0 - -#include /* size_t */ -#include /* memset, etc */ -#include /* exit */ - -#ifdef __GNUC__ -#define UTARRAY_UNUSED __attribute__((__unused__)) -#else -#define UTARRAY_UNUSED -#endif - -#ifdef oom -#error "The name of macro 'oom' has been changed to 'utarray_oom'. Please update your code." -#define utarray_oom() oom() -#endif - -#ifndef utarray_oom -#define utarray_oom() exit(-1) -#endif - -typedef void (ctor_f)(void *dst, const void *src); -typedef void (dtor_f)(void *elt); -typedef void (init_f)(void *elt); -typedef struct { - size_t sz; - init_f *init; - ctor_f *copy; - dtor_f *dtor; -} UT_icd; - -typedef struct { - unsigned i,n;/* i: index of next available slot, n: num slots */ - UT_icd icd; /* initializer, copy and destructor functions */ - char *d; /* n slots of size icd->sz*/ -} UT_array; - -#define utarray_init(a,_icd) do { \ - memset(a,0,sizeof(UT_array)); \ - (a)->icd = *(_icd); \ -} while(0) - -#define utarray_done(a) do { \ - if ((a)->n) { \ - if ((a)->icd.dtor) { \ - unsigned _ut_i; \ - for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ - } \ - } \ - free((a)->d); \ - } \ - (a)->n=0; \ -} while(0) - -#define utarray_new(a,_icd) do { \ - (a) = (UT_array*)malloc(sizeof(UT_array)); \ - if ((a) == NULL) { \ - utarray_oom(); \ - } \ - utarray_init(a,_icd); \ -} while(0) - -#define utarray_free(a) do { \ - utarray_done(a); \ - free(a); \ -} while(0) - -#define utarray_reserve(a,by) do { \ - if (((a)->i+(by)) > (a)->n) { \ - char *utarray_tmp; \ - while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ - utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ - if (utarray_tmp == NULL) { \ - utarray_oom(); \ - } \ - (a)->d=utarray_tmp; \ - } \ -} while(0) - -#define utarray_push_back(a,p) do { \ - utarray_reserve(a,1); \ - if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ - else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ -} while(0) - -#define utarray_pop_back(a) do { \ - if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ - else { (a)->i--; } \ -} while(0) - -#define utarray_extend_back(a) do { \ - utarray_reserve(a,1); \ - if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ - else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ - (a)->i++; \ -} while(0) - -#define utarray_len(a) ((a)->i) - -#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) -#define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) - -#define utarray_insert(a,p,j) do { \ - if ((j) > (a)->i) utarray_resize(a,j); \ - utarray_reserve(a,1); \ - if ((j) < (a)->i) { \ - memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ - ((a)->i - (j))*((a)->icd.sz)); \ - } \ - if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ - else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ - (a)->i++; \ -} while(0) - -#define utarray_inserta(a,w,j) do { \ - if (utarray_len(w) == 0) break; \ - if ((j) > (a)->i) utarray_resize(a,j); \ - utarray_reserve(a,utarray_len(w)); \ - if ((j) < (a)->i) { \ - memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ - _utarray_eltptr(a,j), \ - ((a)->i - (j))*((a)->icd.sz)); \ - } \ - if ((a)->icd.copy) { \ - unsigned _ut_i; \ - for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ - (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ - } \ - } else { \ - memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ - utarray_len(w)*((a)->icd.sz)); \ - } \ - (a)->i += utarray_len(w); \ -} while(0) - -#define utarray_resize(dst,num) do { \ - unsigned _ut_i; \ - if ((dst)->i > (unsigned)(num)) { \ - if ((dst)->icd.dtor) { \ - for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \ - (dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \ - } \ - } \ - } else if ((dst)->i < (unsigned)(num)) { \ - utarray_reserve(dst, (num) - (dst)->i); \ - if ((dst)->icd.init) { \ - for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \ - (dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \ - } \ - } else { \ - memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \ - } \ - } \ - (dst)->i = (num); \ -} while(0) - -#define utarray_concat(dst,src) do { \ - utarray_inserta(dst, src, utarray_len(dst)); \ -} while(0) - -#define utarray_erase(a,pos,len) do { \ - if ((a)->icd.dtor) { \ - unsigned _ut_i; \ - for (_ut_i = 0; _ut_i < (len); _ut_i++) { \ - (a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \ - } \ - } \ - if ((a)->i > ((pos) + (len))) { \ - memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \ - ((a)->i - ((pos) + (len))) * (a)->icd.sz); \ - } \ - (a)->i -= (len); \ -} while(0) - -#define utarray_renew(a,u) do { \ - if (a) utarray_clear(a); \ - else utarray_new(a, u); \ -} while(0) - -#define utarray_clear(a) do { \ - if ((a)->i > 0) { \ - if ((a)->icd.dtor) { \ - unsigned _ut_i; \ - for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ - (a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \ - } \ - } \ - (a)->i = 0; \ - } \ -} while(0) - -#define utarray_sort(a,cmp) do { \ - qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ -} while(0) - -#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) - -#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) -#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : (((a)->i != utarray_eltidx(a,e)+1) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) -#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) != 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) -#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) -#define utarray_eltidx(a,e) (((char*)(e) - (a)->d) / (a)->icd.sz) - -/* last we pre-define a few icd for common utarrays of ints and strings */ -static void utarray_str_cpy(void *dst, const void *src) { - char **_src = (char**)src, **_dst = (char**)dst; - *_dst = (*_src == NULL) ? NULL : strdup(*_src); -} -static void utarray_str_dtor(void *elt) { - char **eltc = (char**)elt; - if (*eltc != NULL) free(*eltc); -} -static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; -static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL}; -static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL}; - - -#endif /* UTARRAY_H */ diff --git a/tests/utlist.h b/tests/utlist.h deleted file mode 100644 index 5bb1ac9..0000000 --- a/tests/utlist.h +++ /dev/null @@ -1,1073 +0,0 @@ -/* -Copyright (c) 2007-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTLIST_H -#define UTLIST_H - -#define UTLIST_VERSION 2.1.0 - -#include - -/* - * This file contains macros to manipulate singly and doubly-linked lists. - * - * 1. LL_ macros: singly-linked lists. - * 2. DL_ macros: doubly-linked lists. - * 3. CDL_ macros: circular doubly-linked lists. - * - * To use singly-linked lists, your structure must have a "next" pointer. - * To use doubly-linked lists, your structure must "prev" and "next" pointers. - * Either way, the pointer to the head of the list must be initialized to NULL. - * - * ----------------.EXAMPLE ------------------------- - * struct item { - * int id; - * struct item *prev, *next; - * } - * - * struct item *list = NULL: - * - * int main() { - * struct item *item; - * ... allocate and populate item ... - * DL_APPEND(list, item); - * } - * -------------------------------------------------- - * - * For doubly-linked lists, the append and delete macros are O(1) - * For singly-linked lists, append and delete are O(n) but prepend is O(1) - * The sort macro is O(n log(n)) for all types of single/double/circular lists. - */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) -#if defined(_MSC_VER) /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define LDECLTYPE(x) decltype(x) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#endif -#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) -#define NO_DECLTYPE -#else /* GNU, Sun and other compilers */ -#define LDECLTYPE(x) __typeof(x) -#endif -#endif - -/* for VS2008 we use some workarounds to get around the lack of decltype, - * namely, we always reassign our tmp variable to the list head if we need - * to dereference its prev/next pointers, and save/restore the real head.*/ -#ifdef NO_DECLTYPE -#define IF_NO_DECLTYPE(x) x -#define LDECLTYPE(x) char* -#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } -#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) -#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } -/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ -#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } -#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } -#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } -#else -#define IF_NO_DECLTYPE(x) -#define UTLIST_SV(elt,list) -#define UTLIST_NEXT(elt,list,next) ((elt)->next) -#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) -/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ -#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) -#define UTLIST_RS(list) -#define UTLIST_CASTASGN(a,b) (a)=(b) -#endif - -/****************************************************************************** - * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * - * Unwieldy variable names used here to avoid shadowing passed-in variables. * - *****************************************************************************/ -#define LL_SORT(list, cmp) \ - LL_SORT2(list, cmp, next) - -#define LL_SORT2(list, cmp, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ - } \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - - -#define DL_SORT(list, cmp) \ - DL_SORT2(list, cmp, prev, next) - -#define DL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } else if ((_ls_qsize == 0) || (!_ls_q)) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - UTLIST_CASTASGN((list)->prev, _ls_tail); \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - -#define CDL_SORT(list, cmp) \ - CDL_SORT2(list, cmp, prev, next) - -#define CDL_SORT2(list, cmp, prev, next) \ -do { \ - LDECLTYPE(list) _ls_p; \ - LDECLTYPE(list) _ls_q; \ - LDECLTYPE(list) _ls_e; \ - LDECLTYPE(list) _ls_tail; \ - LDECLTYPE(list) _ls_oldhead; \ - LDECLTYPE(list) _tmp; \ - int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ - if (list) { \ - _ls_insize = 1; \ - _ls_looping = 1; \ - while (_ls_looping) { \ - UTLIST_CASTASGN(_ls_p,list); \ - UTLIST_CASTASGN(_ls_oldhead,list); \ - (list) = NULL; \ - _ls_tail = NULL; \ - _ls_nmerges = 0; \ - while (_ls_p) { \ - _ls_nmerges++; \ - _ls_q = _ls_p; \ - _ls_psize = 0; \ - for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ - _ls_psize++; \ - UTLIST_SV(_ls_q,list); \ - if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ - _ls_q = NULL; \ - } else { \ - _ls_q = UTLIST_NEXT(_ls_q,list,next); \ - } \ - UTLIST_RS(list); \ - if (!_ls_q) break; \ - } \ - _ls_qsize = _ls_insize; \ - while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ - if (_ls_psize == 0) { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } else if (_ls_qsize == 0 || !_ls_q) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else if (cmp(_ls_p,_ls_q) <= 0) { \ - _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ - UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ - if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ - } else { \ - _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ - UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ - if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ - } \ - if (_ls_tail) { \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ - } else { \ - UTLIST_CASTASGN(list,_ls_e); \ - } \ - UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ - _ls_tail = _ls_e; \ - } \ - _ls_p = _ls_q; \ - } \ - UTLIST_CASTASGN((list)->prev,_ls_tail); \ - UTLIST_CASTASGN(_tmp,list); \ - UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ - if (_ls_nmerges <= 1) { \ - _ls_looping=0; \ - } \ - _ls_insize *= 2; \ - } \ - } \ -} while (0) - -/****************************************************************************** - * singly linked list macros (non-circular) * - *****************************************************************************/ -#define LL_PREPEND(head,add) \ - LL_PREPEND2(head,add,next) - -#define LL_PREPEND2(head,add,next) \ -do { \ - (add)->next = (head); \ - (head) = (add); \ -} while (0) - -#define LL_CONCAT(head1,head2) \ - LL_CONCAT2(head1,head2,next) - -#define LL_CONCAT2(head1,head2,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head1) { \ - _tmp = (head1); \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(head2); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) - -#define LL_APPEND(head,add) \ - LL_APPEND2(head,add,next) - -#define LL_APPEND2(head,add,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - (add)->next=NULL; \ - if (head) { \ - _tmp = (head); \ - while (_tmp->next) { _tmp = _tmp->next; } \ - _tmp->next=(add); \ - } else { \ - (head)=(add); \ - } \ -} while (0) - -#define LL_INSERT_INORDER(head,add,cmp) \ - LL_INSERT_INORDER2(head,add,cmp,next) - -#define LL_INSERT_INORDER2(head,add,cmp,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - LL_APPEND_ELEM2(head, _tmp, add, next); \ - } else { \ - (head) = (add); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define LL_LOWER_BOUND(head,elt,like,cmp) \ - LL_LOWER_BOUND2(head,elt,like,cmp,next) - -#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ - do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ - if (cmp((elt)->next, like) >= 0) { \ - break; \ - } \ - } \ - } \ - } while (0) - -#define LL_DELETE(head,del) \ - LL_DELETE2(head,del,next) - -#define LL_DELETE2(head,del,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (del))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (del)->next; \ - } \ - } \ -} while (0) - -#define LL_COUNT(head,el,counter) \ - LL_COUNT2(head,el,counter,next) \ - -#define LL_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - LL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) - -#define LL_FOREACH(head,el) \ - LL_FOREACH2(head,el,next) - -#define LL_FOREACH2(head,el,next) \ - for ((el) = (head); el; (el) = (el)->next) - -#define LL_FOREACH_SAFE(head,el,tmp) \ - LL_FOREACH_SAFE2(head,el,tmp,next) - -#define LL_FOREACH_SAFE2(head,el,tmp,next) \ - for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) - -#define LL_SEARCH_SCALAR(head,out,field,val) \ - LL_SEARCH_SCALAR2(head,out,field,val,next) - -#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while (0) - -#define LL_SEARCH(head,out,elt,cmp) \ - LL_SEARCH2(head,out,elt,cmp,next) - -#define LL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - LL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while (0) - -#define LL_REPLACE_ELEM2(head, el, add, next) \ -do { \ - LDECLTYPE(head) _tmp; \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ -} while (0) - -#define LL_REPLACE_ELEM(head, el, add) \ - LL_REPLACE_ELEM2(head, el, add, next) - -#define LL_PREPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - LDECLTYPE(head) _tmp; \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - _tmp = (head); \ - while (_tmp->next && (_tmp->next != (el))) { \ - _tmp = _tmp->next; \ - } \ - if (_tmp->next) { \ - _tmp->next = (add); \ - } \ - } \ - } else { \ - LL_APPEND2(head, add, next); \ - } \ -} while (0) \ - -#define LL_PREPEND_ELEM(head, el, add) \ - LL_PREPEND_ELEM2(head, el, add, next) - -#define LL_APPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - (el)->next = (add); \ - } else { \ - LL_PREPEND2(head, add, next); \ - } \ -} while (0) \ - -#define LL_APPEND_ELEM(head, el, add) \ - LL_APPEND_ELEM2(head, el, add, next) - -#ifdef NO_DECLTYPE -/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ - -#undef LL_CONCAT2 -#define LL_CONCAT2(head1,head2,next) \ -do { \ - char *_tmp; \ - if (head1) { \ - _tmp = (char*)(head1); \ - while ((head1)->next) { (head1) = (head1)->next; } \ - (head1)->next = (head2); \ - UTLIST_RS(head1); \ - } else { \ - (head1)=(head2); \ - } \ -} while (0) - -#undef LL_APPEND2 -#define LL_APPEND2(head,add,next) \ -do { \ - if (head) { \ - (add)->next = head; /* use add->next as a temp variable */ \ - while ((add)->next->next) { (add)->next = (add)->next->next; } \ - (add)->next->next=(add); \ - } else { \ - (head)=(add); \ - } \ - (add)->next=NULL; \ -} while (0) - -#undef LL_INSERT_INORDER2 -#define LL_INSERT_INORDER2(head,add,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, add)) >= 0) { \ - (add)->next = (head); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->next = (head)->next; \ - (head)->next = (add); \ - UTLIST_RS(head); \ - } \ -} while (0) - -#undef LL_DELETE2 -#define LL_DELETE2(head,del,next) \ -do { \ - if ((head) == (del)) { \ - (head)=(head)->next; \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && ((head)->next != (del))) { \ - (head) = (head)->next; \ - } \ - if ((head)->next) { \ - (head)->next = ((del)->next); \ - } \ - UTLIST_RS(head); \ - } \ -} while (0) - -#undef LL_REPLACE_ELEM2 -#define LL_REPLACE_ELEM2(head, el, add, next) \ -do { \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->next = head; \ - while ((add)->next->next && ((add)->next->next != (el))) { \ - (add)->next = (add)->next->next; \ - } \ - if ((add)->next->next) { \ - (add)->next->next = (add); \ - } \ - } \ - (add)->next = (el)->next; \ -} while (0) - -#undef LL_PREPEND_ELEM2 -#define LL_PREPEND_ELEM2(head, el, add, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->next = (head); \ - while ((add)->next->next && ((add)->next->next != (el))) { \ - (add)->next = (add)->next->next; \ - } \ - if ((add)->next->next) { \ - (add)->next->next = (add); \ - } \ - } \ - (add)->next = (el); \ - } else { \ - LL_APPEND2(head, add, next); \ - } \ -} while (0) \ - -#endif /* NO_DECLTYPE */ - -/****************************************************************************** - * doubly linked list macros (non-circular) * - *****************************************************************************/ -#define DL_PREPEND(head,add) \ - DL_PREPEND2(head,add,prev,next) - -#define DL_PREPEND2(head,add,prev,next) \ -do { \ - (add)->next = (head); \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev = (add); \ - } else { \ - (add)->prev = (add); \ - } \ - (head) = (add); \ -} while (0) - -#define DL_APPEND(head,add) \ - DL_APPEND2(head,add,prev,next) - -#define DL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (head)->prev->next = (add); \ - (head)->prev = (add); \ - (add)->next = NULL; \ - } else { \ - (head)=(add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define DL_INSERT_INORDER(head,add,cmp) \ - DL_INSERT_INORDER2(head,add,cmp,prev,next) - -#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ - } else { \ - (head) = (add); \ - (head)->prev = (head); \ - (head)->next = NULL; \ - } \ -} while (0) - -#define DL_LOWER_BOUND(head,elt,like,cmp) \ - DL_LOWER_BOUND2(head,elt,like,cmp,next) - -#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ - if ((cmp((elt)->next, like)) >= 0) { \ - break; \ - } \ - } \ - } \ -} while (0) - -#define DL_CONCAT(head1,head2) \ - DL_CONCAT2(head1,head2,prev,next) - -#define DL_CONCAT2(head1,head2,prev,next) \ -do { \ - LDECLTYPE(head1) _tmp; \ - if (head2) { \ - if (head1) { \ - UTLIST_CASTASGN(_tmp, (head2)->prev); \ - (head2)->prev = (head1)->prev; \ - (head1)->prev->next = (head2); \ - UTLIST_CASTASGN((head1)->prev, _tmp); \ - } else { \ - (head1)=(head2); \ - } \ - } \ -} while (0) - -#define DL_DELETE(head,del) \ - DL_DELETE2(head,del,prev,next) - -#define DL_DELETE2(head,del,prev,next) \ -do { \ - assert((head) != NULL); \ - assert((del)->prev != NULL); \ - if ((del)->prev == (del)) { \ - (head)=NULL; \ - } else if ((del)==(head)) { \ - (del)->next->prev = (del)->prev; \ - (head) = (del)->next; \ - } else { \ - (del)->prev->next = (del)->next; \ - if ((del)->next) { \ - (del)->next->prev = (del)->prev; \ - } else { \ - (head)->prev = (del)->prev; \ - } \ - } \ -} while (0) - -#define DL_COUNT(head,el,counter) \ - DL_COUNT2(head,el,counter,next) \ - -#define DL_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - DL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) - -#define DL_FOREACH(head,el) \ - DL_FOREACH2(head,el,next) - -#define DL_FOREACH2(head,el,next) \ - for ((el) = (head); el; (el) = (el)->next) - -/* this version is safe for deleting the elements during iteration */ -#define DL_FOREACH_SAFE(head,el,tmp) \ - DL_FOREACH_SAFE2(head,el,tmp,next) - -#define DL_FOREACH_SAFE2(head,el,tmp,next) \ - for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) - -/* these are identical to their singly-linked list counterparts */ -#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR -#define DL_SEARCH LL_SEARCH -#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 -#define DL_SEARCH2 LL_SEARCH2 - -#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ -do { \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - if ((head) == (el)) { \ - (head) = (add); \ - (add)->next = (el)->next; \ - if ((el)->next == NULL) { \ - (add)->prev = (add); \ - } else { \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - } \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->prev->next = (add); \ - if ((el)->next == NULL) { \ - (head)->prev = (add); \ - } else { \ - (add)->next->prev = (add); \ - } \ - } \ -} while (0) - -#define DL_REPLACE_ELEM(head, el, add) \ - DL_REPLACE_ELEM2(head, el, add, prev, next) - -#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } else { \ - (add)->prev->next = (add); \ - } \ - } else { \ - DL_APPEND2(head, add, prev, next); \ - } \ -} while (0) \ - -#define DL_PREPEND_ELEM(head, el, add) \ - DL_PREPEND_ELEM2(head, el, add, prev, next) - -#define DL_APPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - (add)->prev = (el); \ - (el)->next = (add); \ - if ((add)->next) { \ - (add)->next->prev = (add); \ - } else { \ - (head)->prev = (add); \ - } \ - } else { \ - DL_PREPEND2(head, add, prev, next); \ - } \ -} while (0) \ - -#define DL_APPEND_ELEM(head, el, add) \ - DL_APPEND_ELEM2(head, el, add, prev, next) - -#ifdef NO_DECLTYPE -/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ - -#undef DL_INSERT_INORDER2 -#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - if ((head) == NULL) { \ - (add)->prev = (add); \ - (add)->next = NULL; \ - (head) = (add); \ - } else if ((cmp(head, add)) >= 0) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((head)->next && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->prev = (head); \ - (add)->next = (head)->next; \ - (head)->next = (add); \ - UTLIST_RS(head); \ - if ((add)->next) { \ - (add)->next->prev = (add); \ - } else { \ - (head)->prev = (add); \ - } \ - } \ -} while (0) -#endif /* NO_DECLTYPE */ - -/****************************************************************************** - * circular doubly linked list macros * - *****************************************************************************/ -#define CDL_APPEND(head,add) \ - CDL_APPEND2(head,add,prev,next) - -#define CDL_APPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - (head) = (add); \ - } \ -} while (0) - -#define CDL_PREPEND(head,add) \ - CDL_PREPEND2(head,add,prev,next) - -#define CDL_PREPEND2(head,add,prev,next) \ -do { \ - if (head) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (head)->prev = (add); \ - (add)->prev->next = (add); \ - } else { \ - (add)->prev = (add); \ - (add)->next = (add); \ - } \ - (head) = (add); \ -} while (0) - -#define CDL_INSERT_INORDER(head,add,cmp) \ - CDL_INSERT_INORDER2(head,add,cmp,prev,next) - -#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - LDECLTYPE(head) _tmp; \ - if (head) { \ - CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ - CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ - } else { \ - (head) = (add); \ - (head)->next = (head); \ - (head)->prev = (head); \ - } \ -} while (0) - -#define CDL_LOWER_BOUND(head,elt,like,cmp) \ - CDL_LOWER_BOUND2(head,elt,like,cmp,next) - -#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ -do { \ - if ((head) == NULL || (cmp(head, like)) >= 0) { \ - (elt) = NULL; \ - } else { \ - for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ - if ((cmp((elt)->next, like)) >= 0) { \ - break; \ - } \ - } \ - } \ -} while (0) - -#define CDL_DELETE(head,del) \ - CDL_DELETE2(head,del,prev,next) - -#define CDL_DELETE2(head,del,prev,next) \ -do { \ - if (((head)==(del)) && ((head)->next == (head))) { \ - (head) = NULL; \ - } else { \ - (del)->next->prev = (del)->prev; \ - (del)->prev->next = (del)->next; \ - if ((del) == (head)) (head)=(del)->next; \ - } \ -} while (0) - -#define CDL_COUNT(head,el,counter) \ - CDL_COUNT2(head,el,counter,next) \ - -#define CDL_COUNT2(head, el, counter,next) \ -do { \ - (counter) = 0; \ - CDL_FOREACH2(head,el,next) { ++(counter); } \ -} while (0) - -#define CDL_FOREACH(head,el) \ - CDL_FOREACH2(head,el,next) - -#define CDL_FOREACH2(head,el,next) \ - for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) - -#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ - CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) - -#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ - for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ - (el) && ((tmp2) = (el)->next, 1); \ - (el) = ((el) == (tmp1) ? NULL : (tmp2))) - -#define CDL_SEARCH_SCALAR(head,out,field,val) \ - CDL_SEARCH_SCALAR2(head,out,field,val,next) - -#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((out)->field == (val)) break; \ - } \ -} while (0) - -#define CDL_SEARCH(head,out,elt,cmp) \ - CDL_SEARCH2(head,out,elt,cmp,next) - -#define CDL_SEARCH2(head,out,elt,cmp,next) \ -do { \ - CDL_FOREACH2(head,out,next) { \ - if ((cmp(out,elt))==0) break; \ - } \ -} while (0) - -#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ -do { \ - assert((head) != NULL); \ - assert((el) != NULL); \ - assert((add) != NULL); \ - if ((el)->next == (el)) { \ - (add)->next = (add); \ - (add)->prev = (add); \ - (head) = (add); \ - } else { \ - (add)->next = (el)->next; \ - (add)->prev = (el)->prev; \ - (add)->next->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } \ -} while (0) - -#define CDL_REPLACE_ELEM(head, el, add) \ - CDL_REPLACE_ELEM2(head, el, add, prev, next) - -#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el); \ - (add)->prev = (el)->prev; \ - (el)->prev = (add); \ - (add)->prev->next = (add); \ - if ((head) == (el)) { \ - (head) = (add); \ - } \ - } else { \ - CDL_APPEND2(head, add, prev, next); \ - } \ -} while (0) - -#define CDL_PREPEND_ELEM(head, el, add) \ - CDL_PREPEND_ELEM2(head, el, add, prev, next) - -#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ -do { \ - if (el) { \ - assert((head) != NULL); \ - assert((add) != NULL); \ - (add)->next = (el)->next; \ - (add)->prev = (el); \ - (el)->next = (add); \ - (add)->next->prev = (add); \ - } else { \ - CDL_PREPEND2(head, add, prev, next); \ - } \ -} while (0) - -#define CDL_APPEND_ELEM(head, el, add) \ - CDL_APPEND_ELEM2(head, el, add, prev, next) - -#ifdef NO_DECLTYPE -/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ - -#undef CDL_INSERT_INORDER2 -#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ -do { \ - if ((head) == NULL) { \ - (add)->prev = (add); \ - (add)->next = (add); \ - (head) = (add); \ - } else if ((cmp(head, add)) >= 0) { \ - (add)->prev = (head)->prev; \ - (add)->next = (head); \ - (add)->prev->next = (add); \ - (head)->prev = (add); \ - (head) = (add); \ - } else { \ - char *_tmp = (char*)(head); \ - while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ - (head) = (head)->next; \ - } \ - (add)->prev = (head); \ - (add)->next = (head)->next; \ - (add)->next->prev = (add); \ - (head)->next = (add); \ - UTLIST_RS(head); \ - } \ -} while (0) -#endif /* NO_DECLTYPE */ - -#endif /* UTLIST_H */ diff --git a/tests/utringbuffer.h b/tests/utringbuffer.h deleted file mode 100644 index ce2890e..0000000 --- a/tests/utringbuffer.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright (c) 2015-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a ring-buffer implementation using macros - */ -#ifndef UTRINGBUFFER_H -#define UTRINGBUFFER_H - -#define UTRINGBUFFER_VERSION 2.1.0 - -#include -#include -#include "utarray.h" // for "UT_icd" - -typedef struct { - unsigned i; /* index of next available slot; wraps at n */ - unsigned n; /* capacity */ - unsigned char f; /* full */ - UT_icd icd; /* initializer, copy and destructor functions */ - char *d; /* n slots of size icd->sz */ -} UT_ringbuffer; - -#define utringbuffer_init(a, _n, _icd) do { \ - memset(a, 0, sizeof(UT_ringbuffer)); \ - (a)->icd = *(_icd); \ - (a)->n = (_n); \ - if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \ -} while(0) - -#define utringbuffer_clear(a) do { \ - if ((a)->icd.dtor) { \ - if ((a)->f) { \ - unsigned _ut_i; \ - for (_ut_i = 0; _ut_i < (a)->n; ++_ut_i) { \ - (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ - } \ - } else { \ - unsigned _ut_i; \ - for (_ut_i = 0; _ut_i < (a)->i; ++_ut_i) { \ - (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ - } \ - } \ - } \ - (a)->i = 0; \ - (a)->f = 0; \ -} while(0) - -#define utringbuffer_done(a) do { \ - utringbuffer_clear(a); \ - free((a)->d); (a)->d = NULL; \ - (a)->n = 0; \ -} while(0) - -#define utringbuffer_new(a,n,_icd) do { \ - a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \ - utringbuffer_init(a, n, _icd); \ -} while(0) - -#define utringbuffer_free(a) do { \ - utringbuffer_done(a); \ - free(a); \ -} while(0) - -#define utringbuffer_push_back(a,p) do { \ - if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \ - if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \ - else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \ - if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \ -} while(0) - -#define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i) -#define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f) -#define utringbuffer_full(a) ((a)->f != 0) - -#define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j)) -#define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) -#define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL) - -#define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j)) -#define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) -#define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e)) - -#define utringbuffer_front(a) utringbuffer_eltptr(a,0) -#define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1)) -#define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1)) -#define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1)) - -#endif /* UTRINGBUFFER_H */ diff --git a/tests/utstack.h b/tests/utstack.h deleted file mode 100644 index 3b0c1a0..0000000 --- a/tests/utstack.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright (c) 2018-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTSTACK_H -#define UTSTACK_H - -#define UTSTACK_VERSION 2.1.0 - -/* - * This file contains macros to manipulate a singly-linked list as a stack. - * - * To use utstack, your structure must have a "next" pointer. - * - * ----------------.EXAMPLE ------------------------- - * struct item { - * int id; - * struct item *next; - * } - * - * struct item *stack = NULL: - * - * int main() { - * int count; - * struct item *tmp; - * struct item *item = malloc(sizeof *item); - * item->id = 42; - * STACK_COUNT(stack, tmp, count); assert(count == 0); - * STACK_PUSH(stack, item); - * STACK_COUNT(stack, tmp, count); assert(count == 1); - * STACK_POP(stack, item); - * free(item); - * STACK_COUNT(stack, tmp, count); assert(count == 0); - * } - * -------------------------------------------------- - */ - -#define STACK_TOP(head) (head) - -#define STACK_EMPTY(head) (!(head)) - -#define STACK_PUSH(head,add) \ - STACK_PUSH2(head,add,next) - -#define STACK_PUSH2(head,add,next) \ -do { \ - (add)->next = (head); \ - (head) = (add); \ -} while (0) - -#define STACK_POP(head,result) \ - STACK_POP2(head,result,next) - -#define STACK_POP2(head,result,next) \ -do { \ - (result) = (head); \ - (head) = (head)->next; \ -} while (0) - -#define STACK_COUNT(head,el,counter) \ - STACK_COUNT2(head,el,counter,next) \ - -#define STACK_COUNT2(head,el,counter,next) \ -do { \ - (counter) = 0; \ - for ((el) = (head); el; (el) = (el)->next) { ++(counter); } \ -} while (0) - -#endif /* UTSTACK_H */ diff --git a/tests/utstring.h b/tests/utstring.h deleted file mode 100644 index 4cf5ffd..0000000 --- a/tests/utstring.h +++ /dev/null @@ -1,407 +0,0 @@ -/* -Copyright (c) 2008-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* a dynamic string implementation using macros - */ -#ifndef UTSTRING_H -#define UTSTRING_H - -#define UTSTRING_VERSION 2.1.0 - -#include -#include -#include -#include - -#ifdef __GNUC__ -#define UTSTRING_UNUSED __attribute__((__unused__)) -#else -#define UTSTRING_UNUSED -#endif - -#ifdef oom -#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." -#define utstring_oom() oom() -#endif - -#ifndef utstring_oom -#define utstring_oom() exit(-1) -#endif - -typedef struct { - char *d; /* pointer to allocated buffer */ - size_t n; /* allocated capacity */ - size_t i; /* index of first unused byte */ -} UT_string; - -#define utstring_reserve(s,amt) \ -do { \ - if (((s)->n - (s)->i) < (size_t)(amt)) { \ - char *utstring_tmp = (char*)realloc( \ - (s)->d, (s)->n + (amt)); \ - if (!utstring_tmp) { \ - utstring_oom(); \ - } \ - (s)->d = utstring_tmp; \ - (s)->n += (amt); \ - } \ -} while(0) - -#define utstring_init(s) \ -do { \ - (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ - utstring_reserve(s,100); \ - (s)->d[0] = '\0'; \ -} while(0) - -#define utstring_done(s) \ -do { \ - if ((s)->d != NULL) free((s)->d); \ - (s)->n = 0; \ -} while(0) - -#define utstring_free(s) \ -do { \ - utstring_done(s); \ - free(s); \ -} while(0) - -#define utstring_new(s) \ -do { \ - (s) = (UT_string*)malloc(sizeof(UT_string)); \ - if (!(s)) { \ - utstring_oom(); \ - } \ - utstring_init(s); \ -} while(0) - -#define utstring_renew(s) \ -do { \ - if (s) { \ - utstring_clear(s); \ - } else { \ - utstring_new(s); \ - } \ -} while(0) - -#define utstring_clear(s) \ -do { \ - (s)->i = 0; \ - (s)->d[0] = '\0'; \ -} while(0) - -#define utstring_bincpy(s,b,l) \ -do { \ - utstring_reserve((s),(l)+1); \ - if (l) memcpy(&(s)->d[(s)->i], b, l); \ - (s)->i += (l); \ - (s)->d[(s)->i]='\0'; \ -} while(0) - -#define utstring_concat(dst,src) \ -do { \ - utstring_reserve((dst),((src)->i)+1); \ - if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ - (dst)->i += (src)->i; \ - (dst)->d[(dst)->i]='\0'; \ -} while(0) - -#define utstring_len(s) ((s)->i) - -#define utstring_body(s) ((s)->d) - -UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { - int n; - va_list cp; - for (;;) { -#ifdef _WIN32 - cp = ap; -#else - va_copy(cp, ap); -#endif - n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp); - va_end(cp); - - if ((n > -1) && ((size_t) n < (s->n-s->i))) { - s->i += n; - return; - } - - /* Else try again with more space. */ - if (n > -1) utstring_reserve(s,n+1); /* exact */ - else utstring_reserve(s,(s->n)*2); /* 2x */ - } -} -#ifdef __GNUC__ -/* support printf format checking (2=the format string, 3=start of varargs) */ -static void utstring_printf(UT_string *s, const char *fmt, ...) - __attribute__ (( format( printf, 2, 3) )); -#endif -UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) { - va_list ap; - va_start(ap,fmt); - utstring_printf_va(s,fmt,ap); - va_end(ap); -} - -/******************************************************************************* - * begin substring search functions * - ******************************************************************************/ -/* Build KMP table from left to right. */ -UTSTRING_UNUSED static void _utstring_BuildTable( - const char *P_Needle, - size_t P_NeedleLen, - long *P_KMP_Table) -{ - long i, j; - - i = 0; - j = i - 1; - P_KMP_Table[i] = j; - while (i < (long) P_NeedleLen) - { - while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) - { - j = P_KMP_Table[j]; - } - i++; - j++; - if (i < (long) P_NeedleLen) - { - if (P_Needle[i] == P_Needle[j]) - { - P_KMP_Table[i] = P_KMP_Table[j]; - } - else - { - P_KMP_Table[i] = j; - } - } - else - { - P_KMP_Table[i] = j; - } - } - - return; -} - - -/* Build KMP table from right to left. */ -UTSTRING_UNUSED static void _utstring_BuildTableR( - const char *P_Needle, - size_t P_NeedleLen, - long *P_KMP_Table) -{ - long i, j; - - i = P_NeedleLen - 1; - j = i + 1; - P_KMP_Table[i + 1] = j; - while (i >= 0) - { - while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) - { - j = P_KMP_Table[j + 1]; - } - i--; - j--; - if (i >= 0) - { - if (P_Needle[i] == P_Needle[j]) - { - P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; - } - else - { - P_KMP_Table[i + 1] = j; - } - } - else - { - P_KMP_Table[i + 1] = j; - } - } - - return; -} - - -/* Search data from left to right. ( Multiple search mode. ) */ -UTSTRING_UNUSED static long _utstring_find( - const char *P_Haystack, - size_t P_HaystackLen, - const char *P_Needle, - size_t P_NeedleLen, - long *P_KMP_Table) -{ - long i, j; - long V_FindPosition = -1; - - /* Search from left to right. */ - i = j = 0; - while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) - { - while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) - { - i = P_KMP_Table[i]; - } - i++; - j++; - if (i >= (int)P_NeedleLen) - { - /* Found. */ - V_FindPosition = j - i; - break; - } - } - - return V_FindPosition; -} - - -/* Search data from right to left. ( Multiple search mode. ) */ -UTSTRING_UNUSED static long _utstring_findR( - const char *P_Haystack, - size_t P_HaystackLen, - const char *P_Needle, - size_t P_NeedleLen, - long *P_KMP_Table) -{ - long i, j; - long V_FindPosition = -1; - - /* Search from right to left. */ - j = (P_HaystackLen - 1); - i = (P_NeedleLen - 1); - while ( (j >= 0) && (j >= i) ) - { - while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) - { - i = P_KMP_Table[i + 1]; - } - i--; - j--; - if (i < 0) - { - /* Found. */ - V_FindPosition = j + 1; - break; - } - } - - return V_FindPosition; -} - - -/* Search data from left to right. ( One time search mode. ) */ -UTSTRING_UNUSED static long utstring_find( - UT_string *s, - long P_StartPosition, /* Start from 0. -1 means last position. */ - const char *P_Needle, - size_t P_NeedleLen) -{ - long V_StartPosition; - long V_HaystackLen; - long *V_KMP_Table; - long V_FindPosition = -1; - - if (P_StartPosition < 0) - { - V_StartPosition = s->i + P_StartPosition; - } - else - { - V_StartPosition = P_StartPosition; - } - V_HaystackLen = s->i - V_StartPosition; - if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) - { - V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); - if (V_KMP_Table != NULL) - { - _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); - - V_FindPosition = _utstring_find(s->d + V_StartPosition, - V_HaystackLen, - P_Needle, - P_NeedleLen, - V_KMP_Table); - if (V_FindPosition >= 0) - { - V_FindPosition += V_StartPosition; - } - - free(V_KMP_Table); - } - } - - return V_FindPosition; -} - - -/* Search data from right to left. ( One time search mode. ) */ -UTSTRING_UNUSED static long utstring_findR( - UT_string *s, - long P_StartPosition, /* Start from 0. -1 means last position. */ - const char *P_Needle, - size_t P_NeedleLen) -{ - long V_StartPosition; - long V_HaystackLen; - long *V_KMP_Table; - long V_FindPosition = -1; - - if (P_StartPosition < 0) - { - V_StartPosition = s->i + P_StartPosition; - } - else - { - V_StartPosition = P_StartPosition; - } - V_HaystackLen = V_StartPosition + 1; - if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) - { - V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); - if (V_KMP_Table != NULL) - { - _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); - - V_FindPosition = _utstring_findR(s->d, - V_HaystackLen, - P_Needle, - P_NeedleLen, - V_KMP_Table); - - free(V_KMP_Table); - } - } - - return V_FindPosition; -} -/******************************************************************************* - * end substring search functions * - ******************************************************************************/ - -#endif /* UTSTRING_H */