Coverage Report

Created: 2026-04-01 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tidy-html5/src/message.c
Line
Count
Source
1
/* message.c -- General Message Writing Routines
2
3
  (c) 1998-2017 (W3C) MIT, ERCIM, Keio University, University of
4
  Toronto, HTACG
5
  See tidy.h for the copyright notice.
6
7
*/
8
9
#include "message.h"
10
#include "messageobj.h"
11
#include "limits.h"
12
#include "tidy-int.h"
13
#include "lexer.h"
14
#include "streamio.h"
15
#include "tmbstr.h"
16
#include "utf8.h"
17
#include "version.h"
18
19
20
/*********************************************************************
21
 * Release Information
22
 *********************************************************************/
23
24
ctmbstr TY_(ReleaseDate)(void)
25
0
{
26
0
  return TY_(release_date);
27
0
}
28
29
30
ctmbstr TY_(tidyLibraryVersion)(void)
31
20.4k
{
32
20.4k
  return TY_(library_version);
33
20.4k
}
34
35
36
/*********************************************************************
37
 * General Message Utility Functions
38
 *********************************************************************/
39
40
/* Returns the given node's tag as a string. */
41
static char* TagToString(Node* tag, char* buf, size_t count)
42
11.0M
{
43
11.0M
    *buf = 0;
44
11.0M
    if (tag)
45
9.29M
    {
46
9.29M
        if (TY_(nodeIsElement)(tag))
47
9.15M
            TY_(tmbsnprintf)(buf, count, "<%s>", tag->element);
48
137k
        else if (tag->type == EndTag)
49
78.5k
            TY_(tmbsnprintf)(buf, count, "</%s>", tag->element);
50
58.8k
        else if (tag->type == DocTypeTag)
51
21.9k
            TY_(tmbsnprintf)(buf, count, "<!DOCTYPE>");
52
36.9k
        else if (tag->type == TextNode)
53
33.7k
            TY_(tmbsnprintf)(buf, count, "%s", "STRING_PLAIN_TEXT");
54
3.25k
        else if (tag->type == XmlDecl)
55
1.88k
            TY_(tmbsnprintf)(buf, count, "%s", "STRING_XML_DECLARATION");
56
1.37k
        else if (tag->element)
57
996
            TY_(tmbsnprintf)(buf, count, "%s", tag->element);
58
9.29M
    }
59
11.0M
    return buf + TY_(tmbstrlen)(buf);
60
11.0M
}
61
62
63
/* Convert an integer to a string. */
64
static void NtoS(int n, tmbstr str)
65
1.36k
{
66
1.36k
    tmbchar buf[40];
67
1.36k
    int i;
68
    
69
2.72k
    for (i = 0;; ++i)
70
4.08k
    {
71
4.08k
        buf[i] = (tmbchar)( (n % 10) + '0' );
72
        
73
4.08k
        n = n / 10;
74
        
75
4.08k
        if (n == 0)
76
1.36k
            break;
77
4.08k
    }
78
    
79
1.36k
    n = i;
80
    
81
5.45k
    while (i >= 0)
82
4.08k
    {
83
4.08k
        str[n-i] = buf[i];
84
4.08k
        --i;
85
4.08k
    }
86
    
87
1.36k
    str[n+1] = '\0';
88
1.36k
}
89
90
91
/* Get an HTML version string */
92
static ctmbstr HTMLVersion( TidyDocImpl* doc )
93
6.70k
{
94
6.70k
    uint versionEmitted = doc->lexer->versionEmitted;
95
6.70k
    uint declared = doc->lexer->doctype;
96
6.70k
    uint version = versionEmitted == 0 ? declared : versionEmitted;
97
6.70k
    ctmbstr result = TY_(HTMLVersionNameFromCode)(version, 0);
98
6.70k
    if (!result)
99
0
        result = tidyLocalizedString(STRING_HTML_PROPRIETARY);
100
6.70k
    return result;
101
6.70k
}
102
103
104
/*********************************************************************
105
 * Message Writing Functions
106
 * These functions provide final, formatted output to the output sink.
107
 *********************************************************************/
108
109
110
/* Writes messages to the output sink unless they are suppressed by one of the
111
** message callback filters, or suppressed by the configuration settings.
112
** Report messages are messages that are included in the "error table," and
113
** dialogue messages are any other output that Tidy traditionally emits.
114
*/
115
static void messageOut( TidyMessageImpl *message )
116
7.11M
{
117
7.11M
    TidyDocImpl *doc;
118
7.11M
    Bool go = yes;
119
120
7.11M
    if ( !message )
121
0
        return;
122
123
7.11M
    doc = message->tidyDoc;
124
125
    /* The filter has had a chance to suppress *any* message from output. */
126
7.11M
    go = message->allowMessage;
127
128
    /* Update the count of each report type. */
129
7.11M
    switch ( message->level )
130
7.11M
    {
131
149k
        case TidyInfo:
132
149k
            doc->infoMessages++;
133
149k
            break;
134
6.82M
        case TidyWarning:
135
6.82M
            doc->warnings++;
136
6.82M
            break;
137
0
        case TidyConfig:
138
0
            doc->optionErrors++;
139
0
            break;
140
0
        case TidyAccess:
141
0
            doc->accessErrors++;
142
0
            break;
143
111k
        case TidyError:
144
111k
            doc->errors++;
145
111k
            break;
146
0
        case TidyBadDocument:
147
0
            doc->docErrors++;
148
0
            break;
149
0
        case TidyFatal:
150
            /* Ack! */
151
0
            break;
152
25.9k
        default:
153
25.9k
            break;
154
7.11M
    }
155
156
    /* Suppress report messages if they've been muted. */
157
7.11M
    go = go & !message->muted;
158
159
    /* Suppress report messages if we've already reached the reporting limit. */
160
7.11M
    if ( message->level <= TidyFatal )
161
7.08M
    {
162
7.08M
        go = go & ( doc->errors < cfg(doc, TidyShowErrors) );
163
7.08M
    }
164
165
    /* Let TidyQuiet silence a lot of things. */
166
7.11M
    if ( cfgBool( doc, TidyQuiet ) == yes )
167
0
    {
168
0
        go = go && message->code != STRING_DOCTYPE_GIVEN;
169
0
        go = go && message->code != STRING_CONTENT_LOOKS;
170
0
        go = go && message->code != STRING_NO_SYSID;
171
0
        go = go && message->level != TidyDialogueInfo;
172
0
        go = go && message->level != TidyConfig;
173
0
        go = go && message->level != TidyInfo;
174
0
        go = go && !(message->level >= TidyDialogueSummary &&
175
0
                            message->code != STRING_NEEDS_INTERVENTION);
176
0
    }
177
178
    /* Let !TidyShowInfo silence some things. */
179
7.11M
    if ( cfgBool( doc, TidyShowInfo ) == no )
180
0
    {
181
0
        go = go && message->level != TidyInfo;
182
183
        /* Temporary; TidyShowInfo shouldn't affect TidyDialogueInfo, but
184
           right now such messages are hidden until we granularize the
185
           output controls. */
186
0
        go = go && message->level != TidyDialogueInfo;
187
0
    }
188
189
    /* Let !TidyShowWarnings silence some things. */
190
7.11M
    if ( cfgBool( doc, TidyShowWarnings ) == no )
191
0
    {
192
0
        go = go && message->level != TidyWarning;
193
0
    }
194
195
    /* Output the message if applicable. */
196
7.11M
    if ( go )
197
3.71M
    {
198
3.71M
        TidyOutputSink *outp = &doc->errout->sink;
199
3.71M
        ctmbstr cp;
200
3.71M
        byte b = '\0';
201
225M
        for ( cp = message->messageOutput; *cp; ++cp )
202
222M
        {
203
222M
            b = (*cp & 0xff);
204
222M
            if (b == (byte)'\n')
205
36.6k
                TY_(WriteChar)( b, doc->errout );   /* for EOL translation */
206
222M
            else
207
222M
                outp->putByte( outp->sinkData, b ); /* #383 - no encoding */
208
222M
        }
209
210
        /* Always add a trailing newline. Reports require this, and dialogue
211
           messages will be better spaced out without having to fill the
212
           language file with superfluous newlines. */
213
3.71M
        TY_(WriteChar)( '\n', doc->errout );
214
3.71M
    }
215
216
7.11M
    TY_(tidyMessageRelease)(message);
217
7.11M
}
218
219
220
/*********************************************************************
221
 * Report Formatting
222
 * In order to provide a single, predictable reporting system, Tidy
223
 * provides an extensible messaging system that provides most of the
224
 * basic requirements for most reports, while permitting simple
225
 * implementation of new reports in a flexible manner. By adding
226
 * additional formatters, new messages can be added easily while
227
 * maintaining Tidy's internal organization.
228
 *********************************************************************/
229
230
231
/* Functions of this type will create new instances of TidyMessage specific to
232
** the type of report being emitted. Many messages share the same formatter for
233
** messages, but new ones can be written as required. Please have a look at
234
** the existing formatters in order to determine if an existing signature is
235
** compatible with the report you wish to output before adding a new formatter.
236
** In particular, if an existing formatter provides most of the local variables
237
** required to populate your format string, try to use it.
238
*/
239
typedef TidyMessageImpl*(messageFormatter)(TidyDocImpl* doc, Node *element, Node *node, uint code, uint level, va_list args);
240
241
242
/* Forward declarations of messageFormatter functions. */
243
static messageFormatter formatAccessReport;
244
static messageFormatter formatAttributeReport;
245
static messageFormatter formatEncodingReport;
246
static messageFormatter formatStandard;
247
static messageFormatter formatStandardDynamic;
248
249
250
/* This structure ties together for each report Code the default 
251
** TidyReportLevel, the Formatter to be used to construct the message, and the
252
** next code to output, if applicable. Assuming an existing formatter can,
253
** this it makes it simple to output new reports, or to change report level by
254
** modifying this array.
255
*/
256
static struct _dispatchTable {
257
    uint code;                 /**< The message code. */
258
    TidyReportLevel level;     /**< The default TidyReportLevel of the message. */
259
    messageFormatter *handler; /**< The formatter for the report. */
260
    uint next;                 /**< If multiple codes should be displayed, which is next? */
261
} dispatchTable[] = {
262
    { ADDED_MISSING_CHARSET,        TidyInfo,        formatStandard          },
263
    { ANCHOR_NOT_UNIQUE,            TidyWarning,     formatAttributeReport   },
264
    { ANCHOR_DUPLICATED,            TidyWarning,     formatAttributeReport   },
265
    { APOS_UNDEFINED,               TidyWarning,     formatStandard          },
266
    { ATTR_VALUE_NOT_LCASE,         TidyWarning,     formatAttributeReport   },
267
    { ATTRIBUTE_VALUE_REPLACED,     TidyInfo,        formatAttributeReport   },
268
    { ATTRIBUTE_IS_NOT_ALLOWED,     TidyWarning,     formatAttributeReport   },
269
    { BACKSLASH_IN_URI,             TidyWarning,     formatAttributeReport   },
270
    { BAD_ATTRIBUTE_VALUE_REPLACED, TidyWarning,     formatAttributeReport   },
271
    { BAD_ATTRIBUTE_VALUE,          TidyWarning,     formatAttributeReport   },
272
    { BAD_CDATA_CONTENT,            TidyWarning,     formatStandard          },
273
    { BAD_SUMMARY_HTML5,            TidyWarning,     formatStandard          },
274
    { BAD_SURROGATE_LEAD,           TidyWarning,     formatStandard          },
275
    { BAD_SURROGATE_PAIR,           TidyWarning,     formatStandard          },
276
    { BAD_SURROGATE_TAIL,           TidyWarning,     formatStandard          },
277
    { CANT_BE_NESTED,               TidyWarning,     formatStandard          },
278
    { COERCE_TO_ENDTAG,             TidyWarning,     formatStandard          },
279
    { CONTENT_AFTER_BODY,           TidyWarning,     formatStandard          },
280
    { CUSTOM_TAG_DETECTED,          TidyInfo,        formatStandard          },
281
    { DISCARDING_UNEXPECTED,        0,               formatStandardDynamic   },
282
    { DOCTYPE_AFTER_TAGS,           TidyWarning,     formatStandard          },
283
    { DUPLICATE_FRAMESET,           TidyError,       formatStandard          },
284
    { ELEMENT_NOT_EMPTY,            TidyWarning,     formatStandard          },
285
    { ELEMENT_VERS_MISMATCH_ERROR,  TidyError,       formatStandard          },
286
    { ELEMENT_VERS_MISMATCH_WARN,   TidyWarning,     formatStandard          },
287
    { ENCODING_MISMATCH,            TidyWarning,     formatEncodingReport    },
288
    { ESCAPED_ILLEGAL_URI,          TidyWarning,     formatAttributeReport   },
289
    { FILE_CANT_OPEN,               TidyBadDocument, formatStandard          },
290
    { FILE_CANT_OPEN_CFG,           TidyBadDocument, formatStandard          },
291
    { FILE_NOT_FILE,                TidyBadDocument, formatStandard          },
292
    { FIXED_BACKSLASH,              TidyWarning,     formatAttributeReport   },
293
    { FOUND_STYLE_IN_BODY,          TidyWarning,     formatStandard          },
294
    { ID_NAME_MISMATCH,             TidyWarning,     formatAttributeReport   },
295
    { ILLEGAL_NESTING,              TidyWarning,     formatStandard          },
296
    { ILLEGAL_URI_CODEPOINT,        TidyWarning,     formatAttributeReport   },
297
    { ILLEGAL_URI_REFERENCE,        TidyWarning,     formatAttributeReport   },
298
    { INSERTING_AUTO_ATTRIBUTE,     TidyWarning,     formatAttributeReport   },
299
    { INSERTING_TAG,                TidyWarning,     formatStandard          },
300
    { INVALID_ATTRIBUTE,            TidyWarning,     formatAttributeReport   },
301
    { INVALID_NCR,                  TidyWarning,     formatEncodingReport    },
302
    { INVALID_SGML_CHARS,           TidyWarning,     formatEncodingReport    },
303
    { INVALID_UTF8,                 TidyWarning,     formatEncodingReport    },
304
    { INVALID_UTF16,                TidyWarning,     formatEncodingReport    },
305
    { INVALID_XML_ID,               TidyWarning,     formatAttributeReport   },
306
    { JOINING_ATTRIBUTE,            TidyWarning,     formatAttributeReport   },
307
    { MALFORMED_COMMENT,            TidyInfo,        formatStandard          },
308
    { MALFORMED_COMMENT_EOS,        TidyError,       formatStandard          },
309
    { MALFORMED_COMMENT_DROPPING,   TidyWarning,     formatStandard          },
310
    { MALFORMED_COMMENT_WARN,       TidyWarning,     formatStandard          },
311
    { MALFORMED_DOCTYPE,            TidyWarning,     formatStandard          },
312
    { MISMATCHED_ATTRIBUTE_ERROR,   TidyError,       formatAttributeReport   },
313
    { MISMATCHED_ATTRIBUTE_WARN,    TidyWarning,     formatAttributeReport   },
314
    { MISSING_ATTR_VALUE,           TidyWarning,     formatAttributeReport   },
315
    { MISSING_ATTRIBUTE,            TidyWarning,     formatStandard          },
316
    { MISSING_DOCTYPE,              TidyWarning,     formatStandard          },
317
    { MISSING_ENDTAG_BEFORE,        TidyWarning,     formatStandard          },
318
    { MISSING_ENDTAG_FOR,           TidyWarning,     formatStandard          },
319
    { MISSING_ENDTAG_OPTIONAL,      TidyInfo,        formatStandard          },
320
    { MISSING_IMAGEMAP,             TidyWarning,     formatAttributeReport   },
321
    { MISSING_QUOTEMARK,            TidyWarning,     formatAttributeReport   },
322
    { MISSING_QUOTEMARK_OPEN,       TidyInfo,        formatAttributeReport   },
323
    { MISSING_SEMICOLON_NCR,        TidyWarning,     formatStandard          },
324
    { MISSING_SEMICOLON,            TidyWarning,     formatStandard          },
325
    { MISSING_STARTTAG,             TidyWarning,     formatStandard          },
326
    { MISSING_TITLE_ELEMENT,        TidyWarning,     formatStandard          },
327
    { MOVED_STYLE_TO_HEAD,          TidyWarning,     formatStandard          },
328
    { NESTED_EMPHASIS,              TidyWarning,     formatStandard          },
329
    { NESTED_QUOTATION,             TidyWarning,     formatStandard          },
330
    { NEWLINE_IN_URI,               TidyWarning,     formatAttributeReport   },
331
    { NOFRAMES_CONTENT,             TidyWarning,     formatStandard          },
332
    { NON_MATCHING_ENDTAG,          TidyWarning,     formatStandard          },
333
    { OBSOLETE_ELEMENT,             TidyWarning,     formatStandard          },
334
    { OPTION_REMOVED,               TidyConfig,      formatStandard          },
335
    { OPTION_REMOVED_APPLIED,       TidyConfig,      formatStandard          },
336
    { OPTION_REMOVED_UNAPPLIED,     TidyConfig,      formatStandard          },
337
    { PREVIOUS_LOCATION,            TidyInfo,        formatStandard          },
338
    { PROPRIETARY_ATTR_VALUE,       TidyWarning,     formatAttributeReport   },
339
    { PROPRIETARY_ATTRIBUTE,        TidyWarning,     formatAttributeReport   },
340
    { PROPRIETARY_ELEMENT,          TidyWarning,     formatStandard          },
341
    { REMOVED_HTML5,                TidyWarning,     formatStandard          },
342
    { REPEATED_ATTRIBUTE,           TidyWarning,     formatAttributeReport   },
343
    { REPLACING_ELEMENT,            TidyWarning,     formatStandard          },
344
    { REPLACING_UNEX_ELEMENT,       TidyWarning,     formatStandard          },
345
    { SPACE_PRECEDING_XMLDECL,      TidyWarning,     formatStandard          },
346
    { STRING_ARGUMENT_BAD,          TidyConfig,      formatStandard          },
347
    { STRING_CONTENT_LOOKS,         TidyInfo,        formatStandard          }, /* reportMarkupVersion() */
348
    { STRING_DOCTYPE_GIVEN,         TidyInfo,        formatStandard          }, /* reportMarkupVersion() */
349
    { STRING_MISSING_MALFORMED,     TidyConfig,      formatStandard          },
350
    { STRING_MUTING_TYPE,           TidyInfo,        formatStandard          },
351
    { STRING_NO_SYSID,              TidyInfo,        formatStandard          }, /* reportMarkupVersion() */
352
    { STRING_UNKNOWN_OPTION,        TidyConfig,      formatStandard          },
353
    { SUSPECTED_MISSING_QUOTE,      TidyWarning,     formatStandard          },
354
    { TAG_NOT_ALLOWED_IN,           TidyWarning,     formatStandard, PREVIOUS_LOCATION },
355
    { TOO_MANY_ELEMENTS_IN,         TidyWarning,     formatStandard, PREVIOUS_LOCATION },
356
    { TOO_MANY_ELEMENTS,            TidyWarning,     formatStandard          },
357
    { TRIM_EMPTY_ELEMENT,           TidyWarning,     formatStandard          },
358
    { UNESCAPED_AMPERSAND,          TidyWarning,     formatStandard          },
359
    { UNEXPECTED_END_OF_FILE_ATTR,  TidyWarning,     formatAttributeReport   },
360
    { UNEXPECTED_END_OF_FILE,       TidyWarning,     formatStandard          },
361
    { UNEXPECTED_ENDTAG_IN,         TidyError,       formatStandard          },
362
    { UNEXPECTED_ENDTAG,            TidyWarning,     formatStandard          },
363
    { UNEXPECTED_ENDTAG_ERR,        TidyError,       formatStandard          },
364
    { UNEXPECTED_EQUALSIGN,         TidyWarning,     formatAttributeReport   },
365
    { UNEXPECTED_GT,                TidyWarning,     formatAttributeReport   },
366
    { UNEXPECTED_QUOTEMARK,         TidyWarning,     formatAttributeReport   },
367
    { UNKNOWN_ELEMENT_LOOKS_CUSTOM, TidyError,       formatStandard          },
368
    { UNKNOWN_ELEMENT,              TidyError,       formatStandard          },
369
    { UNKNOWN_ENTITY,               TidyWarning,     formatStandard          },
370
    { USING_BR_INPLACE_OF,          TidyWarning,     formatStandard          },
371
    { VENDOR_SPECIFIC_CHARS,        TidyWarning,     formatEncodingReport    },
372
    { WHITE_IN_URI,                 TidyWarning,     formatAttributeReport   },
373
    { XML_DECLARATION_DETECTED,     TidyWarning,     formatStandard          },
374
    { XML_ID_SYNTAX,                TidyWarning,     formatAttributeReport   },
375
    { BLANK_TITLE_ELEMENT,          TidyWarning,     formatStandard          },
376
377
    { APPLET_MISSING_ALT,                            TidyAccess, formatAccessReport },
378
    { AREA_MISSING_ALT,                              TidyAccess, formatAccessReport },
379
    { ASCII_REQUIRES_DESCRIPTION,                    TidyAccess, formatAccessReport },
380
    { ASSOCIATE_LABELS_EXPLICITLY,                   TidyAccess, formatAccessReport },
381
    { ASSOCIATE_LABELS_EXPLICITLY_FOR,               TidyAccess, formatAccessReport },
382
    { ASSOCIATE_LABELS_EXPLICITLY_ID,                TidyAccess, formatAccessReport },
383
    { AUDIO_MISSING_TEXT_AIFF,                       TidyAccess, formatAccessReport },
384
    { AUDIO_MISSING_TEXT_AU,                         TidyAccess, formatAccessReport },
385
    { AUDIO_MISSING_TEXT_RA,                         TidyAccess, formatAccessReport },
386
    { AUDIO_MISSING_TEXT_RM,                         TidyAccess, formatAccessReport },
387
    { AUDIO_MISSING_TEXT_SND,                        TidyAccess, formatAccessReport },
388
    { AUDIO_MISSING_TEXT_WAV,                        TidyAccess, formatAccessReport },
389
    { COLOR_CONTRAST_ACTIVE_LINK,                    TidyAccess, formatAccessReport },
390
    { COLOR_CONTRAST_LINK,                           TidyAccess, formatAccessReport },
391
    { COLOR_CONTRAST_TEXT,                           TidyAccess, formatAccessReport },
392
    { COLOR_CONTRAST_VISITED_LINK,                   TidyAccess, formatAccessReport },
393
    { DATA_TABLE_MISSING_HEADERS,                    TidyAccess, formatAccessReport },
394
    { DATA_TABLE_MISSING_HEADERS_COLUMN,             TidyAccess, formatAccessReport },
395
    { DATA_TABLE_MISSING_HEADERS_ROW,                TidyAccess, formatAccessReport },
396
    { DATA_TABLE_REQUIRE_MARKUP_COLUMN_HEADERS,      TidyAccess, formatAccessReport },
397
    { DATA_TABLE_REQUIRE_MARKUP_ROW_HEADERS,         TidyAccess, formatAccessReport },
398
    { DOCTYPE_MISSING,                               TidyAccess, formatAccessReport },
399
    { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_APPLET, TidyAccess, formatAccessReport },
400
    { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_EMBED,  TidyAccess, formatAccessReport },
401
    { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_OBJECT, TidyAccess, formatAccessReport },
402
    { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_SCRIPT, TidyAccess, formatAccessReport },
403
    { FRAME_MISSING_LONGDESC,                        TidyAccess, formatAccessReport },
404
    { FRAME_MISSING_NOFRAMES,                        TidyAccess, formatAccessReport },
405
    { FRAME_MISSING_TITLE,                           TidyAccess, formatAccessReport },
406
    { FRAME_SRC_INVALID,                             TidyAccess, formatAccessReport },
407
    { FRAME_TITLE_INVALID_NULL,                      TidyAccess, formatAccessReport },
408
    { FRAME_TITLE_INVALID_SPACES,                    TidyAccess, formatAccessReport },
409
    { HEADER_USED_FORMAT_TEXT,                       TidyAccess, formatAccessReport },
410
    { HEADERS_IMPROPERLY_NESTED,                     TidyAccess, formatAccessReport },
411
    { IMAGE_MAP_SERVER_SIDE_REQUIRES_CONVERSION,     TidyAccess, formatAccessReport },
412
    { IMG_ALT_SUSPICIOUS_FILE_SIZE,                  TidyAccess, formatAccessReport },
413
    { IMG_ALT_SUSPICIOUS_FILENAME,                   TidyAccess, formatAccessReport },
414
    { IMG_ALT_SUSPICIOUS_PLACEHOLDER,                TidyAccess, formatAccessReport },
415
    { IMG_ALT_SUSPICIOUS_TOO_LONG,                   TidyAccess, formatAccessReport },
416
    { IMG_BUTTON_MISSING_ALT,                        TidyAccess, formatAccessReport },
417
    { IMG_MAP_CLIENT_MISSING_TEXT_LINKS,             TidyAccess, formatAccessReport },
418
    { IMG_MAP_SERVER_REQUIRES_TEXT_LINKS,            TidyAccess, formatAccessReport },
419
    { IMG_MISSING_ALT,                               TidyAccess, formatAccessReport },
420
    { IMG_MISSING_DLINK,                             TidyAccess, formatAccessReport },
421
    { IMG_MISSING_LONGDESC,                          TidyAccess, formatAccessReport },
422
    { IMG_MISSING_LONGDESC_DLINK,                    TidyAccess, formatAccessReport },
423
    { INFORMATION_NOT_CONVEYED_APPLET,               TidyAccess, formatAccessReport },
424
    { INFORMATION_NOT_CONVEYED_IMAGE,                TidyAccess, formatAccessReport },
425
    { INFORMATION_NOT_CONVEYED_INPUT,                TidyAccess, formatAccessReport },
426
    { INFORMATION_NOT_CONVEYED_OBJECT,               TidyAccess, formatAccessReport },
427
    { INFORMATION_NOT_CONVEYED_SCRIPT,               TidyAccess, formatAccessReport },
428
    { LANGUAGE_INVALID,                              TidyAccess, formatAccessReport },
429
    { LANGUAGE_NOT_IDENTIFIED,                       TidyAccess, formatAccessReport },
430
    { LAYOUT_TABLE_INVALID_MARKUP,                   TidyAccess, formatAccessReport },
431
    { LAYOUT_TABLES_LINEARIZE_PROPERLY,              TidyAccess, formatAccessReport },
432
    { LINK_TEXT_MISSING,                             TidyAccess, formatAccessReport },
433
    { LINK_TEXT_NOT_MEANINGFUL,                      TidyAccess, formatAccessReport },
434
    { LINK_TEXT_NOT_MEANINGFUL_CLICK_HERE,           TidyAccess, formatAccessReport },
435
    { LINK_TEXT_TOO_LONG,                            TidyAccess, formatAccessReport },
436
    { LIST_USAGE_INVALID_LI,                         TidyAccess, formatAccessReport },
437
    { LIST_USAGE_INVALID_OL,                         TidyAccess, formatAccessReport },
438
    { LIST_USAGE_INVALID_UL,                         TidyAccess, formatAccessReport },
439
    { METADATA_MISSING,                              TidyAccess, formatAccessReport },
440
    { METADATA_MISSING_REDIRECT_AUTOREFRESH,         TidyAccess, formatAccessReport },
441
    { MULTIMEDIA_REQUIRES_TEXT,                      TidyAccess, formatAccessReport },
442
    { NEW_WINDOWS_REQUIRE_WARNING_BLANK,             TidyAccess, formatAccessReport },
443
    { NEW_WINDOWS_REQUIRE_WARNING_NEW,               TidyAccess, formatAccessReport },
444
    { NOFRAMES_INVALID_CONTENT,                      TidyAccess, formatAccessReport },
445
    { NOFRAMES_INVALID_LINK,                         TidyAccess, formatAccessReport },
446
    { NOFRAMES_INVALID_NO_VALUE,                     TidyAccess, formatAccessReport },
447
    { OBJECT_MISSING_ALT,                            TidyAccess, formatAccessReport },
448
    { POTENTIAL_HEADER_BOLD,                         TidyAccess, formatAccessReport },
449
    { POTENTIAL_HEADER_ITALICS,                      TidyAccess, formatAccessReport },
450
    { POTENTIAL_HEADER_UNDERLINE,                    TidyAccess, formatAccessReport },
451
    { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_APPLET,   TidyAccess, formatAccessReport },
452
    { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_EMBED,    TidyAccess, formatAccessReport },
453
    { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_OBJECT,   TidyAccess, formatAccessReport },
454
    { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_SCRIPT,   TidyAccess, formatAccessReport },
455
    { REMOVE_AUTO_REDIRECT,                          TidyAccess, formatAccessReport },
456
    { REMOVE_AUTO_REFRESH,                           TidyAccess, formatAccessReport },
457
    { REMOVE_BLINK_MARQUEE,                          TidyAccess, formatAccessReport },
458
    { REMOVE_FLICKER_ANIMATED_GIF,                   TidyAccess, formatAccessReport },
459
    { REMOVE_FLICKER_APPLET,                         TidyAccess, formatAccessReport },
460
    { REMOVE_FLICKER_EMBED,                          TidyAccess, formatAccessReport },
461
    { REMOVE_FLICKER_OBJECT,                         TidyAccess, formatAccessReport },
462
    { REMOVE_FLICKER_SCRIPT,                         TidyAccess, formatAccessReport },
463
    { REPLACE_DEPRECATED_HTML_APPLET,                TidyAccess, formatAccessReport },
464
    { REPLACE_DEPRECATED_HTML_BASEFONT,              TidyAccess, formatAccessReport },
465
    { REPLACE_DEPRECATED_HTML_CENTER,                TidyAccess, formatAccessReport },
466
    { REPLACE_DEPRECATED_HTML_DIR,                   TidyAccess, formatAccessReport },
467
    { REPLACE_DEPRECATED_HTML_FONT,                  TidyAccess, formatAccessReport },
468
    { REPLACE_DEPRECATED_HTML_ISINDEX,               TidyAccess, formatAccessReport },
469
    { REPLACE_DEPRECATED_HTML_MENU,                  TidyAccess, formatAccessReport },
470
    { REPLACE_DEPRECATED_HTML_S,                     TidyAccess, formatAccessReport },
471
    { REPLACE_DEPRECATED_HTML_STRIKE,                TidyAccess, formatAccessReport },
472
    { REPLACE_DEPRECATED_HTML_U,                     TidyAccess, formatAccessReport },
473
    { SCRIPT_MISSING_NOSCRIPT,                       TidyAccess, formatAccessReport },
474
    { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_CLICK,       TidyAccess, formatAccessReport },
475
    { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_DOWN,  TidyAccess, formatAccessReport },
476
    { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_MOVE,  TidyAccess, formatAccessReport },
477
    { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OUT,   TidyAccess, formatAccessReport },
478
    { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OVER,  TidyAccess, formatAccessReport },
479
    { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_UP,    TidyAccess, formatAccessReport },
480
    { SKIPOVER_ASCII_ART,                            TidyAccess, formatAccessReport },
481
    { STYLE_SHEET_CONTROL_PRESENTATION,              TidyAccess, formatAccessReport },
482
    { STYLESHEETS_REQUIRE_TESTING_LINK,              TidyAccess, formatAccessReport },
483
    { STYLESHEETS_REQUIRE_TESTING_STYLE_ATTR,        TidyAccess, formatAccessReport },
484
    { STYLESHEETS_REQUIRE_TESTING_STYLE_ELEMENT,     TidyAccess, formatAccessReport },
485
    { TABLE_MAY_REQUIRE_HEADER_ABBR,                 TidyAccess, formatAccessReport },
486
    { TABLE_MAY_REQUIRE_HEADER_ABBR_NULL,            TidyAccess, formatAccessReport },
487
    { TABLE_MAY_REQUIRE_HEADER_ABBR_SPACES,          TidyAccess, formatAccessReport },
488
    { TABLE_MISSING_CAPTION,                         TidyAccess, formatAccessReport },
489
    { TABLE_MISSING_SUMMARY,                         TidyAccess, formatAccessReport },
490
    { TABLE_SUMMARY_INVALID_NULL,                    TidyAccess, formatAccessReport },
491
    { TABLE_SUMMARY_INVALID_PLACEHOLDER,             TidyAccess, formatAccessReport },
492
    { TABLE_SUMMARY_INVALID_SPACES,                  TidyAccess, formatAccessReport },
493
    { TEXT_EQUIVALENTS_REQUIRE_UPDATING_APPLET,      TidyAccess, formatAccessReport },
494
    { TEXT_EQUIVALENTS_REQUIRE_UPDATING_OBJECT,      TidyAccess, formatAccessReport },
495
    { TEXT_EQUIVALENTS_REQUIRE_UPDATING_SCRIPT,      TidyAccess, formatAccessReport },
496
497
    { 0, 0, NULL }
498
};
499
500
501
/*********************************************************************
502
 * Message Formatting
503
 * These individual message formatters populate messages with the
504
 * correct, pertinent data.
505
 *********************************************************************/
506
507
508
/* Provides formatting for the Attribute-related reports. This formatter
509
** should be reserved for messages generated by Tidy's accessibility module,
510
** even if the signature matches some unrelated report that you wish to
511
** generate.
512
*/
513
TidyMessageImpl *formatAccessReport(TidyDocImpl* doc, Node *element, Node *node, uint code, uint level, va_list args)
514
0
{
515
0
    doc->badAccess |= BA_WAI;
516
517
    /* Currently *all* cases are handled in the default, but maintain this
518
       structure for possible future cases. */
519
0
    switch (code)
520
0
    {
521
0
        default:
522
0
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level );
523
0
    }
524
525
0
    return NULL;
526
0
}
527
528
/* Provides formatting for the Attribute-related reports. This formatter
529
** provides local variables that are used principally in the formats used for
530
** the attribute related reports.
531
*/
532
TidyMessageImpl *formatAttributeReport(TidyDocImpl* doc, Node *element, Node *node, uint code, uint level, va_list args)
533
698k
{
534
698k
    AttVal *av = NULL;
535
698k
    char const *name = "NULL";
536
698k
    char const *value = "NULL";
537
698k
    char tagdesc[64];
538
539
698k
    TagToString(node, tagdesc, sizeof(tagdesc));
540
541
698k
    if ( ( av = va_arg(args, AttVal*) ) )
542
435k
    {
543
435k
        if (av->attribute)
544
399k
            name = av->attribute;
545
435k
        if (av->value)
546
241k
            value = av->value;
547
435k
    }
548
549
698k
    switch (code)
550
698k
    {
551
43.3k
        case MISSING_QUOTEMARK_OPEN:
552
43.3k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, name );
553
    
554
540
        case BACKSLASH_IN_URI:
555
32.6k
        case ESCAPED_ILLEGAL_URI:
556
32.9k
        case FIXED_BACKSLASH:
557
33.5k
        case ID_NAME_MISMATCH:
558
64.6k
        case ILLEGAL_URI_CODEPOINT:
559
64.6k
        case ILLEGAL_URI_REFERENCE:
560
65.3k
        case INVALID_XML_ID:
561
65.5k
        case MISSING_IMAGEMAP:
562
66.4k
        case MISSING_QUOTEMARK:
563
67.2k
        case NEWLINE_IN_URI:
564
67.6k
        case UNEXPECTED_EQUALSIGN:
565
316k
        case UNEXPECTED_GT:
566
321k
        case UNEXPECTED_QUOTEMARK:
567
327k
        case WHITE_IN_URI:
568
327k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc );
569
570
290
        case ATTRIBUTE_IS_NOT_ALLOWED:
571
1.45k
        case JOINING_ATTRIBUTE:
572
112k
        case MISSING_ATTR_VALUE:
573
229k
        case PROPRIETARY_ATTRIBUTE:
574
229k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, name );
575
576
14
        case ATTRIBUTE_VALUE_REPLACED:
577
41.7k
        case BAD_ATTRIBUTE_VALUE:
578
42.1k
        case BAD_ATTRIBUTE_VALUE_REPLACED:
579
42.1k
        case INSERTING_AUTO_ATTRIBUTE:
580
45.0k
        case INVALID_ATTRIBUTE:
581
45.0k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, name, value );
582
583
0
        case MISMATCHED_ATTRIBUTE_ERROR:
584
6.70k
        case MISMATCHED_ATTRIBUTE_WARN:
585
6.70k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, name, HTMLVersion(doc));
586
587
3.39k
        case ANCHOR_NOT_UNIQUE:
588
37.1k
        case ANCHOR_DUPLICATED:
589
38.7k
        case ATTR_VALUE_NOT_LCASE:
590
38.9k
        case PROPRIETARY_ATTR_VALUE:
591
38.9k
        case XML_ID_SYNTAX:
592
38.9k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, value );
593
594
5.66k
        case REPEATED_ATTRIBUTE:
595
5.66k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, value, name );
596
597
2.17k
        case UNEXPECTED_END_OF_FILE_ATTR:
598
            /* on end of file adjust reported position to end of input */
599
2.17k
            doc->lexer->lines   = doc->docIn->curline;
600
2.17k
            doc->lexer->columns = doc->docIn->curcol;
601
2.17k
            return TY_(tidyMessageCreateWithLexer)(doc, code, level, tagdesc );
602
698k
    }
603
604
0
    return NULL;
605
698k
}
606
607
608
/* Provides report formatting *and* additional status settings for Tidy's
609
** encoding reports. Provides the local variables typically used for this type
610
** of report.
611
** @todo: These status changes probably SHOULD be made in the calling code;
612
**   however these states are captured to generate future output, which may be
613
**   useful here in the long run.
614
*/
615
TidyMessageImpl *formatEncodingReport(TidyDocImpl* doc, Node *element, Node *node, uint code, uint level, va_list args)
616
953k
{
617
953k
    char buf[ 32 ] = {'\0'};
618
953k
    uint c = va_arg( args, uint );
619
953k
    Bool discarded = va_arg( args, Bool );
620
953k
    ctmbstr action = tidyLocalizedString(discarded ? STRING_DISCARDING : STRING_REPLACING);
621
622
953k
    switch (code)
623
953k
    {
624
1.35k
        case INVALID_NCR:
625
1.35k
            NtoS(c, buf);
626
1.35k
            doc->badChars |= BC_INVALID_NCR;
627
1.35k
            break;
628
629
6
        case INVALID_SGML_CHARS:
630
6
            NtoS(c, buf);
631
6
            doc->badChars |= BC_INVALID_SGML_CHARS;
632
6
            break;
633
634
951k
        case INVALID_UTF8:
635
951k
            TY_(tmbsnprintf)(buf, sizeof(buf), "U+%04X", c);
636
951k
            doc->badChars |= BC_INVALID_UTF8;
637
951k
            break;
638
639
733
        case INVALID_UTF16:
640
733
            TY_(tmbsnprintf)(buf, sizeof(buf), "U+%04X", c);
641
733
            doc->badChars |= BC_INVALID_UTF16;
642
733
            break;
643
644
0
        case VENDOR_SPECIFIC_CHARS:
645
0
            NtoS(c, buf);
646
0
            doc->badChars |= BC_VENDOR_SPECIFIC_CHARS;
647
0
            break;
648
649
156
        case ENCODING_MISMATCH:
650
156
            doc->badChars |= BC_ENCODING_MISMATCH;
651
156
            return TY_(tidyMessageCreateWithLexer)(doc,
652
156
                                                   code,
653
156
                                                   level,
654
156
                                                   TY_(CharEncodingName)(doc->docIn->encoding),
655
156
                                                   TY_(CharEncodingName)(c));
656
0
            break;
657
953k
    }
658
659
953k
    return TY_(tidyMessageCreateWithLexer)(doc, code, level, action, buf );
660
661
953k
}
662
663
664
/* Provides general formatting for the majority of Tidy's reports. Because most
665
** reports use the same basic data derived from the element and node, this
666
** formatter covers the vast majority of Tidy's report messages. Note that this
667
** formatter guarantees the values of TidyReportLevel in the dispatchTable[].
668
** Some of the cases in this formatter start new contexts from the va_list
669
** when the required data is simple. For complex local variable needs, it may
670
** be preferred to write a new formatter.
671
*/
672
TidyMessageImpl *formatStandard(TidyDocImpl* doc, Node *element, Node *node, uint code, uint level, va_list args)
673
5.24M
{
674
5.24M
    char nodedesc[ 256 ] = {0};
675
5.24M
    char elemdesc[ 256 ] = {0};
676
5.24M
    Node* rpt = ( element ? element : node );
677
678
5.24M
    TagToString(node, nodedesc, sizeof(nodedesc));
679
680
5.24M
    if ( element )
681
4.95M
        TagToString(element, elemdesc, sizeof(elemdesc));
682
683
5.24M
    switch ( code )
684
5.24M
    {
685
0
        case CUSTOM_TAG_DETECTED:
686
0
        {
687
0
            ctmbstr tagtype;
688
0
            switch ( cfg( doc, TidyUseCustomTags ) )
689
0
            {
690
0
                case TidyCustomBlocklevel:
691
0
                    tagtype = tidyLocalizedString( TIDYCUSTOMBLOCKLEVEL_STRING );
692
0
                    break;
693
0
                case TidyCustomEmpty:
694
0
                    tagtype = tidyLocalizedString( TIDYCUSTOMEMPTY_STRING );
695
0
                    break;
696
0
                case TidyCustomInline:
697
0
                    tagtype = tidyLocalizedString( TIDYCUSTOMINLINE_STRING );
698
0
                    break;
699
0
                case TidyCustomPre:
700
0
                default:
701
0
                    tagtype = tidyLocalizedString( TIDYCUSTOMPRE_STRING );
702
0
                    break;
703
0
            }
704
0
            return TY_(tidyMessageCreateWithNode)(doc, element, code, level, elemdesc, tagtype );
705
0
        }
706
707
0
        case STRING_NO_SYSID:
708
0
            return TY_(tidyMessageCreate)( doc, code, level );
709
            
710
0
        case FILE_CANT_OPEN:
711
0
        case FILE_CANT_OPEN_CFG:
712
0
        case FILE_NOT_FILE:
713
20.4k
        case STRING_CONTENT_LOOKS:
714
20.5k
        case STRING_DOCTYPE_GIVEN:
715
20.5k
        case STRING_MISSING_MALFORMED:
716
20.5k
        case STRING_MUTING_TYPE:
717
20.5k
        {
718
20.5k
            ctmbstr str;
719
20.5k
            if ( (str = va_arg( args, ctmbstr)) )
720
20.5k
                return TY_(tidyMessageCreate)( doc, code, level, str );
721
722
20.5k
        } break;
723
724
0
        case APOS_UNDEFINED:
725
668
        case MISSING_SEMICOLON_NCR:
726
15.4k
        case MISSING_SEMICOLON:
727
30.3k
        case UNESCAPED_AMPERSAND:
728
55.0k
        case UNKNOWN_ENTITY:
729
55.0k
        {
730
55.0k
            ctmbstr entityname;
731
55.0k
            if ( !(entityname = va_arg( args, ctmbstr)) )
732
0
            {
733
0
                entityname = "NULL";
734
0
            }
735
55.0k
            return TY_(tidyMessageCreateWithLexer)(doc, code, level, entityname);
736
30.3k
        }
737
738
9.36k
        case MISSING_ATTRIBUTE:
739
9.36k
        {
740
9.36k
            ctmbstr name;
741
9.36k
            if ( (name = va_arg( args, ctmbstr)) )
742
9.36k
                return TY_(tidyMessageCreateWithNode)(doc, node, code, level, nodedesc, name );
743
9.36k
        } break;
744
745
0
        case STRING_UNKNOWN_OPTION:
746
0
        case OPTION_REMOVED:
747
0
        {
748
0
            ctmbstr str;
749
0
            if ( (str = va_arg( args, ctmbstr)) )
750
0
                return TY_(tidyMessageCreateWithLexer)(doc, code, level, str);
751
0
        } break;
752
753
0
        case OPTION_REMOVED_UNAPPLIED:
754
0
        case STRING_ARGUMENT_BAD:
755
0
        {
756
0
            ctmbstr s1 = va_arg( args, ctmbstr );
757
0
            ctmbstr s2 = va_arg( args, ctmbstr );
758
0
            return TY_(tidyMessageCreateWithLexer)(doc, code, level, s1, s2);
759
0
        }
760
761
0
        case OPTION_REMOVED_APPLIED:
762
0
        {
763
0
            ctmbstr s1 = va_arg( args, ctmbstr );
764
0
            ctmbstr s2 = va_arg( args, ctmbstr );
765
0
            ctmbstr s3 = va_arg( args, ctmbstr );
766
0
            return TY_(tidyMessageCreateWithLexer)(doc, code, level, s1, s2, s3);
767
0
        }
768
769
770
1.57k
        case BAD_SURROGATE_LEAD:
771
1.76k
        case BAD_SURROGATE_PAIR:
772
10.8k
        case BAD_SURROGATE_TAIL:
773
10.8k
        {
774
10.8k
            uint c1 = va_arg( args, uint );
775
10.8k
            uint c2 = va_arg( args, uint );
776
10.8k
            return TY_(tidyMessageCreateWithLexer)(doc, code, level, c1, c2);
777
1.76k
        }
778
779
46
        case SPACE_PRECEDING_XMLDECL:
780
            /* @TODO: Should this be a TidyInfo "silent" fix? */
781
46
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level );
782
783
17.4k
        case CANT_BE_NESTED:
784
18.2k
        case NOFRAMES_CONTENT:
785
22.4k
        case USING_BR_INPLACE_OF:
786
            /* Can we use `rpt` here? No; `element` has a value in every case. */
787
22.4k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, nodedesc );
788
789
0
        case ELEMENT_VERS_MISMATCH_ERROR:
790
0
        case ELEMENT_VERS_MISMATCH_WARN:
791
0
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, nodedesc, HTMLVersion(doc) );
792
793
63.9k
        case TAG_NOT_ALLOWED_IN:
794
            /* Can we use `rpt` here? No; `element` has a value in every case. */
795
63.9k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, nodedesc, element ? element->element : NULL );
796
797
1.35M
        case INSERTING_TAG:
798
1.37M
        case MISSING_STARTTAG:
799
1.37M
        case TOO_MANY_ELEMENTS:
800
1.37M
        case UNEXPECTED_ENDTAG:
801
1.37M
        case UNEXPECTED_ENDTAG_ERR:  /* generated by XML docs */
802
            /* Can we use `rpt` here? No; `element` has a value in every case. */
803
1.37M
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, node->element );
804
805
0
        case UNEXPECTED_ENDTAG_IN:
806
            /* Can we use `rpt` here? No; `element` has a value in every case. */
807
0
            return TY_(tidyMessageCreateWithNode)(doc, node, code, level, node->element, element ? element->element : NULL );
808
809
3.52k
        case BAD_CDATA_CONTENT:
810
9.42k
        case CONTENT_AFTER_BODY:
811
12.3k
        case DOCTYPE_AFTER_TAGS:
812
13.6k
        case DUPLICATE_FRAMESET:
813
22.1k
        case MALFORMED_COMMENT:
814
26.2k
        case MALFORMED_COMMENT_DROPPING:
815
26.3k
        case MALFORMED_COMMENT_EOS:
816
26.3k
        case MALFORMED_COMMENT_WARN:
817
73.0k
        case MALFORMED_DOCTYPE:
818
89.9k
        case MISSING_DOCTYPE:
819
110k
        case MISSING_TITLE_ELEMENT:
820
137k
        case NESTED_QUOTATION:
821
138k
        case SUSPECTED_MISSING_QUOTE:
822
138k
        case XML_DECLARATION_DETECTED:
823
138k
        case BLANK_TITLE_ELEMENT:
824
138k
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level );
825
826
0
        case ELEMENT_NOT_EMPTY:
827
0
        case FOUND_STYLE_IN_BODY:
828
3.50k
        case ILLEGAL_NESTING:
829
4.92k
        case MOVED_STYLE_TO_HEAD:
830
412k
        case TRIM_EMPTY_ELEMENT:
831
412k
        case UNEXPECTED_END_OF_FILE:
832
412k
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, elemdesc );
833
834
2.38k
        case OBSOLETE_ELEMENT:
835
9.51k
        case REPLACING_ELEMENT:
836
9.51k
        case REPLACING_UNEX_ELEMENT:
837
9.51k
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, elemdesc, nodedesc );
838
839
0
        case ADDED_MISSING_CHARSET:
840
195
        case BAD_SUMMARY_HTML5:
841
8.32k
        case NESTED_EMPHASIS:
842
10.5k
        case PROPRIETARY_ELEMENT:
843
1.19M
        case REMOVED_HTML5:
844
1.30M
        case UNKNOWN_ELEMENT:
845
1.30M
        case UNKNOWN_ELEMENT_LOOKS_CUSTOM:
846
1.30M
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, nodedesc );
847
848
1.21M
        case MISSING_ENDTAG_FOR:
849
1.22M
        case MISSING_ENDTAG_OPTIONAL:
850
1.28M
        case PREVIOUS_LOCATION:
851
1.28M
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, element? element->element : NULL );
852
853
520k
        case MISSING_ENDTAG_BEFORE:
854
520k
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, element? element->element : NULL, nodedesc );
855
856
8.27k
        case COERCE_TO_ENDTAG:
857
12.5k
        case NON_MATCHING_ENDTAG:
858
12.5k
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, node->element, node->element );
859
2.55k
        case TOO_MANY_ELEMENTS_IN:
860
2.55k
            return TY_(tidyMessageCreateWithNode)(doc, rpt, code, level, node->element, element ? element->element : NULL);
861
862
5.24M
    }
863
864
0
    return NULL;
865
5.24M
}
866
867
868
/* Provides general formatting as formatStandard, except TidyReportLevel is set
869
** dynamically for these items as it cannot be predicted except at runtime.
870
 */
871
TidyMessageImpl *formatStandardDynamic(TidyDocImpl* doc, Node *element, Node *node, uint code, uint level, va_list args)
872
190k
{
873
190k
    char nodedesc[ 256 ] = {0};
874
875
190k
    TagToString(node, nodedesc, sizeof(nodedesc));
876
877
190k
    switch (code)
878
190k
    {
879
190k
        case DISCARDING_UNEXPECTED:
880
            /* Force error if in a bad form, or Issue #166 - repeated <main> element. */
881
            /* Can we use `rpt` here? No; `element` has a value in every case. */
882
190k
            return TY_(tidyMessageCreateWithNode)(doc, node, code, doc->badForm ? TidyError : TidyWarning, nodedesc );
883
0
            break;
884
190k
    }
885
886
0
    return NULL;
887
190k
}
888
889
890
/*********************************************************************
891
 * High Level Message Writing Functions
892
 * When adding new reports to LibTidy, preference should be given
893
 * to one of the existing, general purpose message writing functions
894
 * above, if possible, otherwise try to use one of these, or as a
895
 * last resort add a new one in this section.
896
 *********************************************************************/
897
898
899
/* This function performs the heavy lifting for TY_(Report)(). Critically we
900
** can accept the va_list needed for recursion.
901
*/
902
static void vReport(TidyDocImpl* doc, Node *element, Node *node, uint code, va_list args)
903
7.08M
{
904
7.08M
    int i = 0;
905
7.08M
    va_list args_copy;
906
907
418M
    while ( dispatchTable[i].code != 0 )
908
418M
    {
909
418M
        if ( dispatchTable[i].code == code )
910
7.08M
        {
911
7.08M
            TidyMessageImpl *message;
912
7.08M
            messageFormatter *handler = dispatchTable[i].handler;
913
7.08M
            TidyReportLevel level = dispatchTable[i].level;
914
915
7.08M
            va_copy(args_copy, args);
916
7.08M
            message = handler( doc, element, node, code, level, args_copy );
917
7.08M
            va_end(args_copy);
918
919
7.08M
            messageOut( message );
920
921
7.08M
            if ( dispatchTable[i].next )
922
66.5k
            {
923
66.5k
                va_copy(args_copy, args);
924
66.5k
                vReport(doc, element, node, dispatchTable[i].next, args_copy);
925
66.5k
                va_end(args_copy);
926
66.5k
            }
927
7.08M
            break;
928
7.08M
        }
929
411M
        i++;
930
411M
    }
931
7.08M
}
932
933
934
/* This single Report output function uses the correct formatter with all
935
** possible, relevant data that can be reported. The only real drawbacks are
936
** having to pass NULL when some of the values aren't used, and the lack of
937
** type safety by using the variable arguments. To counter this some convenience
938
** report output functions exist, too. Any new reports you wish to create must
939
** be able to use this function signature, although convenience functions should
940
** be added to abstract the full function signature and to preserve type safety.
941
*/
942
void TY_(Report)(TidyDocImpl* doc, Node *element, Node *node, uint code, ...)
943
7.01M
{
944
7.01M
    va_list args;
945
7.01M
    va_start(args, code);
946
7.01M
    vReport(doc, element, node, code, args);
947
7.01M
    va_end(args);
948
7.01M
}
949
950
951
/*********************************************************************
952
 * Convenience Reporting Functions
953
 * Functions that don't require the full signature of TY_(Report),
954
 * and help protect type safety by avoiding variable arguments in the
955
 * rest of Tidy's code.
956
 *********************************************************************/
957
958
void TY_(ReportAccessError)( TidyDocImpl* doc, Node* node, uint code )
959
0
{
960
0
    TY_(Report)( doc, NULL, node, code );
961
0
}
962
963
964
void TY_(ReportAttrError)(TidyDocImpl* doc, Node *node, AttVal *av, uint code)
965
698k
{
966
698k
    TY_(Report)( doc, NULL, node, code, av );
967
698k
}
968
969
970
void TY_(ReportBadArgument)( TidyDocImpl* doc, ctmbstr option )
971
0
{
972
0
    assert( option != NULL );
973
0
    TY_(Report)( doc, NULL, NULL, STRING_MISSING_MALFORMED, option );
974
0
}
975
976
977
void TY_(ReportEntityError)( TidyDocImpl* doc, uint code, ctmbstr entity, int ARG_UNUSED(c) )
978
55.0k
{
979
    /* Note that the report formatter currently doesn't use argument c */
980
55.0k
    TY_(Report)( doc, NULL, NULL, code, entity, c );
981
55.0k
}
982
983
984
void TY_(ReportFileError)( TidyDocImpl* doc, ctmbstr file, uint code )
985
0
{
986
0
    TY_(Report)( doc, NULL, NULL, code, file );
987
0
}
988
989
990
void TY_(ReportEncodingError)(TidyDocImpl* doc, uint code, uint c, Bool discarded)
991
953k
{
992
953k
    TY_(Report)( doc, NULL, NULL, code, c, discarded );
993
953k
}
994
995
void TY_(ReportEncodingWarning)(TidyDocImpl* doc, uint code, uint encoding)
996
156
{
997
    /* va_list in formatter expects trailing `no` argument */
998
156
    TY_(Report)( doc, NULL, NULL, code, encoding, no );
999
156
}
1000
1001
1002
void TY_(ReportMissingAttr)( TidyDocImpl* doc, Node* node, ctmbstr name )
1003
9.36k
{
1004
9.36k
    TY_(Report)( doc, NULL, node, MISSING_ATTRIBUTE, name );
1005
9.36k
}
1006
1007
1008
void TY_(ReportSurrogateError)(TidyDocImpl* doc, uint code, uint c1, uint c2)
1009
10.8k
{
1010
10.8k
    TY_(Report)( doc, NULL, NULL, code, c1,c2 );
1011
10.8k
}
1012
1013
1014
void TY_(ReportUnknownOption)( TidyDocImpl* doc, ctmbstr option )
1015
0
{
1016
    /* lexer is not defined when this is called */
1017
0
    TY_(Report)( doc, NULL, NULL, STRING_UNKNOWN_OPTION, option );
1018
0
}
1019
1020
1021
/*********************************************************************
1022
 * Dialogue Output Functions
1023
 * As for issuing reports, Tidy manages all dialogue output from a
1024
 * single source in order to manage message categories in a simple
1025
 * an consistent manner.
1026
 *********************************************************************/
1027
1028
1029
/* This structure ties together for each dialogue Code the default
1030
** TidyReportLevel. This it makes it simple to output new dialogue
1031
** messages, or to change report level by modifying this array.
1032
*/
1033
static struct _dialogueDispatchTable {
1034
    uint code;                 /**< The message code. */
1035
    TidyReportLevel level;     /**< The default TidyReportLevel of the message. */
1036
} dialogueDispatchTable[] = {
1037
    { STRING_HELLO_ACCESS,         TidyDialogueInfo     }, /* AccessibilityChecks() */
1038
    { TEXT_GENERAL_INFO,           TidyDialogueInfo     }, /* tidyGeneralInfo() */
1039
    { TEXT_GENERAL_INFO_PLEA,      TidyDialogueInfo     }, /* tidyGeneralInfo() */
1040
    
1041
    { STRING_NEEDS_INTERVENTION,   TidyDialogueSummary  }, /* tidyDocRunDiagnostics() */
1042
    { STRING_ERROR_COUNT,          TidyDialogueSummary  }, /* ReportNumWarnings() */
1043
    { STRING_NO_ERRORS,            TidyDialogueSummary  }, /* ReportNumWarnings() */
1044
    { STRING_NOT_ALL_SHOWN,        TidyDialogueSummary  }, /* ReportNumWarnings() */
1045
    
1046
    { FOOTNOTE_TRIM_EMPTY_ELEMENT, TidyDialogueFootnote },
1047
    { TEXT_ACCESS_ADVICE1,         TidyDialogueFootnote }, /* errorSummary() */
1048
    { TEXT_ACCESS_ADVICE2,         TidyDialogueFootnote },
1049
    { TEXT_BAD_FORM,               TidyDialogueFootnote },
1050
    { TEXT_BAD_MAIN,               TidyDialogueFootnote },
1051
    { TEXT_HTML_T_ALGORITHM,       TidyDialogueFootnote },
1052
    { TEXT_INVALID_URI,            TidyDialogueFootnote },
1053
    { TEXT_INVALID_UTF8,           TidyDialogueFootnote },
1054
    { TEXT_INVALID_UTF16,          TidyDialogueFootnote },
1055
    { TEXT_M_IMAGE_ALT,            TidyDialogueFootnote },
1056
    { TEXT_M_IMAGE_MAP,            TidyDialogueFootnote },
1057
    { TEXT_M_LINK_ALT,             TidyDialogueFootnote },
1058
    { TEXT_M_SUMMARY,              TidyDialogueFootnote },
1059
    { TEXT_SGML_CHARS,             TidyDialogueFootnote },
1060
    { TEXT_USING_BODY,             TidyDialogueFootnote },
1061
    { TEXT_USING_FONT,             TidyDialogueFootnote },
1062
    { TEXT_USING_FRAMES,           TidyDialogueFootnote },
1063
    { TEXT_USING_LAYER,            TidyDialogueFootnote },
1064
    { TEXT_USING_NOBR,             TidyDialogueFootnote },
1065
    { TEXT_USING_SPACER,           TidyDialogueFootnote },
1066
    { TEXT_VENDOR_CHARS,           TidyDialogueFootnote },
1067
    
1068
    { 0, 0 }
1069
};
1070
1071
1072
/* This message formatter for dialogue messages should be capable of formatting
1073
** every message, because they're not all that complex and there aren't that
1074
** many.
1075
*/
1076
static TidyMessageImpl *formatDialogue( TidyDocImpl* doc, uint code, TidyReportLevel level, va_list args )
1077
25.9k
{
1078
25.9k
    switch (code)
1079
25.9k
    {
1080
0
        case TEXT_SGML_CHARS:
1081
0
        case TEXT_VENDOR_CHARS:
1082
0
        {
1083
0
            ctmbstr str = va_arg(args, ctmbstr);
1084
0
            return TY_(tidyMessageCreate)( doc, code, level, str );
1085
0
        }
1086
            
1087
19.0k
        case STRING_ERROR_COUNT:
1088
20.4k
        case STRING_NOT_ALL_SHOWN:
1089
20.4k
            return TY_(tidyMessageCreate)( doc, code, level,
1090
20.4k
                                           doc->warnings, "STRING_ERROR_COUNT_WARNING",
1091
20.4k
                                           doc->errors, "STRING_ERROR_COUNT_ERROR" );
1092
1093
0
        case FOOTNOTE_TRIM_EMPTY_ELEMENT:
1094
0
        case STRING_HELLO_ACCESS:
1095
5.53k
        case STRING_NEEDS_INTERVENTION:
1096
5.53k
        case STRING_NO_ERRORS:
1097
5.53k
        case TEXT_ACCESS_ADVICE1:
1098
5.53k
        case TEXT_ACCESS_ADVICE2:
1099
5.53k
        case TEXT_BAD_FORM:
1100
5.53k
        case TEXT_BAD_MAIN:
1101
5.53k
        case TEXT_GENERAL_INFO:
1102
5.53k
        case TEXT_GENERAL_INFO_PLEA:
1103
5.53k
        case TEXT_HTML_T_ALGORITHM:
1104
5.53k
        case TEXT_INVALID_URI:
1105
5.53k
        case TEXT_INVALID_UTF8:
1106
5.53k
        case TEXT_INVALID_UTF16:
1107
5.53k
        case TEXT_M_IMAGE_ALT:
1108
5.53k
        case TEXT_M_IMAGE_MAP:
1109
5.53k
        case TEXT_M_LINK_ALT:
1110
5.53k
        case TEXT_M_SUMMARY:
1111
5.53k
        case TEXT_USING_BODY:
1112
5.53k
        case TEXT_USING_FONT:
1113
5.53k
        case TEXT_USING_FRAMES:
1114
5.53k
        case TEXT_USING_LAYER:
1115
5.53k
        case TEXT_USING_NOBR:
1116
5.53k
        case TEXT_USING_SPACER:
1117
5.53k
        default:
1118
5.53k
            return TY_(tidyMessageCreate)( doc, code, level );
1119
25.9k
    }
1120
    
1121
0
    return NULL;
1122
25.9k
}
1123
1124
1125
/* This single Dialogue output function determines the correct message level
1126
** and formats the message with the appropriate formatter, and then outputs it.
1127
** This one dialogue function should be sufficient for every use case.
1128
*/
1129
void TY_(Dialogue)(TidyDocImpl* doc, uint code, ...)
1130
25.9k
{
1131
25.9k
    int i = 0;
1132
25.9k
    va_list args;
1133
1134
127k
    while ( dialogueDispatchTable[i].code != 0 )
1135
127k
    {
1136
127k
        if ( dialogueDispatchTable[i].code == code )
1137
25.9k
        {
1138
25.9k
            TidyMessageImpl *message;
1139
25.9k
            TidyReportLevel level = dialogueDispatchTable[i].level;
1140
25.9k
            va_start(args, code);
1141
25.9k
            message = formatDialogue( doc, code, level, args );
1142
25.9k
            va_end(args);
1143
25.9k
            messageOut( message );
1144
25.9k
            break;
1145
25.9k
        }
1146
101k
        i++;
1147
101k
    }
1148
25.9k
}
1149
1150
1151
/*********************************************************************
1152
 * Output Dialogue Information
1153
 * In addition to reports that are added to the table, Tidy emits
1154
 * various dialogue type information. Most of these are specific to
1155
 * exact circumstances, although `TY_(Dialogue)` should be used
1156
 * instead of adding a new function, if possible.
1157
 *********************************************************************/
1158
1159
1160
/* Outputs the footnotes and other dialogue information after document cleanup
1161
** is complete. LibTidy users might consider capturing these individually in
1162
** the message callback rather than capturing this entire buffer.
1163
** Called by tidyErrorSummary(), in console.
1164
** @todo: This name is a bit misleading and should probably be renamed to
1165
** indicate its focus on printing footnotes.
1166
*/
1167
void TY_(ErrorSummary)( TidyDocImpl* doc )
1168
0
{
1169
0
    ctmbstr encnam = tidyLocalizedString(STRING_SPECIFIED);
1170
0
    int charenc = cfg( doc, TidyCharEncoding ); 
1171
0
    if ( charenc == WIN1252 ) 
1172
0
        encnam = "Windows-1252";
1173
0
    else if ( charenc == MACROMAN )
1174
0
        encnam = "MacRoman";
1175
0
    else if ( charenc == IBM858 )
1176
0
        encnam = "ibm858";
1177
0
    else if ( charenc == LATIN0 )
1178
0
        encnam = "latin0";
1179
1180
    /* adjust badAccess to that it is 0 if frames are ok */
1181
0
    if ( doc->badAccess & (BA_USING_FRAMES | BA_USING_NOFRAMES) )
1182
0
    {
1183
0
        if (!((doc->badAccess & BA_USING_FRAMES) && !(doc->badAccess & BA_USING_NOFRAMES)))
1184
0
        {
1185
0
            doc->badAccess &= ~(BA_USING_FRAMES | BA_USING_NOFRAMES);
1186
0
        }
1187
0
    }
1188
1189
0
    if (doc->badChars)
1190
0
    {
1191
0
        if (doc->badChars & BC_VENDOR_SPECIFIC_CHARS)
1192
0
            TY_(Dialogue)( doc, TEXT_VENDOR_CHARS, encnam );
1193
1194
0
        if ((doc->badChars & BC_INVALID_SGML_CHARS) || (doc->badChars & BC_INVALID_NCR))
1195
0
            TY_(Dialogue)( doc, TEXT_SGML_CHARS, encnam );
1196
1197
0
        if (doc->badChars & BC_INVALID_UTF8)
1198
0
            TY_(Dialogue)( doc, TEXT_INVALID_UTF8 );
1199
1200
0
        if (doc->badChars & BC_INVALID_UTF16)
1201
0
            TY_(Dialogue)( doc, TEXT_INVALID_UTF16 );
1202
1203
0
        if (doc->badChars & BC_INVALID_URI)
1204
0
            TY_(Dialogue)( doc, TEXT_INVALID_URI );
1205
0
    }
1206
    
1207
0
    if (doc->badForm)
1208
0
    {
1209
0
        if (doc->badForm & flg_BadForm) /* Issue #166 - changed to BIT flag to support other errors */
1210
0
            TY_(Dialogue)( doc, TEXT_BAD_FORM );
1211
1212
0
        if (doc->badForm & flg_BadMain) /* Issue #166 - repeated <main> element */
1213
0
            TY_(Dialogue)( doc, TEXT_BAD_MAIN );
1214
0
    }
1215
1216
0
    if (doc->badAccess)
1217
0
    {
1218
        /* Tidy "classic" accessibility tests */
1219
0
        if ( cfg(doc, TidyAccessibilityCheckLevel) == 0 )
1220
0
        {
1221
0
            if (doc->badAccess & BA_MISSING_SUMMARY)
1222
0
                TY_(Dialogue)( doc, TEXT_M_SUMMARY );
1223
1224
0
            if (doc->badAccess & BA_MISSING_IMAGE_ALT)
1225
0
                TY_(Dialogue)( doc, TEXT_M_IMAGE_ALT );
1226
1227
0
            if (doc->badAccess & BA_MISSING_IMAGE_MAP)
1228
0
                TY_(Dialogue)( doc, TEXT_M_IMAGE_MAP );
1229
1230
0
            if (doc->badAccess & BA_MISSING_LINK_ALT)
1231
0
                TY_(Dialogue)( doc, TEXT_M_LINK_ALT );
1232
1233
0
            if ((doc->badAccess & BA_USING_FRAMES) && !(doc->badAccess & BA_USING_NOFRAMES))
1234
0
                TY_(Dialogue)( doc, TEXT_USING_FRAMES );
1235
0
        }
1236
1237
0
        if ( cfg(doc, TidyAccessibilityCheckLevel) > 0 )
1238
0
            TY_(Dialogue)( doc, TEXT_ACCESS_ADVICE2 );
1239
0
        else
1240
0
            TY_(Dialogue)( doc, TEXT_ACCESS_ADVICE1 );
1241
0
    }
1242
1243
0
    if (doc->badLayout)
1244
0
    {
1245
0
        if (doc->badLayout & USING_LAYER)
1246
0
            TY_(Dialogue)( doc, TEXT_USING_LAYER );
1247
1248
0
        if (doc->badLayout & USING_SPACER)
1249
0
            TY_(Dialogue)( doc, TEXT_USING_SPACER );
1250
1251
0
        if (doc->badLayout & USING_FONT)
1252
0
            TY_(Dialogue)( doc, TEXT_USING_FONT );
1253
1254
0
        if (doc->badLayout & USING_NOBR)
1255
0
            TY_(Dialogue)( doc, TEXT_USING_NOBR );
1256
        
1257
0
        if (doc->badLayout & USING_BODY)
1258
0
            TY_(Dialogue)( doc, TEXT_USING_BODY );
1259
0
    }
1260
    
1261
0
    if (doc->footnotes)
1262
0
    {
1263
0
        if (doc->footnotes & FN_TRIM_EMPTY_ELEMENT)
1264
0
            TY_(Dialogue)( doc, FOOTNOTE_TRIM_EMPTY_ELEMENT );
1265
0
    }
1266
0
}
1267
1268
1269
/* Outputs document HTML version and version-related information. 
1270
** Called by tidyRunDiagnostics(), from console.
1271
** Called by tidyDocReportDoctype(), currently unused.
1272
*/
1273
void TY_(ReportMarkupVersion)( TidyDocImpl* doc )
1274
20.4k
{
1275
20.4k
    if ( doc->givenDoctype )
1276
80
        TY_(Report)( doc, NULL, NULL, STRING_DOCTYPE_GIVEN, doc->givenDoctype );
1277
1278
20.4k
    if ( ! cfgBool(doc, TidyXmlTags) )
1279
20.4k
    {
1280
20.4k
        Bool isXhtml = doc->lexer->isvoyager;
1281
20.4k
        uint apparentVers = TY_(ApparentVersion)( doc );
1282
20.4k
        ctmbstr vers = TY_(HTMLVersionNameFromCode)( apparentVers, isXhtml );
1283
1284
20.4k
        if ( !vers )
1285
76
            vers = tidyLocalizedString(STRING_HTML_PROPRIETARY);
1286
1287
20.4k
        TY_(Report)( doc, NULL, NULL, STRING_CONTENT_LOOKS, vers );
1288
1289
        /* Warn about missing system identifier (SI) in emitted doctype */
1290
20.4k
        if ( TY_(WarnMissingSIInEmittedDocType)( doc ) )
1291
0
            TY_(Report)( doc, NULL, NULL, STRING_NO_SYSID );
1292
20.4k
    }
1293
20.4k
}
1294
1295
1296
/* Reports the number of warnings and errors found in the document. 
1297
** Called by tidyRunDiagnostics(), from console.
1298
*/
1299
void TY_(ReportNumWarnings)( TidyDocImpl* doc )
1300
20.4k
{
1301
20.4k
    if ( doc->warnings > 0 || doc->errors > 0 )
1302
20.4k
    {
1303
20.4k
        if ( doc->errors > cfg(doc, TidyShowErrors) || !cfgBool(doc, TidyShowWarnings) )
1304
1.36k
        {
1305
1.36k
            TY_(Dialogue)( doc, STRING_NOT_ALL_SHOWN );
1306
1.36k
        }
1307
19.0k
        else
1308
19.0k
        {
1309
19.0k
            TY_(Dialogue)( doc, STRING_ERROR_COUNT );
1310
19.0k
        }
1311
1312
20.4k
    }
1313
1
    else
1314
1
    {
1315
1
        TY_(Dialogue)( doc, STRING_NO_ERRORS );
1316
1
    }
1317
20.4k
}
1318
1319
1320
/*********************************************************************
1321
 * Message Muting
1322
 *********************************************************************/
1323
1324
1325
void TY_(FreeMutedMessageList)( TidyDocImpl* doc )
1326
20.4k
{
1327
20.4k
    TidyMutedMessages *list = &(doc->muted);
1328
1329
20.4k
    if ( list->list )
1330
0
        TidyFree( doc->allocator, list->list );
1331
20.4k
}
1332
1333
1334
void TY_(DefineMutedMessage)(TidyDocImpl* doc, const TidyOptionImpl* opt, ctmbstr name)
1335
0
{
1336
0
    enum { capacity = 10 };
1337
0
    TidyMutedMessages *list = &(doc->muted);
1338
0
    tidyStrings message = TY_(tidyErrorCodeFromKey)( name );
1339
1340
0
    if ( message <= REPORT_MESSAGE_FIRST || message >= REPORT_MESSAGE_LAST)
1341
0
    {
1342
0
        TY_(Report)( doc, NULL, NULL, STRING_ARGUMENT_BAD, opt->name, name );
1343
0
        return;
1344
0
    }
1345
1346
0
    if ( !list->list )
1347
0
    {
1348
0
        list->list = TidyAlloc(doc->allocator, sizeof(tidyStrings) * capacity );
1349
0
        list->list[0] = 0;
1350
0
        list->capacity = capacity;
1351
0
        list->count = 0;
1352
0
    }
1353
1354
0
    if ( list->count >= list->capacity )
1355
0
    {
1356
0
        list->capacity = list->capacity * 2;
1357
0
        list->list = TidyRealloc(doc->allocator, list->list, sizeof(tidyStrings) * list->capacity + 1 );
1358
0
    }
1359
1360
0
    list->list[list->count] = message;
1361
0
    list->count++;
1362
0
    list->list[list->count] = 0;
1363
1364
    /* Must come *after* adding to the list, in case it's muted, too. */
1365
0
    TY_(Report)( doc, NULL, NULL, STRING_MUTING_TYPE, name );
1366
0
}
1367
1368
1369
TidyIterator TY_(getMutedMessageList)( TidyDocImpl* doc )
1370
0
{
1371
0
    TidyMutedMessages *list = &(doc->muted);
1372
0
    size_t result = list->count > 0 ? 1 : 0;
1373
1374
0
    return (TidyIterator) result;
1375
0
}
1376
1377
1378
ctmbstr TY_(getNextMutedMessage)( TidyDocImpl* doc, TidyIterator* iter )
1379
0
{
1380
0
    TidyMutedMessages *list = &(doc->muted);
1381
0
    size_t index;
1382
0
    ctmbstr result = NULL;
1383
0
    assert( iter != NULL );
1384
0
    index = (size_t)*iter;
1385
1386
0
    if ( index > 0 && index <= list->count )
1387
0
    {
1388
0
        result = TY_(tidyErrorCodeAsKey)(list->list[index-1]);
1389
0
        index++;
1390
0
    }
1391
0
    *iter = (TidyIterator) ( index <= list->count ? index : (size_t)0 );
1392
1393
0
    return result;
1394
0
}
1395
1396
1397
/*********************************************************************
1398
 * Key Discovery
1399
 *********************************************************************/
1400
1401
1402
/*********************************************************************
1403
 * LibTidy users may want to to enable their own localization lookup
1404
 * lookup methods. Because Tidy's errors codes are enums, the actual
1405
 * values can change over time. This table will the LibTidy users
1406
 * always have a static value available for use.
1407
 *
1408
 * For macro documentation, refer to the comments in `tidyenum.h`.
1409
 *********************************************************************/
1410
1411
typedef struct tidyStringsKeyItem {
1412
    ctmbstr key;
1413
    int value;
1414
} tidyStringsKeyItem;
1415
1416
static const tidyStringsKeyItem tidyStringsKeys[] = {
1417
    FOREACH_TIDYCONFIGCATEGORY(MAKE_STRUCT)
1418
    FOREACH_MSG_MISC(MAKE_STRUCT)
1419
    FOREACH_FOOTNOTE_MSG(MAKE_STRUCT)
1420
    FOREACH_DIALOG_MSG(MAKE_STRUCT)
1421
    FOREACH_REPORT_MSG(MAKE_STRUCT)
1422
    FOREACH_ACCESS_MSG(MAKE_STRUCT)
1423
#if SUPPORT_CONSOLE_APP
1424
    FOREACH_MSG_CONSOLE(MAKE_STRUCT)
1425
#endif
1426
    { "TIDYSTRINGS_FIRST",                        TIDYSTRINGS_FIRST },
1427
    { "TIDYSTRINGS_LAST",                         TIDYSTRINGS_LAST  },
1428
    { NULL,                                       0                 },
1429
};
1430
1431
1432
/**
1433
 *  Given an error code, return the string associated with it.
1434
 */
1435
ctmbstr TY_(tidyErrorCodeAsKey)(uint code)
1436
7.11M
{
1437
7.11M
    uint i = 0;
1438
816M
    while (tidyStringsKeys[i].key) {
1439
816M
        if ( tidyStringsKeys[i].value == code )
1440
7.11M
            return tidyStringsKeys[i].key;
1441
809M
        i++;
1442
809M
    }
1443
0
    return "UNDEFINED";
1444
7.11M
}
1445
1446
1447
/**
1448
 *  Given an error code string, return its uint.
1449
 */
1450
uint TY_(tidyErrorCodeFromKey)(ctmbstr code)
1451
0
{
1452
0
    uint i = 0;
1453
0
    while (tidyStringsKeys[i].key) {
1454
0
        if ( strcmp(tidyStringsKeys[i].key, code) == 0 )
1455
0
            return tidyStringsKeys[i].value;
1456
0
        i++;
1457
0
    }
1458
0
    return UINT_MAX;
1459
0
}
1460
1461
1462
/**
1463
 *  Determines the number of error codes used by Tidy.
1464
 */
1465
static const uint tidyErrorCodeListSize()
1466
0
{
1467
0
    static uint array_size = 0;
1468
    
1469
0
    if ( array_size == 0 )
1470
0
    {
1471
0
        while ( tidyStringsKeys[array_size].key ) {
1472
0
            array_size++;
1473
0
        }
1474
0
    }
1475
    
1476
0
    return array_size;
1477
0
}
1478
1479
/**
1480
 *  Initializes the TidyIterator to point to the first item
1481
 *  in Tidy's list of error codes. Individual items must be
1482
 *  retrieved with getNextErrorCode();
1483
 */
1484
TidyIterator TY_(getErrorCodeList)()
1485
0
{
1486
0
    return (TidyIterator)(size_t)1;
1487
0
}
1488
1489
/**
1490
 *  Returns the next error code.
1491
 */
1492
uint TY_(getNextErrorCode)( TidyIterator* iter )
1493
0
{
1494
0
    const tidyStringsKeyItem *item = NULL;
1495
0
    size_t itemIndex;
1496
0
    assert( iter != NULL );
1497
    
1498
0
    itemIndex = (size_t)*iter;
1499
    
1500
0
    if ( itemIndex > 0 && itemIndex <= tidyErrorCodeListSize() )
1501
0
    {
1502
0
        item = &tidyStringsKeys[itemIndex - 1];
1503
0
        itemIndex++;
1504
0
    }
1505
    
1506
0
    *iter = (TidyIterator)( itemIndex <= tidyErrorCodeListSize() ? itemIndex : (size_t)0 );
1507
0
    return item ? item->value : 0;
1508
0
}
1509
1510
1511
/*********************************************************************
1512
 * Documentation of configuration options
1513
 *
1514
 * Although most of the strings now come from the language module,
1515
 * generating the documentation by the console application requires a
1516
 * series of cross-references that are generated in this messaging
1517
 * module.
1518
 *********************************************************************/
1519
1520
1521
#if SUPPORT_CONSOLE_APP
1522
/* Cross-references definitions.
1523
 * Note that each list must be terminated with `TidyUnknownOption`.
1524
 */
1525
static const TidyOptionId TidyAsciiCharsLinks[] =      { TidyMakeClean, TidyUnknownOption };
1526
static const TidyOptionId TidyBlockTagsLinks[] =       { TidyEmptyTags, TidyInlineTags, TidyPreTags, TidyUseCustomTags, TidyUnknownOption };
1527
static const TidyOptionId TidyCharEncodingLinks[] =    { TidyInCharEncoding, TidyOutCharEncoding, TidyUnknownOption };
1528
static const TidyOptionId TidyDuplicateAttrsLinks[] =  { TidyJoinClasses, TidyJoinStyles, TidyUnknownOption };
1529
static const TidyOptionId TidyEmacsLinks[] =           { TidyShowFilename, TidyUnknownOption };
1530
static const TidyOptionId TidyEmptyTagsLinks[] =       { TidyBlockTags, TidyInlineTags, TidyPreTags, TidyUseCustomTags, TidyUnknownOption };
1531
static const TidyOptionId TidyErrFileLinks[] =         { TidyOutFile, TidyUnknownOption };
1532
static const TidyOptionId TidyInCharEncodingLinks[] =  { TidyCharEncoding, TidyUnknownOption };
1533
static const TidyOptionId TidyIndentContentLinks[] =   { TidyIndentSpaces, TidyUnknownOption };
1534
static const TidyOptionId TidyIndentSpacesLinks[] =    { TidyIndentContent, TidyUnknownOption };
1535
static const TidyOptionId TidyInlineTagsLinks[] =      { TidyBlockTags, TidyEmptyTags, TidyPreTags, TidyUseCustomTags, TidyUnknownOption };
1536
static const TidyOptionId TidyMergeDivsLinks[] =       { TidyMakeClean, TidyMergeSpans, TidyUnknownOption };
1537
static const TidyOptionId TidyMergeSpansLinks[] =      { TidyMakeClean, TidyMergeDivs, TidyUnknownOption };
1538
static const TidyOptionId TidyMuteLinks[] =            { TidyMuteShow, TidyUnknownOption };
1539
static const TidyOptionId TidyMuteShowLinks[] =        { TidyMuteReports, TidyUnknownOption };
1540
static const TidyOptionId TidyNumEntitiesLinks[] =     { TidyDoctype, TidyPreserveEntities, TidyUnknownOption };
1541
static const TidyOptionId TidyOutCharEncodingLinks[] = { TidyCharEncoding, TidyUnknownOption };
1542
static const TidyOptionId TidyOutFileLinks[] =         { TidyErrFile, TidyUnknownOption };
1543
static const TidyOptionId TidyPreTagsLinks[] =         { TidyBlockTags, TidyEmptyTags, TidyInlineTags, TidyUseCustomTags, TidyUnknownOption };
1544
static const TidyOptionId TidyShowFilenameLinks[] =    { TidyEmacs, TidyUnknownOption };
1545
static const TidyOptionId TidySortAttributesLinks[] =  { TidyPriorityAttributes, TidyUnknownOption };
1546
static const TidyOptionId TidyUseCustomTagsLinks[] =   { TidyBlockTags, TidyEmptyTags, TidyInlineTags, TidyPreTags, TidyUnknownOption };
1547
static const TidyOptionId TidyWrapAttValsLinks[] =     { TidyWrapScriptlets, TidyLiteralAttribs, TidyUnknownOption };
1548
static const TidyOptionId TidyWrapScriptletsLinks[] =  { TidyWrapAttVals, TidyUnknownOption };
1549
static const TidyOptionId TidyXmlDeclLinks[] =         { TidyCharEncoding, TidyOutCharEncoding, TidyUnknownOption };
1550
1551
/* Cross-reference assignments. 
1552
 * We can't build a complex array at compile time and we're not counting on
1553
 * any type of initialization, so this two-stage building process is required.
1554
 */
1555
static const TidyOptionDoc docs_xrefs[] =
1556
{
1557
    { TidyAsciiChars,      TidyAsciiCharsLinks      },
1558
    { TidyBlockTags,       TidyBlockTagsLinks       },
1559
    { TidyCharEncoding,    TidyCharEncodingLinks    },
1560
    { TidyDuplicateAttrs,  TidyDuplicateAttrsLinks  },
1561
    { TidyEmacs,           TidyEmacsLinks           },
1562
    { TidyEmptyTags,       TidyEmptyTagsLinks       },
1563
    { TidyErrFile,         TidyErrFileLinks         },
1564
    { TidyInCharEncoding,  TidyInCharEncodingLinks  },
1565
    { TidyIndentContent,   TidyIndentContentLinks   },
1566
    { TidyIndentSpaces,    TidyIndentSpacesLinks    },
1567
    { TidyInlineTags,      TidyInlineTagsLinks      },
1568
    { TidyMergeDivs,       TidyMergeDivsLinks       },
1569
    { TidyMergeSpans,      TidyMergeSpansLinks      },
1570
    { TidyMuteShow,        TidyMuteShowLinks        },
1571
    { TidyNumEntities,     TidyNumEntitiesLinks     },
1572
    { TidyOutCharEncoding, TidyOutCharEncodingLinks },
1573
    { TidyOutFile,         TidyOutFileLinks         },
1574
    { TidyPreTags,         TidyPreTagsLinks         },
1575
    { TidyShowFilename,    TidyShowFilenameLinks    },
1576
    { TidySortAttributes,  TidySortAttributesLinks  },
1577
    { TidyMuteReports,     TidyMuteLinks            },
1578
    { TidyUseCustomTags,   TidyUseCustomTagsLinks   },
1579
    { TidyWrapAttVals,     TidyWrapAttValsLinks     },
1580
    { TidyWrapScriptlets,  TidyWrapScriptletsLinks  },
1581
    { TidyXmlDecl,         TidyXmlDeclLinks         },
1582
    { N_TIDY_OPTIONS                                }
1583
};
1584
1585
1586
/* Cross-reference retrieval. */
1587
const TidyOptionDoc* TY_(OptGetDocDesc)( TidyOptionId optId )
1588
0
{
1589
0
    uint i = 0;
1590
1591
0
    while( docs_xrefs[i].opt != N_TIDY_OPTIONS )
1592
0
    {
1593
0
        if ( docs_xrefs[i].opt == optId )
1594
0
            return &docs_xrefs[i];
1595
0
        ++i;
1596
0
    }
1597
0
    return NULL;
1598
0
}
1599
1600
#endif /* SUPPORT_CONSOLE_APP */
1601
1602
1603
/*
1604
 * local variables:
1605
 * mode: c
1606
 * indent-tabs-mode: nil
1607
 * c-basic-offset: 4
1608
 * eval: (c-set-offset 'substatement-open 0)
1609
 * end:
1610
 */