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.
2017-03-13 17:28:57 +00:00
|
|
|
/* 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
|
|
|
|
*********************************************************************/
|
|
|
|
|
|
|
|
|
2017-03-16 20:46:01 +00:00
|
|
|
TidyDocImpl* TY_(getMessageDoc)( TidyMessageImpl message )
|
|
|
|
{
|
|
|
|
return message.tidyDoc;
|
|
|
|
}
|
|
|
|
|
Continue the documentation effort!
- Many, many updates to the public header files.
- tidyenum.h was reorganized substantially in order to better generate
documentation with Doxygen.
- This was also a good time to clean up all of the various enums for languages
and strings. Everything is simple and in a single enum now, other than a
couple of cases (TidyOptionId, for example, doesn't need to be redefined).
- A full and complete audit of the strings meant some opportunities to delete
useless strings.
- Reorganized the order of the strings in language_en.h in order to better
find things when programmers want to make changes. There are a lot fewer
internal "sections" now, and everything has been painstakingly sorted within
the remaining sections.
- Consequently rebased all of the PO's, POT, and other language files.
- Updated several of the READMEs with the newest information.
- Made the READMEs easier to copy into the Doxygen project by changing some of
the code format for compatibility, mainly the use of tildes instead of
backslashes for code blocks.
- Added tidyGetMessageCode() to message API. Despite the huge diff, this is the
only externally-visible change, other than removing some enums (but not their
values!).
- Passing `next` tests on Mac, Linux, Win10.
2017-03-21 01:07:53 +00:00
|
|
|
uint TY_(getMessageCode)( TidyMessageImpl message )
|
|
|
|
{
|
|
|
|
return message.code;
|
|
|
|
}
|
|
|
|
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
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 )
|
|
|
|
{
|
2017-04-04 18:32:29 +00:00
|
|
|
int argNum = (int)(size_t)*arg;
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
assert( argNum <= message.argcount );
|
|
|
|
|
|
|
|
return message.arguments[argNum].type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ctmbstr TY_(getArgFormat)( TidyMessageImpl message, TidyMessageArgument* arg )
|
|
|
|
{
|
2017-04-04 18:32:29 +00:00
|
|
|
int argNum = (int)(size_t)*arg;
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
assert( argNum <= message.argcount );
|
|
|
|
|
|
|
|
return message.arguments[argNum].format;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ctmbstr TY_(getArgValueString)( TidyMessageImpl message, TidyMessageArgument* arg )
|
|
|
|
{
|
2017-04-04 18:32:29 +00:00
|
|
|
int argNum = (int)(size_t)*arg;
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
assert( argNum <= message.argcount );
|
|
|
|
assert( message.arguments[argNum].type == tidyFormatType_STRING);
|
|
|
|
|
|
|
|
return message.arguments[argNum].u.s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint TY_(getArgValueUInt)( TidyMessageImpl message, TidyMessageArgument* arg )
|
|
|
|
{
|
2017-04-04 18:32:29 +00:00
|
|
|
int argNum = (int)(size_t)*arg;
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
assert( argNum <= message.argcount );
|
|
|
|
assert( message.arguments[argNum].type == tidyFormatType_UINT);
|
|
|
|
|
|
|
|
return message.arguments[argNum].u.ui;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int TY_(getArgValueInt)( TidyMessageImpl message, TidyMessageArgument* arg )
|
|
|
|
{
|
2017-04-04 18:32:29 +00:00
|
|
|
int argNum = (int)(size_t)*arg;
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
assert( argNum <= message.argcount );
|
|
|
|
assert( message.arguments[argNum].type == tidyFormatType_INT);
|
|
|
|
|
|
|
|
return message.arguments[argNum].u.i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double TY_(getArgValueDouble)( TidyMessageImpl message, TidyMessageArgument* arg )
|
|
|
|
{
|
2017-04-04 18:32:29 +00:00
|
|
|
int argNum = (int)(size_t)*arg;
|
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.
2017-03-13 17:28:57 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|