Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!devnull!kelley@mpd.tandem.com From: kelley@mpd.tandem.com (Michael Kelley) Newsgroups: comp.lang.c++ Subject: Re: name mangler Message-ID: <165@devnull.mpd.tandem.com> Date: 3 Apr 91 21:06:46 GMT References: <9104021605.AA09745@puma.cad.mcc.com> <9104020404.AA19492@cygnus.com> Sender: news@devnull.mpd.tandem.com Lines: 188 I did get a number of people sending in about my name mangler, so here it is. I haven't had time to move it to any other machine than a sparc, so you may have to do some hacking to plug in the right tools (nawk, nm, etc.) Same goes for it's use with g++: I just don't know. But it's a start, anyway. #!/bin/sh # $Id: mangle,v 1.1 91/04/03 12:04:34 kelley Exp $ # # usage: mangle [-c] # generates a map between demangled and mangled names to stdout, with # a mangled name on the line following its demangled counterpart. # It reads from stdin. With the '-c' argument, you'll get a C++ structure. # # written by Mike Kelley, email kelley@mpd.tandem.com # ## Copyright 1991, by Tandem Computers, Incorporated, Austin, Texas. ## ## All Rights Reserved ## ## Permission to use, copy, modify, and distribute this software and its ## documentation for any purpose and without fee is hereby granted, ## provided that the above copyright notice appear in all copies and that ## both that copyright notice and this permission notice appear in ## supporting documentation, and that the names of Tandem not be ## used in advertising or publicity pertaining to distribution of the ## software without specific, written prior permission. ## ## TANDEM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ## ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ## DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ## ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ## WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ## ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ## SOFTWARE. ## # # known limitations/bugs: # - need to investigate the way enums are handled for C++ variants; with # cfront, they are mangled just as are class names # - if your filter doesn't work, then neither will this # - doesn't work for constructors # - you can't default "unsigned" to "unsigned int" # - demangled names given as input get changed to their fundamental # counterparts (via typedef) as output--you'll have to do your own # substitution # - it's *very* slow # - little or no error checking # TMPDIR=${TMPDIR-/tmp} MANGDIR=$TMPDIR/mangle$$ usage="usage: `basename $0` [-c]" here=`pwd` CC=/usr/CC/sun4/CC CPP=/lib/cpp filter="c++filt -s" # use "nm -B" on SYSV variants NM=nm if test $# -eq 1; then if test "$1" = "-c"; then format=1 else echo $usage exit 1 fi elif test $# -ne 0; then echo $usage exit 1 fi mkdir $MANGDIR trap "cd $here; rm -rf $MANGDIR; exit 1" 1 2 3 15 cd $MANGDIR touch input echo '#include "classes.h"' > nonMember.c $CPP | sed -e "s/^[ ]*//" -e "s/;//g" | while read prototype; do # take out line control information (echo $prototype | egrep '#.*' > /dev/null) && continue; # look for (only one line) typedefs echo $prototype | egrep 'typedef .*' > /dev/null # no '-s' on SYSV if test $? -eq 0; then echo $prototype >> input echo $prototype | sed -e "s/unsigned //" \ -e "s/typedef[ ]*[_a-zA-Z]*[( \*]*\([^() \*]*\).*/TYPEDEF,\1/" \ >> input else echo $prototype | egrep '[_a-zA-Z]+::.*' > /dev/null; if test $? -ne 0; then # not a class member call="`echo $prototype | sed 's/:://'`"; echo "static void $call { }" >> nonMember.c; else class=`expr "$prototype" : '\(.*\)::.*'`; call=`expr "$prototype" : '.*::\(.*\)'`; file=${class}.c; if test ! -f $file; then echo '#include "classes.h"' > $file; echo "class $class {" >> $file; fi echo "virtual void $call { }" >> $file; fi echo $call | tr '()' ',,' | \ sed -e "s/unsigned //" -e "s/const //" -e "s/[ \*&]//g" >> input; fi done nawk -F, ' \ BEGIN { \ typedef[1] = "char"; \ typedef[2] = "short"; \ typedef[3] = "int"; \ typedef[4] = "long"; \ typedef[5] = "float"; \ typedef[6] = "double"; \ ntypes = 6; \ } \ { \ if (substr($1, 1, 8) == "typedef ") printf("%s;\n", $0); \ else if ($1 == "TYPEDEF") typedef[++ntypes] = $2; \ else { \ for (i = 2; i < NF; i++) { \ # cant get expr in array to work... # if (!($i in typedef)) printf("class %s;\n", $i); \ if (length($i) == 0) break; \ for (j = 1; j <= ntypes; j++) if (typedef[j] == $i) break; \ if (j > ntypes) printf("class %s;\n", $i); \ # could add to typedef array, but better to let it go... } \ } \ } ' input > classes.h if [ "$format" ]; then cat << END_CAT static struct MangleNode { const char *prototype; const char *mangled; void (*entry)(...); } mapping[] = { END_CAT fi for f in *.c; do if test $f != "nonMember.c"; then echo "};" >> $f; elif test "`wc -l $f`" -eq 1; then break; fi object="`echo $f | cut -f1 -d.`.o" $CC -c -g $f 2> /dev/null (test $? -ne 0) && continue # sed portion to take out '_' Sun prepends before function name $NM $object | $filter | sed "s/\([: ]\)_/\1/g" > input if [ "$format" ]; then nawk '$2 == "t" { \ printf("\"%s", $3); \ for (i = 4; i < NF; i++) printf(" %s", $i); \ printf("\", \"%s\", 0,\n", $NF); \ } ' input; else nawk '$2 == "t" { \ for (i = 3; i <= NF; i++) \ if (i == NF) printf("\n%s\n", $i); \ else printf("%s ", $i); \ } ' input; fi done if [ "$format" ]; then echo "};" fi cd $here rm -rf $MANGDIR # # here begins sample input: just cut here, whack off the beginning '##', # and you're on your way... ##typedef unsigned int (*PfHash)(const char*); ##typedef char Boolean; ##X::f(int, const Y&); ##X::f(); ##Y::f(int, const Y&); ##zoo::ack(float, unsigned long, double*, Z*); ##job(int, foobar&); ##::go(Boolean); ##HashTable::setup(PfHash, unsigned int); Mike Kelley Tandem Computers, Austin, TX kelley@mpd.tandem.com (512) 244-8830 / Fax (512) 244-8247