From: g0dil Date: Tue, 27 Jan 2009 01:28:45 +0000 (+0000) Subject: Packets: Add packet diagrams X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=cb01986c60bd68d43a56e1f648aecd23b43cb893;p=senf.git Packets: Add packet diagrams git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1078 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/DefaultBundle/EthernetPacket.hh b/Packets/DefaultBundle/EthernetPacket.hh index cbaf6e3..8286e88 100644 --- a/Packets/DefaultBundle/EthernetPacket.hh +++ b/Packets/DefaultBundle/EthernetPacket.hh @@ -96,6 +96,7 @@ namespace senf { \par Fields: \ref EthernetPacketParser + \image html EthernetPacket.png \par Associated registries: \ref EtherTypes @@ -151,7 +152,8 @@ namespace senf { \par Fields: \ref EthVLanPacketParser - + \image html EthVLanPacket.png + \par Associated registries: \ref EtherTypes diff --git a/Packets/DefaultBundle/ICMPv6Packet.hh b/Packets/DefaultBundle/ICMPv6Packet.hh index 44a4316..715ce21 100644 --- a/Packets/DefaultBundle/ICMPv6Packet.hh +++ b/Packets/DefaultBundle/ICMPv6Packet.hh @@ -46,7 +46,21 @@ namespace senf // 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 @@ -76,3 +90,15 @@ namespace senf } #endif + + +// 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 diff --git a/Packets/DefaultBundle/ICMPv6TypePacket.hh b/Packets/DefaultBundle/ICMPv6TypePacket.hh index 8741909..475b11f 100644 --- a/Packets/DefaultBundle/ICMPv6TypePacket.hh +++ b/Packets/DefaultBundle/ICMPv6TypePacket.hh @@ -43,6 +43,17 @@ namespace senf { 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 @@ -70,6 +81,17 @@ namespace senf { 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 @@ -114,6 +136,17 @@ namespace senf { 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 @@ -146,6 +179,17 @@ namespace senf { 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 @@ -179,6 +223,17 @@ namespace senf { 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 @@ -212,6 +267,17 @@ namespace senf { 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 @@ -260,6 +326,17 @@ namespace senf { } }; + /** \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 @@ -308,6 +385,18 @@ namespace senf { } }; + /** \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 @@ -325,3 +414,14 @@ namespace senf { } #endif + + +// 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: diff --git a/Packets/DefaultBundle/IPv4Packet.hh b/Packets/DefaultBundle/IPv4Packet.hh index c1e367b..0dc7917 100644 --- a/Packets/DefaultBundle/IPv4Packet.hh +++ b/Packets/DefaultBundle/IPv4Packet.hh @@ -158,6 +158,8 @@ namespace senf { 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 diff --git a/Packets/DefaultBundle/IPv6Extensions.hh b/Packets/DefaultBundle/IPv6Extensions.hh index 91ac610..d2e9de0 100644 --- a/Packets/DefaultBundle/IPv6Extensions.hh +++ b/Packets/DefaultBundle/IPv6Extensions.hh @@ -71,6 +71,8 @@ namespace senf { \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 diff --git a/Packets/DefaultBundle/IPv6Packet.hh b/Packets/DefaultBundle/IPv6Packet.hh index 63815d8..97f79ab 100644 --- a/Packets/DefaultBundle/IPv6Packet.hh +++ b/Packets/DefaultBundle/IPv6Packet.hh @@ -98,6 +98,8 @@ namespace senf { 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 diff --git a/Packets/DefaultBundle/LlcSnapPacket.hh b/Packets/DefaultBundle/LlcSnapPacket.hh index 037b61f..df1d155 100644 --- a/Packets/DefaultBundle/LlcSnapPacket.hh +++ b/Packets/DefaultBundle/LlcSnapPacket.hh @@ -77,6 +77,8 @@ namespace senf { \par Finalize action: XXXX + \image html LlcSnapPacket.png + \ingroup protocolbundle_default */ struct LlcSnapPacketType diff --git a/Packets/DefaultBundle/UDPPacket.hh b/Packets/DefaultBundle/UDPPacket.hh index 8b1aa70..fb71f44 100644 --- a/Packets/DefaultBundle/UDPPacket.hh +++ b/Packets/DefaultBundle/UDPPacket.hh @@ -71,6 +71,8 @@ namespace senf { Set \a length from payload size\n Calculate \a checksum + \image html UDPPacket.png + \ingroup protocolbundle_default */ struct UDPPacketType diff --git a/Packets/ListParser.hh b/Packets/ListParser.hh index 1b0a4f6..8807578 100644 --- a/Packets/ListParser.hh +++ b/Packets/ListParser.hh @@ -58,7 +58,16 @@ namespace senf { 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 @@ -288,6 +297,11 @@ namespace senf { \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 */ diff --git a/Packets/MPEGDVBBundle/DTCPPacket.hh b/Packets/MPEGDVBBundle/DTCPPacket.hh index d3a8e05..78f226f 100644 --- a/Packets/MPEGDVBBundle/DTCPPacket.hh +++ b/Packets/MPEGDVBBundle/DTCPPacket.hh @@ -44,8 +44,8 @@ namespace senf { { # include SENF_PARSER() - SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser ); - SENF_PARSER_PRIVATE_FIELD( reserved_, UInt8Parser ); + SENF_PARSER_PRIVATE_FIELD( fbipCount_, UInt8Parser ); //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= SENF_PARSER_PRIVATE_FIELD ( reserved1_, UInt8Parser ); // must be zero // Go back to fbipCount so the variant has access to that field @@ -127,6 +129,8 @@ namespace senf { \par Fields: \ref DTCPHelloPacketParser + \image html DTCPPacket.png + \ingroup protocolbundle_mpegdvb */ struct DTCPHelloPacketType diff --git a/Packets/Mainpage.dox b/Packets/Mainpage.dox index b8c5ad9..308d9ac 100644 --- a/Packets/Mainpage.dox +++ b/Packets/Mainpage.dox @@ -587,8 +587,8 @@ 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 diff --git a/Packets/SConscript b/Packets/SConscript index 64aa7a7..5755ab5 100644 --- a/Packets/SConscript +++ b/Packets/SConscript @@ -11,7 +11,37 @@ SENFSCons.StandardTargets(env) 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) diff --git a/Packets/VectorParser.hh b/Packets/VectorParser.hh index 623e18f..db9e0de 100644 --- a/Packets/VectorParser.hh +++ b/Packets/VectorParser.hh @@ -54,7 +54,16 @@ namespace senf { 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 @@ -276,6 +285,11 @@ namespace senf { \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 */ diff --git a/doclib/pkgdraw b/doclib/pkgdraw new file mode 100755 index 0000000..7bacd98 --- /dev/null +++ b/doclib/pkgdraw @@ -0,0 +1,321 @@ +#!/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*// 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()) diff --git a/doclib/textogif b/doclib/textogif new file mode 100755 index 0000000..e8df834 --- /dev/null +++ b/doclib/textogif @@ -0,0 +1,235 @@ +#! /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: +# +# +# +# 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 "\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 +; + } diff --git a/senfscons/Dia2Png.py b/senfscons/Dia2Png.py index 3e5f0fe..a8000be 100644 --- a/senfscons/Dia2Png.py +++ b/senfscons/Dia2Png.py @@ -1,5 +1,5 @@ ## \file -# \brief Bia2Png builder +# \brief Dia2Png builder ## \package senfscons.Dia2Png # \brief Build a PNG file from a DIA file @@ -11,7 +11,7 @@ # # \par Construction Envrionment Variables: # -# +# # # #
\c DIACOMdia command, defaults to \c diak
\c DIACOMdia command, defaults to \c dia
\c DIA2PNGDPIresolution of converted image, defaults to 115
\c DIA2PNGMAXWIDTHmaximum image width, defaults to 800
diff --git a/senfscons/PkgDraw.py b/senfscons/PkgDraw.py new file mode 100644 index 0000000..81309b2 --- /dev/null +++ b/senfscons/PkgDraw.py @@ -0,0 +1,34 @@ +## \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: +# +# +# +#
\c PKGDRAWCOMpkgdraw command, defaults to \c #/doclib/pkgdraw
\c PKGDRAWPACKETSlist packet types to include in +# the diagram, defaults to empty (include all packets)
+# +# \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") diff --git a/senfscons/SENFSCons.py b/senfscons/SENFSCons.py index 32a5cc7..fc81537 100644 --- a/senfscons/SENFSCons.py +++ b/senfscons/SENFSCons.py @@ -50,6 +50,7 @@ from SCons.Script import * SCONS_TOOLS = [ "Doxygen", "Dia2Png", + "PkgDraw", "CopyToDir", "ProgramNoScan", "CompileCheck",