#!/usr/bin/env python

import argparse
import os


def preprocess(path):
    includes = set()
    res = []

    def preprocess_line(path, line):
        if line.strip().startswith('//'):
            return ''
        elif line.strip().startswith('#'):
            line = line.strip()
            if line.startswith('#include') and len(line.split('"')) >= 3:
                lx = line.split('"')
                relpath = ''.join(lx[1:len(lx) - 1])
                target_path = os.path.dirname(path) + '/' + relpath
                if target_path.startswith('/'):
                    target_path = target_path[1:]
                preprocess_path(os.path.normpath(target_path))
                return '\n'
            elif line.startswith('#pragma'):
                if ''.join(line.split(' ')[1:]).strip() == 'once':
                    return ''
        return line

    def preprocess_path(path):
        if path not in includes:
            has_not_started = True
            includes.add(path)

            for line in open(path):
                s = preprocess_line(path, line)
                if has_not_started and s.strip() is not "":
                    prefix = '// ===== {} =====\n\n'.format(os.path.basename(path))
                    res.append(prefix)
                    has_not_started = False
                res.append(s.rstrip())

    preprocess_path(path)
    print('\n'.join(res))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('filepath', nargs=1, help='cpp file')
    args = parser.parse_args()
    filepath = args.filepath[0]
    preprocess(filepath)

@@ -78,16 +78,20 @@
 includes
+_set
  = set()
@@ -95,19 +95,29 @@
 t()%0A    
-res
+includes_list
  = %5B%5D%0A%0A 
@@ -127,34 +127,30 @@
 def 
-preproces
+get_include
 s_li
-ne
+st
 (path
-, line
 ):%0A 
@@ -163,60 +163,79 @@
  if 
-line.strip().startswith('//'):%0A            return ''
+path in includes_set:%0A            return%0A        includes_set.add(path)
 %0A   
@@ -243,40 +243,29 @@
     
-elif
+for
  line
-.strip().startswith('#'
+ in open(path
 ):%0A 
@@ -389,78 +389,45 @@
     
-lx = line.split('%22')%0A                relpath = ''.join(lx%5B1:len(lx) - 
+relpath = ''.join(line.split('%22')%5B1:-
 1%5D)%0A
@@ -608,31 +608,33 @@
         
-preprocess_path
+get_includes_list
 (os.path
@@ -669,45 +669,107 @@
     
-        return '%5Cn'%0A            elif 
+includes_list.append(path)%0A%0A    def ignore_line(line):%0A        line = line.strip()%0A        return (
 line
@@ -785,18 +785,15 @@
 th('
-#pragma'):
+//') or
 %0A   
@@ -809,17 +809,43 @@
     
-if ''.joi
+(line.startswith('#include') and le
 n(li
@@ -858,138 +858,150 @@
 it('
- ')%5B1:%5D).strip() == 'once':%0A                    return ''%0A        return line%0A%0A    def preprocess_path(path):%0A        if
+%22')) %3E= 3) or%0A                line.split(' ') == %5B'#pragma', 'once'%5D)%0A%0A    def print_includes_list():%0A        code_list = %5B%5D%0A        for
  path 
-not 
 in i
@@ -1007,16 +1007,21 @@
 includes
+_list
 :%0A      
@@ -1030,98 +1030,109 @@
     
-has_not_started = True%0A            includes.add(path)%0A%0A            for line in open
+code_list.append('')%0A            code_list.append('// ===== %7B%7D ====='.format(os.path.basename
 (path)
-:
+))
 %0A   
@@ -1144,361 +1144,348 @@
     
-    s = preprocess_line(path, line)%0A                if has_not_started and s.strip() is
+code_list.append('')%0A            code_list += %5B_ for _ in open(path) if
  not 
-%22%22:%0A                    prefix = '// ===== %7B%7D =====%5Cn%5Cn'.format(os.path.basename(path))%0A                    res.append(prefix)%0A                    has_not_started = False%0A                res.append(s.rstrip())%0A%0A    preprocess_path(path)%0A    print('%5Cn'.join(res)
+ignore_line(_)%5D%0A        res = ''%0A        for s, prev in zip(code_list, %5B''%5D + code_list):%0A            if s.strip() != '' or prev.strip() != '':%0A                res += s.rstrip() + '%5Cn'%0A        return res%0A%0A    get_includes_list(path)%0A    return print_includes_list(
 )%0A%0A%0A
@@ -1679,16 +1679,22 @@
 %5B0%5D%0A    
+print(
 preproce
@@ -1701,13 +1701,14 @@
 ss(filepath)
+)
 %0A

Fix preprocessor