31 using std::strncmp; |
31 using std::strncmp; |
32 using std::getline; |
32 using std::getline; |
33 using std::cout; |
33 using std::cout; |
34 using std::endl; |
34 using std::endl; |
35 |
35 |
36 struct entry_type |
36 struct EntryType |
37 { |
37 { |
38 string name; |
38 string name; |
39 string type; |
39 string type; |
40 string defvalue; |
40 string defvalue; |
41 |
41 |
42 inline bool operator< (entry_type const& other) const |
42 inline bool operator< (EntryType const& other) const |
43 { |
43 { |
44 return name < other.name; |
44 return name < other.name; |
45 } |
45 } |
46 |
46 |
47 inline bool operator== (entry_type const& other) const |
47 inline bool operator== (EntryType const& other) const |
48 { |
48 { |
49 return name == other.name and type == other.type; |
49 return name == other.name and type == other.type; |
50 } |
50 } |
51 |
51 |
52 inline bool operator!= (entry_type const& other) const |
52 inline bool operator!= (EntryType const& other) const |
53 { |
53 { |
54 return not operator== (other); |
54 return not operator== (other); |
55 } |
55 } |
56 }; |
56 }; |
57 |
57 |
58 char advance_pointer (char const*& ptr) |
58 char AdvancePointer (char const*& ptr) |
59 { |
59 { |
60 char a = *ptr++; |
60 char a = *ptr++; |
|
61 |
61 if (*ptr == '\0') |
62 if (*ptr == '\0') |
62 throw false; |
63 throw false; |
63 |
64 |
64 return a; |
65 return a; |
65 } |
66 } |
66 |
67 |
67 void read_cfgentries (string const& filename, vector<entry_type>& entries, const char* macroname) |
68 void ReadConfigEntries (string const& filename, vector<EntryType>& entries, const char* macroname) |
68 { |
69 { |
69 ifstream is (filename.c_str()); |
70 ifstream is (filename.c_str()); |
70 string line; |
71 string line; |
71 size_t const macrolen = strlen (macroname); |
72 size_t const macrolen = strlen (macroname); |
72 |
73 |
76 { |
77 { |
77 if (strncmp (line.c_str(), macroname, macrolen) != 0) |
78 if (strncmp (line.c_str(), macroname, macrolen) != 0) |
78 continue; |
79 continue; |
79 |
80 |
80 char const* ptr = &line[macrolen]; |
81 char const* ptr = &line[macrolen]; |
81 entry_type entry; |
82 EntryType entry; |
82 |
83 |
83 // Skip to paren |
84 // Skip to paren |
84 while (*ptr != '(') |
85 while (*ptr != '(') |
85 advance_pointer (ptr); |
86 AdvancePointer (ptr); |
86 |
87 |
87 // Skip whitespace |
88 // Skip whitespace |
88 while (isspace (*ptr)) |
89 while (isspace (*ptr)) |
89 advance_pointer (ptr); |
90 AdvancePointer (ptr); |
90 |
91 |
91 // Skip paren |
92 // Skip paren |
92 advance_pointer (ptr); |
93 AdvancePointer (ptr); |
93 |
94 |
94 // Read type |
95 // Read type |
95 while (*ptr != ',') |
96 while (*ptr != ',') |
96 entry.type += advance_pointer (ptr); |
97 entry.type += AdvancePointer (ptr); |
97 |
98 |
98 // Skip comma and whitespace |
99 // Skip comma and whitespace |
99 for (advance_pointer (ptr); isspace (*ptr); advance_pointer (ptr)) |
100 for (AdvancePointer (ptr); isspace (*ptr); AdvancePointer (ptr)) |
100 ; |
101 ; |
101 |
102 |
102 // Read name |
103 // Read name |
103 while (*ptr != ',') |
104 while (*ptr != ',') |
104 entry.name += advance_pointer (ptr); |
105 entry.name += AdvancePointer (ptr); |
105 |
106 |
106 // Skip comma and whitespace |
107 // Skip comma and whitespace |
107 for (advance_pointer (ptr); isspace (*ptr); advance_pointer (ptr)) |
108 for (AdvancePointer (ptr); isspace (*ptr); AdvancePointer (ptr)) |
108 ; |
109 ; |
109 |
110 |
110 // Read default |
111 // Read default |
111 while (*ptr != ')') |
112 while (*ptr != ')') |
112 entry.defvalue += advance_pointer (ptr); |
113 entry.defvalue += AdvancePointer (ptr); |
113 |
114 |
114 entries.push_back (entry); |
115 entries.push_back (entry); |
115 } |
116 } |
116 catch (bool) {} |
117 catch (bool) {} |
117 } |
118 } |
118 } |
119 } |
119 |
120 |
120 bool check_equality (vector<entry_type> a, vector<entry_type> b) |
121 bool CheckEquality (vector<EntryType> a, vector<EntryType> b) |
121 { |
122 { |
122 if (a.size() != b.size()) |
123 if (a.size() != b.size()) |
123 return false; |
124 return false; |
124 |
125 |
125 std::sort (a.begin(), a.end()); |
126 std::sort (a.begin(), a.end()); |
134 return true; |
135 return true; |
135 } |
136 } |
136 |
137 |
137 int main (int argc, char* argv[]) |
138 int main (int argc, char* argv[]) |
138 { |
139 { |
139 vector<entry_type> entries; |
140 vector<EntryType> entries; |
140 vector<entry_type> oldentries; |
141 vector<EntryType> oldentries; |
141 read_cfgentries (argv[argc - 1], oldentries, "CODEGEN_CACHE"); |
142 ReadConfigEntries (argv[argc - 1], oldentries, "CODEGEN_CACHE"); |
142 |
143 |
143 for (int arg = 1; arg < argc - 1; ++arg) |
144 for (int arg = 1; arg < argc - 1; ++arg) |
144 read_cfgentries (argv[arg], entries, "CFGENTRY"); |
145 ReadConfigEntries (argv[arg], entries, "CFGENTRY"); |
145 |
146 |
146 if (check_equality (entries, oldentries)) |
147 if (CheckEquality (entries, oldentries)) |
147 { |
148 { |
148 cout << "Configuration options unchanged" << endl; |
149 cout << "Configuration options unchanged" << endl; |
149 } |
150 return 0; |
150 else |
|
151 { |
|
152 std::ofstream os (argv[argc - 1]); |
|
153 os << "#pragma once" << endl; |
|
154 os << "#define CODEGEN_CACHE(A,B,C)" << endl; |
|
155 |
|
156 for (vector<entry_type>::const_iterator it = entries.begin(); it != entries.end(); ++it) |
|
157 os << "CODEGEN_CACHE (" << it->type << ", " << it->name << ", " << it->defvalue << ")" << endl; |
|
158 |
|
159 os << endl; |
|
160 for (vector<entry_type>::const_iterator it = entries.begin(); it != entries.end(); ++it) |
|
161 os << "EXTERN_CFGENTRY (" << it->type << ", " << it->name << ")" << endl; |
|
162 |
|
163 os << endl; |
|
164 os << "static void InitConfigurationEntry (AbstractConfigEntry* entry);" << endl; |
|
165 os << "static void SetupConfigurationLists()" << endl; |
|
166 os << "{" << endl; |
|
167 |
|
168 for (vector<entry_type>::const_iterator it = entries.begin(); it != entries.end(); ++it) |
|
169 { |
|
170 os << "\tInitConfigurationEntry (new " << it->type << "ConfigEntry (&cfg::" << |
|
171 it->name << ", \"" << it->name << "\", " << it->defvalue << "));" << endl; |
|
172 } |
|
173 |
|
174 os << "}" << endl; |
|
175 |
|
176 cout << "Wrote configuration options list to " << argv[argc - 1] << "." << endl; |
|
177 } |
151 } |
178 |
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; |
179 return 0; |
180 return 0; |
180 } |
181 } |