summaryrefslogtreecommitdiff
path: root/mcon/pl/common.pl
blob: d797b54ed090ed89752bc86eb42c12d1a3aeee3d (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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
;# $Id: common.pl 1 2006-08-24 12:32:52Z rmanfredi $
;#
;#  Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi
;#  
;#  You may redistribute only under the terms of the Artistic Licence,
;#  as specified in the README file that comes with the distribution.
;#  You may reuse parts of this distribution only within the terms of
;#  that same Artistic Licence; a copy of which may be found at the root
;#  of the source tree for dist 4.0.
;#
;# $Log: common.pl,v $
;# Revision 3.0.1.4  1994/10/29  16:35:01  ram
;# patch36: metaconfig and metaxref ignore ?F: lines from now on
;#
;# Revision 3.0.1.3  1994/05/13  15:29:04  ram
;# patch27: now understands macro definitions in ?H: lines
;#
;# Revision 3.0.1.2  1994/01/24  14:22:54  ram
;# patch16: can now define "internal use only" variables on ?MAKE: lines
;#
;# Revision 3.0.1.1  1993/10/16  13:53:29  ram
;# patch12: added support for ?M: lines and confmagic.h production
;#
;# Revision 3.0  1993/08/18  12:10:19  ram
;# Baseline for dist 3.0 netwide release.
;#
;# The list of all available units is held in @ARGV. We shall parse them and
;# extract the dependencies. A lot of global data structures are filled in
;# during this phase.
;#
;# The following two H tables are used to record each know symbol (i.e. a
;# symbol known by at least one unit), and also how many times this symbol is
;# found in the sources. If an entry for a given key is positive, then the
;# associated symbol (i.e. the key) is wanted and it will be written in the
;# Wanted file.
;#  %shmaster{'$sym'} records how many times '$sym' is found in a .SH file
;#  %cmaster{'SYM'} records how many times 'SYM' is found in a .c file
;#  %cwanted{'SYM'} records the set of necessary shell symbols needed for SYM
;#  %mwanted{'sym'} is set of C symbols needed when sym is found in .c file
;#
;# This data structure records the initializations which are requires at the
;# beginning of a Configure script. The initialization only occurs when the
;# symbol is needed. Those symbols will appear in the produced config.sh file,
;# hence the name of "master" symbols.
;#  @Master records shell configuration symbols which will appear in config.sh
;#
;# The @Cond array records the conditional shell symbols, i.e. those whose
;# value may be defaulted. They will appear in the initialization section of
;# the Configure script with the default value if they are not otherwise used
;# but Configure needs a suitable value internally.
;#  @Cond records symbols which are flagged as conditional in the dependencies
;#  %hasdefault{'sym'} is true when the conditional 'sym' has a default value
;#
;# The %Obsolete array records the obsolecence for units or symbols. The key
;# ends with .U for units, otherwise it is a symbol. Unit's obsolescence is
;# flagged with a ?O: line (the line being the message which will be issued
;# when the unit is used) while symbol obsolecence is indicated on the leading
;# ?C: or ?S: line, between parenthesis. In that case, the value stored is the
;# new symbol which should be used insted.
;#  %Obsolete{'unit.U'} is a message to be printed when obsolete unit is used
;#  %Obsolete{'sym'} is the symbol to be used in place of the obsoleted 'sym'
;#
;# The $dependencies variable is used to record the dependencies extracted
;# from the units (?MAKE: line).
;#
;# During the dependency extraction. some files are produced in the .MT dir.
;#   Init.U records the initialization wanted
;#   Config_h.U records the informations which could go in config.h.SH
;#   Extern.U records the libraries and includes wanted by each symbol
;#
;# This file is shared by both metaconfig and metaxref
;#
# Initialize the extraction process by setting some variables.
# We return a string to be eval to do more customized initializations.
sub init_extraction {
	open(INIT, ">$WD/.MT/Init.U") ||
		die "Can't create .MT/Init.U\n";
	open(CONF_H, ">$WD/.MT/Config_h.U") ||
		die "Can't create .MT/Config_h.U\n";
	open(EXTERN, ">$WD/.MT/Extern.U") ||
		die "Can't create .MT/Extern.U\n";
	open(MAGIC_H, ">$WD/.MT/Magic_h.U") ||
		die "Can't create .MT/Magic_h.U\n";

	$c_symbol = '';				# Current symbol seen in ?C: lines
	$s_symbol = '';				# Current symbol seen in ?S: lines
	$m_symbol = '';				# Current symbol seen in ?M: lines
	$heredoc = '';				# Last "here" document symbol seen
	$heredoc_nosubst = 0;		# True for <<'EOM' here docs
	$condlist = '';				# List of conditional symbols
	$defined = '';				# List of defined symbols in the unit
	$body = '';					# No procedure to handle body
	$ending = '';				# No procedure to clean-up
}

# End the extraction process
sub end_extraction {
	close EXTERN;			# External dependencies (libraries, includes...)
	close CONF_H;			# C symbol definition template
	close INIT;				# Required initializations
	close MAGIC;			# Magic C symbol redefinition templates

	print $dependencies if $opt_v;	# Print extracted dependencies
}

# Process the ?MAKE: line
sub p_make {
	local($_) = @_;
	local(@ary);					# Locally defined symbols
	local(@dep);					# Dependencies
	if (/^[\w+ ]*:/) {				# Main dependency rule
		s|^\s*||;					# Remove leading spaces
		chop;
		s/:(.*)//;
		@dep = split(' ', $1);			# Dependencies
		@ary = split(' ');				# Locally defined symbols
		foreach $sym (@ary) {
			# Symbols starting with a '+' are meant for internal use only.
			next if $sym =~ s/^\+//;
			# Only sumbols starting with a lowercase letter are to
			# appear in config.sh, excepted the ones listed in Except.
			if ($sym =~ /^[_a-z]/ || $Except{$sym}) {
				$shmaster{"\$$sym"} = undef;
				push(@Master,"?$unit:$sym=''\n");	# Initializations
			}
		}
		$condlist = '';				# List of conditional symbols
		local($sym);				# Symbol copy, avoid @dep alteration
		foreach $dep (@dep) {
			if ($dep =~ /^\+[A-Za-z]/) {
				($sym = $dep) =~ s|^\+||;
				$condlist .= "$sym ";
				push(@Cond, $sym) unless $condseen{$sym};
				$condseen{$sym}++;		# Conditionally wanted
			}
		}
		# Append to already existing dependencies. The 'defined' variable
		# is set for &write_out, used to implement ?L: and ?I: canvas. It is
		# reset each time a new unit is parsed.
		# NB: leading '+' for defined symbols (internal use only) have been
		# removed at this point, but conditional dependencies still bear it.
		$defined = join(' ', @ary);		# Symbols defined by this unit
		$dependencies .= $defined . ':' . join(' ', @dep) . "\n";
		$dependencies .= "	-cond $condlist\n" if $condlist;
	} else {
		$dependencies .= $_;		# Building rules
	}
}

# Process the ?O: line
sub p_obsolete {
	local($_) = @_;
	$Obsolete{"$unit.U"} .= $_;		# Message(s) to print if unit is used
}

# Process the ?S: lines
sub p_shell {
	local($_) = @_;
	unless ($s_symbol) {
		if (/^(\w+).*:/) {
			$s_symbol = $1;
			print "  ?S: $s_symbol\n" if $opt_d;
		} else {
			warn "\"$file\", line $.: syntax error in ?S: construct.\n";
			$s_symbol = $unit;
			return;
		}
		# Deal with obsolete symbol list (enclosed between parenthesis)
		&record_obsolete("\$$_") if /\(/;
	}
	m|^\.\s*$| && ($s_symbol = '');		# End of comment
}

# Process the ?C: lines
sub p_c {
	local($_) = @_;
	unless ($c_symbol) {
		if (s/^(\w+)\s*~\s*(\S+)\s*(.*):/$1 $3:/) {
			# The ~ operator aliases the main C symbol to another symbol which
			# is to be used instead for definition in config.h. That is to say,
			# the line '?C:SYM ~ other:' would look for symbol 'other' instead,
			# and the documentation for symbol SYM would only be included in
			# config.h if 'other' were actually wanted.
			$c_symbol = $2;			# Alias for definition in config.h
			print "  ?C: $1 ~ $c_symbol\n" if $opt_d;
		} elsif (/^(\w+).*:/) {
			# Default behaviour. Include in config.h if symbol is needed.
			$c_symbol = $1;
			print "  ?C: $c_symbol\n" if $opt_d;
		} else {
			warn "\"$file\", line $.: syntax error in ?C: construct.\n";
			$c_symbol = $unit;
			return;
		}
		# Deal with obsolete symbol list (enclosed between parenthesis) and
		# make sure that list do not appear in config.h.SH by removing it.
		&record_obsolete("$_") if /\(/;
		s/\s*\(.*\)//;					# Get rid of obsolete symbol list
	}
	s|^(\w+)\s*|?$c_symbol:/* $1| ||						# Start of comment
	(s|^\.\s*$|?$c_symbol: */\n| && ($c_symbol = '', 1)) ||	# End of comment
	s|^(.*)|?$c_symbol: *$1|;								# Middle of comment
	&p_config("$_");					# Add comments to config.h.SH
}

# Process the ?H: lines
sub p_config {
	local($_) = @_;
	local($constraint);					# Constraint to be used for inclusion
	++$old_version if s/^\?%1://;		# Old version
	if (s/^\?(\w+)://) {				# Remove leading '?var:'
		$constraint = $1;				# Constraint is leading '?var'
	} else {
		$constraint = '';				# No constraint
	}
	if (/^#.*\$/) {						# Look only for cpp lines
		if (m|^#\$(\w+)\s+(\w+).*\$(\w+)|) {
			# Case: #$d_var VAR "$var"
			$constraint = $2 unless $constraint;
			print "  ?H: ($constraint) #\$$1 $2 \"\$$3\"\n" if $opt_d;
			$cmaster{$2} = undef;
			$cwanted{$2} = "$1\n$3";
		} elsif (m|^#define\s+(\w+)\((.*)\)\s+\$(\w+)|) {
			# Case: #define VAR(x) $var
			$constraint = $1 unless $constraint;
			print "  ?H: ($constraint) #define $1($2) \$$3\n" if $opt_d;
			$cmaster{$1} = undef;
			$cwanted{$1} = $3;
		} elsif (m|^#\$define\s+(\w+)|) {
			# Case: #$define VAR
			$constraint = $1 unless $constraint;
			print "  ?H: ($constraint) #define $1\n" if $opt_d;
			$cmaster{$1} = undef;
			$cwanted{$1} = "define\n$unit";
		} elsif (m|^#\$(\w+)\s+(\w+)|) {
			# Case: #$d_var VAR
			$constraint = $2 unless $constraint;
			print "  ?H: ($constraint) #\$$1 $2\n" if $opt_d;
			$cmaster{$2} = undef;
			$cwanted{$2} = $1;
		} elsif (m|^#define\s+(\w+).*\$(\w+)|) {
			# Case: #define VAR "$var"
			$constraint = $1 unless $constraint;
			print "  ?H: ($constraint) #define $1 \"\$$2\"\n" if $opt_d;
			$cmaster{$1} = undef;
			$cwanted{$1} = $2;
		} else {
			$constraint = $unit unless $constraint;
			print "  ?H: ($constraint) $_" if $opt_d;
		}
	} else {
		print "  ?H: ($constraint) $_" if $opt_d;
	}
	# If not a single ?H:. line, add the leading constraint
	s/^\.// || s/^/?$constraint:/;
	print CONF_H;
}

# Process the ?M: lines
sub p_magic {
	local($_) = @_;
	unless ($m_symbol) {
		if (/^(\w+):\s*([\w\s]*)\n$/) {
			# A '?M:sym:' line implies a '?W:%<:sym' since we'll need to know
			# about the wantedness of sym later on when building confmagic.h.
			# Buf is sym is wanted, then the C symbol dependencies have to
			# be triggered. That is done by introducing sym in the mwanted
			# array, known by the Wanted file construction process...
			$m_symbol = $1;
			print "  ?M: $m_symbol\n" if $opt_d;
			$mwanted{$m_symbol} = $2;		# Record C dependencies
			&p_wanted("$unit:$m_symbol");	# Build fake ?W: line
		} else {
			warn "\"$file\", line $.: syntax error in ?M: construct.\n";
		}
		return;
	}
	(s/^\.\s*$/?$m_symbol:\n/ && ($m_symbol = '', 1)) ||	# End of block
	s/^/?$m_symbol:/;
	print MAGIC_H;					# Definition goes to confmagic.h
	print "  ?M: $_" if $opt_d;
}

sub p_ignore {}		# Ignore comment line
sub p_lint {}		# Ignore lint directives
sub p_visible {}	# No visible checking in metaconfig
sub p_temp {}		# No temporary variable control
sub p_file {}		# Ignore produced file directives (for now)