Ticket #105: API_FPU_CW_Wrappers.awk

File API_FPU_CW_Wrappers.awk, 2.6 KB (added by Dmitry A. Kuminov, 15 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}