hdr2map.sh revision 7c478bd95313f5f23a4c958a745db2134aa03244
0N/A#!/bin/ksh
0N/A#
0N/A# CDDL HEADER START
0N/A#
0N/A# The contents of this file are subject to the terms of the
0N/A# Common Development and Distribution License, Version 1.0 only
0N/A# (the "License"). You may not use this file except in compliance
0N/A# with the License.
0N/A#
0N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0N/A# or http://www.opensolaris.org/os/licensing.
0N/A# See the License for the specific language governing permissions
0N/A# and limitations under the License.
0N/A#
0N/A# When distributing Covered Code, include this CDDL HEADER in each
0N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0N/A# If applicable, add the following below this CDDL HEADER, with the
0N/A# fields enclosed by brackets "[]" replaced with your own identifying
873N/A# information: Portions Copyright [yyyy] [name of copyright owner]
0N/A#
0N/A# CDDL HEADER END
0N/A#
0N/A#
0N/A# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
868N/A# Use is subject to license terms.
0N/A#
0N/A#ident "%Z%%M% %I% %E% SMI"
0N/A#
0N/A
0N/A#
0N/A# Given a header file, extract function prototypes and global variable
0N/A# declarations in a form that can be used in a mapfile. The list of extracted
0N/A# functions and variables will be combined with a user-specified template to
0N/A# create a complete mapfile.
0N/A#
0N/A# Template
0N/A# --------
0N/A#
0N/A# The template contains two sections - the prologue, and the epilogue. These
0N/A# sections are used, verbatim, as the beginning and the end of the mapfile.
0N/A# Sections begin and end with single-line comments whose sole contents are
0N/A# "/* BEGIN $section */" and "/* END $section */".
0N/A#
0N/A# Template example:
0N/A#
0N/A# /* BEGIN PROLOGUE */
0N/A# [ ... prologue goes here ... ]
0N/A# /* END PROLOGUE */
0N/A# /* BEGIN EPILOGUE */
0N/A# [ ... epilogue goes here ... ]
0N/A# /* END EPILOGUE */
0N/A#
0N/A# Selective Exportation
0N/A# ---------------------
0N/A#
0N/A# Some header files will have a public/private interface mix that is strongly
0N/A# biased towards private interfaces. That is, of the interfaces declared by
0N/A# a given header file, the majority of them are private. Only a small subset
0N/A# of interfaces are to be exported publicly. Using Selective Exportation, a
0N/A# special comment is included in the header file, declaring to this script that
0N/A# only a subset of interfaces - those with a marking declared in the comment -
0N/A# should be included in the mapfile. The marking is itself a special comment,
0N/A# whose format is declared using a directive like this:
0N/A#
0N/A# MAPFILE: export "Driver OK"
0N/A#
0N/A# Using the above directive, only those function prototypes and variable
0N/A# declarations with "/* Driver OK */" comments included in the mapfile. Note
0N/A# that the comment must be at the end of the first line. If the declaration
0N/A# spans multiple lines, the exportation comment must appear on the first line.
#
# Examples of functions selected for exportation:
#
# MAPFILE: export "Driver OK"
#
# extern int foo(int); /* Driver OK */
# extern void bar(int, int, /* Driver OK */
# int, void *);
#
# Selective Exportation may not be used in the same file as Selective Exclusion.
#
# Selective Exclusion
# -------------------
#
# Selective Exclusion is to be used in cases where the public/private interface
# mix is reversed - where public interfaces greatly outnumber the private ones.
# In this case, we want to be able to mark the private ones, thus telling this
# script that the marked interfaces are to be excluded from the mapfile.
# Marking is accomplished via a process similar to that used for Selective
# Exportation. A directive is included in a comment, and is formatted like
# this:
#
# MAPFILE: exclude "Internal"
#
# Using the above directive, function prototypes and variable declarations with
# "/* Internal */" comments would be excluded. Note that the comment must be at
# the end of the first line. If the declaration spans multiple lines, the
# exclusion comment must appear on the first line.
#
# Examples of functions excluded from exportation:
#
# MAPFILE: exclude "Internal"
#
# extern int foo(int); /* Internal */
# extern void bar(int, int, /* Internal */
# int, void *);
#
# Selective Exclusion may not be used in the same file as Selective Exportation.
#
function extract_prototypes
{
typeset header="$1"
typeset prefix="$2"
nawk -v prefix="$prefix" <$header '
/^.*MAPFILE: export \"[^\"]*\"$/ {
if (protoexclude) {
print "ERROR: export after exclude\n";
exit(1);
}
sub(/^[^\"]*\"/, "");
sub(/\"$/, "");
exportmark=sprintf("/* %s */", $0);
next;
}
/^.*MAPFILE: exclude \"[^\"]*\"$/ {
if (protomatch) {
print "ERROR: exclude after export";
exit(1);
}
sub(/^[^\"]*\"/, "");
sub(/\"$/, "");
excludemark=sprintf("/* %s */", $0);
next;
}
exportmark {
# Selective Exportation has been selected (exportmark is
# set), so exclude this line if it does not have the
# magic export mark.
if (length($0) < length(exportmark) ||
substr($0, length($0) - length(exportmark) + 1) != \
exportmark)
next;
}
excludemark {
# Selective Exclusion has been selected (excludemark is
# set), so exclude this line only if it has the magic
# exclude mark.
if (length($0) > length(excludemark) &&
substr($0, \
length($0) - length(excludemark) + 1) == \
excludemark)
next;
}
# Functions
/^extern.*\(/ {
for (i = 1; i <= NF; i++) {
if (sub(/\(.*$/, "", $i)) {
sub(/^\*/, "", $i);
if (!seenfn[$i]) {
printf("%s%s;\n", prefix, $i);
seenfn[$i] = 1;
}
break;
}
}
next;
}
# Global variables
/^extern[^\(\)]*;/ {
for (i = 1; i <= NF; i++) {
if (match($i, /;$/)) {
printf("%s%s;\n", prefix,
substr($i, 1, length($i) - 1));
break;
}
}
next;
}
' || die "Extraction failed"
}
function extract_section
{
typeset skel="$1"
typeset secname="$2"
nawk <$skel -v name=$secname -v skel=$skel '
/\/\* [^ ]* [^ ]* \*\// && $3 == name {
if ($2 == "BEGIN") {
printing = 1;
} else {
printing = 0;
}
next;
}
printing != 0 { print; }
'
}
function die
{
echo "$PROGNAME: $@" >&2
exit 1
}
function usage
{
echo "Usage: $PROGNAME -t tmplfile header [header ...]" >&2
exit 2
}
PROGNAME=$(basename "$0")
while getopts t: c ; do
case $c in
t)
mapfile_skel=$OPTARG
;;
?)
usage
esac
done
[[ -z "$mapfile_skel" ]] && usage
[[ ! -f $mapfile_skel ]] && die "Couldn't open template $tmplfile"
shift $(($OPTIND - 1))
[[ $# -lt 1 ]] && usage
for file in $@ ; do
[[ ! -f $file ]] && die "Can't open input file $file"
done
extract_section $mapfile_skel PROLOGUE
for file in $@ ; do
echo "\t\t/*"
echo "\t\t * Exported functions and variables from:"
echo "\t\t * $file"
echo "\t\t */"
extract_prototypes $file "\t\t"
echo
done
extract_section $mapfile_skel EPILOGUE