diff options
-rw-r--r-- | src/Makefile.files | 6 | ||||
-rw-r--r-- | src/analysis/analysis.cpp | 52 | ||||
-rw-r--r-- | src/analysis/analysis.h | 34 | ||||
-rw-r--r-- | src/analysis/function.cpp | 129 | ||||
-rw-r--r-- | src/analysis/function.h | 40 | ||||
-rw-r--r-- | src/logger.cpp | 13 | ||||
-rw-r--r-- | src/logger.h | 3 | ||||
-rw-r--r-- | src/nodes/base/node.h | 6 | ||||
-rw-r--r-- | src/parsers/generic.cpp | 7 | ||||
-rw-r--r-- | src/parsers/list/tree_list.cpp | 2 | ||||
-rw-r--r-- | src/plugin.cpp | 8 |
11 files changed, 291 insertions, 9 deletions
diff --git a/src/Makefile.files b/src/Makefile.files index 3fcc67a..b338808 100644 --- a/src/Makefile.files +++ b/src/Makefile.files @@ -1,4 +1,8 @@ -SRC = nodes/base/cst.h \ +SRC = analysis/analysis.cpp \ + analysis/analysis.h \ + analysis/function.cpp \ + analysis/function.h \ + nodes/base/cst.h \ nodes/base/decl.h \ nodes/base/expr.h \ nodes/base/node.h \ diff --git a/src/analysis/analysis.cpp b/src/analysis/analysis.cpp new file mode 100644 index 0000000..fa1672c --- /dev/null +++ b/src/analysis/analysis.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Andrei Karas + * + * This file is part of AstDumper. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "analysis/analysis.h" + +#include "command.h" + +#include "analysis/function.h" + +#include "nodes/decl/function_decl.h" + +#include "localconsts.h" + +namespace Analysis +{ + +void walkTree(Node *node) +{ + analyseNode(node); + + FOR_EACH (std::vector<Node*>::iterator, it, node->childs) + { + walkTree(*it); + } +} + +void analyseNode(Node *node) +{ + // searching function declaration + if (node->nodeType == FUNCTION_DECL) + { + analyseFunction(static_cast<FunctionDeclNode*>(node)); + } +} + +} diff --git a/src/analysis/analysis.h b/src/analysis/analysis.h new file mode 100644 index 0000000..64ecffd --- /dev/null +++ b/src/analysis/analysis.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 Andrei Karas + * + * This file is part of AstDumper. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ANALYSIS_ANALYSIS_H +#define ANALYSIS_ANALYSIS_H + +#include "includes.h" + +struct Node; + +namespace Analysis +{ + void walkTree(Node *node); + + void analyseNode(Node *node); +} + +#endif // ANALYSIS_ANALYSIS_H diff --git a/src/analysis/function.cpp b/src/analysis/function.cpp new file mode 100644 index 0000000..21d81ef --- /dev/null +++ b/src/analysis/function.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2015 Andrei Karas + * + * This file is part of AstDumper. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "analysis/function.h" + +#include "command.h" +#include "logger.h" + +#include "nodes/decl/function_decl.h" + +#include "nodes/list/tree_list.h" + +#include <set> + +#include "localconsts.h" + +namespace Analysis +{ + +// walking TREE_LIST and getting all types +void getTypesFromTreeList(TreeListNode *list, + std::vector<TypeNode*> &arr) +{ + while (list) + { + arr.push_back(static_cast<TypeNode*>(list->value)); + list = static_cast<TreeListNode*>(list->chain); + } +} + +// put arg types into arr +void getFunctionArgTypes(FunctionDeclNode *node, + std::vector<TypeNode*> &arr) +{ + // function not have type + if (!node->functionType) + return; + getTypesFromTreeList(node->functionType->argTypes, arr); +} + +TreeListNode *findTreeListPurposeValue(TreeListNode *list, + const std::string &name) +{ + while (list) + { + if (list->purpose->label == name) + { + return static_cast<TreeListNode*>(list->value); + } + list = static_cast<TreeListNode*>(list->chain); + } + return nullptr; +} + +void getFunctionParamsNonNullAttributes(FunctionDeclNode *node, + std::set<int> &arr) +{ + // function not have type + if (!node->functionType) + return; + TreeListNode *list = findTreeListPurposeValue( + static_cast<TreeListNode*>(node->functionType->attribute), + "nonnull"); + // no attribute nonnull + if (!list) + return; + while (list) + { + if (list->value) + { + arr.insert(atoi(list->value->label.c_str())); + } + list = static_cast<TreeListNode*>(list->chain); + } +} + +void analyseFunction(FunctionDeclNode *node) +{ + // ignore external functions + if (node->isExternal) + return; + + std::vector<TypeNode*> types; + std::set<int> nonNull; + + getFunctionArgTypes(node, types); + getFunctionParamsNonNullAttributes(node, nonNull); + if (command == Command::FindArgs) + { + Log::log("%s: ", node->label.c_str()); + const int sz = node->args.size(); + for (int f = 0; f < sz; f ++) + { + const TypeNode *const type = types[f]; + const ParmDeclNode *const name = node->args[f]; + if (nonNull.find(f + 1) != nonNull.end()) + { + Log::log("%s %s nonnull, ", + type->nodeTypeName.c_str(), + name->label.c_str()); + } + else + { + Log::log("%s %s, ", + type->nodeTypeName.c_str(), + name->label.c_str()); + } + } + Log::log("\n"); + } +} + +} diff --git a/src/analysis/function.h b/src/analysis/function.h new file mode 100644 index 0000000..04e3e01 --- /dev/null +++ b/src/analysis/function.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015 Andrei Karas + * + * This file is part of AstDumper. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ANALYSIS_FUNCTION_H +#define ANALYSIS_FUNCTION_H + +#include "includes.h" + +struct FunctionDeclNode; +struct TreeListNode; +struct TypeNode; + +namespace Analysis +{ + void analyseFunction(FunctionDeclNode *node); + + void getFunctionArgTypes(FunctionDeclNode *node, + std::vector<TypeNode*> &arr); + + void getTypesFromTreeList(TreeListNode *list, + std::vector<TypeNode*> &arr); +} + +#endif // ANALYSIS_FUNCTION_H diff --git a/src/logger.cpp b/src/logger.cpp index 13df3ed..34fb90c 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -78,6 +78,15 @@ void error(const char *const text, va_end(ap); } +void log(const char *const text, + ...) +{ + va_list ap; + va_start(ap, text); + vfprintf(stderr, text, ap); + va_end(ap); +} + void dumpInt(const Node *const node, const char *const text, const int val) @@ -124,7 +133,7 @@ void dump(const Node *const node) fprintf(stderr, "%d %s %s\n", node->indent, - node->nodeType.c_str(), + node->nodeTypeName.c_str(), node->file.c_str()); return; } @@ -138,7 +147,7 @@ void dump(const Node *const node) return; } fprintf(stderr, "%s", node->getIndent().c_str()); - fprintf(stderr, "%s", node->nodeType.c_str()); + fprintf(stderr, "%s", node->nodeTypeName.c_str()); if (!node->label.empty()) fprintf(stderr, " %s", node->label.c_str()); if (!node->file.empty()) diff --git a/src/logger.h b/src/logger.h index 76ebddf..771d1f8 100644 --- a/src/logger.h +++ b/src/logger.h @@ -37,6 +37,9 @@ namespace Log void error(const char *const text, ...); + void log(const char *const text, + ...); + void dumpInt(const Node *const node, const char *const text, const int val); diff --git a/src/nodes/base/node.h b/src/nodes/base/node.h index d6b42ad..d29cb5a 100644 --- a/src/nodes/base/node.h +++ b/src/nodes/base/node.h @@ -30,12 +30,13 @@ struct Node { Node() : parent(nullptr), - nodeType(), + nodeTypeName(), label(), file(), tag(), childs(), gccNode(nullptr), + nodeType(ERROR_MARK), line(-1), column(-1), treeNumber(0), @@ -59,12 +60,13 @@ struct Node } Node *parent; - std::string nodeType; + std::string nodeTypeName; std::string label; std::string file; std::string tag; std::vector<Node*> childs; tree gccNode; + tree_code nodeType; int line; int column; int treeNumber; diff --git a/src/parsers/generic.cpp b/src/parsers/generic.cpp index a7195a4..a749fad 100644 --- a/src/parsers/generic.cpp +++ b/src/parsers/generic.cpp @@ -102,14 +102,14 @@ Node *createParseNode(Node *parent, Log::dump(node, "Wrong node type. Want %s but get %s", get_tree_code_name(wantType), - node->nodeType.c_str()); + node->nodeTypeName.c_str()); } else { Log::dump(node, "Wrong node type. Want %s but get %s - %s", get_tree_code_name(wantType), - node->nodeType.c_str(), + node->nodeTypeName.c_str(), tag.c_str()); } if (!parent) @@ -163,7 +163,8 @@ void fillType(Node *node) } node->treeNumber = static_cast<int>(TREE_CODE(node->gccNode)); - node->nodeType = get_tree_code_name(TREE_CODE(node->gccNode)); + node->nodeType = TREE_CODE(node->gccNode); + node->nodeTypeName = get_tree_code_name(TREE_CODE(node->gccNode)); // Log::dump(node); } diff --git a/src/parsers/list/tree_list.cpp b/src/parsers/list/tree_list.cpp index 2b48899..bcc16ef 100644 --- a/src/parsers/list/tree_list.cpp +++ b/src/parsers/list/tree_list.cpp @@ -52,7 +52,7 @@ void parseTreeListNode(TreeListNode *node) node->chain = createParseNode( node, TREE_CHAIN(node->gccNode), - node->tag); + "chain"); /* look like infinite loop FOR_CHAIN(node->gccNode, it, TREE_CHAIN, TREE_CHAIN) diff --git a/src/plugin.cpp b/src/plugin.cpp index 7499a54..ffd86f9 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -25,6 +25,8 @@ #include "command.h" +#include "analysis/analysis.h" + #include "parsers/generic.h" #include "localconsts.h" @@ -39,6 +41,8 @@ static void pre_generic(void *gcc_data, void *user_data A_UNUSED) { Node *node = Generic::parseNodes((tree)gcc_data); + if (command == Command::FindArgs) + Analysis::walkTree(node); Generic::cleanAllNodes(node); } @@ -73,6 +77,10 @@ int plugin_init (struct plugin_name_args *plugin_info, { command = Command::DumpUnsupported; } + else if (cmd == "findargs") + { + command = Command::FindArgs; + } else { error("Plugin %s. Unknown command: %s", |