1#!/usr/bin/perl -w
2#-
3# Copyright (c) 2004 Dag-Erling Sm��rgrav
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer
11#    in this position and unchanged.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. The name of the author may not be used to endorse or promote products
16#    derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29#
30
31use strict;
32use Getopt::Std;
33
34sub EMPTY() {}
35
36MAIN:{
37    my %opts;
38    getopts('c', \%opts);
39
40    my %config;
41    my $machine;
42    my $ident;
43
44    while (<>) {
45	chomp();
46	s/\s*(\#.*)?$//;
47	next unless $_;
48	my ($keyword, $values) = split(' ', $_, 2);
49	foreach my $value (split(/,\s*/, $values)) {
50	    if ($keyword eq 'machine') {
51		$machine = $value;
52	    } elsif ($keyword eq 'ident') {
53		$ident = $value;
54	    } elsif ($keyword eq 'options' && $value =~ m/(\w+)=(.+)/) {
55		$config{$keyword}->{$1} = $2;
56	    } else {
57		$config{$keyword}->{$value} = \&EMPTY;
58	    }
59	}
60    }
61
62    my $generic;
63    if ($machine) {
64	$generic = "/usr/src/sys/$machine/conf/GENERIC";
65    } else {
66	($generic = $ARGV) =~ s|([^/])+$|GENERIC|;
67    }
68    local *GENERIC;
69    open(GENERIC, "<", $generic)
70	or die("$generic: $!\n");
71    my $blank = 0;
72    while (<GENERIC>) {
73	my $line = $_;
74	chomp();
75	if ($opts{'c'} && m/^\s*\#/) {
76	    if ($blank) {
77		print "\n";
78		$blank = 0;
79	    }
80	    print $line;
81	    next;
82	}
83	++$blank unless $_;
84	s/\s*(\#.*)?$//;
85	next unless $_;
86	my ($keyword, $value) = split(' ', $_);
87	if ($keyword eq 'machine') {
88	    die("$generic is for $value, not $machine\n")
89		unless ($value eq $machine);
90	} elsif ($keyword eq 'ident') {
91	    $line =~ s/$value/$ident/;
92	} elsif ($keyword eq 'options' && $value =~ m/(\w+)=(.+)/ &&
93	    $config{$keyword} && $config{$keyword}->{$1} &&
94	    $config{$keyword}->{$1} != \&EMPTY) {
95	    $value = $1;
96	    if ($config{$keyword}->{$value} ne $2) {
97		my ($old, $new) = ($2, $config{$keyword}->{$value});
98		$line =~ s{=$old}{=$new};
99	    }
100	    delete($config{$keyword}->{$value});
101	    delete($config{$keyword})
102		unless %{$config{$keyword}};
103	} elsif ($config{$keyword} && $config{$keyword}->{$value}) {
104	    delete($config{$keyword}->{$value});
105	    delete($config{$keyword})
106		unless %{$config{$keyword}};
107	} else {
108	    next;
109	}
110	if ($blank) {
111	    print "\n";
112	    $blank = 0;
113	}
114	print $line;
115    }
116    close(GENERIC);
117
118    if (%config) {
119	print "\n# Addenda\n";
120	foreach my $keyword (sort(keys(%config))) {
121	    foreach my $value (sort(keys(%{$config{$keyword}}))) {
122		print "$keyword";
123		if (length($keyword) < 7) {
124		    print "\t";
125		} elsif (length($keyword) == 7) {
126		    print " ";
127		}
128		print "\t$value";
129		print "=$config{$keyword}->{$value}"
130		    unless $config{$keyword}->{$value} == \&EMPTY;
131		print "\n";
132	    }
133	}
134    }
135    exit(0);
136}
137