from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import os
import re
import time
def tordir_file(fname):
return os.path.normpath(os.path.relpath(fname))
def srcdir_file(tor_fname):
return os.path.normpath(os.path.relpath(tor_fname, 'src'))
def guard_macro(src_fname):
td = src_fname.replace(".", "_").replace("/", "_").upper()
return "TOR_{}".format(td)
def makeext(fname, new_extension):
base = os.path.splitext(fname)[0]
return base + "." + new_extension
def instantiate_template(template, tor_fname):
src_fname = srcdir_file(tor_fname)
names = {
'header_path' : makeext(src_fname, "h"),
'c_file_path' : makeext(src_fname, "c"),
'short_name' : os.path.basename(src_fname),
'this_year' : time.localtime().tm_year,
'guard_macro' : guard_macro(src_fname),
}
return template.format(**names)
HEADER_TEMPLATE = """\
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-{this_year}, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* @file {short_name}
* @brief Header for {c_file_path}
**/
#ifndef {guard_macro}
#define {guard_macro}
#endif /* !defined({guard_macro}) */
"""
C_FILE_TEMPLATE = """\
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-{this_year}, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* @file {short_name}
* @brief DOCDOC
**/
#include "orconfig.h"
#include "{header_path}"
"""
class AutomakeChunk:
pat = re.compile(r'# ADD_C_FILE: INSERT (\S*) HERE', re.I)
def __init__(self):
self.lines = []
self.kind = ""
self.hasBlank = False
def addLine(self, line):
m = self.pat.match(line)
if m:
if self.lines:
raise ValueError("control line not preceded by a blank line")
self.kind = m.group(1)
if line.strip() == "":
self.hasBlank = True
return True
self.lines.append(line)
return False
def insertMember(self, new_tor_fname):
prespace = "\t"
postspace = "\t\t"
for lineno, line in enumerate(self.lines):
m = re.match(r'(\s+)(\S+)(\s+)\\', line)
if not m:
continue
prespace, cur_tor_fname, postspace = m.groups()
if cur_tor_fname > new_tor_fname:
self.insert_before(lineno, new_tor_fname, prespace, postspace)
return
self.insert_at_end(new_tor_fname, prespace, postspace)
def insert_before(self, lineno, new_tor_fname, prespace, postspace):
self.lines.insert(lineno,
"{}{}{}\\\n".format(prespace, new_tor_fname,
postspace))
def insert_at_end(self, new_tor_fname, prespace, postspace):
lastline = self.lines[-1].strip()
self.lines[-1] = '{}{}{}\\\n'.format(prespace, lastline, postspace)
self.lines.append("{}{}\n".format(prespace, new_tor_fname))
def dump(self, f):
for line in self.lines:
f.write(line)
if not line.endswith("\n"):
f.write("\n")
if self.hasBlank:
f.write("\n")
class ParsedAutomake:
def __init__(self):
self.chunks = []
self.by_type = {}
def addChunk(self, chunk):
self.chunks.append(chunk)
self.by_type[chunk.kind.lower()] = chunk
def add_file(self, tor_fname, kind):
if kind.lower() in self.by_type:
self.by_type[kind.lower()].insertMember(tor_fname)
return True
else:
return False
def dump(self, f):
for chunk in self.chunks:
chunk.dump(f)
def get_include_am_location(tor_fname):
src_fname = srcdir_file(tor_fname)
m = re.match(r'^(lib|core|feature|app)/([a-z0-9_]*)/', src_fname)
if m:
return "src/{}/{}/include.am".format(m.group(1),m.group(2))
if re.match(r'^test/', src_fname):
return "src/test/include.am"
return None
def run(fname):
if not os.path.isdir("src"):
raise RuntimeError("Could not find './src/'. "
"Run this script from the top-level tor source "
"directory.")
if not os.path.isfile("src/include.am"):
raise RuntimeError("Could not find './src/include.am'. "
"Run this script from the top-level tor source "
"directory.")
tor_fname = tordir_file(fname)
if tor_fname[:4] != "src/":
raise ValueError("Requested file path '{}' canonicalized to '{}', "
"but the canonical path did not start with 'src/'. "
"Please add files to the src directory."
.format(fname, tor_fname))
c_tor_fname = makeext(tor_fname, "c")
h_tor_fname = makeext(tor_fname, "h")
if os.path.exists(c_tor_fname):
print("{} already exists".format(c_tor_fname))
return 1
if os.path.exists(h_tor_fname):
print("{} already exists".format(h_tor_fname))
return 1
with open(c_tor_fname, 'w') as f:
f.write(instantiate_template(C_FILE_TEMPLATE, c_tor_fname))
with open(h_tor_fname, 'w') as f:
f.write(instantiate_template(HEADER_TEMPLATE, h_tor_fname))
iam = get_include_am_location(c_tor_fname)
if iam is None or not os.path.exists(iam):
print("Made files successfully but couldn't identify include.am for {}"
.format(c_tor_fname))
return 1
amfile = ParsedAutomake()
cur_chunk = AutomakeChunk()
with open(iam) as f:
for line in f:
if cur_chunk.addLine(line):
amfile.addChunk(cur_chunk)
cur_chunk = AutomakeChunk()
amfile.addChunk(cur_chunk)
amfile.add_file(c_tor_fname, "sources")
amfile.add_file(h_tor_fname, "headers")
with open(iam+".tmp", 'w') as f:
amfile.dump(f)
os.rename(iam+".tmp", iam)
if __name__ == '__main__':
import sys
sys.exit(run(sys.argv[1]))