1#!/bin/sh
2#
3# nana-sfg.in - the nana shortform generator (aka nana science fiction
4#    generator).
5#
6#    A shortform is the program minus the implementation
7#    (code, variables) but includes REQUIRE and ENSURE calls which
8#    are the function pre/postconditions. See below for the translation
9#    rules.
10#
11# Usage:
12#
13#   % nana-sfg <a.c >sf.c
14#   % nana-sfg a.c >sf.c
15#   % nana-sfg *.[ch] >system.sf
16#
17# Options:
18#
19#   Like all good programs this one has no options, obviously different
20#   projects will have different requirements. It is suggested that each
21#   of your projects (or groups) keep a version of this file and modify
22#   it for local taste. For example some people might want to preserve
23#   comments starting in the right hand column.
24#
25# Copyright (c) 1998 Phil Maker <pjm@gnu.org>
26# All rights reserved.
27#
28# Redistribution and use in source and binary forms, with or without
29# modification, are permitted provided that the following conditions
30# are met:
31# 1. Redistributions of source code must retain the above copyright
32#    notice, this list of conditions and the following disclaimer.
33# 2. Redistributions in binary form must reproduce the above copyright
34#    notice, this list of conditions and the following disclaimer in the
35#    documentation and/or other materials provided with the distribution.
36#
37# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
38# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
41# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47# SUCH DAMAGE.
48#
49# $Id: nana-sfg.in,v 1.1.1.1 1999/09/12 03:26:49 pjm Exp $
50#
51
52gawk '
53
54# keep track of previous line for function headers
55{ prev = cur; cur = $0; }
56
57# ignore C/C++ labels even though they occur at column 1
58/[a-zA-Z]*:/     { next }
59
60# various C preprocessor directives
61/^#[ \t]*include/ { emit(); }
62/^#[ \t]*define/  { emit(); }
63/^#[ \t]*/        { next }
64
65# various balanced lists of the form X { ... { ... } ...}
66/^typedef[ \t]+struct/ ||
67/^typedef[ \t]+union/  ||
68/^typedef[ \t]+enum/   ||
69/^class/               ||
70/^struct/ ||
71/^union/ ||
72/^enum/  ||
73/^class/ { balanced("{","}"); }
74
75# simple typedef such "typedef int word;" (note: complicated ones are handled
76#   in the previous rule)
77/^typedef/       { till(";"); }
78
79# any function definition like object starting in column 1
80/^[a-zA-Z].*\(/  {
81		   printprevif("^[a-zA-Z]"); # return type in some styles
82		   till("\{"); #
83                 }
84
85# closing } in column one (end of function/class/typedef/enum/
86/^\}[ \t]*$/             { emit(); }
87
88# REQUIRE/ENSURE clauses
89/^[ \t]*REQUIRE/  ||
90/^[ \t]*ENSURE/   { till("\)[ \t]*;"); }
91
92# PRE/POST clauses
93/^[ \t]*PRE/  ||
94/^[ \t]*POST/   { till("\)[ \t]*;"); }
95
96# ignore blank lines
97/^[ \t]*$/       { next }
98
99# finally all text to be removed is printed out with a
100# leading "@@@" for the next pass to compress into "...".
101#
102#  Alternatively you could use a few state variables in here to
103#  get this to work but the only good state variable is a dead one.
104#
105{ print "@@@" $0 }
106
107#### end of rules ####
108
109# mustgetline - getline with a fatal error on EOF
110function mustgetline() {
111    if(getline <= 0) {
112	print "Fatal error: unexpected eof"
113	exit(1)
114    }
115}
116
117# emit - just print this line and start looking at the next one
118function emit() {
119    print
120    next
121}
122
123# till - print the current line and advance until we match regexp re
124function till(re) {
125    print
126    while(!match($0,re) && (getline > 0))
127	print $0
128    next
129}
130
131# printprevif - print the previous line iff current line matches re
132function printprevif(re) {
133    if(match(prev,re))
134        print prev
135}
136
137# balanced - print a balanced list of lines, in particular:
138#   0. print lines until we get the opening
139#   1. until we reach the end of balanced list print them
140#
141#   Note: multiple open/closes on one line are NOT detected
142#
143function balanced(opening,closing,  cnt) {
144    if(match($0,opening)) {
145        cnt = 1;
146        while(cnt > 0) {
147	    print
148	    mustgetline()
149	    if(match($0,opening)) {
150		cnt++;
151	    }
152	    if(match($0,closing)) {
153	        cnt--;
154	    }
155        }
156	print
157	mustgetline()
158    } else {
159        print
160	mustgetline()
161	if(match($0,opening)) {
162	    balanced(opening,closing)
163	    return
164	} else {
165	    puts "expected " $opening ": not found"
166        }
167    }
168}
169
170
171' $* |
172gawk '
173
174# print adjacent deleted text as ... starting at the column of the
175# first non-white space character in the first line.
176
177/^@@@/ {
178    sub(/^@@@/,"",$0)
179    print indent($0) "..."
180    while(getline > 0) {
181	if(!match($0,/^@@@/)) {
182	    print
183	    break
184	}
185    }
186    next
187}
188
189{ print }
190
191# indent - returns the indentation (first bit of white space)
192function indent(s, i) {
193    i = s
194    gsub(/[^ \t].*/,"", i)
195    return i
196}
197
198'
199
200
201
202