Ticket #105: API_FPU_CW_Wrappers.awk

File API_FPU_CW_Wrappers.awk, 2.6 KB (added by Dmitry A. Kuminov, 14 years ago)

AWK script to create wrappers for Win* and Gpi* calls that restore the FPU Control Word

Line 
1# This AWK script will take os2emx.h and create wrappers that restore
2# the FPU control word to its normal state expected by C/C++ programs
3
4BEGIN {
5    if (ARGC != 2) {
6        print "Usage: API_FPU_CW_Wrappers.awk <os2emx.h>";
7        exit 1;
8    }
9    in_func_decl = 0;
10    func_decl = ""
11    num_funcs = 0
12}
13
14/^[a-zA-Z]+[ \t]+APIENTRY[ \t]+(Win|Gpi).*[ \t]+\(/ { in_func_decl = 1 }
15
16in_func_decl { func_decl = func_decl $0 }
17
18/;/ && in_func_decl {
19    in_func_decl = 0
20    funcs[num_funcs] = substr(func_decl, 1, length(func_decl)-1)
21    func_decl = ""
22    num_funcs++
23}
24
25END {
26    print "/* Generated by API_FPU_CW_Wrappers.awk from os2emx.h      */"
27    print "/* See http://svn.netlabs.org/qt4/ticket/105 for more info */"
28    print ""
29    print "/*"
30    print " * Some OS/2 PM API calls modify the FPU Control Word,"
31    print " * but forget to restore it."
32    print " *"
33    print " * This can result in unexpected XCPT_FLOAT_INVALID_OPCODE or"
34    print " * XCPT_FLOAT_INVALID_OPERATION exceptions. To avoid this, we create"
35    print " * wrappers for each API call that restore the FPU Control Word"
36    print " * after the API call back to the value expected by C/C++ programs."
37    print " */"
38    print ""
39    print "#ifndef API_FPU_CW_WRAPPERS_H"
40    print "#define API_FPU_CW_WRAPPERS_H"
41    print ""
42    print "inline void __FPU_CW_Restore()"
43    print "{"
44    print "    asm(\"pushl %%eax\\n\\t\"       /* Dummy for storing control word */"
45    print "        \"fstcw 0(%%esp)\\n\\t\"    /* Store control word into memory */"
46    print "        \"orw $5, 0(%%esp)\\n\\t\"  /* Set EM_INVALID (0x1) | EM_ZERODIVIDE (0x4) */"
47    print "        \"fldcw 0(%%esp)\\n\\t\"    /* Load control word back */"
48    print "        \"popl %%eax\\n\\t\""
49    print "        ::: \"eax\");"
50    print "}"
51    print ""
52
53    for (i = 0; i < num_funcs; i++) {
54        fnc = funcs[i]
55        rv  = gensub("^(.*)[ \t]+APIENTRY.*", "\\1", "", fnc)
56        fn = gensub(".*[ \t]+((Win|Gpi).*)[ \t]+\\(.*", "\\1", "", fnc)
57        print "inline " gensub(fn, "__FPU_CW_" fn, "", fnc) "\n{"
58        fn_args = gensub(".*\\((.*)\\).*", "\\1", "", fnc)
59        fn_args = gensub("([_a-zA-Z][_a-zA-Z0-9]*[ \t]+)+\\*?([_a-zA-Z][_a-zA-Z0-9]*)(,[ \t]+|$)", "\\2\\3", "g", fn_args)
60        if (toupper(fn_args) == "VOID")
61            fn_args = ""
62        print "    " rv " ret = " fn " (" fn_args ");"
63        print "    __FPU_CW_Restore();"
64        print "    return ret;\n}"
65        print "#define " fn " __FPU_CW_" fn "\n"
66    }
67
68    print "#endif // API_FPU_CW_WRAPPERS_H"
69}