Massive Revamp of the Messaging System

This is a rather large refactoring of Tidy's messaging system. This was done
mostly to allow non-C libraries that cannot adequately take advantage of
arg_lists a chance to query report filter information for information related
to arguments used in constructing an error message.

Three main goals were in mind for this project:

- Don't change the contents of Tidy's existing output sinks. This will ensure
  that changes do no affect console Tidy users, or LibTidy users who use the
  output sinks directly. This was accomplished 100% other than some improved
  cosmetics in the output. See tidy-html5-tests repository, the `refactor` and
  `more_messages_changes` branches for these minor diffs.
- Provide an API that is simple and also extensible without having to write new
  error filters all the time. This was accomplished by adding the new message
  callback `TidyMessageCallback` that provides callback functions an opaque
  object representing the message, and an API to query the message for wanted
  details. With this, we should never have to add a new callback routine again,
  as additional API can simply be written against the opaque object.
- The API should work the same as the rest of LibTidy's API in that it's
  consistent and only uses simple types with wide interoperability with other
  languages. Thanks to @gagern who suggested the model for the API in #409.
  Although the API uses the "Tidy" way off accessing data via an iterator
  rather than an index, this can be easily abstracted in the target language.

There are two *major* API breaking changes:

- Removed TidyReportFilter2
  - This was only used by one application in the entire world, and was a hacky
    kludge that served its purpose. TidyReportCallback (né TidyReportFilter3)
    is much better. If, for some reason, this affects you, I recommend using
    TidyReportCallback instead. It's a minor change for your application.
- Renamed TidyReportFilter3 to TidyReportCallback
  - This name is much more semantic, and much more sensible in light of
    improved callback system. As the name implies, it remains capable of
    *only* receiving callbacks for Tidy "reports."

Introducing TidyMessageCallback, and a new message interrogation API.

- As its name implies, it is able to capture (and optionally suppress) *all*
  of Tidy's output, including the dialogue messages that never make it to
  the existing report filters.
- Provides an opaque `TidyMessage` and an API that can be used to query against
  it to find the juicy goodness inside.
  - For example, `tidyGetMessageOutput( tmessage )` will return the complete,
    localized message.
  - Another example, `tidyGetMessageLine( tmessage )` will return the line the
    message applies to.
- You can also get information about the individual arguments that make up a
  message. By using the `tidyGetMessageArguments( tmessage )` itorator and
  `tidyGetNextMessageArgument` you will obtain an opaque `TidyMessageArgument`
  which has its own interrogation API. For example:
    - tidyGetArgType( tmessage, &iterator );
    - tidyGetArgFormat( tmessage, &iterator );
    - tidyGetArgValueString( tmessage, &iterator );
    - …and so on.

Other major changes include refactoring `messages.c` to use the new message
"object" directly when emitting messages to the console or output sinks. This
allowed replacement of a lot of specialized functions with generalized ones.

Some of this generalizing involved modifications to the `language_xx.h` header
files, and these are all positive improvements even without the above changes.
This commit is contained in:
Jim Derry 2017-03-13 13:28:57 -04:00
parent 4dc8a2cf9a
commit 11178d775b
14 changed files with 1901 additions and 846 deletions

View file

@ -146,7 +146,7 @@ set ( CFILES
${SRCDIR}/buffio.c ${SRCDIR}/fileio.c ${SRCDIR}/streamio.c
${SRCDIR}/tagask.c ${SRCDIR}/tmbstr.c ${SRCDIR}/utf8.c
${SRCDIR}/tidylib.c ${SRCDIR}/mappedio.c ${SRCDIR}/gdoc.c
${SRCDIR}/language.c )
${SRCDIR}/language.c ${SRCDIR}/messageobj.c )
set ( HFILES
${INCDIR}/tidyplatform.h ${INCDIR}/tidy.h ${INCDIR}/tidyenum.h
${INCDIR}/tidybuffio.h )

View file

@ -1558,6 +1558,67 @@ static void unknownOption( uint c )
}
/**
** This callback from LibTidy allows the console application to examine an
** error message before allowing LibTidy to display it. Currently the body
** of the function is not compiled into Tidy, but if you're interested in
** how to use the new message API, then enable it. Possible applications in
** future console Tidy might be to do things like:
** - allow user-defined filtering
** - sort the report output by line number
** - other things that are user facing and best not put into LibTidy
** proper.
*/
static Bool TIDY_CALL reportCallback(TidyMessage tmessage)
{
#if 0
TidyIterator pos;
TidyMessageArgument arg;
TidyFormatParameterType messageType;
ctmbstr messageFormat;
printf("FILTER: %s, %s\n", tidyGetMessageKey( tmessage ), tidyGetMessageOutput( tmessage ));
/* loop through the arguments, if any, and print their details */
pos = tidyGetMessageArguments( tmessage );
while ( pos )
{
arg = tidyGetNextMessageArgument( tmessage, &pos );
messageType = tidyGetArgType( tmessage, &arg );
messageFormat = tidyGetArgFormat( tmessage, &arg );
printf( " Type = %u, Format = %s, Value = ", messageType, messageFormat );
switch (messageType)
{
case tidyFormatType_STRING:
printf("%s\n", tidyGetArgValueString( tmessage, &arg ));
break;
case tidyFormatType_INT:
printf("%d\n", tidyGetArgValueInt( tmessage, &arg));
break;
case tidyFormatType_UINT:
printf("%u\n", tidyGetArgValueUInt( tmessage, &arg));
break;
case tidyFormatType_DOUBLE:
printf("%g\n", tidyGetArgValueDouble( tmessage, &arg));
break;
default:
printf("%s", "unknown so far\n");
}
}
return no; /* suppress LibTidy's own output of this message */
#else
return yes; /* needed so Tidy will not block output of this message */
#endif
}
/**
** MAIN -- let's do something here.
*/
@ -1568,6 +1629,7 @@ int main( int argc, char** argv )
TidyDoc tdoc = tidyCreate();
int status = 0;
tmbstr locale = NULL;
tidySetMessageCallback( tdoc, reportCallback);
uint contentErrors = 0;
uint contentWarnings = 0;

View file

@ -96,6 +96,16 @@ opaque_type( TidyNode );
*/
opaque_type( TidyAttr );
/** @struct TidyMessage
** Opaque messsage record datatype
*/
opaque_type( TidyMessage );
/** @struct TidyMessageArgument
** Opaque message argument datatype
*/
opaque_type( TidyMessageArgument );
/** @} end Opaque group */
@ -566,20 +576,20 @@ TIDY_EXPORT Bool TIDY_CALL tidyInitSink( TidyOutputSink* sink,
TIDY_EXPORT void TIDY_CALL tidyPutByte( TidyOutputSink* sink, uint byteValue );
/****************
Emacs File
****************/
/** Set the file path to use for reports when `TidyEmacs` is being used. This
** function provides a proper interface for using the hidden, internal-only
** `TidyEmacsFile` configuration option.
*/
TIDY_EXPORT void TIDY_CALL tidySetEmacsFile( TidyDoc tdoc, ctmbstr filePath );
/****************
Emacs File
****************/
/** Set the file path to use for reports when `TidyEmacs` is being used. This
** function provides a proper interface for using the hidden, internal-only
** `TidyEmacsFile` configuration option.
*/
TIDY_EXPORT void TIDY_CALL tidySetEmacsFile( TidyDoc tdoc, ctmbstr filePath );
/** Get the file path to use for reports when `TidyEmacs` is being used. This
** function provides a proper interface for using the hidden, internal-only
** `TidyEmacsFile` configuration option.
*/
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetEmacsFile( TidyDoc tdoc );
/** Get the file path to use for reports when `TidyEmacs` is being used. This
** function provides a proper interface for using the hidden, internal-only
** `TidyEmacsFile` configuration option.
*/
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetEmacsFile( TidyDoc tdoc );
/****************
@ -589,32 +599,159 @@ TIDY_EXPORT ctmbstr TIDY_CALL tidyGetEmacsFile( TidyDoc tdoc );
** info, warning, etc. Just set diagnostic output
** handler to redirect all diagnostics output. Return true
** to proceed with output, false to cancel.
>>>>>>> next
*/
typedef Bool (TIDY_CALL *TidyReportFilter)( TidyDoc tdoc, TidyReportLevel lvl,
uint line, uint col, ctmbstr mssg );
uint line, uint col, ctmbstr mssg );
typedef Bool (TIDY_CALL *TidyReportFilter2)( TidyDoc tdoc, TidyReportLevel lvl,
uint line, uint col, ctmbstr mssg, va_list args );
TIDY_EXPORT Bool TIDY_CALL tidySetReportFilter( TidyDoc tdoc,
TidyReportFilter filtCallback );
typedef Bool (TIDY_CALL *TidyReportFilter3)( TidyDoc tdoc, TidyReportLevel lvl,
uint line, uint col, ctmbstr code, va_list args );
/** The `TidyReportCallback` is a simple filtering mechanism that provides
** the TidyDoc instance, the report level, line and column location, as well
** as a string code (see `tidyErrorFilterKeyItem` type for applicable codes)
** to look up your own strings, and a va_list of arguments that you can use
** to fill in your own strings.
*/
typedef Bool (TIDY_CALL *TidyReportCallback)( TidyDoc tdoc, TidyReportLevel lvl,
uint line, uint col, ctmbstr code, va_list args );
/** Give Tidy a filter callback to use */
TIDY_EXPORT Bool TIDY_CALL tidySetReportFilter( TidyDoc tdoc,
TidyReportFilter filtCallback );
TIDY_EXPORT Bool TIDY_CALL tidySetReportCallback( TidyDoc tdoc,
TidyReportCallback filtCallback );
TIDY_EXPORT Bool TIDY_CALL tidySetReportFilter2( TidyDoc tdoc,
TidyReportFilter2 filtCallback );
/** The `TidyMessageCallback` is an advanced filtering mechanism that provides
** great flexibility and exposure to reports and dialogue emitted by Tidy.
** it returns only the opaque type `TidyMessage` which can be queried with the
** message callback API, below. Note that unlike the older filters, this
** callback exposes *all* output that `LibTidy` emits (excluding the console
** application, which is a client of `LibTidy`).
*/
typedef Bool (TIDY_CALL *TidyMessageCallback)( TidyMessage tmessage );
TIDY_EXPORT Bool TIDY_CALL tidySetMessageCallback( TidyDoc tdoc,
TidyMessageCallback filtCallback );
TIDY_EXPORT Bool TIDY_CALL tidySetReportFilter3( TidyDoc tdoc,
TidyReportFilter3 filtCallback );
/** Set error sink to named file */
TIDY_EXPORT FILE* TIDY_CALL tidySetErrorFile( TidyDoc tdoc, ctmbstr errfilnam );
TIDY_EXPORT FILE* TIDY_CALL tidySetErrorFile( TidyDoc tdoc, ctmbstr errfilnam );
/** Set error sink to given buffer */
TIDY_EXPORT int TIDY_CALL tidySetErrorBuffer( TidyDoc tdoc, TidyBuffer* errbuf );
TIDY_EXPORT int TIDY_CALL tidySetErrorBuffer( TidyDoc tdoc, TidyBuffer* errbuf );
/** Set error sink to given generic sink */
TIDY_EXPORT int TIDY_CALL tidySetErrorSink( TidyDoc tdoc, TidyOutputSink* sink );
TIDY_EXPORT int TIDY_CALL tidySetErrorSink( TidyDoc tdoc, TidyOutputSink* sink );
/***************************
** TidyMessageCallback API
** When using `TidyMessageCallback` you will be supplied with a valid
** TidyMessage object. This object can be interrogated with the following
** API before the callback returns. Upon returning from the callback, this
** object is destroyed so do not attempt to keep it around.
****************************/
/** get the message key string. */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageKey( TidyMessage tmessage );
/** get the line number the message applies to. */
TIDY_EXPORT int TIDY_CALL tidyGetMessageLine( TidyMessage tmessage );
/** get the column the message applies to. */
TIDY_EXPORT int TIDY_CALL tidyGetMessageColumn( TidyMessage tmessage );
/** get the TidyReportLevel of the message. */
TIDY_EXPORT TidyReportLevel TIDY_CALL tidyGetMessageLevel( TidyMessage tmessage );
/** the built-in format string */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageFormatDefault( TidyMessage tmessage );
/** the localized format string */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageFormat( TidyMessage tmessage );
/** the message, formatted, default language */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageDefault( TidyMessage tmessage );
/** the message, formatted, localized */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessage( TidyMessage tmessage );
/** the position part, default language */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePosDefault( TidyMessage tmessage );
/** the position part, localized */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePos( TidyMessage tmessage );
/** the prefix part, default language */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePrefixDefault( TidyMessage tmessage );
/** the prefix part, localized */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessagePrefix( TidyMessage tmessage );
/** Get the message as Tidy would emit it in the default localization. */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageOutputDefault( TidyMessage tmessage );
/** Get the message as Tidy would emit it in the currently-set localization. */
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetMessageOutput( TidyMessage tmessage );
/***************************
** TidyMessageCallback Arguments API
** When using `TidyMessageCallback` you will be supplied with a valid
** TidyMessage object, which may have arguments that can be interrogated
** with this API.
****************************/
/**
* Initializes the TidyIterator to point to the first item in the message's
* argument. Use `TY_(getNextMEssageArgument)` to get an opaque instance of
* `TidyMessageArgument` for which the subsequent interrogators will be of use.
*/
TIDY_EXPORT TidyIterator TIDY_CALL tidyGetMessageArguments( TidyMessage tmessage );
/**
* Returns the next `TidyMessageArgument`, which can be interrogated with
* the API, and advances the iterator.
*/
TIDY_EXPORT TidyMessageArgument TIDY_CALL tidyGetNextMessageArgument( TidyMessage tmessage, TidyIterator* iter );
/**
* Returns the `TidyFormatParameterType` of the given message argument.
*/
TIDY_EXPORT TidyFormatParameterType TIDY_CALL tidyGetArgType( TidyMessage tmessage, TidyMessageArgument* arg );
/**
* Returns the format specifier of the given message argument. The memory for
* this string is cleared upon termination of the callback, so do be sure to
* make your own copy.
*/
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetArgFormat( TidyMessage tmessage, TidyMessageArgument* arg );
/**
* Returns the string value of the given message argument. An assertion
* will be generated if the argument type is not a string.
*/
TIDY_EXPORT ctmbstr TIDY_CALL tidyGetArgValueString( TidyMessage tmessage, TidyMessageArgument* arg );
/**
* Returns the unsigned integer value of the given message argument. An
* assertion will be generated if the argument type is not an unsigned
* integer.
*/
TIDY_EXPORT uint TIDY_CALL tidyGetArgValueUInt( TidyMessage tmessage, TidyMessageArgument* arg );
/**
* Returns the integer value of the given message argument. An assertion
* will be generated if the argument type is not an integer.
*/
TIDY_EXPORT int TIDY_CALL tidyGetArgValueInt( TidyMessage tmessage, TidyMessageArgument* arg );
/**
* Returns the double value of the given message argument. An assertion
* will be generated if the argument type is not a double.
*/
TIDY_EXPORT double TIDY_CALL tidyGetArgValueDouble( TidyMessage tmessage, TidyMessageArgument* arg );
/****************

View file

@ -248,16 +248,34 @@ typedef enum
*/
typedef enum
{
TidyInfo = 350, /**< Information about markup usage */
TidyWarning, /**< Warning message */
TidyConfig, /**< Configuration error */
TidyAccess, /**< Accessibility message */
TidyError, /**< Error message - output suppressed */
TidyBadDocument, /**< I/O or file system error */
TidyFatal /**< Crash! */
TidyReportLevel_first = 350,
TidyInfo = 350, /**< Report: Information about markup usage */
TidyWarning, /**< Report: Warning message */
TidyConfig, /**< Report: Configuration error */
TidyAccess, /**< Report: Accessibility message */
TidyError, /**< Report: Error message - output suppressed */
TidyBadDocument, /**< Report: I/O or file system error */
TidyFatal, /**< Report: Crash! */
TidyDialogueInfo, /**< Dialogue: Non-document related information */
TidyDialogueSummary, /**< Dialogue: Summary-related information */
TidyDialogueDoc, /**< Dialogue: Document-related information */
TidyReportLevel_last
} TidyReportLevel;
/** Indicates the data type of a format string parameter used when Tidy
** emits reports and dialogue as part of the messaging callback functions.
** See `messageobj.h` for more information on this API.
*/
typedef enum
{
tidyFormatType_INT = 0,
tidyFormatType_UINT,
tidyFormatType_STRING,
tidyFormatType_DOUBLE,
tidyFormatType_UNKNOWN = 20
} TidyFormatParameterType;
/* Document tree traversal functions
*/
@ -804,8 +822,7 @@ typedef enum
*
* In order to keep code maintainable and make it simple to add new
* messages, the `tidyMessageCodes` and `tidyErrorFilterKeysStruct[]`
* are generated dynamically with preprocessor macros defined below,
* or in respective modules (e.g., `access.h`).
* are generated dynamically with preprocessor macros defined below.
*
* Any visible FOREACH_MSG_* macro (including new ones) must be
* applied to the `tidyMessageCodes` enum with the MAKE_ENUM() macro
@ -938,7 +955,7 @@ typedef enum
FN(VENDOR_SPECIFIC_CHARS)
/* miscellaneous config and info messages */
#define FOREACH_MSG_MISC(FN) \
#define FOREACH_MSG_OTHER(FN) \
FN(STRING_CONTENT_LOOKS) /* `Document content looks like %s`. */ \
FN(STRING_DOCTYPE_GIVEN) /* `Doctype given is \"%s\". */ \
FN(STRING_HTML_PROPRIETARY) /* `HTML Proprietary`/ */ \
@ -1101,7 +1118,7 @@ typedef enum
FOREACH_MSG_ELEMENT(MAKE_ENUM)
FOREACH_MSG_ATTRIBUTE(MAKE_ENUM)
FOREACH_MSG_ENCODING(MAKE_ENUM)
FOREACH_MSG_MISC(MAKE_ENUM)
FOREACH_MSG_OTHER(MAKE_ENUM)
#if SUPPORT_ACCESSIBILITY_CHECKS
/* Defined in `access.h` */
@ -1122,50 +1139,54 @@ typedef enum
* in the message filter callback, and are *not* console application
* specific messages.
*********************************************************************/
#define FOREACH_MSG_MISC(FN) \
/* Point to Accessibility Guidelines. */ FN(ACCESS_URL) \
/* Point to Tidy accessibility page. */ FN(ATRC_ACCESS_URL) \
/* File can't be opened. */ FN(FILE_CANT_OPEN) \
/* Localized `line %d column %d` text. */ FN(LINE_COLUMN_STRING) \
/* For `discarding`. */ FN(STRING_DISCARDING) \
/* `%u %s, %u %s were found!`. */ FN(STRING_ERROR_COUNT) \
/* `error` and `errors`. */ FN(STRING_ERROR_COUNT_ERROR) \
/* `warning` and `warnings`. */ FN(STRING_ERROR_COUNT_WARNING) \
/* Accessibility hello message. */ FN(STRING_HELLO_ACCESS) \
/* `No warnings or errors were found.\n\n`. */ FN(STRING_NO_ERRORS) \
/* ` Not all warnings/errors were shown.\n\n`. */ FN(STRING_NOT_ALL_SHOWN) \
/* For `plain text`. */ FN(STRING_PLAIN_TEXT) \
/* For `replacing`. */ FN(STRING_REPLACING) \
/* For `specified`. */ FN(STRING_SPECIFIED) \
/* For `XML declaration`. */ FN(STRING_XML_DECLARATION) \
/* Explanatory text. */ FN(TEXT_ACCESS_ADVICE1) \
/* Explanatory text. */ FN(TEXT_ACCESS_ADVICE2) \
/* Explanatory text. */ FN(TEXT_BAD_FORM) \
/* Explanatory text. */ FN(TEXT_BAD_MAIN) \
/* Explanatory text. */ FN(TEXT_GENERAL_INFO) \
/* Explanatory text. */ FN(TEXT_GENERAL_INFO_PLEA) \
/* Describes the HTML table algorithm. */ FN(TEXT_HTML_T_ALGORITHM) \
/* Explanatory text. */ FN(TEXT_INVALID_URI) \
/* Explanatory text. */ FN(TEXT_INVALID_UTF16) \
/* Explanatory text. */ FN(TEXT_INVALID_UTF8) \
/* Explanatory text. */ FN(TEXT_M_IMAGE_ALT) \
/* Explanatory text. */ FN(TEXT_M_IMAGE_MAP) \
/* Explanatory text. */ FN(TEXT_M_LINK_ALT) \
/* Explanatory text. */ FN(TEXT_M_SUMMARY) \
/* Explanatory text. */ FN(TEXT_NEEDS_INTERVENTION) \
/* Explanatory text. */ FN(TEXT_SGML_CHARS) \
/* Explanatory text. */ FN(TEXT_USING_BODY) \
/* Explanatory text. */ FN(TEXT_USING_FONT) \
/* Explanatory text. */ FN(TEXT_USING_FRAMES) \
/* Explanatory text. */ FN(TEXT_USING_LAYER) \
/* Explanatory text. */ FN(TEXT_USING_NOBR) \
/* Explanatory text. */ FN(TEXT_USING_SPACER) \
/* Explanatory text. */ FN(TEXT_VENDOR_CHARS) \
/* Explanatory text. */ FN(TEXT_WINDOWS_CHARS)
typedef enum
{
/* This MUST be present and first. */
tidyMessagesMisc_first = tidyMessageCodes_last,
ACCESS_URL, /* Used to point to Web Accessibility Guidelines. */
ATRC_ACCESS_URL, /* Points to Tidy's accessibility page. */
FILE_CANT_OPEN, /* For retrieving a string when a file can't be opened. */
LINE_COLUMN_STRING, /* For retrieving localized `line %d column %d` text. */
STRING_DISCARDING, /* For `discarding`. */
STRING_ERROR_COUNT, /* `%u %s, %u %s were found!`. */
STRING_ERROR_COUNT_ERROR, /* `error` and `errors`. */
STRING_ERROR_COUNT_WARNING, /* `warning` and `warnings`. */
STRING_HELLO_ACCESS, /* Accessibility hello message. */
STRING_NO_ERRORS, /* `No warnings or errors were found.\n\n`. */
STRING_NOT_ALL_SHOWN, /* ` Not all warnings/errors were shown.\n\n`. */
STRING_PLAIN_TEXT, /* For retrieving a string `plain text`. */
STRING_REPLACING, /* For `replacing`. */
STRING_SPECIFIED, /* For `specified`. */
STRING_XML_DECLARATION, /* For retrieving a string `XML declaration`. */
TEXT_ACCESS_ADVICE1, /* Explanatory text. */
TEXT_ACCESS_ADVICE2, /* Explanatory text. */
TEXT_BAD_FORM, /* Explanatory text. */
TEXT_BAD_MAIN, /* Explanatory text. */
TEXT_GENERAL_INFO, /* Explanatory text. */
TEXT_GENERAL_INFO_PLEA, /* Explanatory text. */
TEXT_HTML_T_ALGORITHM, /* Paragraph for describing the HTML table algorithm. */
TEXT_INVALID_URI, /* Explanatory text. */
TEXT_INVALID_UTF16, /* Explanatory text. */
TEXT_INVALID_UTF8, /* Explanatory text. */
TEXT_M_IMAGE_ALT, /* Explanatory text. */
TEXT_M_IMAGE_MAP, /* Explanatory text. */
TEXT_M_LINK_ALT, /* Explanatory text. */
TEXT_M_SUMMARY, /* Explanatory text. */
TEXT_NEEDS_INTERVENTION, /* Explanatory text. */
TEXT_SGML_CHARS, /* Explanatory text. */
TEXT_USING_BODY, /* Explanatory text. */
TEXT_USING_FONT, /* Explanatory text. */
TEXT_USING_FRAMES, /* Explanatory text. */
TEXT_USING_LAYER, /* Explanatory text. */
TEXT_USING_NOBR, /* Explanatory text. */
TEXT_USING_SPACER, /* Explanatory text. */
TEXT_VENDOR_CHARS, /* Explanatory text. */
TEXT_WINDOWS_CHARS, /* Explanatory text. */
FOREACH_MSG_MISC(MAKE_ENUM)
/* This MUST be present and last. */
tidyMessagesMisc_last
@ -1181,90 +1202,94 @@ typedef enum
* Tidy console application. It it possible to build LibTidy without
* these strings.
*********************************************************************/
#define FOREACH_MSG_CONSOLE(FN) \
FN(TC_LABEL_COL) \
FN(TC_LABEL_FILE) \
FN(TC_LABEL_LANG) \
FN(TC_LABEL_LEVL) \
FN(TC_LABEL_OPT) \
FN(TC_MAIN_ERROR_LOAD_CONFIG) \
FN(TC_OPT_ACCESS) \
FN(TC_OPT_ASCII) \
FN(TC_OPT_ASHTML) \
FN(TC_OPT_ASXML) \
FN(TC_OPT_BARE) \
FN(TC_OPT_BIG5) \
FN(TC_OPT_CLEAN) \
FN(TC_OPT_CONFIG) \
FN(TC_OPT_ERRORS) \
FN(TC_OPT_FILE) \
FN(TC_OPT_GDOC) \
FN(TC_OPT_HELP) \
FN(TC_OPT_HELPCFG) \
FN(TC_OPT_HELPOPT) \
FN(TC_OPT_IBM858) \
FN(TC_OPT_INDENT) \
FN(TC_OPT_ISO2022) \
FN(TC_OPT_LANGUAGE) \
FN(TC_OPT_LATIN0) \
FN(TC_OPT_LATIN1) \
FN(TC_OPT_MAC) \
FN(TC_OPT_MODIFY) \
FN(TC_OPT_NUMERIC) \
FN(TC_OPT_OMIT) \
FN(TC_OPT_OUTPUT) \
FN(TC_OPT_QUIET) \
FN(TC_OPT_RAW) \
FN(TC_OPT_SHIFTJIS) \
FN(TC_OPT_SHOWCFG) \
FN(TC_OPT_UPPER) \
FN(TC_OPT_UTF16) \
FN(TC_OPT_UTF16BE) \
FN(TC_OPT_UTF16LE) \
FN(TC_OPT_UTF8) \
FN(TC_OPT_VERSION) \
FN(TC_OPT_WIN1252) \
FN(TC_OPT_WRAP) \
FN(TC_OPT_XML) \
FN(TC_OPT_XMLCFG) \
FN(TC_OPT_XMLSTRG) \
FN(TC_OPT_XMLERRS) \
FN(TC_OPT_XMLOPTS) \
FN(TC_OPT_XMLHELP) \
FN(TC_STRING_CONF_HEADER) \
FN(TC_STRING_CONF_NAME) \
FN(TC_STRING_CONF_TYPE) \
FN(TC_STRING_CONF_VALUE) \
FN(TC_STRING_CONF_NOTE) \
FN(TC_STRING_OPT_NOT_DOCUMENTED) \
FN(TC_STRING_OUT_OF_MEMORY) \
FN(TC_STRING_FATAL_ERROR) \
FN(TC_STRING_FILE_MANIP) \
FN(TC_STRING_LANG_MUST_SPECIFY) \
FN(TC_STRING_LANG_NOT_FOUND) \
FN(TC_STRING_MUST_SPECIFY) \
FN(TC_STRING_PROCESS_DIRECTIVES) \
FN(TC_STRING_CHAR_ENCODING) \
FN(TC_STRING_MISC) \
FN(TC_STRING_XML) \
FN(TC_STRING_UNKNOWN_OPTION) \
FN(TC_STRING_UNKNOWN_OPTION_B) \
FN(TC_STRING_VERS_A) \
FN(TC_STRING_VERS_B) \
FN(TC_TXT_HELP_1) \
FN(TC_TXT_HELP_2A) \
FN(TC_TXT_HELP_2B) \
FN(TC_TXT_HELP_3) \
FN(TC_TXT_HELP_CONFIG) \
FN(TC_TXT_HELP_CONFIG_NAME) \
FN(TC_TXT_HELP_CONFIG_TYPE) \
FN(TC_TXT_HELP_CONFIG_ALLW) \
FN(TC_TXT_HELP_LANG_1) \
FN(TC_TXT_HELP_LANG_2) \
FN(TC_TXT_HELP_LANG_3)
typedef enum
{
/* This MUST be present and first. */
tidyConsoleMessages_first = tidyMessagesMisc_last,
TC_LABEL_COL,
TC_LABEL_FILE,
TC_LABEL_LANG,
TC_LABEL_LEVL,
TC_LABEL_OPT,
TC_MAIN_ERROR_LOAD_CONFIG,
TC_OPT_ACCESS,
TC_OPT_ASCII,
TC_OPT_ASHTML,
TC_OPT_ASXML,
TC_OPT_BARE,
TC_OPT_BIG5,
TC_OPT_CLEAN,
TC_OPT_CONFIG,
TC_OPT_ERRORS,
TC_OPT_FILE,
TC_OPT_GDOC,
TC_OPT_HELP,
TC_OPT_HELPCFG,
TC_OPT_HELPOPT,
TC_OPT_IBM858,
TC_OPT_INDENT,
TC_OPT_ISO2022,
TC_OPT_LANGUAGE,
TC_OPT_LATIN0,
TC_OPT_LATIN1,
TC_OPT_MAC,
TC_OPT_MODIFY,
TC_OPT_NUMERIC,
TC_OPT_OMIT,
TC_OPT_OUTPUT,
TC_OPT_QUIET,
TC_OPT_RAW,
TC_OPT_SHIFTJIS,
TC_OPT_SHOWCFG,
TC_OPT_UPPER,
TC_OPT_UTF16,
TC_OPT_UTF16BE,
TC_OPT_UTF16LE,
TC_OPT_UTF8,
TC_OPT_VERSION,
TC_OPT_WIN1252,
TC_OPT_WRAP,
TC_OPT_XML,
TC_OPT_XMLCFG,
TC_OPT_XMLSTRG,
TC_OPT_XMLERRS,
TC_OPT_XMLOPTS,
TC_OPT_XMLHELP,
TC_STRING_CONF_HEADER,
TC_STRING_CONF_NAME,
TC_STRING_CONF_TYPE,
TC_STRING_CONF_VALUE,
TC_STRING_OPT_NOT_DOCUMENTED,
TC_STRING_OUT_OF_MEMORY,
TC_STRING_FATAL_ERROR,
TC_STRING_FILE_MANIP,
TC_STRING_LANG_MUST_SPECIFY,
TC_STRING_LANG_NOT_FOUND,
TC_STRING_MUST_SPECIFY,
TC_STRING_PROCESS_DIRECTIVES,
TC_STRING_CHAR_ENCODING,
TC_STRING_MISC,
TC_STRING_XML,
TC_STRING_UNKNOWN_OPTION,
TC_STRING_UNKNOWN_OPTION_B,
TC_STRING_VERS_A,
TC_STRING_VERS_B,
TC_TXT_HELP_1,
TC_TXT_HELP_2A,
TC_TXT_HELP_2B,
TC_TXT_HELP_3,
TC_TXT_HELP_CONFIG,
TC_TXT_HELP_CONFIG_NAME,
TC_TXT_HELP_CONFIG_TYPE,
TC_TXT_HELP_CONFIG_ALLW,
TC_TXT_HELP_LANG_1,
TC_TXT_HELP_LANG_2,
TC_TXT_HELP_LANG_3,
FOREACH_MSG_CONSOLE(MAKE_ENUM)
/* This MUST be present and last. */
tidyConsoleMessages_last

View file

@ -1592,13 +1592,13 @@ static void CheckMultiHeaders( TidyDocImpl* doc, Node* node )
if (validColSpanRows == no)
{
TY_(ReportAccessWarning)( doc, node, DATA_TABLE_REQUIRE_MARKUP_ROW_HEADERS );
TY_(DisplayHTMLTableAlgorithm)( doc );
TY_(DialogueMessage)( doc, TEXT_HTML_T_ALGORITHM, TidyDialogueDoc );
}
if (validColSpanColumns == no)
{
TY_(ReportAccessWarning)( doc, node, DATA_TABLE_REQUIRE_MARKUP_COLUMN_HEADERS );
TY_(DisplayHTMLTableAlgorithm)( doc );
TY_(DialogueMessage)( doc, TEXT_HTML_T_ALGORITHM, TidyDialogueDoc );
}
}
}
@ -3225,7 +3225,7 @@ void TY_(AccessibilityChecks)( TidyDocImpl* doc )
InitAccessibilityChecks( doc, cfg(doc, TidyAccessibilityCheckLevel) );
/* Hello there, ladies and gentlemen... */
TY_(AccessibilityHelloMessage)( doc );
TY_(DialogueMessage)( doc, STRING_HELLO_ACCESS, TidyDialogueDoc );
/* Checks all elements for script accessibility */
CheckScriptKeyboardAccessible( doc, &doc->root );

View file

@ -91,8 +91,6 @@ struct _TidyAccessImpl
};
void TY_(AccessibilityHelloMessage)( TidyDocImpl* doc ); /* impl. message.c */
void TY_(DisplayHTMLTableAlgorithm)( TidyDocImpl* doc ); /* impl. message.c */
void TY_(AccessibilityChecks)( TidyDocImpl* doc );

View file

@ -31,6 +31,8 @@ typedef struct _StreamOut StreamOut;
struct _TidyDocImpl;
typedef struct _TidyDocImpl TidyDocImpl;
struct _TidyMessageImpl;
typedef struct _TidyMessageImpl TidyMessageImpl;
struct _Dict;
typedef struct _Dict Dict;

View file

@ -80,14 +80,14 @@ static languageDefinition language_en = { whichPluralForm_en, {
{ STRING_ERROR_COUNT_ERROR, 1, "errors" },
{ STRING_ERROR_COUNT_WARNING, 0, "warning" },
{ STRING_ERROR_COUNT_WARNING, 1, "warnings" },
{ STRING_HELLO_ACCESS, 0, "Accessibility Checks:" },
{ STRING_HELLO_ACCESS, 0, "\nAccessibility Checks:\n" },
{/* This is not a formal name and can be translated. */
STRING_HTML_PROPRIETARY, 0, "HTML Proprietary"
},
{ STRING_MISSING_MALFORMED, 0, "missing or malformed argument for option: %s" },
{ STRING_NO_ERRORS, 0, "No warnings or errors were found." },
{ STRING_NO_SYSID, 0, "No system identifier in emitted doctype" },
{ STRING_NOT_ALL_SHOWN, 0, "Not all warnings/errors were shown." },
{ STRING_NOT_ALL_SHOWN, 0, "Tidy found %u %s and %u %s! Not all warnings/errors were shown." },
{ STRING_PLAIN_TEXT, 0, "plain text" },
{/* For example, "replacing invalid UTF-8 bytes" */
STRING_REPLACING, 0, "replacing"
@ -114,7 +114,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
" referenced by this attribute are inserted into the list and the \n"
" search stops for the current direction.\n"
" TD cells that set the axis attribute are also treated as header cells.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_WINDOWS_CHARS, 0,
@ -122,7 +121,7 @@ static languageDefinition language_en = { whichPluralForm_en, {
"128 - 159 may not be recognized on other platforms. You are\n"
"instead recommended to use named entities, e.g. &trade; rather\n"
"than Windows character code 153 (0x2122 in Unicode). Note that\n"
"as of February 1998 few browsers support the new entities.\n\n"
"as of February 1998 few browsers support the new entities.\n"
},
{/* This console output should be limited to 78 characters per line.
- %s represents a string-encoding name which may be localized in your language. */
@ -131,7 +130,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"work widely enough on the World Wide Web; you should avoid using the \n"
"%s character encoding, instead you are recommended to\n"
"use named entities, e.g. &trade;.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line.
- %s represents a string-encoding name which may be localized in your language.
@ -142,7 +140,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"Tidy assumed you wanted to refer to a character with the same byte value in the \n"
"%s encoding and replaced that reference with the Unicode \n"
"equivalent.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_INVALID_UTF8, 0,
@ -155,7 +152,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"does not allow mapping of unpaired surrogates, nor U+FFFE and U+FFFF\n"
"(but it does allow other noncharacters). For more information please refer to\n"
"http://www.unicode.org/ and http://www.cl.cam.ac.uk/~mgk25/unicode.html\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_INVALID_UTF16, 0,
@ -163,7 +159,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"The definition of UTF-16 in Annex C of ISO/IEC 10646-1:2000 does not allow the\n"
"mapping of unpaired surrogates. For more information please refer to\n"
"http://www.unicode.org/ and http://www.cl.cam.ac.uk/~mgk25/unicode.html\n"
"\n"
},
{/* This console output should be limited to 78 characters per line.
- The strings "Tidy" and "HTML Tidy" are the program name and must not be translated. */
@ -176,7 +171,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"scripts depend on that. If you want to depend on that, you must\n"
"escape the URI on your own. For more information please refer to\n"
"http://www.w3.org/International/O-URL-and-ident.html\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_BAD_FORM, 0,
@ -186,7 +180,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"in one table cell and the </form> in another. If the <form> is\n"
"placed before a table, the </form> cannot be placed inside the\n"
"table! Note that one form can't be nested inside another!\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_BAD_MAIN, 0,
@ -202,7 +195,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"table cells are useful for specifying which headers apply\n"
"to each table cell, enabling non-visual browsers to provide\n"
"a meaningful context for each cell.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_M_IMAGE_ALT, 0,
@ -210,7 +202,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
"of an image; longer descriptions should be given with the\n"
"longdesc attribute which takes a URL linked to the description.\n"
"These measures are needed for people using non-graphical browsers.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_M_IMAGE_MAP, 0,
@ -218,14 +209,12 @@ static languageDefinition language_en = { whichPluralForm_en, {
"maps as the latter are inaccessible to people using non-\n"
"graphical browsers. In addition, client-side maps are easier\n"
"to set up and provide immediate feedback to users.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_M_LINK_ALT, 0,
"For hypertext links defined using a client-side image map, you\n"
"need to use the alt attribute to provide a textual description\n"
"of the link for people using non-graphical browsers.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_USING_FRAMES, 0,
@ -233,31 +222,30 @@ static languageDefinition language_en = { whichPluralForm_en, {
"people who are either blind or using a browser that\n"
"doesn't support frames. A frames-based page should always\n"
"include an alternative layout inside a NOFRAMES element.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
{/* This console output should be limited to 78 characters per line.
- The URL should not be translated unless you find a matching URL in your language. */
TEXT_ACCESS_ADVICE1, 0,
"For further advice on how to make your pages accessible\n"
"see http://www.w3.org/WAI/GL"
"see http://www.w3.org/WAI/GL.\n"
},
{/* This console output should be limited to 78 characters per line.
- The URL should not be translated unless you find a matching URL in your language. */
TEXT_ACCESS_ADVICE2, 0,
" and http://www.html-tidy.org/accessibility/"
"For further advice on how to make your pages accessible\n"
"see http://www.w3.org/WAI/GL and http://www.html-tidy.org/accessibility/.\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_USING_LAYER, 0,
"The Cascading Style Sheets (CSS) Positioning mechanism\n"
"is recommended in preference to the proprietary <LAYER>\n"
"element due to limited vendor support for LAYER.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_USING_SPACER, 0,
"You are recommended to use CSS for controlling white\n"
"space (e.g. for indentation, margins and line spacing).\n"
"The proprietary <SPACER> element has limited vendor support.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_USING_FONT, 0,
@ -265,14 +253,12 @@ static languageDefinition language_en = { whichPluralForm_en, {
"properties such as its size and color. This will reduce\n"
"the size of HTML files and make them easier to maintain\n"
"compared with using <FONT> elements.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_USING_NOBR, 0,
"You are recommended to use CSS to control line wrapping.\n"
"Use \"white-space: nowrap\" to inhibit wrapping in place\n"
"of inserting <NOBR>...</NOBR> into the markup.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line. */
TEXT_USING_BODY, 0,
@ -283,7 +269,6 @@ static languageDefinition language_en = { whichPluralForm_en, {
TEXT_NEEDS_INTERVENTION, 0,
"This document has errors that must be fixed before\n"
"using HTML Tidy to generate a tidied up version.\n"
"\n"
},
{/* This console output should be limited to 78 characters per line.
- The strings "Tidy" and "HTML Tidy" are the program name and must not be translated. */
@ -296,12 +281,12 @@ static languageDefinition language_en = { whichPluralForm_en, {
"Lobby your company to join the W3C: http://www.w3.org/Consortium\n"
},
{/* This console output should be limited to 78 characters per line.
- The strings "Tidy" and "HTML Tidy" are the program name and must not be translated. */
- The strings "Tidy" and "HTML Tidy" are the program name and must not be translated.
- Don't terminate the last line with a newline. */
TEXT_GENERAL_INFO_PLEA, 0,
"\n"
"Do you speak a language other than English, or a different variant of \n"
"English? Consider helping us to localize HTML Tidy. For details please see \n"
"https://github.com/htacg/tidy-html5/blob/master/README/LOCALIZE.md\n"
"https://github.com/htacg/tidy-html5/blob/master/README/LOCALIZE.md"
},
@ -315,6 +300,9 @@ static languageDefinition language_en = { whichPluralForm_en, {
{ TidyError, 0, "Error: " },
{ TidyBadDocument, 0, "Document: " },
{ TidyFatal, 0, "Panic: " },
{ TidyDialogueInfo, 0, "Information: " },
{ TidyDialogueSummary, 0, "Summary: " },
{ TidyDialogueDoc, 0, "Document: " },
/***************************************
** Warnings and Errors
@ -2160,8 +2148,8 @@ static languageDefinition language_en = { whichPluralForm_en, {
},
{/* This console output should be limited to 78 characters per line.
- %n represents the name of the executable from the file system, and is mostly like going to be "tidy".
- %2 represents a version number, typically x.x.xx.
- First %s represents the name of the executable from the file system, and is mostly like going to be "tidy".
- Second %s represents a version number, typically x.x.xx.
- The strings "Tidy" and "HTML Tidy" are the program name and must not be translated. */
TC_TXT_HELP_1, 0,
"\n"

File diff suppressed because it is too large Load diff

View file

@ -1,32 +1,28 @@
#ifndef __MESSAGE_H__
#define __MESSAGE_H__
/*********************************************************************
/******************************************************************************
* General Message Writing Routines
*
* This module handles LibTidy's high level output routines, as well
* as provides some data structures for the console application.
*
* It also provides lookup functions and management for keys used
* for retrieval of these messages.
* This module handles LibTidy's high level output routines, as well as
* provides lookup functions and management for keys used for retrieval
* of these messages.
*
* LibTidy emits two general types of output:
*
* - Reports, which contain data relating to what Tidy discovered
* in your source file, and/or what Tidy did to your source file.
* In some cases general information about your source file is
* emitted as well. Reports are emitted in the current output
* buffer, but LibTidy users will probably prefer to hook into
* a callback in order to take advantage of the data that are
* available in a more flexible way.
* - Reports, which contain data relating to what Tidy discovered in your
* source file, and/or what Tidy did to your source file. In some cases
* general information about your source file is emitted as well. Reports
* are emitted in the current output buffer, but LibTidy users will probably
* prefer to hook into a callback in order to take advantage of the data
* that are available in a more flexible way.
*
* - Dialogue, consisting of general information that's not related
* to your source file in particular, is also written to the current
* output buffer when appropriate.
* - Dialogue, consisting of general information that's not related to your
* source file in particular, is also written to the current output buffer
* when appropriate.
*
* Report information typically takes the form of a warning, an
* error, info., etc., and the output routines keep track of the
* count of these and are make them available in the API.
* Report information typically takes the form of a warning, an error, info,
* etc., and the output routines keep track of the count of these.
*
* The preferred way of handling Tidy diagnostics output is either
* - define a new output sink, or
@ -35,23 +31,33 @@
* (c) 1998-2017 (W3C) MIT, ERCIM, Keio University, University of
* Toronto, HTACG
* See tidy.h for the copyright notice.
*********************************************************************/
******************************************************************************/
#include "forward.h"
/* Release Information */
/** @name Release Information */
/** @{ */
ctmbstr TY_(ReleaseDate)(void);
ctmbstr TY_(tidyLibraryVersion)(void);
/* High Level Message Writing Functions - General */
/** @} */
/** @name High Level Message Writing Functions - General */
/** @{ */
void TY_(ReportNotice)(TidyDocImpl* doc, Node *element, Node *node, uint code);
void TY_(ReportWarning)(TidyDocImpl* doc, Node *element, Node *node, uint code);
void TY_(ReportError)(TidyDocImpl* doc, Node* element, Node* node, uint code);
void TY_(ReportFatal)(TidyDocImpl* doc, Node* element, Node* node, uint code);
/* High Level Message Writing Functions - Specific */
/** @} */
/** @name High Level Message Writing Functions - Specific */
/** @{ */
void TY_(FileError)( TidyDocImpl* doc, ctmbstr file, TidyReportLevel level );
void TY_(ReportAttrError)( TidyDocImpl* doc, Node* node, AttVal* av, uint code );
@ -73,25 +79,27 @@ void TY_(ReportAccessWarning)( TidyDocImpl* doc, Node* node, uint code );
#endif
/* Output Dialogue Information */
/** @} */
/** @name Output Dialogue Information */
/** @{ */
void TY_(DialogueMessage)( TidyDocImpl* doc, uint code, TidyReportLevel level );
void TY_(ErrorSummary)( TidyDocImpl* doc );
void TY_(GeneralInfo)( TidyDocImpl* doc );
void TY_(NeedsAuthorIntervention)( TidyDocImpl* doc );
void TY_(ReportNumWarnings)( TidyDocImpl* doc );
/** @} */
/** @name Key Discovery */
/** @{ */
/**
* LibTidy users may want to use `TidyReportFilter3` to enable their own
* localization lookup features. Because Tidy's errors codes are enums the
* LibTidy users may want to use `TidyReportCallback` to enable their own
* localization lookup features. Because Tidy's report codes are enums the
* specific values can change over time. This function returns a string
* representing the enum value name that can be used as a lookup key
* independent of changing string values (TidyReportFiler2 is vulnerable
* to changing strings). `TidyReportFilter3` will return this general
* string as the error message indicator.
* independent of changing string values. `TidyReportCallback` will return
* this general string as the report message key.
*/
ctmbstr TY_(tidyErrorCodeAsKey)(uint code);

620
src/messageobj.c Normal file
View file

@ -0,0 +1,620 @@
/* messageobj.c
* Provides an external, extensible API for message reporting.
*
* (c) 2017 HTACG
* See tidy.h for the copyright notice.
*/
#include "messageobj.h"
#include "message.h"
#include "tidy-int.h"
#include "limits.h"
#include "tmbstr.h"
#if !defined(NDEBUG) && defined(_MSC_VER)
#include "sprtf.h"
#endif
/*********************************************************************
* BuildArgArray Support - declarations and forward declarations
*********************************************************************/
/** A record of a single argument and its type. An array these
** represents the arguments supplied to a format string, ordered
** in the same position as they occur in the format string. Because
** older versions of Windows don't support positional arguments,
** Tidy doesn't either.
*/
#define FORMAT_LENGTH 21
struct printfArg {
TidyFormatParameterType type; /* type of the argument */
int formatStart; /* where the format starts */
int formatLength; /* length of the format */
char format[FORMAT_LENGTH]; /* buffer for the format */
union { /* the argument */
int i;
uint ui;
double d;
const char *s;
} u;
};
/** Returns a pointer to an allocated array of `printfArg` given a format
** string and a va_list, or NULL if not successful or no parameters were
** given. Parameter `rv` will return with the count of zero or more
** parameters if successful, else -1.
**
*/
static struct printfArg *BuildArgArray( TidyDocImpl *doc, ctmbstr fmt, va_list ap, int *rv );
/*********************************************************************
* Tidy Message Object Support
*********************************************************************/
/** Create an internal representation of a Tidy message with all of
** the information that that we know about the message.
**
** The function signature doesn't have to stay static and is a good
** place to add instantiation if expanding the API.
**
** We currently know the doc, node, code, line, column, level, and
** args, will pre-calculate all of the other members upon creation.
** This ensures that we can use members directly, immediately,
** without having to use accessors internally.
**
** If any message callback filters are setup by API clients, they
** will be called here.
**
** This version serves as the designated initializer and as such
** requires every known parameter.
*/
static TidyMessageImpl *tidyMessageCreateInitV( TidyDocImpl *doc,
Node *node,
uint code,
int line,
int column,
TidyReportLevel level,
va_list args )
{
TidyMessageImpl *result = TidyDocAlloc(doc, sizeof(TidyMessageImpl));
TidyDoc tdoc = tidyImplToDoc(doc);
va_list args_copy;
enum { sizeMessageBuf=2048 };
ctmbstr pattern;
/* Things we know... */
result->tidyDoc = doc;
result->tidyNode = node;
result->code = code;
result->line = line;
result->column = column;
result->level = level;
/* Things we create... */
va_copy(args_copy, args);
result->arguments = BuildArgArray(doc, tidyDefaultString(code), args_copy, &result->argcount);
va_end(args_copy);
result->messageKey = TY_(tidyErrorCodeAsKey)(code);
result->messageFormatDefault = tidyDefaultString(code);
result->messageFormat = tidyLocalizedString(code);
result->messageDefault = TidyDocAlloc(doc, sizeMessageBuf);
va_copy(args_copy, args);
TY_(tmbvsnprintf)(result->messageDefault, sizeMessageBuf, result->messageFormatDefault, args_copy);
va_end(args_copy);
result->message = TidyDocAlloc(doc, sizeMessageBuf);
va_copy(args_copy, args);
TY_(tmbvsnprintf)(result->message, sizeMessageBuf, result->messageFormat, args_copy);
va_end(args_copy);
result->messagePosDefault = TidyDocAlloc(doc, sizeMessageBuf);
result->messagePos = TidyDocAlloc(doc, sizeMessageBuf);
if ( cfgBool(doc, TidyEmacs) && cfgStr(doc, TidyEmacsFile) )
{
/* Change formatting to be parsable by GNU Emacs */
TY_(tmbsnprintf)(result->messagePosDefault, sizeMessageBuf, "%s:%d:%d: ", cfgStr(doc, TidyEmacsFile), line, column);
TY_(tmbsnprintf)(result->messagePos, sizeMessageBuf, "%s:%d:%d: ", cfgStr(doc, TidyEmacsFile), line, column);
}
else
{
/* traditional format */
TY_(tmbsnprintf)(result->messagePosDefault, sizeMessageBuf, tidyDefaultString(LINE_COLUMN_STRING), line, column);
TY_(tmbsnprintf)(result->messagePos, sizeMessageBuf, tidyLocalizedString(LINE_COLUMN_STRING), line, column);
}
result->messagePrefixDefault = tidyDefaultString(level);
result->messagePrefix = tidyLocalizedString(level);
if ( line > 0 && column > 0 )
pattern = "%s%s%s"; /* pattern in there's location information */
else
pattern = "%.0s%s%s"; /* otherwise if there isn't */
if ( level > TidyFatal )
pattern = "%.0s%.0s%s"; /* dialog doesn't have pos or prefix */
result->messageOutputDefault = TidyDocAlloc(doc, sizeMessageBuf);
TY_(tmbsnprintf)(result->messageOutputDefault, sizeMessageBuf, pattern,
result->messagePosDefault, result->messagePrefixDefault,
result->messageDefault);
result->messageOutput = TidyDocAlloc(doc, sizeMessageBuf);
TY_(tmbsnprintf)(result->messageOutput, sizeMessageBuf, pattern,
result->messagePos, result->messagePrefix,
result->message);
result->allowMessage = yes;
/* reportFilter is a simple error filter that provides minimal information
to callback functions, and includes the message buffer in LibTidy's
configured localization. As it's a "legacy" API, it does not receive
TidyDialogue messages.*/
if ( (result->level <= TidyFatal) && doc->reportFilter )
{
result->allowMessage = result->allowMessage & doc->reportFilter( tdoc, result->level, result->line, result->column, result->messageOutput );
}
/* reportCallback is intended to allow LibTidy users to localize messages
via their own means by providing a key and the parameters to fill it.
As it's a "legacy" API, it does not receive TidyDialogue messages. */
if ( (result->level <= TidyFatal) && doc->reportCallback )
{
TidyDoc tdoc = tidyImplToDoc( doc );
va_copy(args_copy, args);
result->allowMessage = result->allowMessage & doc->reportCallback( tdoc, result->level, result->line, result->column, result->messageKey, args_copy );
va_end(args_copy);
}
/* messageCallback is the newest interface to interrogate Tidy's
emitted messages. */
if ( doc->messageCallback )
{
result->allowMessage = result->allowMessage & doc->messageCallback( tidyImplToMessage(result) );
}
return result;
}
TidyMessageImpl *TY_(tidyMessageCreate)( TidyDocImpl *doc,
uint code,
TidyReportLevel level,
... )
{
TidyMessageImpl *result;
va_list args;
va_start(args, level);
result = tidyMessageCreateInitV(doc, NULL, code, 0, 0, level, args);
va_end(args);
return result;
}
TidyMessageImpl *TY_(tidyMessageCreateWithNode)( TidyDocImpl *doc,
Node *node,
uint code,
TidyReportLevel level,
... )
{
TidyMessageImpl *result;
va_list args_copy;
int line = ( node ? node->line :
( doc->lexer ? doc->lexer->lines : 0 ) );
int col = ( node ? node->column :
( doc->lexer ? doc->lexer->columns : 0 ) );
va_start(args_copy, level);
result = tidyMessageCreateInitV(doc, node, code, line, col, level, args_copy);
va_end(args_copy);
return result;
}
TidyMessageImpl *TY_(tidyMessageCreateWithLexer)( TidyDocImpl *doc,
uint code,
TidyReportLevel level,
... )
{
TidyMessageImpl *result;
va_list args_copy;
int line = ( doc->lexer ? doc->lexer->lines : 0 );
int col = ( doc->lexer ? doc->lexer->columns : 0 );
va_start(args_copy, level);
result = tidyMessageCreateInitV(doc, NULL, code, line, col, level, args_copy);
va_end(args_copy);
return result;
}
void TY_(tidyMessageRelease)( TidyMessageImpl *message )
{
if ( !message )
return;
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->arguments );
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->messageDefault );
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->message );
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->messagePosDefault );
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->messagePos );
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->messageOutputDefault );
TidyDocFree( tidyDocToImpl(message->tidyDoc), message->messageOutput );
}
/*********************************************************************
* Modern Message Callback Functions
*********************************************************************/
ctmbstr TY_(getMessageKey)( TidyMessageImpl message )
{
return message.messageKey;
}
int TY_(getMessageLine)( TidyMessageImpl message )
{
return message.line;
}
int TY_(getMessageColumn)( TidyMessageImpl message )
{
return message.column;
}
TidyReportLevel TY_(getMessageLevel)( TidyMessageImpl message )
{
return message.level;
}
ctmbstr TY_(getMessageFormatDefault)( TidyMessageImpl message )
{
return message.messageFormatDefault;
}
ctmbstr TY_(getMessageFormat)( TidyMessageImpl message )
{
return message.messageFormat;
}
ctmbstr TY_(getMessageDefault)( TidyMessageImpl message )
{
return message.messageDefault;
}
ctmbstr TY_(getMessage)( TidyMessageImpl message )
{
return message.message;
}
ctmbstr TY_(getMessagePosDefault)( TidyMessageImpl message )
{
return message.messagePosDefault;
}
ctmbstr TY_(getMessagePos)( TidyMessageImpl message )
{
return message.messagePos;
}
ctmbstr TY_(getMessagePrefixDefault)( TidyMessageImpl message )
{
return message.messagePrefixDefault;
}
ctmbstr TY_(getMessagePrefix)( TidyMessageImpl message )
{
return message.messagePrefix;
}
ctmbstr TY_(getMessageOutputDefault)( TidyMessageImpl message )
{
return message.messageOutputDefault;
}
ctmbstr TY_(getMessageOutput)( TidyMessageImpl message )
{
return message.messageOutput;
}
/*********************************************************************
* Message Argument Interrogation
*********************************************************************/
TidyIterator TY_(getMessageArguments)( TidyMessageImpl message )
{
if (message.argcount > 0)
return (TidyIterator) (size_t)1;
else
return (TidyIterator) (size_t)0;
}
TidyMessageArgument TY_(getNextMessageArgument)( TidyMessageImpl message, TidyIterator* iter )
{
size_t item = 0;
size_t itemIndex;
assert( iter != NULL );
itemIndex = (size_t)*iter;
if ( itemIndex >= 1 && itemIndex <= (size_t)message.argcount )
{
item = itemIndex - 1;
itemIndex++;
}
/* Just as TidyIterator is really just a dumb, one-based index, the
TidyMessageArgument is really just a dumb, zero-based index; however
this type of iterator and opaque interrogation is simply how Tidy
does things. */
*iter = (TidyIterator)( itemIndex <= (size_t)message.argcount ? itemIndex : (size_t)0 );
return (TidyMessageArgument)item;
}
TidyFormatParameterType TY_(getArgType)( TidyMessageImpl message, TidyMessageArgument* arg )
{
int argNum = (int)*arg;
assert( argNum <= message.argcount );
return message.arguments[argNum].type;
}
ctmbstr TY_(getArgFormat)( TidyMessageImpl message, TidyMessageArgument* arg )
{
int argNum = (int)*arg;
assert( argNum <= message.argcount );
return message.arguments[argNum].format;
}
ctmbstr TY_(getArgValueString)( TidyMessageImpl message, TidyMessageArgument* arg )
{
int argNum = (int)*arg;
assert( argNum <= message.argcount );
assert( message.arguments[argNum].type == tidyFormatType_STRING);
return message.arguments[argNum].u.s;
}
uint TY_(getArgValueUInt)( TidyMessageImpl message, TidyMessageArgument* arg )
{
int argNum = (int)*arg;
assert( argNum <= message.argcount );
assert( message.arguments[argNum].type == tidyFormatType_UINT);
return message.arguments[argNum].u.ui;
}
int TY_(getArgValueInt)( TidyMessageImpl message, TidyMessageArgument* arg )
{
int argNum = (int)*arg;
assert( argNum <= message.argcount );
assert( message.arguments[argNum].type == tidyFormatType_INT);
return message.arguments[argNum].u.i;
}
double TY_(getArgValueDouble)( TidyMessageImpl message, TidyMessageArgument* arg )
{
int argNum = (int)*arg;
assert( argNum <= message.argcount );
assert( message.arguments[argNum].type == tidyFormatType_DOUBLE);
return message.arguments[argNum].u.d;
}
/*********************************************************************
* BuildArgArray support
* Adapted loosely from Mozilla `prprf.c`, Mozilla Public License:
* - https://www.mozilla.org/en-US/MPL/2.0/
*********************************************************************/
/** Returns a pointer to an allocated array of `printfArg` given a format
** string and a va_list, or NULL if not successful or no parameters were
** given. Parameter `rv` will return with the count of zero or more
** parameters if successful, else -1.
**
** We'll also be sure to use the document's allocator if specified, thus
** the requirement to pass in a TidyDocImpl.
**
** Currently Tidy only uses %c, %d, %s, %u, %X, although doubles are
** supported as well. Unsupported arguments will result in failure as
** described above.
*/
static struct printfArg* BuildArgArray( TidyDocImpl *doc, ctmbstr fmt, va_list ap, int* rv )
{
int number = 0; /* the quantity of valid arguments found; returned as rv. */
int cn = -1; /* keeps track of which parameter index is current. */
int i = 0; /* typical index. */
int pos = -1; /* starting position of current argument. */
const char* p; /* current position in format string. */
char c; /* current character. */
struct printfArg* nas;
/* first pass: determine number of valid % to allocate space. */
p = fmt;
*rv = 0;
while( ( c = *p++ ) != 0 )
{
if( c != '%' )
continue;
if( ( c = *p++ ) == '%' ) /* skip %% case */
continue;
else
number++;
}
if( number == 0 )
return NULL;
nas = (struct printfArg*)TidyDocAlloc( doc, number * sizeof( struct printfArg ) );
if( !nas )
{
*rv = -1;
return NULL;
}
for( i = 0; i < number; i++ )
{
nas[i].type = tidyFormatType_UNKNOWN;
}
/* second pass: set nas[].type and location. */
p = fmt;
while( ( c = *p++ ) != 0 )
{
if( c != '%' )
continue;
if( ( c = *p++ ) == '%' )
continue; /* skip %% case */
pos = p - fmt - 2; /* p already incremented twice */
/* width -- width via parameter */
if (c == '*')
{
/* not supported feature */
*rv = -1;
break;
}
/* width field -- skip */
while ((c >= '0') && (c <= '9'))
{
c = *p++;
}
/* precision */
if (c == '.')
{
c = *p++;
if (c == '*') {
/* not supported feature */
*rv = -1;
break;
}
while ((c >= '0') && (c <= '9'))
{
c = *p++;
}
}
cn++;
/* size and format */
nas[cn].type = tidyFormatType_UINT;
switch (c)
{
case 'c': /* unsigned int (char) */
case 'u': /* unsigned int */
case 'X': /* unsigned int as hex */
case 'x': /* unsigned int as hex */
case 'o': /* octal */
nas[cn].u.ui = va_arg( ap, unsigned int );
break;
case 'd': /* signed int */
case 'i': /* signed int */
nas[cn].type = tidyFormatType_INT;
nas[cn].u.i = va_arg( ap, int );
break;
case 's': /* string */
nas[cn].type = tidyFormatType_STRING;
nas[cn].u.s = va_arg( ap, char* );
break;
case 'e': /* double */
case 'E': /* double */
case 'f': /* double */
case 'F': /* double */
case 'g': /* double */
case 'G': /* double */
nas[cn].type = tidyFormatType_DOUBLE;
nas[cn].u.d = va_arg( ap, double );
break;
default:
nas[cn].type = tidyFormatType_UNKNOWN;
*rv = -1;
break;
}
/* position and format */
nas[cn].formatStart = pos;
nas[cn].formatLength = (p - fmt) - pos;
/* the format string exceeds the buffer length */
if ( nas[cn].formatLength >= FORMAT_LENGTH )
{
*rv = -1;
break;
}
else
{
strncpy(nas[cn].format, fmt + nas[cn].formatStart, nas[cn].formatLength);
}
/* Something's not right. */
if( nas[cn].type == tidyFormatType_UNKNOWN )
{
*rv = -1;
break;
}
}
/* third pass: fill the nas[cn].ap */
if( *rv < 0 )
{
TidyDocFree( doc, nas );;
return NULL;
}
*rv = number;
return nas;
}

166
src/messageobj.h Normal file
View file

@ -0,0 +1,166 @@
#ifndef messageobj_h
#define messageobj_h
/******************************************************************************
* Provides an external, extensible API for message reporting.
*
* This module implements the `TidyMessageImpl` structure (declared in
* `tidy-int.h`) in order to abstract the reporting of reports and dialogue
* from the rest of Tidy, and to enable a robust and extensible API for
* message interrogation by LibTidy users.
*
* (c) 2017 HTACG
* See tidy.h for the copyright notice.
******************************************************************************/
#include "forward.h"
/** @name Message Creation and Releasing */
/** @{ */
/** Creates a TidyMessageImpl, but without line numbers, such as used for
** information report output.
*/
TidyMessageImpl *TY_(tidyMessageCreate)( TidyDocImpl *doc,
uint code,
TidyReportLevel level,
... );
/** Creates a TidyMessageImpl, using the line and column from the provided
** Node as the message position source.
*/
TidyMessageImpl *TY_(tidyMessageCreateWithNode)( TidyDocImpl *doc,
Node *node,
uint code,
TidyReportLevel level,
... );
/** Creates a TidyMessageImpl, using the line and column from the provided
** document's Lexer as the message position source.
*/
TidyMessageImpl *TY_(tidyMessageCreateWithLexer)( TidyDocImpl *doc,
uint code,
TidyReportLevel level,
... );
/** Deallocates a TidyMessageImpl in order to free up its allocated memory
** when you're done using it.
*/
void TY_(tidyMessageRelease)( TidyMessageImpl *message );
/** @} */
/** @name Report and Dialogue API */
/** @{ */
/** get the message key string. */
ctmbstr TY_(getMessageKey)( TidyMessageImpl message );
/** get the line number the message applies to. */
int TY_(getMessageLine)( TidyMessageImpl message );
/** get the column the message applies to. */
int TY_(getMessageColumn)( TidyMessageImpl message );
/** get the TidyReportLevel of the message. */
TidyReportLevel TY_(getMessageLevel)( TidyMessageImpl message );
/** the built-in format string */
ctmbstr TY_(getMessageFormatDefault)( TidyMessageImpl message );
/** the localized format string */
ctmbstr TY_(getMessageFormat)( TidyMessageImpl message );
/** the message, formatted, default language */
ctmbstr TY_(getMessageDefault)( TidyMessageImpl message );
/** the message, formatted, localized */
ctmbstr TY_(getMessage)( TidyMessageImpl message );
/** the position part, default language */
ctmbstr TY_(getMessagePosDefault)( TidyMessageImpl message );
/** the position part, localized */
ctmbstr TY_(getMessagePos)( TidyMessageImpl message );
/** the prefix part, default language */
ctmbstr TY_(getMessagePrefixDefault)( TidyMessageImpl message );
/** the prefix part, localized */
ctmbstr TY_(getMessagePrefix)( TidyMessageImpl message );
/** the complete message, as would be output in the CLI */
ctmbstr TY_(getMessageOutputDefault)( TidyMessageImpl message );
/* the complete message, as would be output in the CLI, localized */
ctmbstr TY_(getMessageOutput)( TidyMessageImpl message );
/** @} */
/** @name Report Arguments Interrogation API */
/** @{ */
/**
* Initializes the TidyIterator to point to the first item in the message's
* argument. Use `TY_(getNextMEssageArgument)` to get an opaque instance of
* `TidyMessageArgument` for which the subsequent interrogators will be of use.
*/
TidyIterator TY_(getMessageArguments)( TidyMessageImpl message );
/**
* Returns the next `TidyMessageArgument`, for the given message, which can
* then be interrogated with the API, and advances the iterator.
*/
TidyMessageArgument TY_(getNextMessageArgument)( TidyMessageImpl message, TidyIterator* iter );
/**
* Returns the `TidyFormatParameterType` of the given message argument.
*/
TidyFormatParameterType TY_(getArgType)( TidyMessageImpl message, TidyMessageArgument* arg );
/**
* Returns the format specifier of the given message argument. The memory for
* this string is cleared upon termination of the callback, so do be sure to
* make your own copy.
*/
ctmbstr TY_(getArgFormat)( TidyMessageImpl message, TidyMessageArgument* arg );
/**
* Returns the string value of the given message argument. An assertion
* will be generated if the argument type is not a string.
*/
ctmbstr TY_(getArgValueString)( TidyMessageImpl message, TidyMessageArgument* arg );
/**
* Returns the unsigned integer value of the given message argument. An
* assertion will be generated if the argument type is not an unsigned
* integer.
*/
uint TY_(getArgValueUInt)( TidyMessageImpl message, TidyMessageArgument* arg );
/**
* Returns the integer value of the given message argument. An assertion
* will be generated if the argument type is not an integer.
*/
int TY_(getArgValueInt)( TidyMessageImpl message, TidyMessageArgument* arg );
/**
* Returns the double value of the given message argument. An assertion
* will be generated if the argument type is not a double.
*/
double TY_(getArgValueDouble)( TidyMessageImpl message, TidyMessageArgument* arg );
/** @} */
#endif /* messageobj_h */

View file

@ -56,9 +56,9 @@ struct _TidyDocImpl
StreamIn* docIn;
StreamOut* docOut;
StreamOut* errout;
TidyReportFilter mssgFilt;
TidyReportFilter2 mssgFilt2;
TidyReportFilter3 mssgFilt3;
TidyReportFilter reportFilter;
TidyReportCallback reportCallback;
TidyMessageCallback messageCallback;
TidyOptCallback pOptCallback;
TidyPPProgress progressCallback;
@ -96,6 +96,41 @@ struct _TidyDocImpl
tmbstr givenDoctype;
};
/** The basic struct for communicating a message within LibTidy. All of the
** relevant information pertaining to a message can be retrieved with the
** accessor functions and one of these records.
*/
struct _TidyMessageImpl
{
TidyDocImpl *tidyDoc; /* document instance this message is attributed to */
Node *tidyNode; /* the node reporting the message, if applicable */
uint code; /* the message code */
int line; /* the line message applies to */
int column; /* the column the message applies to */
TidyReportLevel level; /* the severity level of the message */
Bool allowMessage; /* indicates whether or not a filter rejected a message */
int argcount; /* the number of arguments */
struct printfArg* arguments; /* the arguments' values and types */
ctmbstr messageKey; /* the message code as a key string */
ctmbstr messageFormatDefault; /* the built-in format string */
ctmbstr messageFormat; /* the localized format string */
tmbstr messageDefault; /* the message, formatted, default language */
tmbstr message; /* the message, formatted, localized */
tmbstr messagePosDefault; /* the position part, default language */
tmbstr messagePos; /* the position part, localized */
ctmbstr messagePrefixDefault; /* the prefix part, default language */
ctmbstr messagePrefix; /* the prefix part, localized */
tmbstr messageOutputDefault; /* the complete string Tidy would output */
tmbstr messageOutput; /* the complete string, localized */
};
/* Twizzle internal/external types */
#ifdef NEVER
@ -112,17 +147,20 @@ const TidyOptionImpl* tidyOptionToImpl( TidyOption topt );
TidyOption tidyImplToOption( const TidyOptionImpl* option );
#else
#define tidyDocToImpl( tdoc ) ((TidyDocImpl*)(tdoc))
#define tidyImplToDoc( doc ) ((TidyDoc)(doc))
#define tidyDocToImpl( tdoc ) ((TidyDocImpl*)(tdoc))
#define tidyImplToDoc( doc ) ((TidyDoc)(doc))
#define tidyNodeToImpl( tnod ) ((Node*)(tnod))
#define tidyImplToNode( node ) ((TidyNode)(node))
#define tidyMessageToImpl( tmessage ) ((TidyMessageImpl*)(tmessage))
#define tidyImplToMessage( message ) ((TidyMessage)(message))
#define tidyAttrToImpl( tattr ) ((AttVal*)(tattr))
#define tidyImplToAttr( attval ) ((TidyAttr)(attval))
#define tidyNodeToImpl( tnod ) ((Node*)(tnod))
#define tidyImplToNode( node ) ((TidyNode)(node))
#define tidyOptionToImpl( topt ) ((const TidyOptionImpl*)(topt))
#define tidyImplToOption( option ) ((TidyOption)(option))
#define tidyAttrToImpl( tattr ) ((AttVal*)(tattr))
#define tidyImplToAttr( attval ) ((TidyAttr)(attval))
#define tidyOptionToImpl( topt ) ((const TidyOptionImpl*)(topt))
#define tidyImplToOption( option ) ((TidyOption)(option))
#endif

View file

@ -26,6 +26,7 @@
#include "gdoc.h"
#include "config.h"
#include "message.h"
#include "messageobj.h"
#include "pprint.h"
#include "entities.h"
#include "tmbstr.h"
@ -639,14 +640,11 @@ Bool TIDY_CALL tidyOptCopyConfig( TidyDoc to, TidyDoc from )
/* I/O and Message handling interface
**
** By default, Tidy will define, create and use
** tdocances of input and output handlers for
** standard C buffered I/O (i.e. FILE* stdin,
** FILE* stdout and FILE* stderr for content
** input, content output and diagnostic output,
** respectively. A FILE* cfgFile input handler
** will be used for config files. Command line
** options will just be set directly.
** By default, Tidy will define, create and use instance of input and output
** handlers for standard C buffered I/O (i.e. FILE* stdin, FILE* stdout and
** FILE* stderr for content input, content output and diagnostic output,
** respectively. A FILE* cfgFile input handler will be used for config files.
** Command line options will just be set directly.
*/
void TIDY_CALL tidySetEmacsFile( TidyDoc tdoc, ctmbstr filePath )
@ -665,49 +663,182 @@ ctmbstr TIDY_CALL tidyGetEmacsFile( TidyDoc tdoc )
** handler to redirect all diagnostics output. Return true
** to proceed with output, false to cancel.
*/
Bool TIDY_CALL tidySetReportFilter( TidyDoc tdoc, TidyReportFilter filt )
Bool TIDY_CALL tidySetReportFilter( TidyDoc tdoc, TidyReportFilter filt )
{
TidyDocImpl* impl = tidyDocToImpl( tdoc );
if ( impl )
{
impl->mssgFilt = filt;
impl->reportFilter = filt;
return yes;
}
return no;
}
/* TidyReportFilter2 functions similar to TidyReportFilter, but provides the
** built-in English format string and va_list so that LibTidy users can use
** the format string as a lookup key for providing their own error
** localizations.
*/
Bool TIDY_CALL tidySetReportFilter2( TidyDoc tdoc, TidyReportFilter2 filt )
{
TidyDocImpl* impl = tidyDocToImpl( tdoc );
if ( impl )
{
impl->mssgFilt2 = filt;
return yes;
}
return no;
}
/* TidyReportFilter3 functions similar to TidyReportFilter, but provides the
/* tidySetReportCallback functions similar to TidyReportFilter, but provides the
* string version of the internal enum name so that LibTidy users can use
** the string as a lookup key for providing their own error localizations.
** See the string key definitions in tidyenum.h.
*/
Bool TIDY_CALL tidySetReportFilter3( TidyDoc tdoc, TidyReportFilter3 filt )
Bool TIDY_CALL tidySetReportCallback( TidyDoc tdoc, TidyReportCallback filt )
{
TidyDocImpl* impl = tidyDocToImpl( tdoc );
if ( impl )
{
impl->mssgFilt3 = filt;
impl->reportCallback = filt;
return yes;
}
return no;
}
Bool TIDY_CALL tidySetMessageCallback( TidyDoc tdoc, TidyMessageCallback filt )
{
TidyDocImpl* impl = tidyDocToImpl( tdoc );
if ( impl )
{
impl->messageCallback = filt;
return yes;
}
return no;
}
ctmbstr TIDY_CALL tidyGetMessageKey( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageKey)(*message);
}
int TIDY_CALL tidyGetMessageLine( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageLine)(*message);
}
int TIDY_CALL tidyGetMessageColumn( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageColumn)(*message);
}
TidyReportLevel TIDY_CALL tidyGetMessageLevel( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageLevel)(*message);
}
ctmbstr TIDY_CALL tidyGetMessageFormatDefault( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageFormatDefault)(*message);
}
ctmbstr TIDY_CALL tidyGetMessageFormat( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageFormat)(*message);
}
ctmbstr TIDY_CALL tidyGetMessageDefault( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageDefault)(*message);
}
ctmbstr TIDY_CALL tidyGetMessage( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessage)(*message);
}
ctmbstr TIDY_CALL tidyGetMessagePosDefault( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessagePosDefault)(*message);
}
ctmbstr TIDY_CALL tidyGetMessagePos( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessagePos)(*message);
}
ctmbstr TIDY_CALL tidyGetMessagePrefixDefault( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessagePrefixDefault)(*message);
}
ctmbstr TIDY_CALL tidyGetMessagePrefix( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessagePrefix)(*message);
}
ctmbstr TIDY_CALL tidyGetMessageOutputDefault( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageOutputDefault)(*message);
}
ctmbstr TIDY_CALL tidyGetMessageOutput( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageOutput)(*message);
}
TidyIterator TIDY_CALL tidyGetMessageArguments( TidyMessage tmessage )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getMessageArguments)(*message);
}
TidyMessageArgument TIDY_CALL tidyGetNextMessageArgument( TidyMessage tmessage, TidyIterator* iter )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getNextMessageArgument)(*message, iter);
}
TidyFormatParameterType TIDY_CALL tidyGetArgType( TidyMessage tmessage, TidyMessageArgument* arg )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getArgType)(*message, arg);
}
ctmbstr TIDY_CALL tidyGetArgFormat( TidyMessage tmessage, TidyMessageArgument* arg )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getArgFormat)(*message, arg);
}
ctmbstr TIDY_CALL tidyGetArgValueString( TidyMessage tmessage, TidyMessageArgument* arg )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getArgValueString)(*message, arg);
}
uint TIDY_CALL tidyGetArgValueUInt( TidyMessage tmessage, TidyMessageArgument* arg )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getArgValueUInt)(*message, arg);
}
int TIDY_CALL tidyGetArgValueInt( TidyMessage tmessage, TidyMessageArgument* arg )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getArgValueInt)(*message, arg);
}
double TIDY_CALL tidyGetArgValueDouble( TidyMessage tmessage, TidyMessageArgument* arg )
{
TidyMessageImpl *message = tidyMessageToImpl(tmessage);
return TY_(getArgValueDouble)(*message, arg);
}
#if 0 /* Not yet */
int tidySetContentOutputSink( TidyDoc tdoc, TidyOutputSink* outp )
{
@ -877,7 +1008,10 @@ void TIDY_CALL tidyGeneralInfo( TidyDoc tdoc )
{
TidyDocImpl* impl = tidyDocToImpl( tdoc );
if ( impl )
TY_(GeneralInfo)( impl );
{
TY_(DialogueMessage)( impl, TEXT_GENERAL_INFO, TidyDialogueInfo);
TY_(DialogueMessage)( impl, TEXT_GENERAL_INFO_PLEA, TidyDialogueInfo);
}
}
@ -1309,7 +1443,7 @@ int tidyDocRunDiagnostics( TidyDocImpl* doc )
}
if ( doc->errors > 0 && !force )
TY_(NeedsAuthorIntervention)( doc );
TY_(DialogueMessage)(doc, TEXT_NEEDS_INTERVENTION, TidyDialogueDoc);
return tidyDocStatus( doc );
}
@ -2362,12 +2496,12 @@ tmbstr TIDY_CALL tidySystemLocale(tmbstr result)
return TY_(tidySystemLocale)( result );
}
Bool TIDY_EXPORT tidySetLanguage( ctmbstr languageCode )
Bool TIDY_CALL tidySetLanguage( ctmbstr languageCode )
{
return TY_(tidySetLanguage)( languageCode );
}
ctmbstr TIDY_EXPORT tidyGetLanguage()
ctmbstr TIDY_CALL tidyGetLanguage()
{
return TY_(tidyGetLanguage)();
}