"Fossies" - the Fresh Open Source Software Archive

Member "udunits-2.2.28/lib/udunits2.h" (7 Dec 2020, 40903 Bytes) of package /linux/privat/udunits-2.2.28.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "udunits2.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.2.26_vs_2.2.28.

    1 /*
    2  * Copyright 2020 University Corporation for Atmospheric Research
    3  *
    4  * This file is part of the UDUNITS-2 package.  See the file COPYRIGHT
    5  * in the top-level source-directory of the package for copying and
    6  * redistribution conditions.
    7  */
    8 #ifndef UT_UNITS2_H_INCLUDED
    9 #define UT_UNITS2_H_INCLUDED
   10 
   11 #include <stdarg.h>
   12 #include <stddef.h>
   13 
   14 #ifdef _MSC_VER
   15 #include <stdlib.h>
   16 #include <stdio.h>
   17 #include <stdarg.h>
   18 #include <io.h>
   19 
   20 #define _USE_MATH_DEFINES
   21 
   22 /* Define a bunch of variables to use the ISO C++ conformant name instead
   23    of the POSIX name. This quiets a lot of the warnings thrown by MSVC. */
   24 #define read _read
   25 #define open _open
   26 #define close _close
   27 #define strdup _strdup
   28 #define strcasecmp stricmp
   29 #define stricmp _stricmp
   30 #define isatty _isatty
   31 
   32 //We must accommodate the lack of snprintf in versions of MSVC less than 1900.
   33 //udunits_snprintf is defined in udunits_snprintf.c, in lib/.
   34 #define snprintf udunits_snprintf
   35 
   36 int udunits_snprintf(
   37    char* str,
   38      size_t size,
   39      const char* format,
   40      ...);
   41 
   42 int udunits_vsnprintf(
   43 char* str,
   44   size_t size,
   45   const char* format,
   46   va_list ap);
   47 
   48 #endif
   49 
   50 /* If we are working in Visual Studio and have a
   51    shared library, we will need to do some slight-of-hand
   52    in order to make it generate a proper export library.
   53 */
   54 
   55 #if defined(DLL_UDUNITS2) /* define when library is a DLL */
   56 #   if defined(DLL_EXPORT) /* defined when building the library */
   57 #     define MSC_EXTRA __declspec(dllexport)
   58 #   else
   59 #     define MSC_EXTRA __declspec(dllimport)
   60 #   endif
   61 #else
   62 # define MSC_EXTRA
   63 #endif /* defined(DLL_UDUNITS2) */
   64 
   65 /*
   66  * Results in
   67  * udunits2.c.obj : error LNK2019: unresolved external symbol cv_free referenced in function handleRequest
   68  * udunits2.c.obj : error LNK2019: unresolved external symbol cv_convert_double referenced in function handleRequest
   69  * udunits2.c.obj : error LNK2019: unresolved external symbol cv_get_expression referenced in function handleRequest
   70  */
   71 #ifndef EXTERNL
   72 #   define EXTERNL MSC_EXTRA extern
   73 #endif
   74 
   75 /*
   76  * Results in "NMAKE : fatal error U1073: don't know how to make 'lib\udunits2.lib'"
   77 #undef EXTERNL
   78 #define EXTERNL extern
   79  */
   80 
   81 #include "converter.h"
   82 
   83 typedef struct ut_system    ut_system;
   84 typedef union ut_unit       ut_unit;
   85 
   86 enum utStatus {
   87     UT_SUCCESS = 0, /* Success */
   88     UT_BAD_ARG,         /* An argument violates the function's contract */
   89     UT_EXISTS,      /* Unit, prefix, or identifier already exists */
   90     UT_NO_UNIT,     /* No such unit exists */
   91     UT_OS,      /* Operating-system error.  See "errno". */
   92     UT_NOT_SAME_SYSTEM, /* The units belong to different unit-systems */
   93     UT_MEANINGLESS, /* The operation on the unit(s) is meaningless */
   94     UT_NO_SECOND,   /* The unit-system doesn't have a unit named "second" */
   95     UT_VISIT_ERROR, /* An error occurred while visiting a unit */
   96     UT_CANT_FORMAT, /* A unit can't be formatted in the desired manner */
   97     UT_SYNTAX,      /* string unit representation contains syntax error */
   98     UT_UNKNOWN,     /* string unit representation contains unknown word */
   99     UT_OPEN_ARG,    /* Can't open argument-specified unit database */
  100     UT_OPEN_ENV,    /* Can't open environment-specified unit database */
  101     UT_OPEN_DEFAULT,    /* Can't open installed, default, unit database */
  102     UT_PARSE        /* Error parsing unit specification */
  103 };
  104 typedef enum utStatus          ut_status;
  105 
  106 enum utEncoding {
  107     UT_ASCII = 0,
  108     UT_ISO_8859_1 = 1,
  109     UT_LATIN1 = UT_ISO_8859_1,
  110     UT_UTF8 = 2
  111 };
  112 typedef enum utEncoding        ut_encoding;
  113 
  114 #define UT_NAMES    4
  115 #define UT_DEFINITION   8
  116 
  117 
  118 /*
  119  * Data-structure for a visitor to a unit:
  120  */
  121 typedef struct ut_visitor {
  122     /*
  123      * Visits a basic-unit.  A basic-unit is a base unit like "meter" or a non-
  124      * dimensional but named unit like "radian".
  125      *
  126      * Arguments:
  127      *  unit        Pointer to the basic-unit.
  128      *  arg     Client pointer passed to ut_accept_visitor().
  129      * Returns:
  130      *  UT_SUCCESS  Success.
  131      *  else        Failure.
  132      */
  133     ut_status   (*visit_basic)(const ut_unit* unit, void* arg);
  134 
  135     /*
  136      * Visits a product-unit.  A product-unit is a product of zero or more
  137      * basic-units, each raised to a non-zero power.
  138      *
  139      * Arguments:
  140      *  unit        Pointer to the product-unit.
  141      *  count       The number of basic-units in the product.  May be zero.
  142      *  basicUnits  Pointer to an array of basic-units in the product.
  143      *  powers      Pointer to an array of powers to which the respective
  144      *          basic-units are raised.
  145      *  arg     Client pointer passed to ut_accept_visitor().
  146      * Returns:
  147      *  UT_SUCCESS  Success.
  148      *  else        Failure.
  149      */
  150     ut_status   (*visit_product)(const ut_unit* unit, int count,
  151     const ut_unit* const* basicUnits, const int* powers, void* arg);
  152 
  153     /*
  154      * Visits a Galilean-unit.  A Galilean-unit has an underlying unit and a
  155      * non-unity scale factor or a non-zero offset.
  156      *
  157      * Arguments:
  158      *  unit        Pointer to the Galilean-unit.
  159      *  scale       The scale factor (e.g., 1000 for a kilometer when the
  160      *          underlying unit is a meter).
  161      *  underlyingUnit  Pointer to the underlying unit.
  162      *  offset      Pointer to the underlying unit.
  163      *  arg     Client pointer passed to ut_accept_visitor().
  164      * Returns:
  165      *  UT_SUCCESS  Success.
  166      *  else        Failure.
  167      */
  168     ut_status   (*visit_galilean)(const ut_unit* unit, double scale,
  169     const ut_unit* underlyingUnit, double offset, void* arg);
  170 
  171     /*
  172      * Visits a timestamp-unit.  A timestamp-unit has an underlying unit of time
  173      * and an encoded time-origin.
  174      *
  175      * Arguments:
  176      *  unit        Pointer to the timestamp-unit.
  177      *  timeUnit    Pointer to the underlying unit of time.
  178      *  origin          Encoded origin of the timestamp-unit.
  179      *  arg     Client pointer passed to ut_accept_visitor().
  180      * Returns:
  181      *  UT_SUCCESS  Success.
  182      *  else        Failure.
  183      */
  184     ut_status   (*visit_timestamp)(const ut_unit* unit,
  185     const ut_unit* timeUnit, double origin, void* arg);
  186 
  187     /*
  188      * Visits a logarithmic-unit.  A logarithmic-unit has a logarithmic base and
  189      * a unit that specifies the reference level.
  190      *
  191      * Arguments:
  192      *  unit        Pointer to the logarithmic-unit.
  193      *  base            The logarithmic base (e.g., 2, M_E, 10).
  194      *  reference   Pointer to the unit that specifies the reference level.
  195      *  arg     Client pointer passed to ut_accept_visitor().
  196      * Returns:
  197      *  UT_SUCCESS  Success.
  198      *  else        Failure.
  199      */
  200     ut_status   (*visit_logarithmic)(const ut_unit* unit, double base,
  201     const ut_unit* reference, void* arg);
  202 } ut_visitor;
  203 
  204 
  205 typedef int (*ut_error_message_handler)(const char* fmt, va_list args);
  206 
  207 
  208 #ifdef __cplusplus
  209 EXTERNL "C" {
  210 #endif
  211 
  212 
  213 /******************************************************************************
  214  * Unit System:
  215  ******************************************************************************/
  216 
  217 
  218 /**
  219  * Returns the pathname of the XML database.
  220  *
  221  * @param path      The pathname of the XML file or NULL.
  222  * @param status    Status. One of UT_OPEN_ARG, UT_OPEN_ENV, or UT_OPEN_DEFAULT.
  223  * @return          If "path" is not NULL, then it is returned; otherwise, the
  224  *                  pathname specified by the environment variable
  225  *                  UDUNITS2_XML_PATH is returned if set; otherwise, the
  226  *                  compile-time pathname of the installed, default, unit
  227  *                  database is returned.
  228  */
  229 EXTERNL const char*
  230 ut_get_path_xml(
  231     const char* path,
  232     ut_status*  status);
  233 
  234 /*
  235  * Returns the unit-system corresponding to an XML file.  This is the usual way
  236  * that a client will obtain a unit-system.
  237  *
  238  * Arguments:
  239  *  path    The pathname of the XML file or NULL.  If NULL, then the
  240  *      pathname specified by the environment variable UDUNITS2_XML_PATH
  241  *      is used if set; otherwise, the compile-time pathname of the
  242  *      installed, default, unit database is used.
  243  * Returns:
  244  *  NULL    Failure.  "ut_get_status()" will be
  245  *          UT_OPEN_ARG     "path" is non-NULL but file couldn't be
  246  *                  opened.  See "errno" for reason.
  247  *          UT_OPEN_ENV     "path" is NULL and environment variable
  248  *                  UDUNITS2_XML_PATH is set but file
  249  *                  couldn't be opened.  See "errno" for
  250  *                  reason.
  251  *          UT_OPEN_DEFAULT "path" is NULL, environment variable
  252  *                  UDUNITS2_XML_PATH is unset, and the
  253  *                  installed, default, unit database
  254  *                  couldn't be opened.  See "errno" for
  255  *                  reason.
  256  *          UT_PARSE        Couldn't parse unit database.
  257  *          UT_OS       Operating-system error.  See "errno".
  258  *  else    Pointer to the unit-system defined by "path".
  259  */
  260 EXTERNL ut_system*
  261 ut_read_xml(
  262     const char* path);
  263 
  264 
  265 /*
  266  * Returns a new unit-system.  On success, the unit-system will only contain
  267  * the dimensionless unit one.  See "ut_get_dimensionless_unit_one()".
  268  *
  269  * Returns:
  270  *  NULL    Failure.  "ut_get_status()" will be:
  271  *          UT_OS   Operating-system error.  See "errno".
  272  *  else    Pointer to a new unit system.
  273  */
  274 EXTERNL ut_system*
  275 ut_new_system(void);
  276 
  277 
  278 /*
  279  * Frees a unit-system.  All unit-to-identifier and identifier-to-unit mappings
  280  * will be removed.
  281  *
  282  * Arguments:
  283  *  system      Pointer to the unit-system to be freed.  Use of "system"
  284  *          upon return results in undefined behavior.
  285  */
  286 EXTERNL void
  287 ut_free_system(
  288     ut_system*  system);
  289 
  290 
  291 /*
  292  * Returns the unit-system to which a unit belongs.
  293  *
  294  * Arguments:
  295  *  unit    Pointer to the unit in question.
  296  * Returns:
  297  *  NULL    Failure.  "ut_get_status()" will be
  298  *          UT_BAD_ARG  "unit" is NULL.
  299  *  else    Pointer to the unit-system to which "unit" belongs.
  300  */
  301 EXTERNL ut_system*
  302 ut_get_system(
  303     const ut_unit* const    unit);
  304 
  305 
  306 /*
  307  * Returns the dimensionless-unit one of a unit-system.
  308  *
  309  * Arguments:
  310  *  system  Pointer to the unit-system for which the dimensionless-unit one
  311  *      will be returned.
  312  * Returns:
  313  *  NULL    Failure.  "ut_get_status()" will be:
  314  *          UT_BAD_ARG  "system" is NULL.
  315  *  else    Pointer to the dimensionless-unit one associated with "system".
  316  *      While not necessary, the pointer may be passed to ut_free()
  317  *      when the unit is no longer needed by the client.
  318  */
  319 EXTERNL ut_unit*
  320 ut_get_dimensionless_unit_one(
  321     const ut_system* const  system);
  322 
  323 
  324 /*
  325  * Returns the unit with a given name from a unit-system.  Name comparisons
  326  * are case-insensitive.
  327  *
  328  * Arguments:
  329  *  system  Pointer to the unit-system.
  330  *  name    Pointer to the name of the unit to be returned.
  331  * Returns:
  332  *  NULL    Failure.  "ut_get_status()" will be
  333  *          UT_SUCCESS      "name" doesn't map to a unit of
  334  *                  "system".
  335  *          UT_BAD_ARG      "system" or "name" is NULL.
  336  *  else    Pointer to the unit of the unit-system with the given name.
  337  *      The pointer should be passed to ut_free() when the unit is
  338  *      no longer needed.
  339  */
  340 EXTERNL ut_unit*
  341 ut_get_unit_by_name(
  342     const ut_system* const  system,
  343     const char* const       name);
  344 
  345 
  346 /*
  347  * Returns the unit with a given symbol from a unit-system.  Symbol
  348  * comparisons are case-sensitive.
  349  *
  350  * Arguments:
  351  *  system      Pointer to the unit-system.
  352  *  symbol      Pointer to the symbol associated with the unit to be
  353  *          returned.
  354  * Returns:
  355  *  NULL    Failure.  "ut_get_status()" will be
  356  *          UT_SUCCESS      "symbol" doesn't map to a unit of
  357  *                  "system".
  358  *          UT_BAD_ARG      "system" or "symbol" is NULL.
  359  *  else    Pointer to the unit in the unit-system with the given symbol.
  360  *      The pointer should be passed to ut_free() when the unit is no
  361  *      longer needed.
  362  */
  363 EXTERNL ut_unit*
  364 ut_get_unit_by_symbol(
  365     const ut_system* const  system,
  366     const char* const       symbol);
  367 
  368 
  369 /*
  370  * Sets the "second" unit of a unit-system.  This function must be called before
  371  * the first call to "ut_offset_by_time()". ut_read_xml() calls this function if the
  372  * resulting unit-system contains a unit named "second".
  373  *
  374  * Arguments:
  375  *  second      Pointer to the "second" unit.
  376  * Returns:
  377  *  UT_BAD_ARG  "second" is NULL.
  378  *  UT_EXISTS   The second unit of the unit-system to which "second"
  379  *          belongs is set to a different unit.
  380  *  UT_SUCCESS  Success.
  381  */
  382 EXTERNL ut_status
  383 ut_set_second(
  384     const ut_unit* const    second);
  385 
  386 
  387 /******************************************************************************
  388  * Defining Unit Prefixes:
  389  ******************************************************************************/
  390 
  391 
  392 /*
  393  * Adds a name-prefix to a unit-system.  A name-prefix is something like "mega"
  394  * or "milli".  Comparisons between name-prefixes are case-insensitive.
  395  *
  396  * Arguments:
  397  *  system      Pointer to the unit-system.
  398  *  name        Pointer to the name-prefix (e.g., "mega").  May be freed
  399  *          upon return.
  400  *  value       The value of the prefix (e.g., 1e6).
  401  * Returns:
  402  *  UT_SUCCESS  Success.
  403  *  UT_BAD_ARG  "system" or "name" is NULL, or "value" is 0.
  404  *  UT_EXISTS   "name" already maps to a different value.
  405  *  UT_OS       Operating-system failure.  See "errno".
  406  */
  407 EXTERNL ut_status
  408 ut_add_name_prefix(
  409     ut_system* const    system,
  410     const char* const   name,
  411     const double    value);
  412 
  413 
  414 /*
  415  * Adds a symbol-prefix to a unit-system.  A symbol-prefix is something like
  416  * "M" or "y".  Comparisons between symbol-prefixes are case-sensitive.
  417  *
  418  * Arguments:
  419  *  system      Pointer to the unit-system.
  420  *  symbol      Pointer to the symbol-prefix (e.g., "M").  May be freed
  421  *          upon return.
  422  *  value       The value of the prefix (e.g., 1e6).
  423  * Returns:
  424  *  UT_SUCCESS  Success.
  425  *  UT_BADSYSTEM    "system" or "symbol" is NULL.
  426  *  UT_BAD_ARG  "value" is 0.
  427  *  UT_EXISTS   "symbol" already maps to a different value.
  428  *  UT_OS       Operating-system failure.  See "errno".
  429  */
  430 EXTERNL ut_status
  431 ut_add_symbol_prefix(
  432     ut_system* const    system,
  433     const char* const   symbol,
  434     const double    value);
  435 
  436 
  437 /******************************************************************************
  438  * Defining and Deleting Units:
  439  ******************************************************************************/
  440 
  441 
  442 /*
  443  * Adds a base-unit to a unit-system.  Clients that use ut_read_xml() should not
  444  * normally need to call this function.
  445  *
  446  * Arguments:
  447  *  system  Pointer to the unit-system to which to add the new base-unit.
  448  * Returns:
  449  *  NULL    Failure.  "ut_get_status()" will be
  450  *          UT_BAD_ARG      "system" or "name" is NULL.
  451  *          UT_OS       Operating-system error.  See "errno".
  452  *  else    Pointer to the new base-unit.  The pointer should be passed to
  453  *      ut_free() when the unit is no longer needed by the client (the
  454  *      unit will remain in the unit-system).
  455  */
  456 EXTERNL ut_unit*
  457 ut_new_base_unit(
  458     ut_system* const    system);
  459 
  460 
  461 /*
  462  * Adds a dimensionless-unit to a unit-system.  In the SI system of units, the
  463  * derived-unit radian is a dimensionless-unit.  Clients that use ut_read_xml()
  464  * should not normally need to call this function.
  465  *
  466  * Arguments:
  467  *  system  Pointer to the unit-system to which to add the new
  468  *      dimensionless-unit.
  469  * Returns:
  470  *  NULL    Failure.  "ut_get_status()" will be
  471  *          UT_BAD_ARG      "system" is NULL.
  472  *          UT_OS       Operating-system error.  See "errno".
  473  *  else    Pointer to the new dimensionless-unit.  The pointer should be
  474  *      passed to ut_free() when the unit is no longer needed by the
  475  *      client (the unit will remain in the unit-system).
  476  */
  477 EXTERNL ut_unit*
  478 ut_new_dimensionless_unit(
  479     ut_system* const    system);
  480 
  481 
  482 /*
  483  * Returns a clone of a unit.
  484  *
  485  * Arguments:
  486  *  unit    Pointer to the unit to be cloned.
  487  * Returns:
  488  *  NULL    Failure.  ut_get_status() will be
  489  *          UT_OS   Operating-system failure.  See "errno".
  490  *          UT_BAD_ARG  "unit" is NULL.
  491  *  else    Pointer to the clone of "unit".  The pointer should be
  492  *      passed to ut_free() when the unit is no longer needed by the
  493  *      client.
  494  */
  495 EXTERNL ut_unit*
  496 ut_clone(
  497     const ut_unit* const unit);
  498 
  499 
  500 /*
  501  * Frees resources associated with a unit.  This function should be invoked on
  502  * all units that are no longer needed by the client.  Use of the unit upon
  503  * return from this function will result in undefined behavior.
  504  *
  505  * Arguments:
  506  *  unit    Pointer to the unit to have its resources freed or NULL.
  507  */
  508 EXTERNL void
  509 ut_free(
  510     ut_unit* const  unit);
  511 
  512 
  513 /******************************************************************************
  514  * Mapping between Units and Names:
  515  ******************************************************************************/
  516 
  517 
  518 /*
  519  * Returns the name in a given encoding to which a unit maps.
  520  *
  521  * Arguments:
  522  *  unit        Pointer to the unit whose name should be returned.
  523  *  encoding    The desired encoding of the name.
  524  * Returns:
  525  *  NULL        Failure.  "ut_get_status()" will be
  526  *              UT_BAD_ARG      "unit" is NULL.
  527  *              UT_SUCCESS      "unit" doesn't map to a name in
  528  *                      in the given encoding.
  529  *  else        Pointer to the name in the given encoding to which
  530  *          "unit" maps.
  531  */
  532 EXTERNL const char*
  533 ut_get_name(
  534     const ut_unit* const    unit,
  535     const ut_encoding       encoding);
  536 
  537 
  538 /*
  539  * Adds a mapping from a name to a unit.
  540  *
  541  * Arguments:
  542  *  name        Pointer to the name to be mapped to "unit".  May be
  543  *          freed upon return.
  544  *      encoding        The character encoding of "name".
  545  *  unit        Pointer to the unit to be mapped-to by "name".  May be
  546  *          freed upon return.
  547  * Returns:
  548  *  UT_BAD_ARG  "name" or "unit" is NULL.
  549  *  UT_OS       Operating-system error.  See "errno".
  550  *  UT_EXISTS   "name" already maps to a different unit.
  551  *  UT_SUCCESS  Success.
  552  */
  553 EXTERNL ut_status
  554 ut_map_name_to_unit(
  555     const char* const       name,
  556     const ut_encoding       encoding,
  557     const ut_unit* const    unit);
  558 
  559 
  560 /*
  561  * Removes a mapping from a name to a unit.  After this function,
  562  * ut_get_unit_by_name(system,name) will no longer return a unit.
  563  *
  564  * Arguments:
  565  *  system      The unit-system to which the unit belongs.
  566  *  name        The name of the unit.
  567  *      encoding        The character encoding of "name".
  568  * Returns:
  569  *  UT_SUCCESS  Success.
  570  *  UT_BAD_ARG  "system" or "name" is NULL.
  571  */
  572 EXTERNL ut_status
  573 ut_unmap_name_to_unit(
  574     ut_system*      system,
  575     const char* const   name,
  576     const ut_encoding   encoding);
  577 
  578 
  579 /*
  580  * Adds a mapping from a unit to a name.
  581  *
  582  * Arguments:
  583  *  unit        Pointer to the unit to be mapped to "name".  May be
  584  *          freed upon return.
  585  *  name        Pointer to the name to be mapped-to by "unit".  May be
  586  *          freed upon return.
  587  *  encoding    The encoding of "name".
  588  * Returns:
  589  *  UT_SUCCESS  Success.
  590  *  UT_BAD_ARG  "unit" or "name" is NULL, or "name" is not in the
  591  *                      specified encoding.
  592  *  UT_OS       Operating-system error.  See "errno".
  593  *  UT_EXISTS   "unit" already maps to a name.
  594  */
  595 EXTERNL ut_status
  596 ut_map_unit_to_name(
  597     const ut_unit* const    unit,
  598     const char* const       name,
  599     ut_encoding         encoding);
  600 
  601 
  602 /*
  603  * Removes a mapping from a unit to a name.
  604  *
  605  * Arguments:
  606  *  unit        Pointer to the unit.  May be freed upon return.
  607  *  encoding    The encoding to be removed.  No other encodings will be
  608  *          removed.
  609  * Returns:
  610  *  UT_BAD_ARG  "unit" is NULL.
  611  *  UT_SUCCESS  Success.
  612  */
  613 EXTERNL ut_status
  614 ut_unmap_unit_to_name(
  615     const ut_unit* const    unit,
  616     ut_encoding         encoding);
  617 
  618 
  619 /******************************************************************************
  620  * Mapping between Units and Symbols:
  621  ******************************************************************************/
  622 
  623 
  624 /*
  625  * Returns the symbol in a given encoding to which a unit maps.
  626  *
  627  * Arguments:
  628  *  unit        Pointer to the unit whose symbol should be returned.
  629  *  encoding    The desired encoding of the symbol.
  630  * Returns:
  631  *  NULL        Failure.  "ut_get_status()" will be
  632  *              UT_BAD_ARG      "unit" is NULL.
  633  *              UT_SUCCESS      "unit" doesn't map to a symbol
  634  *                      in the given encoding.
  635  *  else        Pointer to the symbol in the given encoding to which
  636  *          "unit" maps.
  637  */
  638 EXTERNL const char*
  639 ut_get_symbol(
  640     const ut_unit* const    unit,
  641     const ut_encoding   encoding);
  642 
  643 
  644 /*
  645  * Adds a mapping from a symbol to a unit.
  646  *
  647  * Arguments:
  648  *  symbol      Pointer to the symbol to be mapped to "unit".  May be
  649  *          freed upon return.
  650  *      ut_encoding     The character encoding of "symbol".
  651  *  unit        Pointer to the unit to be mapped-to by "symbol".  May
  652  *          be freed upon return.
  653  * Returns:
  654  *  UT_BAD_ARG  "symbol" or "unit" is NULL.
  655  *  UT_OS       Operating-system error.  See "errno".
  656  *  UT_EXISTS   "symbol" already maps to a different unit.
  657  *  UT_SUCCESS  Success.
  658  */
  659 EXTERNL ut_status
  660 ut_map_symbol_to_unit(
  661     const char* const       symbol,
  662     const ut_encoding       encoding,
  663     const ut_unit* const    unit);
  664 
  665 
  666 /*
  667  * Removes a mapping from a symbol to a unit.  After this function,
  668  * ut_get_unit_by_symbol(system,symbol) will no longer return a unit.
  669  *
  670  * Arguments:
  671  *  system      The unit-system to which the unit belongs.
  672  *  symbol      The symbol of the unit.
  673  *      encoding        The character encoding of "symbol".
  674  * Returns:
  675  *  UT_SUCCESS  Success.
  676  *  UT_BAD_ARG  "system" or "symbol" is NULL.
  677  */
  678 EXTERNL ut_status
  679 ut_unmap_symbol_to_unit(
  680     ut_system*      system,
  681     const char* const   symbol,
  682     const ut_encoding   encoding);
  683 
  684 
  685 /*
  686  * Adds a mapping from a unit to a symbol.
  687  *
  688  * Arguments:
  689  *  unit        Pointer to the unit to be mapped to "symbol".  May be
  690  *          freed upon return.
  691  *  symbol      Pointer to the symbol to be mapped-to by "unit".  May
  692  *          be freed upon return.
  693  *  encoding    The encoding of "symbol".
  694  * Returns:
  695  *  UT_SUCCESS  Success.
  696  *  UT_BAD_ARG  "unit" or "symbol" is NULL.
  697  *  UT_OS       Operating-system error.  See "errno".
  698  *  UT_EXISTS   "unit" already maps to a symbol.
  699  */
  700 EXTERNL ut_status
  701 ut_map_unit_to_symbol(
  702     const ut_unit*      unit,
  703     const char* const       symbol,
  704     ut_encoding         encoding);
  705 
  706 
  707 /*
  708  * Removes a mapping from a unit to a symbol.
  709  *
  710  * Arguments:
  711  *  unit        Pointer to the unit to be unmapped to a symbol.  May be
  712  *          freed upon return.
  713  *  encoding    The encoding to be removed.  The mappings for "unit" in
  714  *          other encodings will not be removed.
  715  * Returns:
  716  *  UT_SUCCESS  Success.
  717  *  UT_BAD_ARG  "unit" is NULL.
  718  */
  719 EXTERNL ut_status
  720 ut_unmap_unit_to_symbol(
  721     const ut_unit* const    unit,
  722     ut_encoding         encoding);
  723 
  724 
  725 /******************************************************************************
  726  * Getting Information about a Unit:
  727  ******************************************************************************/
  728 
  729 
  730 /*
  731  * Indicates if a given unit is dimensionless or not.  Note that logarithmic
  732  * units are dimensionless by definition.
  733  *
  734  * Arguments:
  735  *  unit    Pointer to the unit in question.
  736  * Returns:
  737  *  0   "unit" is dimensionfull or an error occurred.  "ut_get_status()"
  738  *       will be
  739  *          UT_BAD_ARG      "unit" is NULL.
  740  *          UT_SUCCESS      "unit" is dimensionfull.
  741  *  else    "unit" is dimensionless.
  742  */
  743 EXTERNL int
  744 ut_is_dimensionless(
  745     const ut_unit* const    unit);
  746 
  747 
  748 /*
  749  * Indicates if two units belong to the same unit-system.
  750  *
  751  * Arguments:
  752  *  unit1       Pointer to a unit.
  753  *  unit2       Pointer to another unit.
  754  * Returns:
  755  *  0       Failure or the units belong to different unit-systems.
  756  *          "ut_get_status()" will be
  757  *                  UT_BAD_ARG      "unit1" or "unit2" is NULL.
  758  *                  UT_SUCCESS      The units belong to different
  759  *                      unit-systems.
  760  *  else        The units belong to the same unit-system.
  761  */
  762 EXTERNL int
  763 ut_same_system(
  764     const ut_unit* const    unit1,
  765     const ut_unit* const    unit2);
  766 
  767 
  768 /*
  769  * Compares two units.  Returns a value less than, equal to, or greater than
  770  * zero as the first unit is considered less than, equal to, or greater than
  771  * the second unit, respectively.  Units from different unit-systems never
  772  * compare equal.
  773  *
  774  * Arguments:
  775  *  unit1       Pointer to a unit or NULL.
  776  *  unit2       Pointer to another unit or NULL.
  777  * Returns:
  778  *  <0  The first unit is less than the second unit.
  779  *   0  The first and second units are equal or both units are NULL.
  780  *  >0  The first unit is greater than the second unit.
  781  */
  782 EXTERNL int
  783 ut_compare(
  784     const ut_unit* const    unit1,
  785     const ut_unit* const    unit2);
  786 
  787 
  788 /*
  789  * Indicates if numeric values in one unit are convertible to numeric values in
  790  * another unit via "ut_get_converter()".  In making this determination,
  791  * dimensionless units are ignored.
  792  *
  793  * Arguments:
  794  *  unit1       Pointer to a unit.
  795  *  unit2       Pointer to another unit.
  796  * Returns:
  797  *  0       Failure.  "ut_get_status()" will be
  798  *                  UT_BAD_ARG      "unit1" or "unit2" is NULL.
  799  *              UT_NOT_SAME_SYSTEM  "unit1" and "unit2" belong to
  800  *                      different unit-sytems.
  801  *              UT_SUCCESS      Conversion between the units is
  802  *                      not possible (e.g., "unit1" is
  803  *                      "meter" and "unit2" is
  804  *                      "kilogram").
  805  *  else    Numeric values can be converted between the units.
  806  */
  807 EXTERNL int
  808 ut_are_convertible(
  809     const ut_unit* const    unit1,
  810     const ut_unit* const    unit2);
  811 
  812 
  813 /*
  814  * Returns a converter of numeric values in one unit to numeric values in
  815  * another unit.  The returned converter should be passed to cv_free() when it is
  816  * no longer needed by the client.
  817  *
  818  * NOTE:  Leap seconds are not taken into account when converting between
  819  * timestamp units.
  820  *
  821  * Arguments:
  822  *  from        Pointer to the unit from which to convert values.
  823  *  to      Pointer to the unit to which to convert values.
  824  * Returns:
  825  *  NULL        Failure.  "ut_get_status()" will be:
  826  *              UT_BAD_ARG      "from" or "to" is NULL.
  827  *              UT_NOT_SAME_SYSTEM  "from" and "to" belong to
  828  *                      different unit-systems.
  829  *              UT_MEANINGLESS  Conversion between the units is
  830  *                      not possible.  See
  831  *                      "ut_are_convertible()".
  832  *  else        Pointer to the appropriate converter.  The pointer
  833  *          should be passed to cv_free() when no longer needed by
  834  *          the client.
  835  */
  836 EXTERNL cv_converter*
  837 ut_get_converter(
  838     ut_unit* const  from,
  839     ut_unit* const  to);
  840 
  841 
  842 /******************************************************************************
  843  * Arithmetic Unit Manipulation:
  844  ******************************************************************************/
  845 
  846 
  847 /*
  848  * Returns a unit equivalent to another unit scaled by a numeric factor,
  849  * e.g.,
  850  *  const ut_unit*  meter = ...
  851  *  const ut_unit*  kilometer = ut_scale(1000, meter);
  852  *
  853  * Arguments:
  854  *  factor      The numeric scale factor.
  855  *  unit        Pointer to the unit to be scaled.
  856  * Returns:
  857  *  NULL        Failure.  "ut_get_status()" will be
  858  *              UT_BAD_ARG      "factor" is 0 or "unit" is NULL.
  859  *              UT_OS       Operating-system error.  See
  860  *                      "errno".
  861  *  else        Pointer to the resulting unit.  The pointer should be
  862  *          passed to ut_free() when the unit is no longer needed by
  863  *          the client.
  864  */
  865 EXTERNL ut_unit*
  866 ut_scale(
  867     const double        factor,
  868     const ut_unit* const    unit);
  869 
  870 
  871 /*
  872  * Returns a unit equivalent to another unit offset by a numeric amount,
  873  * e.g.,
  874  *  const ut_unit*  kelvin = ...
  875  *  const ut_unit*  celsius = ut_offset(kelvin, 273.15);
  876  *
  877  * Arguments:
  878  *  unit        Pointer to the unit to be offset.
  879  *  offset      The numeric offset.
  880  * Returns:
  881  *  NULL        Failure.  "ut_get_status()" will be
  882  *              UT_BAD_ARG      "unit" is NULL.
  883  *              UT_OS       Operating-system error.  See
  884  *                      "errno".
  885  *  else        Pointer to the resulting unit.  The pointer should be
  886  *          passed to ut_free() when the unit is no longer needed by
  887  *          the client.
  888  */
  889 EXTERNL ut_unit*
  890 ut_offset(
  891     const ut_unit* const    unit,
  892     const double    offset);
  893 
  894 
  895 /*
  896  * Returns a unit equivalent to another unit relative to a particular time.
  897  * e.g.,
  898  *  const ut_unit*  second = ...
  899  *  const ut_unit*  secondsSinceTheEpoch =
  900  *              ut_offset_by_time(second, ut_encode_time(1970, 1, 1, 0, 0, 0.0));
  901  *
  902  * Arguments:
  903  *  unit    Pointer to the time-unit to be made relative to a time-origin.
  904  *  origin  The origin as returned by ut_encode_time().
  905  * Returns:
  906  *  NULL    Failure.  "ut_get_status()" will be
  907  *          UT_BAD_ARG      "unit" is NULL.
  908  *          UT_OS       Operating-system error.  See "errno".
  909  *          UT_MEANINGLESS  Creation of a timestamp unit based on
  910  *                  "unit" is not meaningful.
  911  *          UT_NO_SECOND    The associated unit-system doesn't
  912  *                  contain a "second" unit.  See
  913  *                  ut_set_second().
  914  *  else    Pointer to the resulting unit.  The pointer should be passed
  915  *      to ut_free() when the unit is no longer needed by the client.
  916  */
  917 EXTERNL ut_unit*
  918 ut_offset_by_time(
  919     const ut_unit* const    unit,
  920     const double    origin);
  921 
  922 
  923 /*
  924  * Returns the result of multiplying one unit by another unit.
  925  *
  926  * Arguments:
  927  *  unit1   Pointer to a unit.
  928  *  unit2   Pointer to another unit.
  929  * Returns:
  930  *  NULL    Failure.  "ut_get_status()" will be:
  931  *          UT_BAD_ARG      "unit1" or "unit2" is NULL.
  932  *          UT_NOT_SAME_SYSTEM  "unit1" and "unit2" belong to
  933  *                  different unit-systems.
  934  *          UT_OS       Operating-system error. See "errno".
  935  *  else    Pointer to the resulting unit.  The pointer should be passed
  936  *      to ut_free() when the unit is no longer needed by the client.
  937  */
  938 EXTERNL ut_unit*
  939 ut_multiply(
  940     const ut_unit* const    unit1,
  941     const ut_unit* const    unit2);
  942 
  943 
  944 /*
  945  * Returns the inverse (i.e., reciprocal) of a unit.  This convenience function
  946  * is equal to "ut_raise(unit, -1)".
  947  *
  948  * Arguments:
  949  *  unit    Pointer to the unit.
  950  * Returns:
  951  *  NULL    Failure.  "ut_get_status()" will be:
  952  *          UT_BAD_ARG      "unit" is NULL.
  953  *          UT_OS       Operating-system error. See "errno".
  954  *  else    Pointer to the resulting unit.  The pointer should be passed to
  955  *      ut_free() when the unit is no longer needed by the client.
  956  */
  957 EXTERNL ut_unit*
  958 ut_invert(
  959     const ut_unit* const    unit);
  960 
  961 
  962 /*
  963  * Returns the result of dividing one unit by another unit.  This convenience
  964  * function is equivalent to the following sequence:
  965  *     {
  966  *         ut_unit* inverse = ut_invert(denom);
  967  *         ut_multiply(numer, inverse);
  968  *         ut_free(inverse);
  969  *     }
  970  *
  971  * Arguments:
  972  *  numer   Pointer to the numerator (top, dividend) unit.
  973  *  denom   Pointer to the denominator (bottom, divisor) unit.
  974  * Returns:
  975  *  NULL    Failure.  "ut_get_status()" will be:
  976  *          UT_BAD_ARG      "numer" or "denom" is NULL.
  977  *          UT_NOT_SAME_SYSTEM  "unit1" and "unit2" belong to
  978  *                  different unit-systems.
  979  *          UT_OS       Operating-system error. See "errno".
  980  *  else    Pointer to the resulting unit.  The pointer should be passed to
  981  *      ut_free() when the unit is no longer needed by the client.
  982  */
  983 EXTERNL ut_unit*
  984 ut_divide(
  985     const ut_unit* const    numer,
  986     const ut_unit* const    denom);
  987 
  988 
  989 /*
  990  * Returns the result of raising a unit to a power.
  991  *
  992  * Arguments:
  993  *  unit    Pointer to the unit.
  994  *  power   The power by which to raise "unit".  Must be greater than or
  995  *      equal to -255 and less than or equal to 255.
  996  * Returns:
  997  *  NULL    Failure.  "ut_get_status()" will be:
  998  *          UT_BAD_ARG      "unit" is NULL or "power" is invalid.
  999  *          UT_OS       Operating-system error. See "errno".
 1000  *  else    Pointer to the resulting unit.  The pointer should be passed to
 1001  *      ut_free() when the unit is no longer needed by the client.
 1002  */
 1003 EXTERNL ut_unit*
 1004 ut_raise(
 1005     const ut_unit* const    unit,
 1006     const int           power);
 1007 
 1008 
 1009 /*
 1010  * Returns the result of taking the root of a unit.
 1011  *
 1012  * Arguments:
 1013  *  unit    Pointer to the unit.
 1014  *  root    The root to take of "unit".  Must be greater than or
 1015  *      equal to 1 and less than or equal to 255.
 1016  * Returns:
 1017  *  NULL    Failure.  "ut_get_status()" will be:
 1018  *          UT_BAD_ARG      "unit" is NULL, or "root" is invalid.
 1019  *                              In particular, all powers of base units
 1020  *                              in "unit" must be integral multiples of
 1021  *                              "root".
 1022  *          UT_OS       Operating-system error. See "errno".
 1023  *  else    Pointer to the resulting unit.  The pointer should be passed to
 1024  *      ut_free() when the unit is no longer needed by the client.
 1025  */
 1026 EXTERNL ut_unit*
 1027 ut_root(
 1028     const ut_unit* const    unit,
 1029     const int           root);
 1030 
 1031 
 1032 /*
 1033  * Returns the logarithmic unit corresponding to a logarithmic base and a
 1034  * reference level.  For example, the following creates a decibel unit with a
 1035  * one milliwatt reference level:
 1036  *
 1037  *     const ut_unit* watt = ...;
 1038  *     const ut_unit* milliWatt = ut_scale(0.001, watt);
 1039  *
 1040  *     if (milliWatt != NULL) {
 1041  *         const ut_unit* bel_1_mW = ut_log(10.0, milliWatt);
 1042  *
 1043  *         if (bel_1_mW != NULL) {
 1044  *             const ut_unit* decibel_1_mW = ut_scale(0.1, bel_1_mW);
 1045  *
 1046  *             if (decibel_1_mW != NULL) {
 1047  *                 ...
 1048  *                 ut_free(decibel_1_mW);
 1049  *             }            // "decibel_1_mW" allocated
 1050  *
 1051  *             ut_free(bel_1_mW);
 1052  *         }                // "bel_1_mW" allocated
 1053  *
 1054  *         ut_free(milliWatt);
 1055  *     }                // "milliWatt" allocated
 1056  *
 1057  * Arguments:
 1058  *  base        The logarithmic base (e.g., 2, M_E, 10).  Must be
 1059  *                      greater than one.  "M_E" is defined in <math.h>.
 1060  *  reference   Pointer to the reference value as a unit.
 1061  * Returns:
 1062  *  NULL        Failure.  "ut_get_status()" will be:
 1063  *              UT_BAD_ARG          "base" is invalid or "reference"
 1064  *                                              is NULL.
 1065  *              UT_OS       Operating-system error. See
 1066  *                      "errno".
 1067  *  else        Pointer to the resulting unit.  The pointer should be
 1068  *          passed to ut_free() when the unit is no longer needed by
 1069  *          the client.
 1070  */
 1071 EXTERNL ut_unit*
 1072 ut_log(
 1073     const double        base,
 1074     const ut_unit* const    reference);
 1075 
 1076 
 1077 /******************************************************************************
 1078  * Parsing and Formatting Units:
 1079  ******************************************************************************/
 1080 
 1081 
 1082 /*
 1083  * Returns the binary representation of a unit corresponding to a string
 1084  * representation.
 1085  *
 1086  * Arguments:
 1087  *  system      Pointer to the unit-system in which the parsing will
 1088  *          occur.
 1089  *  string      The string to be parsed (e.g., "millimeters").  There
 1090  *          should be no leading or trailing whitespace in the
 1091  *          string.  See ut_trim().
 1092  *  encoding    The encoding of "string".
 1093  * Returns:
 1094  *  NULL        Failure.  "ut_get_status()" will be one of
 1095  *              UT_BAD_ARG      "system" or "string" is NULL.
 1096  *              UT_SYNTAX       "string" contained a syntax
 1097  *                      error.
 1098  *              UT_UNKNOWN      "string" contained an unknown
 1099  *                      identifier.
 1100  *              UT_OS       Operating-system failure.  See
 1101  *                      "errno".
 1102  *  else        Pointer to the unit corresponding to "string".
 1103  */
 1104 EXTERNL ut_unit*
 1105 ut_parse(
 1106     const ut_system* const  system,
 1107     const char* const       string,
 1108     ut_encoding             encoding);
 1109 
 1110 
 1111 /*
 1112  * Removes leading and trailing whitespace from a string.
 1113  *
 1114  * Arguments:
 1115  *  string      NUL-terminated string.  Will be modified if it contains
 1116  *                      whitespace..
 1117  *  encoding    The character-encoding of "string".
 1118  * Returns:
 1119  *      "string", with all leading and trailing whitespace removed.
 1120  */
 1121 EXTERNL char*
 1122 ut_trim(
 1123     char* const         string,
 1124     const ut_encoding   encoding);
 1125 
 1126 
 1127 /*
 1128  * Formats a unit.
 1129  *
 1130  * Arguments:
 1131  *  unit        Pointer to the unit to be formatted.
 1132  *  buf     Pointer to the buffer into which to format "unit".
 1133  *  size        Size of the buffer in bytes.
 1134  *  opts        Formatting options: bitwise-OR of zero or more of the
 1135  *          following:
 1136  *              UT_NAMES        Use unit names instead of
 1137  *                      symbols
 1138  *                          UT_DEFINITION       The formatted string should be
 1139  *                                              the definition of "unit" in
 1140  *                                              terms of basic-units instead of
 1141  *                      stopping any expansion at the
 1142  *                      highest level possible.
 1143  *              UT_ASCII        The string should be formatted
 1144  *                      using the ASCII character set
 1145  *                      (default).
 1146  *              UT_LATIN1       The string should be formatted
 1147  *                      using the ISO Latin-1 (alias
 1148  *                      ISO-8859-1) character set.
 1149  *              UT_UTF8     The string should be formatted
 1150  *                      using the UTF-8 character set.
 1151  *          UT_LATIN1 and UT_UTF8 are mutually exclusive: they may
 1152  *          not both be specified.
 1153  * Returns:
 1154  *  -1      Failure:  "ut_get_status()" will be
 1155  *              UT_BAD_ARG      "unit" or "buf" is NULL, or both
 1156  *                                              UT_LATIN1 and UT_UTF8 specified.
 1157  *              UT_CANT_FORMAT  "unit" can't be formatted in
 1158  *                      the desired manner.
 1159  *      else        Success.  Number of characters printed in "buf".  If
 1160  *          the number is equal to the size of the buffer, then the
 1161  *          buffer is too small to have a terminating NUL character.
 1162  */
 1163 EXTERNL int
 1164 ut_format(
 1165     const ut_unit* const    unit,
 1166     char*       buf,
 1167     size_t      size,
 1168     unsigned        opts);
 1169 
 1170 
 1171 /*
 1172  * Accepts a visitor to a unit.
 1173  *
 1174  * Arguments:
 1175  *  unit        Pointer to the unit to accept the visitor.
 1176  *  visitor     Pointer to the visitor of "unit".
 1177  *  arg     An arbitrary pointer that will be passed to "visitor".
 1178  * Returns:
 1179  *  UT_BAD_ARG  "unit" or "visitor" is NULL.
 1180  *  UT_VISIT_ERROR  A error occurred in "visitor" while visiting "unit".
 1181  *  UT_SUCCESS  Success.
 1182  */
 1183 EXTERNL ut_status
 1184 ut_accept_visitor(
 1185     const ut_unit* const        unit,
 1186     const ut_visitor* const visitor,
 1187     void* const         arg);
 1188 
 1189 
 1190 /******************************************************************************
 1191  * Time Handling:
 1192  ******************************************************************************/
 1193 
 1194 
 1195 /*
 1196  * Encodes a date as a double-precision value.
 1197  *
 1198  * Arguments:
 1199  *  year        The year.
 1200  *  month       The month.
 1201  *  day     The day (1 = the first of the month).
 1202  * Returns:
 1203  *  The date encoded as a scalar value.
 1204  */
 1205 EXTERNL double
 1206 ut_encode_date(
 1207     int     year,
 1208     int     month,
 1209     int     day);
 1210 
 1211 
 1212 /*
 1213  * Encodes a time as a double-precision value. If an input value isn't within
 1214  * its allowed range, then zero is returned and `ut_get_status()` will return
 1215  * `UT_BAD_ARG`.
 1216  *
 1217  * @param[in] hours    The number of hours (0 = midnight). `abs(hours)` must be
 1218  *                     less than 24.
 1219  * @param[in] minutes  The number of minutes. `abs(minutes)` must be less than
 1220  *                     60.
 1221  * @param[in] seconds  The number of seconds. `fabs(seconds)` must be less than
 1222  *                     or equal to 62.
 1223  * @return             The clock-time encoded as a scalar value.
 1224  */
 1225 EXTERNL double
 1226 ut_encode_clock(
 1227     int    hours,
 1228     int    minutes,
 1229     double seconds);
 1230 
 1231 
 1232 /*
 1233  * Encodes a time as a double-precision value.  The convenience function is
 1234  * equivalent to "ut_encode_date(year,month,day) +
 1235  * ut_encode_clock(hour,minute,second)"
 1236  *
 1237  * Arguments:
 1238  *  year    The year.
 1239  *  month   The month.
 1240  *  day The day.
 1241  *  hour    The hour.
 1242  *  minute  The minute.
 1243  *  second  The second.
 1244  * Returns:
 1245  *  The time encoded as a scalar value.
 1246  */
 1247 EXTERNL double
 1248 ut_encode_time(
 1249     const int       year,
 1250     const int       month,
 1251     const int       day,
 1252     const int       hour,
 1253     const int       minute,
 1254     const double    second);
 1255 
 1256 
 1257 /*
 1258  * Decodes a time from a double-precision value.
 1259  *
 1260  * Arguments:
 1261  *      value           The value to be decoded.
 1262  *      year            Pointer to the variable to be set to the year.
 1263  *      month           Pointer to the variable to be set to the month.
 1264  *      day             Pointer to the variable to be set to the day.
 1265  *      hour            Pointer to the variable to be set to the hour.
 1266  *      minute          Pointer to the variable to be set to the minute.
 1267  *      second          Pointer to the variable to be set to the second.
 1268  *      resolution      Pointer to the variable to be set to the resolution
 1269  *                      of the decoded time in seconds.
 1270  */
 1271 EXTERNL void
 1272 ut_decode_time(
 1273     double  value,
 1274     int     *year,
 1275     int     *month,
 1276     int     *day,
 1277     int     *hour,
 1278     int     *minute,
 1279     double  *second,
 1280     double  *resolution);
 1281 
 1282 
 1283 /******************************************************************************
 1284  * Error Handling:
 1285  ******************************************************************************/
 1286 
 1287 
 1288 /*
 1289  * Returns the status of the last operation by the units module.  This function
 1290  * will not change the status.
 1291  */
 1292 EXTERNL ut_status
 1293 ut_get_status(void);
 1294 
 1295 
 1296 /*
 1297  * Sets the status of the units module.  This function would not normally be
 1298  * called by the user unless they were doing their own parsing or formatting.
 1299  *
 1300  * Arguments:
 1301  *  status  The status of the units module.
 1302  */
 1303 EXTERNL void
 1304 ut_set_status(
 1305     ut_status   status);
 1306 
 1307 
 1308 /*
 1309  * Handles an error-message.
 1310  *
 1311  * Arguments:
 1312  *  fmt The format for the error-message.
 1313  *  ... The arguments for "fmt".
 1314  * Returns:
 1315  *  <0  An output error was encountered.
 1316  *  else    The number of bytes of "fmt" and "arg" written excluding any
 1317  *      terminating NUL.
 1318  */
 1319 EXTERNL int
 1320 ut_handle_error_message(
 1321     const char* const   fmt,
 1322     ...);
 1323 
 1324 
 1325 /*
 1326  * Returns the previously-installed error-message handler and optionally
 1327  * installs a new handler.  The initial handler is "ut_write_to_stderr()".
 1328  *
 1329  * Arguments:
 1330  *      handler     NULL or pointer to the error-message handler.  If NULL,
 1331  *          then the handler is not changed.  The
 1332  *          currently-installed handler can be obtained this way.
 1333  * Returns:
 1334  *  Pointer to the previously-installed error-message handler.
 1335  */
 1336 EXTERNL ut_error_message_handler
 1337 ut_set_error_message_handler(
 1338     ut_error_message_handler    handler);
 1339 
 1340 
 1341 /*
 1342  * Writes an error-message to the standard-error stream when received and
 1343  * appends a newline.  This is the initial error-message handler.
 1344  *
 1345  * Arguments:
 1346  *  fmt The format for the error-message.
 1347  *  args    The arguments of "fmt".
 1348  * Returns:
 1349  *  <0  A output error was encountered.  See "errno".
 1350  *  else    The number of bytes of "fmt" and "arg" written excluding any
 1351  *      terminating NUL.
 1352  */
 1353 EXTERNL int
 1354 ut_write_to_stderr(
 1355     const char* const   fmt,
 1356     va_list     args);
 1357 
 1358 
 1359 /*
 1360  * Does nothing with an error-message.
 1361  *
 1362  * Arguments:
 1363  *  fmt The format for the error-message.
 1364  *  args    The arguments of "fmt".
 1365  * Returns:
 1366  *  0   Always.
 1367  */
 1368 EXTERNL int
 1369 ut_ignore(
 1370     const char* const   fmt,
 1371     va_list     args);
 1372 
 1373 
 1374 #ifdef __cplusplus
 1375 }
 1376 #endif
 1377 
 1378 #endif