aboutsummaryrefslogtreecommitdiff
path: root/doc/howto.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/howto.rst')
-rw-r--r--doc/howto.rst394
1 files changed, 394 insertions, 0 deletions
diff --git a/doc/howto.rst b/doc/howto.rst
new file mode 100644
index 000000000000..513572355bbc
--- /dev/null
+++ b/doc/howto.rst
@@ -0,0 +1,394 @@
+
+Howtos: Focused Directions
+==========================
+
+This section provides task-oriented instructions for selected tasks.
+If you have a task that needs instructions, please open a request as
+an enhancement issue on github.
+
+Howto: Report bugs
+------------------
+
+libxo uses github to track bugs or request enhancements. Please use
+the following URL:
+
+ https://github.com/Juniper/libxo/issues
+
+Howto: Install libxo
+--------------------
+
+libxo is open source, under a new BSD license. Source code is
+available on github, as are recent releases. To get the most
+current release, please visit:
+
+ https://github.com/Juniper/libxo/releases
+
+After downloading and untarring the source code, building involves the
+following steps::
+
+ sh bin/setup.sh
+ cd build
+ ../configure
+ make
+ make test
+ sudo make install
+
+libxo uses a distinct "*build*" directory to keep generated files
+separated from source files.
+
+.. index:: configure
+
+Use "`../configure --help`" to display available configuration
+options, which include the following::
+
+ --enable-warnings Turn on compiler warnings
+ --enable-debug Turn on debugging
+ --enable-text-only Turn on text-only rendering
+ --enable-printflike Enable use of GCC __printflike attribute
+ --disable-libxo-options Turn off support for LIBXO_OPTIONS
+ --with-gettext=PFX Specify location of gettext installation
+ --with-libslax-prefix=PFX Specify location of libslax config
+
+Compiler warnings are a very good thing, but recent compiler version
+have added some very pedantic checks. While every attempt is made to
+keep libxo code warning-free, warnings are now optional. If you are
+doing development work on libxo, it is required that you
+use --enable-warnings to keep the code warning free, but most users
+need not use this option.
+
+.. index:: --enable-text-only
+
+libxo provides the `--enable-text-only` option to reduce the
+footprint of the library for smaller installations. XML, JSON, and
+HTML rendering logic is removed.
+
+.. index:: --with-gettext
+
+The gettext library does not provide a simple means of learning its
+location, but libxo will look for it in /usr and /opt/local. If
+installed elsewhere, the installer will need to provide this
+information using the "`--with-gettext=/dir/path`" option.
+
+.. index:: libslax
+
+libslax is not required by libxo; it contains the "oxtradoc" program
+used to format documentation.
+
+For additional information, see :ref:`building`.
+
+Howto: Convert command line applications
+----------------------------------------
+
+Common question: How do I convert an existing command line application?
+
+There are four basic steps for converting command line application to
+use libxo::
+
+- Setting up the context
+- Converting printf calls
+- Creating hierarchy
+- Converting error functions
+
+Setting up the context
+~~~~~~~~~~~~~~~~~~~~~~
+
+To use libxo, you'll need to include the "xo.h" header file in your
+source code files::
+
+ #include <libxo/xo.h>
+
+In your main() function, you'll need to call xo_parse_args to handling
+argument parsing (:ref:`xo_parse_args`). This function removes
+libxo-specific arguments the program's argv and returns either the
+number of remaining arguments or -1 to indicate an error::
+
+ int
+ main (int argc, char **argv)
+ {
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return argc;
+ ....
+ }
+
+.. index:: atexit
+.. index:: xo_finish_atexit
+
+At the bottom of your main(), you'll need to call xo_finish() to
+complete output processing for the default handle (:ref:`handles`). This
+is required to flush internal information buffers. libxo provides the
+xo_finish_atexit function that is suitable for use with the
+:manpage:`atexit(3)` function::
+
+ atexit(xo_finish_atexit);
+
+Converting printf Calls
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The second task is inspecting code for :manpage:`printf(3)` calls and
+replacing them with xo_emit() calls. The format strings are similar
+in task, but libxo format strings wrap output fields in braces. The
+following two calls produce identical text output::
+
+ OLD::
+ printf("There are %d %s events\n", count, etype);
+
+ NEW::
+ xo_emit("There are {:count/%d} {:event} events\n", count, etype);
+
+"count" and "event" are used as names for JSON and XML output. The
+"count" field uses the format "%d" and "event" uses the default "%s"
+format. Both are "value" roles, which is the default role.
+
+Since text outside of output fields is passed verbatim, other roles
+are less important, but their proper use can help make output more
+useful. The "note" and "label" roles allow HTML output to recognize
+the relationship between text and the associated values, allowing
+appropriate "hover" and "onclick" behavior. Using the "units" role
+allows the presentation layer to perform conversions when needed. The
+"warning" and "error" roles allows use of color and font to draw
+attention to warnings. The "padding" role makes the use of vital
+whitespace more clear (:ref:`padding-role`).
+
+The "*title*" role indicates the headings of table and sections. This
+allows HTML output to use CSS to make this relationship more obvious::
+
+ OLD::
+ printf("Statistics:\n");
+
+ NEW::
+ xo_emit("{T:Statistics}:\n");
+
+The "*color*" roles controls foreground and background colors, as well
+as effects like bold and underline (see :ref:`color-role`)::
+
+ NEW::
+ xo_emit("{C:bold}required{C:}\n");
+
+Finally, the start- and stop-anchor roles allow justification and
+padding over multiple fields (see :ref:`anchor-role`)::
+
+ OLD::
+ snprintf(buf, sizeof(buf), "(%u/%u/%u)", min, ave, max);
+ printf("%30s", buf);
+
+ NEW::
+ xo_emit("{[:30}({:minimum/%u}/{:average/%u}/{:maximum/%u}{]:}",
+ min, ave, max);
+
+Creating Hierarchy
+~~~~~~~~~~~~~~~~~~
+
+Text output doesn't have any sort of hierarchy, but XML and JSON
+require this. Typically applications use indentation to represent
+these relationship::
+
+ OLD::
+ printf("table %d\n", tnum);
+ for (i = 0; i < tmax; i++) {
+ printf(" %s %d\n", table[i].name, table[i].size);
+ }
+
+ NEW::
+ xo_emit("{T:/table %d}\n", tnum);
+ xo_open_list("table");
+ for (i = 0; i < tmax; i++) {
+ xo_open_instance("table");
+ xo_emit("{P: }{k:name} {:size/%d}\n",
+ table[i].name, table[i].size);
+ xo_close_instance("table");
+ }
+ xo_close_list("table");
+
+The open and close list functions are used before and after the list,
+and the open and close instance functions are used before and after
+each instance with in the list.
+
+Typically these developer looks for a "for" loop as an indication of
+where to put these calls.
+
+In addition, the open and close container functions allow for
+organization levels of hierarchy::
+
+ OLD::
+ printf("Paging information:\n");
+ printf(" Free: %lu\n", free);
+ printf(" Active: %lu\n", active);
+ printf(" Inactive: %lu\n", inactive);
+
+ NEW::
+ xo_open_container("paging-information");
+ xo_emit("{P: }{L:Free: }{:free/%lu}\n", free);
+ xo_emit("{P: }{L:Active: }{:active/%lu}\n", active);
+ xo_emit("{P: }{L:Inactive: }{:inactive/%lu}\n", inactive);
+ xo_close_container("paging-information");
+
+Converting Error Functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+libxo provides variants of the standard error and warning functions,
+:manpage:`err(3)` and :manpage:`warn(3)`. There are two variants, one
+for putting the errors on standard error, and the other writes the
+errors and warnings to the handle using the appropriate encoding
+style::
+
+ OLD::
+ err(1, "cannot open output file: %s", file);
+
+ NEW::
+ xo_err(1, "cannot open output file: %s", file);
+ xo_emit_err(1, "cannot open output file: {:filename}", file);
+
+.. index:: xo_finish
+
+Call xo_finish
+~~~~~~~~~~~~~~
+
+One important item: call `xo_finish` at the end of your program so
+ensure that all buffered data is written out. You can call it
+explicitly call it, or use :manpage:`atexit(3)` to have
+`xo_finish_atexit` called implicitly on exit::
+
+ OLD::
+ exit(0);
+
+ NEW::
+ xo_finish();
+ exit(0);
+
+Howto: Use "xo" in Shell Scripts
+--------------------------------
+
+.. admonition:: Needed
+
+ Documentation is needed for this area.
+
+.. index:: Internationalization (i18n)
+.. index:: gettext
+.. index:: xopo
+
+.. _i18n:
+
+Howto: Internationalization (i18n)
+-----------------------------------------------
+
+ How do I use libxo to support internationalization?
+
+libxo allows format and field strings to be used a keys into message
+catalogs to enable translation into a user's native language by
+invoking the standard :manpage:`gettext(3)` functions.
+
+gettext setup is a bit complicated: text strings are extracted from
+source files into "*portable object template*" (.pot) files using the
+`xgettext` command. For each language, this template file is used as
+the source for a message catalog in the "*portable object*" (.po)
+format, which are translated by hand and compiled into "*machine
+object*" (.mo) files using the `msgfmt` command. The .mo files are
+then typically installed in the /usr/share/locale or
+/opt/local/share/locale directories. At run time, the user's language
+settings are used to select a .mo file which is searched for matching
+messages. Text strings in the source code are used as keys to look up
+the native language strings in the .mo file.
+
+Since the xo_emit format string is used as the key into the message
+catalog, libxo removes unimportant field formatting and modifiers from
+the format string before use so that minor formatting changes will not
+impact the expensive translation process. We don't want a developer
+change such as changing "/%06d" to "/%08d" to force hand inspection of
+all .po files. The simplified version can be generated for a single
+message using the `xopo -s $text` command, or an entire .pot can be
+translated using the `xopo -f $input -o $output` command::
+
+ EXAMPLE:
+ % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
+ There are {:count} {:event} events\n
+
+ Recommended workflow:
+ # Extract text messages
+ xgettext --default-domain=foo --no-wrap \
+ --add-comments --keyword=xo_emit --keyword=xo_emit_h \
+ --keyword=xo_emit_warn -C -E -n --foreign-user \
+ -o foo.pot.raw foo.c
+
+ # Simplify format strings for libxo
+ xopo -f foo.pot.raw -o foo.pot
+
+ # For a new language, just copy the file
+ cp foo.pot po/LC/my_lang/foo.po
+
+ # For an existing language:
+ msgmerge --no-wrap po/LC/my_lang/foo.po \
+ foo.pot -o po/LC/my_lang/foo.po.new
+
+ # Now the hard part: translate foo.po using tools
+ # like poedit or emacs' po-mode
+
+ # Compile the finished file; Use of msgfmt's "-v" option is
+ # strongly encouraged, so that "fuzzy" entries are reported.
+ msgfmt -v -o po/my_lang/LC_MESSAGES/foo.mo po/my_lang/foo.po
+
+ # Install the .mo file
+ sudo cp po/my_lang/LC_MESSAGES/foo.mo \
+ /opt/local/share/locale/my_lang/LC_MESSAGE/
+
+Once these steps are complete, you can use the `gettext` command to
+test the message catalog::
+
+ gettext -d foo -e "some text"
+
+i18n and xo_emit
+~~~~~~~~~~~~~~~~
+
+There are three features used in libxo used to support i18n:
+
+- The "{G:}" role looks for a translation of the format string.
+- The "{g:}" modifier looks for a translation of the field.
+- The "{p:}" modifier looks for a pluralized version of the field.
+
+Together these three flags allows a single function call to give
+native language support, as well as libxo's normal XML, JSON, and HTML
+support::
+
+ printf(gettext("Received %zu %s from {g:server} server\n"),
+ counter, ngettext("byte", "bytes", counter),
+ gettext("web"));
+
+ xo_emit("{G:}Received {:received/%zu} {Ngp:byte,bytes} "
+ "from {g:server} server\n", counter, "web");
+
+libxo will see the "{G:}" role and will first simplify the format
+string, removing field formats and modifiers::
+
+ "Received {:received} {N:byte,bytes} from {:server} server\n"
+
+libxo calls :manpage:`gettext(3)` with that string to get a localized
+version. If your language were *Pig Latin*, the result might look
+like::
+
+ "Eceivedray {:received} {N:byte,bytes} omfray "
+ "{:server} erversay\n"
+
+Note the field names do not change and they should not be translated.
+The contents of the note ("byte,bytes") should also not be translated,
+since the "g" modifier will need the untranslated value as the key for
+the message catalog.
+
+The field "{g:server}" requests the rendered value of the field be
+translated using :manpage:`gettext(3)`. In this example, "web" would
+be used.
+
+The field "{Ngp:byte,bytes}" shows an example of plural form using the
+"{p:}" modifier with the "{g:}" modifier. The base singular and plural
+forms appear inside the field, separated by a comma. At run time,
+libxo uses the previous field's numeric value to decide which form to
+use by calling :manpage:`ngettext(3)`.
+
+If a domain name is needed, it can be supplied as the content of the
+{G:} role. Domain names remain in use throughout the format string
+until cleared with another domain name::
+
+ printf(dgettext("dns", "Host %s not found: %d(%s)\n"),
+ name, errno, dgettext("strerror", strerror(errno)));
+
+ xo_emit("{G:dns}Host {:hostname} not found: "
+ "%d({G:strerror}{g:%m})\n", name, errno);