codegen/codegen.cpp

changeset 845
fec7023e91a7
child 848
68410477c8bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/codegen/codegen.cpp	Wed Jul 16 18:57:48 2014 +0300
@@ -0,0 +1,176 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013, 2014 Teemu Piippo
+ *
+ *  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
+ *  (at your option) 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 <sstream>
+#include <fstream>
+#include <string>
+#include <cstring>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+
+using std::string;
+using std::vector;
+using std::ifstream;
+using std::size_t;
+using std::strncmp;
+using std::getline;
+using std::cout;
+using std::endl;
+
+struct entry_type
+{
+	string name;
+	string type;
+	string defvalue;
+
+	inline bool operator< (entry_type const& other) const
+	{
+		return name < other.name;
+	}
+
+	inline bool operator== (entry_type const& other) const
+	{
+		return name == other.name and type == other.type;
+	}
+
+	inline bool operator!= (entry_type const& other) const
+	{
+		return not operator== (other);
+	}
+};
+
+char advance_pointer (char const*& ptr)
+{
+	char a = *ptr++;
+	if (*ptr == '\0')
+		throw false;
+
+	return a;
+}
+
+void read_cfgentries (string const& filename, vector<entry_type>& entries, const char* macroname)
+{
+	ifstream is (filename.c_str());
+	string line;
+	size_t const macrolen = strlen (macroname);
+
+	while (getline (is, line))
+	{
+		try
+		{
+			if (strncmp (line.c_str(), macroname, macrolen) != 0)
+				continue;
+
+			char const* ptr = &line[macrolen];
+			entry_type entry;
+
+			// Skip to paren
+			while (*ptr != '(')
+				advance_pointer (ptr);
+
+			// Skip whitespace
+			while (isspace (*ptr))
+				advance_pointer (ptr);
+
+			// Skip paren
+			advance_pointer (ptr);
+
+			// Read type
+			while (*ptr != ',')
+				entry.type += advance_pointer (ptr);
+
+			// Skip comma and whitespace
+			for (advance_pointer (ptr); isspace (*ptr); advance_pointer (ptr))
+				;
+
+			// Read name
+			while (*ptr != ',')
+				entry.name += advance_pointer (ptr);
+
+			// Skip comma and whitespace
+			for (advance_pointer (ptr); isspace (*ptr); advance_pointer (ptr))
+				;
+
+			// Read default
+			while (*ptr != ')')
+				entry.defvalue += advance_pointer (ptr);
+
+			entries.push_back (entry);
+		}
+		catch (bool) {}
+	}
+}
+
+bool check_equality (vector<entry_type> a, vector<entry_type> b)
+{
+	if (a.size() != b.size())
+		return false;
+
+	std::sort (a.begin(), a.end());
+	std::sort (b.begin(), b.end());
+
+	for (size_t i = 0; i < a.size(); ++i)
+	{
+		if (a[i] != b[i])
+			return false;
+	}
+
+	return true;
+}
+
+int main (int argc, char* argv[])
+{
+	vector<entry_type> entries;
+	vector<entry_type> oldentries;
+	read_cfgentries (argv[argc - 1], oldentries, "CODEGEN_CACHE");
+
+	for (int arg = 1; arg < argc - 1; ++arg)
+		read_cfgentries (argv[arg], entries, "CFGENTRY");
+
+	if (check_equality (entries, oldentries))
+	{
+		cout << "Configuration options unchanged" << endl;
+	}
+	else
+	{
+		std::ofstream os (argv[argc - 1]);
+		os << "#pragma once" << endl;
+		os << "#define CODEGEN_CACHE(A,B,C)" << endl;
+
+		for (vector<entry_type>::const_iterator it = entries.begin(); it != entries.end(); ++it)
+			os << "CODEGEN_CACHE (" << it->type << ", " << it->name << ", " << it->defvalue << ")" << endl;
+
+		os << endl;
+		for (vector<entry_type>::const_iterator it = entries.begin(); it != entries.end(); ++it)
+			os << "EXTERN_CFGENTRY (" << it->type << ", " << it->name << ")" << endl;
+
+		os << endl;
+		os << "static void initConfigurationEntry (ConfigEntry* entry);" << endl;
+		os << "static void setupConfigurationLists()" << endl;
+		os << "{" << endl;
+
+		for (vector<entry_type>::const_iterator it = entries.begin(); it != entries.end(); ++it)
+			os << "\tinitConfigurationEntry (new " << it->type << "ConfigEntry (&cfg::" << it->name << ", \"" << it->name << "\", " << it->defvalue << "));" << endl;
+		os << "}" << endl;
+
+		cout << "Wrote configuration options list to " << argv[argc - 1] << "." << endl;
+	}
+
+	return 0;
+}

mercurial