1 // generate autohdr.h based on the `EX` and `#if HDR` in *.cpp files
2 #include <cstdio>
3 #include <iostream>
4 #include <fstream>
5 #include <string>
6 #include <vector>
7 #include <set>
8 #include <cstdlib>
9
10 using namespace std;
11
12 int indent = 2;
13
ind()14 string ind() { string s; for(int i=0; i<indent; i++) s += ' '; return s; }
15
16 string which_file;
17
18 vector<string> if_stack;
19 int ifs_level;
20
mark_file()21 void mark_file() {
22 if(which_file != "") {
23 cout << "\n" << ind() << "// implemented in: " << which_file << "\n\n";
24 which_file = "";
25 }
26 while(ifs_level < (int) if_stack.size())
27 cout << ind() << if_stack[ifs_level++] << "\n";
28 }
29
30 int in_hdr;
31
32 set<string> seen;
33
34 int lineid;
35
gen(string sf)36 void gen(string sf) {
37 if(seen.count(sf)) return;
38 seen.insert(sf);
39 which_file = sf; lineid = 1;
40 ifstream in(sf.c_str());
41 string s;
42 while(getline(in, s)) {
43 lineid++;
44 while(s != "" && s[0] == ' ') s = s.substr(1);
45 while(s != "" && (s[s.size()-1] == 10 || s[s.size()-1] == 13)) s = s.substr(0, s.size() - 1);
46 if(in_hdr) {
47 if(s == "#endif")
48 in_hdr--;
49 if(s.substr(0, 3) == "#if")
50 in_hdr++;
51 if(in_hdr)
52 cout << ind() << s << "\n";
53 continue;
54 }
55 if(s == "#if HDR") {
56 mark_file();
57 cout << "#line " << lineid << " \"" << sf << "\"\n";
58 in_hdr = true;
59 continue;
60 }
61 if(s == "#if CU_INIT") {
62 if_stack.push_back("#if 1");
63 continue;
64 }
65 if(s.substr(0, 3) == "#if" || s.substr(0, 4) == "# if") {
66 if_stack.push_back(s);
67 }
68 if(s.substr(0, 6) == "#endif") {
69 if(if_stack.empty()) { cerr << "if_stack error " << which_file << ", " << s << "\n"; exit(1); }
70 if_stack.pop_back();
71 while(ifs_level > (int) if_stack.size())
72 cout << ind() << "#endif\n", ifs_level--;
73 }
74 if(s.substr(0, 4) == "EX }") {
75 mark_file();
76 cout << ind() << "}\n";
77 indent -= 2;
78 }
79 else if(s.substr(0, 3) == "EX ") {
80 string t = s.substr(3);
81 if(t.substr(0, 10) == "namespace ") {
82 mark_file();
83 cout << ind() << t << "\n";
84 indent += 2;
85 }
86 else {
87 mark_file();
88 cout << "#line " << lineid-1 << " \"" << sf << "\"\n";
89 for(int i=0;; i++) {
90 if(i == int(t.size())) { cerr << "Error: unrecognizable EX: " << s << "\n"; }
91 else if(t[i] == '{') {
92 while(i && t[i-1] == ' ') i--;
93 cout << ind() << t.substr(0, i) << ";\n";
94 break;
95 }
96 else if(t[i] == ';') {
97 cout << ind() << "extern " << t << "\n";
98 break;
99 }
100 else if(t[i] == '=') {
101 while(i && t[i-1] == ' ') i--;
102 cout << ind() << "extern " << t.substr(0, i) << ";\n";
103 break;
104 }
105 }
106 }
107 }
108 }
109
110 while(ifs_level > (int) if_stack.size())
111 cout << ind() << "#endif\n", ifs_level--;
112
113 while(indent > 2) {
114 cout << ind() << "}\n";
115 indent -= 2;
116 }
117 }
118
main(int argc,char ** argv)119 int main(int argc, char ** argv) {
120 printf("// This file is generated automatically by makeh.cpp.\n\nnamespace hr {\n");
121 indent = 2;
122
123 for(int i=1; i<argc; i++)
124 gen(argv[i]);
125
126 printf(" }\n");
127 }
128