\par Fields:
\ref EthernetPacketParser
+ \image html EthernetPacket.png
\par Associated registries:
\ref EtherTypes
\par Fields:
\ref EthVLanPacketParser
-
+ \image html EthVLanPacket.png
+
\par Associated registries:
\ref EtherTypes
// ICMP type registry
typedef boost::uint16_t key_t;
};
-
+
+ /** \brief ICMP Packet for IPv6
+
+ \par Packet type (typedef):
+ \ref ICMPv6Packet
+
+ \par Fields:
+ \ref ICMPv6PacketParser
+ \image html ICMPv6Packet.png
+
+ \par Associated registries:
+ \ref ICMPTypes
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6PacketType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6PacketType, ICMPTypes>
}
#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
+// End:
+ss
SENF_PARSER_FINALIZE ( ICMPv6EchoRequestParser );
};
+ /** \brief ICMPv6 Echo Request
+
+ \par Packet type (typedef):
+ \ref ICMPv6EchoRequest
+
+ \par Fields:
+ \ref ICMPv6EchoRequestParser
+ \image html ICMPv6EchoRequest.png
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6EchoRequestType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6EchoRequestType>
SENF_PARSER_FINALIZE ( ICMPv6EchoReplyParser );
};
+ /** \brief ICMPv6 Echo Reply
+
+ \par Packet type (typedef):
+ \ref ICMPv6EchoReply
+
+ \par Fields:
+ \ref ICMPv6EchoReplyParser
+ \image html ICMPv6EchoReply.png
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6EchoReplyType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6EchoReplyType>
SENF_PARSER_FINALIZE ( ICMPv6ErrDestUnreachableParser );
};
+ /** \brief ICMPv6 Destination unreachable
+
+ \par Packet type (typedef):
+ \ref ICMPv6ErrDestUnreachable
+
+ \par Fields:
+ \ref ICMPv6ErrDestUnreachableParser
+ \image html ICMPv6ErrDestUnreachable.png
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6ErrDestUnreachableType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6ErrDestUnreachableType>
SENF_PARSER_FINALIZE ( ICMPv6ErrTooBigParser );
};
+ /** \brief ICMPv6 Packet to big
+
+ \par Packet type (typedef):
+ \ref ICMPv6ErrTooBig
+
+ \par Fields:
+ \ref ICMPv6ErrTooBigParser
+ \image html ICMPv6ErrTooBig.png
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6ErrTooBigType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6ErrTooBigType>
SENF_PARSER_FINALIZE ( ICMPv6ErrTimeExceededParser );
};
+ /** \brief ICMPv6 Time exceeded
+
+ \par Packet type (typedef):
+ \ref ICMPv6ErrTimeExceeded
+
+ \par Fields:
+ \ref ICMPv6ErrTimeExceededParser
+ \image html ICMPv6ErrTimeExceeded.png
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6ErrTimeExceededType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6ErrTimeExceededType>
SENF_PARSER_FINALIZE ( ICMPv6ErrParamProblemParser );
};
+ /** \brief ICMPv6 Parameter problem
+
+ \par Packet type (typedef):
+ \ref ICMPv6ErrParamProblem
+
+ \par Fields:
+ \ref ICMPv6ErrParamProblemParser
+ \image html ICMPv6ErrParamProblem.png
+
+ \ingroup protocolbundle_default
+ */
struct ICMPv6ErrParamProblemType
: public PacketTypeBase,
public PacketTypeMixin<ICMPv6ErrParamProblemType>
}
};
+ /** \brief MLDv2 Listener query
+
+ \par Packet type (typedef):
+ \ref MLDv2ListenerQuery
+
+ \par Fields:
+ \ref MLDv2ListenerQueryParser
+ \image html MLDv2ListenerQuery.png
+
+ \ingroup protocolbundle_default
+ */
struct MLDv2ListenerQueryType
: public PacketTypeBase,
public PacketTypeMixin<MLDv2ListenerQueryType>
}
};
+ /** \brief MLDv2 Listener report
+
+ \par Packet type (typedef):
+ \ref MLDv2ListenerReport
+
+ \par Fields:
+ \ref MLDv2ListenerReportParser
+ \image html MLDv2ListenerReport.png
+ \image html MLDv2AddressRecord.png
+
+ \ingroup protocolbundle_default
+ */
struct MLDv2ListenerReportType
: public PacketTypeBase,
public PacketTypeMixin<MLDv2ListenerReportType>
}
#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// comment-column: 40
+// End:
Set \a protocol from type of next packet if found in \ref IpTypes\n
Calculate \a checksum
+ \image html IPv4Packet.png
+
\ingroup protocolbundle_default
*/
struct IPv4PacketType
\par Finalize action:
Set \a nextHeader from type of next packet if found in \ref IpTypes
+ \image html IPv6Extensions_Fragment.png
+
\ingroup protocolbundle_default
*/
struct IPv6ExtensionType_Fragment
Set \a length from payload size\n
Set \a nextHeader from type of next packet if found in \ref IpTypes
+ \image html IPv6Packet.png
+
\ingroup protocolbundle_default
*/
struct IPv6PacketType
\par Finalize action:
XXXX
+ \image html LlcSnapPacket.png
+
\ingroup protocolbundle_default
*/
struct LlcSnapPacketType
Set \a length from payload size\n
Calculate \a checksum
+ \image html UDPPacket.png
+
\ingroup protocolbundle_default
*/
struct UDPPacketType
You will normally not instantiate ListParser directly, you will use the \ref
SENF_PARSER_LIST() helper macro.
- \see ExampleListPolicy
+ Some basic list access methods are defined as parser members. To access the complete list
+ API however you will need to instantiate a container wrapper for the list. See \ref
+ packet_usage_fields_collection.
+
+ \see
+ \ref How to access \ref packet_usage_fields_collection
+ SENF_PARSER_LIST() macro used to define list fields \n
+ ListParser_Container list container wrapper API \n
+ ExampleListPolicy
+
\ingroup parsecollection
*/
template <class ListPolicy>
\param[in] size name of field giving the list size
\param[in] elt_type list element type
+ \see
+ How to use \ref packet_usage_fields_collection \n
+ senf::ListParser the list parser API for list field access
+ senf::ListParser_Container the list parser container API for list field access
+
\hideinitializer
\ingroup packetparsermacros
*/
{
# include SENF_PARSER()
- SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser );
- SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser );
+ SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser ); //<pkgdraw: hide
+ SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser ); //<pkgdraw: hide
SENF_PARSER_VECTOR( fbips, fbipCount_, INet4AddressParser );
{
# include SENF_PARSER()
- SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser );
- SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser );
+ SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser ); //<pkgdraw: hide
+ SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser ); //<pkgdraw: hide
SENF_PARSER_VECTOR( fbips, fbipCount_, INet6AddressParser );
Parser implementing the DTCP packet according to RFC 3077
- \see DTCPPacketType
+ \see DTCPHelloPacketType
*/
struct DTCPHelloPacketParser : public PacketParserBase
{
# include SENF_PARSER()
+ //>pkgdraw: name=vers
SENF_PARSER_BITFIELD ( versionNumber, 4, unsigned ); // must be 1
- SENF_PARSER_BITFIELD ( command, 4, unsigned );
+ SENF_PARSER_BITFIELD ( command, 4, unsigned ); //<pkgdraw: name=cmd
enum Command { JOIN=1, LEAVE=2 };
SENF_PARSER_FIELD ( interval, UInt8Parser ); // should be 5
SENF_PARSER_FIELD ( sequenceNumber, UInt16Parser );
- SENF_PARSER_PRIVATE_BITFIELD ( reserved0_, 3, unsigned );
+ SENF_PARSER_PRIVATE_BITFIELD ( reserved0_, 3, unsigned ); //<pkgdraw: name=
SENF_PARSER_BITFIELD ( receiveCapableFeed, 1, bool );
SENF_PARSER_BITFIELD_RO ( ipVersion, 4, unsigned ); // 4=IPv4, 6=IPv6
SENF_PARSER_FIELD ( tunnelProtocol, UInt8Parser );
SENF_PARSER_FIELD_RO ( fbipCount, UInt8Parser );
+ //>pkgdraw: name=
SENF_PARSER_PRIVATE_FIELD ( reserved1_, UInt8Parser ); // must be zero
// Go back to fbipCount so the variant has access to that field
\par Fields:
\ref DTCPHelloPacketParser
+ \image html DTCPPacket.png
+
\ingroup protocolbundle_mpegdvb
*/
struct DTCPHelloPacketType
invalidate the wrapper if it changes the packets size.
\see
- senf::VectorParser_Container Interface of the vector parser container wrapper \n
- senf::ListParser_Container Interface of the list parser container wrapper
+ senf::VectorParser / senf::VectorParser_Container Interface of the vector parser \n
+ senf::ListParser / senf::ListParser_Container Interface of the list parser
\subsubsection packet_usage_collection_variant The Variant Parser
SENFSCons.Lib(env, sources)
SENFSCons.Doxygen(env, extra_sources = [
env.Dia2Png("structure.dia"),
- env.Dia2Png("MPEGDVBBundle/TLV.dia")
+ env.Dia2Png("MPEGDVBBundle/TLV.dia"),
+ env.PkgDraw("MPEGDVBBundle/DTCPPacket.hh"),
+ env.PkgDraw("DefaultBundle/EthernetPacket.hh",
+ PKGDRAWPACKETS = "EthernetPacketParser"),
+ env.PkgDraw("DefaultBundle/EthVLanPacket.png", "DefaultBundle/EthernetPacket.hh",
+ PKGDRAWPACKETS = "EthVLanPacketParser"),
+ env.PkgDraw("DefaultBundle/IPv4Packet.hh"),
+ env.PkgDraw("DefaultBundle/IPv6Packet.hh"),
+ env.PkgDraw("DefaultBundle/LlcSnapPacket.hh"),
+ env.PkgDraw("DefaultBundle/UDPPacket.hh"),
+ env.PkgDraw("DefaultBundle/IPv6Extensions_Fragment.png", "DefaultBundle/IPv6Extensions.hh",
+ PKGDRAWPACKETS = "IPv6PacketParserExtension_Fragment"),
+ env.PkgDraw("DefaultBundle/ICMPv6Packet.hh"),
+ env.PkgDraw("DefaultBundle/ICMPv6EchoRequest.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "ICMPv6EchoRequestParser"),
+ env.PkgDraw("DefaultBundle/ICMPv6EchoReply.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "ICMPv6EchoReplyParser"),
+ env.PkgDraw("DefaultBundle/ICMPv6ErrDestUnreachable.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "ICMPv6ErrDestUnreachableParser"),
+ env.PkgDraw("DefaultBundle/ICMPv6ErrTooBig.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "ICMPv6ErrTooBigParser"),
+ env.PkgDraw("DefaultBundle/ICMPv6ErrTimeExceeded.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "ICMPv6ErrTimeExceededParser"),
+ env.PkgDraw("DefaultBundle/ICMPv6ErrParamProblem.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "ICMPv6ErrParamProblemParser"),
+ env.PkgDraw("DefaultBundle/MLDv2ListenerQuery.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "MLDv2ListenerQueryParser"),
+ env.PkgDraw("DefaultBundle/MLDv2ListenerReport.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "MLDv2ListenerReportParser"),
+ env.PkgDraw("DefaultBundle/MLDv2AddressRecord.png", "DefaultBundle/ICMPv6TypePacket.hh",
+ PKGDRAWPACKETS = "MLDv2AddressRecordParser"),
])
SENFSCons.InstallIncludeFiles(env, includes)
VectorParser makes use of a policy template argument, \a AuxPolicy, to customize the way the
containers size is obtained. You will normally not instantiate VectorParser directly, you
will use the \ref SENF_PARSER_VECTOR() helper macro.
+
+ Some basic vector access methods are defined as parser members. To access the complete list
+ API however you will need to instantiate a container wrapper for the vector. See \ref
+ packet_usage_fields_collection.
+ \see
+ \ref How to access \ref packet_usage_fields_collection \n
+ SENF_PARSER_VECTOR() macro used to define vector fields \n
+ VectorParser_Container vector container wrapper API
+
\ingroup parsecollection
*/
template <class ElementParser, class AuxPolicy>
\param[in] size name of field giving the vector size
\param[in] elt_type vector element type
+ \see
+ How to use \ref packet_usage_fields_collection \n
+ senf::VectorParser the vector parser API for vector field access
+ senf::VectorParser_Container the vector parser container API for vector field access
+
\hideinitializer
\ingroup packetparsermacros
*/
--- /dev/null
+#!/usr/bin/python
+
+import sys, re, signal, tempfile, os, os.path, shutil, atexit
+
+basedir=os.path.abspath(os.path.split(sys.argv[0])[0])
+
+charsPerBit = 1.4
+
+TEX_HEADER = r"""\documentclass{scrartcl}
+\usepackage[german]{babel}
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{ae,aecompl}
+\usepackage[active]{srcltx}
+
+\usepackage{color}
+\usepackage{bytefield}
+
+\pagestyle{empty}
+
+\begin{document}
+\sffamily
+"""
+
+PACKET_HEADER=r"""\begin{bytefield}{32}
+ \bitheader{0-31} \\
+"""
+
+PACKET_FOOTER=r"""\end{bytefield}
+\bigskip
+
+"""
+
+TEX_FOOTER = r"""\end{document}
+"""
+
+def formatField(width, start, size):
+ areas = []
+ sz = width - start
+ while size > 0:
+ if sz > size:
+ areas.append({'start': start,
+ 'size': size})
+ size = 0
+ else:
+ areas.append({'start': start,
+ 'size': sz})
+ size -= sz
+ sz = width
+ start = 0
+ for i in range(len(areas)-1):
+ if areas[i]['start'] < areas[i+1]['start']+areas[i+1]['size']:
+ areas[i]['bottom'] = False
+ areas[i+1]['top'] = False
+ return areas
+
+def formatSimpleField(width, start, field):
+ areas = formatField(width, start, field['size'])
+ nameix = 0
+ namesz = 0
+ for i in range(len(areas)):
+ if areas[i]['size'] > namesz:
+ namesz = areas[i]['size']
+ nameix = i
+ areas[nameix]['name'] = field['name'][:int(areas[nameix]['size'] * charsPerBit)]
+ if len(areas) == 2 and areas[0].get('bottom',True):
+ if areas[0].get('name','') : ix = 1
+ else : ix = 0
+ if 6 <= int(areas[ix]['size'] * charsPerBit):
+ areas[ix]['name'] = '(cont)'
+ return areas
+
+def formatPacket(width, fields):
+ rows = [ [] ]
+ start = 0
+ for field in fields:
+ areas = []
+ if field.get('repeat', False):
+ if start > 0 and start < width:
+ areas.append({ 'start': start, 'size': width-start, 'bottom': False,
+ 'right': False})
+ start = 0
+ if field.get('size',None):
+ areas.extend(formatSimpleField(width, start, field))
+ start = areas[-1]['start'] + areas[-1]['size']
+ elif field.get('minsize', None):
+ f = dict(field)
+ f['size'] = field['minsize']
+ areas.extend(formatSimpleField(width, start, f))
+ start = areas[-1]['start'] + areas[-1]['size']
+ if start >= width : start = 0
+ addareas = formatField(width, start, field['maxsize'] - field['minsize'])
+ for area in addareas:
+ area['filled'] = True
+ areas += addareas
+ start = areas[-1]['start'] + areas[-1]['size']
+ if start > 0 and start < width:
+ areas.append({ 'start': start, 'size': width-start, 'bottom': False,
+ 'right': False})
+ start = 0
+ else:
+ if start > 0 and start < width:
+ areas.append({ 'start': start, 'size': width-start, 'bottom': False,
+ 'right': False})
+ areas.extend([ { 'start': 0, 'size': width, 'bottom': False,
+ 'name': field['name'] },
+ { 'start': 0, 'size': width, 'skip': True },
+ { 'start': 0, 'size': width, 'top': False } ])
+ start = 0
+ if field.get('repeat'):
+ if start > 0 and start < width:
+ areas.append({ 'start': start, 'size': width-start, 'bottom': False,
+ 'right': False})
+ start = 0
+ areas.append({ 'start': 0, 'size': width, 'dots': True })
+ da = areas[(areas[0].get('right', True) and (0,) or (1,))[0]:-1]
+ for i in range(len(da)):
+ if da[i].get('name','') :
+ da[i] = dict(da[i])
+ del da[i]['name']
+ areas.extend(da)
+ if start == width : start = 0
+
+ while areas:
+ while areas and (not(rows[-1]) or rows[-1][-1]['start'] + rows[-1][-1]['size'] < width):
+ if areas[0].get('right', True) == False:
+ # This is a fillup field. Check, wether to draw top:
+ if len(rows) <= 1:
+ areas[0]['top'] = False
+ elif rows[-2][-1].get('bottom', True):
+ areas[0]['top'] = False
+ rows[-1].append(areas.pop(0))
+ if areas:
+ rows.append([])
+ return rows
+
+def texquote(s):
+ s = s.replace('_', '\\_')
+ return s
+
+def makeTex(rows):
+ lines = []
+ for row in rows:
+ line = []
+ for area in row:
+ sides=""
+ if area.get('left', True) : sides += "l"
+ if area.get('right', True) : sides += "r"
+ if area.get('top', True) : sides += "t"
+ if area.get('bottom', True) : sides += "b"
+ if sides == "lrtb" : sides = ""
+ else : sides = "[%s]" % sides
+ if area.get('filled', False):
+ line.append(r"\bitbox%s{%s}{\color[gray]{0.7}\rule{\width}{\height}}" % (sides, area['size']))
+ elif area.get('skip', False):
+ line.append(r"\skippedwords")
+ elif area.get('dots', False):
+ line.append(r"\wordbox[]{1}{$\vdots$\\[1ex]}")
+ else:
+ line.append(r"\bitbox%s{%s}{\strut %s}"
+ % (sides, area['size'], texquote(area.get('name',''))))
+ lines.append(" & ".join(line))
+ return " \\\\\n".join(lines) + "\n"
+
+FIELD_TYPES = {
+ 'UInt8Parser' : {'size': 8 },
+ 'UInt16Parser' : {'size': 16 },
+ 'UInt24Parser' : {'size': 24 },
+ 'UInt32Parser' : {'size': 32 },
+ 'UInt64Parser' : {'size': 64 },
+ 'Int8Parser' : {'size': 8 },
+ 'Int16Parser' : {'size': 16 },
+ 'Int24Parser' : {'size': 24 },
+ 'Int32Parser' : {'size': 32 },
+ 'Int64Parser' : {'size': 64 },
+ 'MACAddressParser': {'size': 48 },
+ 'INet4AddressParser' : {'size': 32 },
+ 'INet6AddressParser' : {'size': 128 },
+ }
+
+def parse_FIELD(args, flags):
+ args = [ arg.strip() for arg in args.split(',') ]
+ if len(args) != 2:
+ sys.stderr.write("Failed to parse FIELD: %s" % args)
+ return None
+ field = dict(FIELD_TYPES.get(args[1].split(':')[-1], {}))
+ field['name'] = args[0]
+ return field
+
+def parse_PRIVATE_FIELD(args, flags):
+ return parse_FIELD(args, flags)
+
+def parse_FIELD_RO(args, flags):
+ return parse_FIELD(args, flags)
+
+def parse_BITFIELD(args, flags):
+ args = [ arg.strip() for arg in args.split(',') ]
+ if len(args) != 3:
+ sys.stderr.write("Failed to parse BITFIELD: %s" % args)
+ return None
+ try:
+ size = int(args[1])
+ except ValueError:
+ sys.stderr.write("Failed to parse BITFIELD: %s" % args)
+ return None
+ return { 'size' : size, 'name' : args[0] }
+
+def parse_PRIVATE_BITFIELD(args, flags):
+ return parse_BITFIELD(args, flags)
+
+def parse_BITFIELD_RO(args, flags):
+ return parse_BITFIELD(args, flags)
+
+def parse_SKIP(args, flags):
+ args = args.split(',')[0]
+ try:
+ bytes = int(args.strip())
+ except ValueError:
+ sys.stderr.write("Failed to parse SKIP: %s" % args)
+ return None
+ return { 'size': 8*bytes, 'name': '' }
+
+def parse_SKIP_BITS(args, flags):
+ try:
+ bits = int(args.strip())
+ except ValueError:
+ sys.stderr.write("Failed to parse SKIP_BITS: %s" % args)
+ return None
+ return { 'size': bits, 'name': '' }
+
+def parse_VECTOR(args, flags):
+ args = [ arg.strip() for arg in args.split(',') ]
+ if len(args) < 3:
+ sys.stderr.write("Failed to aprse VECTOR: %s" % args)
+ return None
+ field = dict(FIELD_TYPES.get(args[-1].split(':')[-1], {}))
+ field['name'] = args[0]
+ field['repeat'] = True
+ return field
+
+def parse_LIST(args, flags):
+ return parse_VECTOR(args, flags)
+
+def parse_VARIANT(args, flags):
+ return { 'name': args.split(',',1)[0].strip() }
+
+def parse_INIT(args, flags):
+ return None
+
+PARSER_START_RE = re.compile(r"#\s*include\s+SENF_(FIXED_)?PARSER\s*\(\s*\)")
+PARSER_END_RE = re.compile(r"SENF_PARSER_FINALIZE\s*\(([^)]*)\)\s*;")
+PARSER_FIELD_RE = re.compile(r"(?://>pkgdraw:(.*)$\s*)?SENF_PARSER_([A-Z_]+)\s*\(([^;]*)\)\s*;(?:\s*//<pkgdraw:(.*)$)?", re.M)
+
+def scanPackets(data):
+ packets = {}
+ end = 0
+ while True:
+ start = PARSER_START_RE.search(data, end)
+ if not start: return packets
+ start = start.end(0)
+ end = PARSER_END_RE.search(data, start)
+ if not end: return packets
+ name=end.group(1).strip()
+ end = end.start(0)
+ packets[name] = scanFields(data[start:end])
+
+def scanFields(data):
+ fields = []
+ for match in PARSER_FIELD_RE.finditer(data):
+ tp = match.group(2)
+ flags = dict([ ([ arg.strip() for arg in flag.strip().split('=',1) ]+[True])[:2]
+ for flag in ((match.group(1) or '')+(match.group(4) or '')).split(',') ])
+ if flags.has_key('hide') : continue
+ parser = globals().get("parse_%s" % tp, None)
+ if parser:
+ field = parser(match.group(3).strip(), flags)
+ if field:
+ if flags.has_key('name') : field['name'] = flags['name']
+ field['name'] = field['name'].strip('_')
+ fields.append(field)
+ else:
+ sys.stderr.write("Unknown parser type: %s\n" % tp)
+ return fields
+
+tmpdir = tempfile.mkdtemp(prefix="pkgdraw_")
+
+def cleanup():
+ global tmpdir
+ shutil.rmtree(tmpdir)
+
+signal.signal(signal.SIGINT, cleanup)
+signal.signal(signal.SIGTERM, cleanup)
+signal.signal(signal.SIGHUP, cleanup)
+#atexit.register(cleanup)
+
+data = scanPackets(sys.stdin.read())
+
+texf = file(os.path.join(tmpdir, "fields.tex"),"w")
+texf.write(TEX_HEADER)
+
+if len(sys.argv) > 1:
+ names = sys.argv[1:]
+else:
+ names = data.keys()
+ names.sort()
+
+for name in names:
+ texf.write("\\textbf{%s}\n\\bigskip\n\n" % texquote(name))
+ texf.write(PACKET_HEADER)
+ texf.write(makeTex(formatPacket(32, data[name])))
+ texf.write(PACKET_FOOTER)
+
+texf.write(TEX_FOOTER)
+texf.close()
+
+if os.system("cd %s; %s/textogif -png -dpi 80 -res 0.25 fields >pkgdraw.log 2>&1"
+ % (tmpdir, basedir)) != 0:
+ sys.stderr.write("Conversion failed. See %s\n" % tmpdir)
+ os._exit(1)
+
+sys.stdout.write(file(os.path.join(tmpdir, "fields.png")).read())
--- /dev/null
+#! /usr/bin/perl
+#
+# T E X T O G I F
+#
+# by John Walker
+# http://www.fourmilab.ch/
+#
+ $version = '1.1 (2003-11-07)';
+#
+#
+# Converts a LaTeX file containing equations(s) into a GIF file for
+# embedding into an HTML document. The black and white image of the
+# equation is created at high resolution and then resampled to the
+# target resolution to antialias what would otherwise be jagged
+# edges.
+#
+# Online documentation with sample output is available on the Web
+# at http://www.fourmilab.ch/webtools/textogif/
+#
+# Write your equation (or anything else you can typeset with LaTeX)
+# in a file like:
+#
+# \documentclass[12pt]{article}
+# \pagestyle{empty}
+# \begin{document}
+#
+# \begin{displaymath}
+# \bf % Compiled formulae often look better in boldface
+# \int H(x,x')\psi(x')dx' = -\frac{\hbar2}{2m}\frac{d2}{dx2}
+# \psi(x)+V(x)\psi(x)
+# \end{displaymath}
+#
+# \end{document}
+#
+# The "\pagestyle{empty}" is required to avoid generating a huge
+# image with a page number at the bottom.
+#
+# Then (assuming you have all the software described below installed
+# properly), you can simply say:
+#
+# textogif [options] filename ...
+#
+# to compile filename.tex to filename.gif, an interlaced,
+# transparent background GIF file ready to use an an inline image.
+# You can specify the base name, for example, "schrod", rather than
+# the full name of the TeX file ("schrod.tex"). TeX requires the
+# input file to have an extension of ".tex". The command line
+# options are described in the help text at the end of this program
+# and in the "Default Configuration" section below.
+#
+# A sample IMG tag, including the image width and height is printed
+# on standard error, for example:
+#
+# <img src="schrod.gif" width=508 height=56>
+#
+# Required Software
+#
+# This script requires the following software to be installed
+# in the standard manner. Version numbers are those used in the
+# development and testing of the script.
+#
+# Perl 5.8.0 (anything later than 4.036 should work)
+# TeX 3.14159 (Web2C 7.3.1)
+# LaTeX2e <2000/06/01>
+# dvips dvipsk 5.86
+# Ghostscript 6.52 (2001-10-20)
+# Netpbm 9.24
+#
+#
+# Default Configuration
+#
+# The following settings are the defaults used if the -dpi and
+# -res options are not specified on the command line.
+#
+# The parameter $dpi controls how large the equation will appear
+# with respect to other inline images and the surrounding text.
+# The parameter is expressed in "dots per inch" in the PostScript
+# sense. Unfortunately, since there's no standard text size in
+# Web browsers (and most allow the user to change fonts and
+# point sizes), there's no "right" value for this setting. The
+# default of 150 seems about right for most documents. A setting
+# of 75 generates equations at half the normal size, while 300
+# doubles the size of equations. The setting of $dpi can always be
+# overridden by specifying the "-dpi" command line option.
+#
+ $dpi = 150;
+#
+# The parameter $res specifies the oversampling as the ratio
+# of the final image size to the initial black and white image.
+# Smaller values produce smoothing with more levels of grey but
+# require (much) more memory and intermediate file space to create
+# the image. If you run out of memory or disc space with the
+# default value of 0.5, try changing it to 0.75. A $res setting of
+# 1.0 disables antialiasing entirely. The setting of $res can
+# always be overridden by specifying the "res" command line option.
+#
+ $res = 0.5;
+#
+# The $background parameter supplies a command, which may be
+# void, to be inserted in the image processing pipeline to
+# adjust the original black-on-white image so that its background
+# agrees with that of the document in which it is to be inserted.
+# For a document with the default grey background used by Mosaic
+# and old versions of Netscape, use:
+#
+# $background = "ppmdim 0.7 |"; $transparent = "b2/b2/b2";
+#
+# If your document uses a white background, the void specification:
+#
+# $background = ""; $transparent = "ff/ff/ff";
+#
+# should be used. For colour or pattern backgrounds, you'll have
+# to hack the code. The reason for adjusting the background is to
+# ensure that when the image is resampled and then output with a
+# transparent background the edges of the characters will fade
+# smoothly into the page background. Otherwise you'll get a
+# distracting "halo" around each character. You can override this
+# default specification with the -grey command line option.
+#
+ $background = ""; $transparent = "ff/ff/ff";
+#
+# Image generation and decoding commands for GIF and PNG output.
+#
+ $cmdGIF = 'ppmtogif';
+ $cmdGIFdecode = 'giftopnm';
+ $cmdPNG = 'pnmtopng';
+ $cmdPNGdecode = 'pngtopnm';
+#
+# Default image creation modes
+#
+ $imageCmd = $cmdGIF;
+ $imageCmdD = $cmdGIFdecode;
+ $imageExt = 'gif';
+
+ #
+ # Command line option processing
+ #
+ while ($ARGV[0] =~ m/^-/) {
+ $_ = shift(@ARGV);
+ s/^--/-/; # Allow GNU-style -- options
+ if (m/^-d/) { # -dpi nnn
+ $dpi = shift(@ARGV);
+ } elsif (m/^-gi/) { # -gif
+ $imageCmd = $cmdGIF;
+ $imageCmdD = $cmdGIFdecode;
+ $imageExt = 'gif';
+ } elsif (m/^-gr/) { # -grey n
+ $grey = shift(@ARGV);
+ $background = "ppmdim $grey | ";
+ $greylev = int(255 * $grey);
+ $transparent = sprintf("%02x/%02x/%02x", $greylev, $greylev, $greylev);
+ } elsif (m/^-h/) { # -help
+ &help();
+ exit(0);
+ } elsif (m/^-p/) { # -png
+ $imageCmd = $cmdPNG;
+ $imageCmdD = $cmdPNGdecode;
+ $imageExt = 'png';
+ } elsif (m/^-r/) { # -res nnn
+ $res = shift(@ARGV);
+ } elsif (m/^-v/) { # -version
+ print("Version $version\n");
+ exit(0);
+ }
+ }
+ #
+ # Main file processing loop
+ #
+ foreach $f (@ARGV) {
+ $f =~ s/(.*)\.tex$/$1/;
+ &syscmd("echo x | latex $f \n");
+ &syscmd("dvips -f $f >_temp_$$.ps\n");
+
+ # Assemble and execute the command pipeline which generates the image.
+
+ # Start by invoking Ghostscript with the pbmraw output device and
+ # output file set to standard output ("-") and the requested resolution.
+ # The -q (Quiet) option is required; otherwise Ghostscript will send
+ # processing information to standard output and corrupt transmission
+ # of the bitmap to the next component in the pipeline.
+ $cmd = "echo quit | gs -q -dNOPAUSE -r" . int($dpi / $res). "x". int($dpi / $res) .
+ " -sOutputFile=- -sDEVICE=ppmraw _temp_$$.ps | " .
+
+ # Next we crop white space surrounding the generated text, promote
+ # the monochrome bitmap to a grey scale image with 8 bits per pixel,
+ # apply whatever background adjustment transform is requested, and
+ # scale the image to the desired size.
+ "pnmcrop -white | pnmpad -white -left " . int(10/$res) .
+ " -right " . int(10/$res) . " -top " . int(10/$res) .
+ " -bottom " . int(10/$res) . " | " .
+ " $background pnmscale " . $res . " | " .
+
+ # Finally, convert the image to the desired output format and write
+ # the output file.
+ "$imageCmd -interlace -transparent rgb:$transparent >$f.$imageExt";
+ &syscmd($cmd);
+
+ # Sweep up debris left around by the various intermediate steps
+ &syscmd("rm $f.dvi $f.aux $f.log _temp_$$.ps");
+
+ # Print the reference to include this figure, including width and height,
+ # to standard error.
+ $r = `$imageCmdD $f.$imageExt | pnmfile`;
+ $r =~ m/(\d+) by (\d+)/;
+ print(STDERR "<img src=\"$f.$imageExt\" width=\"$1\" height=\"$2\">\n");
+ }
+
+ # Echo and execute a system command
+
+ sub syscmd {
+ local ($cmd) = @_;
+
+ print(STDERR "$cmd\n");
+ system($cmd) == 0 || die("Error processing command:\n\t$cmd\n\t");
+ }
+
+ # Print help text
+
+ sub help {
+ print <<"EOD"
+usage: textogif [ options ] texfile...
+ Options:
+ -dpi n Set rendering dots per inch to n (default 150)
+ -gif Generate GIF image (default)
+ -grey Grey scale background level: 0 = black, 1 = white (default)
+ -help Print this message
+ -png Generate PNG image
+ -res n Set oversampling ratio, smaller = finer (default 0.5)
+ -version Print version number
+For documentation and the latest version of this program
+please visit the Web page:
+ http://www.fourmilab.ch/webtools/textogif/
+EOD
+;
+ }
## \file
-# \brief Bia2Png builder
+# \brief Dia2Png builder
## \package senfscons.Dia2Png
# \brief Build a PNG file from a DIA file
#
# \par Construction Envrionment Variables:
# <table class="senf">
-# <tr><td>\c DIACOM</td><td>dia command, defaults to \c diak</td></tr>
+# <tr><td>\c DIACOM</td><td>dia command, defaults to \c dia</td></tr>
# <tr><td>\c DIA2PNGDPI</td><td>resolution of converted image, defaults to 115</td></tr>
# <tr><td>\c DIA2PNGMAXWIDTH</td><td>maximum image width, defaults to 800</td></tr>
# </table>
--- /dev/null
+## \file
+# \brief PkgDraw builder
+
+## \package senfscons.PkgDraw
+# \brief Generate network packet diagram
+#
+# This builder will call pkgdraw to scan a header file and create network package diagrams
+# from SENF_PARSER macro calls.
+#
+# \par Construction Envrionment Variables:
+# <table class="senf">
+# <tr><td>\c PKGDRAWCOM</td><td>pkgdraw command, defaults to \c #/doclib/pkgdraw</td></tr>
+# <tr><td>\c PKGDRAWPACKETS</td><td>list packet types to include in
+# the diagram, defaults to empty (include all packets)</td></tr>
+# </table>
+#
+# \ingroup builder
+
+import os
+import SCons.Builder, SCons.Action
+
+PkgDraw = SCons.Builder.Builder(
+ suffix = ".png",
+ src_suffix = ".hh",
+ action = SCons.Action.Action("$PKGDRAWCOM $PKGDRAWPACKETS <$SOURCE >$TARGET"),
+ single_source = 1)
+
+def generate(env):
+ env['BUILDERS']['PkgDraw'] = PkgDraw
+ env['PKGDRAWCOM'] = env.Dir('#').abspath + "/doclib/pkgdraw"
+ env['PKGDRAWPACKETS'] = ''
+
+def exists(env):
+ return env.Detect("#/doclib/pkgdraw")
SCONS_TOOLS = [
"Doxygen",
"Dia2Png",
+ "PkgDraw",
"CopyToDir",
"ProgramNoScan",
"CompileCheck",