Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1. Generate a versioned include file from a standard hds.h include file. This can be used by the v4 and v5 HDS libraries to allow them to publicize a version specific API. 2. Script to generate hds_select.c which provides basic version selection code to switch between APIs based on the locator.
- Loading branch information
Showing
2 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#!python | ||
|
||
""" | ||
Given the HDS include file, generate a new include file | ||
for either v4 or v5 API. We can not do lazy evaluation of | ||
macros as we want v5 and v4 and the public API to exist | ||
in code at the same time. | ||
We need to be able to | ||
#include "hds.h" | ||
#include "hds_v5.h" | ||
#include "hds_v4.h" | ||
and get all the APIs defined: datPublic, datPublic_v4 | ||
and datPublic_v4 with no redefinitions. | ||
Internally in the v5 and v4 code, we want to be able to | ||
build the entire HDS standalone with the public API and | ||
build it with the versioned API (we do not want to have | ||
to go through the old HDS code and change all the | ||
datName usage to datName_v4) when used as a wrapper. | ||
This means that hds.h in v4 has to be able to load declaring | ||
public or versioned API. | ||
This routine therefore generates | ||
- standalone copy of hds.h that can be included by the wrapper (hds_vx.h) | ||
- include file of redefinitions that can be included in | ||
internal build of wrapped library. (hds_vx_map.h) | ||
""" | ||
|
||
import codecs | ||
import re | ||
|
||
# Pattern match to find a function | ||
hfunc_re = re.compile(r"^((dat|hds)[A-Z][A-Za-z0-9]+)\(") | ||
|
||
# First define the versioned API | ||
for ver in ["_v4", "_v5"]: | ||
outfile = "hds" + ver + ".h" | ||
outfh = codecs.open( outfile,"w", "utf8") | ||
for line in codecs.open("hds.h", "r", "utf8"): | ||
line = line.strip() | ||
func_match = hfunc_re.search(line) | ||
if func_match: | ||
line = line.replace("(", ver+"(") | ||
elif line.find("STAR_HDS_H") != -1: | ||
line = line.replace("STAR_HDS_H", "STAR_HDS"+ver.upper()+"_H") | ||
outfh.write(line+"\n") | ||
outfh.close() | ||
|
||
# Now the translation file | ||
for ver in ["_v4", "_v5"]: | ||
outfile = "hds" + ver + "_map.h" | ||
outfh = codecs.open( outfile,"w", "utf8") | ||
for line in codecs.open("hds.h", "r", "utf8"): | ||
line = line.strip() | ||
func_match = hfunc_re.search(line) | ||
if func_match: | ||
hds_function = func_match.group(1) | ||
outfh.write("#define {0} {0}{1}\n".format(hds_function, ver)) | ||
outfh.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#!python | ||
|
||
""" | ||
Given the HDS include file, generate a wrapper that calls | ||
the v4 or v5 APIs depending on the type of the input | ||
locator. | ||
Reads through hds.h and for every API definition, generates | ||
a wrapper routine. | ||
Notes: | ||
- datCcopy is only routine that takes two locators and returns a third. | ||
- Routines taking two input locators: | ||
datCopy, datMove | ||
All other routines take one locator and may or may not return a | ||
locator. That locator will be of the correct type. | ||
The copy/move routines will need special code to be able to handle | ||
locators from different implementations. | ||
Routines that don't take a locator at all: | ||
datCctyp - call v5 | ||
datChscn - call v5 | ||
datErmsg - Use wrapper implementation that uses largest error table (default to v5) | ||
hdsEwild - Wrapper implementation | ||
hdsFlush - Call both (only error if both fail) | ||
hdsGtune - call both (only error if both fail or both different) | ||
hdsShow - call one or both depending on whether we have used any v5 or v4 locators. | ||
hdsState - call both (error if different) | ||
hdsStop - call both | ||
hdsTune - call both routines | ||
Routines that open a file: | ||
hdsOpen - Try v5 and if that fails try v4 | ||
hdsWild - presumably will use hdsOpen internally. | ||
This routine has to be implemented in the wrapper | ||
so that the wrapped hdsOpen can be called. | ||
Creating a file: | ||
hdsNew - always creates v5 unless environment variable | ||
indicates to only open v4. | ||
datTemp - uses same logic as for hdsNew | ||
Ideally v5 files would have a different file ending to v4 | ||
but that will require lots of code changes in other packages | ||
that are assuming just one file extension. | ||
Will not be run repeatedly as there will eventually be special | ||
code for these notable routines. File is retained for historical | ||
interest. | ||
""" | ||
|
||
import re | ||
|
||
# Pattern match to find a function | ||
hfunc_re = re.compile(r"^((dat|hds)[A-Z][A-Za-z0-9]+)\(") | ||
|
||
def version_names(line): | ||
v4 = line.replace("(", "_v4(") | ||
v5 = line.replace("(", "_v5(") | ||
return (v4,v5) | ||
|
||
# Code for the different type of functions | ||
def func_simple(line): | ||
(v4,v5) = version_names(line) | ||
# are we dealing with locator or locator1? | ||
locvar = "locator" | ||
if line.find("locator1") >= 0: | ||
locvar = "locator1" | ||
elif line.startswith("datAnnul") or line.startswith("datPrmry") or line.startswith("hdsErase") or line.startswith("hdsClose"): | ||
locvar = "*locator" | ||
print(""" | ||
if (ISHDSv5({0})) return {1} | ||
return {2} | ||
""".format(locvar, v5, v4)) | ||
|
||
|
||
def func_special(line): | ||
print(" /* Requires special code */") | ||
print(' printf("Aborting. Special code required in: %s\\n", "{0}");'.format(line)) | ||
print(" abort();") | ||
if line.find("status") > -1: | ||
print(" return *status;") | ||
|
||
def func_both(line): | ||
v4 = line.replace("(", "_v4(") | ||
print(" "+v4) | ||
v5 = line.replace("(", "_v5(") | ||
print(" return "+v5) | ||
|
||
def func_v5(line): | ||
v5 = line.replace("(", "_v5(") | ||
print(" return "+v5) | ||
|
||
|
||
# Dictionary indicating special cases | ||
special = dict({ | ||
"datCcopy": "special", | ||
"datCctyp": "v5", | ||
"datChscn": "v5", | ||
"datCopy": "special", | ||
"datErmsg": "v5", | ||
"datMove": "special", | ||
"datTemp": "v5", | ||
"hdsEwild": "special", | ||
"hdsFlush": "both", | ||
"hdsGtune": "both", | ||
"hdsNew": "v5", | ||
"hdsOpen": "both", | ||
"hdsShow": "special", | ||
"hdsState": "both", | ||
"hdsStop": "both", | ||
"hdsTune": "both", | ||
"hdsWild": "special" | ||
}) | ||
|
||
inserted_includes = 0 | ||
for line in open("hds.h"): | ||
line = line.strip() | ||
func_match = hfunc_re.search(line) | ||
if func_match: | ||
hds_function = func_match.group(1) | ||
print( line[:-1] + " {") # Without the semi-colon | ||
# Now we have to convert the prototype to a function call | ||
# ie datXxx( type1 var1, type2 var2); to datXxx(var1,var2); | ||
openparen = line.find("(") | ||
closeparen = line.find(")") | ||
argsin = line[openparen:closeparen].split(",") | ||
argsout = [] | ||
for a in argsin: | ||
# Get rid of array [] specifiers | ||
arraypos = a.find("[") | ||
if arraypos > -1: | ||
a = a[:arraypos] | ||
parts = a.split() | ||
varname = parts[-1] | ||
# Remember to drop pointer derefs | ||
argsout.append( varname.replace("*", "") ) | ||
# put the line back together | ||
line = hds_function + "(" + ", ".join(argsout) + ");" | ||
if hds_function in special: | ||
mode = special[hds_function] | ||
if mode == "both": | ||
func_both(line) | ||
elif mode == "special": | ||
func_special(line) | ||
elif mode == "v5": | ||
func_v5(line) | ||
else: | ||
raise ValueError("Unrecognized mode for function {0}".format(hds_function)) | ||
else: | ||
func_simple(line) | ||
print("}") | ||
else: | ||
if not inserted_includes and line.startswith("/*=="): | ||
print('#include <stdlib.h>') # For abort() | ||
print('#include <stdio.h>') # For printf() | ||
print('#include "hds.h"') | ||
print('#include "star/hds_v4.h"') | ||
print('#include "star/hds_v5.h"') | ||
print('#define ISHDSv5(loc) ((loc) && (loc)->hds_version >= 5)') | ||
print("") | ||
inserted_includes=1 | ||
elif line.find("dat_par.h") != -1: | ||
print('#include "hds1_types.h"') | ||
print("#define HDS_INTERNAL_INCLUDES 1") | ||
print(line) | ||
|