1#!/bin/sh
2
3# Copyright (c) 2013, Derek Buitenhuis
4#
5# Permission to use, copy, modify, and/or distribute this software for any
6# purpose with or without fee is hereby granted, provided that the above
7# copyright notice and this permission notice appear in all copies.
8#
9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17# mktemp isn't POSIX, so supply an implementation
18mktemp() {
19    echo "${2%%XXX*}.${HOSTNAME}.${UID}.$$"
20}
21
22if [ $# -lt 2 ]; then
23    echo "Usage: makedef <version_script> <objects>" >&2
24    exit 0
25fi
26
27vscript=$1
28shift
29
30if [ ! -f "$vscript" ]; then
31    echo "Version script does not exist" >&2
32    exit 1
33fi
34
35for object in "$@"; do
36    if [ ! -f "$object" ]; then
37        echo "Object does not exist: ${object}" >&2
38        exit 1
39    fi
40done
41
42# Create a lib temporarily to dump symbols from.
43# It's just much easier to do it this way
44libname=$(mktemp -u "library").lib
45
46trap 'rm -f -- $libname' EXIT
47
48lib -out:${libname} $@ >/dev/null
49if [ $? != 0 ]; then
50    echo "Could not create temporary library." >&2
51    exit 1
52fi
53
54IFS='
55'
56
57# Determine if we're building for x86 or x86_64 and
58# set the symbol prefix accordingly.
59prefix=""
60arch=$(dumpbin -headers ${libname} |
61       tr '\t' ' ' |
62       grep '^ \+.\+machine \+(.\+)' |
63       head -1 |
64       sed -e 's/^ \{1,\}.\{1,\} \{1,\}machine \{1,\}(\(...\)).*/\1/')
65
66if [ "${arch}" = "x86" ]; then
67    prefix="_"
68else
69    if [ "${arch}" != "ARM" ] && [ "${arch}" != "x64" ]; then
70        echo "Unknown machine type." >&2
71        exit 1
72    fi
73fi
74
75started=0
76regex="none"
77
78for line in $(cat ${vscript} | tr '\t' ' '); do
79    # We only care about global symbols
80    echo "${line}" | grep -q '^ \+global:'
81    if [ $? = 0 ]; then
82        started=1
83        line=$(echo "${line}" | sed -e 's/^ \{1,\}global: *//')
84    else
85        echo "${line}" | grep -q '^ \+local:'
86        if [ $? = 0 ]; then
87            started=0
88        fi
89    fi
90
91    if [ ${started} = 0 ]; then
92        continue
93    fi
94
95    # Handle multiple symbols on one line
96    IFS=';'
97
98    # Work around stupid expansion to filenames
99    line=$(echo "${line}" | sed -e 's/\*/.\\+/g')
100    for exp in ${line}; do
101        # Remove leading and trailing whitespace
102        exp=$(echo "${exp}" | sed -e 's/^ *//' -e 's/ *$//')
103
104        if [ "${regex}" = "none" ]; then
105            regex="${exp}"
106        else
107            regex="${regex};${exp}"
108        fi
109    done
110
111    IFS='
112'
113done
114
115dump=$(dumpbin -linkermember:1 ${libname})
116
117rm ${libname}
118
119IFS=';'
120list=""
121for exp in ${regex}; do
122    list="${list}"'
123'$(echo "${dump}" |
124          sed -e '/public symbols/,$!d' -e '/^ \{1,\}Summary/,$d' -e "s/ \{1,\}${prefix}/ /" -e 's/ \{1,\}/ /g' |
125          tail -n +2 |
126          cut -d' ' -f3 |
127          grep "^${exp}" |
128          sed -e 's/^/    /')
129done
130
131echo "EXPORTS"
132echo "${list}" | sort | uniq | tail -n +2
133