2017-04-04 18:07:20 +00:00
|
|
|
/***************************************************************************//**
|
|
|
|
* @file
|
|
|
|
* HTML TidyLib command line driver.
|
|
|
|
*
|
|
|
|
* This console application utilizing LibTidy in order to offer a complete
|
|
|
|
* console application offering all of the features of LibTidy.
|
|
|
|
*
|
|
|
|
* @author HTACG, et al (consult git log)
|
|
|
|
*
|
|
|
|
* @copyright
|
|
|
|
* Copyright (c) 1998-2017 World Wide Web Consortium (Massachusetts
|
|
|
|
* Institute of Technology, European Research Consortium for Informatics
|
|
|
|
* and Mathematics, Keio University) and HTACG.
|
|
|
|
* @par
|
|
|
|
* All Rights Reserved.
|
|
|
|
* @par
|
|
|
|
* See `tidy.h` for the complete license.
|
|
|
|
*
|
|
|
|
* @date Additional updates: consult git log
|
|
|
|
******************************************************************************/
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
#include "tidy.h"
|
2017-04-04 18:07:20 +00:00
|
|
|
#include "tidybuffio.h"
|
|
|
|
#include "locale.h" /* for determing and setting locale */
|
2016-01-15 04:06:15 +00:00
|
|
|
#if defined(_WIN32)
|
2017-04-04 18:07:20 +00:00
|
|
|
#include <windows.h> /* Force console to UTF8. */
|
2016-01-15 04:06:15 +00:00
|
|
|
#endif
|
2014-08-03 18:52:10 +00:00
|
|
|
#if !defined(NDEBUG) && defined(_MSC_VER)
|
2014-08-03 18:33:29 +00:00
|
|
|
#include "sprtf.h"
|
2017-09-17 14:27:17 +00:00
|
|
|
#ifdef _CRTDBG_MAP_ALLOC
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <crtdbg.h>
|
|
|
|
#endif
|
2014-08-03 18:33:29 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef SPRTF
|
|
|
|
#define SPRTF printf
|
|
|
|
#endif
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Tidy will send errors to this file, which will be stderr later. */
|
|
|
|
static FILE* errout = NULL;
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2016-01-29 03:11:53 +00:00
|
|
|
#if defined(_WIN32)
|
2017-04-04 18:07:20 +00:00
|
|
|
/** On Windows, we will store the original code page here. */
|
2016-01-29 03:11:53 +00:00
|
|
|
static uint win_cp; /* original Windows code page */
|
2017-05-30 16:15:25 +00:00
|
|
|
#if (defined(_MSC_VER) && (_MSC_VER < 1900))
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#endif
|
2016-01-29 03:11:53 +00:00
|
|
|
#endif
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** @defgroup console_application Tidy Console Application
|
|
|
|
** @copydoc tidy.c
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* MARK: - Miscellaneous Utilities */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup utilities_misc Miscellaneous Utilities
|
|
|
|
** This group contains general utilities used in the console application.
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Indicates whether or not two filenames are the same.
|
|
|
|
** @result Returns a Bool indicating whether the filenames are the same.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static Bool samefile(ctmbstr filename1, /**< First filename */
|
|
|
|
ctmbstr filename2 /**< Second filename */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
|
|
|
#if FILENAMES_CASE_SENSITIVE
|
2016-01-25 12:58:55 +00:00
|
|
|
return ( strcmp( filename1, filename2 ) == 0 );
|
2011-11-17 02:44:16 +00:00
|
|
|
#else
|
2016-01-25 12:58:55 +00:00
|
|
|
return ( strcasecmp( filename1, filename2 ) == 0 );
|
2011-11-17 02:44:16 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Handles exit cleanup.
|
2016-01-29 03:11:53 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void tidy_cleanup( void )
|
2016-01-29 03:11:53 +00:00
|
|
|
{
|
|
|
|
#if defined(_WIN32)
|
|
|
|
/* Restore original Windows code page. */
|
|
|
|
SetConsoleOutputCP(win_cp);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** Exits with an error in the event of an out of memory condition.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
static void outOfMemory(void)
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
fprintf(stderr, "%s", tidyLocalizedString(TC_STRING_OUT_OF_MEMORY));
|
|
|
|
exit(1);
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Create a new, allocated string with a format and arguments.
|
|
|
|
** @result Returns a new, allocated string that you must free.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static tmbstr stringWithFormat(const ctmbstr fmt, /**< The format string. */
|
|
|
|
... /**< Variable arguments. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
va_list argList;
|
|
|
|
tmbstr result = NULL;
|
|
|
|
int len = 0;
|
|
|
|
|
|
|
|
va_start(argList, fmt);
|
|
|
|
len = vsnprintf( result, 0, fmt, argList );
|
|
|
|
va_end(argList);
|
|
|
|
|
|
|
|
if (!(result = malloc( len + 1) ))
|
|
|
|
outOfMemory();
|
|
|
|
|
|
|
|
va_start(argList, fmt);
|
|
|
|
vsnprintf( result, len + 1, fmt, argList);
|
|
|
|
va_end(argList);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end utilities_misc group */
|
|
|
|
/* MARK: - Output Helping Functions */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup utilities_output Output Helping Functions
|
|
|
|
** This group functions that aid the formatting of output.
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Used by `print1Column`, `print2Columns` and `print3Columns` to manage
|
|
|
|
** wrapping text within columns.
|
|
|
|
** @result The pointer to the next part of the string to output.
|
|
|
|
*/
|
|
|
|
static const char *cutToWhiteSpace(const char *s, /**< starting point of desired string to output */
|
|
|
|
uint offset, /**< column width desired */
|
|
|
|
char *sbuf /**< the buffer to output */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
if (!s)
|
|
|
|
{
|
|
|
|
sbuf[0] = '\0';
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else if (strlen(s) <= offset)
|
|
|
|
{
|
|
|
|
strcpy(sbuf,s);
|
|
|
|
sbuf[offset] = '\0';
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint j, l, n;
|
|
|
|
/* scan forward looking for newline */
|
|
|
|
j = 0;
|
|
|
|
while(j < offset && s[j] != '\n')
|
|
|
|
++j;
|
|
|
|
if ( j == offset ) {
|
|
|
|
/* scan backward looking for first space */
|
|
|
|
j = offset;
|
|
|
|
while(j && s[j] != ' ')
|
|
|
|
--j;
|
|
|
|
l = j;
|
|
|
|
n = j+1;
|
|
|
|
/* no white space */
|
|
|
|
if (j==0)
|
|
|
|
{
|
|
|
|
l = offset;
|
|
|
|
n = offset;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
l = j;
|
|
|
|
n = j+1;
|
|
|
|
}
|
|
|
|
strncpy(sbuf,s,l);
|
|
|
|
sbuf[l] = '\0';
|
|
|
|
return s+n;
|
|
|
|
}
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** Outputs one column of text.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void print1Column(const char* fmt, /**< The format string for formatting the output. */
|
|
|
|
uint l1, /**< The width of the column. */
|
|
|
|
const char *c1 /**< The content of the column. */
|
|
|
|
)
|
2016-01-15 04:06:15 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
const char *pc1=c1;
|
|
|
|
char *c1buf = (char *)malloc(l1+1);
|
|
|
|
if (!c1buf) outOfMemory();
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
pc1 = cutToWhiteSpace(pc1, l1, c1buf);
|
|
|
|
printf(fmt, c1buf[0] !='\0' ? c1buf : "");
|
|
|
|
} while (pc1);
|
|
|
|
free(c1buf);
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** Outputs two columns of text.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void print2Columns(const char* fmt, /**< The format string for formatting the output. */
|
|
|
|
uint l1, /**< The width of column 1. */
|
|
|
|
uint l2, /**< The width of column 2. */
|
|
|
|
const char *c1, /**< The contents of column 1. */
|
|
|
|
const char *c2 /**< The contents of column 2. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
const char *pc1=c1, *pc2=c2;
|
|
|
|
char *c1buf = (char *)malloc(l1+1);
|
|
|
|
char *c2buf = (char *)malloc(l2+1);
|
|
|
|
if (!c1buf) outOfMemory();
|
|
|
|
if (!c2buf) outOfMemory();
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
pc1 = cutToWhiteSpace(pc1, l1, c1buf);
|
|
|
|
pc2 = cutToWhiteSpace(pc2, l2, c2buf);
|
2017-04-04 18:07:20 +00:00
|
|
|
printf(fmt, l1, l1, c1buf[0]!='\0'?c1buf:"",
|
|
|
|
l2, l2, c2buf[0]!='\0'?c2buf:"");
|
2016-01-25 12:58:55 +00:00
|
|
|
} while (pc1 || pc2);
|
|
|
|
free(c1buf);
|
|
|
|
free(c2buf);
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** Outputs three columns of text.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void print3Columns(const char* fmt, /**< The three column format string. */
|
|
|
|
uint l1, /**< Width of column 1. */
|
|
|
|
uint l2, /**< Width of column 2. */
|
|
|
|
uint l3, /**< Width of column 3. */
|
|
|
|
const char *c1, /**< Content of column 1. */
|
|
|
|
const char *c2, /**< Content of column 2. */
|
|
|
|
const char *c3 /**< Content of column 3. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
const char *pc1=c1, *pc2=c2, *pc3=c3;
|
|
|
|
char *c1buf = (char *)malloc(l1+1);
|
|
|
|
char *c2buf = (char *)malloc(l2+1);
|
|
|
|
char *c3buf = (char *)malloc(l3+1);
|
|
|
|
if (!c1buf) outOfMemory();
|
|
|
|
if (!c2buf) outOfMemory();
|
|
|
|
if (!c3buf) outOfMemory();
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
pc1 = cutToWhiteSpace(pc1, l1, c1buf);
|
|
|
|
pc2 = cutToWhiteSpace(pc2, l2, c2buf);
|
|
|
|
pc3 = cutToWhiteSpace(pc3, l3, c3buf);
|
|
|
|
printf(fmt,
|
|
|
|
c1buf[0]!='\0'?c1buf:"",
|
|
|
|
c2buf[0]!='\0'?c2buf:"",
|
|
|
|
c3buf[0]!='\0'?c3buf:"");
|
|
|
|
} while (pc1 || pc2 || pc3);
|
|
|
|
free(c1buf);
|
|
|
|
free(c2buf);
|
|
|
|
free(c3buf);
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** Provides the `unknown option` output to the current errout.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void unknownOption(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
uint c /**< The unknown option. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
fprintf( errout, tidyLocalizedString( TC_STRING_UNKNOWN_OPTION ), (char)c );
|
|
|
|
fprintf( errout, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end utilities_output group */
|
|
|
|
/* MARK: - CLI Options Utilities */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup options_cli CLI Options Utilities
|
|
|
|
** These structures, arrays, declarations, and definitions are used throughout
|
|
|
|
** this console application.
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** @name Format strings and decorations used in output.
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const char helpfmt[] = " %-*.*s %-*.*s\n";
|
2016-01-15 04:06:15 +00:00
|
|
|
static const char helpul[] = "-----------------------------------------------------------------";
|
|
|
|
static const char fmt[] = "%-27.27s %-9.9s %-40.40s\n";
|
|
|
|
static const char ul[] = "=================================================================";
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} */
|
|
|
|
|
|
|
|
/** This enum is used to categorize the options for help output.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
CmdOptFileManip,
|
|
|
|
CmdOptCatFIRST = CmdOptFileManip,
|
|
|
|
CmdOptProcDir,
|
|
|
|
CmdOptCharEnc,
|
|
|
|
CmdOptMisc,
|
|
|
|
CmdOptXML,
|
|
|
|
CmdOptCatLAST
|
2011-11-17 02:44:16 +00:00
|
|
|
} CmdOptCategory;
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** This array contains headings that will be used in help ouput.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
static const struct {
|
2016-01-25 12:58:55 +00:00
|
|
|
ctmbstr mnemonic; /**< Used in XML as a class. */
|
|
|
|
uint key; /**< Key to fetch the localized string. */
|
2011-11-17 02:44:16 +00:00
|
|
|
} cmdopt_catname[] = {
|
2016-01-25 12:58:55 +00:00
|
|
|
{ "file-manip", TC_STRING_FILE_MANIP },
|
|
|
|
{ "process-directives", TC_STRING_PROCESS_DIRECTIVES },
|
|
|
|
{ "char-encoding", TC_STRING_CHAR_ENCODING },
|
|
|
|
{ "misc", TC_STRING_MISC },
|
|
|
|
{ "xml", TC_STRING_XML }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** The struct and subsequent array keep the help output structured
|
|
|
|
** because we _also_ output all of this stuff as as XML.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
typedef struct {
|
2016-01-25 12:58:55 +00:00
|
|
|
CmdOptCategory cat; /**< Category */
|
|
|
|
ctmbstr name1; /**< Name */
|
|
|
|
uint key; /**< Key to fetch the localized description. */
|
|
|
|
uint subKey; /**< Secondary substitution key. */
|
|
|
|
ctmbstr eqconfig; /**< Equivalent configuration option */
|
|
|
|
ctmbstr name2; /**< Name */
|
|
|
|
ctmbstr name3; /**< Name */
|
2011-11-17 02:44:16 +00:00
|
|
|
} CmdOptDesc;
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** All instances of %s will be substituted with localized string
|
|
|
|
** specified by the subKey field.
|
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
static const CmdOptDesc cmdopt_defs[] = {
|
2017-10-01 23:49:44 +00:00
|
|
|
{ CmdOptFileManip, "-output <%s>", TC_OPT_OUTPUT, TC_LABEL_FILE, "output-file: <%s>", "-o <%s>" },
|
|
|
|
{ CmdOptFileManip, "-config <%s>", TC_OPT_CONFIG, TC_LABEL_FILE, NULL },
|
|
|
|
{ CmdOptFileManip, "-file <%s>", TC_OPT_FILE, TC_LABEL_FILE, "error-file: <%s>", "-f <%s>" },
|
|
|
|
{ CmdOptFileManip, "-modify", TC_OPT_MODIFY, 0, "write-back: yes", "-m" },
|
|
|
|
{ CmdOptProcDir, "-indent", TC_OPT_INDENT, 0, "indent: auto", "-i" },
|
|
|
|
{ CmdOptProcDir, "-wrap <%s>", TC_OPT_WRAP, TC_LABEL_COL, "wrap: <%s>", "-w <%s>" },
|
|
|
|
{ CmdOptProcDir, "-upper", TC_OPT_UPPER, 0, "uppercase-tags: yes", "-u" },
|
|
|
|
{ CmdOptProcDir, "-clean", TC_OPT_CLEAN, 0, "clean: yes", "-c" },
|
|
|
|
{ CmdOptProcDir, "-bare", TC_OPT_BARE, 0, "bare: yes", "-b" },
|
|
|
|
{ CmdOptProcDir, "-gdoc", TC_OPT_GDOC, 0, "gdoc: yes", "-g" },
|
|
|
|
{ CmdOptProcDir, "-numeric", TC_OPT_NUMERIC, 0, "numeric-entities: yes", "-n" },
|
|
|
|
{ CmdOptProcDir, "-errors", TC_OPT_ERRORS, 0, "markup: no", "-e" },
|
|
|
|
{ CmdOptProcDir, "-quiet", TC_OPT_QUIET, 0, "quiet: yes", "-q" },
|
|
|
|
{ CmdOptProcDir, "-omit", TC_OPT_OMIT, 0, "omit-optional-tags: yes" },
|
|
|
|
{ CmdOptProcDir, "-xml", TC_OPT_XML, 0, "input-xml: yes" },
|
|
|
|
{ CmdOptProcDir, "-asxml", TC_OPT_ASXML, 0, "output-xhtml: yes", "-asxhtml" },
|
|
|
|
{ CmdOptProcDir, "-ashtml", TC_OPT_ASHTML, 0, "output-html: yes" },
|
|
|
|
{ CmdOptProcDir, "-access <%s>", TC_OPT_ACCESS, TC_LABEL_LEVL, "accessibility-check: <%s>" },
|
|
|
|
{ CmdOptCharEnc, "-raw", TC_OPT_RAW, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-ascii", TC_OPT_ASCII, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-latin0", TC_OPT_LATIN0, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-latin1", TC_OPT_LATIN1, 0, NULL },
|
2011-11-17 02:44:16 +00:00
|
|
|
#ifndef NO_NATIVE_ISO2022_SUPPORT
|
2017-10-01 23:49:44 +00:00
|
|
|
{ CmdOptCharEnc, "-iso2022", TC_OPT_ISO2022, 0, NULL },
|
2011-11-17 02:44:16 +00:00
|
|
|
#endif
|
2017-10-01 23:49:44 +00:00
|
|
|
{ CmdOptCharEnc, "-utf8", TC_OPT_UTF8, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-mac", TC_OPT_MAC, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-win1252", TC_OPT_WIN1252, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-ibm858", TC_OPT_IBM858, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-utf16le", TC_OPT_UTF16LE, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-utf16be", TC_OPT_UTF16BE, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-utf16", TC_OPT_UTF16, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-big5", TC_OPT_BIG5, 0, NULL },
|
|
|
|
{ CmdOptCharEnc, "-shiftjis", TC_OPT_SHIFTJIS, 0, NULL },
|
|
|
|
{ CmdOptMisc, "-version", TC_OPT_VERSION, 0, NULL, "-v" },
|
|
|
|
{ CmdOptMisc, "-help", TC_OPT_HELP, 0, NULL, "-h", "-?" },
|
|
|
|
{ CmdOptMisc, "-help-config", TC_OPT_HELPCFG, 0, NULL },
|
|
|
|
{ CmdOptMisc, "-help-env", TC_OPT_HELPENV, 0, NULL },
|
|
|
|
{ CmdOptMisc, "-show-config", TC_OPT_SHOWCFG, 0, NULL },
|
|
|
|
{ CmdOptMisc, "-export-config", TC_OPT_EXP_CFG, 0, NULL },
|
|
|
|
{ CmdOptMisc, "-export-default-config", TC_OPT_EXP_DEF, 0, NULL },
|
|
|
|
{ CmdOptMisc, "-help-option <%s>", TC_OPT_HELPOPT, TC_LABEL_OPT, NULL },
|
|
|
|
{ CmdOptMisc, "-language <%s>", TC_OPT_LANGUAGE, TC_LABEL_LANG, "language: <%s>" },
|
|
|
|
{ CmdOptXML, "-xml-help", TC_OPT_XMLHELP, 0, NULL },
|
|
|
|
{ CmdOptXML, "-xml-config", TC_OPT_XMLCFG, 0, NULL },
|
|
|
|
{ CmdOptXML, "-xml-strings", TC_OPT_XMLSTRG, 0, NULL },
|
|
|
|
{ CmdOptXML, "-xml-error-strings", TC_OPT_XMLERRS, 0, NULL },
|
|
|
|
{ CmdOptXML, "-xml-options-strings", TC_OPT_XMLOPTS, 0, NULL },
|
2016-01-25 12:58:55 +00:00
|
|
|
{ CmdOptMisc, NULL, 0, 0, NULL }
|
2011-11-17 02:44:16 +00:00
|
|
|
};
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Option names aren't localized, but the sample fields should be localized.
|
|
|
|
** For example, `<file>` should be `<archivo>` in Spanish.
|
|
|
|
** @param pos A CmdOptDesc array with fields that must be localized.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
|
|
|
static void localize_option_names( CmdOptDesc *pos)
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
ctmbstr fileString = tidyLocalizedString(pos->subKey);
|
|
|
|
pos->name1 = stringWithFormat(pos->name1, fileString);
|
|
|
|
if ( pos->name2 )
|
|
|
|
pos->name2 = stringWithFormat(pos->name2, fileString);
|
|
|
|
if ( pos->name3 )
|
|
|
|
pos->name3 = stringWithFormat(pos->name3, fileString);
|
2017-03-06 22:08:32 +00:00
|
|
|
if ( pos->eqconfig )
|
|
|
|
pos->eqconfig = stringWithFormat(pos->eqconfig, fileString);
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Escape a name for XML output. For example, `-output <file>` becomes
|
|
|
|
** `-output <file>` for use in XML.
|
|
|
|
** @param name The option name to escape.
|
|
|
|
** @result Returns an allocated string.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
static tmbstr get_escaped_name( ctmbstr name )
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
tmbstr escpName;
|
|
|
|
char aux[2];
|
|
|
|
uint len = 0;
|
|
|
|
ctmbstr c;
|
|
|
|
for(c=name; *c!='\0'; ++c)
|
|
|
|
switch(*c)
|
|
|
|
{
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
len += 4;
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
len += 6;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
len += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
escpName = (tmbstr)malloc(len+1);
|
|
|
|
if (!escpName) outOfMemory();
|
|
|
|
escpName[0] = '\0';
|
|
|
|
|
|
|
|
aux[1] = '\0';
|
|
|
|
for(c=name; *c!='\0'; ++c)
|
|
|
|
switch(*c)
|
|
|
|
{
|
|
|
|
case '<':
|
|
|
|
strcat(escpName, "<");
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
strcat(escpName, ">");
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
strcat(escpName, """);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
aux[0] = *c;
|
|
|
|
strcat(escpName, aux);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return escpName;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2014-08-06 17:22:28 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end CLI Options Definitions Utilities group */
|
|
|
|
/* MARK: - Configuration Options Utilities */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup utilities_cli_options Configuration Options Utilities
|
|
|
|
** Provide utilities to manipulate configuration options for output.
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2016-01-25 12:58:55 +00:00
|
|
|
|
|
|
|
|
2017-05-12 14:52:59 +00:00
|
|
|
/** Utility to determine if an option has a picklist.
|
2017-04-04 18:07:20 +00:00
|
|
|
** @param topt The option to check.
|
2017-05-12 14:52:59 +00:00
|
|
|
** @result Returns a Bool indicating whether the option has a picklist or not.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-05-12 14:52:59 +00:00
|
|
|
static Bool hasPickList( TidyOption topt )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyIterator pos;
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
if ( tidyOptGetType( topt ) != TidyInteger)
|
|
|
|
return no;
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
pos = tidyOptGetPickList( topt );
|
2017-05-12 14:52:59 +00:00
|
|
|
|
|
|
|
return tidyOptGetNextPick( topt, &pos ) != NULL;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Returns the configuration category name for the specified configuration
|
|
|
|
** category id. This will be used as an XML class attribute value.
|
|
|
|
** @param id The TidyConfigCategory for which to lookup the category name.
|
|
|
|
** @result Returns the configuration category, such as "diagnostics".
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
|
|
|
static ctmbstr ConfigCategoryName( TidyConfigCategory id )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2017-03-10 13:24:23 +00:00
|
|
|
if (id >= TidyMarkup && id <= TidyInternalCategory)
|
2017-02-13 19:29:47 +00:00
|
|
|
return tidyLocalizedString(id);
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
fprintf(stderr, tidyLocalizedString(TC_STRING_FATAL_ERROR), (int)id);
|
2016-01-15 04:06:15 +00:00
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
assert(0);
|
|
|
|
abort();
|
|
|
|
return "never_here"; /* only for the compiler warning */
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Structure maintains a description of a configuration ption.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
typedef struct {
|
2017-04-04 18:07:20 +00:00
|
|
|
ctmbstr name; /**< Name */
|
|
|
|
ctmbstr cat; /**< Category */
|
|
|
|
uint catid; /**< Category ID */
|
|
|
|
ctmbstr type; /**< "String, ... */
|
|
|
|
ctmbstr vals; /**< Potential values. If NULL, use an external function */
|
|
|
|
ctmbstr def; /**< default */
|
2016-01-25 12:58:55 +00:00
|
|
|
tmbchar tempdefs[80]; /**< storage for default such as integer */
|
2017-04-04 18:07:20 +00:00
|
|
|
Bool haveVals; /**< if yes, vals is valid */
|
2011-11-17 02:44:16 +00:00
|
|
|
} OptionDesc;
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** A type for a function pointer for a function used to print out options
|
|
|
|
** descriptions.
|
|
|
|
** @param TidyDoc The document.
|
|
|
|
** @param TidyOption The Tidy option.
|
|
|
|
** @param OptionDesc A pointer to the option description structure.
|
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
typedef void (*OptionFunc)( TidyDoc, TidyOption, OptionDesc * );
|
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Create OptionDesc "d" related to "opt"
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void GetOption(TidyDoc tdoc, /**< The tidy document. */
|
|
|
|
TidyOption topt, /**< The option to create a description for. */
|
|
|
|
OptionDesc *d /**< [out] The new option description. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyOptionId optId = tidyOptGetId( topt );
|
|
|
|
TidyOptionType optTyp = tidyOptGetType( topt );
|
|
|
|
|
|
|
|
d->name = tidyOptGetName( topt );
|
|
|
|
d->cat = ConfigCategoryName( tidyOptGetCategory( topt ) );
|
2017-03-10 13:24:23 +00:00
|
|
|
d->catid = tidyOptGetCategory( topt );
|
2016-01-25 12:58:55 +00:00
|
|
|
d->vals = NULL;
|
|
|
|
d->def = NULL;
|
|
|
|
d->haveVals = yes;
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/* Handle special cases first. */
|
2016-01-25 12:58:55 +00:00
|
|
|
switch ( optId )
|
|
|
|
{
|
|
|
|
case TidyDoctype:
|
|
|
|
d->type = "DocType";
|
|
|
|
d->vals = NULL;
|
|
|
|
{
|
|
|
|
ctmbstr sdef = NULL;
|
|
|
|
sdef = tidyOptGetCurrPick( tdoc, TidyDoctypeMode );
|
|
|
|
if ( !sdef || *sdef == '*' )
|
|
|
|
sdef = tidyOptGetValue( tdoc, TidyDoctype );
|
|
|
|
d->def = sdef;
|
|
|
|
}
|
|
|
|
break;
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
case TidyInlineTags:
|
|
|
|
case TidyBlockTags:
|
|
|
|
case TidyEmptyTags:
|
|
|
|
case TidyPreTags:
|
2017-05-12 14:52:59 +00:00
|
|
|
d->type = "Tag Names";
|
2016-01-25 12:58:55 +00:00
|
|
|
d->vals = "tagX, tagY, ...";
|
|
|
|
d->def = NULL;
|
|
|
|
break;
|
2017-09-23 11:53:57 +00:00
|
|
|
|
|
|
|
case TidyPriorityAttributes:
|
|
|
|
d->type = "Attributes Names";
|
|
|
|
d->vals = "attributeX, attributeY, ...";
|
|
|
|
d->def = NULL;
|
|
|
|
break;
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
case TidyCharEncoding:
|
|
|
|
case TidyInCharEncoding:
|
|
|
|
case TidyOutCharEncoding:
|
|
|
|
d->type = "Encoding";
|
|
|
|
d->def = tidyOptGetEncName( tdoc, optId );
|
|
|
|
if (!d->def)
|
|
|
|
d->def = "?";
|
|
|
|
d->vals = NULL;
|
|
|
|
break;
|
2017-03-13 17:45:32 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
/* General case will handle remaining */
|
|
|
|
default:
|
|
|
|
switch ( optTyp )
|
|
|
|
{
|
|
|
|
case TidyBoolean:
|
|
|
|
d->type = "Boolean";
|
|
|
|
d->def = tidyOptGetCurrPick( tdoc, optId );
|
|
|
|
break;
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
case TidyInteger:
|
2017-05-12 14:52:59 +00:00
|
|
|
if (hasPickList(topt))
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-05-12 14:52:59 +00:00
|
|
|
d->type = "Enum";
|
2016-01-25 12:58:55 +00:00
|
|
|
d->def = tidyOptGetCurrPick( tdoc, optId );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint idef;
|
|
|
|
d->type = "Integer";
|
|
|
|
if ( optId == TidyWrapLen )
|
|
|
|
d->vals = "0 (no wrapping), 1, 2, ...";
|
|
|
|
else
|
|
|
|
d->vals = "0, 1, 2, ...";
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
idef = tidyOptGetInt( tdoc, optId );
|
|
|
|
sprintf(d->tempdefs, "%u", idef);
|
|
|
|
d->def = d->tempdefs;
|
|
|
|
}
|
|
|
|
break;
|
2017-05-12 14:52:59 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
case TidyString:
|
|
|
|
d->type = "String";
|
|
|
|
d->vals = NULL;
|
|
|
|
d->haveVals = no;
|
|
|
|
d->def = tidyOptGetValue( tdoc, optId );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Array holding all options. Contains a trailing sentinel.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
typedef struct {
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyOption topt[N_TIDY_OPTIONS];
|
2011-11-17 02:44:16 +00:00
|
|
|
} AllOption_t;
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** A simple option comparator, used for sorting the options.
|
|
|
|
** @result Returns an integer indicating the result of the comparison.
|
|
|
|
*/
|
|
|
|
static int cmpOpt(const void* e1_, /**< Item A to compare. */
|
|
|
|
const void *e2_ /**< Item B to compare. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
const TidyOption* e1 = (const TidyOption*)e1_;
|
|
|
|
const TidyOption* e2 = (const TidyOption*)e2_;
|
|
|
|
return strcmp(tidyOptGetName(*e1), tidyOptGetName(*e2));
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Returns options sorted.
|
|
|
|
*/
|
|
|
|
static void getSortedOption(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
AllOption_t *tOption /**< [out] The list of options. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyIterator pos = tidyGetOptionList( tdoc );
|
|
|
|
uint i = 0;
|
|
|
|
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
TidyOption topt = tidyGetNextOption( tdoc, &pos );
|
|
|
|
tOption->topt[i] = topt;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
tOption->topt[i] = NULL; /* sentinel */
|
|
|
|
|
|
|
|
qsort(tOption->topt,
|
2017-03-09 21:04:03 +00:00
|
|
|
i, /* there are i items, not including the sentinal */
|
2016-01-25 12:58:55 +00:00
|
|
|
sizeof(tOption->topt[0]),
|
|
|
|
cmpOpt);
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** An iterator for the sorted options.
|
|
|
|
*/
|
|
|
|
static void ForEachSortedOption(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
OptionFunc OptionPrint /**< The printing function to be used. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
AllOption_t tOption;
|
|
|
|
const TidyOption *topt;
|
|
|
|
|
|
|
|
getSortedOption( tdoc, &tOption );
|
|
|
|
for( topt = tOption.topt; *topt; ++topt)
|
|
|
|
{
|
|
|
|
OptionDesc d;
|
|
|
|
|
|
|
|
GetOption( tdoc, *topt, &d );
|
|
|
|
(*OptionPrint)( tdoc, *topt, &d );
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** An iterator for the unsorted options.
|
|
|
|
*/
|
|
|
|
static void ForEachOption(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
OptionFunc OptionPrint /**< The printing function to be used. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyIterator pos = tidyGetOptionList( tdoc );
|
|
|
|
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
TidyOption topt = tidyGetNextOption( tdoc, &pos );
|
|
|
|
OptionDesc d;
|
|
|
|
|
|
|
|
GetOption( tdoc, topt, &d );
|
|
|
|
(*OptionPrint)( tdoc, topt, &d );
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Prints an option's allowed value as specified in its pick list.
|
|
|
|
** @param topt The Tidy option.
|
|
|
|
*/
|
2016-01-15 04:06:15 +00:00
|
|
|
static void PrintAllowedValuesFromPick( TidyOption topt )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyIterator pos = tidyOptGetPickList( topt );
|
|
|
|
Bool first = yes;
|
|
|
|
ctmbstr def;
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = no;
|
|
|
|
else
|
|
|
|
printf(", ");
|
|
|
|
def = tidyOptGetNextPick( topt, &pos );
|
|
|
|
printf("%s", def);
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Prints an option's allowed values.
|
|
|
|
*/
|
|
|
|
static void PrintAllowedValues(TidyOption topt, /**< The Tidy option. */
|
|
|
|
const OptionDesc *d /**< The OptionDesc for the option. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
if (d->vals)
|
|
|
|
printf( "%s", d->vals );
|
|
|
|
else
|
|
|
|
PrintAllowedValuesFromPick( topt );
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end utilities_cli_options group */
|
|
|
|
/* MARK: - Provide the -help Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_help Provide the -help Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Retrieve the option's name(s) from the structure as a single string,
|
|
|
|
** localizing the field values if application. For example, this might
|
|
|
|
** return `-output <file>, -o <file>`.
|
|
|
|
** @param pos A CmdOptDesc array item for which to get the names.
|
|
|
|
** @result Returns the name(s) for the option as a single string.
|
|
|
|
*/
|
|
|
|
static tmbstr get_option_names( const CmdOptDesc* pos )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
tmbstr name;
|
|
|
|
uint len;
|
|
|
|
CmdOptDesc localPos = *pos;
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
localize_option_names( &localPos );
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
len = strlen(localPos.name1);
|
|
|
|
if (localPos.name2)
|
|
|
|
len += 2+strlen(localPos.name2);
|
|
|
|
if (localPos.name3)
|
|
|
|
len += 2+strlen(localPos.name3);
|
2017-03-08 21:53:59 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
name = (tmbstr)malloc(len+1);
|
|
|
|
if (!name) outOfMemory();
|
|
|
|
strcpy(name, localPos.name1);
|
|
|
|
free((tmbstr)localPos.name1);
|
|
|
|
if (localPos.name2)
|
2017-03-08 21:53:59 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
strcat(name, ", ");
|
|
|
|
strcat(name, localPos.name2);
|
|
|
|
free((tmbstr)localPos.name2);
|
2017-03-08 21:53:59 +00:00
|
|
|
}
|
2017-04-04 18:07:20 +00:00
|
|
|
if (localPos.name3)
|
2017-03-08 21:53:59 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
strcat(name, ", ");
|
|
|
|
strcat(name, localPos.name3);
|
|
|
|
free((tmbstr)localPos.name3);
|
2017-03-08 21:53:59 +00:00
|
|
|
}
|
2017-04-04 18:07:20 +00:00
|
|
|
return name;
|
2017-03-08 21:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Returns the final name of the tidy executable by eliminating the path
|
|
|
|
** name components from the executable name.
|
|
|
|
** @param prog The path of the current executable.
|
|
|
|
*/
|
|
|
|
static ctmbstr get_final_name( ctmbstr prog )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
ctmbstr name = prog;
|
|
|
|
int c;
|
|
|
|
size_t i;
|
|
|
|
size_t len = strlen(prog);
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
for (i = 0; i < len; i++)
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
c = prog[i];
|
|
|
|
if ((( c == '/' ) || ( c == '\\' )) && prog[i+1])
|
|
|
|
{
|
|
|
|
name = &prog[i+1];
|
|
|
|
}
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
return name;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Outputs all of the complete help options (text).
|
|
|
|
** @param tdoc The Tidydoc whose options are being printed.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void print_help_options( TidyDoc tdoc )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
CmdOptCategory cat = CmdOptCatFIRST;
|
|
|
|
const CmdOptDesc* pos = cmdopt_defs;
|
|
|
|
uint col1, col2;
|
|
|
|
uint width = 78;
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
for( cat=CmdOptCatFIRST; cat!=CmdOptCatLAST; ++cat)
|
|
|
|
{
|
|
|
|
ctmbstr name = tidyLocalizedString(cmdopt_catname[cat].key);
|
|
|
|
size_t len = width < strlen(name) ? width : strlen(name);
|
|
|
|
printf( "%s\n", name );
|
|
|
|
printf( "%*.*s\n", (int)len, (int)len, helpul );
|
|
|
|
|
|
|
|
/* Tidy's "standard" 78-column output was always 25:52 ratio, so let's
|
|
|
|
try to preserve this approximately 1:2 ratio regardless of whatever
|
|
|
|
silly thing the user might have set for a console width, with a
|
|
|
|
maximum of 50 characters for the first column.
|
|
|
|
*/
|
|
|
|
col1 = width / 3; /* one third of the available */
|
|
|
|
col1 = col1 < 1 ? 1 : col1; /* at least 1 */
|
|
|
|
col1 = col1 > 35 ? 35 : col1; /* no greater than 35 */
|
|
|
|
col2 = width - col1 - 2; /* allow two spaces */
|
|
|
|
col2 = col2 < 1 ? 1 : col2; /* at least 1 */
|
|
|
|
|
|
|
|
for( pos=cmdopt_defs; pos->name1; ++pos)
|
|
|
|
{
|
|
|
|
tmbstr name;
|
|
|
|
if (pos->cat != cat)
|
|
|
|
continue;
|
|
|
|
name = get_option_names( pos );
|
|
|
|
print2Columns( helpfmt, col1, col2, name, tidyLocalizedString( pos->key ) );
|
|
|
|
free(name);
|
|
|
|
}
|
|
|
|
printf("\n");
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Handles the -help service.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void help(TidyDoc tdoc, /**< The tidy document for which help is showing. */
|
|
|
|
ctmbstr prog /**< The path of the current executable. */
|
|
|
|
)
|
2016-01-15 04:06:15 +00:00
|
|
|
{
|
2017-09-30 21:06:19 +00:00
|
|
|
tmbstr temp_string = NULL;
|
2017-04-04 18:07:20 +00:00
|
|
|
uint width = 78;
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
printf("\n");
|
|
|
|
printf( tidyLocalizedString(TC_TXT_HELP_1), get_final_name(prog), tidyLibraryVersion() );
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
#ifdef PLATFORM_NAME
|
2017-09-30 21:06:19 +00:00
|
|
|
temp_string = stringWithFormat( tidyLocalizedString(TC_TXT_HELP_2A), PLATFORM_NAME);
|
2017-04-04 18:07:20 +00:00
|
|
|
#else
|
|
|
|
title_line = stringWithFormat( tidyLocalizedString(TC_TXT_HELP_2B) );
|
|
|
|
#endif
|
2017-09-30 21:06:19 +00:00
|
|
|
width = width < strlen(temp_string) ? width : strlen(temp_string);
|
|
|
|
printf( "%s\n", temp_string );
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( "%*.*s\n\n", width, width, ul);
|
2017-09-30 21:06:19 +00:00
|
|
|
free( temp_string );
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
print_help_options( tdoc );
|
|
|
|
|
2017-09-30 21:06:19 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
printf("\n");
|
2017-09-30 21:06:19 +00:00
|
|
|
#if defined(TIDY_CONFIG_FILE) && defined(TIDY_USER_CONFIG_FILE)
|
|
|
|
temp_string = stringWithFormat( tidyLocalizedString(TC_TXT_HELP_3A), TIDY_CONFIG_FILE, TIDY_USER_CONFIG_FILE );
|
|
|
|
printf( tidyLocalizedString(TC_TXT_HELP_3), temp_string );
|
|
|
|
free( temp_string );
|
|
|
|
#else
|
|
|
|
printf( tidyLocalizedString(TC_TXT_HELP_3), "\n" );
|
|
|
|
#endif
|
2017-04-04 18:07:20 +00:00
|
|
|
printf("\n");
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end service_help group */
|
|
|
|
/* MARK: - Provide the -help-config Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_help_config Provide the -help-config Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Retrieves allowed values from an option's pick list.
|
|
|
|
** @param topt A TidyOption for which to get the allowed values.
|
|
|
|
** @result A string containing the allowed values.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
|
|
|
static tmbstr GetAllowedValuesFromPick( TidyOption topt )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyIterator pos;
|
|
|
|
Bool first;
|
|
|
|
ctmbstr def;
|
|
|
|
uint len = 0;
|
|
|
|
tmbstr val;
|
|
|
|
|
|
|
|
pos = tidyOptGetPickList( topt );
|
|
|
|
first = yes;
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = no;
|
|
|
|
else
|
|
|
|
len += 2;
|
|
|
|
def = tidyOptGetNextPick( topt, &pos );
|
|
|
|
len += strlen(def);
|
|
|
|
}
|
|
|
|
val = (tmbstr)malloc(len+1);
|
|
|
|
if (!val) outOfMemory();
|
|
|
|
val[0] = '\0';
|
|
|
|
pos = tidyOptGetPickList( topt );
|
|
|
|
first = yes;
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
if (first)
|
|
|
|
first = no;
|
|
|
|
else
|
|
|
|
strcat(val, ", ");
|
|
|
|
def = tidyOptGetNextPick( topt, &pos );
|
|
|
|
strcat(val, def);
|
|
|
|
}
|
|
|
|
return val;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Retrieves allowed values for an option.
|
|
|
|
** @result A string containing the allowed values.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static tmbstr GetAllowedValues(TidyOption topt, /**< A TidyOption for which to get the allowed values. */
|
|
|
|
const OptionDesc *d /**< A pointer to the OptionDesc array. */
|
|
|
|
)
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
if (d->vals)
|
|
|
|
{
|
|
|
|
tmbstr val = (tmbstr)malloc(1+strlen(d->vals));
|
|
|
|
if (!val) outOfMemory();
|
|
|
|
strcpy(val, d->vals);
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return GetAllowedValuesFromPick( topt );
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Prints a single option.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void printOption(TidyDoc ARG_UNUSED(tdoc), /**< The Tidy document. */
|
|
|
|
TidyOption topt, /**< The option to print. */
|
|
|
|
OptionDesc *d /**< A pointer to the OptionDesc array. */
|
|
|
|
)
|
2016-01-15 04:06:15 +00:00
|
|
|
{
|
2017-03-10 13:24:23 +00:00
|
|
|
if (tidyOptGetCategory( topt ) == TidyInternalCategory )
|
2016-01-25 12:58:55 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if ( *d->name || *d->type )
|
|
|
|
{
|
|
|
|
ctmbstr pval = d->vals;
|
|
|
|
tmbstr val = NULL;
|
|
|
|
if (!d->haveVals)
|
|
|
|
{
|
|
|
|
pval = "-";
|
|
|
|
}
|
|
|
|
else if (pval == NULL)
|
|
|
|
{
|
|
|
|
val = GetAllowedValues( topt, d);
|
|
|
|
pval = val;
|
|
|
|
}
|
|
|
|
print3Columns( fmt, 27, 9, 40, d->name, d->type, pval );
|
|
|
|
if (val)
|
|
|
|
free(val);
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Handles the -help-config service.
|
|
|
|
** @remark We will not support console word wrapping for the configuration
|
|
|
|
** options table. If users really have a small console, then they
|
|
|
|
* should make it wider or output to a file.
|
|
|
|
** @param tdoc The Tidy document.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
static void optionhelp( TidyDoc tdoc )
|
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( "\n" );
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( "%s", tidyLocalizedString( TC_TXT_HELP_CONFIG ) );
|
|
|
|
|
|
|
|
printf( fmt,
|
|
|
|
tidyLocalizedString( TC_TXT_HELP_CONFIG_NAME ),
|
|
|
|
tidyLocalizedString( TC_TXT_HELP_CONFIG_TYPE ),
|
|
|
|
tidyLocalizedString( TC_TXT_HELP_CONFIG_ALLW ) );
|
|
|
|
|
|
|
|
printf( fmt, ul, ul, ul );
|
|
|
|
|
|
|
|
ForEachSortedOption( tdoc, printOption );
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
|
2017-10-01 22:58:17 +00:00
|
|
|
/** @} end service_help_config group */
|
|
|
|
/* MARK: - Provide the -help-env Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_help_env Provide the -help-env Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Handles the -help-env service.
|
|
|
|
** @param tdoc The Tidy document.
|
|
|
|
*/
|
|
|
|
static void helpEnv( TidyDoc tdoc )
|
|
|
|
{
|
|
|
|
tmbstr subst = "";
|
|
|
|
Bool uses_env = getenv("HTML_TIDY") != NULL;
|
|
|
|
ctmbstr env_var = uses_env ? getenv("HTML_TIDY"): tidyLocalizedString( TC_TXT_HELP_ENV_1B );
|
|
|
|
|
|
|
|
#if defined( TIDY_CONFIG_FILE ) && defined( TIDY_USER_CONFIG_FILE )
|
|
|
|
subst = stringWithFormat( tidyLocalizedString(TC_TXT_HELP_ENV_1A), TIDY_CONFIG_FILE, TIDY_USER_CONFIG_FILE );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
env_var = env_var != NULL ? env_var : tidyLocalizedString( TC_TXT_HELP_ENV_1B );
|
|
|
|
|
|
|
|
printf( "\n" );
|
|
|
|
printf( tidyLocalizedString( TC_TXT_HELP_ENV_1), subst, env_var );
|
|
|
|
|
|
|
|
#if defined( TIDY_CONFIG_FILE ) && defined( TIDY_USER_CONFIG_FILE )
|
|
|
|
if ( uses_env )
|
|
|
|
printf( tidyLocalizedString( TC_TXT_HELP_ENV_1C ), TIDY_USER_CONFIG_FILE );
|
|
|
|
free( subst );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
printf( "\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end service_help_env group */
|
2017-04-04 18:07:20 +00:00
|
|
|
/* MARK: - Provide the -help-option Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_help_option Provide the -help-option Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Cleans up the HTML-laden option descriptions for console output. It's
|
|
|
|
** just a simple HTML filtering/replacement function.
|
|
|
|
** @param description The option description.
|
|
|
|
** @result Returns an allocated string with some HTML stripped away.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
|
|
|
static tmbstr cleanup_description( ctmbstr description )
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
/* Substitutions - this might be a good spot to introduce platform
|
|
|
|
dependent definitions for colorized output on different terminals
|
|
|
|
that support, for example, ANSI escape sequences. The assumption
|
|
|
|
is made the Mac and Linux targets support ANSI colors, but even
|
|
|
|
so debugger terminals may not. Note that the line-wrapping
|
|
|
|
function also doesn't account for non-printing characters. */
|
|
|
|
static struct {
|
|
|
|
ctmbstr tag;
|
|
|
|
ctmbstr replacement;
|
|
|
|
} const replacements[] = {
|
|
|
|
{ "lt", "<" },
|
|
|
|
{ "gt", ">" },
|
|
|
|
{ "br/", "\n\n" },
|
2016-01-15 04:06:15 +00:00
|
|
|
#if defined(LINUX_OS) || defined(MAC_OS_X)
|
2016-01-25 12:58:55 +00:00
|
|
|
{ "code", "\x1b[36m" },
|
|
|
|
{ "/code", "\x1b[0m" },
|
|
|
|
{ "em", "\x1b[4m" },
|
|
|
|
{ "/em", "\x1b[0m" },
|
|
|
|
{ "strong", "\x1b[31m" },
|
|
|
|
{ "/strong", "\x1b[0m" },
|
2016-01-15 04:06:15 +00:00
|
|
|
#endif
|
2016-01-25 12:58:55 +00:00
|
|
|
/* MUST be last */
|
|
|
|
{ NULL, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
/* State Machine Setup */
|
|
|
|
typedef enum {
|
|
|
|
s_DONE,
|
|
|
|
s_DATA,
|
|
|
|
s_WRITING,
|
|
|
|
s_TAG_OPEN,
|
|
|
|
s_TAG_NAME,
|
|
|
|
s_ERROR,
|
|
|
|
s_LAST /* MUST be last */
|
|
|
|
} states;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
c_NIL,
|
|
|
|
c_EOF,
|
|
|
|
c_BRACKET_CLOSE,
|
|
|
|
c_BRACKET_OPEN,
|
|
|
|
c_OTHER
|
|
|
|
} charstates;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
a_NIL,
|
|
|
|
a_BUILD_NAME,
|
|
|
|
a_CONSUME,
|
|
|
|
a_EMIT,
|
|
|
|
a_EMIT_SUBS,
|
|
|
|
a_WRITE,
|
|
|
|
a_ERROR
|
|
|
|
} actions;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
states state;
|
|
|
|
charstates charstate;
|
|
|
|
actions action;
|
|
|
|
states next_state;
|
|
|
|
} transitionType;
|
|
|
|
|
|
|
|
const transitionType transitions[] = {
|
|
|
|
{ s_DATA, c_EOF, a_NIL, s_DONE },
|
|
|
|
{ s_DATA, c_BRACKET_OPEN, a_CONSUME, s_TAG_OPEN },
|
|
|
|
/* special case allows ; */
|
|
|
|
{ s_DATA, c_BRACKET_CLOSE, a_EMIT, s_WRITING },
|
|
|
|
{ s_DATA, c_OTHER, a_EMIT, s_WRITING },
|
|
|
|
{ s_WRITING, c_OTHER, a_WRITE, s_DATA },
|
|
|
|
{ s_WRITING, c_BRACKET_CLOSE, a_WRITE, s_DATA },
|
|
|
|
{ s_TAG_OPEN, c_EOF, a_ERROR, s_DONE },
|
|
|
|
{ s_TAG_OPEN, c_OTHER, a_NIL, s_TAG_NAME },
|
|
|
|
{ s_TAG_NAME, c_BRACKET_OPEN, a_ERROR, s_DONE },
|
|
|
|
{ s_TAG_NAME, c_EOF, a_ERROR, s_DONE },
|
|
|
|
{ s_TAG_NAME, c_BRACKET_CLOSE, a_EMIT_SUBS, s_WRITING },
|
|
|
|
{ s_TAG_NAME, c_OTHER, a_BUILD_NAME, s_TAG_NAME },
|
|
|
|
{ s_ERROR, 0, a_ERROR, s_DONE },
|
|
|
|
{ s_DONE, 0, a_NIL, 0 },
|
|
|
|
/* MUST be last: */
|
|
|
|
{ s_LAST, 0, 0, 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Output Setup */
|
|
|
|
tmbstr result = NULL;
|
2016-10-25 14:41:03 +00:00
|
|
|
int g_result = 100; /* minimum buffer grow size */
|
|
|
|
int l_result = 0; /* buffer current size */
|
|
|
|
int i_result = 0; /* current string position */
|
|
|
|
int writer_len = 0; /* writer length */
|
2016-01-25 12:58:55 +00:00
|
|
|
|
|
|
|
ctmbstr writer = NULL;
|
|
|
|
|
|
|
|
/* Current tag name setup */
|
2016-10-25 14:41:03 +00:00
|
|
|
tmbstr name = NULL; /* tag name */
|
|
|
|
int g_name = 10; /* buffer grow size */
|
|
|
|
int l_name = 0; /* buffer current size */
|
|
|
|
int i_name = 0; /* current string position */
|
2016-01-25 12:58:55 +00:00
|
|
|
|
|
|
|
/* Pump Setup */
|
|
|
|
int i = 0;
|
|
|
|
states state = s_DATA;
|
|
|
|
charstates charstate;
|
|
|
|
char c;
|
|
|
|
int j = 0, k = 0;
|
|
|
|
transitionType transition;
|
|
|
|
|
|
|
|
if ( !description || (strlen(description) < 1) )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process the HTML Snippet */
|
|
|
|
do {
|
|
|
|
c = description[i];
|
|
|
|
|
|
|
|
/* Determine secondary state. */
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
case '\0':
|
|
|
|
charstate = c_EOF;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '<':
|
|
|
|
case '&':
|
|
|
|
charstate = c_BRACKET_OPEN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '>':
|
|
|
|
case ';':
|
|
|
|
charstate = c_BRACKET_CLOSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
charstate = c_OTHER;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find the correct instruction */
|
|
|
|
j = 0;
|
|
|
|
while (transitions[j].state != s_LAST)
|
|
|
|
{
|
|
|
|
transition = transitions[j];
|
|
|
|
if ( transition.state == state && transition.charstate == charstate ) {
|
|
|
|
switch ( transition.action )
|
|
|
|
{
|
|
|
|
/* This action is building the name of an HTML tag. */
|
|
|
|
case a_BUILD_NAME:
|
|
|
|
if ( !name )
|
|
|
|
{
|
|
|
|
l_name = g_name;
|
|
|
|
name = calloc(l_name, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( i_name >= l_name )
|
|
|
|
{
|
|
|
|
l_name = l_name + g_name;
|
|
|
|
name = realloc(name, l_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(name + i_name, &c, 1);
|
|
|
|
i_name++;
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* This character will be emitted into the output
|
|
|
|
stream. The only purpose of this action is to
|
|
|
|
ensure that `writer` is NULL as a flag that we
|
|
|
|
will output the current `c` */
|
|
|
|
case a_EMIT:
|
2016-10-25 14:41:03 +00:00
|
|
|
writer = NULL; /* flag to use c */
|
2016-01-25 12:58:55 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* Now that we've consumed a tag, we will emit the
|
|
|
|
substitution if any has been specified in
|
|
|
|
`replacements`. */
|
|
|
|
case a_EMIT_SUBS:
|
|
|
|
name[i_name] = '\0';
|
|
|
|
i_name = 0;
|
|
|
|
k = 0;
|
|
|
|
writer = "";
|
|
|
|
while ( replacements[k].tag )
|
|
|
|
{
|
|
|
|
if ( strcmp( replacements[k].tag, name ) == 0 )
|
|
|
|
{
|
|
|
|
writer = replacements[k].replacement;
|
|
|
|
}
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* This action will add to our `result` string, expanding
|
|
|
|
the buffer as necessary in reasonable chunks. */
|
|
|
|
case a_WRITE:
|
|
|
|
if ( !writer )
|
|
|
|
writer_len = 1;
|
|
|
|
else
|
|
|
|
writer_len = strlen( writer );
|
|
|
|
/* Lazy buffer creation */
|
|
|
|
if ( !result )
|
|
|
|
{
|
|
|
|
l_result = writer_len + g_result;
|
|
|
|
result = calloc(l_result, 1);
|
|
|
|
}
|
|
|
|
/* Grow the buffer if needed */
|
|
|
|
if ( i_result + writer_len >= l_result )
|
|
|
|
{
|
|
|
|
l_result = l_result + writer_len + g_result;
|
|
|
|
result = realloc(result, l_result);
|
|
|
|
}
|
|
|
|
/* Add current writer to the buffer */
|
|
|
|
if ( !writer )
|
|
|
|
{
|
|
|
|
result[i_result] = c;
|
|
|
|
result[i_result +1] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strncpy( result + i_result, writer, writer_len );
|
|
|
|
}
|
|
|
|
|
|
|
|
i_result += writer_len;
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* This action could be more robust but it serves the
|
|
|
|
current purpose. Cross our fingers and count on our
|
|
|
|
localizers not to give bad HTML descriptions. */
|
|
|
|
case a_ERROR:
|
|
|
|
printf("<Error> The localized string probably has bad HTML.\n");
|
|
|
|
goto EXIT_CLEANLY;
|
|
|
|
|
|
|
|
/* Just a NOP. */
|
|
|
|
case a_NIL:
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* The default case also handles the CONSUME action. */
|
|
|
|
default:
|
|
|
|
i++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = transition.next_state;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
} while ( description[i] );
|
2016-01-15 04:06:15 +00:00
|
|
|
|
|
|
|
EXIT_CLEANLY:
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
if ( name )
|
|
|
|
free(name);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Handles the -help-option service.
|
|
|
|
*/
|
|
|
|
static void optionDescribe(TidyDoc tdoc, /**< The Tidy Document */
|
|
|
|
char *option /**< The name of the option. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
tmbstr result = NULL;
|
|
|
|
Bool allocated = no;
|
|
|
|
TidyOptionId topt = tidyOptGetIdForName( option );
|
|
|
|
uint tcat = tidyOptGetCategory( tidyGetOption(tdoc, topt));
|
|
|
|
|
|
|
|
if (topt < N_TIDY_OPTIONS && tcat != TidyInternalCategory )
|
|
|
|
{
|
|
|
|
result = cleanup_description( tidyOptGetDoc( tdoc, tidyGetOption( tdoc, topt ) ) );
|
|
|
|
allocated = yes;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = (tmbstr)tidyLocalizedString(TC_STRING_UNKNOWN_OPTION_B);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf( "\n" );
|
|
|
|
printf( "`--%s`\n\n", option );
|
|
|
|
print1Column( "%-78.78s\n", 78, result );
|
|
|
|
printf( "\n" );
|
|
|
|
if ( allocated )
|
|
|
|
free ( result );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end service_help_option group */
|
|
|
|
/* MARK: - Provide the -lang help Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_lang_help Provide the -lang help Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Prints the Windows language names that Tidy recognizes, using the specified
|
|
|
|
** format string.
|
|
|
|
** @param format A format string used to display the Windows language names,
|
|
|
|
** or NULL to use the built-in default format.
|
|
|
|
*/
|
|
|
|
void tidyPrintWindowsLanguageNames( ctmbstr format )
|
|
|
|
{
|
|
|
|
const tidyLocaleMapItem *item;
|
|
|
|
TidyIterator i = getWindowsLanguageList();
|
|
|
|
ctmbstr winName;
|
|
|
|
ctmbstr posixName;
|
|
|
|
|
|
|
|
while (i) {
|
|
|
|
item = getNextWindowsLanguage(&i);
|
|
|
|
winName = TidyLangWindowsName( item );
|
|
|
|
posixName = TidyLangPosixName( item );
|
|
|
|
if ( format )
|
|
|
|
printf( format, winName, posixName );
|
|
|
|
else
|
|
|
|
printf( "%-20s -> %s\n", winName, posixName );
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Prints the languages the are currently built into Tidy, using the specified
|
|
|
|
** format string.
|
|
|
|
** @param format A format string used to display the Windows language names,
|
|
|
|
** or NULL to use the built-in default format.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
void tidyPrintTidyLanguageNames( ctmbstr format )
|
2015-10-31 09:33:43 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
ctmbstr item;
|
|
|
|
TidyIterator i = getInstalledLanguageList();
|
2017-03-09 21:04:03 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
while (i) {
|
|
|
|
item = getNextInstalledLanguage(&i);
|
|
|
|
if ( format )
|
|
|
|
printf( format, item );
|
|
|
|
else
|
|
|
|
printf( "%s\n", item );
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-04-04 18:07:20 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Handles the -lang help service.
|
|
|
|
** @remark We will not support console word wrapping for the tables. If users
|
|
|
|
** really have a small console, then they should make it wider or
|
|
|
|
** output to a file.
|
|
|
|
** @param tdoc The Tidy document.
|
|
|
|
*/
|
|
|
|
static void lang_help( TidyDoc tdoc )
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( "\n" );
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( "%s", tidyLocalizedString(TC_TXT_HELP_LANG_1) );
|
|
|
|
printf( "\n" );
|
|
|
|
tidyPrintWindowsLanguageNames(" %-20s -> %s\n");
|
|
|
|
printf( "\n" );
|
|
|
|
printf( "%s", tidyLocalizedString(TC_TXT_HELP_LANG_2) );
|
|
|
|
printf( "\n" );
|
|
|
|
tidyPrintTidyLanguageNames(" %s\n");
|
|
|
|
printf( "\n" );
|
|
|
|
printf( tidyLocalizedString(TC_TXT_HELP_LANG_3), tidyGetLanguage() );
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( "\n" );
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
2015-11-04 01:41:07 +00:00
|
|
|
|
2015-10-31 09:33:43 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end service_lang_help group */
|
|
|
|
/* MARK: - Provide the -show-config Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_show_config Provide the -show-config Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Prints the option value for a given option.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void printOptionValues(TidyDoc ARG_UNUSED(tdoc), /**< The Tidy document. */
|
|
|
|
TidyOption topt, /**< The option for which to show values. */
|
|
|
|
OptionDesc *d /**< The OptionDesc array. */
|
|
|
|
)
|
2016-01-15 04:06:15 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
TidyOptionId optId = tidyOptGetId( topt );
|
2017-03-10 13:24:23 +00:00
|
|
|
|
|
|
|
if ( tidyOptGetCategory(topt) == TidyInternalCategory )
|
|
|
|
return;
|
2016-01-25 12:58:55 +00:00
|
|
|
|
|
|
|
switch ( optId )
|
|
|
|
{
|
|
|
|
case TidyInlineTags:
|
|
|
|
case TidyBlockTags:
|
|
|
|
case TidyEmptyTags:
|
|
|
|
case TidyPreTags:
|
|
|
|
{
|
|
|
|
TidyIterator pos = tidyOptGetDeclTagList( tdoc );
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
d->def = tidyOptGetNextDeclTag(tdoc, optId, &pos);
|
|
|
|
if ( pos )
|
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( fmt, d->name, d->type, d->def );
|
2016-01-25 12:58:55 +00:00
|
|
|
d->name = "";
|
|
|
|
d->type = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fix for http://tidy.sf.net/bug/873921 */
|
|
|
|
if ( *d->name || *d->type || (d->def && *d->def) )
|
|
|
|
{
|
|
|
|
if ( ! d->def )
|
|
|
|
d->def = "";
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( fmt, d->name, d->type, d->def );
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
2015-10-31 09:33:43 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Handles the -show-config service.
|
|
|
|
** @remark We will not support console word wrapping for the table. If users
|
|
|
|
** really have a small console, then they should make it wider or
|
|
|
|
** output to a file.
|
|
|
|
** @param tdoc The Tidy Document.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
|
|
|
static void optionvalues( TidyDoc tdoc )
|
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( "\n%s\n", tidyLocalizedString(TC_STRING_CONF_HEADER) );
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( fmt, tidyLocalizedString(TC_STRING_CONF_NAME),
|
|
|
|
tidyLocalizedString(TC_STRING_CONF_TYPE),
|
|
|
|
tidyLocalizedString(TC_STRING_CONF_VALUE) );
|
|
|
|
printf( fmt, ul, ul, ul );
|
|
|
|
|
|
|
|
ForEachSortedOption( tdoc, printOptionValues );
|
2015-10-31 09:33:43 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** @} end service_show_config group */
|
2017-10-01 23:49:44 +00:00
|
|
|
/* MARK: - Provide the -export-config Services */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_export_config Provide the -export-config Services
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Prints the option value for a given option.
|
|
|
|
*/
|
|
|
|
static void printOptionExportValues(TidyDoc ARG_UNUSED(tdoc), /**< The Tidy document. */
|
|
|
|
TidyOption topt, /**< The option for which to show values. */
|
|
|
|
OptionDesc *d /**< The OptionDesc array. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
TidyOptionId optId = tidyOptGetId( topt );
|
|
|
|
|
|
|
|
if ( tidyOptGetCategory(topt) == TidyInternalCategory )
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch ( optId )
|
|
|
|
{
|
|
|
|
case TidyInlineTags:
|
|
|
|
case TidyBlockTags:
|
|
|
|
case TidyEmptyTags:
|
|
|
|
case TidyPreTags:
|
|
|
|
{
|
|
|
|
TidyIterator pos = tidyOptGetDeclTagList( tdoc );
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
d->def = tidyOptGetNextDeclTag(tdoc, optId, &pos);
|
|
|
|
if ( pos )
|
|
|
|
{
|
|
|
|
printf( "%s: %s\n", d->name, d->def );
|
|
|
|
d->name = "";
|
|
|
|
d->type = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fix for http://tidy.sf.net/bug/873921 */
|
|
|
|
if ( *d->name || *d->type || (d->def && *d->def) )
|
|
|
|
{
|
|
|
|
if ( ! d->def )
|
|
|
|
d->def = "";
|
|
|
|
printf( "%s: %s\n", d->name, d->def );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Handles the -export-config service.
|
|
|
|
** @param tdoc The Tidy Document.
|
|
|
|
*/
|
|
|
|
static void exportOptionValues( TidyDoc tdoc )
|
|
|
|
{
|
|
|
|
ForEachSortedOption( tdoc, printOptionExportValues );
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Handles the -export-default-config service.
|
|
|
|
** @param tdoc The Tidy Document.
|
|
|
|
*/
|
|
|
|
static void exportDefaultOptionValues( TidyDoc tdoc )
|
|
|
|
{
|
|
|
|
tidyOptResetAllToDefault( tdoc );
|
|
|
|
ForEachSortedOption( tdoc, printOptionExportValues );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end service_export_config group */
|
2017-04-04 18:07:20 +00:00
|
|
|
/* MARK: - Provide the -version Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_version Provide the -version Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Handles the -version service.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
static void version( TidyDoc tdoc )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-15 04:06:15 +00:00
|
|
|
#ifdef PLATFORM_NAME
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( tidyLocalizedString( TC_STRING_VERS_A ), PLATFORM_NAME, tidyLibraryVersion() );
|
2016-01-15 04:06:15 +00:00
|
|
|
#else
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( tidyLocalizedString( TC_STRING_VERS_B ), tidyLibraryVersion() );
|
2016-01-15 04:06:15 +00:00
|
|
|
#endif
|
|
|
|
printf("\n");
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end service_version group */
|
|
|
|
/* MARK: - Provide the -xml-config Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_xml_config Provide the -xml-config Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Prints for XML an option's <description>.
|
|
|
|
*/
|
|
|
|
static void printXMLDescription(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
TidyOption topt /**< The option. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ctmbstr doc = tidyOptGetDoc( tdoc, topt );
|
|
|
|
|
|
|
|
if (doc)
|
|
|
|
printf(" <description>%s</description>\n", doc);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf(" <description />\n");
|
|
|
|
fprintf(stderr, tidyLocalizedString(TC_STRING_OPT_NOT_DOCUMENTED),
|
|
|
|
tidyOptGetName( topt ));
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Prints for XML an option's `<seealso>`.
|
|
|
|
*/
|
|
|
|
static void printXMLCrossRef(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
TidyOption topt /**< The option. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
TidyOption optLinked;
|
|
|
|
TidyIterator pos = tidyOptGetDocLinksList(tdoc, topt);
|
|
|
|
while( pos )
|
|
|
|
{
|
|
|
|
optLinked = tidyOptGetNextDocLinks(tdoc, &pos );
|
|
|
|
printf(" <seealso>%s</seealso>\n",tidyOptGetName(optLinked));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Prints for XML an option's `<eqconfig>`.
|
|
|
|
*/
|
|
|
|
static void printXMLCrossRefEqConsole(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
TidyOption topt /**< The option. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
const CmdOptDesc* pos = cmdopt_defs;
|
|
|
|
const CmdOptDesc* hit = NULL;
|
|
|
|
CmdOptDesc localHit;
|
|
|
|
enum { sizeBuffer = 50 }; /* largest config name is 27 chars so far... */
|
|
|
|
char buffer[sizeBuffer];
|
|
|
|
|
|
|
|
for( pos=cmdopt_defs; pos->name1; ++pos)
|
|
|
|
{
|
|
|
|
snprintf(buffer, sizeBuffer, "%s:", tidyOptGetName( topt ));
|
|
|
|
if ( pos->eqconfig && (strncmp(buffer, pos->eqconfig, strlen(buffer)) == 0) )
|
|
|
|
{
|
|
|
|
hit = pos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( hit )
|
|
|
|
{
|
|
|
|
tmbstr localName;
|
2017-05-30 16:15:25 +00:00
|
|
|
localHit = *hit;
|
2017-04-04 18:07:20 +00:00
|
|
|
localize_option_names( &localHit );
|
|
|
|
printf(" <eqconsole>%s</eqconsole>\n", localName = get_escaped_name(localHit.name1));
|
|
|
|
free((tmbstr)localHit.name1);
|
|
|
|
free(localName);
|
|
|
|
if ( localHit.name2 )
|
|
|
|
{
|
|
|
|
printf(" <eqconsole>%s</eqconsole>\n", localName = get_escaped_name(localHit.name2));
|
|
|
|
free((tmbstr)localHit.name2);
|
|
|
|
free(localName);
|
|
|
|
}
|
|
|
|
if ( localHit.name3 )
|
|
|
|
{
|
|
|
|
printf(" <eqconsole>%s</eqconsole>\n", localName = get_escaped_name(localHit.name3));
|
|
|
|
free((tmbstr)localHit.name3);
|
|
|
|
free(localName);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf(" %s\n", " <eqconsole />");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Prints for XML an option.
|
|
|
|
*/
|
|
|
|
static void printXMLOption(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
TidyOption topt, /**< The option. */
|
|
|
|
OptionDesc *d /**< The OptionDesc for the option. */
|
|
|
|
)
|
2016-01-15 04:06:15 +00:00
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
if ( tidyOptGetCategory(topt) == TidyInternalCategory )
|
2016-01-25 12:58:55 +00:00
|
|
|
return;
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
printf( " <option class=\"%s\">\n", d->cat );
|
|
|
|
printf (" <name>%s</name>\n",d->name);
|
|
|
|
printf (" <type>%s</type>\n",d->type);
|
|
|
|
if (d->def)
|
|
|
|
printf(" <default>%s</default>\n",d->def);
|
|
|
|
else
|
|
|
|
printf(" <default />\n");
|
|
|
|
if (d->haveVals)
|
|
|
|
{
|
|
|
|
printf(" <example>");
|
|
|
|
PrintAllowedValues( topt, d );
|
|
|
|
printf("</example>\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf(" <example />\n");
|
|
|
|
}
|
|
|
|
printXMLDescription( tdoc, topt );
|
|
|
|
printXMLCrossRef( tdoc, topt );
|
|
|
|
printXMLCrossRefEqConsole( tdoc, topt );
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( " </option>\n" );
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** Handles the -xml-config service.
|
|
|
|
** @param tdoc The Tidy document.
|
|
|
|
*/
|
|
|
|
static void XMLoptionhelp( TidyDoc tdoc )
|
2011-11-17 02:44:16 +00:00
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( "<?xml version=\"1.0\"?>\n"
|
2017-04-04 18:07:20 +00:00
|
|
|
"<config version=\"%s\">\n", tidyLibraryVersion());
|
|
|
|
ForEachOption( tdoc, printXMLOption );
|
|
|
|
printf( "</config>\n" );
|
2016-01-15 04:06:15 +00:00
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end service_xml_config group */
|
|
|
|
/* MARK: - Provide the -xml-error-strings Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_xml_error_strings Provide the -xml-error-strings Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Handles the -xml-error-strings service.
|
|
|
|
** This service is primarily helpful to developers who need to generate an
|
|
|
|
** updated list of strings to expect when using one of the message callbacks.
|
|
|
|
** Included in the output is the current string associated with the error
|
|
|
|
** symbol.
|
|
|
|
** @param tdoc The Tidy document.
|
2016-02-17 04:35:20 +00:00
|
|
|
**/
|
|
|
|
static void xml_error_strings( TidyDoc tdoc )
|
|
|
|
{
|
2017-02-13 19:29:47 +00:00
|
|
|
uint errorCode;
|
2016-02-17 04:35:20 +00:00
|
|
|
ctmbstr localizedString;
|
|
|
|
TidyIterator j = getErrorCodeList();
|
|
|
|
|
|
|
|
printf( "<?xml version=\"1.0\"?>\n" );
|
|
|
|
printf( "<error_strings version=\"%s\">\n", tidyLibraryVersion());
|
|
|
|
|
|
|
|
while (j) {
|
2017-02-13 19:29:47 +00:00
|
|
|
errorCode = getNextErrorCode(&j);
|
|
|
|
localizedString = tidyLocalizedString(errorCode);
|
2016-02-17 04:35:20 +00:00
|
|
|
printf( " <error_string>\n" );
|
2017-02-13 19:29:47 +00:00
|
|
|
printf( " <name>%s</name>\n", tidyErrorCodeAsKey(errorCode));
|
2016-02-17 04:35:20 +00:00
|
|
|
if ( localizedString )
|
2016-02-17 06:17:18 +00:00
|
|
|
printf( " <string class=\"%s\"><![CDATA[%s]]></string>\n", tidyGetLanguage(), localizedString );
|
2016-02-17 04:35:20 +00:00
|
|
|
else
|
|
|
|
printf( " <string class=\"%s\">NULL</string>\n", tidyGetLanguage() );
|
|
|
|
|
|
|
|
printf( " </error_string>\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
printf( "</error_strings>\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end service_xml_error_strings group */
|
|
|
|
/* MARK: - Provide the -xml-help Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_xmlhelp Provide the -xml-help Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** Outputs an XML element for a CLI option, escaping special characters as
|
|
|
|
** required. For example, it might print `<name>-output <file></name>`.
|
|
|
|
*/
|
|
|
|
static void print_xml_help_option_element(ctmbstr element, /**< XML element name. */
|
|
|
|
ctmbstr name /**< The contents of the element. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
tmbstr escpName;
|
|
|
|
if (!name)
|
|
|
|
return;
|
|
|
|
|
|
|
|
printf(" <%s>%s</%s>\n", element, escpName = get_escaped_name(name), element);
|
|
|
|
free(escpName);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Provides the -xml-help service.
|
|
|
|
*/
|
|
|
|
static void xml_help( void )
|
|
|
|
{
|
|
|
|
const CmdOptDesc* pos;
|
|
|
|
CmdOptDesc localPos;
|
|
|
|
|
|
|
|
printf( "<?xml version=\"1.0\"?>\n"
|
|
|
|
"<cmdline version=\"%s\">\n", tidyLibraryVersion());
|
|
|
|
|
|
|
|
for( pos=cmdopt_defs; pos->name1; ++pos)
|
|
|
|
{
|
|
|
|
localPos = *pos;
|
|
|
|
localize_option_names(&localPos);
|
|
|
|
printf(" <option class=\"%s\">\n", cmdopt_catname[pos->cat].mnemonic );
|
|
|
|
print_xml_help_option_element("name", localPos.name1);
|
|
|
|
print_xml_help_option_element("name", localPos.name2);
|
|
|
|
print_xml_help_option_element("name", localPos.name3);
|
|
|
|
print_xml_help_option_element("description", tidyLocalizedString( pos->key ) );
|
|
|
|
if (pos->eqconfig)
|
|
|
|
print_xml_help_option_element("eqconfig", localPos.eqconfig);
|
|
|
|
else
|
|
|
|
printf(" <eqconfig />\n");
|
|
|
|
printf(" </option>\n");
|
|
|
|
|
|
|
|
if (localPos.name1) free((tmbstr)localPos.name1);
|
|
|
|
if (localPos.name2) free((tmbstr)localPos.name2);
|
|
|
|
if (localPos.name3) free((tmbstr)localPos.name3);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf( "</cmdline>\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end service_xmlhelp group */
|
|
|
|
/* MARK: - Provide the -xml-options-strings Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_xml_opts_strings Provide the -xml-options-strings Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** Handles printing of option description for -xml-options-strings service.
|
|
|
|
**/
|
|
|
|
static void printXMLOptionString(TidyDoc tdoc, /**< The Tidy document. */
|
|
|
|
TidyOption topt, /**< The option. */
|
|
|
|
OptionDesc *d /**< The OptionDesc array. */
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if ( tidyOptGetCategory(topt) == TidyInternalCategory )
|
|
|
|
return;
|
|
|
|
|
|
|
|
printf( " <option>\n" );
|
|
|
|
printf( " <name>%s</name>\n",d->name);
|
|
|
|
printf( " <string class=\"%s\"><![CDATA[%s]]></string>\n", tidyGetLanguage(), tidyOptGetDoc( tdoc, topt ) );
|
|
|
|
printf( " </option>\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Handles the -xml-options-strings service.
|
|
|
|
** This service is primarily helpful to developers and localizers to test
|
|
|
|
** that option description strings as represented on screen output are
|
|
|
|
** correct and do not break tidy.
|
|
|
|
** @param tdoc The Tidy document.
|
|
|
|
*/
|
|
|
|
static void xml_options_strings( TidyDoc tdoc )
|
|
|
|
{
|
|
|
|
printf( "<?xml version=\"1.0\"?>\n"
|
|
|
|
"<options_strings version=\"%s\">\n", tidyLibraryVersion());
|
|
|
|
ForEachOption( tdoc, printXMLOptionString);
|
|
|
|
printf( "</options_strings>\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @} end service_xml_opts_strings group */
|
|
|
|
/* MARK: - Provide the -xml-strings Service */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup service_xml_strings Provide the -xml-strings Service
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
|
|
|
*/
|
2016-02-17 04:35:20 +00:00
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** Handles the -xml-strings service.
|
|
|
|
** This service was primarily helpful to developers and localizers to compare
|
|
|
|
** localized strings to the built in `en` strings. It's probably better to use
|
|
|
|
** our POT/PO workflow with your favorite tools, or simply diff the language
|
|
|
|
** header files directly.
|
|
|
|
** @note The attribute `id` is not a specification, promise, or part of an
|
|
|
|
** API. You must not depend on this value. For strings meant for error
|
|
|
|
** output, the `label` attribute will contain the stringified version of
|
|
|
|
** the internal key for the string.
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
|
|
|
static void xml_strings( void )
|
|
|
|
{
|
|
|
|
uint i;
|
|
|
|
TidyIterator j;
|
2016-01-25 12:58:55 +00:00
|
|
|
|
|
|
|
ctmbstr current_language = tidyGetLanguage();
|
2017-02-13 19:29:47 +00:00
|
|
|
ctmbstr current_label;
|
2016-01-25 12:58:55 +00:00
|
|
|
Bool skip_current = strcmp( current_language, "en" ) == 0;
|
|
|
|
Bool matches_base;
|
|
|
|
|
|
|
|
printf( "<?xml version=\"1.0\"?>\n"
|
|
|
|
"<localized_strings version=\"%s\">\n", tidyLibraryVersion());
|
|
|
|
|
|
|
|
j = getStringKeyList();
|
2016-01-15 04:06:15 +00:00
|
|
|
while (j) {
|
|
|
|
i = getNextStringKey(&j);
|
2017-02-13 19:29:47 +00:00
|
|
|
current_label = tidyErrorCodeAsKey(i);
|
|
|
|
if (!strcmp(current_label, "UNDEFINED"))
|
|
|
|
current_label = "";
|
|
|
|
printf( "<localized_string id=\"%u\" label=\"%s\">\n", i, current_label );
|
2016-01-25 12:58:55 +00:00
|
|
|
printf( " <string class=\"%s\">", "en" );
|
|
|
|
printf("%s", tidyDefaultString(i));
|
|
|
|
printf( "</string>\n" );
|
|
|
|
if ( !skip_current ) {
|
|
|
|
matches_base = strcmp( tidyLocalizedString(i), tidyDefaultString(i) ) == 0;
|
|
|
|
printf( " <string class=\"%s\" same_as_base=\"%s\">", tidyGetLanguage(), matches_base ? "yes" : "no" );
|
|
|
|
printf("%s", tidyLocalizedString(i));
|
|
|
|
printf( "</string>\n" );
|
|
|
|
}
|
|
|
|
printf( "</localized_string>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
printf( "</localized_strings>\n" );
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end service_xml_strings group */
|
|
|
|
/* MARK: - Experimental Stuff */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup experimental_stuff Experimental Stuff
|
|
|
|
** From time to time the developers might leave stuff here that you can use
|
|
|
|
** to experiment on their own, or that they're using to experiment with.
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** This callback from LibTidy allows the console application to examine an
|
|
|
|
** error message before allowing LibTidy to display it. Currently the body
|
|
|
|
** of the function is not compiled into Tidy, but if you're interested in
|
|
|
|
** how to use the new message API, then enable it. Possible applications in
|
|
|
|
** future console Tidy might be to do things like:
|
|
|
|
** - allow user-defined filtering
|
|
|
|
** - sort the report output by line number
|
|
|
|
** - other things that are user facing and best not put into LibTidy
|
|
|
|
** proper.
|
Massive Revamp of the Messaging System
This is a rather large refactoring of Tidy's messaging system. This was done
mostly to allow non-C libraries that cannot adequately take advantage of
arg_lists a chance to query report filter information for information related
to arguments used in constructing an error message.
Three main goals were in mind for this project:
- Don't change the contents of Tidy's existing output sinks. This will ensure
that changes do no affect console Tidy users, or LibTidy users who use the
output sinks directly. This was accomplished 100% other than some improved
cosmetics in the output. See tidy-html5-tests repository, the `refactor` and
`more_messages_changes` branches for these minor diffs.
- Provide an API that is simple and also extensible without having to write new
error filters all the time. This was accomplished by adding the new message
callback `TidyMessageCallback` that provides callback functions an opaque
object representing the message, and an API to query the message for wanted
details. With this, we should never have to add a new callback routine again,
as additional API can simply be written against the opaque object.
- The API should work the same as the rest of LibTidy's API in that it's
consistent and only uses simple types with wide interoperability with other
languages. Thanks to @gagern who suggested the model for the API in #409.
Although the API uses the "Tidy" way off accessing data via an iterator
rather than an index, this can be easily abstracted in the target language.
There are two *major* API breaking changes:
- Removed TidyReportFilter2
- This was only used by one application in the entire world, and was a hacky
kludge that served its purpose. TidyReportCallback (né TidyReportFilter3)
is much better. If, for some reason, this affects you, I recommend using
TidyReportCallback instead. It's a minor change for your application.
- Renamed TidyReportFilter3 to TidyReportCallback
- This name is much more semantic, and much more sensible in light of
improved callback system. As the name implies, it remains capable of
*only* receiving callbacks for Tidy "reports."
Introducing TidyMessageCallback, and a new message interrogation API.
- As its name implies, it is able to capture (and optionally suppress) *all*
of Tidy's output, including the dialogue messages that never make it to
the existing report filters.
- Provides an opaque `TidyMessage` and an API that can be used to query against
it to find the juicy goodness inside.
- For example, `tidyGetMessageOutput( tmessage )` will return the complete,
localized message.
- Another example, `tidyGetMessageLine( tmessage )` will return the line the
message applies to.
- You can also get information about the individual arguments that make up a
message. By using the `tidyGetMessageArguments( tmessage )` itorator and
`tidyGetNextMessageArgument` you will obtain an opaque `TidyMessageArgument`
which has its own interrogation API. For example:
- tidyGetArgType( tmessage, &iterator );
- tidyGetArgFormat( tmessage, &iterator );
- tidyGetArgValueString( tmessage, &iterator );
- …and so on.
Other major changes include refactoring `messages.c` to use the new message
"object" directly when emitting messages to the console or output sinks. This
allowed replacement of a lot of specialized functions with generalized ones.
Some of this generalizing involved modifications to the `language_xx.h` header
files, and these are all positive improvements even without the above changes.
2017-03-13 17:28:57 +00:00
|
|
|
*/
|
|
|
|
static Bool TIDY_CALL reportCallback(TidyMessage tmessage)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
TidyIterator pos;
|
|
|
|
TidyMessageArgument arg;
|
|
|
|
TidyFormatParameterType messageType;
|
|
|
|
ctmbstr messageFormat;
|
|
|
|
|
|
|
|
printf("FILTER: %s, %s\n", tidyGetMessageKey( tmessage ), tidyGetMessageOutput( tmessage ));
|
|
|
|
|
|
|
|
/* loop through the arguments, if any, and print their details */
|
|
|
|
pos = tidyGetMessageArguments( tmessage );
|
|
|
|
while ( pos )
|
|
|
|
{
|
|
|
|
arg = tidyGetNextMessageArgument( tmessage, &pos );
|
|
|
|
messageType = tidyGetArgType( tmessage, &arg );
|
|
|
|
messageFormat = tidyGetArgFormat( tmessage, &arg );
|
|
|
|
printf( " Type = %u, Format = %s, Value = ", messageType, messageFormat );
|
|
|
|
|
|
|
|
switch (messageType)
|
|
|
|
{
|
|
|
|
case tidyFormatType_STRING:
|
|
|
|
printf("%s\n", tidyGetArgValueString( tmessage, &arg ));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case tidyFormatType_INT:
|
|
|
|
printf("%d\n", tidyGetArgValueInt( tmessage, &arg));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case tidyFormatType_UINT:
|
|
|
|
printf("%u\n", tidyGetArgValueUInt( tmessage, &arg));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case tidyFormatType_DOUBLE:
|
|
|
|
printf("%g\n", tidyGetArgValueDouble( tmessage, &arg));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printf("%s", "unknown so far\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return no; /* suppress LibTidy's own output of this message */
|
|
|
|
#else
|
|
|
|
return yes; /* needed so Tidy will not block output of this message */
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
/** @} end experimental_stuff group */
|
|
|
|
/* MARK: - main() */
|
|
|
|
/***************************************************************************//**
|
|
|
|
** @defgroup main Main
|
|
|
|
** Let's do something here!
|
|
|
|
*******************************************************************************
|
|
|
|
** @{
|
2016-01-15 04:06:15 +00:00
|
|
|
*/
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
int main( int argc, char** argv )
|
|
|
|
{
|
2016-01-25 12:58:55 +00:00
|
|
|
ctmbstr prog = argv[0];
|
|
|
|
ctmbstr cfgfil = NULL, errfil = NULL, htmlfil = NULL;
|
2017-09-17 14:27:17 +00:00
|
|
|
TidyDoc tdoc = NULL;
|
2016-01-25 12:58:55 +00:00
|
|
|
int status = 0;
|
|
|
|
tmbstr locale = NULL;
|
|
|
|
|
|
|
|
uint contentErrors = 0;
|
|
|
|
uint contentWarnings = 0;
|
|
|
|
uint accessWarnings = 0;
|
|
|
|
|
2017-09-17 14:27:17 +00:00
|
|
|
#if !defined(NDEBUG) && defined(_MSC_VER)
|
|
|
|
#if defined(_CRTDBG_MAP_ALLOC)
|
|
|
|
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
|
|
|
#endif
|
|
|
|
set_log_file((char *)"temptidy.txt", 0);
|
|
|
|
/* add_append_log(1); */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
tdoc = tidyCreate();
|
|
|
|
|
2017-05-30 16:15:25 +00:00
|
|
|
tidySetMessageCallback( tdoc, reportCallback); /* experimental group */
|
2016-01-25 12:58:55 +00:00
|
|
|
errout = stderr; /* initialize to stderr */
|
|
|
|
|
2016-01-29 03:11:53 +00:00
|
|
|
/* Set an atexit handler. */
|
|
|
|
atexit( tidy_cleanup );
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/*************************************/
|
2016-01-25 12:58:55 +00:00
|
|
|
/* Set the locale for tidy's output. */
|
2017-04-04 18:07:20 +00:00
|
|
|
/*************************************/
|
2016-01-25 12:58:55 +00:00
|
|
|
locale = tidySystemLocale(locale);
|
|
|
|
tidySetLanguage(locale);
|
|
|
|
if ( locale )
|
|
|
|
free( locale );
|
|
|
|
|
2016-01-29 03:11:53 +00:00
|
|
|
#if defined(_WIN32)
|
|
|
|
/* Force Windows console to use UTF, otherwise many characters will
|
|
|
|
* be garbage. Note that East Asian languages *are* supported, but
|
|
|
|
* only when Windows OS locale (not console only!) is set to an
|
|
|
|
* East Asian language.
|
|
|
|
*/
|
|
|
|
win_cp = GetConsoleOutputCP();
|
|
|
|
SetConsoleOutputCP(CP_UTF8);
|
|
|
|
#endif
|
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
/*
|
|
|
|
* Look for default configuration files using any of
|
|
|
|
* the following possibilities:
|
|
|
|
* - TIDY_CONFIG_FILE - from tidyplatform.h, typically /etc/tidy.conf
|
|
|
|
* - HTML_TIDY - environment variable
|
|
|
|
* - TIDY_USER_CONFIG_FILE - from tidyplatform.h, typically ~/tidy.conf
|
|
|
|
*/
|
2011-11-17 02:44:16 +00:00
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
#ifdef TIDY_CONFIG_FILE
|
2016-01-25 12:58:55 +00:00
|
|
|
if ( tidyFileExists( tdoc, TIDY_CONFIG_FILE) )
|
|
|
|
{
|
|
|
|
status = tidyLoadConfig( tdoc, TIDY_CONFIG_FILE );
|
|
|
|
if ( status != 0 ) {
|
|
|
|
fprintf(errout, tidyLocalizedString( TC_MAIN_ERROR_LOAD_CONFIG ), TIDY_CONFIG_FILE, status);
|
|
|
|
fprintf(errout, "\n");
|
|
|
|
}
|
|
|
|
}
|
2016-01-15 04:06:15 +00:00
|
|
|
#endif /* TIDY_CONFIG_FILE */
|
2016-01-25 12:58:55 +00:00
|
|
|
|
|
|
|
if ( (cfgfil = getenv("HTML_TIDY")) != NULL )
|
|
|
|
{
|
|
|
|
status = tidyLoadConfig( tdoc, cfgfil );
|
|
|
|
if ( status != 0 ) {
|
|
|
|
fprintf(errout, tidyLocalizedString( TC_MAIN_ERROR_LOAD_CONFIG ), cfgfil, status);
|
|
|
|
fprintf(errout, "\n");
|
|
|
|
}
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
#ifdef TIDY_USER_CONFIG_FILE
|
2016-01-25 12:58:55 +00:00
|
|
|
else if ( tidyFileExists( tdoc, TIDY_USER_CONFIG_FILE) )
|
|
|
|
{
|
|
|
|
status = tidyLoadConfig( tdoc, TIDY_USER_CONFIG_FILE );
|
|
|
|
if ( status != 0 ) {
|
|
|
|
fprintf(errout, tidyLocalizedString( TC_MAIN_ERROR_LOAD_CONFIG ), TIDY_USER_CONFIG_FILE, status);
|
|
|
|
fprintf(errout, "\n");
|
|
|
|
}
|
|
|
|
}
|
2011-11-17 02:44:16 +00:00
|
|
|
#endif /* TIDY_USER_CONFIG_FILE */
|
|
|
|
|
2016-01-15 04:06:15 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
/*
|
|
|
|
* Read command line
|
|
|
|
*/
|
|
|
|
|
|
|
|
while ( argc > 0 )
|
|
|
|
{
|
|
|
|
if (argc > 1 && argv[1][0] == '-')
|
|
|
|
{
|
|
|
|
/* support -foo and --foo */
|
|
|
|
ctmbstr arg = argv[1] + 1;
|
|
|
|
|
|
|
|
if ( strcasecmp(arg, "xml") == 0)
|
|
|
|
tidyOptSetBool( tdoc, TidyXmlTags, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "asxml") == 0 ||
|
|
|
|
strcasecmp(arg, "asxhtml") == 0 )
|
|
|
|
{
|
|
|
|
tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "ashtml") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyHtmlOut, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "indent") == 0 )
|
|
|
|
{
|
|
|
|
tidyOptSetInt( tdoc, TidyIndentContent, TidyAutoState );
|
|
|
|
if ( tidyOptGetInt(tdoc, TidyIndentSpaces) == 0 )
|
|
|
|
tidyOptResetToDefault( tdoc, TidyIndentSpaces );
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "omit") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyOmitOptionalTags, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "upper") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyUpperCaseTags, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "clean") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyMakeClean, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "gdoc") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyGDocClean, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "bare") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyMakeBare, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "raw") == 0 ||
|
|
|
|
strcasecmp(arg, "ascii") == 0 ||
|
|
|
|
strcasecmp(arg, "latin0") == 0 ||
|
|
|
|
strcasecmp(arg, "latin1") == 0 ||
|
|
|
|
strcasecmp(arg, "utf8") == 0 ||
|
2011-11-17 02:44:16 +00:00
|
|
|
#ifndef NO_NATIVE_ISO2022_SUPPORT
|
2016-01-25 12:58:55 +00:00
|
|
|
strcasecmp(arg, "iso2022") == 0 ||
|
2011-11-17 02:44:16 +00:00
|
|
|
#endif
|
2016-01-25 12:58:55 +00:00
|
|
|
strcasecmp(arg, "utf16le") == 0 ||
|
|
|
|
strcasecmp(arg, "utf16be") == 0 ||
|
|
|
|
strcasecmp(arg, "utf16") == 0 ||
|
|
|
|
strcasecmp(arg, "shiftjis") == 0 ||
|
|
|
|
strcasecmp(arg, "big5") == 0 ||
|
|
|
|
strcasecmp(arg, "mac") == 0 ||
|
|
|
|
strcasecmp(arg, "win1252") == 0 ||
|
|
|
|
strcasecmp(arg, "ibm858") == 0 )
|
|
|
|
{
|
|
|
|
tidySetCharEncoding( tdoc, arg );
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "numeric") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyNumEntities, yes );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "modify") == 0 ||
|
|
|
|
strcasecmp(arg, "change") == 0 || /* obsolete */
|
|
|
|
strcasecmp(arg, "update") == 0 ) /* obsolete */
|
|
|
|
{
|
|
|
|
tidyOptSetBool( tdoc, TidyWriteBack, yes );
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "errors") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyShowMarkup, no );
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "quiet") == 0 )
|
|
|
|
tidyOptSetBool( tdoc, TidyQuiet, yes );
|
|
|
|
|
|
|
|
/* Currenly user must specify a language
|
|
|
|
prior to anything that causes output */
|
|
|
|
else if ( strcasecmp(arg, "language") == 0 ||
|
|
|
|
strcasecmp(arg, "lang") == 0 )
|
|
|
|
if ( argc >= 3)
|
|
|
|
{
|
|
|
|
if ( strcasecmp(argv[2], "help") == 0 )
|
|
|
|
{
|
2017-04-04 18:07:20 +00:00
|
|
|
lang_help( tdoc );
|
2016-01-25 12:58:55 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
if ( !tidySetLanguage( argv[2] ) )
|
|
|
|
{
|
|
|
|
printf(tidyLocalizedString(TC_STRING_LANG_NOT_FOUND),
|
|
|
|
argv[2], tidyGetLanguage());
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf( "%s\n", tidyLocalizedString(TC_STRING_LANG_MUST_SPECIFY));
|
|
|
|
}
|
|
|
|
|
2017-09-22 21:27:49 +00:00
|
|
|
else if ( strcasecmp(arg, "help") == 0 ||
|
|
|
|
strcasecmp(arg, "-help") == 0 ||
|
|
|
|
strcasecmp(arg, "h") == 0 || *arg == '?' )
|
|
|
|
{
|
|
|
|
help( tdoc, prog );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "xml-help") == 0)
|
|
|
|
{
|
|
|
|
xml_help( );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "xml-error-strings") == 0)
|
|
|
|
{
|
|
|
|
xml_error_strings( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "xml-options-strings") == 0)
|
|
|
|
{
|
|
|
|
xml_options_strings( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "xml-strings") == 0)
|
|
|
|
{
|
|
|
|
xml_strings( );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "help-config") == 0 )
|
|
|
|
{
|
|
|
|
optionhelp( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
2017-10-01 22:58:17 +00:00
|
|
|
else if ( strcasecmp(arg, "help-env") == 0 )
|
|
|
|
{
|
|
|
|
helpEnv( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
else if ( strcasecmp(arg, "help-option") == 0 )
|
|
|
|
{
|
|
|
|
if ( argc >= 3)
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
optionDescribe( tdoc, argv[2] );
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
else
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
printf( "%s\n", tidyLocalizedString(TC_STRING_MUST_SPECIFY));
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "xml-config") == 0 )
|
|
|
|
{
|
|
|
|
XMLoptionhelp( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "show-config") == 0 )
|
|
|
|
{
|
|
|
|
optionvalues( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
2017-10-01 23:49:44 +00:00
|
|
|
else if ( strcasecmp(arg, "export-config") == 0 )
|
|
|
|
{
|
|
|
|
exportOptionValues( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "export-default-config") == 0 )
|
|
|
|
{
|
|
|
|
exportDefaultOptionValues( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
else if ( strcasecmp(arg, "config") == 0 )
|
|
|
|
{
|
|
|
|
if ( argc >= 3 )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
ctmbstr post;
|
|
|
|
|
|
|
|
tidyLoadConfig( tdoc, argv[2] );
|
|
|
|
|
|
|
|
/* Set new error output stream if setting changed */
|
|
|
|
post = tidyOptGetValue( tdoc, TidyErrFile );
|
|
|
|
if ( post && (!errfil || !samefile(errfil, post)) )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
errfil = post;
|
|
|
|
errout = tidySetErrorFile( tdoc, post );
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
|
|
|
|
--argc;
|
|
|
|
++argv;
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else if ( strcasecmp(arg, "output") == 0 ||
|
|
|
|
strcasecmp(arg, "-output-file") == 0 ||
|
|
|
|
strcasecmp(arg, "o") == 0 )
|
|
|
|
{
|
|
|
|
if ( argc >= 3 )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
tidyOptSetValue( tdoc, TidyOutFile, argv[2] );
|
|
|
|
--argc;
|
|
|
|
++argv;
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "file") == 0 ||
|
|
|
|
strcasecmp(arg, "-file") == 0 ||
|
|
|
|
strcasecmp(arg, "f") == 0 )
|
|
|
|
{
|
|
|
|
if ( argc >= 3 )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
errfil = argv[2];
|
|
|
|
errout = tidySetErrorFile( tdoc, errfil );
|
|
|
|
--argc;
|
|
|
|
++argv;
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "wrap") == 0 ||
|
|
|
|
strcasecmp(arg, "-wrap") == 0 ||
|
|
|
|
strcasecmp(arg, "w") == 0 )
|
|
|
|
{
|
|
|
|
if ( argc >= 3 )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
uint wraplen = 0;
|
|
|
|
int nfields = sscanf( argv[2], "%u", &wraplen );
|
|
|
|
tidyOptSetInt( tdoc, TidyWrapLen, wraplen );
|
|
|
|
if (nfields > 0)
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
}
|
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
}
|
|
|
|
else if ( strcasecmp(arg, "version") == 0 ||
|
|
|
|
strcasecmp(arg, "-version") == 0 ||
|
|
|
|
strcasecmp(arg, "v") == 0 )
|
|
|
|
{
|
|
|
|
version( tdoc );
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
return 0; /* success */
|
2016-01-25 12:58:55 +00:00
|
|
|
|
2017-09-22 21:27:49 +00:00
|
|
|
}
|
|
|
|
else if ( strncmp(argv[1], "--", 2 ) == 0)
|
|
|
|
{
|
|
|
|
if ( tidyOptParseValue(tdoc, argv[1]+2, argv[2]) )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
/* Set new error output stream if setting changed */
|
|
|
|
ctmbstr post = tidyOptGetValue( tdoc, TidyErrFile );
|
|
|
|
if ( post && (!errfil || !samefile(errfil, post)) )
|
2016-01-25 12:58:55 +00:00
|
|
|
{
|
2017-09-22 21:27:49 +00:00
|
|
|
errfil = post;
|
|
|
|
errout = tidySetErrorFile( tdoc, post );
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
|
|
|
|
2017-09-22 21:27:49 +00:00
|
|
|
++argv;
|
|
|
|
--argc;
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
2017-09-22 21:27:49 +00:00
|
|
|
}
|
2016-01-25 12:58:55 +00:00
|
|
|
else if ( strcasecmp(arg, "access") == 0 )
|
|
|
|
{
|
|
|
|
if ( argc >= 3 )
|
|
|
|
{
|
|
|
|
uint acclvl = 0;
|
|
|
|
int nfields = sscanf( argv[2], "%u", &acclvl );
|
|
|
|
tidyOptSetInt( tdoc, TidyAccessibilityCheckLevel, acclvl );
|
|
|
|
if (nfields > 0)
|
|
|
|
{
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint c;
|
|
|
|
ctmbstr s = argv[1];
|
|
|
|
|
|
|
|
while ( (c = *++s) != '\0' )
|
|
|
|
{
|
|
|
|
switch ( c )
|
|
|
|
{
|
|
|
|
case 'i':
|
|
|
|
tidyOptSetInt( tdoc, TidyIndentContent, TidyAutoState );
|
|
|
|
if ( tidyOptGetInt(tdoc, TidyIndentSpaces) == 0 )
|
|
|
|
tidyOptResetToDefault( tdoc, TidyIndentSpaces );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
tidyOptSetBool( tdoc, TidyUpperCaseTags, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
tidyOptSetBool( tdoc, TidyMakeClean, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g':
|
|
|
|
tidyOptSetBool( tdoc, TidyGDocClean, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
tidyOptSetBool( tdoc, TidyMakeBare, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
tidyOptSetBool( tdoc, TidyNumEntities, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
tidyOptSetBool( tdoc, TidyWriteBack, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'e':
|
|
|
|
tidyOptSetBool( tdoc, TidyShowMarkup, no );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'q':
|
|
|
|
tidyOptSetBool( tdoc, TidyQuiet, yes );
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2017-04-04 18:07:20 +00:00
|
|
|
unknownOption( tdoc, c );
|
2016-01-25 12:58:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
2016-01-25 12:58:55 +00:00
|
|
|
if ( argc > 1 )
|
|
|
|
{
|
|
|
|
htmlfil = argv[1];
|
2014-08-03 18:52:10 +00:00
|
|
|
#if (!defined(NDEBUG) && defined(_MSC_VER))
|
2016-01-25 12:58:55 +00:00
|
|
|
SPRTF("Tidying '%s'\n", htmlfil);
|
2016-10-25 14:41:03 +00:00
|
|
|
#endif /* DEBUG outout */
|
2017-03-08 01:11:31 +00:00
|
|
|
if ( tidyOptGetBool(tdoc, TidyEmacs) )
|
|
|
|
tidySetEmacsFile( tdoc, htmlfil );
|
2016-01-25 12:58:55 +00:00
|
|
|
status = tidyParseFile( tdoc, htmlfil );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
htmlfil = "stdin";
|
|
|
|
status = tidyParseStdin( tdoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( status >= 0 )
|
|
|
|
status = tidyCleanAndRepair( tdoc );
|
|
|
|
|
|
|
|
if ( status >= 0 ) {
|
|
|
|
status = tidyRunDiagnostics( tdoc );
|
2017-03-17 17:02:11 +00:00
|
|
|
/*\ Issue #119 - but not really related to 'custom_tags' support.
|
|
|
|
* Issue ?: To remove some 2014 extra debug output - I wanted to
|
|
|
|
* remove the Info: messages, but chose to except one, namely
|
|
|
|
* tidyReportDoctype(), but never intended keeping it here
|
|
|
|
* for so long!
|
|
|
|
* That doctype Info:, and all others, are still reported by
|
|
|
|
* default. geoff
|
|
|
|
\*/
|
|
|
|
#if 0 /* 000000000 this code can be removed some time in future 00000000000 */
|
2016-01-25 12:58:55 +00:00
|
|
|
if ( !tidyOptGetBool(tdoc, TidyQuiet) ) {
|
|
|
|
/* NOT quiet, show DOCTYPE, if not already shown */
|
|
|
|
if (!tidyOptGetBool(tdoc, TidyShowInfo)) {
|
|
|
|
tidyOptSetBool( tdoc, TidyShowInfo, yes );
|
|
|
|
tidyReportDoctype( tdoc ); /* FIX20140913: like warnings, errors, ALWAYS report DOCTYPE */
|
|
|
|
tidyOptSetBool( tdoc, TidyShowInfo, no );
|
|
|
|
}
|
|
|
|
}
|
2017-03-17 17:02:11 +00:00
|
|
|
#endif /* 000000000 this code can be removed some time in future 00000000000 */
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
|
|
|
if ( status > 1 ) /* If errors, do we want to force output? */
|
|
|
|
status = ( tidyOptGetBool(tdoc, TidyForceOutput) ? status : -1 );
|
|
|
|
|
|
|
|
if ( status >= 0 && tidyOptGetBool(tdoc, TidyShowMarkup) )
|
|
|
|
{
|
|
|
|
if ( tidyOptGetBool(tdoc, TidyWriteBack) && argc > 1 )
|
|
|
|
status = tidySaveFile( tdoc, htmlfil );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ctmbstr outfil = tidyOptGetValue( tdoc, TidyOutFile );
|
|
|
|
if ( outfil ) {
|
|
|
|
status = tidySaveFile( tdoc, outfil );
|
|
|
|
} else {
|
2014-08-03 18:33:29 +00:00
|
|
|
#if !defined(NDEBUG) && defined(_MSC_VER)
|
2016-01-25 12:58:55 +00:00
|
|
|
static char tmp_buf[264];
|
|
|
|
sprintf(tmp_buf,"%s.html",get_log_file());
|
|
|
|
status = tidySaveFile( tdoc, tmp_buf );
|
|
|
|
SPRTF("Saved tidied content to '%s'\n",tmp_buf);
|
2014-08-03 18:33:29 +00:00
|
|
|
#else
|
2016-01-25 12:58:55 +00:00
|
|
|
status = tidySaveStdout( tdoc );
|
2014-08-03 18:33:29 +00:00
|
|
|
#endif
|
2016-01-25 12:58:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
contentErrors += tidyErrorCount( tdoc );
|
|
|
|
contentWarnings += tidyWarningCount( tdoc );
|
|
|
|
accessWarnings += tidyAccessWarningCount( tdoc );
|
|
|
|
|
|
|
|
--argc;
|
|
|
|
++argv;
|
|
|
|
|
|
|
|
if ( argc <= 1 )
|
|
|
|
break;
|
|
|
|
} /* read command line loop */
|
|
|
|
|
|
|
|
|
|
|
|
if (!tidyOptGetBool(tdoc, TidyQuiet) &&
|
|
|
|
errout == stderr && !contentErrors)
|
|
|
|
fprintf(errout, "\n");
|
|
|
|
|
|
|
|
if (contentErrors + contentWarnings > 0 &&
|
|
|
|
!tidyOptGetBool(tdoc, TidyQuiet))
|
|
|
|
tidyErrorSummary(tdoc);
|
|
|
|
|
|
|
|
if (!tidyOptGetBool(tdoc, TidyQuiet))
|
|
|
|
tidyGeneralInfo(tdoc);
|
|
|
|
|
|
|
|
/* called to free hash tables etc. */
|
|
|
|
tidyRelease( tdoc );
|
|
|
|
|
|
|
|
/* return status can be used by scripts */
|
|
|
|
if ( contentErrors > 0 )
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
if ( contentWarnings > 0 )
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* 0 signifies all is ok */
|
|
|
|
return 0;
|
2011-11-17 02:44:16 +00:00
|
|
|
}
|
|
|
|
|
2017-04-04 18:07:20 +00:00
|
|
|
|
|
|
|
/** @} end main group */
|
|
|
|
/** @} end console_application group */
|
|
|
|
|
|
|
|
|
2011-11-17 02:44:16 +00:00
|
|
|
/*
|
|
|
|
* local variables:
|
|
|
|
* mode: c
|
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* eval: (c-set-offset 'substatement-open 0)
|
|
|
|
* end:
|
|
|
|
*/
|