#!/usr/bin/awk -f
##
## Copyright (c) 2000 University of Utah and the Flux Group.
## All rights reserved.
## 
## This file is part of the Knit component composition software.
## 
## Permission to use, copy, modify, distribute, and sell this software and
## its documentation is hereby granted without fee, provided that the above
## copyright notice and this permission/disclaimer notice is retained in all
## copies or modified versions, and that both notices appear in supporting
## documentation.  THE COPYRIGHT HOLDERS PROVIDE THIS SOFTWARE "AS IS" AND
## WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION,
## THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE.  THE COPYRIGHT HOLDERS DISCLAIM ANY LIABILITY OF ANY KIND FOR
## ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
## 
## Users are requested, but not required, to send to csl-dist@cs.utah.edu any
## improvements that they make and grant Univ. of Utah redistribution rights.
##

## This is a little `awk' script to pull definitions out of Knit unit files.
## The principal intended use of this script is to extract definitions so that
## they may be incorporated into documentation, e.g., the Knit User's Manual.
##
## Usage:
##	awk -f getdefs [MATCHING=...] [HEADERS=(0|1)] [<unit-file> ...]
## or:
##	getdefs ...
##
## where:
##	MATCHING is an `awk' regular expression that matches the names of the
##	definitions of interest.  If unspecified, MATCHING is set to ".", which
##	matches all non-empty definition names.
##
##	HEADERS is a flag.  If set, any block of `//'-style comments that
##	immediately precedes a matched definition will be output as well.
##	By default, this flag is set.
##
##	<unit-file> is the name of a Knit unit file.  If no files are given on
##	the command line, this script reads from stdin.
##
## This script assumes that a definition starts at a line like:
##
##	<word> <name> = ...
##
## where <word> appears at the beginning of the line (column 0).  A definition
## ends either (1) on the same line, if the line ends with "}", or (2) on the
## next line in which "}" appears at the beginning of the line (in column 0).
##
## This script requires GNU `awk'.

###############################################################################

BEGIN	{
		FS = " "
		MATCHING = "."
		HEADERS = 1
		found_any_defs = 0
		in_def = 0
		one_liner = 0
		header_lines = 0
		header_trailing_blanks = 0
		discarded = 0
	}

/^(\w+)[[:blank:]]+(\w+)[[:blank:]]*=/ {
		# The `split' handles cases in which there is no space between
		# the name and `=', meaning that the `=' (and whatever follows,
		# up to the next space) becomes part of $2.
		split($2, def_name, "=")
		if (match(def_name[1],MATCHING)) {
			in_def = 1
			if (discarded && found_any_defs) {
				print ""
				discarded = 0
			}
			one_liner = 0
			if (match($0,"\}[[:blank:]]*(//.*)?$")) {
				one_liner = 1
			}
			found_any_defs = 1
			if ((header_lines > 0) && HEADERS) {
				for (i = 0; i < header_lines; ++i)
					print header[i]
			}
		}
		header_lines = 0
		delete header
		header_trailing_blanks = 0
	}

/^\/\// {
		if (!in_def) {
			if (header_trailing_blanks) {
				header_lines = 0
				delete header
			}
			header[header_lines] = $0
			header_lines++
			header_trailing_blanks = 0
		}
	}

/^[[:blank:]]*$/ {
		if (!in_def) {
			if ((header_lines > 0) && !header_trailing_blanks) {
				header[header_lines] = $0
				header_lines++
				header_trailing_blanks = 1
			}
		}
	}

# The following action applies to all lines.
	{
		if (in_def) {
			print
			if (one_liner)
				in_def = 0
				discarded = 0
		} else {
			discarded = 1
		}
	}

/^}/	{
		if (in_def)
			discarded = 0
		else
			discarded = 1
		in_def = 0
	}

END	{
		if (in_def)
			print "Warning: unterminated definition at end of file." > "/dev/stderr"
	}

###############################################################################

## End of file.

