mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 15:18:20 +00:00
Initial implementation of a make doc
target to generate script docs.
This commit is contained in:
parent
bd523f2905
commit
5183ab409b
12 changed files with 964 additions and 2 deletions
|
@ -43,6 +43,11 @@ file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.csh
|
||||||
"setenv BROPATH `${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n")
|
"setenv BROPATH `${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n")
|
||||||
|
|
||||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
|
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)
|
||||||
|
string(REPLACE "." " " version_numbers ${VERSION})
|
||||||
|
separate_arguments(version_numbers)
|
||||||
|
list(GET version_numbers 0 VERSION_MAJOR)
|
||||||
|
list(GET version_numbers 1 VERSION_MINOR)
|
||||||
|
set(VERSION_MAJ_MIN "${VERSION_MAJOR}.${VERSION_MINOR}")
|
||||||
|
|
||||||
set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused")
|
set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused")
|
||||||
|
|
||||||
|
@ -162,8 +167,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(policy)
|
add_subdirectory(policy)
|
||||||
#add_subdirectory(scripts)
|
add_subdirectory(doc)
|
||||||
#add_subdirectory(doc)
|
|
||||||
|
|
||||||
include(CheckOptionalBuildSources)
|
include(CheckOptionalBuildSources)
|
||||||
|
|
||||||
|
|
40
doc/CMakeLists.txt
Normal file
40
doc/CMakeLists.txt
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
set(POLICY_SRC_DIR ${PROJECT_SOURCE_DIR}/policy)
|
||||||
|
set(DOC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/out)
|
||||||
|
set(DOC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/source)
|
||||||
|
set(DOC_SOURCE_WORKDIR ${CMAKE_CURRENT_BINARY_DIR}/source)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE DOC_SOURCES FOLLOW_SYMLINKS "*")
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/conf.py
|
||||||
|
@ONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_reST_docs.py.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/generate_reST_docs.py
|
||||||
|
@ONLY)
|
||||||
|
|
||||||
|
add_custom_target(doc
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
||||||
|
${DOC_SOURCE_DIR}
|
||||||
|
${DOC_SOURCE_WORKDIR}
|
||||||
|
COMMAND python generate_reST_docs.py
|
||||||
|
COMMAND sphinx-build
|
||||||
|
-b html
|
||||||
|
-c ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
-d ${DOC_OUTPUT_DIR}/doctrees
|
||||||
|
${DOC_SOURCE_WORKDIR}
|
||||||
|
${DOC_OUTPUT_DIR}/html
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMENT "[Sphinx] Generating Script Documentation"
|
||||||
|
VERBATIM
|
||||||
|
# SOURCES just adds stuff to IDE projects as a convienience
|
||||||
|
SOURCES ${DOC_SOURCES})
|
||||||
|
|
||||||
|
add_dependencies(doc bro)
|
||||||
|
# TODO: add dependency that's a check for `python`, `sphinx-build`, etc.
|
||||||
|
|
||||||
|
add_custom_target(doc-clean
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/source
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E remove_directory
|
||||||
|
${DOC_OUTPUT_DIR}
|
||||||
|
VERBATIM)
|
215
doc/conf.py.in
Normal file
215
doc/conf.py.in
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Bro documentation build configuration file, created by sphinx-quickstart
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
sys.path.insert(0, os.path.abspath('source/ext'))
|
||||||
|
|
||||||
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
|
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
|
extensions = ['bro']
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['source/_templates']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'Bro'
|
||||||
|
copyright = u'2011, Jon Siwek'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = '@VERSION_MAJ_MIN@'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = '@VERSION@'
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = []
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
show_authors = True
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'default'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
#html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> documentation".
|
||||||
|
#html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['source/_static']
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
#html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'Brodoc'
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for LaTeX output --------------------------------------------------
|
||||||
|
|
||||||
|
# The paper size ('letter' or 'a4').
|
||||||
|
#latex_paper_size = 'letter'
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#latex_font_size = '10pt'
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||||
|
latex_documents = [
|
||||||
|
('index', 'Bro.tex', u'Bro Documentation',
|
||||||
|
u'Jon Siwek', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#latex_preamble = ''
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output --------------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
('index', 'bro', u'Bro Documentation',
|
||||||
|
[u'Jon Siwek'], 1)
|
||||||
|
]
|
178
doc/example.bro
Normal file
178
doc/example.bro
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
##! This is an example script that demonstrates how to document. Comments
|
||||||
|
##! of the form ``##!`` are for the script summary. The contents of
|
||||||
|
##! these comments are transferred directly into the auto-generated
|
||||||
|
##! `reStructuredText <http://docutils.sourceforge.net/rst.html>`_
|
||||||
|
##! (reST) document's summary section.
|
||||||
|
##!
|
||||||
|
##! .. tip:: You can embed directives and roles within ``##``-stylized comments
|
||||||
|
##!
|
||||||
|
##! :Author: Jon Siwek <jsiwek@ncsa.illinois.edu>
|
||||||
|
|
||||||
|
# Comments that use a single pound sign (#) are not significant to
|
||||||
|
# a script's auto-generated documentation, but ones that use a
|
||||||
|
# double pound sign (##) do matter. In some cases, like record
|
||||||
|
# field comments, it's necessary to disambiguate the field with
|
||||||
|
# which a comment associates: e.g. "##<" can be used on the same line
|
||||||
|
# as a field to signify the comment relates to it and not the
|
||||||
|
# following field. "##<" is not meant for general use, just
|
||||||
|
# record/enum fields.
|
||||||
|
#
|
||||||
|
# Generally, the auto-doc comments (##) are associated with the
|
||||||
|
# next declaration/identifier found in the script, but the doc framework
|
||||||
|
# will track/render identifiers regardless of whether they have any
|
||||||
|
# of these special comments associated with them.
|
||||||
|
#
|
||||||
|
# The first sentence contained within the "##"-stylized comments for
|
||||||
|
# a given identifier is special in that it will be used as summary
|
||||||
|
# text in a table containing all such identifiers and short summaries.
|
||||||
|
# If there are no sentences (text terminated with '.'), then everything
|
||||||
|
# in the "##"-stylized comments up until the first empty comment
|
||||||
|
# is taken as the summary text for a given identifier.
|
||||||
|
|
||||||
|
# @load directives are self-documenting
|
||||||
|
@load notice
|
||||||
|
|
||||||
|
# "module" statements are self-documenting
|
||||||
|
module Example;
|
||||||
|
|
||||||
|
# redefinitions of "capture_filters" are self-documenting and
|
||||||
|
# go into the generated documentation's "Packet Filter" section
|
||||||
|
redef capture_filters += {
|
||||||
|
["ssl"] = "tcp port 443",
|
||||||
|
["nntps"] = "tcp port 563",
|
||||||
|
};
|
||||||
|
|
||||||
|
global example_ports = {
|
||||||
|
443/tcp, 563/tcp,
|
||||||
|
} &redef;
|
||||||
|
|
||||||
|
# redefinitions of "dpd_config" are self-documenting and
|
||||||
|
# go into the generated doc's "Port Analysis" section
|
||||||
|
redef dpd_config += {
|
||||||
|
[ANALYZER_SSL] = [$ports = example_ports]
|
||||||
|
};
|
||||||
|
|
||||||
|
# redefinitions of "Notice::Type" are self-documenting, but
|
||||||
|
# more information can be supplied in two different ways
|
||||||
|
redef enum Notice += {
|
||||||
|
## any number of this type of comment
|
||||||
|
## will document "Notice_One"
|
||||||
|
Notice_One,
|
||||||
|
Notice_Two, ##< any number of this type of comment
|
||||||
|
##< will document "Notice_Two"
|
||||||
|
Notice_Three,
|
||||||
|
Notice_Four,
|
||||||
|
};
|
||||||
|
|
||||||
|
# Anything declared in the export section will show up in the rendered
|
||||||
|
# documentation's "public interface" section
|
||||||
|
|
||||||
|
export {
|
||||||
|
|
||||||
|
# these headings don't mean anything special to the
|
||||||
|
# doc framework right now, I'm just including them
|
||||||
|
# to make it more clear to the reader how the doc
|
||||||
|
# framework will actually categorize a script's identifiers
|
||||||
|
|
||||||
|
############## types ################
|
||||||
|
|
||||||
|
# Note that I'm just mixing the "##" and "##<"
|
||||||
|
# types of comments in the following declarations
|
||||||
|
# as a demonstration. Normally, it would be good style
|
||||||
|
# to pick one and be consistent.
|
||||||
|
|
||||||
|
## documentation for "SimpleEnum"
|
||||||
|
## goes here.
|
||||||
|
type SimpleEnum: enum {
|
||||||
|
## and more specific info for "ONE"
|
||||||
|
## can span multiple lines
|
||||||
|
ONE,
|
||||||
|
TWO, ##< or more info like this for "TWO"
|
||||||
|
##< can span multiple lines
|
||||||
|
THREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
## document the "SimpleEnum" redef here
|
||||||
|
redef enum SimpleEnum += {
|
||||||
|
FOUR, ##< and some documentation for "FOUR"
|
||||||
|
## also "FIVE" for good measure
|
||||||
|
FIVE
|
||||||
|
};
|
||||||
|
|
||||||
|
## general documentation for a type "SimpleRecord"
|
||||||
|
## goes here.
|
||||||
|
type SimpleRecord: record {
|
||||||
|
## counts something
|
||||||
|
field1: count;
|
||||||
|
field2: bool; ##< toggles something
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
## general documentation for a type "ComplexRecord" goes here
|
||||||
|
type ComplexRecord: record {
|
||||||
|
field1: count; ##< counts something
|
||||||
|
field2: bool; ##< toggles something
|
||||||
|
field3: SimpleRecord;
|
||||||
|
msg: string &default="blah"; ##< attributes are self-documenting
|
||||||
|
} &redef;
|
||||||
|
|
||||||
|
############## options ################
|
||||||
|
# right now, I'm just defining an option as
|
||||||
|
# any const with &redef (something that can
|
||||||
|
# change at parse time, but not at run time.
|
||||||
|
|
||||||
|
## add documentation for "an_option" here
|
||||||
|
const an_option: set[addr, addr, string] &redef;
|
||||||
|
|
||||||
|
# default initialization will be self-documenting
|
||||||
|
const option_with_init = 0.01 secs &redef;
|
||||||
|
|
||||||
|
############## state variables ############
|
||||||
|
# right now, I'm defining this as any global
|
||||||
|
# that's not a function/event. doesn't matter
|
||||||
|
# if &redef attribute is present
|
||||||
|
|
||||||
|
## put some documentation for "a_var" here
|
||||||
|
global a_var: bool;
|
||||||
|
|
||||||
|
# attributes are self-documenting
|
||||||
|
global var_with_attr: count &persistent;
|
||||||
|
|
||||||
|
# it's fine if the type is inferred, that information is self-documenting
|
||||||
|
global var_without_explicit_type = "this works";
|
||||||
|
|
||||||
|
############## functions/events ############
|
||||||
|
|
||||||
|
## Summarize purpose of "a_function" here.
|
||||||
|
## Give more details about "a_function" here.
|
||||||
|
## Separating the documentation of the params/return values with
|
||||||
|
## empty comments is optional, but improves readability of script.
|
||||||
|
##
|
||||||
|
## tag: function arguments can be described
|
||||||
|
## like this
|
||||||
|
## msg: another param
|
||||||
|
##
|
||||||
|
## Returns: describe the return type here
|
||||||
|
global a_function: function(tag: string, msg: string): string;
|
||||||
|
|
||||||
|
## Summarize "an_event" here.
|
||||||
|
## Give more details about "an_event" here.
|
||||||
|
## name: describe the argument here
|
||||||
|
global an_event: event(name: string);
|
||||||
|
}
|
||||||
|
|
||||||
|
# this function is documented in the "private interface" section
|
||||||
|
# of generated documentation and any "##"-stylized comments would also
|
||||||
|
# be rendered there
|
||||||
|
function function_without_proto(tag: string): string
|
||||||
|
{
|
||||||
|
return "blah";
|
||||||
|
}
|
||||||
|
|
||||||
|
# this record type is documented in the "private interface" section
|
||||||
|
# of generated documentation and any "##"-stylized comments would also
|
||||||
|
# be rendered there
|
||||||
|
type PrivateRecord: record {
|
||||||
|
field1: bool;
|
||||||
|
field2: count;
|
||||||
|
};
|
121
doc/scripts/generate_reST_docs.py.in
Executable file
121
doc/scripts/generate_reST_docs.py.in
Executable file
|
@ -0,0 +1,121 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
import glob
|
||||||
|
import string
|
||||||
|
|
||||||
|
BRO = "@CMAKE_BINARY_DIR@/src/bro"
|
||||||
|
BROPATHDEV = "`@CMAKE_BINARY_DIR@/bro-path-dev`"
|
||||||
|
BRO_ARGS = "--doc-scripts"
|
||||||
|
DOC_DST_DIR = "@DOC_SOURCE_WORKDIR@/policy"
|
||||||
|
BROPATH = subprocess.Popen("@CMAKE_BINARY_DIR@/bro-path-dev", shell=True,
|
||||||
|
stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.readline()
|
||||||
|
|
||||||
|
class BroToReST:
|
||||||
|
bro_src_file = ""
|
||||||
|
doc_src_file = ""
|
||||||
|
load_via_stdin = False
|
||||||
|
|
||||||
|
def __init__(self, src_file, load_method=False, src_dir="@POLICY_SRC_DIR@"):
|
||||||
|
self.bro_src_file = os.path.join(src_dir, src_file)
|
||||||
|
self.load_via_stdin = load_method
|
||||||
|
|
||||||
|
# formulate doc_src_file from src_file
|
||||||
|
filename = os.path.basename(src_file)
|
||||||
|
basename, ext = os.path.splitext(filename)
|
||||||
|
if ext == ".bro":
|
||||||
|
self.doc_src_file = basename + ".rst"
|
||||||
|
else:
|
||||||
|
self.doc_src_file = filename + ".rst"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "bro_src_file: " + self.bro_src_file \
|
||||||
|
+ "\ndoc_src_file: " + self.doc_src_file \
|
||||||
|
+ "\ndoc_dst_file: " + os.path.join(DOC_DST_DIR, self.doc_src_file) \
|
||||||
|
+ "\nstdin_load: %s" % self.load_via_stdin
|
||||||
|
|
||||||
|
def GenDoc(self):
|
||||||
|
bro_src_basename = os.path.basename(self.bro_src_file)
|
||||||
|
|
||||||
|
if self.load_via_stdin:
|
||||||
|
cmd = "echo '@load %s' | %s %s" % (bro_src_basename, BRO, BRO_ARGS)
|
||||||
|
else:
|
||||||
|
cmd = "%s %s %s" % (BRO, BRO_ARGS, self.bro_src_file)
|
||||||
|
|
||||||
|
p = subprocess.Popen(cmd, shell=True, env={"BROPATH": BROPATH})
|
||||||
|
|
||||||
|
if p.wait() == 0:
|
||||||
|
shutil.copy(self.doc_src_file, DOC_DST_DIR)
|
||||||
|
shutil.copy(self.bro_src_file, DOC_DST_DIR)
|
||||||
|
|
||||||
|
for leftover in glob.glob("*.rst"):
|
||||||
|
os.remove(leftover)
|
||||||
|
|
||||||
|
def GenDocs(doc_list, load_method=False):
|
||||||
|
for f in doc_list:
|
||||||
|
doc = BroToReST(f, load_method)
|
||||||
|
print "Generating reST document for " + f
|
||||||
|
doc.GenDoc()
|
||||||
|
|
||||||
|
# search BROPATH for the script and return the absolute path to it
|
||||||
|
def FindBroScript(src_file):
|
||||||
|
for path in string.split(BROPATH, ":"):
|
||||||
|
abs_path = os.path.join(path, src_file)
|
||||||
|
if os.path.exists(abs_path):
|
||||||
|
return abs_path
|
||||||
|
|
||||||
|
# Scripts that can be loaded by bro via command line argument
|
||||||
|
# TODO: generate docs for more scripts
|
||||||
|
docs = [
|
||||||
|
"alarm.bro",
|
||||||
|
"arp.bro",
|
||||||
|
"conn.bro",
|
||||||
|
"dhcp.bro",
|
||||||
|
"dns.bro",
|
||||||
|
"ftp.bro",
|
||||||
|
"http.bro",
|
||||||
|
"http-reply.bro",
|
||||||
|
"http-request.bro",
|
||||||
|
"irc.bro",
|
||||||
|
"smtp.bro",
|
||||||
|
"ssl.bro",
|
||||||
|
"ssl-ciphers.bro",
|
||||||
|
"ssl-errors.bro",
|
||||||
|
"synflood.bro",
|
||||||
|
"tcp.bro",
|
||||||
|
"udp.bro",
|
||||||
|
"weird.bro",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Scripts that can't be loaded by bro via command line argument (possible
|
||||||
|
# due to dependency issues), but can be loaded via an @load on stdin
|
||||||
|
stdin_docs = [
|
||||||
|
"notice.bro",
|
||||||
|
]
|
||||||
|
|
||||||
|
GenDocs(docs)
|
||||||
|
GenDocs(stdin_docs, True)
|
||||||
|
|
||||||
|
BroToReST("example.bro", False, "@PROJECT_SOURCE_DIR@/doc").GenDoc()
|
||||||
|
|
||||||
|
# Generate documentation for stuff that's always loaded into bro by default
|
||||||
|
cmd = "echo '' | %s %s" % (BRO, BRO_ARGS)
|
||||||
|
p = subprocess.Popen(cmd, shell=True, env={"BROPATH": BROPATH})
|
||||||
|
if p.wait() == 0:
|
||||||
|
for doc in glob.glob("*.rst"):
|
||||||
|
if doc == "<stdin>.rst":
|
||||||
|
os.remove(doc)
|
||||||
|
continue
|
||||||
|
|
||||||
|
basename, ext = os.path.splitext(doc)
|
||||||
|
basename2, ext = os.path.splitext(basename)
|
||||||
|
if ext == ".init":
|
||||||
|
src_file = basename
|
||||||
|
else:
|
||||||
|
src_file = basename + ".bro"
|
||||||
|
src_file = FindBroScript(src_file)
|
||||||
|
shutil.copy(src_file, DOC_DST_DIR)
|
||||||
|
shutil.copy(doc, DOC_DST_DIR)
|
||||||
|
os.remove(doc)
|
64
doc/source/_static/showhide.js
Normal file
64
doc/source/_static/showhide.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// make literal blocks corresponding to identifier initial values
|
||||||
|
// hidden by default
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var showText='(Show Value)';
|
||||||
|
var hideText='(Hide Value)';
|
||||||
|
|
||||||
|
var is_visible = false;
|
||||||
|
|
||||||
|
// select field-list tables that come before a literal block
|
||||||
|
tables = $('.highlight-python').prev('table.docutils.field-list');
|
||||||
|
|
||||||
|
tables.find('th.field-name').filter(function(index) {
|
||||||
|
return $(this).html() == "Default :";
|
||||||
|
}).next().append('<a href="#" class="toggleLink">'+showText+'</a>');
|
||||||
|
|
||||||
|
// hide all literal blocks that follow a field-list table
|
||||||
|
tables.next('.highlight-python').hide();
|
||||||
|
|
||||||
|
// register handler for clicking a "toggle" link
|
||||||
|
$('a.toggleLink').click(function() {
|
||||||
|
is_visible = !is_visible;
|
||||||
|
|
||||||
|
$(this).html( (!is_visible) ? showText : hideText);
|
||||||
|
|
||||||
|
// the link is inside a <table><tbody><tr><td> and the next
|
||||||
|
// literal block after the table is the literal block that we want
|
||||||
|
// to show/hide
|
||||||
|
$(this).parent().parent().parent().parent().next('.highlight-python').slideToggle('fast');
|
||||||
|
|
||||||
|
// override default link behavior
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// make "Private Interface" sections hidden by default
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
var showText='Show Private Interface (for internal use)';
|
||||||
|
var hideText='Hide Private Interface';
|
||||||
|
|
||||||
|
var is_visible = false;
|
||||||
|
|
||||||
|
// insert show/hide links
|
||||||
|
$('#private-interface').children(":first-child").after('<a href="#" class="privateToggle">'+showText+'</a>');
|
||||||
|
|
||||||
|
// wrap all sub-sections in a new div that can be hidden/shown
|
||||||
|
$('#private-interface').children(".section").wrapAll('<div class="private" />');
|
||||||
|
|
||||||
|
// hide the given class
|
||||||
|
$('.private').hide();
|
||||||
|
|
||||||
|
// register handler for clicking a "toggle" link
|
||||||
|
$('a.privateToggle').click(function() {
|
||||||
|
is_visible = !is_visible;
|
||||||
|
|
||||||
|
$(this).html( (!is_visible) ? showText : hideText);
|
||||||
|
|
||||||
|
$('.private').slideToggle('fast');
|
||||||
|
|
||||||
|
// override default link behavior
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
5
doc/source/_templates/layout.html
Normal file
5
doc/source/_templates/layout.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends "!layout.html" %}
|
||||||
|
{% block extrahead %}
|
||||||
|
<script type="text/javascript" src="{{ pathto('_static/showhide.js', 1) }}"></script>
|
||||||
|
{{ super() }}
|
||||||
|
{% endblock %}
|
121
doc/source/builtins.rst
Normal file
121
doc/source/builtins.rst
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
Builtins
|
||||||
|
========
|
||||||
|
|
||||||
|
Types
|
||||||
|
-----
|
||||||
|
|
||||||
|
The Bro scripting language supports the following built-in types.
|
||||||
|
|
||||||
|
.. TODO: add documentation
|
||||||
|
|
||||||
|
.. bro:type:: void
|
||||||
|
|
||||||
|
.. bro:type:: bool
|
||||||
|
|
||||||
|
.. bro:type:: int
|
||||||
|
|
||||||
|
.. bro:type:: count
|
||||||
|
|
||||||
|
.. bro:type:: counter
|
||||||
|
|
||||||
|
.. bro:type:: double
|
||||||
|
|
||||||
|
.. bro:type:: time
|
||||||
|
|
||||||
|
.. bro:type:: interval
|
||||||
|
|
||||||
|
.. bro:type:: string
|
||||||
|
|
||||||
|
.. bro:type:: pattern
|
||||||
|
|
||||||
|
.. bro:type:: enum
|
||||||
|
|
||||||
|
.. bro:type:: timer
|
||||||
|
|
||||||
|
.. bro:type:: port
|
||||||
|
|
||||||
|
.. bro:type:: addr
|
||||||
|
|
||||||
|
.. bro:type:: net
|
||||||
|
|
||||||
|
.. bro:type:: subnet
|
||||||
|
|
||||||
|
.. bro:type:: any
|
||||||
|
|
||||||
|
.. bro:type:: table
|
||||||
|
|
||||||
|
.. bro:type:: union
|
||||||
|
|
||||||
|
.. bro:type:: record
|
||||||
|
|
||||||
|
.. bro:type:: types
|
||||||
|
|
||||||
|
.. bro:type:: func
|
||||||
|
|
||||||
|
.. bro:type:: file
|
||||||
|
|
||||||
|
.. bro:type:: vector
|
||||||
|
|
||||||
|
.. TODO: below are kind of "special cases" that bro knows about?
|
||||||
|
|
||||||
|
.. bro:type:: set
|
||||||
|
|
||||||
|
.. bro:type:: function
|
||||||
|
|
||||||
|
.. bro:type:: event
|
||||||
|
|
||||||
|
.. TODO: Notice will get documented as part of notice.bro, which can eventually
|
||||||
|
be referenced here once that documentation is auto-generated.
|
||||||
|
|
||||||
|
.. bro:type:: Notice
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
|
||||||
|
The Bro scripting language supports the following built-in attributes.
|
||||||
|
|
||||||
|
.. TODO: add documentation
|
||||||
|
|
||||||
|
.. bro:attr:: &optional
|
||||||
|
|
||||||
|
.. bro:attr:: &default
|
||||||
|
|
||||||
|
.. bro:attr:: &redef
|
||||||
|
|
||||||
|
.. bro:attr:: &rotate_interval
|
||||||
|
|
||||||
|
.. bro:attr:: &rotate_size
|
||||||
|
|
||||||
|
.. bro:attr:: &add_func
|
||||||
|
|
||||||
|
.. bro:attr:: &delete_func
|
||||||
|
|
||||||
|
.. bro:attr:: &expire_func
|
||||||
|
|
||||||
|
.. bro:attr:: &read_expire
|
||||||
|
|
||||||
|
.. bro:attr:: &write_expire
|
||||||
|
|
||||||
|
.. bro:attr:: &create_expire
|
||||||
|
|
||||||
|
.. bro:attr:: &persistent
|
||||||
|
|
||||||
|
.. bro:attr:: &synchronized
|
||||||
|
|
||||||
|
.. bro:attr:: &postprocessor
|
||||||
|
|
||||||
|
.. bro:attr:: &encrypt
|
||||||
|
|
||||||
|
.. bro:attr:: &match
|
||||||
|
|
||||||
|
.. bro:attr:: &disable_print_hook
|
||||||
|
|
||||||
|
.. bro:attr:: &raw_output
|
||||||
|
|
||||||
|
.. bro:attr:: &mergeable
|
||||||
|
|
||||||
|
.. bro:attr:: &priority
|
||||||
|
|
||||||
|
.. bro:attr:: &group
|
||||||
|
|
||||||
|
.. bro:attr:: (&tracked)
|
19
doc/source/common.rst
Normal file
19
doc/source/common.rst
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Common Documentation
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. _common_port_analysis_doc:
|
||||||
|
|
||||||
|
Port Analysis
|
||||||
|
-------------
|
||||||
|
|
||||||
|
TODO: add some stuff here
|
||||||
|
|
||||||
|
.. _common_packet_filter_doc:
|
||||||
|
|
||||||
|
Packet Filter
|
||||||
|
-------------
|
||||||
|
|
||||||
|
TODO: add some stuff here
|
||||||
|
|
||||||
|
.. note:: Filters are only relevant when dynamic protocol detection (DPD)
|
||||||
|
is explicitly turned off (Bro release 1.6 enabled DPD by default).
|
167
doc/source/ext/bro.py
Normal file
167
doc/source/ext/bro.py
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
"""
|
||||||
|
The Bro domain for Sphinx.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setup(Sphinx):
|
||||||
|
Sphinx.add_domain(BroDomain)
|
||||||
|
|
||||||
|
from sphinx import addnodes
|
||||||
|
from sphinx.domains import Domain, ObjType, Index
|
||||||
|
from sphinx.locale import l_, _
|
||||||
|
from sphinx.directives import ObjectDescription
|
||||||
|
from sphinx.roles import XRefRole
|
||||||
|
from sphinx.util.nodes import make_refnode
|
||||||
|
import string
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.parsers.rst import Directive
|
||||||
|
from docutils.parsers.rst import directives
|
||||||
|
from docutils.parsers.rst.roles import set_classes
|
||||||
|
|
||||||
|
class BroGeneric(ObjectDescription):
|
||||||
|
def add_target_and_index(self, name, sig, signode):
|
||||||
|
targetname = self.objtype + '-' + name
|
||||||
|
if targetname not in self.state.document.ids:
|
||||||
|
signode['names'].append(targetname)
|
||||||
|
signode['ids'].append(targetname)
|
||||||
|
signode['first'] = (not self.names)
|
||||||
|
self.state.document.note_explicit_target(signode)
|
||||||
|
|
||||||
|
objects = self.env.domaindata['bro']['objects']
|
||||||
|
key = (self.objtype, name)
|
||||||
|
# this is commented out mostly just to avoid having a special directive
|
||||||
|
# for events in order to avoid the duplicate warnings in that case
|
||||||
|
"""
|
||||||
|
if key in objects:
|
||||||
|
self.env.warn(self.env.docname,
|
||||||
|
'duplicate description of %s %s, ' %
|
||||||
|
(self.objtype, name) +
|
||||||
|
'other instance in ' +
|
||||||
|
self.env.doc2path(objects[key]),
|
||||||
|
self.lineno)
|
||||||
|
"""
|
||||||
|
objects[key] = self.env.docname
|
||||||
|
indextext = self.get_index_text(self.objtype, name)
|
||||||
|
if indextext:
|
||||||
|
self.indexnode['entries'].append(('single', indextext,
|
||||||
|
targetname, targetname))
|
||||||
|
|
||||||
|
def get_index_text(self, objectname, name):
|
||||||
|
return _('%s (%s)') % (name, self.objtype)
|
||||||
|
|
||||||
|
def handle_signature(self, sig, signode):
|
||||||
|
signode += addnodes.desc_name("", sig)
|
||||||
|
return sig
|
||||||
|
|
||||||
|
class BroNamespace(BroGeneric):
|
||||||
|
def add_target_and_index(self, name, sig, signode):
|
||||||
|
targetname = self.objtype + '-' + name
|
||||||
|
if targetname not in self.state.document.ids:
|
||||||
|
signode['names'].append(targetname)
|
||||||
|
signode['ids'].append(targetname)
|
||||||
|
signode['first'] = (not self.names)
|
||||||
|
self.state.document.note_explicit_target(signode)
|
||||||
|
|
||||||
|
objects = self.env.domaindata['bro']['objects']
|
||||||
|
key = (self.objtype, name)
|
||||||
|
objects[key] = self.env.docname
|
||||||
|
indextext = self.get_index_text(self.objtype, name)
|
||||||
|
self.indexnode['entries'].append(('single', indextext,
|
||||||
|
targetname, targetname))
|
||||||
|
self.indexnode['entries'].append(('single',
|
||||||
|
"namespaces; %s" % (sig),
|
||||||
|
targetname, targetname))
|
||||||
|
|
||||||
|
def get_index_text(self, objectname, name):
|
||||||
|
return _('%s (namespace); %s') % (name, self.env.docname)
|
||||||
|
|
||||||
|
def handle_signature(self, sig, signode):
|
||||||
|
signode += addnodes.desc_name("", sig)
|
||||||
|
return sig
|
||||||
|
|
||||||
|
class BroEnum(BroGeneric):
|
||||||
|
def add_target_and_index(self, name, sig, signode):
|
||||||
|
targetname = self.objtype + '-' + name
|
||||||
|
if targetname not in self.state.document.ids:
|
||||||
|
signode['names'].append(targetname)
|
||||||
|
signode['ids'].append(targetname)
|
||||||
|
signode['first'] = (not self.names)
|
||||||
|
self.state.document.note_explicit_target(signode)
|
||||||
|
|
||||||
|
objects = self.env.domaindata['bro']['objects']
|
||||||
|
key = (self.objtype, name)
|
||||||
|
objects[key] = self.env.docname
|
||||||
|
indextext = self.get_index_text(self.objtype, name)
|
||||||
|
#self.indexnode['entries'].append(('single', indextext,
|
||||||
|
# targetname, targetname))
|
||||||
|
m = sig.split()
|
||||||
|
self.indexnode['entries'].append(('single',
|
||||||
|
"%s (enum values); %s" % (m[1], m[0]),
|
||||||
|
targetname, targetname))
|
||||||
|
|
||||||
|
def handle_signature(self, sig, signode):
|
||||||
|
m = sig.split()
|
||||||
|
name = m[0]
|
||||||
|
signode += addnodes.desc_name("", name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
class BroIdentifier(BroGeneric):
|
||||||
|
def get_index_text(self, objectname, name):
|
||||||
|
return name
|
||||||
|
|
||||||
|
class BroAttribute(BroGeneric):
|
||||||
|
def get_index_text(self, objectname, name):
|
||||||
|
return _('%s (attribute)') % (name)
|
||||||
|
|
||||||
|
class BroDomain(Domain):
|
||||||
|
"""Bro domain."""
|
||||||
|
name = 'bro'
|
||||||
|
label = 'Bro'
|
||||||
|
|
||||||
|
object_types = {
|
||||||
|
'type': ObjType(l_('type'), 'type'),
|
||||||
|
'namespace': ObjType(l_('namespace'), 'namespace'),
|
||||||
|
'id': ObjType(l_('id'), 'id'),
|
||||||
|
'enum': ObjType(l_('enum'), 'enum'),
|
||||||
|
'attr': ObjType(l_('attr'), 'attr'),
|
||||||
|
}
|
||||||
|
|
||||||
|
directives = {
|
||||||
|
'type': BroGeneric,
|
||||||
|
'namespace': BroNamespace,
|
||||||
|
'id': BroIdentifier,
|
||||||
|
'enum': BroEnum,
|
||||||
|
'attr': BroAttribute,
|
||||||
|
}
|
||||||
|
|
||||||
|
roles = {
|
||||||
|
'type': XRefRole(),
|
||||||
|
'namespace': XRefRole(),
|
||||||
|
'id': XRefRole(),
|
||||||
|
'enum': XRefRole(),
|
||||||
|
'attr': XRefRole(),
|
||||||
|
}
|
||||||
|
|
||||||
|
initial_data = {
|
||||||
|
'objects': {}, # fullname -> docname, objtype
|
||||||
|
}
|
||||||
|
|
||||||
|
def clear_doc(self, docname):
|
||||||
|
for (typ, name), doc in self.data['objects'].items():
|
||||||
|
if doc == docname:
|
||||||
|
del self.data['objects'][typ, name]
|
||||||
|
|
||||||
|
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
|
||||||
|
contnode):
|
||||||
|
objects = self.data['objects']
|
||||||
|
objtypes = self.objtypes_for_role(typ)
|
||||||
|
for objtype in objtypes:
|
||||||
|
if (objtype, target) in objects:
|
||||||
|
return make_refnode(builder, fromdocname,
|
||||||
|
objects[objtype, target],
|
||||||
|
objtype + '-' + target,
|
||||||
|
contnode, target + ' ' + objtype)
|
||||||
|
|
||||||
|
def get_objects(self):
|
||||||
|
for (typ, name), docname in self.data['objects'].iteritems():
|
||||||
|
yield name, name, typ, docname, typ + '-' + name, 1
|
20
doc/source/index.rst
Normal file
20
doc/source/index.rst
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
.. Bro documentation master file
|
||||||
|
|
||||||
|
Welcome to Bro's documentation!
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:glob:
|
||||||
|
|
||||||
|
common
|
||||||
|
builtins
|
||||||
|
policy/index
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
8
doc/source/policy/index.rst
Normal file
8
doc/source/policy/index.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Policy Files
|
||||||
|
============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:glob:
|
||||||
|
|
||||||
|
*
|
Loading…
Add table
Add a link
Reference in a new issue