1#!/usr/bin/env python
2#
3# Script to sort the game controller database entries in SDL_gamecontroller.c
4
5import re
6
7
8filename = "SDL_gamecontrollerdb.h"
9input = open(filename)
10output = open(filename + ".new", "w")
11parsing_controllers = False
12controllers = []
13controller_guids = {}
14conditionals = []
15split_pattern = re.compile(r'([^"]*")([^,]*,)([^,]*,)([^"]*)(".*)')
16
17def find_element(prefix, bindings):
18    i=0
19    for element in bindings:
20        if element.startswith(prefix):
21            return i
22        i=(i + 1)
23
24    return -1
25
26def save_controller(line):
27    global controllers
28    match = split_pattern.match(line)
29    entry = [ match.group(1), match.group(2), match.group(3) ]
30    bindings = sorted(match.group(4).split(","))
31    if (bindings[0] == ""):
32        bindings.pop(0)
33
34    pos=find_element("sdk", bindings)
35    if pos >= 0:
36        bindings.append(bindings.pop(pos))
37
38    pos=find_element("hint:", bindings)
39    if pos >= 0:
40        bindings.append(bindings.pop(pos))
41
42    entry.extend(",".join(bindings) + ",")
43    entry.append(match.group(5))
44    controllers.append(entry)
45
46    if ',sdk' in line or ',hint:' in line:
47        conditionals.append(entry[1])
48
49def write_controllers():
50    global controllers
51    global controller_guids
52    # Check for duplicates
53    for entry in controllers:
54        if (entry[1] in controller_guids and entry[1] not in conditionals):
55            current_name = entry[2]
56            existing_name = controller_guids[entry[1]][2]
57            print("Warning: entry '%s' is duplicate of entry '%s'" % (current_name, existing_name))
58
59            if (not current_name.startswith("(DUPE)")):
60                entry[2] = "(DUPE) " + current_name
61
62            if (not existing_name.startswith("(DUPE)")):
63                controller_guids[entry[1]][2] = "(DUPE) " + existing_name
64
65        controller_guids[entry[1]] = entry
66
67    for entry in sorted(controllers, key=lambda entry: entry[2]+"-"+entry[1]):
68        line = "".join(entry) + "\n"
69        line = line.replace("\t", "    ")
70        if not line.endswith(",\n") and not line.endswith("*/\n"):
71            print("Warning: '%s' is missing a comma at the end of the line" % (line))
72        output.write(line)
73
74    controllers = []
75    controller_guids = {}
76
77for line in input:
78    if (parsing_controllers):
79        if (line.startswith("{")):
80            output.write(line)
81        elif (line.startswith("    NULL")):
82            parsing_controllers = False
83            write_controllers()
84            output.write(line)
85        elif (line.startswith("#if")):
86            print("Parsing " + line.strip())
87            output.write(line)
88        elif (line.startswith("#endif")):
89            write_controllers()
90            output.write(line)
91        else:
92            save_controller(line)
93    else:
94        if (line.startswith("static const char *s_ControllerMappings")):
95            parsing_controllers = True
96
97        output.write(line)
98
99output.close()
100print("Finished writing %s.new" % filename)
101