codegen/codegen.cpp

changeset 933
f4c80d92e71e
parent 932
738673e8a6b4
child 934
be8128aff739
equal deleted inserted replaced
932:738673e8a6b4 933:f4c80d92e71e
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013, 2014 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sstream>
20 #include <fstream>
21 #include <string>
22 #include <cstring>
23 #include <iostream>
24 #include <vector>
25 #include <algorithm>
26
27 using std::string;
28 using std::vector;
29 using std::ifstream;
30 using std::size_t;
31 using std::strncmp;
32 using std::getline;
33 using std::cout;
34 using std::endl;
35
36 struct EntryType
37 {
38 string name;
39 string type;
40 string defvalue;
41
42 inline bool operator< (EntryType const& other) const
43 {
44 return name < other.name;
45 }
46
47 inline bool operator== (EntryType const& other) const
48 {
49 return name == other.name and type == other.type;
50 }
51
52 inline bool operator!= (EntryType const& other) const
53 {
54 return not operator== (other);
55 }
56 };
57
58 char AdvancePointer (char const*& ptr)
59 {
60 char a = *ptr++;
61
62 if (*ptr == '\0')
63 throw false;
64
65 return a;
66 }
67
68 void ReadConfigEntries (string const& filename, vector<EntryType>& entries, const char* macroname)
69 {
70 ifstream is (filename.c_str());
71 string line;
72 size_t const macrolen = strlen (macroname);
73
74 while (getline (is, line))
75 {
76 try
77 {
78 if (strncmp (line.c_str(), macroname, macrolen) != 0)
79 continue;
80
81 char const* ptr = &line[macrolen];
82 EntryType entry;
83
84 // Skip to paren
85 while (*ptr != '(')
86 AdvancePointer (ptr);
87
88 // Skip whitespace
89 while (isspace (*ptr))
90 AdvancePointer (ptr);
91
92 // Skip paren
93 AdvancePointer (ptr);
94
95 // Read type
96 while (*ptr != ',')
97 entry.type += AdvancePointer (ptr);
98
99 // Skip comma and whitespace
100 for (AdvancePointer (ptr); isspace (*ptr); AdvancePointer (ptr))
101 ;
102
103 // Read name
104 while (*ptr != ',')
105 entry.name += AdvancePointer (ptr);
106
107 // Skip comma and whitespace
108 for (AdvancePointer (ptr); isspace (*ptr); AdvancePointer (ptr))
109 ;
110
111 // Read default
112 while (*ptr != ')')
113 entry.defvalue += AdvancePointer (ptr);
114
115 entries.push_back (entry);
116 }
117 catch (bool) {}
118 }
119 }
120
121 bool CheckEquality (vector<EntryType> a, vector<EntryType> b)
122 {
123 if (a.size() != b.size())
124 return false;
125
126 std::sort (a.begin(), a.end());
127 std::sort (b.begin(), b.end());
128
129 for (size_t i = 0; i < a.size(); ++i)
130 {
131 if (a[i] != b[i])
132 return false;
133 }
134
135 return true;
136 }
137
138 int main (int argc, char* argv[])
139 {
140 vector<EntryType> entries;
141 vector<EntryType> oldentries;
142 ReadConfigEntries (argv[argc - 1], oldentries, "CODEGEN_CACHE");
143
144 for (int arg = 1; arg < argc - 1; ++arg)
145 ReadConfigEntries (argv[arg], entries, "CFGENTRY");
146
147 if (CheckEquality (entries, oldentries))
148 {
149 cout << "Configuration options unchanged" << endl;
150 return 0;
151 }
152
153 std::ofstream os (argv[argc - 1]);
154 os << "#pragma once" << endl;
155 os << "#define CODEGEN_CACHE(A,B,C)" << endl;
156
157 for (vector<EntryType>::const_iterator it = entries.begin(); it != entries.end(); ++it)
158 {
159 os << "CODEGEN_CACHE (" << it->type << ", " << it->name << ", " <<
160 it->defvalue << ")" << endl;
161 }
162
163 os << endl;
164 for (vector<EntryType>::const_iterator it = entries.begin(); it != entries.end(); ++it)
165 os << "EXTERN_CFGENTRY (" << it->type << ", " << it->name << ")" << endl;
166
167 os << endl;
168 os << "static void InitConfigurationEntry (AbstractConfigEntry* entry);" << endl;
169 os << "static void SetupConfigurationLists()" << endl;
170 os << "{" << endl;
171
172 for (vector<EntryType>::const_iterator it = entries.begin(); it != entries.end(); ++it)
173 {
174 os << "\tInitConfigurationEntry (new " << it->type << "ConfigEntry (&cfg::" <<
175 it->name << ", \"" << it->name << "\", " << it->defvalue << "));" << endl;
176 }
177
178 os << "}" << endl;
179 cout << "Wrote configuration options list to " << argv[argc - 1] << "." << endl;
180 return 0;
181 }

mercurial