1#!/bin/perl -w
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, Version 1.0 only
7# (the "License").  You may not use this file except in compliance
8# 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#
24# ident	"%Z%%M%	%I%	%E% SMI"
25#
26# Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
27# Use is subject to license terms.
28#
29# ctfcvtptbl [-o outfile] patch-makeup-table
30#
31# Given a path to a patch makeup table, this script converts that table to
32# machine-optimal format and deposits it in the file specified by the -o option
33# or on stdout depending on whether or not -o is specified.
34#
35# The user-supplied patch makeup table is in the following format:
36#
37#   #
38#   # comment
39#   #
40#
41#   genunix_archive=/path/to/genunix/archive
42#
43#   patch 100001-01 kureq 100002-01
44#     usr/src/uts/sparc/sd/debug32/sd
45#     module2
46#
47#   patch 100003-08
48#     module3
49#
50# The machine-optimal format for the above looks like this:
51#
52#   GENUNIX_ARCHIVE=/path/to/genunix/archive
53#   module1 100001-01 100002-01
54#   module2 100001-01 100002-01
55#   module3 100003-08
56#
57#
58# Macros and other time-savers:
59#
60#  * $RELEASE and $MACH in the genunix archive path will be replaced by the
61#    values of the RELEASE and MACH environment variables, respectively, as
62#    set by the program calling this one.
63#
64#  * BUILD, BUILD32, and BUILD64 will, when used in the path for the module,
65#    will be match as follows:
66#
67#	BUILD	debug32, debug64, obj32, obj64
68#	BUILD32	debug32, obj32
69#	BUILD64	debug64, obj64
70#
71#  * The presence of `usr/src' at the beginning of each module path will be
72#    assumed, and is not required to be specified.
73#
74
75use strict;
76use Getopt::Std;
77use File::Basename;
78
79my $PROGNAME = basename($0);
80
81my $genunix_archive;
82my %moddata;
83my %typehash = (
84    BUILD	=> [ "debug32", "debug64", "obj32", "obj64" ],
85    BUILD32	=> [ "debug32", "obj32" ],
86    BUILD64	=> [ "debug64", "obj64" ]
87);
88
89my %opts;
90my $err = 0;
91$err = 1 unless getopts("ho:", \%opts);
92if ($opts{"o"}) {
93	close(STDOUT);
94	open(STDOUT, ">" . $opts{"o"}) || do {
95		print STDERR "Couldn't open " . $opts{"o"} . ": $!\n";
96		exit(1);
97	}
98}
99if ($opts{"h"}) {
100	&usage;
101	exit(2);
102}
103
104if (@ARGV != 1) {
105	$err = 1;
106}
107
108if ($err) {
109	&usage;
110	exit(2);
111}
112
113$::table = $ARGV[0];
114
115if (!open(TABLE, "<$::table")) {
116	print STDERR "Couldn't open $::table: $!\n";
117	exit(1);
118}
119
120if (!&read_table) {
121	exit(1);
122}
123
124&sub_vars;
125
126&dump_table;
127
128exit(0);
129
130sub usage {
131	print STDERR "Usage: $PROGNAME [-o outfile] table\n";
132}
133
134sub read_table {
135	my $patchid = "";
136	my $kureq = "";
137	my $kuprev = "";
138
139	$genunix_archive = "";
140	undef %moddata;
141
142	while (<TABLE>) {
143		chop;
144		s/\#.*$//; # Strip comments
145		s/^\s+//;
146
147		if (!$patchid && /^genunix_archive=(\S+)\s*$/) {
148			$genunix_archive = $1;
149			next;
150		}
151
152		while ($_) {
153			if (s/^patch\s+(\d{6}-\d{2})
154			    (\s+ku(req|prev)\s+(\d{6}-\d{2}|fcs))?//x &&
155			    (!$_ || /^\s/)) {
156				$patchid = $1;
157				$kureq = (defined $4 ? $4 : "fcs");
158				$kuprev = (defined $3 && $3 eq "prev" ? 1 : 0);
159			} elsif ($patchid && s/^(\S+)//) {
160				my $module = $1;
161
162				if (($module =~ m:/genunix/:) && !$kuprev) {
163					&parseerror("No kuprev supplied " .
164					    "for entry including genunix");
165				}
166
167				if (($module !~ m:^usr/src/:)) {
168					$module = "usr/src/" . $module;
169				}
170
171				if (($module =~
172				    m:^(.*)\$(BUILD|BUILD32|BUILD64)(/.*)$:)) {
173					foreach my $type (@{$typehash{$2}}) {
174						$moddata{$1 . $type . $3} =
175						    [$patchid, $kureq];
176					}
177				} else {
178					$moddata{$module} = [$patchid, $kureq];
179				}
180			} else {
181				&parseerror("Cannot parse table");
182			}
183
184			s/^\s+//;
185		}
186	}
187
188	if (!$genunix_archive) {
189		print STDERR "No genunix_archive line in table\n";
190		return (0);
191	}
192
193	if (!%moddata) {
194		print STDERR "No module information read\n";
195		return (0);
196	}
197
198	return (1);
199}
200
201sub parseerror {
202	my $msg = $_[0];
203
204	print STDERR "$msg at line $.\n";
205	exit(1);
206}
207
208sub sub_vars {
209	my $release = $ENV{"RELEASE"};
210	my $mach = $ENV{"MACH"};
211
212	$genunix_archive =~ s/\$RELEASE/$release/ if defined $release;
213	$genunix_archive =~ s/\$MACH/$mach/ if defined $mach;
214}
215
216sub dump_table {
217	print "GENUNIX_ARCHIVE=" . $genunix_archive . "\n";
218
219	foreach my $mod (sort keys %moddata) {
220		print join(" ", ($mod, @{$moddata{$mod}})) . "\n";
221	}
222}
223