1#!/usr/local/bin/python3.8
2
3# This script parses spglib_f.c, searches for all symbols, and writes a new
4# wrapper spglib_f_meta.c with all combinations of name mangling.
5# This script should only be called when spglib is updated.
6
7# Felipe H. da Jornada, Nov 2013
8
9import re
10
11f_in = open('spglib_f.c')
12str_in = f_in.read()
13f_in.close()
14
15f_out = open('spglib_f_meta.c', 'w')
16f_out.write(
17'''\
18/******************************************************************************
19*
20*  spglib_f_meta           Originally by FHJ     Last Modified 11/08/2012 (FHJ)
21*
22*
23*  SHORT
24*    BerkeleyGW meta wrapper for spglib.
25*
26*  LONG
27*    spglib`s Fortran wrappers assume the Fortran compiler will append an
28*    underscore after each symbol`s name, which is not true for all compilers,
29*    such as XL. This can lead to terrible results, especially since the symbols
30*    without underscores are also available in the library, but take different
31*    arguments. This file fixes this problem by exporting symbols with both
32*    "_f" and "_f_" appended to the names, so that they should work regardless
33*    of the name mangling.
34*
35*    This file is part of the BerkeleyGW package.
36*
37******************************************************************************/
38
39''')
40
41for match in re.findall(r'^void spg_[^)]*\);', str_in, re.DOTALL+re.MULTILINE):
42    obj = re.search(r'(spg_[^\s(]*)(\([^)]*\))', match)
43    try:
44        func_name = obj.group(1)
45        arg_list = obj.group(2)
46    except:
47        continue
48    arg_list_stripped = arg_list.replace('*', '').replace('&', '')
49    subs = ['short','long','unsigned','signed','char','int','float','double','void','const']
50    for sub in subs:
51        arg_list_stripped = re.sub(r'\W'+sub+'\W', '', arg_list_stripped)
52    arg_list_stripped = re.sub('\[[^]]*\]', '', arg_list_stripped)
53    print('Exporting symbol %s'%(func_name))
54    f_out.write('\n/* Original symbol from spglib_f.c */\n')
55    f_out.write('extern %s\n'%(match))
56    f_out.write('/* Wrapped symbol without underscore */\n')
57    f_out.write('''void %s%s {
58    %s%s;
59}
60'''%(func_name+'f', arg_list, func_name, arg_list_stripped))
61    f_out.write('/* Wrapped symbol with underscore */\n')
62    f_out.write('''void %s%s {
63    %s%s;
64}
65'''%(func_name+'f_', arg_list, func_name, arg_list_stripped))
66