~ubuntu-branches/ubuntu/precise/tidy/precise-updates

« back to all changes in this revision

Viewing changes to console/tidy.c

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2005-04-20 11:22:49 UTC
  • mto: (3.1.1 lenny)
  • mto: This revision was merged to the branch mainline in revision 2.
  • Revision ID: james.westby@ubuntu.com-20050420112249-epdnkgi03ubep83z
Tags: upstream-20050415
ImportĀ upstreamĀ versionĀ 20050415

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  tidy.c - HTML TidyLib command line driver
 
3
 
 
4
  Copyright (c) 1998-2005 World Wide Web Consortium
 
5
  (Massachusetts Institute of Technology, European Research 
 
6
  Consortium for Informatics and Mathematics, Keio University).
 
7
  All Rights Reserved.
 
8
 
 
9
  CVS Info :
 
10
 
 
11
    $Author: arnaud02 $ 
 
12
    $Date: 2005/04/14 14:51:01 $ 
 
13
    $Revision: 1.34 $ 
 
14
*/
 
15
 
 
16
#include "tidy.h"
 
17
 
 
18
static FILE* errout = NULL;  /* set to stderr */
 
19
/* static FILE* txtout = NULL; */  /* set to stdout */
 
20
 
 
21
static Bool samefile( ctmbstr filename1, ctmbstr filename2 )
 
22
{
 
23
#if FILENAMES_CASE_SENSITIVE
 
24
    return ( strcmp( filename1, filename2 ) == 0 );
 
25
#else
 
26
    return ( strcasecmp( filename1, filename2 ) == 0 );
 
27
#endif
 
28
}
 
29
 
 
30
static const char *cutToWhiteSpace(const char *s, uint offset, char *sbuf)
 
31
{
 
32
    if (!s)
 
33
    {
 
34
        sbuf[0] = '\0';
 
35
        return NULL;
 
36
    }
 
37
    else if (strlen(s) <= offset)
 
38
    {
 
39
        strcpy(sbuf,s);
 
40
        sbuf[offset] = '\0';
 
41
        return NULL;
 
42
    }
 
43
    else
 
44
    {
 
45
        uint j, l, n;
 
46
        j = offset;
 
47
        while(j && s[j] != ' ')
 
48
            --j;
 
49
        l = j;
 
50
        n = j+1;
 
51
        /* no white space */
 
52
        if (j==0)
 
53
        {
 
54
            l = offset;
 
55
            n = offset;
 
56
        }
 
57
        strncpy(sbuf,s,l);
 
58
        sbuf[l] = '\0';
 
59
        return s+n;
 
60
    }
 
61
}
 
62
 
 
63
static void print2Columns( const char* fmt, uint l1, uint l2,
 
64
                           const char *c1, const char *c2 )
 
65
{
 
66
    const char *pc1=c1, *pc2=c2;
 
67
    char *c1buf = malloc(l1+1);
 
68
    char *c2buf = malloc(l2+1);
 
69
 
 
70
    do
 
71
    {
 
72
        pc1 = cutToWhiteSpace(pc1, l1, c1buf);
 
73
        pc2 = cutToWhiteSpace(pc2, l2, c2buf);
 
74
        printf(fmt,
 
75
               c1buf[0]!='\0'?c1buf:"",
 
76
               c2buf[0]!='\0'?c2buf:"");
 
77
    } while (pc1 || pc2);
 
78
    free(c1buf);
 
79
    free(c2buf);
 
80
}
 
81
 
 
82
static void print3Columns( const char* fmt, uint l1, uint l2, uint l3,
 
83
                           const char *c1, const char *c2, const char *c3 )
 
84
{
 
85
    const char *pc1=c1, *pc2=c2, *pc3=c3;
 
86
    char *c1buf = malloc(l1+1);
 
87
    char *c2buf = malloc(l2+1);
 
88
    char *c3buf = malloc(l3+1);
 
89
 
 
90
    do
 
91
    {
 
92
        pc1 = cutToWhiteSpace(pc1, l1, c1buf);
 
93
        pc2 = cutToWhiteSpace(pc2, l2, c2buf);
 
94
        pc3 = cutToWhiteSpace(pc3, l3, c3buf);
 
95
        printf(fmt,
 
96
               c1buf[0]!='\0'?c1buf:"",
 
97
               c2buf[0]!='\0'?c2buf:"",
 
98
               c3buf[0]!='\0'?c3buf:"");
 
99
    } while (pc1 || pc2 || pc3);
 
100
    free(c1buf);
 
101
    free(c2buf);
 
102
    free(c3buf);
 
103
}
 
104
 
 
105
static const char helpfmt[] = " %-19.19s %-58.58s\n";
 
106
static const char helpul[]
 
107
        = "-----------------------------------------------------------------";
 
108
static const char fmt[] = "%-27.27s %-9.9s  %-40.40s\n";
 
109
static const char valfmt[] = "%-27.27s %-9.9s %-1.1s%-39.39s\n";
 
110
static const char ul[]
 
111
        = "=================================================================";
 
112
 
 
113
typedef enum
 
114
{
 
115
  CmdOptFileManip,
 
116
  CmdOptCatFIRST = CmdOptFileManip,
 
117
  CmdOptProcDir,
 
118
  CmdOptCharEnc,
 
119
  CmdOptMisc,
 
120
  CmdOptCatLAST,
 
121
} CmdOptCategory;
 
122
 
 
123
static const struct {
 
124
    ctmbstr mnemonic;
 
125
    ctmbstr name;
 
126
} cmdopt_catname[] = {
 
127
    { "file-manip", "File manipulation" },
 
128
    { "process-directives", "Processing directives" },
 
129
    { "char-encoding", "Character encodings" },
 
130
    { "misc", "Miscellaneous" }
 
131
};
 
132
 
 
133
typedef struct {
 
134
    ctmbstr name1;      /**< Name */
 
135
    ctmbstr desc;       /**< Description */
 
136
    ctmbstr eqconfig;   /**< Equivalent configuration option */
 
137
    CmdOptCategory cat; /**< Category */
 
138
    ctmbstr name2;      /**< Name */
 
139
    ctmbstr name3;      /**< Name */
 
140
} CmdOptDesc;
 
141
 
 
142
static const CmdOptDesc cmdopt_defs[] =  {
 
143
    { "-output <file>",
 
144
      "write output to the specified <file>",
 
145
      "output-file: <file>", CmdOptFileManip, "-o <file>" },
 
146
    { "-config <file>",
 
147
      "set configuration options from the specified <file>",
 
148
      NULL, CmdOptFileManip },
 
149
    { "-file <file>",
 
150
      "write errors to the specified <file>",
 
151
      "error-file: <file>", CmdOptFileManip, "-f <file>" },
 
152
    { "-modify",
 
153
      "modify the original input files",
 
154
      "write-back: yes", CmdOptFileManip, "-m" },
 
155
    { "-indent",
 
156
      "indent element content",
 
157
      "indent: auto", CmdOptProcDir, "-i" },
 
158
    { "-wrap <column>",
 
159
      "wrap text at the specified <column> (default is 68)",
 
160
      "wrap: <column>", CmdOptProcDir, "-w <column>" },
 
161
    { "-upper",
 
162
      "force tags to upper case (default is lower case)",
 
163
      "uppercase-tags: yes", CmdOptProcDir, "-u" },
 
164
    { "-clean",
 
165
      "replace FONT, NOBR and CENTER tags by CSS",
 
166
      "clean: yes", CmdOptProcDir, "-c" },
 
167
    { "-bare",
 
168
      "strip out smart quotes and em dashes, etc.",
 
169
      "bare: yes", CmdOptProcDir, "-b" },
 
170
    { "-numeric",
 
171
      "output numeric rather than named entities",
 
172
      "numeric-entities: yes", CmdOptProcDir, "-n" },
 
173
    { "-errors",
 
174
      "only show errors",
 
175
      "markup: no", CmdOptProcDir, "-e" },
 
176
    { "-quiet",
 
177
      "suppress nonessential output",
 
178
      "quiet: yes", CmdOptProcDir, "-q" },
 
179
    { "-omit",
 
180
      "omit optional end tags",
 
181
      "hide-endtags: yes", CmdOptProcDir },
 
182
    { "-xml",
 
183
      "specify the input is well formed XML",
 
184
      "input-xml: yes", CmdOptProcDir },
 
185
    { "-asxml",
 
186
      "convert HTML to well formed XHTML",
 
187
      "output-xhtml: yes", CmdOptProcDir, "-asxhtml" },
 
188
    { "-ashtml",
 
189
      "force XHTML to well formed HTML",
 
190
      "output-html: yes", CmdOptProcDir },
 
191
#if SUPPORT_ACCESSIBILITY_CHECKS
 
192
    { "-access <level>",
 
193
      "do additional accessibility checks (<level> = 1, 2, 3)",
 
194
      "accessibility-check: <level>", CmdOptProcDir },
 
195
#endif
 
196
    { "-raw",
 
197
      "output values above 127 without conversion to entities",
 
198
      NULL, CmdOptCharEnc },
 
199
    { "-ascii",
 
200
      "use ISO-8859-1 for input, US-ASCII for output",
 
201
      NULL, CmdOptCharEnc },
 
202
    { "-latin0",
 
203
      "use ISO-8859-15 for input, US-ASCII for output",
 
204
      NULL, CmdOptCharEnc },
 
205
    { "-latin1",
 
206
      "use ISO-8859-1 for both input and output",
 
207
      NULL, CmdOptCharEnc },
 
208
#ifndef NO_NATIVE_ISO2022_SUPPORT
 
209
    { "-iso2022",
 
210
      "use ISO-2022 for both input and output",
 
211
      NULL, CmdOptCharEnc },
 
212
#endif
 
213
    { "-utf8",
 
214
      "use UTF-8 for both input and output",
 
215
      NULL, CmdOptCharEnc },
 
216
    { "-mac",
 
217
      "use MacRoman for input, US-ASCII for output",
 
218
      NULL, CmdOptCharEnc },
 
219
    { "-win1252",
 
220
      "use Windows-1252 for input, US-ASCII for output",
 
221
      NULL, CmdOptCharEnc },
 
222
    { "-ibm858",
 
223
      "use IBM-858 (CP850+Euro) for input, US-ASCII for output",
 
224
      NULL, CmdOptCharEnc },
 
225
#if SUPPORT_UTF16_ENCODINGS
 
226
    { "-utf16le",
 
227
      "use UTF-16LE for both input and output",
 
228
      NULL, CmdOptCharEnc },
 
229
    { "-utf16be",
 
230
      "use UTF-16BE for both input and output",
 
231
      NULL, CmdOptCharEnc },
 
232
    { "-utf16",
 
233
      "use UTF-16 for both input and output",
 
234
      NULL, CmdOptCharEnc },
 
235
#endif
 
236
#if SUPPORT_ASIAN_ENCODINGS /* #431953 - RJ */
 
237
    { "-big5",
 
238
      "use Big5 for both input and output",
 
239
      NULL, CmdOptCharEnc },
 
240
    { "-shiftjis",
 
241
      "use Shift_JIS for both input and output",
 
242
      NULL, CmdOptCharEnc },
 
243
    { "-language <lang>",
 
244
      "set the two-letter language code <lang> (for future use)",
 
245
      "language: <lang>", CmdOptCharEnc },
 
246
#endif
 
247
    { "-version",
 
248
      "show the version of Tidy",
 
249
      NULL, CmdOptMisc, "-v" },
 
250
    { "-help",
 
251
      "list the command line options",
 
252
      NULL, CmdOptMisc, "-h", "-?" },
 
253
    { "-xml-help",
 
254
      "list the command line options in XML format",
 
255
      NULL, CmdOptMisc },
 
256
    { "-help-config",
 
257
      "list all configuration options",
 
258
      NULL, CmdOptMisc },
 
259
    { "-xml-config",
 
260
      "list all configuration options in XML format",
 
261
      NULL, CmdOptMisc },
 
262
    { "-show-config",
 
263
      "list the current configuration settings",
 
264
      NULL, CmdOptMisc },
 
265
    { NULL, NULL, NULL, CmdOptMisc }
 
266
};
 
267
 
 
268
static tmbstr get_option_names( const CmdOptDesc* pos )
 
269
{
 
270
    tmbstr name;
 
271
    uint len = strlen(pos->name1);
 
272
    if (pos->name2)
 
273
        len += 2+strlen(pos->name2);
 
274
    if (pos->name3)
 
275
        len += 2+strlen(pos->name3);
 
276
 
 
277
    name = malloc(len+1);
 
278
    strcpy(name, pos->name1);
 
279
    if (pos->name2)
 
280
    {
 
281
        strcat(name, ", ");
 
282
        strcat(name, pos->name2);
 
283
    }
 
284
    if (pos->name3)
 
285
    {
 
286
        strcat(name, ", ");
 
287
        strcat(name, pos->name3);
 
288
    }
 
289
    return name;
 
290
}
 
291
 
 
292
static tmbstr get_escaped_name( ctmbstr name )
 
293
{
 
294
    tmbstr escpName;
 
295
    char aux[2];
 
296
    uint len = 0;
 
297
    ctmbstr c;
 
298
    for(c=name; *c!='\0'; ++c)
 
299
        switch(*c)
 
300
        {
 
301
        case '<':
 
302
        case '>':
 
303
            len += 4;
 
304
            break;
 
305
        case '"':
 
306
            len += 6;
 
307
            break;
 
308
        default:
 
309
            len += 1;
 
310
            break;
 
311
        }
 
312
 
 
313
    escpName = malloc(len+1);
 
314
    escpName[0] = '\0';
 
315
 
 
316
    aux[1] = '\0';
 
317
    for(c=name; *c!='\0'; ++c)
 
318
        switch(*c)
 
319
        {
 
320
        case '<':
 
321
            strcat(escpName, "&lt;");
 
322
            break;
 
323
        case '>':
 
324
            strcat(escpName, "&gt;");
 
325
            break;
 
326
        case '"':
 
327
            strcat(escpName, "&quot;");
 
328
            break;
 
329
        default:
 
330
            aux[0] = *c;
 
331
            strcat(escpName, aux);
 
332
            break;
 
333
        }
 
334
 
 
335
    return escpName;
 
336
}
 
337
 
 
338
static void print_help_option( void )
 
339
{
 
340
    CmdOptCategory cat = CmdOptCatFIRST;
 
341
    const CmdOptDesc* pos = cmdopt_defs;
 
342
 
 
343
    for( cat=CmdOptCatFIRST; cat!=CmdOptCatLAST; ++cat)
 
344
    {
 
345
        size_t len =  strlen(cmdopt_catname[cat].name);
 
346
        printf("%s\n", cmdopt_catname[cat].name );
 
347
        printf("%*.*s\n", len, len, helpul );
 
348
        for( pos=cmdopt_defs; pos->name1; ++pos)
 
349
        {
 
350
            tmbstr name;
 
351
            if (pos->cat != cat)
 
352
                continue;
 
353
            name = get_option_names( pos );
 
354
            print2Columns( helpfmt, 19, 58, name, pos->desc );
 
355
            free(name);
 
356
        }
 
357
        printf("\n");
 
358
    }
 
359
}
 
360
 
 
361
static void print_xml_help_option_element( ctmbstr element, ctmbstr name )
 
362
{
 
363
    tmbstr escpName;
 
364
    if (!name)
 
365
        return;
 
366
    printf("  <%s>%s</%s>\n", element, escpName = get_escaped_name(name),
 
367
           element);
 
368
    free(escpName);
 
369
}
 
370
 
 
371
static void print_xml_help_option( void )
 
372
{
 
373
    const CmdOptDesc* pos = cmdopt_defs;
 
374
 
 
375
    for( pos=cmdopt_defs; pos->name1; ++pos)
 
376
    {
 
377
        printf(" <option class=\"%s\">\n", cmdopt_catname[pos->cat].mnemonic );
 
378
        print_xml_help_option_element("name", pos->name1);
 
379
        print_xml_help_option_element("name", pos->name2);
 
380
        print_xml_help_option_element("name", pos->name3);
 
381
        print_xml_help_option_element("description", pos->desc);
 
382
        if (pos->eqconfig)
 
383
            print_xml_help_option_element("eqconfig", pos->eqconfig);
 
384
        else
 
385
            printf("  <eqconfig />\n");
 
386
        printf(" </option>\n");
 
387
    }
 
388
}
 
389
 
 
390
static void xml_help( void )
 
391
{
 
392
    printf( "<?xml version=\"1.0\"?>\n"
 
393
            "<cmdline version=\"%s\">\n", tidyReleaseDate());
 
394
    print_xml_help_option();
 
395
    printf( "</cmdline>\n" );
 
396
}
 
397
 
 
398
static void help( ctmbstr prog )
 
399
{
 
400
    printf( "%s [option...] [file...] [option...] [file...]\n", prog );
 
401
    printf( "Utility to clean up and pretty print HTML/XHTML/XML\n");
 
402
    printf( "see http://tidy.sourceforge.net/\n");
 
403
    printf( "\n");
 
404
 
 
405
#ifdef PLATFORM_NAME
 
406
    printf( "Options for HTML Tidy for %s released on %s:\n",
 
407
             PLATFORM_NAME, tidyReleaseDate() );
 
408
#else
 
409
    printf( "Options for HTML Tidy released on %s:\n", tidyReleaseDate() );
 
410
#endif
 
411
    printf( "\n");
 
412
 
 
413
    print_help_option();
 
414
 
 
415
    printf( "Use --blah blarg for any configuration option \"blah\" with argument \"blarg\"\n");
 
416
    printf( "\n");
 
417
 
 
418
    printf( "Input/Output default to stdin/stdout respectively\n");
 
419
    printf( "Single letter options apart from -f may be combined\n");
 
420
    printf( "as in:  tidy -f errs.txt -imu foo.html\n");
 
421
    printf( "For further info on HTML see http://www.w3.org/MarkUp\n");
 
422
    printf( "\n");
 
423
}
 
424
 
 
425
static Bool isAutoBool( TidyOption topt )
 
426
{
 
427
    TidyIterator pos;
 
428
    ctmbstr def;
 
429
 
 
430
    if ( tidyOptGetType( topt ) != TidyInteger)
 
431
        return no;
 
432
 
 
433
    pos = tidyOptGetPickList( topt );
 
434
    while ( pos )
 
435
    {
 
436
        def = tidyOptGetNextPick( topt, &pos );
 
437
        if (0==strcmp(def,"yes"))
 
438
           return yes;
 
439
    }
 
440
    return no;
 
441
}
 
442
 
 
443
static
 
444
ctmbstr ConfigCategoryName( TidyConfigCategory id )
 
445
{
 
446
    switch( id )
 
447
    {
 
448
    case TidyMarkup:
 
449
        return "markup";
 
450
    case TidyDiagnostics:
 
451
        return "diagnostics";
 
452
    case TidyPrettyPrint:
 
453
        return "print";
 
454
    case TidyEncoding:
 
455
        return "encoding";
 
456
    case TidyMiscellaneous:
 
457
        return "misc";
 
458
    }
 
459
    assert(0);
 
460
    abort();
 
461
}
 
462
 
 
463
/* Description of an option */
 
464
typedef struct {
 
465
    ctmbstr name;  /**< Name */
 
466
    ctmbstr cat;   /**< Category */
 
467
    ctmbstr type;  /**< "String, ... */
 
468
    ctmbstr vals;  /**< Potential values. If NULL, use an external function */
 
469
    ctmbstr def;   /**< default */
 
470
    tmbchar tempdefs[80]; /**< storage for default such as integer */
 
471
    Bool haveVals; /**< if yes, vals is valid */
 
472
} OptionDesc;
 
473
 
 
474
typedef void (*OptionFunc)( TidyDoc, TidyOption, OptionDesc * );
 
475
 
 
476
 
 
477
/* Create description "d" related to "opt" */
 
478
static
 
479
void GetOption( TidyDoc tdoc, TidyOption topt, OptionDesc *d )
 
480
{
 
481
    TidyOptionId optId = tidyOptGetId( topt );
 
482
    TidyOptionType optTyp = tidyOptGetType( topt );
 
483
 
 
484
    d->name = tidyOptGetName( topt );
 
485
    d->cat = ConfigCategoryName( tidyOptGetCategory( topt ) );
 
486
    d->vals = NULL;
 
487
    d->def = NULL;
 
488
    d->haveVals = yes;
 
489
 
 
490
    /* Handle special cases first.
 
491
     */
 
492
    switch ( optId )
 
493
    {
 
494
    case TidyDuplicateAttrs:
 
495
    case TidyNewline:
 
496
    case TidyAccessibilityCheckLevel:
 
497
        d->type = "enum";
 
498
        d->vals = NULL;
 
499
        d->def =
 
500
            optId==TidyNewline ?
 
501
            "<em>Platform dependent</em>"
 
502
            :tidyOptGetCurrPick( tdoc, optId );
 
503
        break;
 
504
 
 
505
    case TidyDoctype:
 
506
        d->type = "DocType";
 
507
        d->vals = NULL;
 
508
        {
 
509
            ctmbstr sdef = NULL;
 
510
            sdef = tidyOptGetCurrPick( tdoc, TidyDoctypeMode );
 
511
            if ( !sdef || *sdef == '*' )
 
512
                sdef = tidyOptGetValue( tdoc, TidyDoctype );
 
513
            d->def = sdef;
 
514
        }
 
515
        break;
 
516
 
 
517
    case TidyInlineTags:
 
518
    case TidyBlockTags:
 
519
    case TidyEmptyTags:
 
520
    case TidyPreTags:
 
521
        d->type = "Tag names";
 
522
        d->vals = "tagX, tagY, ...";
 
523
        d->def = NULL;
 
524
        break;
 
525
 
 
526
    case TidyCharEncoding:
 
527
    case TidyInCharEncoding:
 
528
    case TidyOutCharEncoding:
 
529
        d->type = "Encoding";
 
530
        d->def = tidyOptGetEncName( tdoc, optId );
 
531
        if (!d->def)
 
532
            d->def = "?";
 
533
        d->vals = NULL;
 
534
        break;
 
535
 
 
536
        /* General case will handle remaining */
 
537
    default:
 
538
        switch ( optTyp )
 
539
        {
 
540
        case TidyBoolean:
 
541
            d->type = "Boolean";
 
542
            d->vals = "y/n, yes/no, t/f, true/false, 1/0";
 
543
            d->def = tidyOptGetCurrPick( tdoc, optId );
 
544
            break;
 
545
 
 
546
        case TidyInteger:
 
547
            if (isAutoBool(topt))
 
548
            {
 
549
                d->type = "AutoBool";
 
550
                d->vals = "auto, y/n, yes/no, t/f, true/false, 1/0";
 
551
                d->def = tidyOptGetCurrPick( tdoc, optId );
 
552
            }
 
553
            else
 
554
            {
 
555
                uint idef;
 
556
                d->type = "Integer";
 
557
                if ( optId == TidyWrapLen )
 
558
                    d->vals = "0 (no wrapping), 1, 2, ...";
 
559
                else
 
560
                    d->vals = "0, 1, 2, ...";
 
561
 
 
562
                idef = tidyOptGetInt( tdoc, optId );
 
563
                sprintf(d->tempdefs, "%u", idef);
 
564
                d->def = d->tempdefs;
 
565
            }
 
566
            break;
 
567
 
 
568
        case TidyString:
 
569
            d->type = "String";
 
570
            d->vals = NULL;
 
571
            d->haveVals = no;
 
572
            d->def = tidyOptGetValue( tdoc, optId );
 
573
            break;
 
574
        }
 
575
    }
 
576
}
 
577
 
 
578
/* Array holding all options. Contains a trailing sentinel. */
 
579
typedef struct {
 
580
    TidyOption topt[N_TIDY_OPTIONS];
 
581
} AllOption_t;
 
582
 
 
583
static
 
584
int cmpOpt(const void* e1_, const void *e2_)
 
585
{
 
586
    const TidyOption* e1 = e1_;
 
587
    const TidyOption* e2 = e2_;
 
588
    return strcmp(tidyOptGetName(*e1), tidyOptGetName(*e2));
 
589
}
 
590
 
 
591
static
 
592
void getSortedOption( TidyDoc tdoc, AllOption_t *tOption )
 
593
{
 
594
    TidyIterator pos = tidyGetOptionList( tdoc );
 
595
    uint i = 0;
 
596
 
 
597
    while ( pos )
 
598
    {
 
599
        TidyOption topt = tidyGetNextOption( tdoc, &pos );
 
600
        tOption->topt[i] = topt;
 
601
        ++i;
 
602
    }
 
603
    tOption->topt[i] = NULL; /* sentinel */
 
604
 
 
605
    qsort(tOption->topt,
 
606
          /* Do not sort the sentinel: hence `-1' */
 
607
          sizeof(tOption->topt)/sizeof(tOption->topt[0])-1,
 
608
          sizeof(tOption->topt[0]),
 
609
          cmpOpt);
 
610
}
 
611
 
 
612
static void ForEachSortedOption( TidyDoc tdoc, OptionFunc OptionPrint )
 
613
{
 
614
    AllOption_t tOption;
 
615
    const TidyOption *topt;
 
616
 
 
617
    getSortedOption( tdoc, &tOption );
 
618
    for( topt = tOption.topt; *topt; ++topt)
 
619
    {
 
620
        OptionDesc d;
 
621
 
 
622
        GetOption( tdoc, *topt, &d );
 
623
        (*OptionPrint)( tdoc, *topt, &d );
 
624
    }
 
625
}
 
626
 
 
627
static void ForEachOption( TidyDoc tdoc, OptionFunc OptionPrint )
 
628
{
 
629
    TidyIterator pos = tidyGetOptionList( tdoc );
 
630
 
 
631
    while ( pos )
 
632
    {
 
633
        TidyOption topt = tidyGetNextOption( tdoc, &pos );
 
634
        OptionDesc d;
 
635
 
 
636
        GetOption( tdoc, topt, &d );
 
637
        (*OptionPrint)( tdoc, topt, &d );
 
638
    }
 
639
}
 
640
 
 
641
static
 
642
void PrintAllowedValuesFromPick( TidyOption topt )
 
643
{
 
644
    TidyIterator pos = tidyOptGetPickList( topt );
 
645
    Bool first = yes;
 
646
    ctmbstr def;
 
647
    while ( pos )
 
648
    {
 
649
        if (first)
 
650
            first = no;
 
651
        else
 
652
            printf(", ");
 
653
        def = tidyOptGetNextPick( topt, &pos );
 
654
        printf("%s", def);
 
655
    }
 
656
}
 
657
 
 
658
static
 
659
void PrintAllowedValues( TidyOption topt, const OptionDesc *d )
 
660
{
 
661
    if (d->vals)
 
662
        printf( "%s", d->vals );
 
663
    else
 
664
        PrintAllowedValuesFromPick( topt );
 
665
}
 
666
 
 
667
static
 
668
void printXMLDescription( TidyDoc tdoc, TidyOption topt )
 
669
{
 
670
    ctmbstr doc = tidyOptGetDoc( tdoc, topt );
 
671
 
 
672
    if (doc)
 
673
        printf("  <description>%s</description>\n", doc);
 
674
    else
 
675
    {
 
676
        printf("  <description />\n");
 
677
        fprintf(stderr, "Warning: option `%s' is not documented.\n",
 
678
                tidyOptGetName( topt ));
 
679
    }
 
680
}
 
681
 
 
682
static
 
683
void printXMLCrossRef( TidyDoc tdoc, TidyOption topt )
 
684
{
 
685
    TidyOption optLinked;
 
686
    TidyIterator pos = tidyOptGetDocLinksList(tdoc, topt);
 
687
    while( pos )
 
688
    {
 
689
        optLinked = tidyOptGetNextDocLinks(tdoc, &pos );
 
690
        printf("  <seealso>%s</seealso>\n",tidyOptGetName(optLinked));
 
691
    }
 
692
}
 
693
 
 
694
static
 
695
void printXMLOption( TidyDoc tdoc, TidyOption topt, OptionDesc *d )
 
696
{
 
697
    if ( tidyOptIsReadOnly(topt) )
 
698
        return;
 
699
 
 
700
    printf( " <option class=\"%s\">\n", d->cat );
 
701
    printf  ("  <name>%s</name>\n",d->name);
 
702
    printf  ("  <type>%s</type>\n",d->type);
 
703
    if (d->def)
 
704
        printf("  <default>%s</default>\n",d->def);
 
705
    else
 
706
        printf("  <default />\n");
 
707
    if (d->haveVals)
 
708
    {
 
709
        printf("  <example>");
 
710
        PrintAllowedValues( topt, d );
 
711
        printf("</example>\n");
 
712
    }
 
713
    else
 
714
    {
 
715
        printf("  <example />\n");
 
716
    }
 
717
    printXMLDescription( tdoc, topt );
 
718
    printXMLCrossRef( tdoc, topt );
 
719
    printf( " </option>\n" );
 
720
}
 
721
 
 
722
static void XMLoptionhelp( TidyDoc tdoc )
 
723
{
 
724
    printf( "<?xml version=\"1.0\"?>\n"
 
725
            "<config version=\"%s\">\n", tidyReleaseDate());
 
726
    ForEachOption( tdoc, printXMLOption );
 
727
    printf( "</config>\n" );
 
728
}
 
729
 
 
730
static
 
731
tmbstr GetAllowedValuesFromPick( TidyOption topt )
 
732
{
 
733
    TidyIterator pos;
 
734
    Bool first;
 
735
    ctmbstr def;
 
736
    uint len = 0;
 
737
    tmbstr val;
 
738
 
 
739
    pos = tidyOptGetPickList( topt );
 
740
    first = yes;
 
741
    while ( pos )
 
742
    {
 
743
        if (first)
 
744
            first = no;
 
745
        else
 
746
            len += 2;
 
747
        def = tidyOptGetNextPick( topt, &pos );
 
748
        len += strlen(def);
 
749
    }
 
750
    val = malloc(len+1);
 
751
    val[0] = '\0';
 
752
    pos = tidyOptGetPickList( topt );
 
753
    first = yes;
 
754
    while ( pos )
 
755
    {
 
756
        if (first)
 
757
            first = no;
 
758
        else
 
759
            strcat(val, ", ");
 
760
        def = tidyOptGetNextPick( topt, &pos );
 
761
        strcat(val, def);
 
762
    }
 
763
    return val;
 
764
}
 
765
 
 
766
static
 
767
tmbstr GetAllowedValues( TidyOption topt, const OptionDesc *d )
 
768
{
 
769
    if (d->vals)
 
770
    {
 
771
        tmbstr val = malloc(1+strlen(d->vals));
 
772
        strcpy(val, d->vals);
 
773
        return val;
 
774
    }
 
775
    else
 
776
        return GetAllowedValuesFromPick( topt );
 
777
}
 
778
 
 
779
static
 
780
void printOption( TidyDoc ARG_UNUSED(tdoc), TidyOption topt,
 
781
                  OptionDesc *d )
 
782
{
 
783
    if ( tidyOptIsReadOnly(topt) )
 
784
        return;
 
785
 
 
786
    if ( *d->name || *d->type )
 
787
    {
 
788
        ctmbstr pval = d->vals;
 
789
        tmbstr val = NULL;
 
790
        if (!d->haveVals)
 
791
        {
 
792
            pval = "-";
 
793
        }
 
794
        else if (pval == NULL)
 
795
        {
 
796
            val = GetAllowedValues( topt, d);
 
797
            pval = val;
 
798
        }
 
799
        print3Columns( fmt, 27, 9, 40, d->name, d->type, pval );
 
800
        if (val)
 
801
            free(val);
 
802
    }
 
803
}
 
804
 
 
805
static void optionhelp( TidyDoc tdoc )
 
806
{
 
807
    printf( "\nHTML Tidy Configuration Settings\n\n" );
 
808
    printf( "Within a file, use the form:\n\n" );
 
809
    printf( "wrap: 72\n" );
 
810
    printf( "indent: no\n\n" );
 
811
    printf( "When specified on the command line, use the form:\n\n" );
 
812
    printf( "--wrap 72 --indent no\n\n");
 
813
 
 
814
    printf( fmt, "Name", "Type", "Allowable values" );
 
815
    printf( fmt, ul, ul, ul );
 
816
 
 
817
    ForEachSortedOption( tdoc, printOption );
 
818
}
 
819
 
 
820
static
 
821
void printOptionValues( TidyDoc ARG_UNUSED(tdoc), TidyOption topt,
 
822
                        OptionDesc *d )
 
823
{
 
824
    TidyOptionId optId = tidyOptGetId( topt );
 
825
    ctmbstr ro = tidyOptIsReadOnly( topt ) ? "*" : "" ;
 
826
 
 
827
    switch ( optId )
 
828
    {
 
829
    case TidyInlineTags:
 
830
    case TidyBlockTags:
 
831
    case TidyEmptyTags:
 
832
    case TidyPreTags:
 
833
        {
 
834
            TidyIterator pos = tidyOptGetDeclTagList( tdoc );
 
835
            while ( pos )
 
836
            {
 
837
                d->def = tidyOptGetNextDeclTag(tdoc, optId, &pos);
 
838
                if ( pos )
 
839
                {
 
840
                    if ( *d->name )
 
841
                        printf( valfmt, d->name, d->type, ro, d->def );
 
842
                    else
 
843
                        printf( fmt, d->name, d->type, d->def );
 
844
                    d->name = "";
 
845
                    d->type = "";
 
846
                }
 
847
            }
 
848
        }
 
849
        break;
 
850
    case TidyNewline:
 
851
        d->def = tidyOptGetCurrPick( tdoc, optId );
 
852
        break;
 
853
    }
 
854
 
 
855
    /* fix for http://tidy.sf.net/bug/873921 */
 
856
    if ( *d->name || *d->type || (d->def && *d->def) )
 
857
    {
 
858
        if ( ! d->def )
 
859
            d->def = "";
 
860
        if ( *d->name )
 
861
            printf( valfmt, d->name, d->type, ro, d->def );
 
862
        else
 
863
            printf( fmt, d->name, d->type, d->def );
 
864
    }
 
865
}
 
866
 
 
867
static void optionvalues( TidyDoc tdoc )
 
868
{
 
869
    printf( "\nConfiguration File Settings:\n\n" );
 
870
    printf( fmt, "Name", "Type", "Current Value" );
 
871
    printf( fmt, ul, ul, ul );
 
872
 
 
873
    ForEachSortedOption( tdoc, printOptionValues );
 
874
 
 
875
    printf( "\n\nValues marked with an *asterisk are calculated \n"
 
876
            "internally by HTML Tidy\n\n" );
 
877
}
 
878
 
 
879
static void version( void )
 
880
{
 
881
#ifdef PLATFORM_NAME
 
882
    printf( "HTML Tidy for %s released on %s\n",
 
883
             PLATFORM_NAME, tidyReleaseDate() );
 
884
#else
 
885
    printf( "HTML Tidy released on %s\n", tidyReleaseDate() );
 
886
#endif
 
887
}
 
888
 
 
889
static void unknownOption( uint c )
 
890
{
 
891
    fprintf( errout, "HTML Tidy: unknown option: %c\n", (char)c );
 
892
}
 
893
 
 
894
int main( int argc, char** argv )
 
895
{
 
896
    ctmbstr prog = argv[0];
 
897
    ctmbstr cfgfil = NULL, errfil = NULL, htmlfil = NULL;
 
898
    TidyDoc tdoc = tidyCreate();
 
899
    int status = 0;
 
900
 
 
901
    uint contentErrors = 0;
 
902
    uint contentWarnings = 0;
 
903
    uint accessWarnings = 0;
 
904
 
 
905
    errout = stderr;  /* initialize to stderr */
 
906
    status = 0;
 
907
    
 
908
#ifdef CONFIG_FILE
 
909
    if ( tidyFileExists(CONFIG_FILE) )
 
910
    {
 
911
        status = tidyLoadConfig( tdoc, CONFIG_FILE );
 
912
        if ( status != 0 )
 
913
            fprintf(errout, "Loading config file \"%s\" failed, err = %d\n", CONFIG_FILE, status);
 
914
    }
 
915
#endif /* CONFIG_FILE */
 
916
 
 
917
    /* look for env var "HTML_TIDY" */
 
918
    /* then for ~/.tidyrc (on platforms defining $HOME) */
 
919
 
 
920
    if ( cfgfil = getenv("HTML_TIDY") )
 
921
    {
 
922
        status = tidyLoadConfig( tdoc, cfgfil );
 
923
        if ( status != 0 )
 
924
            fprintf(errout, "Loading config file \"%s\" failed, err = %d\n", cfgfil, status);
 
925
    }
 
926
#ifdef USER_CONFIG_FILE
 
927
    else if ( tidyFileExists(USER_CONFIG_FILE) )
 
928
    {
 
929
        status = tidyLoadConfig( tdoc, USER_CONFIG_FILE );
 
930
        if ( status != 0 )
 
931
            fprintf(errout, "Loading config file \"%s\" failed, err = %d\n", USER_CONFIG_FILE, status);
 
932
    }
 
933
#endif /* USER_CONFIG_FILE */
 
934
 
 
935
    /* read command line */
 
936
    while ( argc > 0 )
 
937
    {
 
938
        if (argc > 1 && argv[1][0] == '-')
 
939
        {
 
940
            /* support -foo and --foo */
 
941
            ctmbstr arg = argv[1] + 1;
 
942
 
 
943
            if ( strcasecmp(arg, "xml") == 0)
 
944
                tidyOptSetBool( tdoc, TidyXmlTags, yes );
 
945
 
 
946
            else if ( strcasecmp(arg,   "asxml") == 0 ||
 
947
                      strcasecmp(arg, "asxhtml") == 0 )
 
948
            {
 
949
                tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
 
950
            }
 
951
            else if ( strcasecmp(arg,   "ashtml") == 0 )
 
952
                tidyOptSetBool( tdoc, TidyHtmlOut, yes );
 
953
 
 
954
            else if ( strcasecmp(arg, "indent") == 0 )
 
955
            {
 
956
                tidyOptSetInt( tdoc, TidyIndentContent, TidyAutoState );
 
957
                if ( tidyOptGetInt(tdoc, TidyIndentSpaces) == 0 )
 
958
                    tidyOptResetToDefault( tdoc, TidyIndentSpaces );
 
959
            }
 
960
            else if ( strcasecmp(arg, "omit") == 0 )
 
961
                tidyOptSetBool( tdoc, TidyHideEndTags, yes );
 
962
 
 
963
            else if ( strcasecmp(arg, "upper") == 0 )
 
964
                tidyOptSetBool( tdoc, TidyUpperCaseTags, yes );
 
965
 
 
966
            else if ( strcasecmp(arg, "clean") == 0 )
 
967
                tidyOptSetBool( tdoc, TidyMakeClean, yes );
 
968
 
 
969
            else if ( strcasecmp(arg, "bare") == 0 )
 
970
                tidyOptSetBool( tdoc, TidyMakeBare, yes );
 
971
 
 
972
            else if ( strcasecmp(arg, "raw") == 0      ||
 
973
                      strcasecmp(arg, "ascii") == 0    ||
 
974
                      strcasecmp(arg, "latin0") == 0   ||
 
975
                      strcasecmp(arg, "latin1") == 0   ||
 
976
                      strcasecmp(arg, "utf8") == 0     ||
 
977
#ifndef NO_NATIVE_ISO2022_SUPPORT
 
978
                      strcasecmp(arg, "iso2022") == 0  ||
 
979
#endif
 
980
#if SUPPORT_UTF16_ENCODINGS
 
981
                      strcasecmp(arg, "utf16le") == 0  ||
 
982
                      strcasecmp(arg, "utf16be") == 0  ||
 
983
                      strcasecmp(arg, "utf16") == 0    ||
 
984
#endif
 
985
#if SUPPORT_ASIAN_ENCODINGS
 
986
                      strcasecmp(arg, "shiftjis") == 0 ||
 
987
                      strcasecmp(arg, "big5") == 0     ||
 
988
#endif
 
989
                      strcasecmp(arg, "mac") == 0      ||
 
990
                      strcasecmp(arg, "win1252") == 0  ||
 
991
                      strcasecmp(arg, "ibm858") == 0 )
 
992
            {
 
993
                tidySetCharEncoding( tdoc, arg );
 
994
            }
 
995
            else if ( strcasecmp(arg, "numeric") == 0 )
 
996
                tidyOptSetBool( tdoc, TidyNumEntities, yes );
 
997
 
 
998
            else if ( strcasecmp(arg, "modify") == 0 ||
 
999
                      strcasecmp(arg, "change") == 0 ||  /* obsolete */
 
1000
                      strcasecmp(arg, "update") == 0 )   /* obsolete */
 
1001
            {
 
1002
                tidyOptSetBool( tdoc, TidyWriteBack, yes );
 
1003
            }
 
1004
            else if ( strcasecmp(arg, "errors") == 0 )
 
1005
                tidyOptSetBool( tdoc, TidyShowMarkup, no );
 
1006
 
 
1007
            else if ( strcasecmp(arg, "quiet") == 0 )
 
1008
                tidyOptSetBool( tdoc, TidyQuiet, yes );
 
1009
 
 
1010
            else if ( strcasecmp(arg, "help") == 0 ||
 
1011
                      strcasecmp(arg,    "h") == 0 || *arg == '?' )
 
1012
            {
 
1013
                help( prog );
 
1014
                tidyRelease( tdoc );
 
1015
                return 0; /* success */
 
1016
            }
 
1017
            else if ( strcasecmp(arg, "xml-help") == 0)
 
1018
            {
 
1019
                xml_help( );
 
1020
                tidyRelease( tdoc );
 
1021
                return 0; /* success */
 
1022
            }
 
1023
            else if ( strcasecmp(arg, "help-config") == 0 )
 
1024
            {
 
1025
                optionhelp( tdoc );
 
1026
                tidyRelease( tdoc );
 
1027
                return 0; /* success */
 
1028
            }
 
1029
            else if ( strcasecmp(arg, "xml-config") == 0 )
 
1030
            {
 
1031
                XMLoptionhelp( tdoc );
 
1032
                tidyRelease( tdoc );
 
1033
                return 0; /* success */
 
1034
            }
 
1035
            else if ( strcasecmp(arg, "show-config") == 0 )
 
1036
            {
 
1037
                optionvalues( tdoc );
 
1038
                tidyRelease( tdoc );
 
1039
                return 0; /* success */
 
1040
            }
 
1041
            else if ( strcasecmp(arg, "config") == 0 )
 
1042
            {
 
1043
                if ( argc >= 3 )
 
1044
                {
 
1045
                    ctmbstr post;
 
1046
 
 
1047
                    tidyLoadConfig( tdoc, argv[2] );
 
1048
 
 
1049
                    /* Set new error output stream if setting changed */
 
1050
                    post = tidyOptGetValue( tdoc, TidyErrFile );
 
1051
                    if ( post && (!errfil || !samefile(errfil, post)) )
 
1052
                    {
 
1053
                        errfil = post;
 
1054
                        errout = tidySetErrorFile( tdoc, post );
 
1055
                    }
 
1056
 
 
1057
                    --argc;
 
1058
                    ++argv;
 
1059
                }
 
1060
            }
 
1061
 
 
1062
#if SUPPORT_ASIAN_ENCODINGS
 
1063
            else if ( strcasecmp(arg, "language") == 0 ||
 
1064
                      strcasecmp(arg,     "lang") == 0 )
 
1065
            {
 
1066
                if ( argc >= 3 )
 
1067
                {
 
1068
                    tidyOptSetValue( tdoc, TidyLanguage, argv[2] );
 
1069
                    --argc;
 
1070
                    ++argv;
 
1071
                }
 
1072
            }
 
1073
#endif
 
1074
 
 
1075
            else if ( strcasecmp(arg, "output") == 0 ||
 
1076
                      strcasecmp(arg, "-output-file") == 0 ||
 
1077
                      strcasecmp(arg, "o") == 0 )
 
1078
            {
 
1079
                if ( argc >= 3 )
 
1080
                {
 
1081
                    tidyOptSetValue( tdoc, TidyOutFile, argv[2] );
 
1082
                    --argc;
 
1083
                    ++argv;
 
1084
                }
 
1085
            }
 
1086
            else if ( strcasecmp(arg,  "file") == 0 ||
 
1087
                      strcasecmp(arg, "-file") == 0 ||
 
1088
                      strcasecmp(arg,     "f") == 0 )
 
1089
            {
 
1090
                if ( argc >= 3 )
 
1091
                {
 
1092
                    errfil = argv[2];
 
1093
                    errout = tidySetErrorFile( tdoc, errfil );
 
1094
                    --argc;
 
1095
                    ++argv;
 
1096
                }
 
1097
            }
 
1098
            else if ( strcasecmp(arg,  "wrap") == 0 ||
 
1099
                      strcasecmp(arg, "-wrap") == 0 ||
 
1100
                      strcasecmp(arg,     "w") == 0 )
 
1101
            {
 
1102
                if ( argc >= 3 )
 
1103
                {
 
1104
                    uint wraplen = 0;
 
1105
                    sscanf( argv[2], "%u", &wraplen );
 
1106
                    tidyOptSetInt( tdoc, TidyWrapLen, wraplen );
 
1107
                    --argc;
 
1108
                    ++argv;
 
1109
                }
 
1110
            }
 
1111
            else if ( strcasecmp(arg,  "version") == 0 ||
 
1112
                      strcasecmp(arg, "-version") == 0 ||
 
1113
                      strcasecmp(arg,        "v") == 0 )
 
1114
            {
 
1115
                version();
 
1116
                tidyRelease( tdoc );
 
1117
                return 0;  /* success */
 
1118
 
 
1119
            }
 
1120
            else if ( strncmp(argv[1], "--", 2 ) == 0)
 
1121
            {
 
1122
                if ( tidyOptParseValue(tdoc, argv[1]+2, argv[2]) )
 
1123
                {
 
1124
                    /* Set new error output stream if setting changed */
 
1125
                    ctmbstr post = tidyOptGetValue( tdoc, TidyErrFile );
 
1126
                    if ( post && (!errfil || !samefile(errfil, post)) )
 
1127
                    {
 
1128
                        errfil = post;
 
1129
                        errout = tidySetErrorFile( tdoc, post );
 
1130
                    }
 
1131
 
 
1132
                    ++argv;
 
1133
                    --argc;
 
1134
                }
 
1135
            }
 
1136
 
 
1137
#if SUPPORT_ACCESSIBILITY_CHECKS
 
1138
            else if ( strcasecmp(arg, "access") == 0 )
 
1139
            {
 
1140
                if ( argc >= 3 )
 
1141
                {
 
1142
                    uint acclvl = 0;
 
1143
                    sscanf( argv[2], "%u", &acclvl );
 
1144
                    tidyOptSetInt( tdoc, TidyAccessibilityCheckLevel, acclvl );
 
1145
                    --argc;
 
1146
                    ++argv;
 
1147
                }
 
1148
            }
 
1149
#endif
 
1150
 
 
1151
            else
 
1152
            {
 
1153
                uint c;
 
1154
                ctmbstr s = argv[1];
 
1155
 
 
1156
                while ( c = *++s )
 
1157
                {
 
1158
                    switch ( c )
 
1159
                    {
 
1160
                    case 'i':
 
1161
                        tidyOptSetInt( tdoc, TidyIndentContent, TidyAutoState );
 
1162
                        if ( tidyOptGetInt(tdoc, TidyIndentSpaces) == 0 )
 
1163
                            tidyOptResetToDefault( tdoc, TidyIndentSpaces );
 
1164
                        break;
 
1165
 
 
1166
                    /* Usurp -o for output file.  Anyone hiding end tags?
 
1167
                    case 'o':
 
1168
                        tidyOptSetBool( tdoc, TidyHideEndTags, yes );
 
1169
                        break;
 
1170
                    */
 
1171
 
 
1172
                    case 'u':
 
1173
                        tidyOptSetBool( tdoc, TidyUpperCaseTags, yes );
 
1174
                        break;
 
1175
 
 
1176
                    case 'c':
 
1177
                        tidyOptSetBool( tdoc, TidyMakeClean, yes );
 
1178
                        break;
 
1179
 
 
1180
                    case 'b':
 
1181
                        tidyOptSetBool( tdoc, TidyMakeBare, yes );
 
1182
                        break;
 
1183
 
 
1184
                    case 'n':
 
1185
                        tidyOptSetBool( tdoc, TidyNumEntities, yes );
 
1186
                        break;
 
1187
 
 
1188
                    case 'm':
 
1189
                        tidyOptSetBool( tdoc, TidyWriteBack, yes );
 
1190
                        break;
 
1191
 
 
1192
                    case 'e':
 
1193
                        tidyOptSetBool( tdoc, TidyShowMarkup, no );
 
1194
                        break;
 
1195
 
 
1196
                    case 'q':
 
1197
                        tidyOptSetBool( tdoc, TidyQuiet, yes );
 
1198
                        break;
 
1199
 
 
1200
                    default:
 
1201
                        unknownOption( c );
 
1202
                        break;
 
1203
                    }
 
1204
                }
 
1205
            }
 
1206
 
 
1207
            --argc;
 
1208
            ++argv;
 
1209
            continue;
 
1210
        }
 
1211
 
 
1212
        if ( argc > 1 )
 
1213
        {
 
1214
            htmlfil = argv[1];
 
1215
            if ( tidyOptGetBool(tdoc, TidyEmacs) )
 
1216
                tidyOptSetValue( tdoc, TidyEmacsFile, htmlfil );
 
1217
            status = tidyParseFile( tdoc, htmlfil );
 
1218
        }
 
1219
        else
 
1220
        {
 
1221
            htmlfil = "stdin";
 
1222
            status = tidyParseStdin( tdoc );
 
1223
        }
 
1224
 
 
1225
        if ( status >= 0 )
 
1226
            status = tidyCleanAndRepair( tdoc );
 
1227
 
 
1228
        if ( status >= 0 )
 
1229
            status = tidyRunDiagnostics( tdoc );
 
1230
 
 
1231
        if ( status > 1 ) /* If errors, do we want to force output? */
 
1232
            status = ( tidyOptGetBool(tdoc, TidyForceOutput) ? status : -1 );
 
1233
 
 
1234
        if ( status >= 0 && tidyOptGetBool(tdoc, TidyShowMarkup) )
 
1235
        {
 
1236
            if ( tidyOptGetBool(tdoc, TidyWriteBack) && argc > 1 )
 
1237
                status = tidySaveFile( tdoc, htmlfil );
 
1238
            else
 
1239
            {
 
1240
                ctmbstr outfil = tidyOptGetValue( tdoc, TidyOutFile );
 
1241
                if ( outfil )
 
1242
                    status = tidySaveFile( tdoc, outfil );
 
1243
                else
 
1244
                    status = tidySaveStdout( tdoc );
 
1245
            }
 
1246
        }
 
1247
 
 
1248
        contentErrors   += tidyErrorCount( tdoc );
 
1249
        contentWarnings += tidyWarningCount( tdoc );
 
1250
        accessWarnings  += tidyAccessWarningCount( tdoc );
 
1251
 
 
1252
        --argc;
 
1253
        ++argv;
 
1254
 
 
1255
        if ( argc <= 1 )
 
1256
            break;
 
1257
    }
 
1258
 
 
1259
    if (!tidyOptGetBool(tdoc, TidyQuiet) &&
 
1260
        errout == stderr && !contentErrors)
 
1261
        fprintf(errout, "\n");
 
1262
 
 
1263
    if (contentErrors + contentWarnings > 0 && 
 
1264
         !tidyOptGetBool(tdoc, TidyQuiet))
 
1265
        tidyErrorSummary(tdoc);
 
1266
 
 
1267
    if (!tidyOptGetBool(tdoc, TidyQuiet))
 
1268
        tidyGeneralInfo(tdoc);
 
1269
 
 
1270
    /* called to free hash tables etc. */
 
1271
    tidyRelease( tdoc );
 
1272
 
 
1273
    /* return status can be used by scripts */
 
1274
    if ( contentErrors > 0 )
 
1275
        return 2;
 
1276
 
 
1277
    if ( contentWarnings > 0 )
 
1278
        return 1;
 
1279
 
 
1280
    /* 0 signifies all is ok */
 
1281
    return 0;
 
1282
}
 
1283
 
 
1284
/*
 
1285
 * local variables:
 
1286
 * mode: c
 
1287
 * indent-tabs-mode: nil
 
1288
 * c-basic-offset: 4
 
1289
 * eval: (c-set-offset 'substatement-open 0)
 
1290
 * end:
 
1291
 */