Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
a66b2d20
Unverified
Commit
a66b2d20
authored
Jan 13, 2018
by
Niels Lohmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
🚨
removed linter warnings for Python code
parent
f4a55f26
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
262 additions
and
248 deletions
+262
-248
CHANGES.md
develop/amalgamate/CHANGES.md
+10
-0
amalgamate.py
develop/amalgamate/amalgamate.py
+252
-248
No files found.
develop/amalgamate/CHANGES.md
0 → 100644
View file @
a66b2d20
The following changes have been made to the code with respect to
<https://github.com/edlund/amalgamate/commit/c91f07eea1133aa184f652b8f1398eaf03586208>
:
-
Resolved inspection results from PyCharm:
-
replaced tabs with spaces
-
added encoding annotation
-
reindented file to remove trailing whitespaces
-
unused import
`sys`
-
membership check
-
made function from
`_is_within`
-
removed unused variable
`actual_path`
develop/amalgamate/amalgamate.py
View file @
a66b2d20
#!/usr/bin/env python
#!/usr/bin/env python
# coding=utf-8
# amalgamate.py - Amalgamate C source and header files.
# amalgamate.py - Amalgamate C source and header files.
# Copyright (c) 2012, Erik Edlund <erik.edlund@32767.se>
# Copyright (c) 2012, Erik Edlund <erik.edlund@32767.se>
...
@@ -37,259 +38,262 @@ import datetime
...
@@ -37,259 +38,262 @@ import datetime
import
json
import
json
import
os
import
os
import
re
import
re
import
sys
class
Amalgamation
(
object
):
class
Amalgamation
(
object
):
# Prepends self.source_path to file_path if needed.
# Prepends self.source_path to file_path if needed.
def
actual_path
(
self
,
file_path
):
def
actual_path
(
self
,
file_path
):
if
not
os
.
path
.
isabs
(
file_path
):
if
not
os
.
path
.
isabs
(
file_path
):
file_path
=
os
.
path
.
join
(
self
.
source_path
,
file_path
)
file_path
=
os
.
path
.
join
(
self
.
source_path
,
file_path
)
return
file_path
return
file_path
# Search included file_path in self.include_paths and
# Search included file_path in self.include_paths and
# in source_dir if specified.
# in source_dir if specified.
def
find_included_file
(
self
,
file_path
,
source_dir
):
def
find_included_file
(
self
,
file_path
,
source_dir
):
search_dirs
=
self
.
include_paths
[:]
search_dirs
=
self
.
include_paths
[:]
if
source_dir
:
if
source_dir
:
search_dirs
.
insert
(
0
,
source_dir
)
search_dirs
.
insert
(
0
,
source_dir
)
for
search_dir
in
search_dirs
:
for
search_dir
in
search_dirs
:
search_path
=
os
.
path
.
join
(
search_dir
,
file_path
)
search_path
=
os
.
path
.
join
(
search_dir
,
file_path
)
if
os
.
path
.
isfile
(
self
.
actual_path
(
search_path
)):
if
os
.
path
.
isfile
(
self
.
actual_path
(
search_path
)):
return
search_path
return
search_path
return
None
return
None
def
__init__
(
self
,
args
):
def
__init__
(
self
,
args
):
with
open
(
args
.
config
,
'r'
)
as
f
:
with
open
(
args
.
config
,
'r'
)
as
f
:
config
=
json
.
loads
(
f
.
read
())
config
=
json
.
loads
(
f
.
read
())
for
key
in
config
:
for
key
in
config
:
setattr
(
self
,
key
,
config
[
key
])
setattr
(
self
,
key
,
config
[
key
])
self
.
verbose
=
args
.
verbose
==
"yes"
self
.
verbose
=
args
.
verbose
==
"yes"
self
.
prologue
=
args
.
prologue
self
.
prologue
=
args
.
prologue
self
.
source_path
=
args
.
source_path
self
.
source_path
=
args
.
source_path
self
.
included_files
=
[]
self
.
included_files
=
[]
# Generate the amalgamation and write it to the target file.
# Generate the amalgamation and write it to the target file.
def
generate
(
self
):
def
generate
(
self
):
amalgamation
=
""
amalgamation
=
""
if
self
.
prologue
:
if
self
.
prologue
:
with
open
(
self
.
prologue
,
'r'
)
as
f
:
with
open
(
self
.
prologue
,
'r'
)
as
f
:
amalgamation
+=
datetime
.
datetime
.
now
()
.
strftime
(
f
.
read
())
amalgamation
+=
datetime
.
datetime
.
now
()
.
strftime
(
f
.
read
())
if
self
.
verbose
:
if
self
.
verbose
:
print
(
"Config:"
)
print
(
"Config:"
)
print
(
" target = {0}"
.
format
(
self
.
target
))
print
(
" target = {0}"
.
format
(
self
.
target
))
print
(
" working_dir = {0}"
.
format
(
os
.
getcwd
()))
print
(
" working_dir = {0}"
.
format
(
os
.
getcwd
()))
print
(
" include_paths = {0}"
.
format
(
self
.
include_paths
))
print
(
" include_paths = {0}"
.
format
(
self
.
include_paths
))
print
(
"Creating amalgamation:"
)
print
(
"Creating amalgamation:"
)
for
file_path
in
self
.
sources
:
for
file_path
in
self
.
sources
:
# Do not check the include paths while processing the source
# Do not check the include paths while processing the source
# list, all given source paths must be correct.
# list, all given source paths must be correct.
actual_path
=
self
.
actual_path
(
file_path
)
# actual_path = self.actual_path(file_path)
print
(
" - processing
\"
{0}
\"
"
.
format
(
file_path
))
print
(
" - processing
\"
{0}
\"
"
.
format
(
file_path
))
t
=
TranslationUnit
(
file_path
,
self
,
True
)
t
=
TranslationUnit
(
file_path
,
self
,
True
)
amalgamation
+=
t
.
content
amalgamation
+=
t
.
content
with
open
(
self
.
target
,
'w'
)
as
f
:
with
open
(
self
.
target
,
'w'
)
as
f
:
f
.
write
(
amalgamation
)
f
.
write
(
amalgamation
)
print
(
"...done!
\n
"
)
print
(
"...done!
\n
"
)
if
self
.
verbose
:
if
self
.
verbose
:
print
(
"Files processed: {0}"
.
format
(
self
.
sources
))
print
(
"Files processed: {0}"
.
format
(
self
.
sources
))
print
(
"Files included: {0}"
.
format
(
self
.
included_files
))
print
(
"Files included: {0}"
.
format
(
self
.
included_files
))
print
(
""
)
print
(
""
)
def
_is_within
(
match
,
matches
):
for
m
in
matches
:
if
match
.
start
()
>
m
.
start
()
and
\
match
.
end
()
<
m
.
end
():
return
True
return
False
class
TranslationUnit
(
object
):
class
TranslationUnit
(
object
):
# // C++ comment.
# // C++ comment.
cpp_comment_pattern
=
re
.
compile
(
r"//.*?\n"
)
cpp_comment_pattern
=
re
.
compile
(
r"//.*?\n"
)
# /* C comment. */
# /* C comment. */
c_comment_pattern
=
re
.
compile
(
r"/\*.*?\*/"
,
re
.
S
)
c_comment_pattern
=
re
.
compile
(
r"/\*.*?\*/"
,
re
.
S
)
# "complex \"stri\\\ng\" value".
# "complex \"stri\\\ng\" value".
string_pattern
=
re
.
compile
(
"[^']"
r'".*?(?<=[^\\])"'
,
re
.
S
)
string_pattern
=
re
.
compile
(
"[^']"
r'".*?(?<=[^\\])"'
,
re
.
S
)
# Handle simple include directives. Support for advanced
# Handle simple include directives. Support for advanced
# directives where macros and defines needs to expanded is
# directives where macros and defines needs to expanded is
# not a concern right now.
# not a concern right now.
include_pattern
=
re
.
compile
(
include_pattern
=
re
.
compile
(
r'#\s*include\s+(<|")(?P<path>.*?)("|>)'
,
re
.
S
)
r'#\s*include\s+(<|")(?P<path>.*?)("|>)'
,
re
.
S
)
# #pragma once
# #pragma once
pragma_once_pattern
=
re
.
compile
(
r'#\s*pragma\s+once'
,
re
.
S
)
pragma_once_pattern
=
re
.
compile
(
r'#\s*pragma\s+once'
,
re
.
S
)
# Search for pattern in self.content, add the match to
# Search for pattern in self.content, add the match to
# contexts if found and update the index accordingly.
# contexts if found and update the index accordingly.
def
_search_content
(
self
,
index
,
pattern
,
contexts
):
def
_search_content
(
self
,
index
,
pattern
,
contexts
):
match
=
pattern
.
search
(
self
.
content
,
index
)
match
=
pattern
.
search
(
self
.
content
,
index
)
if
match
:
if
match
:
contexts
.
append
(
match
)
contexts
.
append
(
match
)
return
match
.
end
()
return
match
.
end
()
return
index
+
2
return
index
+
2
# Return all the skippable contexts, i.e., comments and strings
# Return all the skippable contexts, i.e., comments and strings
def
_find_skippable_contexts
(
self
):
def
_find_skippable_contexts
(
self
):
# Find contexts in the content in which a found include
# Find contexts in the content in which a found include
# directive should not be processed.
# directive should not be processed.
skippable_contexts
=
[]
skippable_contexts
=
[]
# Walk through the content char by char, and try to grab
# Walk through the content char by char, and try to grab
# skippable contexts using regular expressions when found.
# skippable contexts using regular expressions when found.
i
=
1
i
=
1
content_len
=
len
(
self
.
content
)
content_len
=
len
(
self
.
content
)
while
i
<
content_len
:
while
i
<
content_len
:
j
=
i
-
1
j
=
i
-
1
current
=
self
.
content
[
i
]
current
=
self
.
content
[
i
]
previous
=
self
.
content
[
j
]
previous
=
self
.
content
[
j
]
if
current
==
'"'
:
if
current
==
'"'
:
# String value.
# String value.
i
=
self
.
_search_content
(
j
,
self
.
string_pattern
,
i
=
self
.
_search_content
(
j
,
self
.
string_pattern
,
skippable_contexts
)
skippable_contexts
)
elif
current
==
'*'
and
previous
==
'/'
:
elif
current
==
'*'
and
previous
==
'/'
:
# C style comment.
# C style comment.
i
=
self
.
_search_content
(
j
,
self
.
c_comment_pattern
,
i
=
self
.
_search_content
(
j
,
self
.
c_comment_pattern
,
skippable_contexts
)
skippable_contexts
)
elif
current
==
'/'
and
previous
==
'/'
:
elif
current
==
'/'
and
previous
==
'/'
:
# C++ style comment.
# C++ style comment.
i
=
self
.
_search_content
(
j
,
self
.
cpp_comment_pattern
,
i
=
self
.
_search_content
(
j
,
self
.
cpp_comment_pattern
,
skippable_contexts
)
skippable_contexts
)
else
:
else
:
# Skip to the next char.
# Skip to the next char.
i
+=
1
i
+=
1
return
skippable_contexts
return
skippable_contexts
# Returns True if the match is within list of other matches
# Returns True if the match is within list of other matches
def
_is_within
(
self
,
match
,
matches
):
# Removes pragma once from content
for
m
in
matches
:
def
_process_pragma_once
(
self
):
if
match
.
start
()
>
m
.
start
()
and
\
content_len
=
len
(
self
.
content
)
match
.
end
()
<
m
.
end
():
if
content_len
<
len
(
"#include <x>"
):
return
True
return
0
return
False
# Find contexts in the content in which a found include
# Removes pragma once from content
# directive should not be processed.
def
_process_pragma_once
(
self
):
skippable_contexts
=
self
.
_find_skippable_contexts
()
content_len
=
len
(
self
.
content
)
if
content_len
<
len
(
"#include <x>"
):
pragmas
=
[]
return
0
pragma_once_match
=
self
.
pragma_once_pattern
.
search
(
self
.
content
)
while
pragma_once_match
:
# Find contexts in the content in which a found include
if
not
_is_within
(
pragma_once_match
,
skippable_contexts
):
# directive should not be processed.
pragmas
.
append
(
pragma_once_match
)
skippable_contexts
=
self
.
_find_skippable_contexts
()
pragma_once_match
=
self
.
pragma_once_pattern
.
search
(
self
.
content
,
pragmas
=
[]
pragma_once_match
.
end
())
pragma_once_match
=
self
.
pragma_once_pattern
.
search
(
self
.
content
)
while
pragma_once_match
:
# Handle all collected pragma once directives.
if
not
self
.
_is_within
(
pragma_once_match
,
skippable_contexts
):
prev_end
=
0
pragmas
.
append
(
pragma_once_match
)
tmp_content
=
''
for
pragma_match
in
pragmas
:
pragma_once_match
=
self
.
pragma_once_pattern
.
search
(
self
.
content
,
tmp_content
+=
self
.
content
[
prev_end
:
pragma_match
.
start
()]
pragma_once_match
.
end
())
prev_end
=
pragma_match
.
end
()
tmp_content
+=
self
.
content
[
prev_end
:]
# Handle all collected pragma once directives.
self
.
content
=
tmp_content
prev_end
=
0
tmp_content
=
''
# Include all trivial #include directives into self.content.
for
pragma_match
in
pragmas
:
def
_process_includes
(
self
):
tmp_content
+=
self
.
content
[
prev_end
:
pragma_match
.
start
()]
content_len
=
len
(
self
.
content
)
prev_end
=
pragma_match
.
end
()
if
content_len
<
len
(
"#include <x>"
):
tmp_content
+=
self
.
content
[
prev_end
:]
return
0
self
.
content
=
tmp_content
# Find contexts in the content in which a found include
# Include all trivial #include directives into self.content.
# directive should not be processed.
def
_process_includes
(
self
):
skippable_contexts
=
self
.
_find_skippable_contexts
()
content_len
=
len
(
self
.
content
)
if
content_len
<
len
(
"#include <x>"
):
# Search for include directives in the content, collect those
return
0
# which should be included into the content.
includes
=
[]
# Find contexts in the content in which a found include
include_match
=
self
.
include_pattern
.
search
(
self
.
content
)
# directive should not be processed.
while
include_match
:
skippable_contexts
=
self
.
_find_skippable_contexts
()
if
not
_is_within
(
include_match
,
skippable_contexts
):
include_path
=
include_match
.
group
(
"path"
)
# Search for include directives in the content, collect those
search_same_dir
=
include_match
.
group
(
1
)
==
'"'
# which should be included into the content.
found_included_path
=
self
.
amalgamation
.
find_included_file
(
includes
=
[]
include_path
,
self
.
file_dir
if
search_same_dir
else
None
)
include_match
=
self
.
include_pattern
.
search
(
self
.
content
)
if
found_included_path
:
while
include_match
:
includes
.
append
((
include_match
,
found_included_path
))
if
not
self
.
_is_within
(
include_match
,
skippable_contexts
):
include_path
=
include_match
.
group
(
"path"
)
include_match
=
self
.
include_pattern
.
search
(
self
.
content
,
search_same_dir
=
include_match
.
group
(
1
)
==
'"'
include_match
.
end
())
found_included_path
=
self
.
amalgamation
.
find_included_file
(
include_path
,
self
.
file_dir
if
search_same_dir
else
None
)
# Handle all collected include directives.
if
found_included_path
:
prev_end
=
0
includes
.
append
((
include_match
,
found_included_path
))
tmp_content
=
''
for
include
in
includes
:
include_match
=
self
.
include_pattern
.
search
(
self
.
content
,
include_match
,
found_included_path
=
include
include_match
.
end
())
tmp_content
+=
self
.
content
[
prev_end
:
include_match
.
start
()]
tmp_content
+=
"// {0}
\n
"
.
format
(
include_match
.
group
(
0
))
# Handle all collected include directives.
if
found_included_path
not
in
self
.
amalgamation
.
included_files
:
prev_end
=
0
t
=
TranslationUnit
(
found_included_path
,
self
.
amalgamation
,
False
)
tmp_content
=
''
tmp_content
+=
t
.
content
for
include
in
includes
:
prev_end
=
include_match
.
end
()
include_match
,
found_included_path
=
include
tmp_content
+=
self
.
content
[
prev_end
:]
tmp_content
+=
self
.
content
[
prev_end
:
include_match
.
start
()]
self
.
content
=
tmp_content
tmp_content
+=
"// {0}
\n
"
.
format
(
include_match
.
group
(
0
))
if
not
found_included_path
in
self
.
amalgamation
.
included_files
:
return
len
(
includes
)
t
=
TranslationUnit
(
found_included_path
,
self
.
amalgamation
,
False
)
tmp_content
+=
t
.
content
# Make all content processing
prev_end
=
include_match
.
end
()
def
_process
(
self
):
tmp_content
+=
self
.
content
[
prev_end
:]
if
not
self
.
is_root
:
self
.
content
=
tmp_content
self
.
_process_pragma_once
()
self
.
_process_includes
()
return
len
(
includes
)
def
__init__
(
self
,
file_path
,
amalgamation
,
is_root
):
# Make all content processing
self
.
file_path
=
file_path
def
_process
(
self
):
self
.
file_dir
=
os
.
path
.
dirname
(
file_path
)
if
not
self
.
is_root
:
self
.
amalgamation
=
amalgamation
self
.
_process_pragma_once
()
self
.
is_root
=
is_root
self
.
_process_includes
()
self
.
amalgamation
.
included_files
.
append
(
self
.
file_path
)
def
__init__
(
self
,
file_path
,
amalgamation
,
is_root
):
self
.
file_path
=
file_path
actual_path
=
self
.
amalgamation
.
actual_path
(
file_path
)
self
.
file_dir
=
os
.
path
.
dirname
(
file_path
)
if
not
os
.
path
.
isfile
(
actual_path
):
self
.
amalgamation
=
amalgamation
raise
IOError
(
"File not found:
\"
{0}
\"
"
.
format
(
file_path
))
self
.
is_root
=
is_root
with
open
(
actual_path
,
'r'
)
as
f
:
self
.
content
=
f
.
read
()
self
.
amalgamation
.
included_files
.
append
(
self
.
file_path
)
self
.
_process
()
actual_path
=
self
.
amalgamation
.
actual_path
(
file_path
)
if
not
os
.
path
.
isfile
(
actual_path
):
raise
IOError
(
"File not found:
\"
{0}
\"
"
.
format
(
file_path
))
with
open
(
actual_path
,
'r'
)
as
f
:
self
.
content
=
f
.
read
()
self
.
_process
()
def
main
():
def
main
():
description
=
"Amalgamate C source and header files."
description
=
"Amalgamate C source and header files."
usage
=
" "
.
join
([
usage
=
" "
.
join
([
"amalgamate.py"
,
"amalgamate.py"
,
"[-v]"
,
"[-v]"
,
"-c path/to/config.json"
,
"-c path/to/config.json"
,
"-s path/to/source/dir"
,
"-s path/to/source/dir"
,
"[-p path/to/prologue.(c|h)]"
"[-p path/to/prologue.(c|h)]"
])
])
argsparser
=
argparse
.
ArgumentParser
(
argsparser
=
argparse
.
ArgumentParser
(
description
=
description
,
usage
=
usage
)
description
=
description
,
usage
=
usage
)
argsparser
.
add_argument
(
"-v"
,
"--verbose"
,
dest
=
"verbose"
,
choices
=
[
"yes"
,
"no"
],
metavar
=
""
,
help
=
"be verbose"
)
argsparser
.
add_argument
(
"-c"
,
"--config"
,
dest
=
"config"
,
required
=
True
,
metavar
=
""
,
help
=
"path to a JSON config file"
)
argsparser
.
add_argument
(
"-s"
,
"--source"
,
dest
=
"source_path"
,
required
=
True
,
metavar
=
""
,
help
=
"source code path"
)
argsparser
.
add_argument
(
"-p"
,
"--prologue"
,
dest
=
"prologue"
,
required
=
False
,
metavar
=
""
,
help
=
"path to a C prologue file"
)
amalgamation
=
Amalgamation
(
argsparser
.
parse_args
())
amalgamation
.
generate
()
if
__name__
==
"__main__"
:
argsparser
.
add_argument
(
"-v"
,
"--verbose"
,
dest
=
"verbose"
,
main
()
choices
=
[
"yes"
,
"no"
],
metavar
=
""
,
help
=
"be verbose"
)
argsparser
.
add_argument
(
"-c"
,
"--config"
,
dest
=
"config"
,
required
=
True
,
metavar
=
""
,
help
=
"path to a JSON config file"
)
argsparser
.
add_argument
(
"-s"
,
"--source"
,
dest
=
"source_path"
,
required
=
True
,
metavar
=
""
,
help
=
"source code path"
)
argsparser
.
add_argument
(
"-p"
,
"--prologue"
,
dest
=
"prologue"
,
required
=
False
,
metavar
=
""
,
help
=
"path to a C prologue file"
)
amalgamation
=
Amalgamation
(
argsparser
.
parse_args
())
amalgamation
.
generate
()
if
__name__
==
"__main__"
:
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment