2017-05-08 20:14:35 +00:00
|
|
|
/* config.c
|
|
|
|
* Read configuration files and manage configuration properties.
|
|
|
|
*
|
|
|
|
* Copyright (c) 1998-2017 World Wide Web Consortium (Massachusetts
|
|
|
|
* Institute of Technology, European Research Consortium for Informatics
|
|
|
|
* and Mathematics, Keio University) and HTACG.
|
|
|
|
*
|
|
|
|
* See tidy.h for the copyright notice.
|
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "tidy-int.h"
|
|
|
|
#include "message.h"
|
|
|
|
#include "tmbstr.h"
|
|
|
|
#include "tags.h"
|
|
|
|
|
|
|
|
#ifdef WINDOWS_OS
|
2017-10-03 19:30:21 +00:00
|
|
|
# include <io.h>
|
2011-11-17 02:44:16 +00:00
|
|
|
#else
|
2017-10-03 19:30:21 +00:00
|
|
|
# ifdef DMALLOC
|
|
|
|
/* macro for valloc() in dmalloc.h may conflict with declaration for valloc()
|
|
|
|
in unistd.h - we don't need (debugging for) valloc() here. dmalloc.h should
|
|
|
|
come last but it doesn't.*/
|
|
|
|
# ifdef valloc
|
|
|
|
# undef valloc
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# include <unistd.h>
|
2011-11-17 02:44:16 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
void TY_(InitConfig)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
TidyClearMemory( &doc->config, sizeof(TidyConfigImpl) );
|
|
|
|
TY_(ResetConfigToDefault)( doc );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TY_(FreeConfig)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
TY_(ResetConfigToDefault)( doc );
|
|
|
|
TY_(TakeConfigSnapshot)( doc );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
/*
|
|
|
|
Arrange so index can be cast to enum. Note that the value field in the
|
|
|
|
following structures is not currently used in code; they're present for
|
|
|
|
documentation purposes currently. The arrays must be populated in enum order.
|
2011-11-17 02:44:16 +00:00
|
|
|
*/
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems boolPicks = {
|
|
|
|
{ "no", TidyNoState, { "0", "n", "f", "no", "false", NULL } },
|
|
|
|
{ "yes", TidyYesState, { "1", "y", "t", "yes", "true", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems autoBoolPicks = {
|
2017-09-25 19:26:03 +00:00
|
|
|
{ "no", TidyNoState, { "0", "n", "f", "no", "false", NULL } },
|
|
|
|
{ "yes", TidyYesState, { "1", "y", "t", "yes", "true", NULL } },
|
|
|
|
{ "auto", TidyAutoState, { "auto", NULL } },
|
2017-05-08 20:14:35 +00:00
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems repeatAttrPicks = {
|
|
|
|
{ "keep-first", TidyNoState, { "keep-first", NULL } },
|
|
|
|
{ "keep-last", TidyYesState, { "keep-last", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems accessPicks = {
|
|
|
|
{ "0 (Tidy Classic)", 0, { "0", "0 (Tidy Classic)", NULL } },
|
|
|
|
{ "1 (Priority 1 Checks)", 1, { "1", "1 (Priority 1 Checks)", NULL } },
|
|
|
|
{ "2 (Priority 2 Checks)", 2, { "2", "2 (Priority 2 Checks)", NULL } },
|
|
|
|
{ "3 (Priority 3 Checks)", 3, { "3", "3 (Priority 3 Checks)", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems charEncPicks = {
|
|
|
|
{ "raw", TidyEncRaw, { "raw", NULL } },
|
|
|
|
{ "ascii", TidyEncAscii, { "ascii", NULL } },
|
|
|
|
{ "latin0", TidyEncLatin0, { "latin0", NULL } },
|
|
|
|
{ "latin1", TidyEncLatin1, { "latin1", NULL } },
|
|
|
|
{ "utf8", TidyEncUtf8, { "utf8", NULL } },
|
2011-11-17 02:44:16 +00:00
|
|
|
#ifndef NO_NATIVE_ISO2022_SUPPORT
|
2017-05-08 20:14:35 +00:00
|
|
|
{ "iso2022", TidyEncIso2022, { "iso2022", NULL } },
|
2011-11-17 02:44:16 +00:00
|
|
|
#endif
|
2017-05-08 20:14:35 +00:00
|
|
|
{ "mac", TidyEncMac, { "mac", NULL } },
|
|
|
|
{ "win1252", TidyEncWin1252, { "win1252", NULL } },
|
|
|
|
{ "ibm858", TidyEncIbm858, { "ibm858", NULL } },
|
|
|
|
{ "utf16le", TidyEncUtf16le, { "utf16le", NULL } },
|
|
|
|
{ "utf16be", TidyEncUtf16be, { "utf16be", NULL } },
|
|
|
|
{ "utf16", TidyEncUtf16, { "utf16", NULL } },
|
|
|
|
{ "big5", TidyEncBig5, { "big5", NULL } },
|
|
|
|
{ "shiftjis", TidyEncShiftjis, { "shiftjis", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems newlinePicks = {
|
|
|
|
{ "LF", TidyLF, { "lf", NULL } },
|
|
|
|
{ "CRLF", TidyCRLF, { "crlf", NULL } },
|
|
|
|
{ "CR", TidyCR, { "cr", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems doctypePicks = {
|
|
|
|
{ "html5", TidyDoctypeHtml5, { "html5", NULL } },
|
|
|
|
{ "omit", TidyDoctypeOmit, { "omit", NULL } },
|
|
|
|
{ "auto", TidyDoctypeAuto, { "auto", NULL } },
|
|
|
|
{ "strict", TidyDoctypeStrict, { "strict", NULL } },
|
|
|
|
{ "transitional", TidyDoctypeLoose, { "loose", "transitional", NULL } },
|
|
|
|
{ "user", TidyDoctypeUser, { "user", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems sorterPicks = {
|
|
|
|
{ "none", TidySortAttrNone, { "none", NULL } },
|
|
|
|
{ "alpha", TidySortAttrAlpha, { "alpha", NULL } },
|
|
|
|
{ NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
static PickListItems customTagsPicks = {
|
|
|
|
{"no", TidyCustomNo, { "no", "n", NULL } },
|
|
|
|
{"blocklevel", TidyCustomBlocklevel, { "blocklevel", NULL } },
|
|
|
|
{"empty", TidyCustomEmpty, { "empty", NULL } },
|
|
|
|
{"inline", TidyCustomInline, { "inline", "y", "yes", NULL } },
|
|
|
|
{"pre", TidyCustomPre, { "pre", NULL } },
|
|
|
|
{ NULL }
|
2017-03-13 17:45:32 +00:00
|
|
|
};
|
|
|
|
|
2017-05-11 22:12:56 +00:00
|
|
|
static PickListItems attributeCasePicks = {
|
|
|
|
{ "no", TidyUppercaseNo, { "0", "n", "f", "no", "false", NULL } },
|
|
|
|
{ "yes", TidyUppercaseYes, { "1", "y", "t", "yes", "true", NULL } },
|
|
|
|
{ "preserve", TidyUppercasePreserve, { "preserve", NULL } },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
#define DG TidyDiagnostics
|
2017-10-04 16:24:07 +00:00
|
|
|
#define DD TidyDisplay
|
|
|
|
#define DT TidyDocumentIO
|
2011-11-17 02:44:16 +00:00
|
|
|
#define CE TidyEncoding
|
2017-10-04 16:24:07 +00:00
|
|
|
#define IO TidyFileIO
|
|
|
|
#define MC TidyMarkupCleanup
|
|
|
|
#define ME TidyMarkupEntities
|
|
|
|
#define MR TidyMarkupRepair
|
|
|
|
#define MT TidyMarkupTeach
|
|
|
|
#define MX TidyMarkupXForm
|
|
|
|
#define PP TidyPrettyPrint
|
2017-03-09 21:04:03 +00:00
|
|
|
#define IR TidyInternalCategory
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
#define IN TidyInteger
|
|
|
|
#define BL TidyBoolean
|
|
|
|
#define ST TidyString
|
|
|
|
|
|
|
|
#define XX (TidyConfigCategory)-1
|
|
|
|
#define XY (TidyOptionType)-1
|
|
|
|
|
|
|
|
#define DLF DEFAULT_NL_CONFIG
|
|
|
|
|
|
|
|
static void AdjustConfig( TidyDocImpl* doc );
|
|
|
|
|
|
|
|
/* parser for integer values */
|
|
|
|
static ParseProperty ParseInt;
|
|
|
|
|
2017-09-23 11:30:17 +00:00
|
|
|
/* a space or comma separated list */
|
|
|
|
static ParseProperty ParseList;
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
/* a string excluding whitespace */
|
|
|
|
static ParseProperty ParseName;
|
|
|
|
|
|
|
|
/* a CSS1 selector - CSS class naming for -clean option */
|
|
|
|
static ParseProperty ParseCSS1Selector;
|
|
|
|
|
|
|
|
/* a string including whitespace */
|
|
|
|
static ParseProperty ParseString;
|
|
|
|
|
|
|
|
/* a space or comma separated list of tag names */
|
|
|
|
static ParseProperty ParseTagNames;
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
/* RAW, ASCII, LATIN0, LATIN1, UTF8, ISO2022, MACROMAN,
|
2011-11-17 02:44:16 +00:00
|
|
|
WIN1252, IBM858, UTF16LE, UTF16BE, UTF16, BIG5, SHIFTJIS
|
|
|
|
*/
|
|
|
|
static ParseProperty ParseCharEnc;
|
|
|
|
|
2012-03-15 05:11:01 +00:00
|
|
|
/* html5 | omit | auto | strict | loose | <fpi> */
|
2011-11-17 02:44:16 +00:00
|
|
|
static ParseProperty ParseDocType;
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
/* 20150515 - support using tabs instead of spaces - Issue #108
|
|
|
|
*/
|
2015-05-15 13:06:52 +00:00
|
|
|
static ParseProperty ParseTabs;
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
/* General parser for options having picklists */
|
|
|
|
static ParseProperty ParsePickList;
|
2017-03-13 17:45:32 +00:00
|
|
|
|
|
|
|
|
2017-03-08 15:29:41 +00:00
|
|
|
/* Ensure struct order is same order as tidyenum.h:TidyOptionId! */
|
2011-11-17 02:44:16 +00:00
|
|
|
static const TidyOptionImpl option_defs[] =
|
|
|
|
{
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyUnknownOption, IR, "unknown!", IN, 0, NULL, NULL },
|
2017-10-03 16:45:34 +00:00
|
|
|
{ TidyAccessibilityCheckLevel, DG, "accessibility-check", IN, 0, ParsePickList, &accessPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyAltText, MR, "alt-text", ST, 0, ParseString, NULL },
|
|
|
|
{ TidyAnchorAsName, MR, "anchor-as-name", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyAsciiChars, ME, "ascii-chars", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyBlockTags, MT, "new-blocklevel-tags", ST, 0, ParseTagNames, NULL },
|
|
|
|
{ TidyBodyOnly, DD, "show-body-only", IN, no, ParsePickList, &autoBoolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyBreakBeforeBR, PP, "break-before-br", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyCharEncoding, CE, "char-encoding", IN, UTF8, ParseCharEnc, &charEncPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyCoerceEndTags, MR, "coerce-endtags", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyCSSPrefix, MR, "css-prefix", ST, 0, ParseCSS1Selector, NULL },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyCustomTags, IR, "new-custom-tags", ST, 0, ParseTagNames, NULL }, /* 20170309 - Issue #119 */
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyDecorateInferredUL, MX, "decorate-inferred-ul", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyDoctype, DT, "doctype", ST, 0, ParseDocType, &doctypePicks },
|
2017-03-10 13:24:23 +00:00
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyDoctypeMode, IR, "doctype-mode", IN, TidyDoctypeAuto, NULL, &doctypePicks },
|
2017-03-10 13:24:23 +00:00
|
|
|
#endif
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyDropEmptyElems, MC, "drop-empty-elements", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyDropEmptyParas, MC, "drop-empty-paras", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyDropPropAttrs, MC, "drop-proprietary-attributes", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyDuplicateAttrs, MR, "repeated-attributes", IN, TidyKeepLast, ParsePickList, &repeatAttrPicks },
|
|
|
|
{ TidyEmacs, DD, "gnu-emacs", BL, no, ParsePickList, &boolPicks },
|
2017-03-10 13:24:23 +00:00
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyEmacsFile, IR, "gnu-emacs-file", ST, 0, ParseString, NULL },
|
2017-03-10 13:24:23 +00:00
|
|
|
#endif
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyEmptyTags, MT, "new-empty-tags", ST, 0, ParseTagNames, NULL },
|
|
|
|
{ TidyEncloseBlockText, MR, "enclose-block-text", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyEncloseBodyText, MR, "enclose-text", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyErrFile, IO, "error-file", ST, 0, ParseString, NULL },
|
|
|
|
{ TidyEscapeCdata, MX, "escape-cdata", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyEscapeScripts, MR, "escape-scripts", BL, yes, ParsePickList, &boolPicks }, /* 20160227 - Issue #348 */
|
|
|
|
{ TidyFixBackslash, MR, "fix-backslash", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyFixComments, MR, "fix-bad-comments", IN, TidyAutoState, ParsePickList, &autoBoolPicks },
|
|
|
|
{ TidyFixUri, MR, "fix-uri", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyForceOutput, DG, "force-output", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyGDocClean, MC, "gdoc", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyHideComments, MX, "hide-comments", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyHtmlOut, DT, "output-html", BL, no, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyInCharEncoding, CE, "input-encoding", IN, UTF8, ParseCharEnc, &charEncPicks },
|
|
|
|
{ TidyIndentAttributes, PP, "indent-attributes", BL, no, ParsePickList, &boolPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyIndentCdata, PP, "indent-cdata", BL, no, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyIndentContent, PP, "indent", IN, TidyNoState, ParsePickList, &autoBoolPicks },
|
|
|
|
{ TidyIndentSpaces, PP, "indent-spaces", IN, 2, ParseInt, NULL },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyInlineTags, MT, "new-inline-tags", ST, 0, ParseTagNames, NULL },
|
|
|
|
{ TidyJoinClasses, MX, "join-classes", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyJoinStyles, MX, "join-styles", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyKeepFileTimes, IO, "keep-time", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyLiteralAttribs, MR, "literal-attributes", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyLogicalEmphasis, MC, "logical-emphasis", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyLowerLiterals, MR, "lower-literals", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyMakeBare, MC, "bare", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyMakeClean, MC, "clean", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyMark, PP, "tidy-mark", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyMergeDivs, MC, "merge-divs", IN, TidyAutoState, ParsePickList, &autoBoolPicks },
|
|
|
|
{ TidyMergeEmphasis, MX, "merge-emphasis", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyMergeSpans, MC, "merge-spans", IN, TidyAutoState, ParsePickList, &autoBoolPicks },
|
|
|
|
{ TidyMetaCharset, DT, "add-meta-charset", BL, no, ParsePickList, &boolPicks }, /* 20161004 - Issue #456 */
|
|
|
|
{ TidyNCR, ME, "ncr", BL, yes, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyNewline, CE, "newline", IN, DLF, ParsePickList, &newlinePicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyNumEntities, ME, "numeric-entities", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyOmitOptionalTags, PP, "omit-optional-tags", BL, no, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyOutCharEncoding, CE, "output-encoding", IN, UTF8, ParseCharEnc, &charEncPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyOutFile, IO, "output-file", ST, 0, ParseString, NULL },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyOutputBOM, CE, "output-bom", IN, TidyAutoState, ParsePickList, &autoBoolPicks },
|
|
|
|
{ TidyPPrintTabs, PP, "indent-with-tabs", BL, no, ParseTabs, &boolPicks }, /* 20150515 - Issue #108 */
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyPreserveEntities, ME, "preserve-entities", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyPreTags, MT, "new-pre-tags", ST, 0, ParseTagNames, NULL },
|
|
|
|
{ TidyPriorityAttributes, PP, "priority-attributes", ST, 0, ParseList, NULL },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyPunctWrap, PP, "punctuation-wrap", BL, no, ParsePickList, &boolPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyQuiet, DD, "quiet", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyQuoteAmpersand, ME, "quote-ampersand", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyQuoteMarks, ME, "quote-marks", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyQuoteNbsp, ME, "quote-nbsp", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyReplaceColor, MX, "replace-color", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyShowErrors, DD, "show-errors", IN, 6, ParseInt, NULL },
|
|
|
|
{ TidyShowInfo, DD, "show-info", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyShowMarkup, DD, "markup", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyShowMetaChange, DG, "show-meta-change", BL, no, ParsePickList, &boolPicks }, /* 20170609 - Issue #456 */
|
|
|
|
{ TidyShowWarnings, DD, "show-warnings", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidySkipNested, MR, "skip-nested", BL, yes, ParsePickList, &boolPicks }, /* 1642186 - Issue #65 */
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidySortAttributes, PP, "sort-attributes", IN, TidySortAttrNone,ParsePickList, &sorterPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyStrictTagsAttr, MR, "strict-tags-attributes", BL, no, ParsePickList, &boolPicks }, /* 20160209 - Issue #350 */
|
|
|
|
{ TidyStyleTags, MR, "fix-style-tags", BL, yes, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyTabSize, PP, "tab-size", IN, 8, ParseInt, NULL },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyUpperCaseAttrs, MR, "uppercase-attributes", IN, TidyUppercaseNo, ParsePickList, &attributeCasePicks },
|
|
|
|
{ TidyUpperCaseTags, MR, "uppercase-tags", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyUseCustomTags, MR, "custom-tags", IN, TidyCustomNo, ParsePickList, &customTagsPicks }, /* 20170309 - Issue #119 */
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyVertSpace, PP, "vertical-space", IN, no, ParsePickList, &autoBoolPicks }, /* #228 - tri option */
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyWarnPropAttrs, DG, "warn-proprietary-attributes", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyWord2000, MC, "word-2000", BL, no, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ TidyWrapAsp, PP, "wrap-asp", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyWrapAttVals, PP, "wrap-attributes", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyWrapJste, PP, "wrap-jste", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyWrapLen, PP, "wrap", IN, 68, ParseInt, NULL },
|
|
|
|
{ TidyWrapPhp, PP, "wrap-php", BL, yes, ParsePickList, &boolPicks },
|
|
|
|
{ TidyWrapScriptlets, PP, "wrap-script-literals", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyWrapSection, PP, "wrap-sections", BL, yes, ParsePickList, &boolPicks },
|
2017-10-04 16:24:07 +00:00
|
|
|
{ TidyWriteBack, IO, "write-back", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyXhtmlOut, DT, "output-xhtml", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyXmlDecl, DT, "add-xml-decl", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyXmlOut, DT, "output-xml", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyXmlPIs, MR, "assume-xml-procins", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyXmlSpace, DT, "add-xml-space", BL, no, ParsePickList, &boolPicks },
|
|
|
|
{ TidyXmlTags, DT, "input-xml", BL, no, ParsePickList, &boolPicks },
|
2017-05-11 22:12:56 +00:00
|
|
|
{ N_TIDY_OPTIONS, XX, NULL, XY, 0, NULL, NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
/* Deleted options. This array keeps track of options that have been
|
|
|
|
** removed from Tidy, and suggests a replacement. When a deleted option is
|
|
|
|
** used, client programs will have the opportunity to consume the option
|
|
|
|
** first via the callback, and if not handled by the callback, will be
|
|
|
|
** handled by Tidy, generally by setting an alternate or new option.
|
|
|
|
*/
|
2017-10-06 20:14:54 +00:00
|
|
|
static const struct {
|
|
|
|
ctmbstr name; /**< name of the deprecated option */
|
|
|
|
TidyOptionId replacementId; /**< Id of the replacement option, or 0 if none. */
|
|
|
|
} deprecatedOptions[] = {
|
2017-10-07 15:20:57 +00:00
|
|
|
// { "show-body-only", TidyBodyOnly }, /* WIP, for development purposes! */
|
2017-10-06 20:14:54 +00:00
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
/* Should only be called by options set by name
|
|
|
|
** thus, it is cheaper to do a few scans than set
|
|
|
|
** up every option in a hash table.
|
|
|
|
*/
|
|
|
|
const TidyOptionImpl* TY_(lookupOption)( ctmbstr s )
|
|
|
|
{
|
|
|
|
const TidyOptionImpl* np = option_defs;
|
|
|
|
for ( /**/; np < option_defs + N_TIDY_OPTIONS; ++np )
|
|
|
|
{
|
|
|
|
if ( TY_(tmbstrcasecmp)(s, np->name) == 0 )
|
|
|
|
return np;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TidyOptionImpl* TY_(getOption)( TidyOptionId optId )
|
|
|
|
{
|
|
|
|
if ( optId < N_TIDY_OPTIONS )
|
|
|
|
return option_defs + optId;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void FreeOptionValue( TidyDocImpl* doc, const TidyOptionImpl* option, TidyOptionValue* value )
|
|
|
|
{
|
|
|
|
if ( option->type == TidyString && value->p && value->p != option->pdflt )
|
|
|
|
TidyDocFree( doc, value->p );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CopyOptionValue( TidyDocImpl* doc, const TidyOptionImpl* option,
|
|
|
|
TidyOptionValue* oldval, const TidyOptionValue* newval )
|
|
|
|
{
|
|
|
|
assert( oldval != NULL );
|
|
|
|
FreeOptionValue( doc, option, oldval );
|
|
|
|
|
|
|
|
if ( option->type == TidyString )
|
|
|
|
{
|
|
|
|
if ( newval->p && newval->p != option->pdflt )
|
|
|
|
oldval->p = TY_(tmbstrdup)( doc->allocator, newval->p );
|
|
|
|
else
|
|
|
|
oldval->p = newval->p;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
oldval->v = newval->v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Bool SetOptionValue( TidyDocImpl* doc, TidyOptionId optId, ctmbstr val )
|
|
|
|
{
|
|
|
|
const TidyOptionImpl* option = &option_defs[ optId ];
|
|
|
|
Bool status = ( optId < N_TIDY_OPTIONS );
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
assert( option->id == optId && option->type == TidyString );
|
|
|
|
FreeOptionValue( doc, option, &doc->config.value[ optId ] );
|
2015-06-08 11:42:45 +00:00
|
|
|
if ( TY_(tmbstrlen)(val)) /* Issue #218 - ONLY if it has LENGTH! */
|
|
|
|
doc->config.value[ optId ].p = TY_(tmbstrdup)( doc->allocator, val );
|
|
|
|
else
|
|
|
|
doc->config.value[ optId ].p = 0; /* should already be zero, but to be sure... */
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TY_(SetOptionInt)( TidyDocImpl* doc, TidyOptionId optId, ulong val )
|
|
|
|
{
|
|
|
|
Bool status = ( optId < N_TIDY_OPTIONS );
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
assert( option_defs[ optId ].type == TidyInteger );
|
|
|
|
doc->config.value[ optId ].v = val;
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TY_(SetOptionBool)( TidyDocImpl* doc, TidyOptionId optId, Bool val )
|
|
|
|
{
|
|
|
|
Bool status = ( optId < N_TIDY_OPTIONS );
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
assert( option_defs[ optId ].type == TidyBoolean );
|
|
|
|
doc->config.value[ optId ].v = val;
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void GetOptionDefault( const TidyOptionImpl* option,
|
|
|
|
TidyOptionValue* dflt )
|
|
|
|
{
|
|
|
|
if ( option->type == TidyString )
|
|
|
|
dflt->p = (char*)option->pdflt;
|
|
|
|
else
|
|
|
|
dflt->v = option->dflt;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool OptionValueEqDefault( const TidyOptionImpl* option,
|
|
|
|
const TidyOptionValue* val )
|
|
|
|
{
|
|
|
|
return ( option->type == TidyString ) ?
|
|
|
|
val->p == option->pdflt :
|
|
|
|
val->v == option->dflt;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TY_(ResetOptionToDefault)( TidyDocImpl* doc, TidyOptionId optId )
|
|
|
|
{
|
|
|
|
Bool status = ( optId > 0 && optId < N_TIDY_OPTIONS );
|
|
|
|
if ( status )
|
|
|
|
{
|
|
|
|
TidyOptionValue dflt;
|
|
|
|
const TidyOptionImpl* option = option_defs + optId;
|
|
|
|
TidyOptionValue* value = &doc->config.value[ optId ];
|
|
|
|
assert( optId == option->id );
|
|
|
|
GetOptionDefault( option, &dflt );
|
|
|
|
CopyOptionValue( doc, option, value, &dflt );
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ReparseTagType( TidyDocImpl* doc, TidyOptionId optId )
|
|
|
|
{
|
|
|
|
ctmbstr tagdecl = cfgStr( doc, optId );
|
|
|
|
tmbstr dupdecl = TY_(tmbstrdup)( doc->allocator, tagdecl );
|
|
|
|
TY_(ParseConfigValue)( doc, optId, dupdecl );
|
|
|
|
TidyDocFree( doc, dupdecl );
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool OptionValueIdentical( const TidyOptionImpl* option,
|
|
|
|
const TidyOptionValue* val1,
|
|
|
|
const TidyOptionValue* val2 )
|
|
|
|
{
|
|
|
|
if ( option->type == TidyString )
|
|
|
|
{
|
|
|
|
if ( val1->p == val2->p )
|
|
|
|
return yes;
|
|
|
|
if ( !val1->p || !val2->p )
|
|
|
|
return no;
|
|
|
|
return TY_(tmbstrcmp)( val1->p, val2->p ) == 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return val1->v == val2->v;
|
|
|
|
}
|
|
|
|
|
2017-03-13 17:45:32 +00:00
|
|
|
static Bool NeedReparseTagDecls( TidyDocImpl* doc,
|
|
|
|
const TidyOptionValue* current,
|
2011-11-17 02:44:16 +00:00
|
|
|
const TidyOptionValue* new,
|
|
|
|
uint *changedUserTags )
|
|
|
|
{
|
|
|
|
Bool ret = no;
|
|
|
|
uint ixVal;
|
|
|
|
const TidyOptionImpl* option = option_defs;
|
|
|
|
*changedUserTags = tagtype_null;
|
|
|
|
|
|
|
|
for ( ixVal=0; ixVal < N_TIDY_OPTIONS; ++option, ++ixVal )
|
|
|
|
{
|
|
|
|
assert( ixVal == (uint) option->id );
|
|
|
|
switch (option->id)
|
|
|
|
{
|
|
|
|
#define TEST_USERTAGS(USERTAGOPTION,USERTAGTYPE) \
|
|
|
|
case USERTAGOPTION: \
|
|
|
|
if (!OptionValueIdentical(option,¤t[ixVal],&new[ixVal])) \
|
|
|
|
{ \
|
|
|
|
*changedUserTags |= USERTAGTYPE; \
|
|
|
|
ret = yes; \
|
|
|
|
} \
|
|
|
|
break
|
|
|
|
TEST_USERTAGS(TidyInlineTags,tagtype_inline);
|
|
|
|
TEST_USERTAGS(TidyBlockTags,tagtype_block);
|
|
|
|
TEST_USERTAGS(TidyEmptyTags,tagtype_empty);
|
|
|
|
TEST_USERTAGS(TidyPreTags,tagtype_pre);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ReparseTagDecls( TidyDocImpl* doc, uint changedUserTags )
|
|
|
|
{
|
|
|
|
#define REPARSE_USERTAGS(USERTAGOPTION,USERTAGTYPE) \
|
|
|
|
if ( changedUserTags & USERTAGTYPE ) \
|
|
|
|
{ \
|
|
|
|
TY_(FreeDeclaredTags)( doc, USERTAGTYPE ); \
|
|
|
|
ReparseTagType( doc, USERTAGOPTION ); \
|
|
|
|
}
|
|
|
|
REPARSE_USERTAGS(TidyInlineTags,tagtype_inline);
|
|
|
|
REPARSE_USERTAGS(TidyBlockTags,tagtype_block);
|
|
|
|
REPARSE_USERTAGS(TidyEmptyTags,tagtype_empty);
|
|
|
|
REPARSE_USERTAGS(TidyPreTags,tagtype_pre);
|
|
|
|
}
|
|
|
|
|
2017-10-06 20:14:54 +00:00
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
/* Returns the option id of the replacement Tidy option for optName. Because
|
|
|
|
** an option might not have a replacement (0, TidyUnknownOption), a return
|
|
|
|
** value of N_TIDY_OPTIONS indicates an error, i.e., that the option isn't
|
|
|
|
** in the deprecated list.
|
|
|
|
*/
|
2017-10-06 20:14:54 +00:00
|
|
|
static TidyOptionId getOptionReplacement( ctmbstr optName )
|
|
|
|
{
|
|
|
|
uint i = 0;
|
|
|
|
ctmbstr testName;
|
|
|
|
while ( (testName = deprecatedOptions[i].name) )
|
|
|
|
{
|
|
|
|
if ( TY_(tmbstrcasecmp)( optName, testName ) == 0 )
|
|
|
|
return deprecatedOptions[i].replacementId;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return N_TIDY_OPTIONS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
/* Indicates whether or not optName is deprecated */
|
2017-10-06 20:14:54 +00:00
|
|
|
static Bool isOptionDeprecated( ctmbstr optName )
|
|
|
|
{
|
|
|
|
return getOptionReplacement( optName ) != N_TIDY_OPTIONS;
|
|
|
|
}
|
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
/* Forward declaration */
|
2017-10-06 20:14:54 +00:00
|
|
|
Bool GetPickListValue();
|
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
/* Aubstitute the new option for the deprecated one. */
|
2017-10-06 20:14:54 +00:00
|
|
|
static Bool subDeprecatedOption( TidyDocImpl* doc, ctmbstr oldName, ctmbstr oldValue)
|
|
|
|
{
|
|
|
|
TidyOptionId newOptId = getOptionReplacement( oldName );
|
2017-10-07 15:04:18 +00:00
|
|
|
ctmbstr newName = TY_(getOption)( newOptId )->name;
|
|
|
|
TidyDoc tdoc = tidyImplToDoc( doc );
|
2017-10-06 20:14:54 +00:00
|
|
|
|
|
|
|
if ( newOptId == TidyUnknownOption )
|
|
|
|
{
|
2017-10-07 15:04:18 +00:00
|
|
|
TY_(Report)( doc, NULL, NULL, OPTION_REMOVED, oldName );
|
2017-10-06 20:14:54 +00:00
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
/********************/
|
|
|
|
/* `show-body-only` */
|
|
|
|
/********************/
|
2017-10-06 20:14:54 +00:00
|
|
|
if ( TY_(tmbstrcasecmp)( oldName, "show-body-only" ) == 0 )
|
|
|
|
{
|
|
|
|
uint value;
|
|
|
|
|
|
|
|
/* `show-body-only` used to use the boolPicks */
|
|
|
|
if ( GetPickListValue( oldValue, boolPicks, &value ) )
|
|
|
|
{
|
|
|
|
if ( value == TidyNoState )
|
|
|
|
{
|
2017-10-07 15:04:18 +00:00
|
|
|
TY_(Report)( doc, NULL, NULL, OPTION_REMOVED_UNAPPLIED, oldName, newName );
|
2017-10-06 20:14:54 +00:00
|
|
|
TY_(SetOptionBool)( doc, newOptId, value );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TY_(SetOptionBool)( doc, newOptId, value );
|
2017-10-07 15:04:18 +00:00
|
|
|
ctmbstr val = tidyOptGetCurrPick( tdoc, newOptId );
|
|
|
|
TY_(Report)( doc, NULL, NULL, OPTION_REMOVED_APPLIED, oldName, newName, val );
|
2017-10-06 20:14:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-07 15:04:18 +00:00
|
|
|
printf("-->Report bad argument %s\n", oldValue);
|
2017-10-06 20:14:54 +00:00
|
|
|
}
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
|
2017-10-07 15:04:18 +00:00
|
|
|
|
2017-10-06 20:14:54 +00:00
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
void TY_(ResetConfigToDefault)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
uint ixVal;
|
|
|
|
const TidyOptionImpl* option = option_defs;
|
|
|
|
TidyOptionValue* value = &doc->config.value[ 0 ];
|
|
|
|
for ( ixVal=0; ixVal < N_TIDY_OPTIONS; ++option, ++ixVal )
|
|
|
|
{
|
|
|
|
TidyOptionValue dflt;
|
|
|
|
assert( ixVal == (uint) option->id );
|
|
|
|
GetOptionDefault( option, &dflt );
|
|
|
|
CopyOptionValue( doc, option, &value[ixVal], &dflt );
|
|
|
|
}
|
|
|
|
TY_(FreeDeclaredTags)( doc, tagtype_null );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TY_(TakeConfigSnapshot)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
uint ixVal;
|
|
|
|
const TidyOptionImpl* option = option_defs;
|
|
|
|
const TidyOptionValue* value = &doc->config.value[ 0 ];
|
|
|
|
TidyOptionValue* snap = &doc->config.snapshot[ 0 ];
|
|
|
|
|
|
|
|
AdjustConfig( doc ); /* Make sure it's consistent */
|
|
|
|
for ( ixVal=0; ixVal < N_TIDY_OPTIONS; ++option, ++ixVal )
|
|
|
|
{
|
|
|
|
assert( ixVal == (uint) option->id );
|
|
|
|
CopyOptionValue( doc, option, &snap[ixVal], &value[ixVal] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TY_(ResetConfigToSnapshot)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
uint ixVal;
|
|
|
|
const TidyOptionImpl* option = option_defs;
|
|
|
|
TidyOptionValue* value = &doc->config.value[ 0 ];
|
|
|
|
const TidyOptionValue* snap = &doc->config.snapshot[ 0 ];
|
|
|
|
uint changedUserTags;
|
2017-03-13 17:45:32 +00:00
|
|
|
Bool needReparseTagsDecls = NeedReparseTagDecls( doc, value, snap,
|
2011-11-17 02:44:16 +00:00
|
|
|
&changedUserTags );
|
|
|
|
|
|
|
|
for ( ixVal=0; ixVal < N_TIDY_OPTIONS; ++option, ++ixVal )
|
|
|
|
{
|
|
|
|
assert( ixVal == (uint) option->id );
|
|
|
|
CopyOptionValue( doc, option, &value[ixVal], &snap[ixVal] );
|
|
|
|
}
|
|
|
|
if ( needReparseTagsDecls )
|
|
|
|
ReparseTagDecls( doc, changedUserTags );
|
|
|
|
}
|
|
|
|
|
|
|
|
void TY_(CopyConfig)( TidyDocImpl* docTo, TidyDocImpl* docFrom )
|
|
|
|
{
|
|
|
|
if ( docTo != docFrom )
|
|
|
|
{
|
|
|
|
uint ixVal;
|
|
|
|
const TidyOptionImpl* option = option_defs;
|
|
|
|
const TidyOptionValue* from = &docFrom->config.value[ 0 ];
|
|
|
|
TidyOptionValue* to = &docTo->config.value[ 0 ];
|
|
|
|
uint changedUserTags;
|
2017-03-13 17:45:32 +00:00
|
|
|
Bool needReparseTagsDecls = NeedReparseTagDecls( docTo, to, from,
|
2011-11-17 02:44:16 +00:00
|
|
|
&changedUserTags );
|
|
|
|
|
|
|
|
TY_(TakeConfigSnapshot)( docTo );
|
|
|
|
for ( ixVal=0; ixVal < N_TIDY_OPTIONS; ++option, ++ixVal )
|
|
|
|
{
|
|
|
|
assert( ixVal == (uint) option->id );
|
|
|
|
CopyOptionValue( docTo, option, &to[ixVal], &from[ixVal] );
|
|
|
|
}
|
|
|
|
if ( needReparseTagsDecls )
|
|
|
|
ReparseTagDecls( docTo, changedUserTags );
|
|
|
|
AdjustConfig( docTo ); /* Make sure it's consistent */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
|
|
|
/* Debug accessor functions will be type-safe and assert option type match */
|
|
|
|
ulong TY_(_cfgGet)( TidyDocImpl* doc, TidyOptionId optId )
|
|
|
|
{
|
|
|
|
assert( optId < N_TIDY_OPTIONS );
|
|
|
|
return doc->config.value[ optId ].v;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TY_(_cfgGetBool)( TidyDocImpl* doc, TidyOptionId optId )
|
|
|
|
{
|
|
|
|
ulong val = TY_(_cfgGet)( doc, optId );
|
|
|
|
const TidyOptionImpl* opt = &option_defs[ optId ];
|
|
|
|
assert( opt && opt->type == TidyBoolean );
|
|
|
|
return (Bool) val;
|
|
|
|
}
|
|
|
|
|
|
|
|
TidyTriState TY_(_cfgGetAutoBool)( TidyDocImpl* doc, TidyOptionId optId )
|
|
|
|
{
|
|
|
|
ulong val = TY_(_cfgGet)( doc, optId );
|
|
|
|
const TidyOptionImpl* opt = &option_defs[ optId ];
|
|
|
|
assert( opt && opt->type == TidyInteger
|
2017-05-13 15:39:13 +00:00
|
|
|
&& opt->parser == ParsePickList );
|
2011-11-17 02:44:16 +00:00
|
|
|
return (TidyTriState) val;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctmbstr TY_(_cfgGetString)( TidyDocImpl* doc, TidyOptionId optId )
|
|
|
|
{
|
|
|
|
const TidyOptionImpl* opt;
|
|
|
|
|
|
|
|
assert( optId < N_TIDY_OPTIONS );
|
|
|
|
opt = &option_defs[ optId ];
|
|
|
|
assert( opt && opt->type == TidyString );
|
|
|
|
return doc->config.value[ optId ].p;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static tchar GetC( TidyConfigImpl* config )
|
|
|
|
{
|
|
|
|
if ( config->cfgIn )
|
|
|
|
return TY_(ReadChar)( config->cfgIn );
|
|
|
|
return EndOfStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
static tchar FirstChar( TidyConfigImpl* config )
|
|
|
|
{
|
|
|
|
config->c = GetC( config );
|
|
|
|
return config->c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static tchar AdvanceChar( TidyConfigImpl* config )
|
|
|
|
{
|
|
|
|
if ( config->c != EndOfStream )
|
|
|
|
config->c = GetC( config );
|
|
|
|
return config->c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static tchar SkipWhite( TidyConfigImpl* config )
|
|
|
|
{
|
|
|
|
while ( TY_(IsWhite)(config->c) && !TY_(IsNewline)(config->c) )
|
|
|
|
config->c = GetC( config );
|
|
|
|
return config->c;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip until end of line
|
|
|
|
static tchar SkipToEndofLine( TidyConfigImpl* config )
|
|
|
|
{
|
|
|
|
while ( config->c != EndOfStream )
|
|
|
|
{
|
|
|
|
config->c = GetC( config );
|
|
|
|
if ( config->c == '\n' || config->c == '\r' )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return config->c;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
skip over line continuations
|
|
|
|
to start of next property
|
|
|
|
*/
|
|
|
|
static uint NextProperty( TidyConfigImpl* config )
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
/* skip to end of line */
|
|
|
|
while ( config->c != '\n' && config->c != '\r' && config->c != EndOfStream )
|
|
|
|
config->c = GetC( config );
|
|
|
|
|
|
|
|
/* treat \r\n \r or \n as line ends */
|
|
|
|
if ( config->c == '\r' )
|
|
|
|
config->c = GetC( config );
|
|
|
|
|
|
|
|
if ( config->c == '\n' )
|
|
|
|
config->c = GetC( config );
|
|
|
|
}
|
|
|
|
while ( TY_(IsWhite)(config->c) ); /* line continuation? */
|
|
|
|
|
|
|
|
return config->c;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Todd Lewis contributed this code for expanding
|
|
|
|
~/foo or ~your/foo according to $HOME and your
|
|
|
|
user name. This will work partially on any system
|
|
|
|
which defines $HOME. Support for ~user/foo will
|
|
|
|
work on systems that support getpwnam(userid),
|
|
|
|
namely Unix/Linux.
|
|
|
|
*/
|
|
|
|
static ctmbstr ExpandTilde( TidyDocImpl* doc, ctmbstr filename )
|
|
|
|
{
|
|
|
|
char *home_dir = NULL;
|
|
|
|
|
|
|
|
if ( !filename )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if ( filename[0] != '~' )
|
|
|
|
return filename;
|
|
|
|
|
|
|
|
if (filename[1] == '/')
|
|
|
|
{
|
|
|
|
home_dir = getenv("HOME");
|
|
|
|
if ( home_dir )
|
|
|
|
++filename;
|
|
|
|
}
|
|
|
|
#ifdef SUPPORT_GETPWNAM
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct passwd *passwd = NULL;
|
|
|
|
ctmbstr s = filename + 1;
|
|
|
|
tmbstr t;
|
|
|
|
|
|
|
|
while ( *s && *s != '/' )
|
|
|
|
s++;
|
|
|
|
|
2017-09-30 21:06:19 +00:00
|
|
|
if ( (t = TidyDocAlloc(doc, s - filename)) )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
|
|
|
memcpy(t, filename+1, s-filename-1);
|
|
|
|
t[s-filename-1] = 0;
|
|
|
|
|
|
|
|
passwd = getpwnam(t);
|
|
|
|
|
|
|
|
TidyDocFree(doc, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( passwd )
|
|
|
|
{
|
|
|
|
filename = s;
|
|
|
|
home_dir = passwd->pw_dir;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* SUPPORT_GETPWNAM */
|
|
|
|
|
|
|
|
if ( home_dir )
|
|
|
|
{
|
|
|
|
uint len = TY_(tmbstrlen)(filename) + TY_(tmbstrlen)(home_dir) + 1;
|
|
|
|
tmbstr p = (tmbstr)TidyDocAlloc( doc, len );
|
|
|
|
TY_(tmbstrcpy)( p, home_dir );
|
|
|
|
TY_(tmbstrcat)( p, filename );
|
|
|
|
return (ctmbstr) p;
|
|
|
|
}
|
|
|
|
return (ctmbstr) filename;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TIDY_CALL tidyFileExists( TidyDoc tdoc, ctmbstr filename )
|
|
|
|
{
|
|
|
|
TidyDocImpl* doc = tidyDocToImpl( tdoc );
|
|
|
|
ctmbstr fname = (tmbstr) ExpandTilde( doc, filename );
|
|
|
|
#ifndef NO_ACCESS_SUPPORT
|
|
|
|
Bool exists = ( access(fname, 0) == 0 );
|
|
|
|
#else
|
|
|
|
Bool exists;
|
|
|
|
/* at present */
|
|
|
|
FILE* fin = fopen(fname, "r");
|
|
|
|
if (fin != NULL)
|
|
|
|
fclose(fin);
|
|
|
|
exists = ( fin != NULL );
|
|
|
|
#endif
|
|
|
|
if ( fname != filename )
|
|
|
|
TidyDocFree( doc, (tmbstr) fname );
|
|
|
|
return exists;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int TY_(ParseConfigFile)( TidyDocImpl* doc, ctmbstr file )
|
|
|
|
{
|
|
|
|
return TY_(ParseConfigFileEnc)( doc, file, "ascii" );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* open the file and parse its contents
|
|
|
|
*/
|
|
|
|
int TY_(ParseConfigFileEnc)( TidyDocImpl* doc, ctmbstr file, ctmbstr charenc )
|
|
|
|
{
|
2017-10-03 17:56:31 +00:00
|
|
|
enum { tidy_max_name = 64 };
|
2011-11-17 02:44:16 +00:00
|
|
|
uint opterrs = doc->optionErrors;
|
|
|
|
tmbstr fname = (tmbstr) ExpandTilde( doc, file );
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
FILE* fin = fopen( fname, "r" );
|
|
|
|
int enc = TY_(CharEncodingId)( doc, charenc );
|
|
|
|
|
|
|
|
if ( fin == NULL || enc < 0 )
|
|
|
|
{
|
2017-09-04 15:24:48 +00:00
|
|
|
TY_(ReportFileError)( doc, fname, FILE_CANT_OPEN_CFG );
|
2011-11-17 02:44:16 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tchar c;
|
|
|
|
cfg->cfgIn = TY_(FileInput)( doc, fin, enc );
|
|
|
|
c = FirstChar( cfg );
|
|
|
|
|
|
|
|
for ( c = SkipWhite(cfg); c != EndOfStream; c = NextProperty(cfg) )
|
|
|
|
{
|
|
|
|
uint ix = 0;
|
2017-10-03 17:56:31 +00:00
|
|
|
tmbchar name[ tidy_max_name ] = {0};
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
/* // or # start a comment */
|
|
|
|
if ( c == '/' || c == '#' )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
while ( ix < sizeof(name)-1 && c != '\n' && c != EndOfStream && c != ':' )
|
|
|
|
{
|
|
|
|
name[ ix++ ] = (tmbchar) c; /* Option names all ASCII */
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( c == ':' )
|
|
|
|
{
|
2017-10-07 15:20:57 +00:00
|
|
|
Bool isDeprecated = isOptionDeprecated( name );
|
2011-11-17 02:44:16 +00:00
|
|
|
const TidyOptionImpl* option = TY_(lookupOption)( name );
|
|
|
|
c = AdvanceChar( cfg );
|
2017-10-07 15:20:57 +00:00
|
|
|
if ( option && !isDeprecated )
|
2011-11-17 02:44:16 +00:00
|
|
|
option->parser( doc, option );
|
|
|
|
else
|
|
|
|
{
|
2017-10-07 15:20:57 +00:00
|
|
|
if ( (NULL != doc->pOptCallback) || (NULL != doc->pConfigCallback) || isDeprecated )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tmbchar buf[8192];
|
|
|
|
uint i = 0;
|
|
|
|
tchar delim = 0;
|
|
|
|
Bool waswhite = yes;
|
2017-10-07 15:20:57 +00:00
|
|
|
Bool response = no;
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
tchar c = SkipWhite( cfg );
|
|
|
|
|
|
|
|
if ( c == '"' || c == '\'' )
|
|
|
|
{
|
|
|
|
delim = c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && c != '\r' && c != '\n' )
|
|
|
|
{
|
|
|
|
if ( delim && c == delim )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ( TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
if ( waswhite )
|
|
|
|
{
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
c = ' ';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
waswhite = no;
|
|
|
|
|
|
|
|
buf[i++] = (tmbchar) c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
buf[i] = '\0';
|
2017-08-26 16:47:18 +00:00
|
|
|
|
|
|
|
if ( doc->pOptCallback )
|
2017-10-07 15:20:57 +00:00
|
|
|
response = (*doc->pOptCallback)( name, buf );
|
2017-08-26 16:47:18 +00:00
|
|
|
|
|
|
|
if ( doc->pConfigCallback )
|
|
|
|
response = response && (*doc->pConfigCallback)( tidyImplToDoc(doc), name, buf );
|
|
|
|
|
2017-10-07 15:20:57 +00:00
|
|
|
if ( !response && isDeprecated )
|
|
|
|
response = subDeprecatedOption( doc, name, buf);
|
|
|
|
|
|
|
|
if ( response == no )
|
2011-11-17 02:44:16 +00:00
|
|
|
TY_(ReportUnknownOption)( doc, name );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TY_(ReportUnknownOption)( doc, name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TY_(freeFileSource)(&cfg->cfgIn->source, yes);
|
|
|
|
TY_(freeStreamIn)( cfg->cfgIn );
|
|
|
|
cfg->cfgIn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( fname != (tmbstr) file )
|
|
|
|
TidyDocFree( doc, fname );
|
|
|
|
|
|
|
|
AdjustConfig( doc );
|
|
|
|
|
|
|
|
/* any new config errors? If so, return warning status. */
|
|
|
|
return (doc->optionErrors > opterrs ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns false if unknown option, missing parameter,
|
|
|
|
** or option doesn't use parameter
|
|
|
|
*/
|
|
|
|
Bool TY_(ParseConfigOption)( TidyDocImpl* doc, ctmbstr optnam, ctmbstr optval )
|
|
|
|
{
|
|
|
|
const TidyOptionImpl* option = TY_(lookupOption)( optnam );
|
2017-10-06 20:14:54 +00:00
|
|
|
Bool isDeprecated = isOptionDeprecated( optnam );
|
|
|
|
Bool status = ( option != NULL ) && !isDeprecated;
|
2011-11-17 02:44:16 +00:00
|
|
|
if ( !status )
|
|
|
|
{
|
2017-10-06 20:14:54 +00:00
|
|
|
/* Unknown or deprecated, so check to see if the user application
|
|
|
|
wants to deal with it first. */
|
2011-11-17 02:44:16 +00:00
|
|
|
if (NULL != doc->pOptCallback)
|
|
|
|
status = (*doc->pOptCallback)( optnam, optval );
|
2017-10-06 13:41:54 +00:00
|
|
|
if (NULL != doc->pConfigCallback )
|
|
|
|
status = status && (*doc->pConfigCallback)( tidyImplToDoc(doc), optnam, optval );
|
2017-10-06 20:14:54 +00:00
|
|
|
if (!status && isDeprecated)
|
|
|
|
status = subDeprecatedOption( doc, optnam, optval);
|
2011-11-17 02:44:16 +00:00
|
|
|
if (!status)
|
|
|
|
TY_(ReportUnknownOption)( doc, optnam );
|
|
|
|
}
|
2017-10-06 20:14:54 +00:00
|
|
|
else
|
2011-11-17 02:44:16 +00:00
|
|
|
status = TY_(ParseConfigValue)( doc, option->id, optval );
|
2017-10-06 20:14:54 +00:00
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns false if unknown option, missing parameter,
|
|
|
|
** or option doesn't use parameter
|
|
|
|
*/
|
|
|
|
Bool TY_(ParseConfigValue)( TidyDocImpl* doc, TidyOptionId optId, ctmbstr optval )
|
|
|
|
{
|
2017-03-08 15:29:41 +00:00
|
|
|
const TidyOptionImpl* option = NULL;
|
|
|
|
/* #472: fail status if there is a NULL parser. @ralfjunker */
|
|
|
|
Bool status = ( optId < N_TIDY_OPTIONS
|
|
|
|
&& (option = option_defs + optId)->parser
|
|
|
|
&& optval != NULL );
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
if ( !status )
|
2017-03-08 15:29:41 +00:00
|
|
|
if ( option )
|
|
|
|
TY_(ReportBadArgument)(doc, option->name);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If optId < N_TIDY_OPTIONS then option remains unassigned,
|
|
|
|
and we have to fall back to an ugly error message. */
|
2017-03-09 17:44:48 +00:00
|
|
|
enum { sizeBuf = 11 }; /* uint_max is 10 characters */
|
|
|
|
char buffer[sizeBuf];
|
2017-03-08 15:29:41 +00:00
|
|
|
TY_(tmbsnprintf(buffer, sizeBuf, "%u", optId));
|
|
|
|
TY_(ReportUnknownOption(doc, buffer));
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
TidyBuffer inbuf; /* Set up input source */
|
|
|
|
tidyBufInitWithAllocator( &inbuf, doc->allocator );
|
|
|
|
tidyBufAttach( &inbuf, (byte*)optval, TY_(tmbstrlen)(optval)+1 );
|
2011-07-26 12:31:36 +00:00
|
|
|
if (optId == TidyOutFile)
|
|
|
|
doc->config.cfgIn = TY_(BufferInput)( doc, &inbuf, RAW );
|
|
|
|
else
|
2017-02-23 15:28:19 +00:00
|
|
|
doc->config.cfgIn = TY_(BufferInput)( doc, &inbuf, RAW ); /* Issue #468 - Was ASCII! */
|
2011-11-17 02:44:16 +00:00
|
|
|
doc->config.c = GetC( &doc->config );
|
|
|
|
|
|
|
|
status = option->parser( doc, option );
|
|
|
|
|
|
|
|
TY_(freeStreamIn)(doc->config.cfgIn); /* Release input source */
|
|
|
|
doc->config.cfgIn = NULL;
|
|
|
|
tidyBufDetach( &inbuf );
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ensure that char encodings are self consistent */
|
|
|
|
Bool TY_(AdjustCharEncoding)( TidyDocImpl* doc, int encoding )
|
|
|
|
{
|
|
|
|
int outenc = -1;
|
|
|
|
int inenc = -1;
|
|
|
|
|
|
|
|
switch( encoding )
|
|
|
|
{
|
|
|
|
case MACROMAN:
|
|
|
|
inenc = MACROMAN;
|
|
|
|
outenc = ASCII;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WIN1252:
|
|
|
|
inenc = WIN1252;
|
|
|
|
outenc = ASCII;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IBM858:
|
|
|
|
inenc = IBM858;
|
|
|
|
outenc = ASCII;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASCII:
|
|
|
|
inenc = LATIN1;
|
|
|
|
outenc = ASCII;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LATIN0:
|
|
|
|
inenc = LATIN0;
|
|
|
|
outenc = ASCII;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RAW:
|
|
|
|
case LATIN1:
|
|
|
|
case UTF8:
|
|
|
|
#ifndef NO_NATIVE_ISO2022_SUPPORT
|
|
|
|
case ISO2022:
|
|
|
|
#endif
|
|
|
|
|
|
|
|
case UTF16LE:
|
|
|
|
case UTF16BE:
|
|
|
|
case UTF16:
|
|
|
|
case SHIFTJIS:
|
|
|
|
case BIG5:
|
|
|
|
inenc = outenc = encoding;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( inenc >= 0 )
|
|
|
|
{
|
|
|
|
TY_(SetOptionInt)( doc, TidyCharEncoding, encoding );
|
|
|
|
TY_(SetOptionInt)( doc, TidyInCharEncoding, inenc );
|
|
|
|
TY_(SetOptionInt)( doc, TidyOutCharEncoding, outenc );
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ensure that config is self consistent */
|
|
|
|
void AdjustConfig( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
if ( cfgBool(doc, TidyEncloseBlockText) )
|
|
|
|
TY_(SetOptionBool)( doc, TidyEncloseBodyText, yes );
|
|
|
|
|
|
|
|
if ( cfgAutoBool(doc, TidyIndentContent) == TidyNoState )
|
|
|
|
TY_(SetOptionInt)( doc, TidyIndentSpaces, 0 );
|
|
|
|
|
|
|
|
/* disable wrapping */
|
|
|
|
if ( cfg(doc, TidyWrapLen) == 0 )
|
|
|
|
TY_(SetOptionInt)( doc, TidyWrapLen, 0x7FFFFFFF );
|
|
|
|
|
|
|
|
/* Word 2000 needs o:p to be declared as inline */
|
|
|
|
if ( cfgBool(doc, TidyWord2000) )
|
|
|
|
{
|
|
|
|
doc->config.defined_tags |= tagtype_inline;
|
|
|
|
TY_(DefineTag)( doc, tagtype_inline, "o:p" );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* #480701 disable XHTML output flag if both output-xhtml and xml input are set */
|
|
|
|
if ( cfgBool(doc, TidyXmlTags) )
|
|
|
|
TY_(SetOptionBool)( doc, TidyXhtmlOut, no );
|
|
|
|
|
|
|
|
/* XHTML is written in lower case */
|
|
|
|
if ( cfgBool(doc, TidyXhtmlOut) )
|
|
|
|
{
|
|
|
|
TY_(SetOptionBool)( doc, TidyXmlOut, yes );
|
|
|
|
TY_(SetOptionBool)( doc, TidyUpperCaseTags, no );
|
2017-05-12 11:30:20 +00:00
|
|
|
TY_(SetOptionInt)( doc, TidyUpperCaseAttrs, no );
|
2011-11-17 02:44:16 +00:00
|
|
|
/* TY_(SetOptionBool)( doc, TidyXmlPIs, yes ); */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if XML in, then XML out */
|
|
|
|
if ( cfgBool(doc, TidyXmlTags) )
|
|
|
|
{
|
|
|
|
TY_(SetOptionBool)( doc, TidyXmlOut, yes );
|
|
|
|
TY_(SetOptionBool)( doc, TidyXmlPIs, yes );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* #427837 - fix by Dave Raggett 02 Jun 01
|
|
|
|
** generate <?xml version="1.0" encoding="iso-8859-1"?>
|
|
|
|
** if the output character encoding is Latin-1 etc.
|
|
|
|
*/
|
|
|
|
if ( cfg(doc, TidyOutCharEncoding) != ASCII &&
|
|
|
|
cfg(doc, TidyOutCharEncoding) != UTF8 &&
|
|
|
|
cfg(doc, TidyOutCharEncoding) != UTF16 &&
|
|
|
|
cfg(doc, TidyOutCharEncoding) != UTF16BE &&
|
|
|
|
cfg(doc, TidyOutCharEncoding) != UTF16LE &&
|
|
|
|
cfg(doc, TidyOutCharEncoding) != RAW &&
|
|
|
|
cfgBool(doc, TidyXmlOut) )
|
|
|
|
{
|
|
|
|
TY_(SetOptionBool)( doc, TidyXmlDecl, yes );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XML requires end tags */
|
|
|
|
if ( cfgBool(doc, TidyXmlOut) )
|
|
|
|
{
|
|
|
|
/* XML requires a BOM on output if using UTF-16 encoding */
|
|
|
|
ulong enc = cfg( doc, TidyOutCharEncoding );
|
|
|
|
if ( enc == UTF16LE || enc == UTF16BE || enc == UTF16 )
|
|
|
|
TY_(SetOptionInt)( doc, TidyOutputBOM, yes );
|
2017-10-03 16:26:38 +00:00
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
TY_(SetOptionBool)( doc, TidyQuoteAmpersand, yes );
|
2017-05-03 22:16:03 +00:00
|
|
|
TY_(SetOptionBool)( doc, TidyOmitOptionalTags, no );
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-23 02:14:59 +00:00
|
|
|
|
2017-09-23 11:30:17 +00:00
|
|
|
/* Coordinates Config update and Attributes data for priority attributes, as
|
|
|
|
a service to ParseList().
|
|
|
|
*/
|
2017-09-23 02:14:59 +00:00
|
|
|
void TY_(DeclarePriorityAttrib)( TidyDocImpl* doc, TidyOptionId optId, ctmbstr name )
|
|
|
|
{
|
|
|
|
ctmbstr prvval = cfgStr( doc, optId );
|
|
|
|
tmbstr catval = NULL;
|
|
|
|
ctmbstr theval = name;
|
|
|
|
if ( prvval )
|
|
|
|
{
|
|
|
|
uint len = TY_(tmbstrlen)(name) + TY_(tmbstrlen)(prvval) + 3;
|
|
|
|
catval = TY_(tmbstrndup)( doc->allocator, prvval, len );
|
|
|
|
TY_(tmbstrcat)( catval, ", " );
|
|
|
|
TY_(tmbstrcat)( catval, name );
|
|
|
|
theval = catval;
|
|
|
|
}
|
|
|
|
|
|
|
|
TY_(DefinePriorityAttribute)( doc, name );
|
|
|
|
SetOptionValue( doc, optId, theval );
|
|
|
|
if ( catval )
|
|
|
|
TidyDocFree( doc, catval );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* a space or comma separated list of attribute names */
|
2017-09-23 11:30:17 +00:00
|
|
|
Bool ParseList( TidyDocImpl* doc, const TidyOptionImpl* option )
|
2017-09-23 02:14:59 +00:00
|
|
|
{
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tmbchar buf[1024];
|
2017-09-23 11:30:17 +00:00
|
|
|
uint i = 0, nItems = 0;
|
2017-09-23 02:14:59 +00:00
|
|
|
uint c = SkipWhite( cfg );
|
|
|
|
|
|
|
|
SetOptionValue( doc, option->id, NULL );
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (c == ' ' || c == '\t' || c == ',')
|
|
|
|
{
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( c == '\r' || c == '\n' )
|
|
|
|
{
|
|
|
|
uint c2 = AdvanceChar( cfg );
|
|
|
|
if ( c == '\r' && c2 == '\n' )
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
else
|
|
|
|
c = c2;
|
|
|
|
|
|
|
|
if ( !TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
buf[i] = 0;
|
|
|
|
TY_(UngetChar)( c, cfg->cfgIn );
|
|
|
|
TY_(UngetChar)( '\n', cfg->cfgIn );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && !TY_(IsWhite)(c) && c != ',' )
|
|
|
|
{
|
|
|
|
buf[i++] = (tmbchar) c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[i] = '\0';
|
|
|
|
if (i == 0) /* Skip empty attribute definition. Possible when */
|
|
|
|
continue; /* there is a trailing space on the line. */
|
|
|
|
|
|
|
|
/* add attribute to array */
|
2017-09-23 11:30:17 +00:00
|
|
|
switch ( option->id )
|
|
|
|
{
|
|
|
|
case TidyPriorityAttributes:
|
|
|
|
TY_(DeclarePriorityAttrib)( doc, option->id, buf );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-09-23 02:14:59 +00:00
|
|
|
i = 0;
|
2017-09-23 11:30:17 +00:00
|
|
|
++nItems;
|
2017-09-23 02:14:59 +00:00
|
|
|
}
|
|
|
|
while ( c != EndOfStream );
|
|
|
|
|
|
|
|
if ( i > 0 )
|
2017-09-23 11:30:17 +00:00
|
|
|
switch ( option->id )
|
|
|
|
{
|
|
|
|
case TidyPriorityAttributes:
|
|
|
|
TY_(DeclarePriorityAttrib)( doc, option->id, buf );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2017-09-23 02:14:59 +00:00
|
|
|
|
2017-09-23 11:30:17 +00:00
|
|
|
return ( nItems > 0 );
|
2017-09-23 02:14:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
/* unsigned integers */
|
|
|
|
Bool ParseInt( TidyDocImpl* doc, const TidyOptionImpl* entry )
|
|
|
|
{
|
|
|
|
ulong number = 0;
|
|
|
|
Bool digits = no;
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tchar c = SkipWhite( cfg );
|
|
|
|
|
|
|
|
while ( TY_(IsDigit)(c) )
|
|
|
|
{
|
|
|
|
number = c - '0' + (10 * number);
|
|
|
|
digits = yes;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !digits )
|
|
|
|
TY_(ReportBadArgument)( doc, entry->name );
|
|
|
|
else
|
|
|
|
TY_(SetOptionInt)( doc, entry->id, number );
|
|
|
|
return digits;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* a string excluding whitespace */
|
2017-02-18 23:14:51 +00:00
|
|
|
Bool FUNC_UNUSED ParseName( TidyDocImpl* doc, const TidyOptionImpl* option )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
|
|
|
tmbchar buf[ 1024 ] = {0};
|
|
|
|
uint i = 0;
|
|
|
|
uint c = SkipWhite( &doc->config );
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && !TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
buf[i++] = (tmbchar) c;
|
|
|
|
c = AdvanceChar( &doc->config );
|
|
|
|
}
|
|
|
|
buf[i] = 0;
|
|
|
|
|
|
|
|
if ( i == 0 )
|
|
|
|
TY_(ReportBadArgument)( doc, option->name );
|
|
|
|
else
|
|
|
|
SetOptionValue( doc, option->id, buf );
|
|
|
|
return ( i > 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* #508936 - CSS class naming for -clean option */
|
|
|
|
Bool ParseCSS1Selector( TidyDocImpl* doc, const TidyOptionImpl* option )
|
|
|
|
{
|
|
|
|
char buf[256] = {0};
|
|
|
|
uint i = 0;
|
|
|
|
uint c = SkipWhite( &doc->config );
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && !TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
buf[i++] = (tmbchar) c;
|
|
|
|
c = AdvanceChar( &doc->config );
|
|
|
|
}
|
|
|
|
buf[i] = '\0';
|
|
|
|
|
2015-11-26 03:21:48 +00:00
|
|
|
if ( i == 0 ) {
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
else if ( !TY_(IsCSS1Selector)(buf) ) {
|
2011-11-17 02:44:16 +00:00
|
|
|
TY_(ReportBadArgument)( doc, option->name );
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[i++] = '-'; /* Make sure any escaped Unicode is terminated */
|
|
|
|
buf[i] = 0; /* so valid class names are generated after */
|
|
|
|
/* Tidy appends last digits. */
|
|
|
|
|
|
|
|
SetOptionValue( doc, option->id, buf );
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
|
2017-10-06 20:14:54 +00:00
|
|
|
|
|
|
|
/* Given a string, return the picklist value from an arbitrary picklist. */
|
|
|
|
Bool GetPickListValue( ctmbstr value, PickListItems* pickList, uint *result )
|
2017-05-08 20:14:35 +00:00
|
|
|
{
|
|
|
|
const PickListItem *item = NULL;
|
|
|
|
uint ix = 0;
|
2017-10-06 20:14:54 +00:00
|
|
|
|
|
|
|
while ( (item = &(*pickList)[ ix ]) && item->label )
|
2017-05-08 20:14:35 +00:00
|
|
|
{
|
|
|
|
ctmbstr input;
|
|
|
|
uint i = 0;
|
|
|
|
while ( ( input = &(*item->inputs[i]) ) )
|
|
|
|
{
|
2017-10-06 20:14:54 +00:00
|
|
|
if (TY_(tmbstrcasecmp)(value, input) == 0 )
|
2017-05-08 20:14:35 +00:00
|
|
|
{
|
|
|
|
*result = ix;
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
++ix;
|
|
|
|
}
|
2017-10-06 20:14:54 +00:00
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-06 20:14:54 +00:00
|
|
|
/* A general parser for anything using pick lists. This provides the engine to
|
|
|
|
determine the proper option value, and can be used by parsers in addition to
|
|
|
|
ParsePickList that require special handling.
|
|
|
|
*/
|
|
|
|
Bool GetParsePickListValue( TidyDocImpl* doc, const TidyOptionImpl* entry, uint *result )
|
|
|
|
{
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tchar c = SkipWhite( cfg );
|
|
|
|
tmbchar work[ 16 ] = {0};
|
|
|
|
tmbstr cp = work, end = work + sizeof(work);
|
|
|
|
|
|
|
|
while ( c!=EndOfStream && cp < end && !TY_(IsWhite)(c) && c != '\r' && c != '\n' )
|
|
|
|
{
|
|
|
|
*cp++ = (tmbchar) c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( GetPickListValue( work, entry->pickList, result ) != yes )
|
|
|
|
{
|
|
|
|
TY_(ReportBadArgument)( doc, entry->name );
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-08 20:14:35 +00:00
|
|
|
/* A general parser for anything using pick lists that don't require special
|
|
|
|
handling.
|
|
|
|
*/
|
|
|
|
Bool ParsePickList( TidyDocImpl* doc, const TidyOptionImpl* entry )
|
|
|
|
{
|
|
|
|
uint value;
|
|
|
|
|
|
|
|
if ( GetParsePickListValue( doc, entry, &value ) )
|
|
|
|
{
|
|
|
|
if ( entry->type == TidyBoolean )
|
|
|
|
TY_(SetOptionBool)( doc, entry->id, value );
|
|
|
|
else if ( entry->type == TidyInteger )
|
|
|
|
TY_(SetOptionInt)( doc, entry->id, value );
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
|
|
|
|
TY_(ReportBadArgument)( doc, entry->name );
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-15 13:06:52 +00:00
|
|
|
/*\
|
|
|
|
* 20150515 - support using tabs instead of spaces - Issue #108
|
|
|
|
* Sets the indent character to a tab if on, and set indent space count to 1
|
|
|
|
* and sets indent character to a space if off.
|
2017-05-08 20:14:35 +00:00
|
|
|
\*/
|
2015-05-15 13:06:52 +00:00
|
|
|
Bool ParseTabs( TidyDocImpl* doc, const TidyOptionImpl* entry )
|
|
|
|
{
|
2017-05-08 20:14:35 +00:00
|
|
|
uint flag = 0;
|
|
|
|
Bool status = GetParsePickListValue( doc, entry, &flag );
|
|
|
|
|
2015-05-15 13:06:52 +00:00
|
|
|
if ( status ) {
|
|
|
|
Bool tabs = flag != 0 ? yes : no;
|
|
|
|
TY_(SetOptionBool)( doc, entry->id, tabs );
|
|
|
|
if (tabs) {
|
|
|
|
TY_(SetOptionInt)( doc, TidyIndentSpaces, 1 );
|
|
|
|
} else {
|
|
|
|
/* optional - TY_(ResetOptionToDefault)( doc, TidyIndentSpaces ); */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
/* Coordinates Config update and Tags data */
|
2017-03-13 17:45:32 +00:00
|
|
|
void TY_(DeclareUserTag)( TidyDocImpl* doc, TidyOptionId optId,
|
2011-11-17 02:44:16 +00:00
|
|
|
UserTagType tagType, ctmbstr name )
|
|
|
|
{
|
|
|
|
ctmbstr prvval = cfgStr( doc, optId );
|
|
|
|
tmbstr catval = NULL;
|
|
|
|
ctmbstr theval = name;
|
|
|
|
if ( prvval )
|
|
|
|
{
|
|
|
|
uint len = TY_(tmbstrlen)(name) + TY_(tmbstrlen)(prvval) + 3;
|
|
|
|
catval = TY_(tmbstrndup)( doc->allocator, prvval, len );
|
|
|
|
TY_(tmbstrcat)( catval, ", " );
|
|
|
|
TY_(tmbstrcat)( catval, name );
|
|
|
|
theval = catval;
|
|
|
|
}
|
|
|
|
TY_(DefineTag)( doc, tagType, name );
|
|
|
|
SetOptionValue( doc, optId, theval );
|
|
|
|
if ( catval )
|
|
|
|
TidyDocFree( doc, catval );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* a space or comma separated list of tag names */
|
|
|
|
Bool ParseTagNames( TidyDocImpl* doc, const TidyOptionImpl* option )
|
|
|
|
{
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tmbchar buf[1024];
|
|
|
|
uint i = 0, nTags = 0;
|
|
|
|
uint c = SkipWhite( cfg );
|
|
|
|
UserTagType ttyp = tagtype_null;
|
|
|
|
|
|
|
|
switch ( option->id )
|
|
|
|
{
|
2017-03-13 17:45:32 +00:00
|
|
|
case TidyInlineTags: ttyp = tagtype_inline; break;
|
|
|
|
case TidyBlockTags: ttyp = tagtype_block; break;
|
|
|
|
case TidyEmptyTags: ttyp = tagtype_empty; break;
|
|
|
|
case TidyPreTags: ttyp = tagtype_pre; break;
|
|
|
|
case TidyCustomTags: ttyp = cfg(doc, TidyUseCustomTags); break;
|
|
|
|
default:
|
|
|
|
TY_(ReportUnknownOption)( doc, option->name );
|
|
|
|
return no;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetOptionValue( doc, option->id, NULL );
|
|
|
|
TY_(FreeDeclaredTags)( doc, ttyp );
|
|
|
|
cfg->defined_tags |= ttyp;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (c == ' ' || c == '\t' || c == ',')
|
|
|
|
{
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( c == '\r' || c == '\n' )
|
|
|
|
{
|
|
|
|
uint c2 = AdvanceChar( cfg );
|
|
|
|
if ( c == '\r' && c2 == '\n' )
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
else
|
|
|
|
c = c2;
|
|
|
|
|
|
|
|
if ( !TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
buf[i] = 0;
|
|
|
|
TY_(UngetChar)( c, cfg->cfgIn );
|
|
|
|
TY_(UngetChar)( '\n', cfg->cfgIn );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
if ( c == '\n' )
|
|
|
|
{
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
if ( !TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
buf[i] = 0;
|
|
|
|
TY_(UngetChar)( c, cfg->cfgIn );
|
|
|
|
TY_(UngetChar)( '\n', cfg->cfgIn );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && !TY_(IsWhite)(c) && c != ',' )
|
|
|
|
{
|
|
|
|
buf[i++] = (tmbchar) c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[i] = '\0';
|
|
|
|
if (i == 0) /* Skip empty tag definition. Possible when */
|
|
|
|
continue; /* there is a trailing space on the line. */
|
|
|
|
|
|
|
|
/* add tag to dictionary */
|
2017-03-13 17:45:32 +00:00
|
|
|
TY_(DeclareUserTag)( doc, option->id, ttyp, buf );
|
2011-11-17 02:44:16 +00:00
|
|
|
i = 0;
|
|
|
|
++nTags;
|
|
|
|
}
|
|
|
|
while ( c != EndOfStream );
|
|
|
|
|
|
|
|
if ( i > 0 )
|
2017-03-13 17:45:32 +00:00
|
|
|
TY_(DeclareUserTag)( doc, option->id, ttyp, buf );
|
2011-11-17 02:44:16 +00:00
|
|
|
return ( nTags > 0 );
|
|
|
|
}
|
|
|
|
|
2017-09-23 02:14:59 +00:00
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
/* a string including whitespace */
|
|
|
|
/* munges whitespace sequences */
|
|
|
|
Bool ParseString( TidyDocImpl* doc, const TidyOptionImpl* option )
|
|
|
|
{
|
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tmbchar buf[8192];
|
|
|
|
uint i = 0;
|
|
|
|
tchar delim = 0;
|
|
|
|
Bool waswhite = yes;
|
|
|
|
|
|
|
|
tchar c = SkipWhite( cfg );
|
|
|
|
|
|
|
|
if ( c == '"' || c == '\'' )
|
|
|
|
{
|
|
|
|
delim = c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && c != '\r' && c != '\n' )
|
|
|
|
{
|
|
|
|
if ( delim && c == delim )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ( TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
if ( waswhite )
|
|
|
|
{
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
c = ' ';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
waswhite = no;
|
|
|
|
|
|
|
|
buf[i++] = (tmbchar) c;
|
|
|
|
c = AdvanceChar( cfg );
|
|
|
|
}
|
|
|
|
buf[i] = '\0';
|
|
|
|
|
|
|
|
SetOptionValue( doc, option->id, buf );
|
|
|
|
return yes;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool ParseCharEnc( TidyDocImpl* doc, const TidyOptionImpl* option )
|
|
|
|
{
|
|
|
|
tmbchar buf[64] = {0};
|
|
|
|
uint i = 0;
|
|
|
|
int enc = ASCII;
|
|
|
|
Bool validEncoding = yes;
|
|
|
|
tchar c = SkipWhite( &doc->config );
|
|
|
|
|
|
|
|
while ( i < sizeof(buf)-2 && c != EndOfStream && !TY_(IsWhite)(c) )
|
|
|
|
{
|
|
|
|
buf[i++] = (tmbchar) TY_(ToLower)( c );
|
|
|
|
c = AdvanceChar( &doc->config );
|
|
|
|
}
|
|
|
|
buf[i] = 0;
|
|
|
|
|
|
|
|
enc = TY_(CharEncodingId)( doc, buf );
|
|
|
|
|
|
|
|
if ( enc < 0 )
|
|
|
|
{
|
|
|
|
validEncoding = no;
|
|
|
|
TY_(ReportBadArgument)( doc, option->name );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TY_(SetOptionInt)( doc, option->id, enc );
|
|
|
|
|
|
|
|
if ( validEncoding && option->id == TidyCharEncoding )
|
|
|
|
TY_(AdjustCharEncoding)( doc, enc );
|
|
|
|
return validEncoding;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int TY_(CharEncodingId)( TidyDocImpl* ARG_UNUSED(doc), ctmbstr charenc )
|
|
|
|
{
|
|
|
|
int enc = TY_(GetCharEncodingFromOptName)( charenc );
|
|
|
|
return enc;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctmbstr TY_(CharEncodingName)( int encoding )
|
|
|
|
{
|
|
|
|
ctmbstr encodingName = TY_(GetEncodingNameFromTidyId)(encoding);
|
|
|
|
|
|
|
|
if (!encodingName)
|
|
|
|
encodingName = "unknown";
|
|
|
|
|
|
|
|
return encodingName;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctmbstr TY_(CharEncodingOptName)( int encoding )
|
|
|
|
{
|
|
|
|
ctmbstr encodingName = TY_(GetEncodingOptNameFromTidyId)(encoding);
|
|
|
|
|
|
|
|
if (!encodingName)
|
|
|
|
encodingName = "unknown";
|
|
|
|
|
|
|
|
return encodingName;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2012-03-15 05:11:01 +00:00
|
|
|
doctype: html5 | omit | auto | strict | loose | <fpi>
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
where the fpi is a string similar to
|
|
|
|
|
|
|
|
"-//ACME//DTD HTML 3.14159//EN"
|
|
|
|
*/
|
|
|
|
Bool ParseDocType( TidyDocImpl* doc, const TidyOptionImpl* option )
|
|
|
|
{
|
|
|
|
Bool status = yes;
|
2017-05-08 20:14:35 +00:00
|
|
|
uint value;
|
2011-11-17 02:44:16 +00:00
|
|
|
TidyConfigImpl* cfg = &doc->config;
|
|
|
|
tchar c = SkipWhite( cfg );
|
|
|
|
|
|
|
|
/* "-//ACME//DTD HTML 3.14159//EN" or similar */
|
|
|
|
|
|
|
|
if ( c == '"' || c == '\'' )
|
|
|
|
{
|
|
|
|
status = ParseString(doc, option);
|
|
|
|
if (status)
|
2017-05-08 20:14:35 +00:00
|
|
|
{
|
2011-11-17 02:44:16 +00:00
|
|
|
TY_(SetOptionInt)( doc, TidyDoctypeMode, TidyDoctypeUser );
|
2017-05-08 20:14:35 +00:00
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
return status;
|
|
|
|
}
|
2017-05-08 20:14:35 +00:00
|
|
|
|
|
|
|
if ( (status = GetParsePickListValue( doc, option, &value ) ) )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2017-05-08 20:14:35 +00:00
|
|
|
TY_(SetOptionInt)( doc, TidyDoctypeMode, value );
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TY_(ReportBadArgument)( doc, option->name );
|
|
|
|
}
|
2017-05-08 20:14:35 +00:00
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use TidyOptionId as iterator.
|
|
|
|
** Send index of 1st option after TidyOptionUnknown as start of list.
|
|
|
|
*/
|
|
|
|
TidyIterator TY_(getOptionList)( TidyDocImpl* ARG_UNUSED(doc) )
|
|
|
|
{
|
|
|
|
return (TidyIterator) (size_t)1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this item is last valid option.
|
|
|
|
** If so, zero out iterator.
|
|
|
|
*/
|
|
|
|
const TidyOptionImpl* TY_(getNextOption)( TidyDocImpl* ARG_UNUSED(doc),
|
|
|
|
TidyIterator* iter )
|
|
|
|
{
|
2017-03-09 21:04:03 +00:00
|
|
|
const TidyOptionImpl* option = NULL;
|
|
|
|
size_t optId;
|
|
|
|
assert( iter != NULL );
|
|
|
|
optId = (size_t) *iter;
|
|
|
|
if ( optId > TidyUnknownOption && optId < N_TIDY_OPTIONS )
|
|
|
|
{
|
|
|
|
option = &option_defs[ optId ];
|
2017-03-08 01:11:31 +00:00
|
|
|
optId++;
|
2017-03-09 21:04:03 +00:00
|
|
|
}
|
|
|
|
*iter = (TidyIterator) ( optId < N_TIDY_OPTIONS ? optId : (size_t)0 );
|
|
|
|
return option;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Use a 1-based array index as iterator: 0 == end-of-list
|
|
|
|
*/
|
|
|
|
TidyIterator TY_(getOptionPickList)( const TidyOptionImpl* option )
|
|
|
|
{
|
|
|
|
size_t ix = 0;
|
|
|
|
if ( option && option->pickList )
|
|
|
|
ix = 1;
|
|
|
|
return (TidyIterator) ix;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctmbstr TY_(getNextOptionPick)( const TidyOptionImpl* option,
|
|
|
|
TidyIterator* iter )
|
|
|
|
{
|
|
|
|
size_t ix;
|
|
|
|
ctmbstr val = NULL;
|
2017-05-08 20:14:35 +00:00
|
|
|
const PickListItem *item= NULL;
|
2011-11-17 02:44:16 +00:00
|
|
|
assert( option!=NULL && iter != NULL );
|
|
|
|
|
|
|
|
ix = (size_t) *iter;
|
2017-05-08 20:14:35 +00:00
|
|
|
|
|
|
|
if ( option->pickList )
|
|
|
|
{
|
|
|
|
if ( ix > 0 && ix < TIDY_PL_SIZE && option->pickList )
|
|
|
|
{
|
|
|
|
item = &(*option->pickList)[ ix-1 ];
|
|
|
|
val = item->label;
|
|
|
|
}
|
|
|
|
item = &(*option->pickList)[ ix ];
|
|
|
|
*iter = (TidyIterator) ( val && item->label ? ix + 1 : (size_t)0 );
|
|
|
|
}
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int WriteOptionString( const TidyOptionImpl* option,
|
|
|
|
ctmbstr sval, StreamOut* out )
|
|
|
|
{
|
|
|
|
ctmbstr cp = option->name;
|
|
|
|
while ( *cp )
|
|
|
|
TY_(WriteChar)( *cp++, out );
|
|
|
|
TY_(WriteChar)( ':', out );
|
|
|
|
TY_(WriteChar)( ' ', out );
|
|
|
|
cp = sval;
|
|
|
|
while ( *cp )
|
|
|
|
TY_(WriteChar)( *cp++, out );
|
|
|
|
TY_(WriteChar)( '\n', out );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int WriteOptionInt( const TidyOptionImpl* option, uint ival, StreamOut* out )
|
|
|
|
{
|
|
|
|
tmbchar sval[ 32 ] = {0};
|
|
|
|
TY_(tmbsnprintf)(sval, sizeof(sval), "%u", ival );
|
|
|
|
return WriteOptionString( option, sval, out );
|
|
|
|
}
|
|
|
|
|
|
|
|
static int WriteOptionBool( const TidyOptionImpl* option, Bool bval, StreamOut* out )
|
|
|
|
{
|
|
|
|
ctmbstr sval = bval ? "yes" : "no";
|
|
|
|
return WriteOptionString( option, sval, out );
|
|
|
|
}
|
|
|
|
|
|
|
|
static int WriteOptionPick( const TidyOptionImpl* option, uint ival, StreamOut* out )
|
|
|
|
{
|
2017-05-08 20:14:35 +00:00
|
|
|
uint ix = 0;
|
|
|
|
const PickListItem *item = NULL;
|
|
|
|
|
|
|
|
if ( option-> pickList )
|
|
|
|
{
|
|
|
|
while ( (item = &(*option->pickList)[ ix ]) && item->label && ix<ival )
|
|
|
|
{
|
|
|
|
++ix;
|
|
|
|
}
|
|
|
|
if ( ix==ival && item->label )
|
|
|
|
return WriteOptionString( option, item->label, out );
|
|
|
|
}
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TY_(ConfigDiffThanSnapshot)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
int diff = memcmp( &doc->config.value, &doc->config.snapshot,
|
|
|
|
N_TIDY_OPTIONS * sizeof(uint) );
|
|
|
|
return ( diff != 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
Bool TY_(ConfigDiffThanDefault)( TidyDocImpl* doc )
|
|
|
|
{
|
|
|
|
Bool diff = no;
|
|
|
|
const TidyOptionImpl* option = option_defs + 1;
|
|
|
|
const TidyOptionValue* val = doc->config.value;
|
|
|
|
for ( /**/; !diff && option && option->name; ++option, ++val )
|
|
|
|
{
|
|
|
|
diff = !OptionValueEqDefault( option, val );
|
|
|
|
}
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int SaveConfigToStream( TidyDocImpl* doc, StreamOut* out )
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
const TidyOptionImpl* option;
|
|
|
|
for ( option=option_defs+1; 0==rc && option && option->name; ++option )
|
|
|
|
{
|
|
|
|
const TidyOptionValue* val = &doc->config.value[ option->id ];
|
|
|
|
if ( option->parser == NULL )
|
|
|
|
continue;
|
|
|
|
if ( OptionValueEqDefault( option, val ) && option->id != TidyDoctype)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( option->id == TidyDoctype ) /* Special case */
|
|
|
|
{
|
|
|
|
ulong dtmode = cfg( doc, TidyDoctypeMode );
|
|
|
|
if ( dtmode == TidyDoctypeUser )
|
|
|
|
{
|
|
|
|
tmbstr t;
|
|
|
|
|
|
|
|
/* add 2 double quotes */
|
|
|
|
if (( t = (tmbstr)TidyDocAlloc( doc, TY_(tmbstrlen)( val->p ) + 2 ) ))
|
|
|
|
{
|
|
|
|
t[0] = '\"'; t[1] = 0;
|
|
|
|
|
|
|
|
TY_(tmbstrcat)( t, val->p );
|
|
|
|
TY_(tmbstrcat)( t, "\"" );
|
|
|
|
rc = WriteOptionString( option, t, out );
|
|
|
|
|
|
|
|
TidyDocFree( doc, t );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( dtmode == option_defs[TidyDoctypeMode].dflt )
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
rc = WriteOptionPick( option, dtmode, out );
|
|
|
|
}
|
2017-05-08 20:14:35 +00:00
|
|
|
else if ( option->pickList)
|
2011-11-17 02:44:16 +00:00
|
|
|
rc = WriteOptionPick( option, val->v, out );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch ( option->type )
|
|
|
|
{
|
|
|
|
case TidyString:
|
|
|
|
rc = WriteOptionString( option, val->p, out );
|
|
|
|
break;
|
|
|
|
case TidyInteger:
|
|
|
|
rc = WriteOptionInt( option, val->v, out );
|
|
|
|
break;
|
|
|
|
case TidyBoolean:
|
|
|
|
rc = WriteOptionBool( option, val->v ? yes : no, out );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TY_(SaveConfigFile)( TidyDocImpl* doc, ctmbstr cfgfil )
|
|
|
|
{
|
|
|
|
int status = -1;
|
|
|
|
StreamOut* out = NULL;
|
|
|
|
uint outenc = cfg( doc, TidyOutCharEncoding );
|
|
|
|
uint nl = cfg( doc, TidyNewline );
|
|
|
|
FILE* fout = fopen( cfgfil, "wb" );
|
|
|
|
if ( fout )
|
|
|
|
{
|
|
|
|
out = TY_(FileOutput)( doc, fout, outenc, nl );
|
|
|
|
status = SaveConfigToStream( doc, out );
|
|
|
|
fclose( fout );
|
|
|
|
TidyDocFree( doc, out );
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TY_(SaveConfigSink)( TidyDocImpl* doc, TidyOutputSink* sink )
|
|
|
|
{
|
|
|
|
uint outenc = cfg( doc, TidyOutCharEncoding );
|
|
|
|
uint nl = cfg( doc, TidyNewline );
|
|
|
|
StreamOut* out = TY_(UserOutput)( doc, sink, outenc, nl );
|
|
|
|
int status = SaveConfigToStream( doc, out );
|
|
|
|
TidyDocFree( doc, out );
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* local variables:
|
|
|
|
* mode: c
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* eval: (c-set-offset 'substatement-open 0)
|
|
|
|
* end:
|
|
|
|
*/
|