commit 138e695

Emilia Smólska  ·  2026-08-28 17:16:14 +0000 UTC
parent ff862c1
cstyle
3 files changed,  +1407, -0
+384, -0
  1@@ -0,0 +1,384 @@
  2+Unless otherwise noted, all files in this distribution are released
  3+under the Common Development and Distribution License (CDDL).
  4+Exceptions are noted within the associated source files.
  5+
  6+--------------------------------------------------------------------
  7+
  8+
  9+COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
 10+
 11+1. Definitions.
 12+
 13+    1.1. "Contributor" means each individual or entity that creates
 14+         or contributes to the creation of Modifications.
 15+
 16+    1.2. "Contributor Version" means the combination of the Original
 17+         Software, prior Modifications used by a Contributor (if any),
 18+         and the Modifications made by that particular Contributor.
 19+
 20+    1.3. "Covered Software" means (a) the Original Software, or (b)
 21+         Modifications, or (c) the combination of files containing
 22+         Original Software with files containing Modifications, in
 23+         each case including portions thereof.
 24+
 25+    1.4. "Executable" means the Covered Software in any form other
 26+         than Source Code.
 27+
 28+    1.5. "Initial Developer" means the individual or entity that first
 29+         makes Original Software available under this License.
 30+
 31+    1.6. "Larger Work" means a work which combines Covered Software or
 32+         portions thereof with code not governed by the terms of this
 33+         License.
 34+
 35+    1.7. "License" means this document.
 36+
 37+    1.8. "Licensable" means having the right to grant, to the maximum
 38+         extent possible, whether at the time of the initial grant or
 39+         subsequently acquired, any and all of the rights conveyed
 40+         herein.
 41+
 42+    1.9. "Modifications" means the Source Code and Executable form of
 43+         any of the following:
 44+
 45+        A. Any file that results from an addition to, deletion from or
 46+           modification of the contents of a file containing Original
 47+           Software or previous Modifications;
 48+
 49+        B. Any new file that contains any part of the Original
 50+           Software or previous Modifications; or
 51+
 52+        C. Any new file that is contributed or otherwise made
 53+           available under the terms of this License.
 54+
 55+    1.10. "Original Software" means the Source Code and Executable
 56+          form of computer software code that is originally released
 57+          under this License.
 58+
 59+    1.11. "Patent Claims" means any patent claim(s), now owned or
 60+          hereafter acquired, including without limitation, method,
 61+          process, and apparatus claims, in any patent Licensable by
 62+          grantor.
 63+
 64+    1.12. "Source Code" means (a) the common form of computer software
 65+          code in which modifications are made and (b) associated
 66+          documentation included in or with such code.
 67+
 68+    1.13. "You" (or "Your") means an individual or a legal entity
 69+          exercising rights under, and complying with all of the terms
 70+          of, this License.  For legal entities, "You" includes any
 71+          entity which controls, is controlled by, or is under common
 72+          control with You.  For purposes of this definition,
 73+          "control" means (a) the power, direct or indirect, to cause
 74+          the direction or management of such entity, whether by
 75+          contract or otherwise, or (b) ownership of more than fifty
 76+          percent (50%) of the outstanding shares or beneficial
 77+          ownership of such entity.
 78+
 79+2. License Grants.
 80+
 81+    2.1. The Initial Developer Grant.
 82+
 83+    Conditioned upon Your compliance with Section 3.1 below and
 84+    subject to third party intellectual property claims, the Initial
 85+    Developer hereby grants You a world-wide, royalty-free,
 86+    non-exclusive license:
 87+
 88+        (a) under intellectual property rights (other than patent or
 89+            trademark) Licensable by Initial Developer, to use,
 90+            reproduce, modify, display, perform, sublicense and
 91+            distribute the Original Software (or portions thereof),
 92+            with or without Modifications, and/or as part of a Larger
 93+            Work; and
 94+
 95+        (b) under Patent Claims infringed by the making, using or
 96+            selling of Original Software, to make, have made, use,
 97+            practice, sell, and offer for sale, and/or otherwise
 98+            dispose of the Original Software (or portions thereof).
 99+
100+        (c) The licenses granted in Sections 2.1(a) and (b) are
101+            effective on the date Initial Developer first distributes
102+            or otherwise makes the Original Software available to a
103+            third party under the terms of this License.
104+
105+        (d) Notwithstanding Section 2.1(b) above, no patent license is
106+            granted: (1) for code that You delete from the Original
107+            Software, or (2) for infringements caused by: (i) the
108+            modification of the Original Software, or (ii) the
109+            combination of the Original Software with other software
110+            or devices.
111+
112+    2.2. Contributor Grant.
113+
114+    Conditioned upon Your compliance with Section 3.1 below and
115+    subject to third party intellectual property claims, each
116+    Contributor hereby grants You a world-wide, royalty-free,
117+    non-exclusive license:
118+
119+        (a) under intellectual property rights (other than patent or
120+            trademark) Licensable by Contributor to use, reproduce,
121+            modify, display, perform, sublicense and distribute the
122+            Modifications created by such Contributor (or portions
123+            thereof), either on an unmodified basis, with other
124+            Modifications, as Covered Software and/or as part of a
125+            Larger Work; and
126+
127+        (b) under Patent Claims infringed by the making, using, or
128+            selling of Modifications made by that Contributor either
129+            alone and/or in combination with its Contributor Version
130+            (or portions of such combination), to make, use, sell,
131+            offer for sale, have made, and/or otherwise dispose of:
132+            (1) Modifications made by that Contributor (or portions
133+            thereof); and (2) the combination of Modifications made by
134+            that Contributor with its Contributor Version (or portions
135+            of such combination).
136+
137+        (c) The licenses granted in Sections 2.2(a) and 2.2(b) are
138+            effective on the date Contributor first distributes or
139+            otherwise makes the Modifications available to a third
140+            party.
141+
142+        (d) Notwithstanding Section 2.2(b) above, no patent license is
143+            granted: (1) for any code that Contributor has deleted
144+            from the Contributor Version; (2) for infringements caused
145+            by: (i) third party modifications of Contributor Version,
146+            or (ii) the combination of Modifications made by that
147+            Contributor with other software (except as part of the
148+            Contributor Version) or other devices; or (3) under Patent
149+            Claims infringed by Covered Software in the absence of
150+            Modifications made by that Contributor.
151+
152+3. Distribution Obligations.
153+
154+    3.1. Availability of Source Code.
155+
156+    Any Covered Software that You distribute or otherwise make
157+    available in Executable form must also be made available in Source
158+    Code form and that Source Code form must be distributed only under
159+    the terms of this License.  You must include a copy of this
160+    License with every copy of the Source Code form of the Covered
161+    Software You distribute or otherwise make available.  You must
162+    inform recipients of any such Covered Software in Executable form
163+    as to how they can obtain such Covered Software in Source Code
164+    form in a reasonable manner on or through a medium customarily
165+    used for software exchange.
166+
167+    3.2. Modifications.
168+
169+    The Modifications that You create or to which You contribute are
170+    governed by the terms of this License.  You represent that You
171+    believe Your Modifications are Your original creation(s) and/or
172+    You have sufficient rights to grant the rights conveyed by this
173+    License.
174+
175+    3.3. Required Notices.
176+
177+    You must include a notice in each of Your Modifications that
178+    identifies You as the Contributor of the Modification.  You may
179+    not remove or alter any copyright, patent or trademark notices
180+    contained within the Covered Software, or any notices of licensing
181+    or any descriptive text giving attribution to any Contributor or
182+    the Initial Developer.
183+
184+    3.4. Application of Additional Terms.
185+
186+    You may not offer or impose any terms on any Covered Software in
187+    Source Code form that alters or restricts the applicable version
188+    of this License or the recipients' rights hereunder.  You may
189+    choose to offer, and to charge a fee for, warranty, support,
190+    indemnity or liability obligations to one or more recipients of
191+    Covered Software.  However, you may do so only on Your own behalf,
192+    and not on behalf of the Initial Developer or any Contributor.
193+    You must make it absolutely clear that any such warranty, support,
194+    indemnity or liability obligation is offered by You alone, and You
195+    hereby agree to indemnify the Initial Developer and every
196+    Contributor for any liability incurred by the Initial Developer or
197+    such Contributor as a result of warranty, support, indemnity or
198+    liability terms You offer.
199+
200+    3.5. Distribution of Executable Versions.
201+
202+    You may distribute the Executable form of the Covered Software
203+    under the terms of this License or under the terms of a license of
204+    Your choice, which may contain terms different from this License,
205+    provided that You are in compliance with the terms of this License
206+    and that the license for the Executable form does not attempt to
207+    limit or alter the recipient's rights in the Source Code form from
208+    the rights set forth in this License.  If You distribute the
209+    Covered Software in Executable form under a different license, You
210+    must make it absolutely clear that any terms which differ from
211+    this License are offered by You alone, not by the Initial
212+    Developer or Contributor.  You hereby agree to indemnify the
213+    Initial Developer and every Contributor for any liability incurred
214+    by the Initial Developer or such Contributor as a result of any
215+    such terms You offer.
216+
217+    3.6. Larger Works.
218+
219+    You may create a Larger Work by combining Covered Software with
220+    other code not governed by the terms of this License and
221+    distribute the Larger Work as a single product.  In such a case,
222+    You must make sure the requirements of this License are fulfilled
223+    for the Covered Software.
224+
225+4. Versions of the License.
226+
227+    4.1. New Versions.
228+
229+    Sun Microsystems, Inc. is the initial license steward and may
230+    publish revised and/or new versions of this License from time to
231+    time.  Each version will be given a distinguishing version number.
232+    Except as provided in Section 4.3, no one other than the license
233+    steward has the right to modify this License.
234+
235+    4.2. Effect of New Versions.
236+
237+    You may always continue to use, distribute or otherwise make the
238+    Covered Software available under the terms of the version of the
239+    License under which You originally received the Covered Software.
240+    If the Initial Developer includes a notice in the Original
241+    Software prohibiting it from being distributed or otherwise made
242+    available under any subsequent version of the License, You must
243+    distribute and make the Covered Software available under the terms
244+    of the version of the License under which You originally received
245+    the Covered Software.  Otherwise, You may also choose to use,
246+    distribute or otherwise make the Covered Software available under
247+    the terms of any subsequent version of the License published by
248+    the license steward.
249+
250+    4.3. Modified Versions.
251+
252+    When You are an Initial Developer and You want to create a new
253+    license for Your Original Software, You may create and use a
254+    modified version of this License if You: (a) rename the license
255+    and remove any references to the name of the license steward
256+    (except to note that the license differs from this License); and
257+    (b) otherwise make it clear that the license contains terms which
258+    differ from this License.
259+
260+5. DISCLAIMER OF WARRANTY.
261+
262+    COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS"
263+    BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
264+    INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED
265+    SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
266+    PURPOSE OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND
267+    PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU.  SHOULD ANY
268+    COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
269+    INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
270+    NECESSARY SERVICING, REPAIR OR CORRECTION.  THIS DISCLAIMER OF
271+    WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.  NO USE OF
272+    ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
273+    DISCLAIMER.
274+
275+6. TERMINATION.
276+
277+    6.1. This License and the rights granted hereunder will terminate
278+    automatically if You fail to comply with terms herein and fail to
279+    cure such breach within 30 days of becoming aware of the breach.
280+    Provisions which, by their nature, must remain in effect beyond
281+    the termination of this License shall survive.
282+
283+    6.2. If You assert a patent infringement claim (excluding
284+    declaratory judgment actions) against Initial Developer or a
285+    Contributor (the Initial Developer or Contributor against whom You
286+    assert such claim is referred to as "Participant") alleging that
287+    the Participant Software (meaning the Contributor Version where
288+    the Participant is a Contributor or the Original Software where
289+    the Participant is the Initial Developer) directly or indirectly
290+    infringes any patent, then any and all rights granted directly or
291+    indirectly to You by such Participant, the Initial Developer (if
292+    the Initial Developer is not the Participant) and all Contributors
293+    under Sections 2.1 and/or 2.2 of this License shall, upon 60 days
294+    notice from Participant terminate prospectively and automatically
295+    at the expiration of such 60 day notice period, unless if within
296+    such 60 day period You withdraw Your claim with respect to the
297+    Participant Software against such Participant either unilaterally
298+    or pursuant to a written agreement with Participant.
299+
300+    6.3. In the event of termination under Sections 6.1 or 6.2 above,
301+    all end user licenses that have been validly granted by You or any
302+    distributor hereunder prior to termination (excluding licenses
303+    granted to You by any distributor) shall survive termination.
304+
305+7. LIMITATION OF LIABILITY.
306+
307+    UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
308+    (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
309+    INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
310+    COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
311+    LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
312+    CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
313+    LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK
314+    STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
315+    COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
316+    INFORMED OF THE POSSIBILITY OF SUCH DAMAGES.  THIS LIMITATION OF
317+    LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
318+    INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
319+    APPLICABLE LAW PROHIBITS SUCH LIMITATION.  SOME JURISDICTIONS DO
320+    NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
321+    CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT
322+    APPLY TO YOU.
323+
324+8. U.S. GOVERNMENT END USERS.
325+
326+    The Covered Software is a "commercial item," as that term is
327+    defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
328+    computer software" (as that term is defined at 48
329+    C.F.R. 252.227-7014(a)(1)) and "commercial computer software
330+    documentation" as such terms are used in 48 C.F.R. 12.212
331+    (Sept. 1995).  Consistent with 48 C.F.R. 12.212 and 48
332+    C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
333+    U.S. Government End Users acquire Covered Software with only those
334+    rights set forth herein.  This U.S. Government Rights clause is in
335+    lieu of, and supersedes, any other FAR, DFAR, or other clause or
336+    provision that addresses Government rights in computer software
337+    under this License.
338+
339+9. MISCELLANEOUS.
340+
341+    This License represents the complete agreement concerning subject
342+    matter hereof.  If any provision of this License is held to be
343+    unenforceable, such provision shall be reformed only to the extent
344+    necessary to make it enforceable.  This License shall be governed
345+    by the law of the jurisdiction specified in a notice contained
346+    within the Original Software (except to the extent applicable law,
347+    if any, provides otherwise), excluding such jurisdiction's
348+    conflict-of-law provisions.  Any litigation relating to this
349+    License shall be subject to the jurisdiction of the courts located
350+    in the jurisdiction and venue specified in a notice contained
351+    within the Original Software, with the losing party responsible
352+    for costs, including, without limitation, court costs and
353+    reasonable attorneys' fees and expenses.  The application of the
354+    United Nations Convention on Contracts for the International Sale
355+    of Goods is expressly excluded.  Any law or regulation which
356+    provides that the language of a contract shall be construed
357+    against the drafter shall not apply to this License.  You agree
358+    that You alone are responsible for compliance with the United
359+    States export administration regulations (and the export control
360+    laws and regulation of any other countries) when You use,
361+    distribute or otherwise make available any Covered Software.
362+
363+10. RESPONSIBILITY FOR CLAIMS.
364+
365+    As between Initial Developer and the Contributors, each party is
366+    responsible for claims and damages arising, directly or
367+    indirectly, out of its utilization of rights under this License
368+    and You agree to work with Initial Developer and Contributors to
369+    distribute such responsibility on an equitable basis.  Nothing
370+    herein is intended or shall be deemed to constitute any admission
371+    of liability.
372+
373+--------------------------------------------------------------------
374+
375+NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
376+DISTRIBUTION LICENSE (CDDL)
377+
378+For Covered Software in this distribution, this License shall
379+be governed by the laws of the State of California (excluding
380+conflict-of-law provisions).
381+
382+Any litigation relating to this License shall be subject to the
383+jurisdiction of the Federal Courts of the Northern District of
384+California and the state courts of the State of California, with
385+venue lying in Santa Clara County, California.
+1022, -0
   1@@ -0,0 +1,1022 @@
   2+#!/usr/bin/perl -w
   3+#
   4+# CDDL HEADER START
   5+#
   6+# The contents of this file are subject to the terms of the
   7+# Common Development and Distribution License (the "License").
   8+# You may not use this file except in compliance with the License.
   9+#
  10+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  11+# or http://www.opensolaris.org/os/licensing.
  12+# See the License for the specific language governing permissions
  13+# and limitations under the License.
  14+#
  15+# When distributing Covered Code, include this CDDL HEADER in each
  16+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  17+# If applicable, add the following below this CDDL HEADER, with the
  18+# fields enclosed by brackets "[]" replaced with your own identifying
  19+# information: Portions Copyright [yyyy] [name of copyright owner]
  20+#
  21+# CDDL HEADER END
  22+#
  23+# Copyright 2015 Toomas Soome <tsoome@me.com>
  24+# Copyright 2016 Nexenta Systems, Inc.
  25+# Copyright 2023 Oxide Computer Company
  26+#
  27+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  28+# Use is subject to license terms.
  29+#
  30+# Copyright (c) 2015 by Delphix. All rights reserved.
  31+#
  32+# @(#)cstyle 1.58 98/09/09 (from shannon)
  33+#
  34+# cstyle - check for some common stylistic errors.
  35+#
  36+#	cstyle is a sort of "lint" for C coding style.
  37+#	It attempts to check for the style used in the
  38+#	kernel, sometimes known as "Bill Joy Normal Form".
  39+#
  40+#	There's a lot this can't check for, like proper indentation
  41+#	of code blocks.  There's also a lot more this could check for.
  42+#
  43+#	A note to the non perl literate:
  44+#
  45+#		perl regular expressions are pretty much like egrep
  46+#		regular expressions, with the following special symbols
  47+#
  48+#		\s	any space character
  49+#		\S	any non-space character
  50+#		\w	any "word" character [a-zA-Z0-9_]
  51+#		\W	any non-word character
  52+#		\d	a digit [0-9]
  53+#		\D	a non-digit
  54+#		\b	word boundary (between \w and \W)
  55+#		\B	non-word boundary
  56+#
  57+
  58+require 5.0;
  59+use IO::File;
  60+use Getopt::Std;
  61+use strict;
  62+
  63+my $usage =
  64+"usage: cstyle [-chpvCP] [-o constructs] file ...
  65+	-c	check continuation indentation inside functions
  66+	-h	perform heuristic checks that are sometimes wrong
  67+	-p	perform some of the more picky checks
  68+	-v	verbose
  69+	-C	don't check anything in header block comments
  70+	-P	check for use of non-POSIX types
  71+	-o constructs
  72+		allow a comma-seperated list of optional constructs:
  73+		    doxygen	allow doxygen-style block comments (/** /*!)
  74+		    splint	allow splint-style lint comments (/*@ ... @*/)
  75+";
  76+
  77+my %opts;
  78+
  79+if (!getopts("cho:pvCP", \%opts)) {
  80+	print $usage;
  81+	exit 2;
  82+}
  83+
  84+my $check_continuation = $opts{'c'};
  85+my $heuristic = $opts{'h'};
  86+my $picky = $opts{'p'};
  87+my $verbose = $opts{'v'};
  88+my $ignore_hdr_comment = $opts{'C'};
  89+my $check_posix_types = $opts{'P'};
  90+
  91+my $doxygen_comments = 0;
  92+my $splint_comments = 0;
  93+
  94+if (defined($opts{'o'})) {
  95+	for my $x (split /,/, $opts{'o'}) {
  96+		if ($x eq "doxygen") {
  97+			$doxygen_comments = 1;
  98+		} elsif ($x eq "splint") {
  99+			$splint_comments = 1;
 100+		} else {
 101+			print "cstyle: unrecognized construct \"$x\"\n";
 102+			print $usage;
 103+			exit 2;
 104+		}
 105+	}
 106+}
 107+
 108+my ($filename, $line, $prev);		# shared globals
 109+
 110+my $fmt;
 111+my $hdr_comment_start;
 112+
 113+if ($verbose) {
 114+	$fmt = "%s: %d: %s\n%s\n";
 115+} else {
 116+	$fmt = "%s: %d: %s\n";
 117+}
 118+
 119+if ($doxygen_comments) {
 120+	# doxygen comments look like "/*!" or "/**"; allow them.
 121+	$hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
 122+} else {
 123+	$hdr_comment_start = qr/^\s*\/\*$/;
 124+}
 125+
 126+# FreeBSD uses comments styled as such for their license headers:
 127+# /*-
 128+#  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
 129+#  *
 130+#  ...
 131+#
 132+# In order to apply other cstyle checks to those files without stumbling over
 133+# the license header, tolerate such comment openings as well.
 134+my $fbsd_comment_start = qr/^\s*\/\*-$/;
 135+
 136+# Note, following must be in single quotes so that \s and \w work right.
 137+my $typename = '(int|char|short|long|unsigned|float|double' .
 138+    '|\w+_t|struct\s+\w+|union\s+\w+|FILE)';
 139+
 140+# mapping of old types to POSIX compatible types
 141+my %old2posix = (
 142+	'unchar' => 'uchar_t',
 143+	'ushort' => 'ushort_t',
 144+	'uint' => 'uint_t',
 145+	'ulong' => 'ulong_t',
 146+	'u_int' => 'uint_t',
 147+	'u_short' => 'ushort_t',
 148+	'u_long' => 'ulong_t',
 149+	'u_char' => 'uchar_t',
 150+	'u_int8_t' => 'uint8_t',
 151+	'u_int16_t' => 'uint16_t',
 152+	'u_int32_t' => 'uint32_t',
 153+	'u_int64_t' => 'uint64_t',
 154+	'u_quad_t' => 'uint64_t',
 155+	'quad' => 'quad_t'
 156+);
 157+
 158+my $lint_re = qr/\/\*(?:
 159+	ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
 160+	CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
 161+	FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
 162+	PROTOLIB[0-9]*|SCANFLIKE[0-9]*|CSTYLED.*?
 163+    )\*\//x;
 164+
 165+my $splint_re = qr/\/\*@.*?@\*\//x;
 166+
 167+my $warlock_re = qr/\/\*\s*(?:
 168+	VARIABLES\ PROTECTED\ BY|
 169+	MEMBERS\ PROTECTED\ BY|
 170+	ALL\ MEMBERS\ PROTECTED\ BY|
 171+	READ-ONLY\ VARIABLES:|
 172+	READ-ONLY\ MEMBERS:|
 173+	VARIABLES\ READABLE\ WITHOUT\ LOCK:|
 174+	MEMBERS\ READABLE\ WITHOUT\ LOCK:|
 175+	LOCKS\ COVERED\ BY|
 176+	LOCK\ UNNEEDED\ BECAUSE|
 177+	LOCK\ NEEDED:|
 178+	LOCK\ HELD\ ON\ ENTRY:|
 179+	READ\ LOCK\ HELD\ ON\ ENTRY:|
 180+	WRITE\ LOCK\ HELD\ ON\ ENTRY:|
 181+	LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
 182+	READ\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
 183+	WRITE\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
 184+	LOCK\ RELEASED\ AS\ SIDE\ EFFECT:|
 185+	LOCK\ UPGRADED\ AS\ SIDE\ EFFECT:|
 186+	LOCK\ DOWNGRADED\ AS\ SIDE\ EFFECT:|
 187+	FUNCTIONS\ CALLED\ THROUGH\ POINTER|
 188+	FUNCTIONS\ CALLED\ THROUGH\ MEMBER|
 189+	LOCK\ ORDER:
 190+    )/x;
 191+
 192+my $err_stat = 0;		# exit status
 193+
 194+if ($#ARGV >= 0) {
 195+	foreach my $arg (@ARGV) {
 196+		my $fh = new IO::File $arg, "r";
 197+		if (!defined($fh)) {
 198+			printf "%s: can not open\n", $arg;
 199+		} else {
 200+			&cstyle($arg, $fh);
 201+			close $fh;
 202+		}
 203+	}
 204+} else {
 205+	&cstyle("<stdin>", *STDIN);
 206+}
 207+exit $err_stat;
 208+
 209+my $no_errs = 0;		# set for CSTYLED-protected lines
 210+
 211+sub err($) {
 212+	my ($error) = @_;
 213+	unless ($no_errs) {
 214+		if ($verbose) {
 215+			printf $fmt, $filename, $., $error, $line;
 216+		} else {
 217+			printf $fmt, $filename, $., $error;
 218+		}
 219+		$err_stat = 1;
 220+	}
 221+}
 222+
 223+sub err_prefix($$) {
 224+	my ($prevline, $error) = @_;
 225+	my $out = $prevline."\n".$line;
 226+	unless ($no_errs) {
 227+		if ($verbose) {
 228+			printf $fmt, $filename, $., $error, $out;
 229+		} else {
 230+			printf $fmt, $filename, $., $error;
 231+		}
 232+		$err_stat = 1;
 233+	}
 234+}
 235+
 236+sub err_prev($) {
 237+	my ($error) = @_;
 238+	unless ($no_errs) {
 239+		if ($verbose) {
 240+			printf $fmt, $filename, $. - 1, $error, $prev;
 241+		} else {
 242+			printf $fmt, $filename, $. - 1, $error;
 243+		}
 244+		$err_stat = 1;
 245+	}
 246+}
 247+
 248+sub cstyle($$) {
 249+
 250+my ($fn, $filehandle) = @_;
 251+$filename = $fn;			# share it globally
 252+
 253+my $in_cpp = 0;
 254+my $next_in_cpp = 0;
 255+
 256+my $in_comment = 0;
 257+my $in_header_comment = 0;
 258+my $comment_done = 0;
 259+my $in_warlock_comment = 0;
 260+my $in_function = 0;
 261+my $in_function_header = 0;
 262+my $function_header_full_indent = 0;
 263+my $in_declaration = 0;
 264+my $note_level = 0;
 265+my $nextok = 0;
 266+my $nocheck = 0;
 267+
 268+my $in_string = 0;
 269+
 270+my ($okmsg, $comment_prefix);
 271+
 272+$line = '';
 273+$prev = '';
 274+reset_indent();
 275+
 276+line: while (<$filehandle>) {
 277+	s/\r?\n$//;	# strip return and newline
 278+
 279+	# save the original line, then remove all text from within
 280+	# double or single quotes, we do not want to check such text.
 281+
 282+	$line = $_;
 283+
 284+	#
 285+	# C allows strings to be continued with a backslash at the end of
 286+	# the line.  We translate that into a quoted string on the previous
 287+	# line followed by an initial quote on the next line.
 288+	#
 289+	# (we assume that no-one will use backslash-continuation with character
 290+	# constants)
 291+	#
 292+	$_ = '"' . $_		if ($in_string && !$nocheck && !$in_comment);
 293+
 294+	#
 295+	# normal strings and characters
 296+	#
 297+	s/'([^\\']|\\[^xX0]|\\0[0-9]*|\\[xX][0-9a-fA-F]*)'/''/g;
 298+	s/"([^\\"]|\\.)*"/\"\"/g;
 299+
 300+	#
 301+	# detect string continuation
 302+	#
 303+	if ($nocheck || $in_comment) {
 304+		$in_string = 0;
 305+	} else {
 306+		#
 307+		# Now that all full strings are replaced with "", we check
 308+		# for unfinished strings continuing onto the next line.
 309+		#
 310+		$in_string =
 311+		    (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
 312+		    s/^("")*"([^\\"]|\\.)*\\$/""/);
 313+	}
 314+
 315+	#
 316+	# figure out if we are in a cpp directive
 317+	#
 318+	$in_cpp = $next_in_cpp || /^\s*#/;	# continued or started
 319+	$next_in_cpp = $in_cpp && /\\$/;	# only if continued
 320+
 321+	# strip off trailing backslashes, which appear in long macros
 322+	s/\s*\\$//;
 323+
 324+	# an /* END CSTYLED */ comment ends a no-check block.
 325+	if ($nocheck) {
 326+		if (/\/\* *END *CSTYLED *\*\//) {
 327+			$nocheck = 0;
 328+		} else {
 329+			reset_indent();
 330+			next line;
 331+		}
 332+	}
 333+
 334+	# a /*CSTYLED*/ comment indicates that the next line is ok.
 335+	if ($nextok) {
 336+		if ($okmsg) {
 337+			err($okmsg);
 338+		}
 339+		$nextok = 0;
 340+		$okmsg = 0;
 341+		if (/\/\* *CSTYLED.*\*\//) {
 342+			/^.*\/\* *CSTYLED *(.*) *\*\/.*$/;
 343+			$okmsg = $1;
 344+			$nextok = 1;
 345+		}
 346+		$no_errs = 1;
 347+	} elsif ($no_errs) {
 348+		$no_errs = 0;
 349+	}
 350+
 351+	# check length of line.
 352+	# first, a quick check to see if there is any chance of being too long.
 353+	if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) {
 354+		# yes, there is a chance.
 355+		# replace tabs with spaces and check again.
 356+		my $eline = $line;
 357+		1 while $eline =~
 358+		    s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
 359+		if (length($eline) > 80) {
 360+			err("line > 80 characters");
 361+		}
 362+	}
 363+
 364+	# ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
 365+	if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
 366+		s/[^()]//g;			  # eliminate all non-parens
 367+		$note_level += s/\(//g - length;  # update paren nest level
 368+		next;
 369+	}
 370+
 371+	# a /* BEGIN CSTYLED */ comment starts a no-check block.
 372+	if (/\/\* *BEGIN *CSTYLED *\*\//) {
 373+		$nocheck = 1;
 374+	}
 375+
 376+	# a /*CSTYLED*/ comment indicates that the next line is ok.
 377+	if (/\/\* *CSTYLED.*\*\//) {
 378+		/^.*\/\* *CSTYLED *(.*) *\*\/.*$/;
 379+		$okmsg = $1;
 380+		$nextok = 1;
 381+	}
 382+	if (/\/\/ *CSTYLED/) {
 383+		/^.*\/\/ *CSTYLED *(.*)$/;
 384+		$okmsg = $1;
 385+		$nextok = 1;
 386+	}
 387+
 388+	# universal checks; apply to everything
 389+	if (/\t +\t/) {
 390+		err("spaces between tabs");
 391+	}
 392+	if (/ \t+ /) {
 393+		err("tabs between spaces");
 394+	}
 395+	if (/\s$/) {
 396+		err("space or tab at end of line");
 397+	}
 398+	if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
 399+		err("comment preceded by non-blank");
 400+	}
 401+
 402+	# is this the beginning or ending of a function?
 403+	# (not if "struct foo\n{\n")
 404+	if (/^\{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
 405+		$in_function = 1;
 406+		$in_declaration = 1;
 407+		$in_function_header = 0;
 408+		$function_header_full_indent = 0;
 409+		$prev = $line;
 410+		next line;
 411+	}
 412+	if (/^\}\s*(\/\*.*\*\/\s*)*$/) {
 413+		if ($prev =~ /^\s*return\s*;/) {
 414+			err_prev("unneeded return at end of function");
 415+		}
 416+		$in_function = 0;
 417+		reset_indent();		# we don't check between functions
 418+		$prev = $line;
 419+		next line;
 420+	}
 421+	if ($in_function_header && ! /^    (\w|\.)/ ) {
 422+		if (/^\{\}$/) {
 423+			$in_function_header = 0;
 424+			$function_header_full_indent = 0;
 425+		} elsif ($picky && ! (/^\t/ && $function_header_full_indent != 0)) {
 426+			err("continuation line should be indented by 4 spaces");
 427+		}
 428+	}
 429+
 430+	#
 431+	# If this matches something of form "foo(", it's probably a function
 432+	# definition, unless it ends with ") bar;", in which case it's a declaration
 433+	# that uses a macro to generate the type.
 434+	#
 435+	if (/^\w+\(/ && !/\) \w+;$/) {
 436+		$in_function_header = 1;
 437+		if (/\($/) {
 438+			$function_header_full_indent = 1;
 439+		}
 440+	}
 441+	if ($in_function_header && /^\{$/) {
 442+		$in_function_header = 0;
 443+		$function_header_full_indent = 0;
 444+		$in_function = 1;
 445+	}
 446+	if ($in_function_header && /\);$/) {
 447+		$in_function_header = 0;
 448+		$function_header_full_indent = 0;
 449+	}
 450+	if ($in_function_header && /\{$/ ) {
 451+		if ($picky) {
 452+			err("opening brace on same line as function header");
 453+		}
 454+		$in_function_header = 0;
 455+		$function_header_full_indent = 0;
 456+		$in_function = 1;
 457+		next line;
 458+	}
 459+
 460+	if ($in_warlock_comment && /\*\//) {
 461+		$in_warlock_comment = 0;
 462+		$prev = $line;
 463+		next line;
 464+	}
 465+
 466+	# a blank line terminates the declarations within a function.
 467+	# XXX - but still a problem in sub-blocks.
 468+	if ($in_declaration && /^$/) {
 469+		$in_declaration = 0;
 470+	}
 471+
 472+	if ($comment_done) {
 473+		$in_comment = 0;
 474+		$in_header_comment = 0;
 475+		$comment_done = 0;
 476+	}
 477+	# does this looks like the start of a block comment?
 478+	if (/$hdr_comment_start/ || /$fbsd_comment_start/) {
 479+		if (!/^\t*\/\*/) {
 480+			err("block comment not indented by tabs");
 481+		}
 482+		$in_comment = 1;
 483+		/^(\s*)\//;
 484+		$comment_prefix = $1;
 485+		if ($comment_prefix eq "") {
 486+			$in_header_comment = 1;
 487+		}
 488+		$prev = $line;
 489+		next line;
 490+	}
 491+	# are we still in the block comment?
 492+	if ($in_comment) {
 493+		if (/^$comment_prefix \*\/$/) {
 494+			$comment_done = 1;
 495+		} elsif (/\*\//) {
 496+			$comment_done = 1;
 497+			err("improper block comment close")
 498+			    unless ($ignore_hdr_comment && $in_header_comment);
 499+		} elsif (!/^$comment_prefix \*[ \t]/ &&
 500+		    !/^$comment_prefix \*$/) {
 501+			err("improper block comment")
 502+			    unless ($ignore_hdr_comment && $in_header_comment);
 503+		}
 504+	}
 505+
 506+	if ($in_header_comment && $ignore_hdr_comment) {
 507+		$prev = $line;
 508+		next line;
 509+	}
 510+
 511+	# check for errors that might occur in comments and in code.
 512+
 513+	# allow spaces to be used to draw pictures in header comments.
 514+	if (/[^ ]     / && !/".*     .*"/ && !$in_header_comment) {
 515+		err("spaces instead of tabs");
 516+	}
 517+	if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
 518+	    (!/^    (\w|\.)/ || $in_function != 0)) {
 519+		err("indent by spaces instead of tabs");
 520+	}
 521+	if (/^\t+ [^ \t\*]/ || /^\t+  \S/ || /^\t+   \S/) {
 522+		err("continuation line not indented by 4 spaces");
 523+	}
 524+	if (/$warlock_re/ && !/\*\//) {
 525+		$in_warlock_comment = 1;
 526+		$prev = $line;
 527+		next line;
 528+	}
 529+	if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
 530+		err("improper first line of block comment");
 531+	}
 532+
 533+	if ($in_comment) {	# still in comment, don't do further checks
 534+		$prev = $line;
 535+		next line;
 536+	}
 537+
 538+	if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
 539+	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
 540+		err("missing blank after open comment");
 541+	}
 542+	if (/\S\*\/[^)]|\S\*\/$/ &&
 543+	    !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
 544+		err("missing blank before close comment");
 545+	}
 546+	if (/\/\/\S/) {		# C++ comments
 547+		err("missing blank after start comment");
 548+	}
 549+	# check for unterminated single line comments, but allow them when
 550+	# they are used to comment out the argument list of a function
 551+	# declaration.
 552+	if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
 553+		err("unterminated single line comment");
 554+	}
 555+
 556+	if (/^(#else|#endif|#include)(.*)$/) {
 557+		$prev = $line;
 558+		if ($picky) {
 559+			my $directive = $1;
 560+			my $clause = $2;
 561+			# Enforce ANSI rules for #else and #endif: no noncomment
 562+			# identifiers are allowed after #endif or #else.  Allow
 563+			# C++ comments since they seem to be a fact of life.
 564+			if ((($1 eq "#endif") || ($1 eq "#else")) &&
 565+			    ($clause ne "") &&
 566+			    (!($clause =~ /^\s+\/\*.*\*\/$/)) &&
 567+			    (!($clause =~ /^\s+\/\/.*$/))) {
 568+				err("non-comment text following " .
 569+				    "$directive (or malformed $directive " .
 570+				    "directive)");
 571+			}
 572+		}
 573+		next line;
 574+	}
 575+
 576+	#
 577+	# delete any comments and check everything else.  Note that
 578+	# ".*?" is a non-greedy match, so that we don't get confused by
 579+	# multiple comments on the same line.
 580+	#
 581+	s/\/\*.*?\*\///g;
 582+	s/\/\/.*$//;		# C++ comments
 583+
 584+	# delete any trailing whitespace; we have already checked for that.
 585+	s/\s*$//;
 586+
 587+	# following checks do not apply to text in comments.
 588+
 589+	if (/[^<>\s][!<>=]=/ || /[^<>][!<>=]=[^\s,]/ ||
 590+	    (/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
 591+	    (/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
 592+	    /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
 593+		err("missing space around relational operator");
 594+	}
 595+	if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
 596+	    (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
 597+	    (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
 598+		# XXX - should only check this for C++ code
 599+		# XXX - there are probably other forms that should be allowed
 600+		if (!/\soperator=/) {
 601+			err("missing space around assignment operator");
 602+		}
 603+	}
 604+	if (/[,;]\S/ && !/\bfor \(;;\)/) {
 605+		err("comma or semicolon followed by non-blank");
 606+	}
 607+	# allow "for" statements to have empty "while" clauses
 608+	if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
 609+		err("comma or semicolon preceded by blank");
 610+	}
 611+	if (/^\s*(&&|\|\|)/) {
 612+		err("improper boolean continuation");
 613+	}
 614+	if (/\S   *(&&|\|\|)/ || /(&&|\|\|)   *\S/) {
 615+		err("more than one space around boolean operator");
 616+	}
 617+	if (/\b(for|if|while|switch|sizeof|alignof|return|case)\(/) {
 618+		err("missing space between keyword and paren");
 619+	}
 620+	if (/(\b(for|if|while|switch|return)\b.*){2,}/ && !/^#define/) {
 621+		# multiple "case" and "sizeof" allowed
 622+		err("more than one keyword on line");
 623+	}
 624+	if (/\b(for|if|while|switch|sizeof|alignof|return|case)\s\s+\(/ &&
 625+	    !/^#if\s+\(/) {
 626+		err("extra space between keyword and paren");
 627+	}
 628+	# try to detect "func (x)" but not "if (x)" or
 629+	# "#define foo (x)" or "int (*func)();"
 630+	if (/\w\s\(/) {
 631+		my $s = $_;
 632+		# strip off all keywords on the line
 633+		s/\b(for|if|while|switch|return|case|alignof|sizeof)\s\(/XXX(/g;
 634+		s/#elif\s\(/XXX(/g;
 635+		s/^#define\s+\w+\s+\(/XXX(/;
 636+		# do not match things like "void (*f)();"
 637+		# or "typedef void (func_t)();"
 638+		s/\w\s\(+\*/XXX(*/g;
 639+		s/\b($typename|void)\s+\(+/XXX(/og;
 640+		if (/\w\s\(/) {
 641+			err("extra space between function name and left paren");
 642+		}
 643+		$_ = $s;
 644+	}
 645+	# try to detect "int foo(x)", but not "extern int foo(x);"
 646+	# XXX - this still trips over too many legitimate things,
 647+	# like "int foo(x,\n\ty);"
 648+#		if (/^(\w+(\s|\*)+)+\w+\(/ && !/\)[;,](\s|)*$/ &&
 649+#		    !/^(extern|static)\b/) {
 650+#			err("return type of function not on separate line");
 651+#		}
 652+	# this is a close approximation
 653+	if (/^(\w+(\s|\*)+)+\w+\(.*\)(\s|)*$/ &&
 654+	    !/^(extern|static)\b/) {
 655+		err("return type of function not on separate line");
 656+	}
 657+	if (/^#define /) {
 658+		err("#define followed by space instead of tab");
 659+	}
 660+	if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
 661+		err("unparenthesized return expression");
 662+	}
 663+	if (/\bsizeof\b/ && !/\bsizeof\s*\(.*\)/) {
 664+		err("unparenthesized sizeof expression");
 665+	}
 666+	if (/\balignof\b/ && !/\balignof\s*\(.*\)/) {
 667+		err("unparenthesized alignof expression");
 668+	}
 669+	if (/\(\s/) {
 670+		err("whitespace after left paren");
 671+	}
 672+	# allow "for" statements to have empty "continue" clauses
 673+	if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
 674+		err("whitespace before right paren");
 675+	}
 676+	if (/^\s*\(void\)[^ ]/) {
 677+		err("missing space after (void) cast");
 678+	}
 679+	if (/\S\{/ && !/\{\{/) {
 680+		err("missing space before left brace");
 681+	}
 682+	if ($in_function && /^\s+\{/ &&
 683+	    ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
 684+		err("left brace starting a line");
 685+	}
 686+	if (/\}(else|while)/) {
 687+		err("missing space after right brace");
 688+	}
 689+	if (/\}\s\s+(else|while)/) {
 690+		err("extra space after right brace");
 691+	}
 692+	if (/\b_VOID\b|\bVOID\b|\bSTATIC\b/) {
 693+		err("obsolete use of VOID or STATIC");
 694+	}
 695+	if (/\b$typename\*/o) {
 696+		err("missing space between type name and *");
 697+	}
 698+	if (/^\s+#/) {
 699+		err("preprocessor statement not in column 1");
 700+	}
 701+	if (/^#\s/) {
 702+		err("blank after preprocessor #");
 703+	}
 704+	if (/!\s*(strcmp|strncmp|bcmp)\s*\(/) {
 705+		err("don't use boolean ! with comparison functions");
 706+	}
 707+
 708+	#
 709+	# We completely ignore, for purposes of indentation:
 710+	#  * lines outside of functions
 711+	#  * preprocessor lines
 712+	#
 713+	if ($check_continuation && $in_function && !$in_cpp) {
 714+		process_indent($_);
 715+	}
 716+	if ($picky) {
 717+		# try to detect spaces after casts, but allow (e.g.)
 718+		# "sizeof (int) + 1", "void (*funcptr)(int) = foo;", and
 719+		# "int foo(int) __NORETURN;"
 720+		if ((/^\($typename( \*+)?\)\s/o ||
 721+		    /\W\($typename( \*+)?\)\s/o) &&
 722+		    !/sizeof\s*\($typename( \*)?\)\s/o &&
 723+		    !/\($typename( \*+)?\)\s+=[^=]/o) {
 724+			err("space after cast");
 725+		}
 726+		if (/\b$typename\s*\*\s/o &&
 727+		    !/\b$typename\s*\*\s+const\b/o) {
 728+			err("unary * followed by space");
 729+		}
 730+	}
 731+	if ($check_posix_types) {
 732+		# try to detect old non-POSIX types.
 733+		# POSIX requires all non-standard typedefs to end in _t,
 734+		# but historically these have been used.
 735+		my $types = join '|', keys %old2posix;
 736+		if (/\b($types)\b/) {
 737+			err("non-POSIX typedef $1 used: use $old2posix{$1} instead");
 738+		}
 739+	}
 740+	if ($heuristic) {
 741+		# cannot check this everywhere due to "struct {\n...\n} foo;"
 742+		if ($in_function && !$in_declaration &&
 743+		    /\}./ && !/\}\s+=/ && !/\{.*\}[;,]$/ && !/\}(\s|)*$/ &&
 744+		    !/\} (else|while)/ && !/\}\}/) {
 745+			err("possible bad text following right brace");
 746+		}
 747+		# cannot check this because sub-blocks in
 748+		# the middle of code are ok
 749+		if ($in_function && /^\s+\{/) {
 750+			err("possible left brace starting a line");
 751+		}
 752+	}
 753+	if (/^\s*else\W/) {
 754+		if ($prev =~ /^\s*\}$/) {
 755+			err_prefix($prev,
 756+			    "else and right brace should be on same line");
 757+		}
 758+	}
 759+	$prev = $line;
 760+}
 761+
 762+if ($prev eq "") {
 763+	err("last line in file is blank");
 764+}
 765+
 766+}
 767+
 768+#
 769+# Continuation-line checking
 770+#
 771+# The rest of this file contains the code for the continuation checking
 772+# engine.  It's a pretty simple state machine which tracks the expression
 773+# depth (unmatched '('s and '['s).
 774+#
 775+# Keep in mind that the argument to process_indent() has already been heavily
 776+# processed; all comments have been replaced by control-A, and the contents of
 777+# strings and character constants have been elided.
 778+#
 779+
 780+my $cont_in;		# currently inside of a continuation
 781+my $cont_off;		# skipping an initializer or definition
 782+my $cont_noerr;		# suppress cascading errors
 783+my $cont_start;		# the line being continued
 784+my $cont_base;		# the base indentation
 785+my $cont_first;		# this is the first line of a statement
 786+my $cont_multiseg;	# this continuation has multiple segments
 787+
 788+my $cont_special;	# this is a C statement (if, for, etc.)
 789+my $cont_macro;		# this is a macro
 790+my $cont_case;		# this is a multi-line case
 791+
 792+my @cont_paren;		# the stack of unmatched ( and [s we've seen
 793+
 794+sub
 795+reset_indent()
 796+{
 797+	$cont_in = 0;
 798+	$cont_off = 0;
 799+}
 800+
 801+sub
 802+delabel($)
 803+{
 804+	#
 805+	# replace labels with tabs.  Note that there may be multiple
 806+	# labels on a line.
 807+	#
 808+	local $_ = $_[0];
 809+
 810+	while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
 811+		my ($pre_tabs, $label, $rest) = ($1, $2, $3);
 812+		$_ = $pre_tabs;
 813+		while ($label =~ s/^([^\t]*)(\t+)//) {
 814+			$_ .= "\t" x (length($2) + length($1) / 8);
 815+		}
 816+		$_ .= ("\t" x (length($label) / 8)).$rest;
 817+	}
 818+
 819+	return ($_);
 820+}
 821+
 822+sub
 823+process_indent($)
 824+{
 825+	require strict;
 826+	local $_ = $_[0];			# preserve the global $_
 827+
 828+	s///g;	# No comments
 829+	s/\s+$//;	# Strip trailing whitespace
 830+
 831+	return			if (/^$/);	# skip empty lines
 832+
 833+	# regexps used below; keywords taking (), macros, and continued cases
 834+	my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
 835+	my $macro = '[A-Z_][A-Z_0-9]*\(';
 836+	my $case = 'case\b[^:]*$';
 837+
 838+	# skip over enumerations, array definitions, initializers, etc.
 839+	if ($cont_off <= 0 && !/^\s*$special/ &&
 840+	    (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*))\{/ ||
 841+	    (/^\s*\{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
 842+		$cont_in = 0;
 843+		$cont_off = tr/{/{/ - tr/}/}/;
 844+		return;
 845+	}
 846+	if ($cont_off) {
 847+		$cont_off += tr/{/{/ - tr/}/}/;
 848+		return;
 849+	}
 850+
 851+	if (!$cont_in) {
 852+		$cont_start = $line;
 853+
 854+		if (/^\t* /) {
 855+			err("non-continuation indented 4 spaces");
 856+			$cont_noerr = 1;		# stop reporting
 857+		}
 858+		$_ = delabel($_);	# replace labels with tabs
 859+
 860+		# check if the statement is complete
 861+		return		if (/^\s*\}?$/);
 862+		return		if (/^\s*\}?\s*else\s*\{?$/);
 863+		return		if (/^\s*do\s*\{?$/);
 864+		return		if (/\{$/);
 865+		return		if (/\}[,;]?$/);
 866+
 867+		# Allow macros on their own lines
 868+		return		if (/^\s*[A-Z_][A-Z_0-9]*$/);
 869+
 870+		# cases we don't deal with, generally non-kosher
 871+		if (/\{/) {
 872+			err("stuff after {");
 873+			return;
 874+		}
 875+
 876+		# Get the base line, and set up the state machine
 877+		/^(\t*)/;
 878+		$cont_base = $1;
 879+		$cont_in = 1;
 880+		@cont_paren = ();
 881+		$cont_first = 1;
 882+		$cont_multiseg = 0;
 883+
 884+		# certain things need special processing
 885+		$cont_special = /^\s*$special/? 1 : 0;
 886+		$cont_macro = /^\s*$macro/? 1 : 0;
 887+		$cont_case = /^\s*$case/? 1 : 0;
 888+	} else {
 889+		$cont_first = 0;
 890+
 891+		# Strings may be pulled back to an earlier (half-)tabstop
 892+		unless ($cont_noerr || /^$cont_base    / ||
 893+		    (/^\t*(?:    )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
 894+			err_prefix($cont_start,
 895+			    "continuation should be indented 4 spaces");
 896+		}
 897+	}
 898+
 899+	my $rest = $_;			# keeps the remainder of the line
 900+
 901+	#
 902+	# The split matches 0 characters, so that each 'special' character
 903+	# is processed separately.  Parens and brackets are pushed and
 904+	# popped off the @cont_paren stack.  For normal processing, we wait
 905+	# until a ; or { terminates the statement.  "special" processing
 906+	# (if/for/while/switch) is allowed to stop when the stack empties,
 907+	# as is macro processing.  Case statements are terminated with a :
 908+	# and an empty paren stack.
 909+	#
 910+	foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
 911+		next		if (length($_) == 0);
 912+
 913+		# rest contains the remainder of the line
 914+		my $rxp = "[^\Q$_\E]*\Q$_\E";
 915+		$rest =~ s/^$rxp//;
 916+
 917+		if (/\(/ || /\[/) {
 918+			push @cont_paren, $_;
 919+		} elsif (/\)/ || /\]/) {
 920+			my $cur = $_;
 921+			tr/\)\]/\(\[/;
 922+
 923+			my $old = (pop @cont_paren);
 924+			if (!defined($old)) {
 925+				err("unexpected '$cur'");
 926+				$cont_in = 0;
 927+				last;
 928+			} elsif ($old ne $_) {
 929+				err("'$cur' mismatched with '$old'");
 930+				$cont_in = 0;
 931+				last;
 932+			}
 933+
 934+			#
 935+			# If the stack is now empty, do special processing
 936+			# for if/for/while/switch and macro statements.
 937+			#
 938+			next		if (@cont_paren != 0);
 939+			if ($cont_special) {
 940+				if ($rest =~ /^\s*\{?$/) {
 941+					$cont_in = 0;
 942+					last;
 943+				}
 944+				if ($rest =~ /^\s*;$/) {
 945+					err("empty if/for/while body ".
 946+					    "not on its own line");
 947+					$cont_in = 0;
 948+					last;
 949+				}
 950+				if (!$cont_first && $cont_multiseg == 1) {
 951+					err_prefix($cont_start,
 952+					    "multiple statements continued ".
 953+					    "over multiple lines");
 954+					$cont_multiseg = 2;
 955+				} elsif ($cont_multiseg == 0) {
 956+					$cont_multiseg = 1;
 957+				}
 958+				# We've finished this section, start
 959+				# processing the next.
 960+				goto section_ended;
 961+			}
 962+			if ($cont_macro) {
 963+				if ($rest =~ /^$/) {
 964+					$cont_in = 0;
 965+					last;
 966+				}
 967+			}
 968+		} elsif (/\;/) {
 969+			if ($cont_case) {
 970+				err("unexpected ;");
 971+			} elsif (!$cont_special) {
 972+				err("unexpected ;")	if (@cont_paren != 0);
 973+				if (!$cont_first && $cont_multiseg == 1) {
 974+					err_prefix($cont_start,
 975+					    "multiple statements continued ".
 976+					    "over multiple lines");
 977+					$cont_multiseg = 2;
 978+				} elsif ($cont_multiseg == 0) {
 979+					$cont_multiseg = 1;
 980+				}
 981+				if ($rest =~ /^$/) {
 982+					$cont_in = 0;
 983+					last;
 984+				}
 985+				if ($rest =~ /^\s*special/) {
 986+					err("if/for/while/switch not started ".
 987+					    "on its own line");
 988+				}
 989+				goto section_ended;
 990+			}
 991+		} elsif (/\{/) {
 992+			err("{ while in parens/brackets") if (@cont_paren != 0);
 993+			err("stuff after {")		if ($rest =~ /[^\s}]/);
 994+			$cont_in = 0;
 995+			last;
 996+		} elsif (/\}/) {
 997+			err("} while in parens/brackets") if (@cont_paren != 0);
 998+			if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
 999+				if ($rest =~ /^$/) {
1000+					err("unexpected }");
1001+				} else {
1002+					err("stuff after }");
1003+				}
1004+				$cont_in = 0;
1005+				last;
1006+			}
1007+		} elsif (/\:/ && $cont_case && @cont_paren == 0) {
1008+			err("stuff after multi-line case") if ($rest !~ /$^/);
1009+			$cont_in = 0;
1010+			last;
1011+		}
1012+		next;
1013+section_ended:
1014+		# End of a statement or if/while/for loop.  Reset
1015+		# cont_special and cont_macro based on the rest of the
1016+		# line.
1017+		$cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
1018+		$cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
1019+		$cont_case = 0;
1020+		next;
1021+	}
1022+	$cont_noerr = 0			if (!$cont_in);
1023+}
1@@ -3,6 +3,7 @@ c() { ln -sf $1 $2; }
2 c $PWD/Xdefaults ~/.Xdefaults
3 mkdir -p ~/bin
4 c $PWD/bin/amused-monitor ~/bin/amused-monitor
5+c $PWD/cddl/cstyle ~/bin/cstyle
6 c $PWD/bin/dxmessage ~/bin/dxmessage
7 c $PWD/bin/emifetch ~/bin/emifetch
8 c $PWD/bin/gcc ~/bin/gcc