📄 archive.py
字号:
# -*- python -*-
# Copyright (c) 2005 Intel Corporation
# All rights reserved.
#
# This file is distributed under the terms in the attached INTEL-LICENSE
# file. If you do not find these files, copies can be found by writing to
# Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
# 94704. Attention: Intel License Inquiry.
# Archive nesdoc information from a given compilation in a nesdoc repository.
#
# A nesdoc repository is a directory containing separate XML files for each
# known interface and component (in the "interfaces" and "components"
# subdirectories respectively). These files have basically the same format
# as a single interfacedef and component element from the nesC XML dump
# format, with the following changes:
# - all "interfacedef", "interfacedef-ref", "component" and "component-ref"
# elements have an extra "nicename" attribute which stores the full
# `package name' for the corresponding element (see below for details)
# - components have two extra sub-elements:
# o "specification": a list of the "interface" and "function"
# elements that form the components specification
# o "referenced": the "interface" and "function" elements referenced
# from the wiring graph
# the "component" elements referenced from these "interface" and
# "function" elements
# (but the "referenced" list excludes self-references, i.e., the
# component itself and the "interface" and "function" elements
# already found in "specification")
# A `package name' is a component or interface name prefixed with its path
# relative to a set of "top directories", and with path separators replaced
# by dots. The root of a TinyOS installation is usually the single top
# directory, but more can be specified with the -topdir option.
from xml.dom import *
from xml.dom.minidom import *
from sys import *
from getopt import getopt
from string import *
from nesdoc.utils import *
from nesdoc.graph import generate_graph
from nesdoc.html import *
import os
def check(x):
if not x:
print "%s is not a nesC documentation file" % argv[1]
exit(2)
return x
def get1(x, tag):
return check(xml_tagfind(x, tag))
def usage():
print "Usage: %s [-t dir] [--topdir dir] [--preserve] [--app] [--quiet] repository" % argv[0]
print " where -t/--topdir specify prefixes to remove from file names"
print " to create nice, package-like names for interface and components"
print " (based on their full filename)."
print " If --preserve is specified, existing XML files are preserved."
print " If --app is specified, a page for this application is created in the"
print " current directory."
print " If --quiet is specified, the program is less verbose."
print " The XML input is read from stdin."
# Return package name for elem, or None if no valid name is found
# (i.e., if the element's file name does not match any known topdir)
def packagename(elem):
loc = elem.getAttribute("loc")
colon = index(loc, ":")
filename = canonicalise(loc[colon + 1:])
for dir in topdir:
dirlen = len(dir)
if filename[0:dirlen] == dir:
filename = filename[dirlen:]
break
if filename[0] == "/":
return None
else:
return replace(replace(filename, ".nc", ""), "/", ".")
# simplify file names (for generating package names, so no need to
# preserve path validity):
# empty strings become ./
# windows paths are made unix-like:
# c: becomes /c/
# all \ become /
def canonicalise(name):
if name == "":
name = "."
if (name[1:2] == ":"): # windows disk names
name = "/%s/%s" %(name[0], name[2:])
name = replace(name, "\\", "/")
return name
# canonicalise a directory. like canonicalise, but ensures
# there is trailing /
def canonicalisedir(dirname):
dirname = canonicalise(dirname)
if dirname[-1] != "/":
return dirname + "/"
else:
return dirname
# option processing. See usage string for details.
def process_opts(argv):
options = {
"topdir": (True, lambda (x): topdir + [canonicalisedir(x)]),
"preserve": (False, lambda x: True),
"app": (False, lambda x: True),
"quiet": (False, lambda x: True),
}
getopt_args = []
for p in options:
globals()[p] = False
opt = p
if options[p][0]:
opt += "="
getopt_args += [ opt ]
(opts, args) = getopt(argv, "", getopt_args)
topdir = []
highlight = ""
for o, a in opts:
opt = o[2:]
globals()[opt] = options[opt][1](a)
return args
args = process_opts(argv[1:])
if len(args) != 1:
usage()
exit(2)
repository = args[0]
try:
dom = parse(stdin)
except xml.parsers.expat.ExpatError:
nfail("nesdoc failed: no valid input")
creator = xml.dom.minidom.getDOMImplementation()
check(dom.documentElement.tagName == "nesc")
interfacedefs = get1(dom, "interfacedefs")
components = get1(dom, "components")
interfaces = get1(dom, "interfaces")
functions = get1(dom, "functions")
# index everything
refidx = {}
qnameidx = {}
for x in interfaces.getElementsByTagName("interface"):
refidx[x.getAttribute("ref")] = x
for x in functions.getElementsByTagName("function"):
refidx[x.getAttribute("ref")] = x
for x in components.getElementsByTagName("component"):
qnameidx[x.getAttribute("qname")] = x
for x in interfacedefs.getElementsByTagName("interfacedef"):
qnameidx[x.getAttribute("qname")] = x
# collect specification elements by component
speclist = {}
# interfaces
for x in interfaces.getElementsByTagName("interface"):
incomponent = get1(x, "component-ref").getAttribute("qname")
if speclist.has_key(incomponent):
speclist[incomponent].append(x)
else:
speclist[incomponent] = [x]
# and bare commands, events
for x in functions.getElementsByTagName("function"):
# hack: tasks don't show up with a command/event attribute
# don't include commands/events from interfaces
if (x.hasAttribute("event") or x.hasAttribute("command")) and (not xml_tag(x, "interface-ref")):
incomponent = get1(x, "component-ref").getAttribute("qname")
if speclist.has_key(incomponent):
speclist[incomponent].append(x)
else:
speclist[incomponent] = [x]
# add nicename (i.e., with package prefix) attributes to all interfacedef,
# interfacedef-ref, component and component-ref elements
nicenames = {}
def define_nicename(x):
name = x.getAttribute("qname")
nicename = packagename(x)
if nicename == None:
nicename = name
nicenames[name] = nicename
def set_nicename(x):
x.setAttribute("nicename", nicenames[x.getAttribute("qname")])
for x in interfacedefs.getElementsByTagName("interfacedef"):
define_nicename(x)
set_nicename(x)
for x in components.getElementsByTagName("component"):
define_nicename(x)
set_nicename(x)
for x in dom.getElementsByTagName("interfacedef-ref"):
set_nicename(x)
for x in dom.getElementsByTagName("component-ref"):
set_nicename(x)
# Do the app stuff if requested
if app:
# The firt component is the main application component.
toplevel = xml_idx(components, 0)
name = toplevel.getAttribute("qname")
nicename = toplevel.getAttribute("nicename")
wiring = xml_tag(xml_tag(dom, "nesc"), "wiring")
generate_graph(".", repository, dom, wiring, name, nicename)
ht = Html("%s.html" % nicename)
ht.title("Application: " + nicename)
ht.body()
ht.push("h2");
ht.p("Application: " + nicename)
ht.popln();
ht.pushln("map", 'name="comp"')
cmap = file("%s.cmap" % nicename)
for line in cmap.readlines():
ht.pln(line)
cmap.close()
ht.popln()
ht.tag("img", 'src="%s.png"' % nicename, 'usemap="#comp"', 'id=imgwiring')
ht.close()
# save xml information per-interface and per-component in the specified
# repository
nmkdir(repository)
chdir(repository)
nmkdir("interfaces")
nmkdir("components")
# save interface definitions
for x in interfacedefs.getElementsByTagName("interfacedef"):
name = x.getAttribute("qname")
nicename = x.getAttribute("nicename")
filename = "interfaces/%s.xml" % nicename
if preserve and os.path.exists(filename):
continue
if not quiet:
print "interface %s (%s)" % (name, nicename)
doc = creator.createDocument(None, None, None)
copy = x.cloneNode(True)
doc.appendChild(copy)
ifile = file(filename, "w")
doc.writexml(ifile)
doc.unlink()
ifile.close()
# save component definitions, excluding instantiations
for x in components.getElementsByTagName("component"):
if len(x.getElementsByTagName("instance")) == 0:
# not an instance
name = x.getAttribute("qname")
nicename = x.getAttribute("nicename")
filename = "components/%s.xml" % nicename
if preserve and os.path.exists(filename):
continue
if not quiet:
print "component %s (%s)" % (name, nicename)
doc = creator.createDocument(None, None, None)
# copy component and create its specification
copy = x.cloneNode(True)
spec = dom.createElement("specification")
copy.appendChild(spec)
try:
for intf in speclist[name]:
spec.appendChild(intf.cloneNode(True))
except KeyError:
0
# collect information used in wiring graph
allelems = {}
allcomps = {}
def addelem(wireref):
actualref = xml_tagset(wireref, ["interface-ref", "function-ref"])
elemref = actualref.getAttribute("ref")
elem = refidx[elemref]
compname = xml_tag(elem, "component-ref").getAttribute("qname")
# exclude self-references, those are in the specification already
if compname != name:
allelems[elemref] = True
allcomps[compname] = True
for wireref in x.getElementsByTagName("from"): addelem(wireref)
for wireref in x.getElementsByTagName("to"): addelem(wireref)
# create the referenced element which will store the wiring information
refd = dom.createElement("referenced")
copy.appendChild(refd)
for ref in allelems.keys():
refd.appendChild(refidx[ref].cloneNode(True))
for qname in allcomps.keys():
refd.appendChild(qnameidx[qname].cloneNode(True))
doc.appendChild(copy)
ifile = file(filename, "w")
doc.writexml(ifile)
doc.unlink()
ifile.close()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -