~ps-jenkins/ubuntu-push/ubuntu-vivid-proposed

« back to all changes in this revision

Viewing changes to docs/example-server/node_modules/request/node_modules/http-signature/node_modules/ctype/tools/jsstyle

  • Committer: Roberto Alsina
  • Date: 2014-09-05 14:57:17 UTC
  • mto: (91.179.25 automatic)
  • mto: This revision was merged to the branch mainline in revision 129.
  • Revision ID: roberto.alsina@canonical.com-20140905145717-0ufcsv27w25i1nnu
added example app server

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env perl
 
2
#
 
3
# CDDL HEADER START
 
4
#
 
5
# The contents of this file are subject to the terms of the
 
6
# Common Development and Distribution License (the "License").
 
7
# You may not use this file except in compliance with the License.
 
8
#
 
9
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 
10
# or http://www.opensolaris.org/os/licensing.
 
11
# See the License for the specific language governing permissions
 
12
# and limitations under the License.
 
13
#
 
14
# When distributing Covered Code, include this CDDL HEADER in each
 
15
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 
16
# If applicable, add the following below this CDDL HEADER, with the
 
17
# fields enclosed by brackets "[]" replaced with your own identifying
 
18
# information: Portions Copyright [yyyy] [name of copyright owner]
 
19
#
 
20
# CDDL HEADER END
 
21
#
 
22
#
 
23
# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 
24
# Use is subject to license terms.
 
25
#
 
26
# Copyright 2011 Joyent, Inc. All rights reserved.
 
27
#
 
28
# jsstyle - check for some common stylistic errors.
 
29
#
 
30
#       jsstyle is a sort of "lint" for Javascript coding style.  This tool is
 
31
#       derived from the cstyle tool, used to check for the style used in the
 
32
#       Solaris kernel, sometimes known as "Bill Joy Normal Form".
 
33
#
 
34
#       There's a lot this can't check for, like proper indentation of code
 
35
#       blocks.  There's also a lot more this could check for.
 
36
#
 
37
#       A note to the non perl literate:
 
38
#
 
39
#               perl regular expressions are pretty much like egrep
 
40
#               regular expressions, with the following special symbols
 
41
#
 
42
#               \s      any space character
 
43
#               \S      any non-space character
 
44
#               \w      any "word" character [a-zA-Z0-9_]
 
45
#               \W      any non-word character
 
46
#               \d      a digit [0-9]
 
47
#               \D      a non-digit
 
48
#               \b      word boundary (between \w and \W)
 
49
#               \B      non-word boundary
 
50
#
 
51
 
 
52
require 5.0;
 
53
use IO::File;
 
54
use Getopt::Std;
 
55
use strict;
 
56
 
 
57
my $usage =
 
58
"usage: jsstyle [-chvC] [-o constructs] file ...
 
59
        -c      check continuation indentation inside functions
 
60
        -h      perform heuristic checks that are sometimes wrong
 
61
        -v      verbose
 
62
        -C      don't check anything in header block comments
 
63
        -o constructs
 
64
                allow a comma-seperated list of optional constructs:
 
65
                    doxygen     allow doxygen-style block comments (/** /*!)
 
66
                    splint      allow splint-style lint comments (/*@ ... @*/)
 
67
";
 
68
 
 
69
my %opts;
 
70
 
 
71
if (!getopts("cho:vC", \%opts)) {
 
72
        print $usage;
 
73
        exit 2;
 
74
}
 
75
 
 
76
my $check_continuation = $opts{'c'};
 
77
my $heuristic = $opts{'h'};
 
78
my $verbose = $opts{'v'};
 
79
my $ignore_hdr_comment = $opts{'C'};
 
80
 
 
81
my $doxygen_comments = 0;
 
82
my $splint_comments = 0;
 
83
 
 
84
if (defined($opts{'o'})) {
 
85
        for my $x (split /,/, $opts{'o'}) {
 
86
                if ($x eq "doxygen") {
 
87
                        $doxygen_comments = 1;
 
88
                } elsif ($x eq "splint") {
 
89
                        $splint_comments = 1;
 
90
                } else {
 
91
                        print "jsstyle: unrecognized construct \"$x\"\n";
 
92
                        print $usage;
 
93
                        exit 2;
 
94
                }
 
95
        }
 
96
}
 
97
 
 
98
my ($filename, $line, $prev);           # shared globals
 
99
 
 
100
my $fmt;
 
101
my $hdr_comment_start;
 
102
 
 
103
if ($verbose) {
 
104
        $fmt = "%s: %d: %s\n%s\n";
 
105
} else {
 
106
        $fmt = "%s: %d: %s\n";
 
107
}
 
108
 
 
109
if ($doxygen_comments) {
 
110
        # doxygen comments look like "/*!" or "/**"; allow them.
 
111
        $hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
 
112
} else {
 
113
        $hdr_comment_start = qr/^\s*\/\*$/;
 
114
}
 
115
 
 
116
# Note, following must be in single quotes so that \s and \w work right.
 
117
my $lint_re = qr/\/\*(?:
 
118
        jsl:\w+?|ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
 
119
        CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
 
120
        FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
 
121
        PROTOLIB[0-9]*|SCANFLIKE[0-9]*|JSSTYLED.*?
 
122
    )\*\//x;
 
123
 
 
124
my $splint_re = qr/\/\*@.*?@\*\//x;
 
125
 
 
126
my $err_stat = 0;               # exit status
 
127
 
 
128
if ($#ARGV >= 0) {
 
129
        foreach my $arg (@ARGV) {
 
130
                my $fh = new IO::File $arg, "r";
 
131
                if (!defined($fh)) {
 
132
                        printf "%s: cannot open\n", $arg;
 
133
                } else {
 
134
                        &jsstyle($arg, $fh);
 
135
                        close $fh;
 
136
                }
 
137
        }
 
138
} else {
 
139
        &jsstyle("<stdin>", *STDIN);
 
140
}
 
141
exit $err_stat;
 
142
 
 
143
my $no_errs = 0;                # set for JSSTYLED-protected lines
 
144
 
 
145
sub err($) {
 
146
        my ($error) = @_;
 
147
        unless ($no_errs) {
 
148
                printf $fmt, $filename, $., $error, $line;
 
149
                $err_stat = 1;
 
150
        }
 
151
}
 
152
 
 
153
sub err_prefix($$) {
 
154
        my ($prevline, $error) = @_;
 
155
        my $out = $prevline."\n".$line;
 
156
        unless ($no_errs) {
 
157
                printf $fmt, $filename, $., $error, $out;
 
158
                $err_stat = 1;
 
159
        }
 
160
}
 
161
 
 
162
sub err_prev($) {
 
163
        my ($error) = @_;
 
164
        unless ($no_errs) {
 
165
                printf $fmt, $filename, $. - 1, $error, $prev;
 
166
                $err_stat = 1;
 
167
        }
 
168
}
 
169
 
 
170
sub jsstyle($$) {
 
171
 
 
172
my ($fn, $filehandle) = @_;
 
173
$filename = $fn;                        # share it globally
 
174
 
 
175
my $in_cpp = 0;
 
176
my $next_in_cpp = 0;
 
177
 
 
178
my $in_comment = 0;
 
179
my $in_header_comment = 0;
 
180
my $comment_done = 0;
 
181
my $in_function = 0;
 
182
my $in_function_header = 0;
 
183
my $in_declaration = 0;
 
184
my $note_level = 0;
 
185
my $nextok = 0;
 
186
my $nocheck = 0;
 
187
 
 
188
my $in_string = 0;
 
189
 
 
190
my ($okmsg, $comment_prefix);
 
191
 
 
192
$line = '';
 
193
$prev = '';
 
194
reset_indent();
 
195
 
 
196
line: while (<$filehandle>) {
 
197
        s/\r?\n$//;     # strip return and newline
 
198
 
 
199
        # save the original line, then remove all text from within
 
200
        # double or single quotes, we do not want to check such text.
 
201
 
 
202
        $line = $_;
 
203
 
 
204
        #
 
205
        # C allows strings to be continued with a backslash at the end of
 
206
        # the line.  We translate that into a quoted string on the previous
 
207
        # line followed by an initial quote on the next line.
 
208
        #
 
209
        # (we assume that no-one will use backslash-continuation with character
 
210
        # constants)
 
211
        #
 
212
        $_ = '"' . $_           if ($in_string && !$nocheck && !$in_comment);
 
213
 
 
214
        #
 
215
        # normal strings and characters
 
216
        #
 
217
        s/'([^\\']|\\.)*'/\'\'/g;
 
218
        s/"([^\\"]|\\.)*"/\"\"/g;
 
219
 
 
220
        #
 
221
        # detect string continuation
 
222
        #
 
223
        if ($nocheck || $in_comment) {
 
224
                $in_string = 0;
 
225
        } else {
 
226
                #
 
227
                # Now that all full strings are replaced with "", we check
 
228
                # for unfinished strings continuing onto the next line.
 
229
                #
 
230
                $in_string =
 
231
                    (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
 
232
                    s/^("")*"([^\\"]|\\.)*\\$/""/);
 
233
        }
 
234
 
 
235
        #
 
236
        # figure out if we are in a cpp directive
 
237
        #
 
238
        $in_cpp = $next_in_cpp || /^\s*#/;      # continued or started
 
239
        $next_in_cpp = $in_cpp && /\\$/;        # only if continued
 
240
 
 
241
        # strip off trailing backslashes, which appear in long macros
 
242
        s/\s*\\$//;
 
243
 
 
244
        # an /* END JSSTYLED */ comment ends a no-check block.
 
245
        if ($nocheck) {
 
246
                if (/\/\* *END *JSSTYLED *\*\//) {
 
247
                        $nocheck = 0;
 
248
                } else {
 
249
                        reset_indent();
 
250
                        next line;
 
251
                }
 
252
        }
 
253
 
 
254
        # a /*JSSTYLED*/ comment indicates that the next line is ok.
 
255
        if ($nextok) {
 
256
                if ($okmsg) {
 
257
                        err($okmsg);
 
258
                }
 
259
                $nextok = 0;
 
260
                $okmsg = 0;
 
261
                if (/\/\* *JSSTYLED.*\*\//) {
 
262
                        /^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
 
263
                        $okmsg = $1;
 
264
                        $nextok = 1;
 
265
                }
 
266
                $no_errs = 1;
 
267
        } elsif ($no_errs) {
 
268
                $no_errs = 0;
 
269
        }
 
270
 
 
271
        # check length of line.
 
272
        # first, a quick check to see if there is any chance of being too long.
 
273
        if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) {
 
274
                # yes, there is a chance.
 
275
                # replace tabs with spaces and check again.
 
276
                my $eline = $line;
 
277
                1 while $eline =~
 
278
                    s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
 
279
                if (length($eline) > 80) {
 
280
                        err("line > 80 characters");
 
281
                }
 
282
        }
 
283
 
 
284
        # ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
 
285
        if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
 
286
                s/[^()]//g;                       # eliminate all non-parens
 
287
                $note_level += s/\(//g - length;  # update paren nest level
 
288
                next;
 
289
        }
 
290
 
 
291
        # a /* BEGIN JSSTYLED */ comment starts a no-check block.
 
292
        if (/\/\* *BEGIN *JSSTYLED *\*\//) {
 
293
                $nocheck = 1;
 
294
        }
 
295
 
 
296
        # a /*JSSTYLED*/ comment indicates that the next line is ok.
 
297
        if (/\/\* *JSSTYLED.*\*\//) {
 
298
                /^.*\/\* *JSSTYLED *(.*) *\*\/.*$/;
 
299
                $okmsg = $1;
 
300
                $nextok = 1;
 
301
        }
 
302
        if (/\/\/ *JSSTYLED/) {
 
303
                /^.*\/\/ *JSSTYLED *(.*)$/;
 
304
                $okmsg = $1;
 
305
                $nextok = 1;
 
306
        }
 
307
 
 
308
        # universal checks; apply to everything
 
309
        if (/\t +\t/) {
 
310
                err("spaces between tabs");
 
311
        }
 
312
        if (/ \t+ /) {
 
313
                err("tabs between spaces");
 
314
        }
 
315
        if (/\s$/) {
 
316
                err("space or tab at end of line");
 
317
        }
 
318
        if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
 
319
                err("comment preceded by non-blank");
 
320
        }
 
321
 
 
322
        # is this the beginning or ending of a function?
 
323
        # (not if "struct foo\n{\n")
 
324
        if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
 
325
                $in_function = 1;
 
326
                $in_declaration = 1;
 
327
                $in_function_header = 0;
 
328
                $prev = $line;
 
329
                next line;
 
330
        }
 
331
        if (/^}\s*(\/\*.*\*\/\s*)*$/) {
 
332
                if ($prev =~ /^\s*return\s*;/) {
 
333
                        err_prev("unneeded return at end of function");
 
334
                }
 
335
                $in_function = 0;
 
336
                reset_indent();         # we don't check between functions
 
337
                $prev = $line;
 
338
                next line;
 
339
        }
 
340
        if (/^\w*\($/) {
 
341
                $in_function_header = 1;
 
342
        }
 
343
 
 
344
        # a blank line terminates the declarations within a function.
 
345
        # XXX - but still a problem in sub-blocks.
 
346
        if ($in_declaration && /^$/) {
 
347
                $in_declaration = 0;
 
348
        }
 
349
 
 
350
        if ($comment_done) {
 
351
                $in_comment = 0;
 
352
                $in_header_comment = 0;
 
353
                $comment_done = 0;
 
354
        }
 
355
        # does this looks like the start of a block comment?
 
356
        if (/$hdr_comment_start/) {
 
357
                if (!/^\t*\/\*/) {
 
358
                        err("block comment not indented by tabs");
 
359
                }
 
360
                $in_comment = 1;
 
361
                /^(\s*)\//;
 
362
                $comment_prefix = $1;
 
363
                if ($comment_prefix eq "") {
 
364
                        $in_header_comment = 1;
 
365
                }
 
366
                $prev = $line;
 
367
                next line;
 
368
        }
 
369
        # are we still in the block comment?
 
370
        if ($in_comment) {
 
371
                if (/^$comment_prefix \*\/$/) {
 
372
                        $comment_done = 1;
 
373
                } elsif (/\*\//) {
 
374
                        $comment_done = 1;
 
375
                        err("improper block comment close")
 
376
                            unless ($ignore_hdr_comment && $in_header_comment);
 
377
                } elsif (!/^$comment_prefix \*[ \t]/ &&
 
378
                    !/^$comment_prefix \*$/) {
 
379
                        err("improper block comment")
 
380
                            unless ($ignore_hdr_comment && $in_header_comment);
 
381
                }
 
382
        }
 
383
 
 
384
        if ($in_header_comment && $ignore_hdr_comment) {
 
385
                $prev = $line;
 
386
                next line;
 
387
        }
 
388
 
 
389
        # check for errors that might occur in comments and in code.
 
390
 
 
391
        # allow spaces to be used to draw pictures in header comments.
 
392
        #if (/[^ ]     / && !/".*     .*"/ && !$in_header_comment) {
 
393
        #       err("spaces instead of tabs");
 
394
        #}
 
395
        #if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
 
396
        #    (!/^    \w/ || $in_function != 0)) {
 
397
        #       err("indent by spaces instead of tabs");
 
398
        #}
 
399
        if (/^ {2,}/ && !/^    [^ ]/) {
 
400
                err("indent by spaces instead of tabs");
 
401
        }
 
402
        if (/^\t+ [^ \t\*]/ || /^\t+  \S/ || /^\t+   \S/) {
 
403
                err("continuation line not indented by 4 spaces");
 
404
        }
 
405
 
 
406
        if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
 
407
                err("improper first line of block comment");
 
408
        }
 
409
 
 
410
        if ($in_comment) {      # still in comment, don't do further checks
 
411
                $prev = $line;
 
412
                next line;
 
413
        }
 
414
 
 
415
        if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
 
416
            !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
 
417
                err("missing blank after open comment");
 
418
        }
 
419
        if (/\S\*\/[^)]|\S\*\/$/ &&
 
420
            !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
 
421
                err("missing blank before close comment");
 
422
        }
 
423
        if (/\/\/\S/) {         # C++ comments
 
424
                err("missing blank after start comment");
 
425
        }
 
426
        # check for unterminated single line comments, but allow them when
 
427
        # they are used to comment out the argument list of a function
 
428
        # declaration.
 
429
        if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
 
430
                err("unterminated single line comment");
 
431
        }
 
432
 
 
433
        if (/^(#else|#endif|#include)(.*)$/) {
 
434
                $prev = $line;
 
435
                next line;
 
436
        }
 
437
 
 
438
        #
 
439
        # delete any comments and check everything else.  Note that
 
440
        # ".*?" is a non-greedy match, so that we don't get confused by
 
441
        # multiple comments on the same line.
 
442
        #
 
443
        s/\/\*.*?\*\///g;
 
444
        s/\/\/.*$//;           # C++ comments
 
445
 
 
446
        # delete any trailing whitespace; we have already checked for that.
 
447
        s/\s*$//;
 
448
 
 
449
        # following checks do not apply to text in comments.
 
450
        if (/"/) {
 
451
                err("literal string using double-quote instead of single");
 
452
        }
 
453
 
 
454
        if (/[^=!<>\s][!<>=]=/ || /[^<>!=][!<>=]==?[^\s,=]/ ||
 
455
            (/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
 
456
            (/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
 
457
            /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
 
458
                err("missing space around relational operator");
 
459
        }
 
460
        if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
 
461
            (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
 
462
            (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
 
463
                # XXX - should only check this for C++ code
 
464
                # XXX - there are probably other forms that should be allowed
 
465
                if (!/\soperator=/) {
 
466
                        err("missing space around assignment operator");
 
467
                }
 
468
        }
 
469
        if (/[,;]\S/ && !/\bfor \(;;\)/) {
 
470
                err("comma or semicolon followed by non-blank");
 
471
        }
 
472
        # allow "for" statements to have empty "while" clauses
 
473
        if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
 
474
                err("comma or semicolon preceded by blank");
 
475
        }
 
476
        if (/^\s*(&&|\|\|)/) {
 
477
                err("improper boolean continuation");
 
478
        }
 
479
        if (/\S   *(&&|\|\|)/ || /(&&|\|\|)   *\S/) {
 
480
                err("more than one space around boolean operator");
 
481
        }
 
482
        if (/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\(/) {
 
483
                err("missing space between keyword and paren");
 
484
        }
 
485
        if (/(\b(catch|for|if|with|while|switch|return)\b.*){2,}/) {
 
486
                # multiple "case" and "sizeof" allowed
 
487
                err("more than one keyword on line");
 
488
        }
 
489
        if (/\b(delete|typeof|instanceOf|with|throw|catch|new|function|in|for|if|while|switch|return|case)\s\s+\(/ &&
 
490
            !/^#if\s+\(/) {
 
491
                err("extra space between keyword and paren");
 
492
        }
 
493
        # try to detect "func (x)" but not "if (x)" or
 
494
        # "#define foo (x)" or "int (*func)();"
 
495
        if (/\w\s\(/) {
 
496
                my $s = $_;
 
497
                # strip off all keywords on the line
 
498
                s/\b(delete|typeof|instanceOf|throw|with|catch|new|function|in|for|if|while|switch|return|case)\s\(/XXX(/g;
 
499
                s/#elif\s\(/XXX(/g;
 
500
                s/^#define\s+\w+\s+\(/XXX(/;
 
501
                # do not match things like "void (*f)();"
 
502
                # or "typedef void (func_t)();"
 
503
                s/\w\s\(+\*/XXX(*/g;
 
504
                s/\b(void)\s+\(+/XXX(/og;
 
505
                if (/\w\s\(/) {
 
506
                        err("extra space between function name and left paren");
 
507
                }
 
508
                $_ = $s;
 
509
        }
 
510
 
 
511
        if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
 
512
                err("unparenthesized return expression");
 
513
        }
 
514
        if (/\btypeof\b/ && !/\btypeof\s*\(.*\)/) {
 
515
                err("unparenthesized typeof expression");
 
516
        }
 
517
        if (/\(\s/) {
 
518
                err("whitespace after left paren");
 
519
        }
 
520
        # allow "for" statements to have empty "continue" clauses
 
521
        if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
 
522
                err("whitespace before right paren");
 
523
        }
 
524
        if (/^\s*\(void\)[^ ]/) {
 
525
                err("missing space after (void) cast");
 
526
        }
 
527
        if (/\S{/ && !/({|\(){/) {
 
528
                err("missing space before left brace");
 
529
        }
 
530
        if ($in_function && /^\s+{/ &&
 
531
            ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
 
532
                err("left brace starting a line");
 
533
        }
 
534
        if (/}(else|while)/) {
 
535
                err("missing space after right brace");
 
536
        }
 
537
        if (/}\s\s+(else|while)/) {
 
538
                err("extra space after right brace");
 
539
        }
 
540
        if (/^\s+#/) {
 
541
                err("preprocessor statement not in column 1");
 
542
        }
 
543
        if (/^#\s/) {
 
544
                err("blank after preprocessor #");
 
545
        }
 
546
 
 
547
        #
 
548
        # We completely ignore, for purposes of indentation:
 
549
        #  * lines outside of functions
 
550
        #  * preprocessor lines
 
551
        #
 
552
        if ($check_continuation && $in_function && !$in_cpp) {
 
553
                process_indent($_);
 
554
        }
 
555
 
 
556
        if ($heuristic) {
 
557
                # cannot check this everywhere due to "struct {\n...\n} foo;"
 
558
                if ($in_function && !$in_declaration &&
 
559
                    /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|)*$/ &&
 
560
                    !/} (else|while)/ && !/}}/) {
 
561
                        err("possible bad text following right brace");
 
562
                }
 
563
                # cannot check this because sub-blocks in
 
564
                # the middle of code are ok
 
565
                if ($in_function && /^\s+{/) {
 
566
                        err("possible left brace starting a line");
 
567
                }
 
568
        }
 
569
        if (/^\s*else\W/) {
 
570
                if ($prev =~ /^\s*}$/) {
 
571
                        err_prefix($prev,
 
572
                            "else and right brace should be on same line");
 
573
                }
 
574
        }
 
575
        $prev = $line;
 
576
}
 
577
 
 
578
if ($prev eq "") {
 
579
        err("last line in file is blank");
 
580
}
 
581
 
 
582
}
 
583
 
 
584
#
 
585
# Continuation-line checking
 
586
#
 
587
# The rest of this file contains the code for the continuation checking
 
588
# engine.  It's a pretty simple state machine which tracks the expression
 
589
# depth (unmatched '('s and '['s).
 
590
#
 
591
# Keep in mind that the argument to process_indent() has already been heavily
 
592
# processed; all comments have been replaced by control-A, and the contents of
 
593
# strings and character constants have been elided.
 
594
#
 
595
 
 
596
my $cont_in;            # currently inside of a continuation
 
597
my $cont_off;           # skipping an initializer or definition
 
598
my $cont_noerr;         # suppress cascading errors
 
599
my $cont_start;         # the line being continued
 
600
my $cont_base;          # the base indentation
 
601
my $cont_first;         # this is the first line of a statement
 
602
my $cont_multiseg;      # this continuation has multiple segments
 
603
 
 
604
my $cont_special;       # this is a C statement (if, for, etc.)
 
605
my $cont_macro;         # this is a macro
 
606
my $cont_case;          # this is a multi-line case
 
607
 
 
608
my @cont_paren;         # the stack of unmatched ( and [s we've seen
 
609
 
 
610
sub
 
611
reset_indent()
 
612
{
 
613
        $cont_in = 0;
 
614
        $cont_off = 0;
 
615
}
 
616
 
 
617
sub
 
618
delabel($)
 
619
{
 
620
        #
 
621
        # replace labels with tabs.  Note that there may be multiple
 
622
        # labels on a line.
 
623
        #
 
624
        local $_ = $_[0];
 
625
 
 
626
        while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
 
627
                my ($pre_tabs, $label, $rest) = ($1, $2, $3);
 
628
                $_ = $pre_tabs;
 
629
                while ($label =~ s/^([^\t]*)(\t+)//) {
 
630
                        $_ .= "\t" x (length($2) + length($1) / 8);
 
631
                }
 
632
                $_ .= ("\t" x (length($label) / 8)).$rest;
 
633
        }
 
634
 
 
635
        return ($_);
 
636
}
 
637
 
 
638
sub
 
639
process_indent($)
 
640
{
 
641
        require strict;
 
642
        local $_ = $_[0];                       # preserve the global $_
 
643
 
 
644
        s///g; # No comments
 
645
        s/\s+$//;       # Strip trailing whitespace
 
646
 
 
647
        return                  if (/^$/);      # skip empty lines
 
648
 
 
649
        # regexps used below; keywords taking (), macros, and continued cases
 
650
        my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
 
651
        my $macro = '[A-Z_][A-Z_0-9]*\(';
 
652
        my $case = 'case\b[^:]*$';
 
653
 
 
654
        # skip over enumerations, array definitions, initializers, etc.
 
655
        if ($cont_off <= 0 && !/^\s*$special/ &&
 
656
            (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*)){/ ||
 
657
            (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
 
658
                $cont_in = 0;
 
659
                $cont_off = tr/{/{/ - tr/}/}/;
 
660
                return;
 
661
        }
 
662
        if ($cont_off) {
 
663
                $cont_off += tr/{/{/ - tr/}/}/;
 
664
                return;
 
665
        }
 
666
 
 
667
        if (!$cont_in) {
 
668
                $cont_start = $line;
 
669
 
 
670
                if (/^\t* /) {
 
671
                        err("non-continuation indented 4 spaces");
 
672
                        $cont_noerr = 1;                # stop reporting
 
673
                }
 
674
                $_ = delabel($_);       # replace labels with tabs
 
675
 
 
676
                # check if the statement is complete
 
677
                return          if (/^\s*\}?$/);
 
678
                return          if (/^\s*\}?\s*else\s*\{?$/);
 
679
                return          if (/^\s*do\s*\{?$/);
 
680
                return          if (/{$/);
 
681
                return          if (/}[,;]?$/);
 
682
 
 
683
                # Allow macros on their own lines
 
684
                return          if (/^\s*[A-Z_][A-Z_0-9]*$/);
 
685
 
 
686
                # cases we don't deal with, generally non-kosher
 
687
                if (/{/) {
 
688
                        err("stuff after {");
 
689
                        return;
 
690
                }
 
691
 
 
692
                # Get the base line, and set up the state machine
 
693
                /^(\t*)/;
 
694
                $cont_base = $1;
 
695
                $cont_in = 1;
 
696
                @cont_paren = ();
 
697
                $cont_first = 1;
 
698
                $cont_multiseg = 0;
 
699
 
 
700
                # certain things need special processing
 
701
                $cont_special = /^\s*$special/? 1 : 0;
 
702
                $cont_macro = /^\s*$macro/? 1 : 0;
 
703
                $cont_case = /^\s*$case/? 1 : 0;
 
704
        } else {
 
705
                $cont_first = 0;
 
706
 
 
707
                # Strings may be pulled back to an earlier (half-)tabstop
 
708
                unless ($cont_noerr || /^$cont_base    / ||
 
709
                    (/^\t*(?:    )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
 
710
                        err_prefix($cont_start,
 
711
                            "continuation should be indented 4 spaces");
 
712
                }
 
713
        }
 
714
 
 
715
        my $rest = $_;                  # keeps the remainder of the line
 
716
 
 
717
        #
 
718
        # The split matches 0 characters, so that each 'special' character
 
719
        # is processed separately.  Parens and brackets are pushed and
 
720
        # popped off the @cont_paren stack.  For normal processing, we wait
 
721
        # until a ; or { terminates the statement.  "special" processing
 
722
        # (if/for/while/switch) is allowed to stop when the stack empties,
 
723
        # as is macro processing.  Case statements are terminated with a :
 
724
        # and an empty paren stack.
 
725
        #
 
726
        foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
 
727
                next            if (length($_) == 0);
 
728
 
 
729
                # rest contains the remainder of the line
 
730
                my $rxp = "[^\Q$_\E]*\Q$_\E";
 
731
                $rest =~ s/^$rxp//;
 
732
 
 
733
                if (/\(/ || /\[/) {
 
734
                        push @cont_paren, $_;
 
735
                } elsif (/\)/ || /\]/) {
 
736
                        my $cur = $_;
 
737
                        tr/\)\]/\(\[/;
 
738
 
 
739
                        my $old = (pop @cont_paren);
 
740
                        if (!defined($old)) {
 
741
                                err("unexpected '$cur'");
 
742
                                $cont_in = 0;
 
743
                                last;
 
744
                        } elsif ($old ne $_) {
 
745
                                err("'$cur' mismatched with '$old'");
 
746
                                $cont_in = 0;
 
747
                                last;
 
748
                        }
 
749
 
 
750
                        #
 
751
                        # If the stack is now empty, do special processing
 
752
                        # for if/for/while/switch and macro statements.
 
753
                        #
 
754
                        next            if (@cont_paren != 0);
 
755
                        if ($cont_special) {
 
756
                                if ($rest =~ /^\s*{?$/) {
 
757
                                        $cont_in = 0;
 
758
                                        last;
 
759
                                }
 
760
                                if ($rest =~ /^\s*;$/) {
 
761
                                        err("empty if/for/while body ".
 
762
                                            "not on its own line");
 
763
                                        $cont_in = 0;
 
764
                                        last;
 
765
                                }
 
766
                                if (!$cont_first && $cont_multiseg == 1) {
 
767
                                        err_prefix($cont_start,
 
768
                                            "multiple statements continued ".
 
769
                                            "over multiple lines");
 
770
                                        $cont_multiseg = 2;
 
771
                                } elsif ($cont_multiseg == 0) {
 
772
                                        $cont_multiseg = 1;
 
773
                                }
 
774
                                # We've finished this section, start
 
775
                                # processing the next.
 
776
                                goto section_ended;
 
777
                        }
 
778
                        if ($cont_macro) {
 
779
                                if ($rest =~ /^$/) {
 
780
                                        $cont_in = 0;
 
781
                                        last;
 
782
                                }
 
783
                        }
 
784
                } elsif (/\;/) {
 
785
                        if ($cont_case) {
 
786
                                err("unexpected ;");
 
787
                        } elsif (!$cont_special) {
 
788
                                err("unexpected ;")     if (@cont_paren != 0);
 
789
                                if (!$cont_first && $cont_multiseg == 1) {
 
790
                                        err_prefix($cont_start,
 
791
                                            "multiple statements continued ".
 
792
                                            "over multiple lines");
 
793
                                        $cont_multiseg = 2;
 
794
                                } elsif ($cont_multiseg == 0) {
 
795
                                        $cont_multiseg = 1;
 
796
                                }
 
797
                                if ($rest =~ /^$/) {
 
798
                                        $cont_in = 0;
 
799
                                        last;
 
800
                                }
 
801
                                if ($rest =~ /^\s*special/) {
 
802
                                        err("if/for/while/switch not started ".
 
803
                                            "on its own line");
 
804
                                }
 
805
                                goto section_ended;
 
806
                        }
 
807
                } elsif (/\{/) {
 
808
                        err("{ while in parens/brackets") if (@cont_paren != 0);
 
809
                        err("stuff after {")            if ($rest =~ /[^\s}]/);
 
810
                        $cont_in = 0;
 
811
                        last;
 
812
                } elsif (/\}/) {
 
813
                        err("} while in parens/brackets") if (@cont_paren != 0);
 
814
                        if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
 
815
                                if ($rest =~ /^$/) {
 
816
                                        err("unexpected }");
 
817
                                } else {
 
818
                                        err("stuff after }");
 
819
                                }
 
820
                                $cont_in = 0;
 
821
                                last;
 
822
                        }
 
823
                } elsif (/\:/ && $cont_case && @cont_paren == 0) {
 
824
                        err("stuff after multi-line case") if ($rest !~ /$^/);
 
825
                        $cont_in = 0;
 
826
                        last;
 
827
                }
 
828
                next;
 
829
section_ended:
 
830
                # End of a statement or if/while/for loop.  Reset
 
831
                # cont_special and cont_macro based on the rest of the
 
832
                # line.
 
833
                $cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
 
834
                $cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
 
835
                $cont_case = 0;
 
836
                next;
 
837
        }
 
838
        $cont_noerr = 0                 if (!$cont_in);
 
839
}