From a794d7231410f16747e44b690fcc03a96274894c Mon Sep 17 00:00:00 2001 From: Manuel Traut Date: Mon, 18 Jul 2011 14:02:41 +0200 Subject: delete vorlesung specific stuff Signed-off-by: Manuel Traut --- Makefile | 84 ---------------------------------------------------------------- 1 file changed, 84 deletions(-) delete mode 100644 Makefile (limited to 'Makefile') diff --git a/Makefile b/Makefile deleted file mode 100644 index 97b6efe..0000000 --- a/Makefile +++ /dev/null @@ -1,84 +0,0 @@ -SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime - -default: - make all - -all clean:: - for dir in $(SUBDIRS) ; do \ - (cd $$dir && make $@); \ - done - rm -rf pdf - rm -f *.aux - rm -f *.log - rm -f *.nav - rm -f *.toc - rm -f *.pdf - rm -f *.snm - rm -f *.bbl - rm -f *.blg - rm -f *.out - rm -f *.vrb - -vorlesung:: - mv configpres.tex _configpres.tex - touch configpres.tex - mv tailpres.tex _tailpres.tex - touch tailpres.tex - pdflatex vorl7.tex - pdflatex vorl7.tex - pdflatex vorl.tex - pdflatex vorl.tex - rm configpres.tex tailpres.tex - mv _configpres.tex configpres.tex - mv _tailpres.tex tailpres.tex - mv confighandout.tex _confighandout.tex - touch confighandout.tex - mv tailhandout.tex _tailhandout.tex - touch tailhandout.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout5.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout5.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout.tex - rm confighandout.tex tailhandout.tex - mv _confighandout.tex confighandout.tex - mv _tailhandout.tex tailhandout.tex - - -pres:: - mv configpres.tex _configpres.tex - touch configpres.tex - mv tailpres.tex _tailpres.tex - touch tailpres.tex - pdflatex pres_master.tex - bibtex pres_master.aux - pdflatex pres_master.tex - pdflatex pres_master.tex - rm configpres.tex tailpres.tex - mv _configpres.tex configpres.tex - mv _tailpres.tex tailpres.tex -book:: - mv confighandout.tex _confighandout.tex - touch confighandout.tex - mv tailhandout.tex _tailhandout.tex - touch tailhandout.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout_master.tex - bibtex handout_master.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout_master.tex - TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout_master.tex - rm confighandout.tailhandout.tex - mv _confighandout.tex confighandout.tex - mv _tailhandout.tex tailhandout.tex -pdf:: - rm -rf pdf - mkdir -p pdf/pres - mkdir -p pdf/handout - mkdir -p pdf/hints - find . -name pres_*.pdf | xargs cp -t pdf/pres - find . -name hints_*.pdf | xargs cp -t pdf/hints - find . -name handout_*.pdf | xargs cp -t pdf/handout - cd pdf/pres && \ - pdfsam-console -o `pwd`/../pres.pdf -d `pwd` concat - cd pdf/hints && \ - pdfsam-console -o `pwd`/../hints.pdf -d `pwd` concat - cd pdf/handout && \ - pdfsam-console -o `pwd`/../handout.pdf -d `pwd` concat -- cgit v1.2.3 From a47cd5a143bc4cb6438bff35507b59098b13a62d Mon Sep 17 00:00:00 2001 From: Manuel Traut Date: Mon, 18 Jul 2011 14:08:21 +0200 Subject: restore Makefile (deleted by vorlesungs merge) Signed-off-by: Manuel Traut --- Makefile | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Makefile (limited to 'Makefile') diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1ef20b1 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime + +default: + make all + +all clean:: + for dir in $(SUBDIRS) ; do \ + (cd $$dir && make $@); \ + done + rm -rf pdf + rm -f *.aux + rm -f *.log + rm -f *.nav + rm -f *.toc + rm -f *.pdf + rm -f *.snm + rm -f *.bbl + rm -f *.blg + rm -f *.out + rm -f *.vrb +pres:: + mv configpres.tex _configpres.tex + touch configpres.tex + mv tailpres.tex _tailpres.tex + touch tailpres.tex + pdflatex pres_master.tex + bibtex pres_master.aux + pdflatex pres_master.tex + pdflatex pres_master.tex + mv _configpres.tex configpres.tex + mv _tailpres.tex tailpres.tex + rm configpres.tex tailpres.tex +book:: + mv confighandout.tex _confighandout.tex + touch confighandout.tex + mv tailhandout.tex _tailhandout.tex + touch tailhandout.tex + TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout_master.tex + bibtex handout_master.tex + TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout_master.tex + TEXINPUTS=`pwd`/wise:.:$(TEXINPUTS) pdflatex handout_master.tex + rm confighandout.tailhandout.tex + mv _confighandout.tex confighandout.tex + mv _tailhandout.tex tailhandout.tex +pdf:: + rm -rf pdf + mkdir -p pdf/pres + mkdir -p pdf/handout + mkdir -p pdf/hints + find . -name pres_*.pdf | xargs cp -t pdf/pres + find . -name hints_*.pdf | xargs cp -t pdf/hints + find . -name handout_*.pdf | xargs cp -t pdf/handout + cd pdf/pres && \ + pdfsam-console -o `pwd`/../pres.pdf -d `pwd` concat + cd pdf/hints && \ + pdfsam-console -o `pwd`/../hints.pdf -d `pwd` concat + cd pdf/handout && \ + pdfsam-console -o `pwd`/../handout.pdf -d `pwd` concat -- cgit v1.2.3 From 73b8bf14798e661351a8e51237cac38bdc824d86 Mon Sep 17 00:00:00 2001 From: Jan Altenberg Date: Mon, 22 Oct 2012 11:01:44 +0200 Subject: Add security/ directory to global Makefile. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 1ef20b1..034011f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime +SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime security default: make all -- cgit v1.2.3 From 494b16d6fbd565225e4f9ddaf2b813b520271753 Mon Sep 17 00:00:00 2001 From: Holger Dengler Date: Mon, 22 Oct 2012 17:05:03 +0200 Subject: Misc/xml: Add new XML fasttrack Add new miscellaneous section with an XML fasttrack. Coding samples are located in misc/samples/. Signed-off-by: Holger Dengler --- Makefile | 2 +- misc/Makefile | 9 + misc/pres_xml-fasttrack_en.tex | 426 +++++++++++++++++++++++++++++++++++++++++ misc/samples/.gitignore | 2 + misc/samples/Makefile | 10 + misc/samples/xml_dom.c | 55 ++++++ misc/samples/xml_full.xml | 24 +++ misc/samples/xml_sax.c | 109 +++++++++++ misc/samples/xml_small.xml | 14 ++ misc/section.tex | 3 + 10 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 misc/Makefile create mode 100644 misc/pres_xml-fasttrack_en.tex create mode 100644 misc/samples/.gitignore create mode 100644 misc/samples/Makefile create mode 100644 misc/samples/xml_dom.c create mode 100644 misc/samples/xml_full.xml create mode 100644 misc/samples/xml_sax.c create mode 100644 misc/samples/xml_small.xml create mode 100644 misc/section.tex (limited to 'Makefile') diff --git a/Makefile b/Makefile index 034011f..0130884 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime security +SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime security misc default: make all diff --git a/misc/Makefile b/misc/Makefile new file mode 100644 index 0000000..7d530a5 --- /dev/null +++ b/misc/Makefile @@ -0,0 +1,9 @@ +all: + for pdf in `ls -1 handout_*.tex pres_*.tex` ; do \ + TEXINPUTS=`pwd`/../..:.:..:$(TEXINPUTS) pdflatex $$pdf; \ + TEXINPUTS=`pwd`/../..:.:..:$(TEXINPUTS) pdflatex $$pdf; \ + done + +clean: + rm -f *.aux *.log *.pdf *.log *.snm *.toc *.vrb *.nav *.out + diff --git a/misc/pres_xml-fasttrack_en.tex b/misc/pres_xml-fasttrack_en.tex new file mode 100644 index 0000000..35027ee --- /dev/null +++ b/misc/pres_xml-fasttrack_en.tex @@ -0,0 +1,426 @@ +\def\lximg{/usr/share/lx/icons/fueller.png} + +\input{configpres} + +% ------------------------ +\section{Programming in C/C++} + +% ------------------------ +\subsection{XML Processing} + +\title{XML Processing in C/C++} +\maketitle + +\def\lximg{none} + +\begin{frame} +\frametitle{Contents} +\tableofcontents +\end{frame} + +% ------------------------ +\subsubsection{Basics} + +\begin{frame}[fragile] +\frametitle{What is XML?} +XML is +\begin{itemize} +\item a Markup Language to describe structured data +\item extensible by defining new data type definitions +\item human readable as well as machine readable +\end{itemize} + +{ \tiny +\begin{verbatim} + + + + + The Lord Of The Rings + J.R.R. Tolkien + + + The Wall + Pink Floyd + Another Brick in the Wall + Mother + + +\end{verbatim} +} +\end{frame} + +% ------------------------ +\subsubsection{Processing} + +\begin{frame}[fragile] +\frametitle{Own parser vs. using a common library} +Using a common library is the preferred solution +\begin{itemize} +\item XML can get very complex +\item own parsers might struggle with some exotic but allowed constructs +\item common libraries are (mostly) well tested +\item rapid prototyping with common libraries +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{GNOME XML library} +\begin{itemize} +\item libxml2 is the most common XML library for Linux and C/C++ +\item provides a large toolset for nearly all XML problems +\item can be used for small XML junks as well as for huge XML files or streams +\item support Document Object Model (DOM) as well as Simple API for XML (SAX) +\item support parse, generate and validate +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{Document Object Model (DOM)} +\begin{itemize} +\item DOM Parser creates a tree representation of the XML junk in main memory +\item Pros: + \begin{itemize} + \item navigation support + \item model can be modified + \item easy export of an existing model + \end{itemize} +\item Cons: + \begin{itemize} + \item large XML junks need lot of main memory + \item no stream handling support + \item slow for large XML files + \end{itemize} +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{Simple API for XML (SAX)} +\begin{itemize} +\item DOM tree parser uses SAX2 internally! +\item SAX uses callbacks for parsing events (start element, end element etc.) +\item Pros: + \begin{itemize} + \item lean and fast + \item large-file and stream handling support + \item memory footprint depends on callback implementation + \end{itemize} +\item Cons: + \begin{itemize} + \item no navigation support + \item no XML generation support + \end{itemize} +\end{itemize} +\end{frame} + +\begin{frame}[fragile] +\frametitle{Recommendation} +\begin{itemize} +\item choose the right parser for the right use case +\item DOM: + \begin{itemize} + \item small files + \item navigate/modify/generate + \item data model validation (DTD) + \end{itemize} +\item SAX2: + \begin{itemize} + \item streams or large files + \item preselect XML junks + \end{itemize} +\item combine SAX2 and DOM if necessary +\end{itemize} +\end{frame} + +% ------------------------ +\subsubsection{Examples} + +\begin{frame}[fragile] +\frametitle{DOM main()} +{ \tiny +\begin{verbatim} +#include +#include +#include + +static void print_element_names(xmlNode *); + +int main(int argc, char **argv) { + xmlDocPtr my_doc = NULL; + xmlNode *root_element = NULL; + + my_doc = xmlReadFile(argv[1], NULL, 0); // parse XML file + + root_element = xmlDocGetRootElement(my_doc); + + print_element_names(root_element); // output + + xmlFreeDoc(my_doc); + xmlCleanupParser(); + return 0; +} +\end{verbatim} +} +\end{frame} + +\begin{frame}[fragile] +\frametitle{DOM tree navigation and output} +{ \tiny +\begin{verbatim} +static void print_element_names(xmlNode * a_node) +{ + xmlNode *cur_node = NULL; + + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + printf("node type: Element, name: %s\n", cur_node->name); + } + + print_element_names(cur_node->children); + } +} +\end{verbatim} +} +\end{frame} + +\begin{frame}[fragile] +\frametitle{DOM: Input / Output} +\begin{columns} +\begin{column}{5cm} +{ \tiny +\begin{verbatim} + + + + +The Lord Of The Rings +J.R.R. Tolkien + + +The Wall +Pink Floyd + + Another Brick in the Wall +Mother + + +\end{verbatim} +} +\end{column} +\begin{column}{5cm} +{ \tiny +\begin{verbatim} + + +node type: Element, name: store + +node type: Element, name: book +node type: Element, name: title +node type: Element, name: author + +node type: Element, name: cd +node type: Element, name: title +node type: Element, name: artist +node type: Element, name: track + +node type: Element, name: track + + +\end{verbatim} +} +\end{column} +\end{columns} +\end{frame} + +\begin{frame}[fragile] +\frametitle{SAX2 main()} +{ \tiny +\begin{verbatim} +/* + * Simple SAX example + */ + +#include +#include +#include + +static int cb_total = 0; + +int main(int argc, char **argv) { + cb_total = 0; + + xmlSAXUserParseFile(debugSAXHandler, NULL, argv[1]); + + fprintf(stdout, "\ncallback calls: %d\n", cb_total); + + xmlCleanupParser(); + xmlMemoryDump(); + + return 0; +} +\end{verbatim} +} +\end{frame} + +\begin{frame}[fragile] +\frametitle{SAX2 callback implementations} +{ \tiny +\begin{verbatim} +static void cb_start_document(void *ctx ATTRIBUTE_UNUSED) +{ + cb_total++; + fprintf(stdout, "SAX.startDocument()\n"); +} + +static void cb_end_document(void *ctx ATTRIBUTE_UNUSED) +{ + cb_total++; + fprintf(stdout, "SAX.endDocument()\n"); +} + +static void cb_characters(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) +{ + char output[40]; + int i; + + cb_total++; + for (i = 0;(i + + + + + + +[...] + + +\end{verbatim} +} +\end{column} +\begin{column}{5cm} +{ \tiny +\begin{verbatim} +SAX.startDocument() +SAX.startElement(store) +SAX.characters( +, 1) +SAX.comment( Sample Bookstore ) +SAX.characters( +, 1) +[...] +SAX.endElement(store) +SAX.endDocument() +\end{verbatim} +} +\end{column} +\end{columns} +\end{frame} + +\begin{frame}[fragile] +\frametitle{SAX: Input / Output - Element} +\begin{columns} +\begin{column}{5cm} +{ \tiny +\begin{verbatim} + + + +The Lord Of The Rings + + + + +J.R.R. Tolkien + + + + + +\end{verbatim} +} +\end{column} +\begin{column}{5cm} +{ \tiny +\begin{verbatim} +SAX.startElement(book, isbn='10000001') +SAX.characters( +, 1) +SAX.startElement(title) +SAX.characters(The Lord Of The Rings, 21) +SAX.endElement(title) +SAX.characters( +, 1) +SAX.startElement(author) +SAX.characters(J.R.R. Tolkien, 13) +SAX.endElement(author) +SAX.characters( +, 1) +SAX.endElement(book) +\end{verbatim} +} +\end{column} +\end{columns} +\end{frame} + +% ------------------------ +\subsection{} +\begin{frame} +\frametitle{References} + +XML on W3C: +\begin{itemize} +\item \url{http://www.w3.org/XML/} +\item \url{http://www.w3.org/TR/REC-xml/} +\end{itemize} + +GNOME XML Library: +\begin{itemize} +\item \url{http://www.xmlsoft.org/} +\end{itemize} + +Wikipedia: +\begin{itemize} +\item \url{http://en.wikipedia.org/wiki/XML} +\end{itemize} +\end{frame} + +\input{tailpres} diff --git a/misc/samples/.gitignore b/misc/samples/.gitignore new file mode 100644 index 0000000..805c89c --- /dev/null +++ b/misc/samples/.gitignore @@ -0,0 +1,2 @@ +xml_dom +xml_sax diff --git a/misc/samples/Makefile b/misc/samples/Makefile new file mode 100644 index 0000000..cd411f2 --- /dev/null +++ b/misc/samples/Makefile @@ -0,0 +1,10 @@ +XML_TARGETS=xml_dom xml_sax +XML_CFLAGS=$(shell xml2-config --cflags) + +all: $(XML_TARGETS) + +%: %.c + $(CC) $(XML_CFLAGS) -g -O0 -l xml2 -o $@ $^ + +clean: + rm -r $(XML_TARGETS) diff --git a/misc/samples/xml_dom.c b/misc/samples/xml_dom.c new file mode 100644 index 0000000..66166dd --- /dev/null +++ b/misc/samples/xml_dom.c @@ -0,0 +1,55 @@ +#include +#include +#include + +static void print_element_names(xmlNode *); + +int main(int argc, char **argv) { + xmlDocPtr my_doc = NULL; + xmlNode *root_element = NULL; + char *filename; + int rc = 1; + + if (argc != 2) { + rc = 1; + goto out; + } + filename = argv[1]; + + /* ABI checking (opt.) */ + LIBXML_TEST_VERSION + + my_doc = xmlReadFile(filename, NULL, 0); + if (!my_doc) { + rc = 1; + goto out_cleanup; + } + + /*Get the root element node */ + root_element = xmlDocGetRootElement(my_doc); + + print_element_names(root_element); + + rc = 0; +out_freedoc: + /* Free parsed DOM tree */ + xmlFreeDoc(my_doc); +out_cleanup: + /* Cleanup function for the XML library */ + xmlCleanupParser(); +out: + return(rc); +} + +static void print_element_names(xmlNode * a_node) +{ + xmlNode *cur_node = NULL; + + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + printf("node type: Element, name: %s\n", cur_node->name); + } + + print_element_names(cur_node->children); + } +} diff --git a/misc/samples/xml_full.xml b/misc/samples/xml_full.xml new file mode 100644 index 0000000..c8b0ecd --- /dev/null +++ b/misc/samples/xml_full.xml @@ -0,0 +1,24 @@ + + + + +The Lord Of The Rings +J.R.R. Tolkien + + +Maitreyi +Mircea Eliade + + +The Wall +Pink Floyd +Another Brick in the Wall +Mother + + +Come on Over +Shania Twain +From This Moment On +You're Still The One + + diff --git a/misc/samples/xml_sax.c b/misc/samples/xml_sax.c new file mode 100644 index 0000000..b586a21 --- /dev/null +++ b/misc/samples/xml_sax.c @@ -0,0 +1,109 @@ +/* + * Simple SAX example + */ + +#include +#include +#include + +static int cb_total = 0; + +/* + * Callback implementations + */ +static void +cb_start_document(void *ctx ATTRIBUTE_UNUSED) +{ + cb_total++; + fprintf(stdout, "SAX.startDocument()\n"); +} + +static void +cb_end_document(void *ctx ATTRIBUTE_UNUSED) +{ + cb_total++; + fprintf(stdout, "SAX.endDocument()\n"); +} + +static void +cb_start_element(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name, const xmlChar **atts) +{ + int i; + + cb_total++; + fprintf(stdout, "SAX.startElement(%s", (char *) name); + if (atts != NULL) { + for (i = 0;(atts[i] != NULL);i++) { + fprintf(stdout, ", %s='", atts[i++]); + if (atts[i] != NULL) + fprintf(stdout, "%s'", atts[i]); + } + } + fprintf(stdout, ")\n"); +} + +static void +cb_end_element(void *ctx ATTRIBUTE_UNUSED, const xmlChar *name) +{ + cb_total++; + fprintf(stdout, "SAX.endElement(%s)\n", (char *) name); +} + +static void +cb_characters(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch, int len) +{ + char output[40]; + int i; + + cb_total++; + for (i = 0;(i + + + +The Lord Of The Rings +J.R.R. Tolkien + + +The Wall +Pink Floyd +Another Brick in the Wall +Mother + + diff --git a/misc/section.tex b/misc/section.tex new file mode 100644 index 0000000..d12f8a2 --- /dev/null +++ b/misc/section.tex @@ -0,0 +1,3 @@ +% Dummy section file for misc topics. +% Please specify the related section directly in the presentation. +% \section{} -- cgit v1.2.3 From fb94679a12508a61b45d13ca86c967c3979dffbb Mon Sep 17 00:00:00 2001 From: Jan Altenberg Date: Fri, 25 Jan 2013 11:27:16 +0100 Subject: Add ELBE to global Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0130884..ef20e74 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime security misc +SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics protocols realtime security misc distribution default: make all -- cgit v1.2.3 From f0c173214d2f37fa56a5dbad403e4b3827b9ddde Mon Sep 17 00:00:00 2001 From: Jan Altenberg Date: Fri, 25 Jan 2013 11:35:01 +0100 Subject: Fix broken clean target --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index ef20e74..0c57970 100644 --- a/Makefile +++ b/Makefile @@ -3,10 +3,12 @@ SUBDIRS = application-devel flash-memory frameworks kernel-devel linux-basics pr default: make all -all clean:: +all: for dir in $(SUBDIRS) ; do \ (cd $$dir && make $@); \ done + +clean: rm -rf pdf rm -f *.aux rm -f *.log @@ -18,7 +20,7 @@ all clean:: rm -f *.blg rm -f *.out rm -f *.vrb -pres:: +pres: mv configpres.tex _configpres.tex touch configpres.tex mv tailpres.tex _tailpres.tex @@ -30,7 +32,7 @@ pres:: mv _configpres.tex configpres.tex mv _tailpres.tex tailpres.tex rm configpres.tex tailpres.tex -book:: +book: mv confighandout.tex _confighandout.tex touch confighandout.tex mv tailhandout.tex _tailhandout.tex @@ -42,7 +44,7 @@ book:: rm confighandout.tailhandout.tex mv _confighandout.tex confighandout.tex mv _tailhandout.tex tailhandout.tex -pdf:: +pdf: rm -rf pdf mkdir -p pdf/pres mkdir -p pdf/handout -- cgit v1.2.3