gen_runtime.cpp revision ea877edd85a9b030fec742491322ee58324b7ae6
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <vector>
19#include <list>
20#include <string>
21
22using namespace std;
23
24FILE *gIn;
25FILE *gOut;
26
27class Func {
28public:
29    Func() {
30        mMinVersion = 0;
31        mMaxVersion = 0;
32    }
33
34    string mName;
35    int mMinVersion;
36    int mMaxVersion;
37
38    vector<vector<string> > mReplaceables;
39    vector<string> mArgs;
40    string mRet;
41    vector<string> mComment;
42    vector<string> mInline;
43
44};
45
46vector<Func *> gFuncs;
47
48bool getNextLine(FILE *in, string *s) {
49    s->clear();
50    while (1) {
51        int c = fgetc(in);
52        if (c == EOF) return s->size() != 0;
53        if (c == '\n') break;
54        s->push_back((char)c);
55    }
56    return true;
57}
58
59void trim(string *s, size_t start) {
60    if (start > 0) {
61        s->erase(0, start);
62    }
63
64    while (s->size() && (s->at(0) == ' ')) {
65        s->erase(0, 1);
66    }
67
68    size_t p = s->find_first_of("\n\r");
69    if (p != string::npos) {
70        s->erase(p);
71    }
72
73    while ((s->size() > 0) && (s->at(s->size()-1) == ' ')) {
74        s->erase(s->size() -1);
75    }
76}
77
78Func * scanFunction(FILE *in) {
79    Func *f = new Func();
80    bool modeComment = false;
81    bool modeInline = false;
82    size_t replacables = 0;
83
84    while (1) {
85        string s;
86        bool ret = getNextLine(in, &s);
87        if (!ret) break;
88
89        if (modeComment) {
90            if (!s.size() || (s[0] == ' ')) {
91                trim(&s, 0);
92                f->mComment.push_back(s);
93                continue;
94            } else {
95                modeComment = false;
96            }
97        }
98
99        if (modeInline) {
100            if (!s.size() || (s[0] == ' ')) {
101                trim(&s, 0);
102                f->mInline.push_back(s);
103                continue;
104            } else {
105                modeInline = false;
106            }
107        }
108
109        if (s[0] == '#') {
110            continue;
111        }
112
113        if (s.compare(0, 5, "name:") == 0) {
114            trim(&s, 5);
115            f->mName = s;
116            continue;
117        }
118
119        if (s.compare(0, 4, "arg:") == 0) {
120            trim(&s, 4);
121            f->mArgs.push_back(s);
122            continue;
123        }
124
125        if (s.compare(0, 4, "ret:") == 0) {
126            trim(&s, 4);
127            f->mRet = s;
128            continue;
129        }
130
131        if (s.compare(0, 4, "end:") == 0) {
132            return f;
133        }
134
135        if (s.compare(0, 8, "comment:") == 0) {
136            modeComment = true;
137            continue;
138        }
139
140        if (s.compare(0, 7, "inline:") == 0) {
141            modeInline = true;
142            continue;
143        }
144
145        if (s.compare(0, 8, "version:") == 0) {
146            trim(&s, 8);
147            sscanf(s.c_str(), "%i %i", &f->mMinVersion, &f->mMaxVersion);
148            continue;
149        }
150
151        if (s.compare(0, 8, "start:") == 0) {
152            continue;
153        }
154
155        if (s.compare(0, 2, "w:") == 0) {
156            vector<string> t;
157            if (s.find("1") != string::npos) {
158                t.push_back("");
159            }
160            if (s.find("2") != string::npos) {
161                t.push_back("2");
162            }
163            if (s.find("3") != string::npos) {
164                t.push_back("3");
165            }
166            if (s.find("4") != string::npos) {
167                t.push_back("4");
168            }
169            f->mReplaceables.push_back(t);
170            continue;
171        }
172
173        if (s.compare(0, 2, "t:") == 0) {
174            vector<string> t;
175            if (s.find("f16") != string::npos) {
176                t.push_back("half");
177            }
178            if (s.find("f32") != string::npos) {
179                t.push_back("float");
180            }
181            if (s.find("f64") != string::npos) {
182                t.push_back("double");
183            }
184            if (s.find("i8") != string::npos) {
185                t.push_back("char");
186            }
187            if (s.find("u8") != string::npos) {
188                t.push_back("uchar");
189            }
190            if (s.find("i16") != string::npos) {
191                t.push_back("short");
192            }
193            if (s.find("u16") != string::npos) {
194                t.push_back("ushort");
195            }
196            if (s.find("i32") != string::npos) {
197                t.push_back("int");
198            }
199            if (s.find("u32") != string::npos) {
200                t.push_back("uint");
201            }
202            if (s.find("i64") != string::npos) {
203                t.push_back("long");
204            }
205            if (s.find("u64") != string::npos) {
206                t.push_back("ulong");
207            }
208            f->mReplaceables.push_back(t);
209            continue;
210        }
211
212        if (s.size() == 0) {
213            // eat empty line
214            continue;
215        }
216
217        printf("Error, line:\n");
218        printf("  %s\n", s.c_str());
219    }
220
221    delete f;
222    return NULL;
223}
224
225string stringReplace(string s, string match, string rep) {
226    while(1) {
227        size_t p = s.find(match);
228        if (p == string::npos) break;
229
230        s.erase(p, match.size());
231        s.insert(p, rep);
232    }
233    return s;
234}
235
236string stringExpand(string s, const Func *f, int i1, int i2, int i3, int i4) {
237    if (f->mReplaceables.size() > 0) {
238        s = stringReplace(s, "#1", f->mReplaceables[0][i1]);
239    }
240    if (f->mReplaceables.size() > 1) {
241        s = stringReplace(s, "#2", f->mReplaceables[1][i2]);
242    }
243    if (f->mReplaceables.size() > 2) {
244        s = stringReplace(s, "#3", f->mReplaceables[2][i3]);
245    }
246    if (f->mReplaceables.size() > 3) {
247        s = stringReplace(s, "#4", f->mReplaceables[3][i4]);
248    }
249    return s;
250}
251
252void writeLegal(FILE *o) {
253    fprintf(o, "/*\n");
254    fprintf(o, " * Copyright (C) 2014 The Android Open Source Project\n");
255    fprintf(o, " *\n");
256    fprintf(o, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
257    fprintf(o, " * you may not use this file except in compliance with the License.\n");
258    fprintf(o, " * You may obtain a copy of the License at\n");
259    fprintf(o, " *\n");
260    fprintf(o, " *      http://www.apache.org/licenses/LICENSE-2.0\n");
261    fprintf(o, " *\n");
262    fprintf(o, " * Unless required by applicable law or agreed to in writing, software\n");
263    fprintf(o, " * distributed under the License is distributed on an \"AS IS\" BASIS,\n");
264    fprintf(o, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
265    fprintf(o, " * See the License for the specific language governing permissions and\n");
266    fprintf(o, " * limitations under the License.\n");
267    fprintf(o, " */\n\n");
268}
269
270void writeIfdef(FILE *o, string filename, bool isStart) {
271    string t = "__";
272    t += filename;
273    t += "__";
274
275    for (size_t i = 2; i < t.size(); i++) {
276        if (t[i] == '.') {
277            t[i] = '_';
278        }
279    }
280
281    if (isStart) {
282        fprintf(o, "#ifndef %s\n", t.c_str());
283        fprintf(o, "#define %s\n", t.c_str());
284    } else {
285        fprintf(o, "#endif // %s\n", t.c_str());
286    }
287}
288
289
290
291void writeHeaderFunc(FILE *o, const Func *f, int i1, int i2, int i3, int i4) {
292    string s;
293
294    if (f->mMinVersion || f->mMaxVersion) {
295        if (f->mMaxVersion) {
296            fprintf(o, "#if (defined(RS_VERSION) && (RS_VERSION >= %i) && (RS_VERSION <= %i))\n",
297                    f->mMinVersion, f->mMaxVersion);
298        } else {
299            fprintf(o, "#if (defined(RS_VERSION) && (RS_VERSION >= %i))\n",
300                    f->mMinVersion);
301        }
302    }
303
304    fprintf(o, "/*\n");
305    for (size_t ct=0; ct < f->mComment.size(); ct++) {
306        s = stringExpand(f->mComment[ct], f, i1, i2, i3, i4);
307        if (s.size()) {
308            fprintf(o, " * %s\n", s.c_str());
309        } else {
310            fprintf(o, " *\n");
311        }
312    }
313    fprintf(o, " *\n");
314    if (f->mMinVersion || f->mMaxVersion) {
315        if (f->mMaxVersion) {
316            fprintf(o, " * Suppored by API versions %i - %i\n",
317                    f->mMinVersion, f->mMaxVersion);
318        } else {
319            fprintf(o, " * Supported by API versions %i and newer.\n",
320                    f->mMinVersion);
321        }
322    }
323
324    fprintf(o, " */\n");
325
326    s.clear();
327    if (f->mInline.size() > 0) {
328        s += "static ";
329    } else {
330        s += "extern ";
331    }
332    s += f->mRet;
333    s += " __attribute__((const, overloadable))";
334    s += f->mName;
335    s += "(";
336    if (f->mArgs.size()) {
337        s += f->mArgs[0];
338    }
339    for (size_t ct=1; ct < f->mArgs.size(); ct++) {
340        s += ", ";
341        s += f->mArgs[ct];
342    }
343    if (f->mInline.size() > 0) {
344        s += ") {";
345    } else {
346        s += ");";
347    }
348    s = stringExpand(s, f, i1, i2, i3, i4);
349    fprintf(o, "%s\n", s.c_str());
350
351    if (f->mInline.size() > 0) {
352        for (size_t ct=0; ct < f->mInline.size(); ct++) {
353            s = stringExpand(f->mInline[ct], f, i1, i2, i3, i4);
354            fprintf(o, " %s\n", s.c_str());
355        }
356        fprintf(o, "}\n");
357    }
358
359    if (f->mMinVersion || f->mMaxVersion) {
360        fprintf(o, "#endif\n");
361    }
362
363    fprintf(o, "\n", s.c_str());
364}
365
366
367void writeHeaderFuncs(FILE *o, const Func *f) {
368    switch(f->mReplaceables.size()) {
369    case 0:
370        writeHeaderFunc(o, f, -1, -1, -1, -1);
371        break;
372    case 1:
373        for (size_t i1 = 0; i1 < f->mReplaceables[0].size(); i1++) {
374            writeHeaderFunc(o, f, i1, -1, -1, -1);
375        }
376        break;
377    case 2:
378        for (size_t i2 = 0; i2 < f->mReplaceables[1].size(); i2++) {
379            for (size_t i1 = 0; i1 < f->mReplaceables[0].size(); i1++) {
380                writeHeaderFunc(o, f, i1, i2, -1, -1);
381            }
382        }
383        break;
384    case 3:
385        for (size_t i3 = 0; i3 < f->mReplaceables[2].size(); i3++) {
386            for (size_t i2 = 0; i2 < f->mReplaceables[1].size(); i2++) {
387                for (size_t i1 = 0; i1 < f->mReplaceables[0].size(); i1++) {
388                    writeHeaderFunc(o, f, i1, i2, i3, -1);
389                }
390            }
391        }
392        break;
393    case 4:
394        for (size_t i4 = 0; i4 < f->mReplaceables[3].size(); i4++) {
395            for (size_t i3 = 0; i3 < f->mReplaceables[2].size(); i3++) {
396                for (size_t i2 = 0; i2 < f->mReplaceables[1].size(); i2++) {
397                    for (size_t i1 = 0; i1 < f->mReplaceables[0].size(); i1++) {
398                        writeHeaderFunc(o, f, i1, i2, i3, i4);
399                    }
400                }
401            }
402        }
403        break;
404    }
405}
406
407
408
409int main(int argc, char* argv[])
410{
411    const char *inpath = "runtime.spec";
412    const char *outpath = "rs_core_math.rsh";
413
414    gIn = fopen(inpath, "rt");
415    if (!gIn) {
416        printf("Error opening input file: %s", inpath);
417        return -1;
418    }
419
420    while (1) {
421        Func *f = scanFunction(gIn);
422        if (f != NULL) {
423            gFuncs.push_back(f);
424        } else {
425            break;
426        }
427    }
428
429    gOut = fopen(outpath, "wt");
430    if (!gOut) {
431        printf("Error opening output file: %s", outpath);
432        return -1;
433    }
434
435    writeLegal(gOut);
436    writeIfdef(gOut, outpath, true);
437    for (size_t ct=0; ct < gFuncs.size(); ct++) {
438        writeHeaderFuncs(gOut, gFuncs[ct]);
439    }
440    writeIfdef(gOut, outpath, false);
441
442    fclose (gIn);
443    fclose (gOut);
444
445    printf("%i Functions processed.\n", (int)gFuncs.size());
446
447    return 0;
448}
449
450
451