#!/bin/ksh # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # # # Given a header file, extract function prototypes and global variable # declarations in a form that can be used in a mapfile. The list of extracted # functions and variables will be combined with a user-specified template to # create a complete mapfile. # # Template # -------- # # The template contains two sections - the prologue, and the epilogue. These # sections are used, verbatim, as the beginning and the end of the mapfile. # Sections begin and end with single-line comments whose sole contents are # "/* BEGIN $section */" and "/* END $section */". # # Template example: # # /* BEGIN PROLOGUE */ # [ ... prologue goes here ... ] # /* END PROLOGUE */ # /* BEGIN EPILOGUE */ # [ ... epilogue goes here ... ] # /* END EPILOGUE */ # # Selective Exportation # --------------------- # # Some header files will have a public/private interface mix that is strongly # biased towards private interfaces. That is, of the interfaces declared by # a given header file, the majority of them are private. Only a small subset # of interfaces are to be exported publicly. Using Selective Exportation, a # special comment is included in the header file, declaring to this script that # only a subset of interfaces - those with a marking declared in the comment - # should be included in the mapfile. The marking is itself a special comment, # whose format is declared using a directive like this: # # MAPFILE: export "Driver OK" # # Using the above directive, only those function prototypes and variable # declarations with "/* Driver OK */" comments included in the mapfile. Note # that the comment must be at the end of the first line. If the declaration # 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; /* variable */\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