diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/htmlbook.ctr |
Initial commit
Diffstat (limited to 'support/dktools/htmlbook.ctr')
-rw-r--r-- | support/dktools/htmlbook.ctr | 2867 |
1 files changed, 2867 insertions, 0 deletions
diff --git a/support/dktools/htmlbook.ctr b/support/dktools/htmlbook.ctr new file mode 100644 index 0000000000..fd679bcad8 --- /dev/null +++ b/support/dktools/htmlbook.ctr @@ -0,0 +1,2867 @@ +%% options + +copyright owner = Dirk Krause +copyright year = 2013-xxxx +license = bsd + + + +%% header + +#include "dk3conf.h" +#include "dk3types.h" +#include "dk3numco.h" + + + +/** Image dimension cache entry. +*/ +typedef struct { + dkChar *fn; /**< Image name. */ + unsigned long w; /**< Image width. */ + unsigned long h; /**< Image height. */ +} hb_img_dim_t; + + + +/** External link. +*/ +typedef struct { + dkChar *url; /**< Link URL. */ + unsigned long lno; /**< Link number within current page. */ +} hb_link_t; + + + +/** One contents line. +*/ +typedef struct { + dkChar *text; /**< Allocated line text. */ + dkChar *aname; /**< The a name text (if any). */ + dkChar *realtext; /**< Real start of text for header. */ + unsigned long lineno; /**< Line number. */ + unsigned long header; /**< Running number of header. */ + unsigned headlevel; /**< Header level (1 to 6). */ + int lt; /**< Line type (0=normal, 1=header). */ +} hb_line_t; + + + +/** One node in the document tree. +*/ +struct hb__node_t { + struct hb__node_t *parent; /**< Parent node. */ + struct hb__node_t *curchild; /**< Current child to edit. */ + struct hb__node_t *jumpnode; /**< Link target node. */ + dk3_sto_t *s_subnodes; /**< Subnodes collection. */ + dk3_sto_it_t *i_subnodes; /**< Subnodes iterator. */ + dk3_sto_t *s_variables; /**< Variables storage. */ + dk3_sto_it_t *i_variables; /**< Variables iterator. */ + dk3_sto_t *s_lines; /**< Contents lines storage. */ + dk3_sto_it_t *i_lines; /**< Contents lines iterator. */ + dk3_sto_t *s_lbyurl; /**< Storage for links by URL. */ + dk3_sto_it_t *i_lbyurl; /**< Iterator for links by URL. */ + dk3_sto_t *s_lbylno; /**< Storage for links by number. */ + dk3_sto_it_t *i_lbylno; /**< Iterator for links by number. */ + dk3_sto_t *s_jsfiles; /**< Storage for JS files. */ + dk3_sto_it_t *i_jsfiles; /**< Iterator for JS files. */ + dkChar *title; /**< Node title. */ + dkChar *shorttitle; /**< Short title (optional). */ + dkChar *fulltitle; /**< Full title (browser title bar). */ + dkChar *filename; /**< Text file name (optional). */ + dkChar *suffix; /**< Output file name suffix (opt). */ + dkChar *template; /**< Template file name (optional). */ + dkChar *stylefile; /**< Style file. */ + dkChar *author; /**< Name of author. */ + dkChar *location; /**< Location (city) of author. */ + dkChar *icontoc; /**< File name TOC icon. */ + dkChar *iconprev; /**< File name previous section icon. */ + dkChar *iconnext; /**< File name next section icon. */ + dkChar *iconindex; /**< File name index icon. */ + dkChar *iconhome; /**< File name home icon. */ + dkChar *favicon; /**< favicon. */ + dkChar *metadesc; /**< Meta description tag. */ + dkChar *metakeyw; /**< Meta keywords tag. */ + dkChar const *outFileName; /**< Output file name. */ + unsigned long lineno; /**< Line number in project file. */ + unsigned long objno; /**< Object index. */ + unsigned long pobjno; /**< Printable object number. */ + unsigned long nextlink; /**< Next link number. */ + unsigned long nextindex; /**< Next index entry number. */ + unsigned long headno; /**< Head number. */ + unsigned long nextsubheadno; /**< Next head number for sub node. */ + unsigned long nextjs; /**< Number of next js file. */ + long contnum; /**< Context number. */ + unsigned options; /**< Options for node. */ + int indent; /**< Line indent (number o spaces). */ + int depth; /**< Depth. */ + int tocstate; /**< State when creating TOC. */ + int inenc; /**< Text file input encoding. */ + int havenavimenu; /**< Flag: Already have navi menu. */ +}; + +/** One node in the document tree. +*/ +typedef struct hb__node_t hb_node_t; + + + +/** Entry in keyword index. +*/ +typedef struct { + dkChar *tx; /**< Keyword index text. */ + dkChar *fn; /**< File name. */ + dkChar *an; /**< Anchor name (optional). */ + unsigned long ul; /**< Anchor number (if no name available). */ + hb_node_t *no; /**< Node for file name (needed for title). */ +} hb_index_entry_t; + + + +/** Job type for the htmlbook program. + The s_nodes storage contains a plain list of all nodes, + this storage is used to release all nodes at the end of the program. + The s_pnodes storage contains a plain list of all nodes to + write output for. + The tree structure is below the rootnode element. +*/ +typedef struct { + dk3_tm_t starttime; /**< Start time. */ + dk3_app_t *app; /**< Application structure. */ + dkChar const * const *msg; /**< Localized messages. */ + dkChar const * const *kwnl; /**< Keywords, not localized. */ + dk3_option_set_t *opt; /**< Command line options. */ + dk3_sto_t *s_nodes; /**< All nodes storage. */ + dk3_sto_it_t *i_nodes; /**< All nodes storage iterator. */ + dk3_sto_t *s_pnodes; /**< Leaf nodes storage. */ + dk3_sto_it_t *i_pnodes; /**< Leaf nodes storage iterator. */ + dk3_sto_t *s_files; /**< Additional files storage. */ + dk3_sto_it_t *i_files; /**< Additional files iterator. */ + dk3_sto_t *s_index; /**< Index entries storage. */ + dk3_sto_it_t *i_index; /**< Index entries storage iterator. */ + dk3_sto_t *s_optsect; /**< Optional sections storage. */ + dk3_sto_it_t *i_optsect; /**< Optional sections iterator. */ + dk3_sto_t *s_imgdim; /**< Image dimension cache storage. */ + dk3_sto_it_t *i_imgdim; /**< Image dimension cache iterator. */ + hb_node_t *rootnode; /**< Root node. */ + hb_node_t *currentnode; /**< Current node to modify. */ + hb_node_t *impressumnode; /**< Impressum node. */ + hb_node_t *firstnode; /**< First pnode. */ + hb_node_t *lastnode; /**< Last pnode. */ + dkChar const *infilename; /**< Input file name (project). */ + dkChar const *outputdir; /**< Output directory (allocated). */ + dkChar const *outputscript; /**< Name of script to produce. */ + dkChar const *url; /**< URL to publish the results. */ + dkChar const *indexfile; /**< Typically index html. */ + dkChar const *impressumlink; /**< Link to impressum. */ + dkChar const *chmlang; /**< Language setting for CHM. */ + dkChar *shipbuffer; /**< Shipout buffer. */ + dkChar *iltemplate; /**< Input line from template. */ + dkChar *ilfile; /**< Input line from file. */ + dkChar *special; /**< Buffer for current special. */ + dk3_c32_t *buffer32; /**< Buffer for 32-bit characters. */ + FILE *of; /**< Output file. */ + unsigned long lineno; /**< Line number. */ + unsigned long nextobj; /**< Next object number. */ + unsigned long npobjs; /**< Number of printable objects. */ + size_t bs; /**< Buffer size. */ + size_t spused; /**< Number elements used in special. */ + size_t shipused; /**< Shipout buffer used. */ + unsigned options; /**< Job options. */ + int iecmd; /**< Input encoding from cmd args. */ + int actsect; /**< Flag: Active section. */ + int cmd; /**< Option processing result. */ + int exv; /**< Exit status code. */ + int cs; /**< Character set for HTML output. */ + int secttype; /**< Section type. */ + int non_url; /**< Flag: Non-URL characters found. */ + int maxdepth; /**< Maximum depth of a node. */ + int headlevels; /**< Maximum depth to print header. */ + int coli; /**< Current code line number. */ + int cols; /**< Code line state. */ +} hb_job_t; + + + +/** File processing help structure. +*/ +typedef struct { + hb_job_t *job; /**< Job structure. */ + hb_node_t *p; /**< Previous node. */ + hb_node_t *n; /**< Next node. */ + int in_template; /**< Flag: Processing template. */ + int stm; /**< State machine. */ +} hb_file_processor_t; + + + +/** @defgroup hboptions Node options from project file. */ +/**@{*/ + +/** Write page TOC. +*/ +#define HB_NODE_OPT_PAGE_TOC 0x0001U + +/** Replace ampersand. +*/ +#define HB_NODE_OPT_REPLACE_AMPERSAND 0x0002U + +/** Use tidy while copying. +*/ +#define HB_NODE_OPT_USE_TIDY 0x0004U + +/** Write header chain. +*/ +#define HB_NODE_OPT_HEADER_CHAIN 0x0008U + +/** Indicate the impressum node. +*/ +#define HB_NODE_OPT_IMPRESSUM 0x0010U + +/** Stop inheritance of JS files at this node. +*/ +#define HB_NODE_OPT_STOP_JS_INHERITANCE 0x0020U + +/**@}*/ + + + +/** @defgroup hbjoboptions Job options. */ +/**@{*/ + +/** Create index file. +*/ +#define HB_JOB_OPT_CREATE_INDEX 0x0001U + +/** Create table of contents. +*/ +#define HB_JOB_OPT_CREATE_TOC 0x0002U + +/** Currently processing code. +*/ +#define HB_JOB_OPT_CODE 0x0004U + +/** Produce output for building a chm file. +*/ +#define HB_JOB_OPT_CHM 0x0008U + +/** Use ln instead of cp for resource files. +*/ +#define HB_JOB_OPT_LN 0x0010U + +/** Write section number in positions table. +*/ +#define HB_JOB_OPT_NUM_IN_POS 0x0020U + +/** Write section number in keyword index. +*/ +#define HB_JOB_OPT_NUM_IN_IDX 0x0040U + +/** Write section number in page header. +*/ +#define HB_JOB_OPT_NUM_IN_PAGE_HEADER 0x0080U + +/** Enable full text search in chm output. +*/ +#define HB_JOB_OPT_CHM_FULL_TEXT_SEARCH 0x0100U + +/** Print line numbers for code. +*/ +#define HB_JOB_OPT_CODE_LINE_NUMBERS 0x0200U + +/**@}*/ + + + +/** @defgroup hbcharsets Character sets used by htmlbook. */ +/**@{*/ + +/** Character set us-ascii. +*/ +#define HB_CS_ASCII 0 + +/** Character set UTF-8. +*/ +#define HB_CS_UTF_8 1 + +/**@}*/ + + + +/** @defgroup hbsections Section types. */ +/**@{*/ + +/** Section type not yet known. +*/ +#define HB_SECTION_UNKNOWN 0 + +/** Options section. +*/ +#define HB_SECTION_OPTIONS 1 + +/** Files section. +*/ +#define HB_SECTION_FILES 2 + +/** Contents section. +*/ +#define HB_SECTION_CONTENTS 3 + +/**@}*/ + + + +/** @defgroup hbtocstate Node state when creating TOC. */ +/**@{*/ + +/** Work on this node is not yet in progress. +*/ +#define HB_TOC_STATE_INIT 0 + +/** Work on this node is in progress. +*/ +#define HB_TOC_STATE_IN_PROGRESS 1 + +/** Work on this node is finished. +*/ +#define HB_TOC_STATE_FINISHED 2 + +/**@}*/ + + + +/** @defgroup hbcolist Code line states. */ +/**@{*/ + +/** Directly after code special command. +*/ +#define HB_COLIST_NONE 0 + +/** In a new line, no contents yet thus no opened code tag. +*/ +#define HB_COLIST_NOT_OPENED 1 + +/** Code tag was opened and must be closed. +*/ +#define HB_COLIST_OPENED 2 + +/**@}*/ + + + +/** Maximum line length. +*/ +#define HB_LINE_LENGTH 16383 + + +#include "hbnode.h" +#include "hbconf.h" +#include "hbhtml.h" +#include "hbtool.h" +#include "hbcont.h" +#include "hbindex.h" +#include "hbimgdim.h" +#include "hbchm.h" +#include "dk3strkv.h" +#include "dk3kv.h" +#include "dk3se.h" + + + +%% module + +#include "dk3all.h" +#if 0 +#include "dkt-version.h" +#endif +#include "dk4vers.h" +#include "htmlbook.h" + + +/* Synopsis: + htmlbook -h | --help + htmlbook -v | --version + htmlbook -L | --license + htmlbook [<options>] <project> + + Options: +*/ + + +$!trace-include + + + +/** @defgroup hbcmd Commands for htmlbook. */ +/**@{*/ +/** Print help. +*/ +#define HB_CMD_HELP 1 +/** Print version number. +*/ +#define HB_CMD_VERSION 2 +/** Print license terms. +*/ +#define HB_CMD_LICENSE 4 +/**@}*/ + + + +/** Version information. +*/ +static dkChar const *hb_version[] = { + dkT("htmlbook "), + DKT_VERSION_DK +}; + + + +/** License conditions. +*/ +static dkChar const * const hb_license[] = { +$!text macro=dkT + +Copyright (c) 2013-2016, Dirk Krause +All rights reserved. + +Redistribution and use in source and binary forms, +with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. +* Neither the name of the copyright holder(s) nor the names of + contributors may be used to endorse or promote + products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +$!end +}; + + + +/** Help text shown if help file is not found. +*/ +static dkChar const * const hb_help_text[] = { +$!text macro=dkT + +NAME + +htmlbook - Create HTML book structure + +SYNOPSIS + + htmlbook [<option>] <file> + htmlbook -h + htmlbook -v + htmlbook -L + +DESCRIPTION + +The program creates a HTML book structure in a specified output directory. +Configuration is read from a project file specified on the command line. + +OPTIONS + +-i <encoding> | --input-encoding=<encoding> + Input encoding for project file to process. + +-o name[,name...] + Activate optional project file sections. + +-s name=value | --set=name=value + Set variables (overwrite variables from options section). + +-h | --help + Show help text. + +-v | --version + Show version information. + +-L | --license + Show license terms. + +EXIT STATUS + +0 on success, all other exit status codes indicate an error. + +FILES + +The project file contains project settings and information about the +document structure (text files and used template files). + +Project file +------------ +A project file consists of three sections: ``[options]'', ``[files]'', and +``[contents]''. A project file can contain optional sections +``[options:<name>]'', ``[files:<name>]'', and ``[contents:<name>]''. Optional +sections are only processed when activated by the -o command line option. +On Windows systems optional sections named ``windows'' are activated +automatically, on non-Windows systems sections named ``non-windows'' are +activated automatically. + +The options section contains ``key=value'' lines for the following keys: + + output directory Name of output directory. This directory is + removed completely and created again each + time the output script is run. + + output script Script to re-create the output directory and + copy files into it. + + title Document or collection title. + + url URL to access the document collection via web. + + index file Name of file containing text for start page. + + html charset Character set for output HTML files + (``us-ascii'', ``ascii'', or ``utf-8''). + + template Name of default template file (``web.hbt''). + + style Name of default style file (``style.css''). + + page toc Flag: Create an intra-page table of contents. + + create toc Flag: Create table of contents. + + create index Flag: Create keyword index. + + section numbers in index Flag: Write section numbers in index. + + replace ampersand Flag: Replace ampersand in texts (no). + + tidy Flag: Use tidy for inspection and correction + of HTML output files. + + ln Flag: Use ln command instead of cp to save + disk space. + + author Author name. + + location Location of author. + + write position Flag: Write position within the collection at + start of page. + + section numbers in position Flag: Write section number in position. + + shortcut icon URL to shortcut icon. + + icon toc File names for icons in navigation bar. + icon previous + icon next + icon index + + impressum link URL to impressum. + + impressum page Name of text file for impressum (you can use + either impressum link or impressum page). + + chm Flag: Create HTML to produce a CHM file later. + + chm language Language setting for CHM project + (``0x409 English (USA)''). + + js file File name of JavaScript file. + + inherit js Flag: Inherit JavaScript files from parents. + + var Set variable (the first text word on the + right side is the variable name, the + remainder of the line is the variable value). + +The ``[files]'' section lists the name of additional files to copy, +one per line. + +The ``[contents]'' section contains the tree structure for navigation. +Each subsection for a node is started by a title line. +The indent level corresponds to the tree structure. +Title lines with same indent level are neighbours (sub-nodes of the same +parent node). A nodes parent node is the next node above the node with +smaller indent. +After the node title there are lines started by @ to configure the node: + + file = <File> Text file for the nodes contents. + input encoding = <Encoding> Default encoding to use if no BOM is found. + suffix = <String> File name suffix for output file. + short = <Short title> Short title for use in the navigation menu. + +Additionally you can use the ``html charset'', ``template'', ``style'', +``page toc'', ``write position'', ``replace ampersand'', ``tidy'', ``ln'', +``author'', ``location'', ``js file'', ``inherit js'', ``var'', +``icon toc'', ``icon previous'', ``icon next'', ``icon index'', and +``shortcut icon'' settings as shown for the options section. + +Leafs (nodes without further subnodes) must have a text file configured, +for other nodes it's optional. + +Template file +------------- +The template file specifies the text between <BODY> and </BODY>. +Special commands %%command%% can be used to insert the text, the navigation +menu, navigation blocks with clickable icons. +The following special commands are available: + + \%%contents%% Insert the text file contents. + + \%%title%% Insert the node title. + + \%%img <options>%% Insert an image. The following options + are available: + div[=bool] Create <div> around <img> + centered[=bool] Show image centered, not left-aligned. + src=file File name for image. + alt="text" Alternative text for image. + title[="text"] Title text (alt= is used as default). + caption[="text"] Image caption. + longdesc=URL File containing long description of image. + border=width Border width. + height=height Image height. + width=width Image width. + svg=file SVG version of image. + svgwh[=bool] Apply PNG/JPEG dimensions to SVG object. + object[=bool] Create object for SVG. + pdf=file PDF version of image. + larger=file Larger version of image. + ismap[=bool] Set ismap attribute. + usemap=file Image map file. + name=name Item name. + id=name ID for CSS styling. + class=name Class name for CSS styling. + align=name Alignment. + vspace=distance Vertical space. + hspace=distance Horizontal space. + downloads[=bool] Provide links to download vector graphics + cache Cache image dimensions for images used multiple + times. Image dimensions for images used in + a template are cached automatically. + + \%%menu <options>%% Insert the navigation menu. + The following options are available: + style=... One from ``reverse'' (full menu in reverse + order), ``full'' (full menu), ``top'' (show + only first hierarchy level) or ``current'' + (show only current hierarchy level). + sub[=bool] Flag: Show subnodes of current node. + + \%%navigation <options>%% Insert a navigation block. + The following options are available: + itop=file Icon for table of contents (``toc.png''). + iprev=file Icon for previous section (``prev.png''). + inext=file Icon for next section (``next.png''). + ikind=file Icon for keyword index (``index.png''). + + \%%author%% Insert the author name. + + \%%location%% Insert the authors location. + + \%%date <options>%% Insert the current node. + The following options are available: + style=name Date style, currently only ``german'' is + allowed to switch from the default + ``yyyy-mm-dd'' to ``dd.mm.yyyy''. + + \%%var <name> <options>%% Insert a variable value. + The following options are available: + url[=bool] Flag: Encode as URL, not as text. + + \%%code <options>%% Output encoding. By default the + ``<'', ``>'' are not replaced by ``<'', and + ``>'' as we expect to get correct HTML + from the text files. Replacement of ``&'' + by ``&'' is controlled by the + ``replace ampersand'' setting in the options + section. + In code mode our text comes from a source + code file, so we have to encode these + characters for HTML output. + The following options are available: + enable[=bool] Turn code mode on. + on[=bool] Turn code mode on. + disable[=bool] Turn code mode off. + off[=bool] Turn code mode off. + toggle Toggle code mode. + + \%%a <options>%% Insert a named anchor or a hyperlink. + The following options are available: + name=name Anchor name. + href=URL Link destination. + title=``text'' Text to show when mouse is over link. + text=``text'' Text for hyperlink. + target=destination Destination windows or frame, i.e. ``_blank''. + type=text MIME type. + external[=bool] Override result of internal/external test. + id=text ID for CSS styling. + class=text Class name for CSS styling. + style=text Direct style information. + hreflang=text Language for href text. + charset=text Character set. + onblur=text Script to execute when link looses focus. + onfocus=text Script to execute when link gets focus. + accesskey=text Hotkey for link. + tabindex=number Tabulator index. + shape=text Link shape form. + coords=text Coordinates. + rel=text Information for link to next element. + rev=text Information for link to previous element. + + \%%menuentry <options>%% Insert code to visualize a menu entry. + The following options are available: + item=``text'' Text of the menu entry, can be used + multiple times for hierarchical menus. + + \%%sourcefile <options>%% Show a file contents in a <PRE></PRE> + environment and provide a download + hyperlink. The following options are available: + file=file File name. + type=text MIME type. + title=``text'' Text shown when mouse is over hyperlink. + +Text file +--------- +Text files contain the page contents. +You can use headings like + .1 @name@ Heading text +for a structural document. Depths 1, 2, 3, 4, or 5 are converted to +<h2>...<h6> headers. A <h1> header is used for the page title. +The @name@ specification is optional, it results in a named anchor + <a name="name"></a> +before the heading. If the name specification is omitted, an anchor name +is generated automatically. + +Text files can use the special commands listed in ``Template file'', execpt +\%%contents%%. Additionally the following special command can be used +in text files: + + \%%index <options>%% Add an entry to the keyword index. + The following options can be used: + text=``text'' Keyword. + name=``text'' Name of a named anchor. + reference[=bool] Flag: Use existing named anchor, do not + create an anchor. +NOTES + +All text files, style files and images must be local files +in the current working directory. + +AUTHOR + +Dirk krause + +COPYRIGHT AND LICENSE + +Run + htmlbook --license +to see the license conditions. + +SEE ALSO + +tidy + +$!end +}; + + + +/** 8-bit character keywords. +*/ +static char const * const hb_c8_kw[] = { +$!string-table +# +# 0 1 Newline and space +# +\n + +# +# 2 3 DOS command to remove directory +# +RD /S /Q " +"\n +# +# 4 5 UNIX command to remove directory +# +rm -fr ' +'\n +# +# 6 DOS command to create a directory +# +MKDIR " +# +# 7 Unix command to create a directory +# +mkdir -p ' +# +# 8 9 +# +IF NOT EXIST " +" ECHO ERROR File does not exist: +# +# 10 11 12 13 +# +IF EXIST " +" XCOPY " +" " +\\" /Y /Q\n +# +# 14 15 16 17 18 +# +if [ -f ' +' ]\n +then\n +else\n +fi\n +# +# 19 20 21 +# +ln ' +cp ' +' ' +# +# 22 23 +# +echo 'ERROR: File + does not exist'\n +# +# 24 25 26 +# +tidy -q -utf8 < " +tidy -q -ascii < " +" > " +# +# 27 28 29 30 +# +tidy -q -utf8 < ' +tidy -q -ascii < ' +' > ' +/ +# +# 31 32 33 34 35 +# +@ECHO OFF\n +\#! /bin/sh\n +EXITCODE=0\n +exit $EXITCODE\n +EXITCODE=1\n +# +# 36 +# +ECHO TIDY +# +# 37 +# +echo TIDY +# +# 38 39 +# +" DEL /Q " +"\n +# +# 40 41 42 +# +find ' +' -type d -exec chmod ugo+rx {} \\;\n +' -type f -exec chmod ugo+r {} \\;\n +$!end +}; + + + +/** Fixed keywords (not localized). +*/ +static dkChar const * const hb_kwnl[] = { +$!string-table macro=dkT +# +# 0: Program group name +# +dktools +# +# 1: String table file name +# +htmlbook.str +# +# 2: Help text file name. +# +htmlbook.txt +# +# 3: Configuration file name +# +htmlbook.conf +# +# 4: File name for TOC icon +# +toc.png +# +# 5: File name for previous section icon +# +prev.png +# +# 6: File name for next section icon +# +next.png +# +# 7: File name for index icon +# +index.png +# +# 8: Name of root node output file +# +index.html +# +# 9: Dot for file name suffix. +# +. +# +# 10: Default suffix. +# +html +# +# 11: Alternative date style +# +german +# +# 12: url keyword var special command +# +url +# +# 13: internal anchor for keyword index +# +\#hb_index +# +# 14 15 16 17 Icon file names for navigation +# +toc.png +prev.png +next.png +index.png +# +# 18 19 Section names +# +windows +non-windows +# +# 20 21 Protocols +# +http:// +ftp:// +# +# 22 File open mode write +# +w +# +# 23 24 +# +html +htm +# +# 25 Switch back to standard encoding +# +none +# +# 26 Name of hhc.exe project file +# +project.hhp +# +# 27 Name of hhc.exe output file +# +index.chm +# +# 28 Name of hhc.exe contents file +# +contents.hhc +# +# 29 Name of hhc.exe index file +# +index.hhk +# +# 30 File open mode +# +wb +# +# 31 Anchor name for TOC +# +\#hb_toc +# +# 32 Long option to set variables +# +set +# +# 33 34 +# +SVG +PDF +# +# 35 (space) +# + +# +# 36 (index.xml file name for chmcmd) +# +project.xml +# +# 37 (icon file name for home button) +# +home.png +$!end +}; + + + +/** Default message texts. +*/ +static dkChar const * const hb_kw[] = { +$!string-table macro=dkT +# +# 0: Title for impressum page +# +Impressum +# +# 1: Link title +# +Go to start page: +# +# 2: Link title +# +At start page. +# +# 3: Link title +# +Go to previous page: +# +# 4: Link title +# +At first page. +# +# 5: Link title +# +Go to next page: +# +# 6: Link title +# +At last page. +# +# 7: Link title +# +Go to keyword index. +# +# 8: Syntax error, missing = +# +Syntax error, missing "="! +# +# 9: Syntax error, empty value! +# +Syntax error, empty value! +# +# 10: Syntax error, only allowed in options section +# +Syntax error, setting only allowed in options section! +# +# 11: Syntax error, illegal character set +# +Syntax error, illegal character set!\nOnly "ascii" or "utf-8" allowed. +# +# 12: Syntax error, no path specification in file name allowed! +# +Syntax error, no path specification in file name allowed! +# +# 13: Missing project file name +# +Missing project file name! +# +# 14: Too many project files specified, just one allowed! +# +Too many project file specified, just one allowed! +# +# 15: No parent candidate found! +# +No parent candidate found (probably a bug)! +# +# 16 +# +Syntax error, missing section name! +# +# 17 +# +Syntax error, missing closing square bracket! +# +# 18 +# +Syntax error, illegal section name! +# +# 19 +# +No template for node! +# +# 20 +# +Failed to obtain file name (probably a bug)! +# +# 21 22 +# +String " +" contains characters not usable in an URL! +# +# 23 Header External links +# +External links +# +# 24 Error: No source file +# +No source file specified! +# +# 25 26 Error: Illegal menu style +# +Syntax error, illegal menu style: " +"! +# +# 27 ERROR: Illegal key +# +Syntax error, illegal key (attribute name): " +# +# 28 ERROR: Contents is allowed only in templates! +# +Syntax error, "%%contents%%" is only allowed in templates! +# +# 29 ERROR: Illegal special command +# +Syntax error, illegal special command: " +# +# 30 ERROR: Parsing failed +# +Syntax error, parsing special command failed near:\n" +# +# 31 ERROR: Line too long +# +Line too long:\n" +# +# 32 +# +Syntax error, missing header text! +# +# 33 +# +Syntax error, missing closing ``@''! +# +# 34 +# +Syntax error, missing text after ``@''! +# +# 35 +# +Syntax error, missing header level! +# +# 36 +# +Syntax error, no text after leading ``.'' in line! +# +# 37 +# +Header level corrected to allowed maximum 6! +# +# 38 +# +Syntax error, ''url'' can be set in options section only! +# +# 39 +# +Failed to process a special command! +# +# 40 +# +Syntax error, parsing special command arguments failed! +# +# 41 +# +Syntax error, too many items for menu entry! +# +# 42 +# +Syntax error, no items for menu entry! +# +# 43 44 +# +Syntax error, illegal configuration key: " +"! +# +# 45 +# +Table of contents +# +# 46 +# +Keyword and key phrases index +# +# 47 +# +No default topic found! +# +# 48 +# +Missing ``text'' attribute! +# +# 49 +# +Missing ``file'' attribute! +# +# 50 +# +The ``index'' special command can not be used in template! +# +# 51 +# +No destination file for link found! +# +# 52 53 +# +No text node for title:\n" +"! +# +# 54 55 56 57 +# +Current position +Page table of contents +External links +Table of contents +# +# 58 59 +# +Large +Image +# +# 60 +# +Menu entry +# +# 61 Text "Impressum" used in the HTML head range link tag. +# +Impressum +# +# 62 Error message, unfinished command! +# +Unfinished ``%%'' command! +# +# 63 64 +# +Not a backslash escape sequence: `` +''! +# +# 65 +# +Image +# +# 66 +# +Overwriting ``div'' option by ``table''! +# +# 67 68 +# +No output directory configured! +No output script configured +# +# 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 +# +Overwriting previous setting for ``author''! +Overwriting previous setting for ``title''! +Overwriting previous setting for ``output directory''! +Overwriting previous setting for ``output script''! +Overwriting previous setting for ``template''! +Overwriting previous setting for ``style''! +Overwriting previous setting for ``short''! +Overwriting previous setting for ``file''! +Overwriting previous setting for ``suffix''! +Overwriting previous setting for ``icon toc''! +Overwriting previous setting for ``icon previous''! +Overwriting previous setting for ``icon next''! +Overwriting previous setting for ``icon index''! +Overwriting previous setting for ``shortcut icon''! +Overwriting previous setting for ``var''! +# +# 84 85 +# +File not found: " +"! +# +# 86 +# +Overwriting previous setting for ``file''! +# +# 87 +# +Start page +# +# 88 +# +Too many text lines, max. 999 allowed! +# +# 89 90 +# +Syntax error, ignoring unexpected %%hint%% key \" +"! +# +# 91 +# +Syntax error, missing text for %%hint%%! +# +# 92 +# +Syntax error, missing title for %%hint%%! +# +# 93 94 +# +Go to table of contents: +On start page. +# +# 95 +# +Overwriting previous setting for ``icon home''! +# +# 96 +# +Syntax error, value required! +# +# 97 98 99 +# +Overwriting previous setting for ``meta description''! +Overwriting previous setting for ``meta keywords''! +Overwriting previous setting for ``location''! +$!end +}; + + + +/** Section names in project files. +*/ +static dkChar const * const hb_section_names[] = { +$!string-table macro=dkT +options +files +contents +$!end +}; + + + +/** Accepted program options. +*/ +static dk3_option_t const hb_options[] = { + { dkT('h'), dkT("help"), 0 }, + { dkT('v'), dkT("version"), 0 }, + { dkT('L'), dkT("license"), 0 }, + { dkT('o'), dkT("optional-sections"), 1 }, + { dkT('i'), dkT("input-encoding"), 1 } +}; + +/** Number of elements in the hb_options array. +*/ +static size_t const hb_sz_options = sizeof(hb_options)/sizeof(dk3_option_t); + + + +/** Initialize job structure. + @param job Job structure to initialize. + @param app Application structure. + @param msg Localized keywords. + @param kwnl Keywords not localized. +*/ +static +void +hb_job_init( + hb_job_t *job, + dk3_app_t *app, + dkChar const * const *msg, + dkChar const * const *kwnl +) +{ + $? "+ hb_job_init" + job->app = app; + job->msg = msg; + job->kwnl = kwnl; + job->opt = NULL; + job->s_nodes = NULL; + job->i_nodes = NULL; + job->s_pnodes = NULL; + job->i_pnodes = NULL; + job->s_files = NULL; + job->i_files = NULL; + job->s_index = NULL; + job->i_index = NULL; + job->s_optsect = NULL; + job->i_optsect = NULL; + job->s_imgdim = NULL; + job->i_imgdim = NULL; + job->rootnode = NULL; + job->currentnode = NULL; + job->impressumnode = NULL; + job->firstnode = NULL; + job->lastnode = NULL; + job->infilename = NULL; + job->outputdir = NULL; + job->outputscript = NULL; + job->url = NULL; + job->indexfile = NULL; + job->impressumlink = NULL; + job->chmlang = NULL; + job->shipbuffer = NULL; + job->iltemplate = NULL; + job->ilfile = NULL; + job->special = NULL; + job->buffer32 = NULL; + job->of = NULL; + job->lineno = 0UL; + job->nextobj = 0UL; + job->npobjs = 0UL; + job->spused = 0; + job->shipused = 0; + job->options = HB_JOB_OPT_CREATE_TOC; + job->options |= HB_JOB_OPT_NUM_IN_POS; + job->options |= HB_JOB_OPT_NUM_IN_IDX; + job->options |= HB_JOB_OPT_NUM_IN_PAGE_HEADER; + job->options |= HB_JOB_OPT_CODE_LINE_NUMBERS; + job->actsect = 1; + job->iecmd = -1; /* No input encoding specified */ + job->bs = 0; + job->cmd = 0; + job->exv = 1; $? ". INIT" + job->cs = HB_CS_ASCII; + job->secttype = HB_SECTION_UNKNOWN; + job->non_url = 0; + job->maxdepth = 0; + job->coli = 0; + job->cols = HB_COLIST_NONE; +#if DK3_SIZEOF_INT > 2 +#if Dk3_SIZEOF_INT > 4 + job->headlevels = 9223372036854775807; +#else + job->headlevels = 2147483647; +#endif +#else + job->headlevels = 32767; +#endif + $? "- hb_job_init" +} + + + +/** Clean up job structure at end of program. + @param job Job structure to clean up. +*/ +static +void +hb_job_end(hb_job_t *job) +{ + hb_img_dim_t *idptr; /* Current image dimension cache entry */ + hb_index_entry_t *ie; /* Current index entry */ + hb_node_t *cn; /* Current node */ + dkChar *cfn; /* Current file name */ + $? "+ hb_job_end" + /* Release options. + */ + if(job->opt) { + dk3opt_close(job->opt); job->opt = NULL; + } + + /* The s_nodes component contains a list of all nodes. + We traverse this container to release all nodes. + */ + if(job->s_nodes) { + if(job->i_nodes) { + dk3sto_it_reset(job->i_nodes); + while(NULL != (cn = (hb_node_t *)dk3sto_it_next(job->i_nodes))) { + hb_node_delete(cn); + } + dk3sto_it_close(job->i_nodes); job->i_nodes = NULL; + } + dk3sto_close(job->s_nodes); job->s_nodes = NULL; + } + + if(job->s_imgdim) { + if(job->i_imgdim) { + dk3sto_it_reset(job->i_imgdim); + while(NULL != (idptr = (hb_img_dim_t *)dk3sto_it_next(job->i_imgdim))) { + hbimgdim_delete(idptr); + } + dk3sto_it_close(job->i_imgdim); + } + dk3sto_close(job->s_imgdim); + } job->s_imgdim = NULL; job->i_imgdim = NULL; + + if(job->s_optsect) { + if(job->i_optsect) { + dk3sto_it_reset(job->i_optsect); + while(NULL != (cfn = (dkChar *)dk3sto_it_next(job->i_optsect))) { + $? ". releasing optional section \"%!ds\"", TR_STR(cfn) + dk3_release(cfn); + } + dk3sto_it_close(job->i_optsect); + } + dk3sto_close(job->s_optsect); + } + job->s_optsect = NULL; job->i_optsect = NULL; + + if(job->s_index) { + if(job->i_index) { + dk3sto_it_reset(job->i_index); + while(NULL != (ie = (hb_index_entry_t *)dk3sto_it_next(job->i_index))) { + hbindex_delete(ie); + } + dk3sto_it_close(job->i_index); + } + dk3sto_close(job->s_index); + } + job->s_index = NULL; job->i_index = NULL; + + /* We must free the list of additional files. + */ + if(job->s_files) { + if(job->i_files) { + dk3sto_it_reset(job->i_files); + while(NULL != (cfn = (dkChar *)dk3sto_it_next(job->i_files))) { + $? ". release file name \"%!ds\"", cfn + dk3_release(cfn); + } + dk3sto_it_close(job->i_files); job->i_files = NULL; + } + dk3sto_close(job->s_files); job->s_files = NULL; + } + + /* The s_pnodes component contains a list of the leaf nodes + only (nodes to produce output for). + We already traversed s_nodes to release all the nodes, so + we can simply close s_pnodes and i_pnodes here. + */ + if(job->s_pnodes) { + if(job->i_pnodes) { + dk3sto_it_close(job->i_pnodes); + } + dk3sto_close(job->s_pnodes); job->s_pnodes = NULL; + } + + /* Release components allocated dynamically. + */ + dk3_release(job->outputdir); + dk3_release(job->outputscript); + dk3_release(job->url); + dk3_release(job->impressumlink); + dk3_release(job->chmlang); + dk3_release(job->indexfile); + dk3_release(job->shipbuffer); + dk3_release(job->iltemplate); + dk3_release(job->ilfile); + dk3_release(job->special); + dk3_release(job->buffer32); + + job->impressumnode = NULL; + $? "- hb_job_end" +} + + + +/** Save names of optional sections to process. + @param job Job structure. + @param sections Section names. + @return 1 on success, 0 on errors. +*/ +static +int +hb_save_optional_sections(hb_job_t *job, dkChar const *sections) +{ + dkChar bu[1024]; /* Private copy of sections */ + dkChar *p1; /* Current section name */ + dkChar *p2; /* Next section name */ + dkChar *p3; /* Copy of current section for storage */ + int back = 0; /* Result */ + $? "+ hb_save_optional_sections \"%!ds\"", TR_STR(sections) + if((job) && (sections)) { + if(dk3str_len(sections) < DK3_SIZEOF(bu,dkChar)) { + dk3str_cpy(bu, sections); + back = 1; $? ". back = 1" + p1 = dk3str_start(bu, NULL); + while(p1) { + p2 = dk3str_chr(p1, dkT(',')); + if(p2) { + *(p2++) = dkT('\0'); + p2 = dk3str_start(p2, NULL); + } + dk3str_chomp(p1, NULL); + $? ". saving optional section \"%!ds\"", p1 + p3 = dk3str_dup_app(p1, job->app); + if(p3) { + if(!dk3sto_add(job->s_optsect, p3)) { + dk3_release(p3); + back = 0; /* REPORTED */ $? ". back = 0" + } + } else { + back = 0; /* REPORTED */ $? ". back = 0" + } + p1 = p2; + } + } else { + dk3app_log_i3(job->app, DK3_LL_ERROR, 135, 136, sections); + } + } $? "- hb_save_optional_sections %d", back + return back; +} + + + +/** Process command line options. + @param job Job structure. + @return 1 on success, 0 on error. +*/ +static +int +hb_process_options(hb_job_t *job) +{ + dkChar const *optarg; /* Option argument */ + int back = 0; + job->opt = dk3opt_open_from_app( + hb_options, hb_sz_options, dkT('s'), hb_kwnl[32], job->app + ); + if(job->opt) { + if(0 == dk3opt_get_error_code(job->opt)) { + back = 1; + if(dk3opt_is_set(job->opt, dkT('h'))) { + job->cmd |= HB_CMD_HELP; + } + if(dk3opt_is_set(job->opt, dkT('v'))) { + job->cmd |= HB_CMD_VERSION; + } + if(dk3opt_is_set(job->opt, dkT('L'))) { + job->cmd |= HB_CMD_LICENSE; + } + if(0 == (job->cmd)) { + if(dk3opt_is_set(job->opt, dkT('i'))) { + optarg = dk3opt_get_short_arg(job->opt, dkT('i')); + if(optarg) { + job->iecmd = dk3enc_get_text_encoding_app(optarg, job->app); + if(0 > job->iecmd) { job->iecmd = -1; } + } + } + if(1 > dk3opt_get_num_args(job->opt)) { $? "! no project" + /* ERROR: No project file specified! */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 13); + back = 0; + } else { + if(1 < dk3opt_get_num_args(job->opt)) { $? "! too many" + /* WARNING: Too many project files, using just one! */ + dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 14); + } + } + } + } + } + return back; +} + + + +/** Print help text, version information or license terms. + @param job Job structure. +*/ +static +void +hb_help_version_license(hb_job_t *job) +{ + dkChar const * const *ptr; /* Current line to print */ + $? "+ hb_help_version_license" + /* Show version + */ + dk3sf_initialize_stdout(); + dk3sf_fputs(hb_version[0], stdout); + dk3sf_fputs(hb_version[1], stdout); + dk3sf_fputc(dkT('\n'), stdout); + + if(HB_CMD_LICENSE & (job->cmd)) { + /* Show license + */ + ptr = hb_license; + while(*ptr) { + dk3sf_fputs(*(ptr++), stdout); dk3sf_fputc(dkT('\n'), stdout); + } + } + if(HB_CMD_HELP & (job->cmd)) { + /* Show help + */ + dk3app_help(job->app, hb_kwnl[2], hb_help_text); + } + job->exv = 0; $? ". SUCCESS" + $? "- hb_help_version_license" +} + + + +/** Compare two file names. + @param l Left pointer. + @param r Right pointer. + @param cr Comparison criteria (ignored). + @return Comparison result. +*/ +static +int +hb_file_name_compare(void const *l, void const *r, int cr) +{ + int back = 0; + $? "+ hb_file_name_compare PTR=%d PTR=%d", TR_IPTR(l), TR_IPTR(r) + if(l) { + if(r) { + back = dk3str_fncmp((dkChar const *)l, (dkChar const *)r); + if(-1 > back) { back = -1; } + if( 1 < back) { back = 1; } + } else { + back = 1; + } + } else { + if(r) { + back = -1; + } + } $? "- hb_file_name_compare %d", back + return back; +} + + + +/** Compare two strings. + @param l Left string. + @param r Right string. + @param cr Comparison criteria (ignored). + @return Comparison result. +*/ +static +int +hb_compare_strings(void const *l, void const *r, int cr) +{ + int back = 0; + $? "+ hb_compare_strings PTR=%d PTR=%d", TR_IPTR(l), TR_IPTR(r) + if(l) { + if(r) { + back = dk3str_cmp((dkChar const *)l, (dkChar const *)r); + if(-1 > back) { back = -1; } + if( 1 < back) { back = 1; } + } else back = 1; + } else { + if(r) back = -1; + } $? "- hb_compare_strings %d", back + return back; +} + + + +/** Allocate memory for job structure. + @param job Job structure to initialize. + @return 1 on success, 0 on error. +*/ +static +int +hb_job_allocate(hb_job_t *job) +{ + int back = 0; + $? "+ hb_job_allocate" + job->s_nodes = dk3sto_open_app(job->app); + if(job->s_nodes) { + dk3sto_set_comp(job->s_nodes, hb_node_compare, 0); + job->i_nodes = dk3sto_it_open(job->s_nodes); + if(job->i_nodes) { + job->s_pnodes = dk3sto_open_app(job->app); + if(job->s_pnodes) { + dk3sto_set_comp(job->s_pnodes, hb_node_compare, 0); + job->i_pnodes = dk3sto_it_open(job->s_pnodes); + if(job->i_pnodes) { + job->rootnode = hb_node_new(job, NULL, 0UL, 0UL, -1); + job->nextobj += 1UL; + if(job->rootnode) { + (job->rootnode)->depth = 0; + if(dk3sto_add(job->s_nodes, job->rootnode)) { + job->currentnode = job->rootnode; + job->shipbuffer = dk3_new_app(dkChar,HB_LINE_LENGTH,job->app); + job->iltemplate = dk3_new_app(dkChar,HB_LINE_LENGTH,job->app); + job->ilfile = dk3_new_app(dkChar,HB_LINE_LENGTH,job->app); + job->special = dk3_new_app(dkChar,HB_LINE_LENGTH,job->app); + job->buffer32 = dk3_new_app(dk3_c32_t,HB_LINE_LENGTH,job->app); + job->bs = HB_LINE_LENGTH; + job->spused = 0; + if(job->iltemplate) { + if(job->ilfile) { + if(job->special) { + if(job->buffer32) { + if(job->shipbuffer) { + job->s_files = dk3sto_open_app(job->app); + if(job->s_files) { + dk3sto_set_comp(job->s_files,hb_file_name_compare,0); + job->i_files = dk3sto_it_open(job->s_files); + if(job->i_files) { + if(dk3sto_add(job->s_pnodes, job->rootnode)) { + back = 1; + } + } + } + } + } + } + } + } + } else { + hb_node_delete(job->rootnode); + job->rootnode = NULL; + } + } + } + } + } + } + if(back) { + back = 0; + job->s_index = dk3sto_open_app(job->app); + if(job->s_index) { + dk3sto_set_comp(job->s_index, hbindex_compare, 0); + job->i_index = dk3sto_it_open(job->s_index); + if(job->i_index) { + job->s_optsect = dk3sto_open_app(job->app); + if(job->s_optsect) { + dk3sto_set_comp(job->s_optsect, hb_compare_strings, 0); + job->i_optsect = dk3sto_it_open(job->s_optsect); + if(job->i_optsect) { + job->s_imgdim = dk3sto_open_app(job->app); + if(job->s_imgdim) { + dk3sto_set_comp(job->s_imgdim, hbimgdim_compare, 0); + job->i_imgdim = dk3sto_it_open(job->s_imgdim); + if(job->i_imgdim) { + back = 1; + } + } + } + } + } + } + } $? "- hb_job_allocate %d", back + return back; +} + + + +#if 0 +/** Add one file to file list. + @param job Job structure. + @param il Input line to process, contains file name. + @return 1 on success, -1 on error. +*/ +static +int +hb_add_file_to_file_list(hb_job_t *job, dkChar *il) +{ +#if VERSION_BEFORE_20131207 + dkChar *p1; /* Start of line */ + dkChar *p2; /* Allocated memory */ + int back = 1; + p1 = dk3str_start(il, NULL); + if(p1) { + dk3str_chomp(p1, NULL); + if(!(dk3sto_it_find_like(job->i_files, (void const *)il, 0))) { + p2 = dk3str_dup_app(il,job->app); + if(p2) { + if(!(dk3sto_add(job->s_files, (void *)p2))) { + back = -1; + dk3_release(p2); + } + } else { + back = -1; + } + } + } + return back; +#else + return(hbtool_add_file(job,il)); +#endif +} +#endif + + + +/** Find indent level. + @param il Input line to process. + @return Number of leading spaces. +*/ +static +int +hb_find_indent(dkChar *il) +{ + dkChar *p1; /* Traverse text line */ + int back = 0; + $? "+ hb_find_indent \"%!ds\"", TR_STR(il) + p1 = il; + while((dkT(' ') == *p1) || (dkT('\t') == *p1)) { + back++; + if(dkT('\t') == *p1) { + while(back % 8) { back++; } + } + p1++; + } $? "- hb_find_indent %d", back + return back; +} + + + +/** Find parent candidate for new node. + @param current Current node to edit. + @param indent Indent of new node. + @return Pointer to node on success, NULL on error. +*/ +static +hb_node_t * +hb_parent_candidate(hb_node_t *current, int indent) +{ + hb_node_t *back = NULL; + hb_node_t *ca; /* Candidate node */ + int cc; /* Flag: Can continue */ + $? "+ hb_parent_candidate" + ca = current; + cc = 1; + while(cc) { + if(ca) { + if((ca->indent) < indent) { + back = ca; + cc = 0; + } else { + ca = ca->parent; + } + } else { + cc = 0; + } + } $? "- hb_parent_candidate PTR=%d", TR_IPTR(back) + return back; +} + + + +/** Process a line from the contents section. + @param job Job structure. + @param il Input line. + @return 1 on success, -1 on error. +*/ +static +int +hb_add_contents(hb_job_t *job, dkChar *il) +{ + hb_node_t *pa; /* Parent node for new node */ + hb_node_t *nn; /* New node */ + dkChar *p1; /* Start of text line */ + int indent; /* Indent level */ + int back = 1; + $? "+ hb_add_contents \"%!ds\"", TR_STR(il) + p1 = dk3str_start(il, NULL); + if(p1) { + if(dkT('@') == *p1) { + p1++; + back = hbconf_process_line(job, p1, HB_SECTION_CONTENTS); + } else { + /* Create new node. */ + indent = hb_find_indent(il); + pa = hb_parent_candidate(job->currentnode, indent); + if(pa) { + nn = hb_node_new(job, pa, job->lineno, job->nextobj, indent); + job->nextobj += 1UL; + if(nn) { + if(nn->depth > job->maxdepth) { job->maxdepth = nn->depth; } + if(dk3sto_add(job->s_nodes, (void *)nn)) { + if(dk3sto_add(pa->s_subnodes, (void *)nn)) { + job->currentnode = nn; + nn->title = dk3str_dup_app(p1,job->app); + if(!(nn->title)) { + back = -1; /* REPORTED */ + } + } else { + back = -1; /* REPORTED */ + } + } else { + back = -1; /* REPORTED */ + hb_node_delete(nn); + } + } else { + back = -1; /* REPORTED */ + } + } else { + back = -1; + /* ERROR: No parent candidate found! */ + dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 15); + } + } + } $? "- hb_add_contents %d", back + return back; +} + + + +/** Process one line from project file. + @param job Job structure. + @param il Input line to process. + @return 1 on success, 0 on minor errors, -1 on fatal errors. +*/ +static +int +hb_process_line(hb_job_t *job, dkChar *il) +{ + dkChar *p1; /* Start of line */ + dkChar *p2; /* Next pointer */ + int back = 1; /* Result */ + int newst = HB_SECTION_UNKNOWN; /* New section type */ + $? "+ hb_process_line \"%!ds\"", TR_STR(il) + job->lineno += 1UL; + p1 = dk3str_start(il, NULL); + if(p1) { + dk3str_chomp(p1,NULL); + if(dkT('#') != *p1) { + if(dkT('[') == *p1) { + job->actsect = 1; + job->secttype = HB_SECTION_UNKNOWN; + p1++; + p1 = dk3str_start(p1, NULL); + if(p1) { + p2 = dk3str_chr(p1, dkT(']')); + if(p2) { + *p2 = dkT('\0'); + dk3str_chomp(p1, NULL); + p2 = dk3str_chr(p1, dkT(':')); + if(p2) { + *(p2++) = dkT('\0'); + p2 = dk3str_start(p2, NULL); + dk3str_chomp(p2, NULL); + dk3str_chomp(p1, NULL); + } + newst = dk3str_array_index(hb_section_names, p1, 0); + if(0 <= newst) { + job->secttype = 1 + newst; + } else { + /* ERROR: Syntax (unknown section name) */ + dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 18); + } + if(p2) { + if(!dk3sto_it_find_like(job->i_optsect, p2, 0)) { + job->actsect = 0; +#if DK3_ON_WINDOWS + if(0 == dk3str_cmp(p2, (job->kwnl)[18])) { + job->actsect = 1; + } +#else + if(0 == dk3str_cmp(p2, (job->kwnl)[19])) { + job->actsect = 1; + } +#endif + } + } + } else { + /* ERROR: Syntax (missing closing bracket) */ + dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 17); + } + } else { + /* ERROR: Syntax (no text in bracket) */ + back = -1; + dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 16); + } + } else { + if(job->actsect) { + switch(job->secttype) { + case HB_SECTION_OPTIONS: { + back = hbconf_process_line(job, il, HB_SECTION_OPTIONS); + } break; + case HB_SECTION_FILES: { + back = hbtool_add_file(job, il); + } break; + case HB_SECTION_CONTENTS: { + back = hb_add_contents(job, il); + } break; + } + } + } + } + } $? "- hb_process_line %d", back + return back; +} + + + +/** Line handler to process one line from project file. + @param obj Object to save data. + @param il Input line to process. + @return 1 on success, 0 on minor errors, -1 on fatal errors. +*/ +static +int +hb_line_reader_handler(void *obj, dkChar *il) +{ + int back; + $? "+ hb_line_reader_handler" + back = hb_process_line((hb_job_t *)obj, il); + $? "- hb_line_reader_handler %d", back + return back; +} + + + +/** Process command line variables, overwrite settings from + options section in project file. + @param job Job structure. + @return 1 on success, 0 on error. +*/ +static +int +hb_read_variables(hb_job_t *job) +{ + dkChar bu[1024]; /* Buffer for modification */ + dk3_key_value_t *kvp; /* New key value pair */ + dkChar const *optstr; /* Option string */ + dkChar *p1; /* Start of option string (key) */ + dkChar *p2; /* Start of value */ + dkChar *p3; /* Copy of value */ + int back = 1; + int nfo; /* Number of further arguments */ + int i; /* Index of current argument */ + + if(0 < (nfo = dk3opt_get_num_fo(job->opt))) { + for(i = 0; i < nfo; i++) { + optstr = dk3opt_get_fo(job->opt, i); + if(optstr) { + if(dk3str_len(optstr) < DK3_SIZEOF(bu,dkChar)) { + dk3str_cpy(bu, optstr); + p1 = dk3str_start(bu, NULL); + if(p1) { + p2 = dk3str_chr(p1, dkT('=')); + if(p2) { + *(p2++) = dkT('\0'); + p2 = dk3str_start(p2, NULL); + } + if(p2) { + dk3str_chomp(p1, NULL); + dk3str_chomp(p2, NULL); + kvp = dk3sto_it_find_like( + (job->rootnode)->i_variables, p1, 1 + ); + if(kvp) { + p3 = dk3str_dup_app(p2, job->app); + if(p3) { + dk3_release(kvp->val); + kvp->val = p3; + } else { + back = 0; + } + } else { + kvp = dk3kv_new_app(p1, p2, job->app); + if(kvp) { + if(!dk3sto_add((job->rootnode)->s_variables, kvp)) { + dk3kv_delete(kvp); + back = 0; + } + } else { + back = 0; + } + } + } else { + kvp = dk3sto_it_find_like( + (job->rootnode)->i_variables, p1, 1 + ); + if(kvp) { + dk3sto_remove((job->rootnode)->s_variables, kvp); + dk3kv_delete(kvp); + } + } + } else { + /* Empty string is ok */ + } + } else { + /* ERROR: String too long! */ + dk3app_log_i3(job->app, DK3_LL_ERROR, 135, 136, optstr); + } + } + } + } + return back; +} + + + +/** Read the project file. + @param job Job structure. + @return 1 on success, 0 on error. +*/ +static +int +hb_read_project(hb_job_t *job) +{ + int back = 0; + int inenc; /* Input encoding */ + $? "+ hb_read_project" + inenc = dk3app_get_input_file_encoding(job->app); + if(0 <= job->iecmd) { inenc = job->iecmd; } + back = dk3stream_process_filename_lines_app( + (void *)job, hb_line_reader_handler, job->infilename, + job->ilfile, job->bs, + dk3app_get_encoding(job->app), + inenc, + job->app + ); + if(!hb_read_variables(job)) { + back = 0; + } + if((job->options) & HB_JOB_OPT_CHM) { + job->cs = HB_CS_ASCII; + } + if(1 != back) { back = 0; } + $? "- hb_read_project %d", back + return back; +} + + + +/** Write all HTML files for the project. + @param job Job structure. +*/ +static +void +hb_write_html_files(hb_job_t *job) +{ +#if VERSION_BEFORE_20131206 + hb_node_t *nptr; + $? "+ hb_write_html_files" + dk3sto_it_reset(job->i_pnodes); + while(NULL != (nptr = (hb_node_t *)dk3sto_it_next(job->i_pnodes))) { + $? ". node \"%!ds\"", TR_STR(nptr->title) + if(0UL != nptr->objno) { $? ". must write" + hbhtml_write_file(job, nptr); + } + } $? "- hb_write_html_files" +#else + hb_node_t *c; + hb_node_t *p; + hb_node_t *n; + $? "+ hb_write_html_files" + p = c = n = NULL; + dk3sto_it_reset(job->i_pnodes); + c = dk3sto_it_next(job->i_pnodes); + while(c) { + n = dk3sto_it_next(job->i_pnodes); + if(0UL != c->objno) { + hbhtml_write_file(job, c, p, n); + } + p = c; + c = n; + } + $? "- hb_write_html_files" +#endif +} + + + +/** Write index html file. + @param job Job structure. +*/ +static +void +hb_write_index(hb_job_t *job) +{ + hb_node_t *n; /* Current index item */ + $? "+ hb_write_index" + dk3sto_it_reset(job->i_pnodes); + if(dk3sto_it_next(job->i_pnodes)) { + n = (hb_node_t *)dk3sto_it_next(job->i_pnodes); + if(n) { + hbhtml_write_file(job, job->rootnode, NULL, n); + } else { +/* 2014/02/05 We now allow an empty contents section to + produce just one file index.html. +*/ +#if VERSION_BEFORE_20140205 + job->exv = 1; $? "! ERROR" +#else + hbhtml_write_file(job, job->rootnode, NULL, n); +#endif + } + } else { + job->exv = 1; $? "! ERROR" + } $? "- hb_write_index" +} + + + +#if TRACE_DEBUG && (DK3_CHAR_SIZE == 1) +/** Show document tree structure at a node recursively. + @param job Job structure. + @param nptr Current node to show. + @param l Indent level. +*/ +static +void +hb_show_tree_node(hb_job_t *job, hb_node_t *nptr, int l) +{ + hb_node_t *hbptr; + int i; + if(dktrace_file()) { + fputs("> ", dktrace_file()); + for(i = 0; i < l; i++) { + fputs(" ", dktrace_file()); + } + fputs(nptr->title, dktrace_file()); + if(nptr->shorttitle) { + fputs(" (", dktrace_file()); + fputs(nptr->shorttitle, dktrace_file()); + fputs(")", dktrace_file()); + } + fprintf(dktrace_file(), " depth=%d", nptr->depth); + fputc('\n', dktrace_file()); + dk3sto_it_reset(nptr->i_subnodes); + while(NULL != (hbptr = (hb_node_t *)dk3sto_it_next(nptr->i_subnodes))) { + hb_show_tree_node(job, hbptr, (l+1)); + } + } +} + +/** Show document tree structure. + @param job Job structure. +*/ +static +void +hb_show_structure(hb_job_t *job) +{ + hb_show_tree_node(job, job->rootnode, 0); +} +#endif + + + +#if (DK3_ON_WINDOWS) || (DK3_CHAR_SIZE > 1) +/** Write file name to output file, ANSI encoded. + Set exit status code on error. + @param job Job structure. + @param fn File name. +*/ +static +void +hb_write_ansi_filename(hb_job_t *job, dkChar const *fn) +{ + $? "+ hb_write_ansi_filename \"%!ds\"", TR_STR(fn) + if(!dk3se_ansi_fputs(fn, dk3app_get_encoding(job->app), job->of, job->app)) { + job->exv = 1; + } $? "- hb_write_ansi_filename" +} +#endif + + +#if !DK3_ON_WINDOWS +/** Write a file name. + @param job Job structure. + @param fn File name to write. +*/ +static +void +hb_write_filename(hb_job_t *job, dkChar const *fn) +{ +#if DK3_CHAR_SIZE > 1 + hb_write_ansi_filename(job, fn); +#error "Not implemented!" +#else + if(EOF == fputs(fn, job->of)) { + job->exv = 1; + /* ERROR: Write attempt failed! */ + dk3app_log_i1(job->app, DK3_LL_ERROR, 120); + } +#endif +} +#endif + + + +/** Check whether the output file for a node is a HTML file. + @param nptr Node to check. + @return 1 for HTML files, 0 otherwise. +*/ +static +int +hb_htfile(hb_node_t *nptr) +{ + int back = 1; + $? "+ hb_htfile" + if(nptr->suffix) { + back = 0; + if(dk3str_fncmp(nptr->suffix, hb_kwnl[23]) == 0) { back = 1; } + if(dk3str_fncmp(nptr->suffix, hb_kwnl[24]) == 0) { back = 1; } + } $? "- hb_htfile %d", back + return back; +} + + + +/** Write instruction to copy one file to script. + @param job Job structure. + @param fn File name. +*/ +static +void +hb_write_script_copy_file(hb_job_t *job, dkChar const *fn) +{ +#if DK3_ON_WINDOWS + fputs(hb_c8_kw[8], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[9], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[0], job->of); + fputs(hb_c8_kw[10], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[11], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[12], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputs(hb_c8_kw[13], job->of); +#else + fputs(hb_c8_kw[14], job->of); /* if */ + hb_write_filename(job, fn); + fputs(hb_c8_kw[15], job->of); /* then */ + fputs(hb_c8_kw[16], job->of); /* else */ + if((job->options) & HB_JOB_OPT_LN) { + fputs(hb_c8_kw[19], job->of); + } else { + fputs(hb_c8_kw[20], job->of); + } + hb_write_filename(job, fn); + fputs(hb_c8_kw[21], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[5], job->of); + fputs(hb_c8_kw[17], job->of); /* fi */ + fputs(hb_c8_kw[22], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[23], job->of); + fputs(hb_c8_kw[35], job->of); + fputs(hb_c8_kw[18], job->of); +#endif +} + + + +/** Write the output script. + Set exit status code on errors. + @param job Job structure. +*/ +static +void +hb_write_script(hb_job_t *job) +{ + dkChar of[DK3_MAX_PATH]; /* Output file name */ + hb_node_t *nptr; /* Current print node */ + dkChar const *fn; /* Current resource file name */ + $? "+ hb_write_script" + if(job->outputscript) { + if(job->outputdir) { + job->of = dk3sf_fopen_app(job->outputscript, hb_kwnl[22], job->app); + if(job->of) { + /* Start of file + */ +#if DK3_ON_WINDOWS + fputs(hb_c8_kw[31], job->of); +#else + fputs(hb_c8_kw[32], job->of); + fputs(hb_c8_kw[33], job->of); +#endif + /* Remove existing directory completely. + */ +#if DK3_ON_WINDOWS + fputs(hb_c8_kw[2], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputs(hb_c8_kw[3], job->of); +#else + fputs(hb_c8_kw[4], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[5], job->of); +#endif + /* Create new directory. + */ +#if DK3_ON_WINDOWS + fputs(hb_c8_kw[6], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputs(hb_c8_kw[5], job->of); +#else + fputs(hb_c8_kw[7], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[5], job->of); +#endif + /* Copy resource files. + */ + dk3sto_it_reset(job->i_files); + while(NULL != (fn = (dkChar const *)dk3sto_it_next(job->i_files))) { + /* 2014-04-17 + Writinig the file copy instruction is now in the + hb_write_script_copy_file() function. + */ + hb_write_script_copy_file(job, fn); + } + /* For CHM projects copy index.hhp, index.hhc and index.hhk + */ + if ((job->options) & HB_JOB_OPT_CHM) { + hb_write_script_copy_file(job, hb_kwnl[36]); + hb_write_script_copy_file(job, hb_kwnl[26]); + hb_write_script_copy_file(job, hb_kwnl[28]); + if ((job->options) & HB_JOB_OPT_CREATE_INDEX) { + if (hbchm_have_index_entries(job)) { + hb_write_script_copy_file(job, hb_kwnl[29]); + } + } + } + /* Copy HTML files, use tidy if available. + */ + dk3sto_it_reset(job->i_pnodes); + while(NULL != (nptr = (hb_node_t *)dk3sto_it_next(job->i_pnodes))) { + if(hbhtml_create_output_filename(of,DK3_SIZEOF(of,dkChar),job,nptr)) + { + fn = of; +#if DK3_ON_WINDOWS + /* Remove existing file. + */ + fputs(hb_c8_kw[10], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputc('\\', job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[38], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputc('\\', job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[39], job->of); + /* Use tidy or xcopy to bring new file in place. + */ + fputs(hb_c8_kw[8], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[9], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[0], job->of); + if(((nptr->options) & HB_NODE_OPT_USE_TIDY) && (hb_htfile(nptr))) { + fputs(hb_c8_kw[36], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[0], job->of); + if(HB_CS_UTF_8 == job->cs) { + fputs(hb_c8_kw[24], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[26], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputc('\\', job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[3], job->of); + } else { + fputs(hb_c8_kw[25], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[26], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputc('\\', job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[3], job->of); + } + } else { + fputs(hb_c8_kw[10], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[11], job->of); + hb_write_ansi_filename(job, fn); + fputs(hb_c8_kw[12], job->of); + hb_write_ansi_filename(job, job->outputdir); + fputs(hb_c8_kw[13], job->of); + } +#else + /* Remove existing file. + */ + fputs(hb_c8_kw[14], job->of); /* if */ + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[30], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[15], job->of); + fputs(hb_c8_kw[16], job->of); /* then */ + fputs(hb_c8_kw[4], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[30], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[5], job->of); + fputs(hb_c8_kw[18], job->of); /* fi */ + /* Use tidy, cp or ln to bring new file in place. + */ + fputs(hb_c8_kw[14], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[15], job->of); + fputs(hb_c8_kw[16], job->of); + if(((nptr->options) & HB_NODE_OPT_USE_TIDY) && (hb_htfile(nptr))) { + fputs(hb_c8_kw[37], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[0], job->of); + if(HB_CS_UTF_8 == job->cs) { + fputs(hb_c8_kw[27], job->of); + } else { + fputs(hb_c8_kw[28], job->of); + } + hb_write_filename(job, fn); + fputs(hb_c8_kw[29], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[30], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[5], job->of); + } else { + if((job->options) & HB_JOB_OPT_LN) { + fputs(hb_c8_kw[19], job->of); + } else { + fputs(hb_c8_kw[20], job->of); + } + hb_write_filename(job, fn); + fputs(hb_c8_kw[21], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[5], job->of); + } + fputs(hb_c8_kw[17], job->of); + fputs(hb_c8_kw[22], job->of); + hb_write_filename(job, fn); + fputs(hb_c8_kw[23], job->of); + fputs(hb_c8_kw[35], job->of); + fputs(hb_c8_kw[18], job->of); +#endif + } + } + /* End of file. + */ +#if !DK3_ON_WINDOWS + /* find ... -type d -exec chmod ugo+rx {} \; */ + fputs(hb_c8_kw[40], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[41], job->of); + /* find ... -type f -exec chmod ugo+r {} \; */ + fputs(hb_c8_kw[40], job->of); + hb_write_filename(job, job->outputdir); + fputs(hb_c8_kw[42], job->of); + /* exit EXITCODE */ + fputs(hb_c8_kw[34], job->of); +#endif + /* Close file. + */ + if(!dk3sf_fclose_fn_app(job->of, job->outputscript, job->app)) { + job->exv = 1; + } + } else { + job->exv = 1; + } + } else { + job->exv = 1; + /* ERROR: No output directory configured! */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 67); + } + } else { + job->exv = 1; + /* ERROR: No output script configured! */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 68); + } $? "- hb_write_script" +} + + + +/** Write output files. + Set exit status code on errors. + @param job Job structure. +*/ +static +void +hb_write_output(hb_job_t *job) +{ + $? "+ hb_write_output" +#if DK3_CHAR_SIZE == 1 + $!trace-code hb_show_structure(job); +#endif + hb_write_html_files(job); + hb_write_index(job); + hb_write_script(job); + if((job->options) & HB_JOB_OPT_CHM) { + if(!hbchm_write_project(job)) { job->exv = 1; } + } +#if DK3_CHAR_SIZE == 1 + $!trace-code hb_show_structure(job); +#endif + $? "- hb_write_output" +} + + + +/** Check consistency of input data. + @param job Job structure. + @return 1 on success, 0 on error. +*/ +static +int +hb_check_data(hb_job_t *job) +{ + hb_node_t *nptr; /* Current node */ + int back = 1; + $? "+ hb_check_data" + /* All printable nodes must have a template. + */ + job->npobjs = 0UL; + dk3sto_it_reset(job->i_pnodes); + while(NULL != (nptr = (hb_node_t *)dk3sto_it_next(job->i_pnodes))) { + if(!(job->firstnode)) { job->firstnode = nptr; } + job->lastnode = nptr; + nptr->pobjno = job->npobjs; + job->npobjs += 1UL; + if(!hbconf_node_template(job, nptr)) { + back = 0; + /* ERROR: No template for node! */ + dk3app_set_source_line(job->app, nptr->lineno); + dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 19); + } + } + if(back) { + /* ##### Further tests. */ + } $? "- hb_check_data %d", back + return back; +} + + + +/** Do normal processing for one specified project file. + @param job Job structure. +*/ +static +void +hb_run_with_input_filename(hb_job_t *job) +{ + int res = 1; + $? "+ hb_run_with_input_filename" + dk3app_set_source_file(job->app, job->infilename); + dk3app_set_source_line(job->app, 0UL); + if(hb_job_allocate(job)) { $? ". allocation ok" + if(dk3opt_is_set(job->opt, dkT('o'))) { + res = hb_save_optional_sections( + job, dk3opt_get_short_arg(job->opt, dkT('o')) + ); + } + if(res) { + if(hbconf_read_files(job)) { + if(hb_read_project(job)) { + if(hb_check_data(job)) { + hbtool_enumerate(job); + job->exv = 0; $? ". SUCCESS" + hb_write_output(job); + } + } + } + } + } else { $? "! allocation failed" + } + $? "- hb_run_with_input_filename" +} + + + +/** Run normally. + @param job Job structure. +*/ +static +void +hb_run(hb_job_t *job) +{ + dkChar const *infilename; /* Input file name */ + dk3_dir_t *fne; /* File name expander */ + dk3_um_t numfiles; /* Number of files in expander */ + $? "+ hb_run" + infilename = dk3opt_get_arg(job->opt, 0); + if(infilename) { + if(dk3sf_must_expand(infilename)) { + fne = dk3dir_fne_open_app(infilename, job->app); + if(fne) { + numfiles = dk3dir_get_number_of_files(fne); + if(DK3_UM_0 < numfiles) { + if(DK3_UM_1 < numfiles) { + /* ERROR: Too many file names match */ + dk3app_log_i3(job->app, DK3_LL_ERROR, 168, 169, infilename); + } else { + if(dk3dir_get_next_file(fne)) { + job->infilename = dk3dir_get_fullname(fne); + if(job->infilename) { + hb_run_with_input_filename(job); + } else { + /* ERROR: Failed to obtain file name */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 20); + } + } else { + /* ERROR: Failed to obtain file name */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 20); + } + } + } else { + /* ERROR: No matching file name! */ + dk3app_log_i3(job->app, DK3_LL_ERROR, 215, 216, infilename); + } + dk3dir_close(fne); + } + } else { + job->infilename = infilename; + hb_run_with_input_filename(job); + } + } else { + /* ERROR: Missing project file name! */ + dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 13); + } + $? "- hb_run" +} + + + +/** Main function of the htmlbook program. + @param argc Number of command line arguments. + @param argv Command line arguments array. + @return 0 on success, any other value indicates an error. +*/ +DK3_MAIN +{ + hb_job_t job; /* Job structure */ + dk3_app_t *app = NULL; /* Application structure */ + dkChar const * const *msg = NULL; /* Localized message texts */ + dk3_time_t timer; /* Current time */ + int exv = 1; /* Exit status code */ + + $!trace-init htmlbook.deb + $? "+ main" +#if DK3_HAVE_TZSET + tzset(); +#endif + app = dk3app_open_command( + argc, (dkChar const * const *)argv, hb_kwnl[0] + ); + if(app) { + msg = dk3app_messages(app, hb_kwnl[1], (dkChar const **)hb_kw); + hb_job_init(&job, app, msg, hb_kwnl); + dk3sf_time(&timer); + dk3sf_localtime_app(&(job.starttime), &timer, app); + if(hb_process_options(&job)) { + if(job.cmd) { + hb_help_version_license(&job); + } else { + hb_run(&job); + } + } + exv = job.exv; + hb_job_end(&job); + dk3app_close(app); app = NULL; + } else { + fputs("htmlbook: ERROR: Not enough memory (RAM/swap)!\n", stderr); + fflush(stderr); + } + $? "- main %d", exv + $!trace-end + fflush(stdout); + exit(exv); return exv; +} + + |