lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <YDvNbbHd2cKXlLme@localhost.localdomain>
Date:   Sun, 28 Feb 2021 20:05:49 +0300
From:   Alexey Dobriyan <adobriyan@...il.com>
To:     torvalds@...ux-foundation.org
Cc:     linux-kernel@...r.kernel.org, akpm@...ux-foundation.org
Subject: [PATCH 11/11] pragma once: conversion script (in Python 2)

>From 2bffcdfec69a8d28e9cb2c535724fbba8e12b820 Mon Sep 17 00:00:00 2001
From: Alexey Dobriyan <adobriyan@...il.com>
Date: Tue, 9 Feb 2021 14:47:34 +0300
Subject: [PATCH 11/11] pragma once: conversion script (in Python 2)

Script accepts list of files to be converted from the command line,
strips include guard if any and inserts "#pragma once" directive in
the beginning.

The following patterns are recognised:

	#ifndef FOO_H		#ifndef FOO_H
	#define FOO_H		#ifndef FOO_H 1

	#endif
	#endif // comment
	#endif /* one line comment */

This is how almost all include guards look like.

Scripts doesn't pretend to be a compiler. For example, comments inside
preprocessor directive aren't recognised because people don't write code
like this:

	# /*
	   * legal C
	   */        def\
	ine FOO /*
		 * no, we don't care
		 */

Trailing multiline comments aren't recognised as well.

Script can cut through SPDX comments:

	/* SPDX-License-Identifier: xxx
	 *	<=== pragma once will be inserted here
	 * Copyright ...
	 */

In other words, the script is simple but not too simple.

It cowardly exits and doesn't do anything as a safety measure in case of
an existing pragma once directive, missing/broken include guard or a bug.
Running it second time shouldn't do anything.

Signed-off-by: Alexey Dobriyan <adobriyan@...il.com>
---
 scripts/pragma-once.py | 159 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)
 create mode 100755 scripts/pragma-once.py

diff --git a/scripts/pragma-once.py b/scripts/pragma-once.py
new file mode 100755
index 000000000000..7c8a274aad28
--- /dev/null
+++ b/scripts/pragma-once.py
@@ -0,0 +1,159 @@
+#!/usr/bin/python2
+# Copyright (c) 2021 Alexey Dobriyan <adobriyan@...il.com>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# Change include guard to "#pragma once" directive in place.
+import os
+import re
+import sys
+
+def read_file(filename):
+    with open(filename) as f:
+        return f.read()
+
+def write_file(filename, buf):
+    tmp = '%s.pragma-once' % filename
+    with open(tmp, 'w') as f:
+        f.write(buf)
+    os.rename(tmp, filename)
+
+def ws(c):
+    return c == ' ' or c == '\t' or c == '\n'
+
+re_ifndef = re.compile('#[ \t]*ifndef[ \t]+([A-Za-z_][A-Za-z0-9_]*)\n')
+re_define = re.compile('#[ \t]*define[ \t]+([A-Za-z_][A-Za-z0-9_]*)([ \t]+1)?\n')
+re_endif1 = re.compile('#[ \t]*endif[ \t]*//')
+re_endif2 = re.compile('#[ \t]*endif[ \t]*/\*')
+
+def pragma_once(c):
+    i = 0
+
+    # skip leading whitespace and comments
+    while i < len(c):
+        if ws(c[i]):
+            i += 1
+        elif c[i] == '/' and c[i + 1] == '*':
+            i = c.index('*/', i + 2) + 2
+        elif c[i] == '/' and c[i + 1] == '/':
+            i = c.index('\n', i + 2) + 1
+        else:
+            break;
+
+    # find #ifndef
+    ifndef_start = i
+    match = re_ifndef.match(c, i)
+    guard = match.group(1)
+    i = match.end()
+
+    # find #define
+    match = re_define.match(c, i)
+    if match.group(1) != guard:
+        raise
+    i = match.end()
+
+    while ws(c[i]):
+        i += 1
+
+    define_end = i
+
+    # trim whitespace before #ifndef
+    i = ifndef_start
+    while i > 0 and ws(c[i - 1]):
+        i -= 1
+    if c[i] == '\n':
+        i += 1
+    ifndef_start = i
+
+    #print repr(c[ifndef_start:define_end])
+
+    # find #endif
+    i = c.rindex('\n#endif', i) + 1
+    endif_start = i
+
+    match = None
+    if match is None:
+        match = re_endif1.match(c, i)
+        if match:
+            try:
+                i = c.index('\n', match.end()) + 1
+            except ValueError:
+                i = len(c)
+
+    if match is None:
+        match = re_endif2.match(c, i)
+        if match:
+            try:
+                i = c.index('*/', match.end()) + 2
+            except ValueError:
+                i = len(c)
+
+    if match is None:
+        i = endif_start + len('#endif')
+
+    while i < len(c) and ws(c[i]):
+        i += 1
+    if i != len(c):
+        raise
+
+    endif_end = i
+
+    # trim whitespace before #endif
+    i = endif_start
+    while i > 0 and ws(c[i - 1]):
+        i -= 1
+    if c[i] == '\n':
+        i += 1
+    endif_start = i
+
+    #print repr(c[endif_start:endif_end])
+
+    if define_end > endif_start:
+        raise
+
+    spdx_end = None
+    pragma_once = '#pragma once\n'
+    cut_comment = False
+    if c.startswith('/* SPDX'):
+        spdx_end = c.index('\n') + 1
+        if not (c[spdx_end - 3] == '*' and c[spdx_end - 2] == '/'):
+            cut_comment = True
+    elif c.startswith('// SPDX') or c.startswith('//SPDX'):
+        spdx_end = c.index('\n') + 1
+
+    if spdx_end is None:
+        l = [pragma_once, c[0:ifndef_start]]
+    elif cut_comment:
+        l = [c[0:spdx_end - 1], ' */\n', pragma_once, '/*\n', c[spdx_end:ifndef_start]]
+    else:
+        l = [c[0:spdx_end], pragma_once, c[spdx_end:ifndef_start]]
+
+    l.append(c[define_end:endif_start])
+    l.append(c[endif_end:])
+    return ''.join(l)
+
+def main():
+    for filename in sys.argv[1:]:
+        s = ''
+        try:
+            buf = read_file(filename)
+            if buf.find('#pragma once') == -1:
+                write_file(filename, pragma_once(buf))
+            else:
+                s = 'skip '
+        except:
+            pass
+        print '#pragma once: %s%s' % (s, filename)
+
+if __name__ == '__main__':
+    main()
-- 
2.29.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ