iMSTK
Interactive Medical Simulation Toolkit
include-guard-convert.py
1 #!/usr/bin/env python
2 
3 """
4 Tool to convert traditional include guards to #pragma once.
5 
6 This tool is licensed under GPLv2.
7 See the LICENSE file for details.
8 
9 Dowloaded from this: https://github.com/marcusmueller/include-guard-convert
10 Usage: In Linux/Mac Terminal (not Windows), go to the Source folder then execute the following command:
11 
12 find . -iname "*.h" -exec python3 ~/Programming/include-guard-convert.py {} \;
13 
14 Note: After the conversion for the header files, uncrustify need to be run to re-format them
15 
16 """
17 
18 import re
19 import os
20 import subprocess
21 import shlex
22 
23 regexes = {
24  'ifndef' : '^\s*#(?:ifndef|IFNDEF)\s+([A-Za-z_0-9]{4,})\s*$',
25  'define' : '^\s*#(?:define|DEFINE)\s+([A-Za-z_0-9]{4,})\s*$',
26  'endif' : '^\s*#(?:endif|ENDIF)\s*(/\*.*\*/|//.+)?\s*$',
27  'blank' : '^\s*(/\*.*\*/|//.+)?\s*$',
28  'pragma' : '^\s*#(?:pragma|PRAGMA)\s+(?:once|ONCE)'
29 }
30 patterns = dict( [ (key, re.compile(regexes[key]) ) for key in regexes.keys() ] )
31 
32 cpp_commands = {
33  'strip_comments' : 'cpp -w -dD -fpreprocessed -P -x c++ {file}',
34  'test_if_guarded' : 'cpp -w -P -x c++ -D{define} {file}'
35 }
36 
37 class guarded_include(object):
38  """
39  Class representing an #include'able file (a.k.a. a header).
40  """
41 
42  def __init__(self, filename, autoconvert = False):
43  self.filename = filename
44  assert(self._test_readable())
45  if autoconvert and self.test_oldstyle_guarded():
46  self.convert()
47 
48  def _test_readable(self):
49  return os.access(self.filename, os.R_OK)
50 
51 
52  def test_oldstyle_guarded(self):
53  try:
54  self._stripped = subprocess.check_output(
55  shlex.split(
56  cpp_commands['strip_comments'].format(file=self.filename)
57  ),
58  stderr=subprocess.STDOUT
59  ).decode('utf-8')
60  lineend = self._stripped.find('\n')
61  match_ifndef = patterns['ifndef'].search(self._stripped[:lineend])
62  if not match_ifndef:
63  return False
64  define = match_ifndef.group(1)
65  with_define = subprocess.check_output(
66  shlex.split(
67  cpp_commands['test_if_guarded'].format(file=self.filename, define=define)
68  ),
69  stderr=subprocess.STDOUT
70  )
71  if not len(with_define) < 2:
72  return False
73  fh = open(self.filename, 'r')
74  line = fh.readline()
75  while not patterns['ifndef'].search(line):
76  line = fh.readline()
77  if not len(line):
78  fh.close()
79  return False
80 
81  line = fh.readline()
82  fh.close()
83  return patterns['define'].search(line)
84 
85  except subprocess.CalledProcessError as err:
86  return False
87 
88  def convert(self):
89  freadh = open(self.filename, 'r')
90  lines = freadh.readlines()
91  sep = '\r\n' if lines[0].endswith('\r\n') else '\n'
92  freadh.close()
93  fwriteh = open(self.filename , 'w')
94  for l_number in range(1,len(lines)):
95  line = lines[-l_number]
96  if patterns['blank'].search(line):
97  continue
98  elif patterns['endif'].search(line):
99  lines.pop(-l_number)
100  break
101  else:
102  raise SyntaxError('encountered meaningful line after last #endif: \n'+line)
103  define = None
104  done = False
105  for l_number,line in enumerate(lines):
106  if done:
107  fwriteh.write(line)
108  continue
109  if define is None:
110  pattern = patterns['ifndef']
111  else:
112  pattern = patterns['define']
113  match = pattern.search(line)
114  if match:
115  newdefine = match.group(1)
116  if define is None:
117  define = newdefine
118  elif define == newdefine:
119  fwriteh.write('#pragma once' + sep)
120  done = True
121  else:
122  fwriteh.write(line)
123  if define is None:
124  raise SyntaxError('could not find #ifndef')
125  elif define != newdefine:
126  raise SyntaxError('found #ifndef ' + define + ', does not match #define ' + newdefine)
127  fwriteh.close()
128 
129 if __name__ == '__main__':
130  import argparse
131  parser = argparse.ArgumentParser()
132  parser.add_argument('filename', nargs='*')
133  args = parser.parse_args()
134  for filen in args.filename:
135  try:
136  gi = guarded_include(filen)
137  if gi.test_oldstyle_guarded():
138  gi.convert()
139  except SyntaxError as e:
140  print (filen)
141  print (e)