summaryrefslogtreecommitdiff
path: root/web/glasgow/lit2x-0.16/literate/a-cpp-ish-thing-from-the-net
blob: 41b38e9d5aae9269619977ae8c247e8fc7026a1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
From aks@anywhere.ucsb.edu Fri May  3 10:51:57 1991
From: aks@anywhere.ucsb.edu (Alan Stebbens)
Newsgroups: comp.lang.perl
Subject: Program to list (and comprehend) nested includes
Summary: Program to list nested `cpp' includes
Keywords: Program lists nested #includes
Date: 1 May 91 23:57:43 GMT
Organization: CCSE, Univ. of CA, Santa Barbara

When trying to port software to the IBM RS3000 running AIX 3.1, it
often occurs that I have to isolate a missing or malformed rerenced to
some "standard" macro or define.  Also, there are many include files in
the /usr/include hierarchy which are ultimately recursive by
re-invoking, for example, /usr/include/standards.h.  It becomes very
difficult to understand the dependencies of these include files when
such recursion occurs is several places or is very deep.

The following program, "includes", is my "quick 'n dirty" solution to
this problem:  it will list, and optionally indent and line-number, the
standard `cpp' include directives.

Oh yeah, a caveat: I had originally intended the program to be able to
dynamically interpret #define's and #undef's, but never followed up
with the code to do the job.  Thus, the internal documentation and
"usage:" show a -D and -U option usage, but don't really do anything
with it.  Perhaps, some other time, I'll make it work as intended.  Or,
someone else will.

Enjoy.

Alan Stebbens        <aks@hub.ucsb.edu>             (805) 893-3221
     Center for Computational Sciences and Engineering (CCSE)
          University of California, Santa Barbara (UCSB)
           3111 Engineering I, Santa Barbara, CA 93106

============================= cut here ===================================
#!/bin/perl
# includes [[-[vincu]...] [-Idir] [-Dname] [-Uname]]... files
#
# Given a list of files, determine the #include dependency list
# given '-c', use CPP to determine the _dynamic_ dependency list,
# otherwise, the static include file dependency list is produced.
#
# If the `-D' or `-U' options are given, `-c' is assumed.
#
#
$IndentStr = ' ' x 4;
@IncludeDirs = ('.');
@Defines = ();
$Verbose = 0;
$Pathnames = 0;
$LineNums = 0;
$Indent = 0;
$SortUniq = 0;
&Usage unless $#ARGV >= $[;
while ($_ = shift) { 	# scan arguments
    if (!/^-/) {
	unshift(@ARGV,$_);
	last;
    }
    while (s/^-(.)/-/) {
	$Compile++ 			if $1 eq 'c';
	$Indent++			if $1 eq 'i';
	$LineNums++			if $1 eq 'n';
	$Pathnames++			if $1 eq 'p';
	$SortUniq++			if $1 eq 's';
	$Verbose++			if $1 eq 'v';
	if ($1 =~ /[IDU]/) {
	    $opt = $1;
	    s/^-(.*)/-$opt$1/;		# put option back in
	    push(@IncludeDirs,$_)	if $opt eq 'I';
	    push(@Defines,$_)		if $opt =~ /DU/;
	    last;
	}
	&Usage unless $1 =~ /[cinpsv]/;
    }
}
&Usage if $SortUniq && ($LineNums || $Indent);
$Compile++ if $#Defines >= $[;		# any defines? compile it
$Pathnames = $LineNums = $Indent = 1 if $Verbose;
@Files = @ARGV;
while ($File = shift(@Files)) {
    printf "%s:\n",$File;
    if ($SortUniq) {
	select(STDOUT); $| = 1;
	open(SORT,"|sort -u +1 -2") || die "Can't open pipe to `sort -u' filter because $!\n";
	select(SORT);	$| = 1;
    }
    &ShowIncludes($File,0);
    if ($SortUniq) {
	close(SORT);
	select(STDOUT);
    }
}
exit;

%Included = ();
sub ShowIncludes {
    local($name,$level) = @_;
    local(*FILE);
    local($_,$.);
    local($pathname,$lq,$incname,$rq);
    local($indent) = $Indent ? $IndentStr x $level : '';

    if (open(FILE,$name)) {
	$Included{$name}++;
	while (<FILE>) {
	    next unless /^#include/;
	    chop;
	    if (/^#include\s*(")([^"]*)(")/ ||
		/^#include\s*(<)([^>]*)(>)/) {
		($lq,$incname,$rq) = ($1,$2,$3);
		print $indent;
		printf "%3d:",$. if $LineNums;
		printf "#include %s%s%s",$lq,$incname,$rq;
		if ($file = &FindFile($incname,($lq eq '"'))) {
		    printf "\t(%s)",$file if $Pathnames;
		    print "\n";
		    &ShowIncludes($file,$level+1) unless $Included{$file};
		} else {
		    printf ": can't find $incname\n";
		}
	    } else {
		print ": bad syntax.\n";
	    }
	}
	close FILE;
    } else {
	print ": can't open $name because $!\n";
    }
}

sub FindFile {
    local($file,$localflag) = @_;
    local($path);
    if ($localflag) {
	foreach $dir (@IncludeDirs) {
	    ($path = $dir . '/' . $file) =~ s/^-I//;
	    return $path if -f $path;
	}
    }
    foreach $dir ('/usr/local/include', '/usr/include') {
	return $path if -f ($path = $dir . '/' . $file);
    }
    '';
}

sub Usage {
    select(STDERR);
    print STDERR <<"EOF";
usage: includes [-cinspv] [-Ipath]... [-[D|U]name]... files
Prints the '#include' statements referenced by the named files, automatically
following nested #includes; statically recursive #includes are detected.
 -c	Compile (interpret) #ifdef's and expressions
 -i	Indent nested #includes
 -n	Print the line numbers of the #include statements
 -p	Print the absolute path names for each include file
 -s	Run the #includes through a `sort -u' filter
 -v	Verbose mode; implies `-inp' options
 -Ipath Add `path' to the include search path.
 -Dname	Define `name'; implies the `-c' option.
 -Uname	Undefine `name'; implies the `-c' option.
Sorting is mutually exclusive with indents and line numbering.
EOF
    exit 1;
}
  
============================= cut here ===================================
--

Alan Stebbens

From aks@anywhere.ucsb.edu Fri May  3 10:52:08 1991
From: aks@anywhere.ucsb.edu (Alan Stebbens)
Newsgroups: comp.lang.perl
Subject: Program to check for balanced #{if|else|endif}s
Summary: List, with optional line numbers and indention, `cpp' conditionals
Keywords: CPP #ifdef #else #endif listing
Date: 1 May 91 23:47:36 GMT
Organization: CCSE, Univ. of CA, Santa Barbara

The following is a perl program to list, with optional indentions 
and line numbers, the `cpp' conditionals: #ifdef, #elif, #else, #endif.
I wrote this because I was unsuccessfully trying to find a missing 
#ifdef in some newly patched software.

Enjoy.

Alan Stebbens        <aks@hub.ucsb.edu>             (805) 893-3221
     Center for Computational Sciences and Engineering (CCSE)
          University of California, Santa Barbara (UCSB)
           3111 Engineering I, Santa Barbara, CA 93106

============================= cut here ===================================
#!/bin/perl
# ifdefs [-n] [-i INDENT] [-l]
require 'getopts.pl';

&Getopts('i:nl') || die "Usage: ifdefs [-i indent] [-l] [-n] [files...]\n";

$INDENT = $opt_i ? $opt_i : 3;
$indent = 0;
@block = ();
@state = (0);
# States: 0 - nothing; 1 = #if ; 2 = #elsif ; 3 = #else 
select(STDOUT); $| = 1;
while (<>) {
    if (/^#\s*(if|ifn?def|elif|elsif|elseif|else|endif)/) {
	$key = $1;
	s/[ \t]+/ /g; 
	$nextindent = $indent;
	if ($key eq 'if' || $key =~ /ifn?def/) {
	    $state[$indent] = 1;
	    $block[$indent] = "$key $.";
	    $state[++$nextindent] = 0;
	} elsif ($key eq 'elseif' || $key eq 'elsif' || $key eq 'elif') {
	    $indent--;
	    &Error if !$indent || $state[$indent] < 1 || $state[$indent] > 2;
	    $block[$indent] = "$key $.";
	    $state[$indent] = 2;
	} elsif ($key eq 'else') {
	    &Error if !$indent;
	    $indent--;
	    &Error if $state[$indent] < 1 || $state[$indent] > 2;
	    $state[$indent] = 3;
	    $block[$indent] = "$key $.";
	} elsif ($key eq 'endif') {
    	    &Error if !$indent || $state[$indent];
	    $indent--;
	    &Error if !$state[$indent];
	    $state[$indent] = 0;
	    $block[$indent] = '';
	    $nextindent--;
	}
    } else {
	next unless $opt_l;
    }
    printf "%4d:",$. if $opt_n;
    printf "%s%s",(' 'x($indent * $INDENT)),$_;
    $indent = $nextindent;
}

sub Error {
    if (!$indent) {
	printf "ERROR: Unmatched \#%s:\n%4d: %s",$key,$.,$_;
    } else {
	printf "ERROR: Out of place \#%s:\n%4d: %s",$key,$.,$_;
	($keyw,$keyl) = split(' ',$block[$indent]);
	printf "Previous \#%s at line %d not terminated\n",$keyw,+$keyl;
    }
    next;
}
============================= cut here ===================================
--

Alan Stebbens