1#! /bin/sh
2#
3# Copyright (C) 2009 Free Software Foundation, Inc.
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17#
18
19# This script determines the declared global symbols in a C header file.
20# Assumptions:
21# - The header files are in C, with only C89 comments.
22# - No use of macros with parameters.
23# - All global declarations are marked with 'extern'.
24# - All declarations end in ';' on the same line.
25# - Not more than one symbol is declared in a declaration.
26
27# func_usage
28# outputs to stdout the --help usage message.
29func_usage ()
30{
31  echo "\
32Usage: declared.sh [OPTION]... < SOURCE.h
33
34Extracts the declared global symbols of a C header file.
35
36Options:
37      --help           print this help and exit
38      --version        print version information and exit
39
40Report bugs to <bruno@clisp.org>."
41}
42
43# func_version
44# outputs to stdout the --version message.
45func_version ()
46{
47  echo "declared.sh (GNU libunistring)"
48  echo "Copyright (C) 2006, 2009 Free Software Foundation, Inc.
49License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
50This is free software: you are free to change and redistribute it.
51There is NO WARRANTY, to the extent permitted by law."
52  echo "Written by" "Bruno Haible"
53}
54
55# func_fatal_error message
56# outputs to stderr a fatal error message, and terminates the program.
57func_fatal_error ()
58{
59  echo "declared.sh: *** $1" 1>&2
60  echo "declared.sh: *** Stop." 1>&2
61  exit 1
62}
63
64# Command-line option processing.
65while test $# -gt 0; do
66  case "$1" in
67    --help | --hel | --he | --h )
68      func_usage
69      exit 0 ;;
70   --version | --versio | --versi | --vers | --ver | --ve | --v )
71      func_version
72      exit 0 ;;
73    -- )      # Stop option prcessing
74      shift; break ;;
75    -* )
76      func_fatal_error "unrecognized option: $option"
77      ;;
78    * )
79      break ;;
80  esac
81done
82
83if test $# -gt 0; then
84  func_fatal_error "too many arguments"
85fi
86
87# A sed expression that removes ANSI C and ISO C99 comments.
88sed_remove_comments="
89/[/][/*]/{
90  ta
91  :a
92  s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)//.*,\\1,
93  te
94  s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)/[*]\\([^*]\\|[*][^/*]\\)*[*][*]*/,\\1 ,
95  ta
96  /^\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*[/][*]/{
97    s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)/[*].*,\\1 ,
98    tu
99    :u
100    n
101    s,^\\([^*]\\|[*][^/*]\\)*[*][*]*/,,
102    tv
103    s,^.*\$,,
104    bu
105    :v
106  }
107  :e
108}"
109
110# Check that 'sed' supports the kind of regular expressions used in
111# sed_remove_comments. The use of \| meaning alternation of basic regular
112# expressions is a GNU extension.
113sed_test='s,^\(\(a\|X\)*\)//.*,\1,'
114sed_result=`echo 'aaa//bcd' | sed -e "$sed_test"`
115test "$sed_result" = 'aaa' \
116  || func_fatal_error "The 'sed' program is not GNU sed. Try installing GNU sed."
117
118# A sed expression that joins 'extern' declarations that are broken over
119# several lines.
120sed_join_multiline_externs='
121/^extern [^;]*$/{
122  :a
123  N
124  s/\n/ /g
125  /^extern [^;]*$/{
126    ba
127  }
128}'
129
130# A sed expression that extracts the identifier of each 'extern' declaration.
131sed_extract_extern_declared='s/^extern [^()]* \([A-Za-z_][A-Za-z0-9_]*\) *[;(].*$/\1/p'
132
133sed -e "$sed_remove_comments" \
134  | sed -e "$sed_join_multiline_externs" \
135  | sed -n -e "$sed_extract_extern_declared"
136