#!/bin/sh

# Swarm library. Copyright (C) 1996-1998 Santa Fe Institute.
# This library is distributed without any warranty; without even the
# implied warranty of merchantability or fitness for a particular purpose.
# See file LICENSE for details and terms of copying.

# make-h2x -- generate .xm, .xt, and .xc files from module source directory

if [ $# -ne 1 ]; then
  echo 'Usage: make-h2x <module-name>.xm'
  exit 1
fi

m=`basename $1 .xm`
if [ ! -f $m.h ]; then
  echo "make-h2x: header file $m.h does not exist in directory"
  exit 1
fi

echo making $m.xm $m.xt $m.xc

# generate #import statements in generated file

echo \
'#import <'$m'.h>
#import <objc/objc-api.h>
' >$m.xm

# extract all declared symbols into temporary file

$CC -E "$CFLAGS" $m.h | \
sed -n \
  -e 's@//.*$@@' \
  -e 's/	//g' \
  -e 's/^[ ]*extern //g' \
  -e 's/[ ][ ]*//g' -e 's///g' \
  -e '/id<Symbol>/,/^$/p' \
  -e '/id<Warning>/,/^$/p' \
  -e '/id<Error>/,/^$/p' \
  -e '/id<Event>/,/^$/p' >$m.xm+

# define symbol identifiers in generated file

sed -e 's/<.*>/ /' -e '/^$/d' -e 's/\([,;]\)/=0\1/g' <$m.xm+ >>$m.xm

# generate array of defined symbols

echo '
void *_'$m'_symbols[]={' >>$m.xm
sed <$m.xm+ >>$m.xm \
  -e 's/id<.*>//g' -e '/^$/d' -e 's/;/,/g' \
  -e 's/\([A-Za-z0-9_][A-Za-z0-9_]*\)/\&\1/g'
echo 0, >>$m.xm
sed <$m.xm+ >>$m.xm \
  -e '/^$/d' -e 's/id[ ]*<\(.*\)>/0\1,/g' -e 's/;/,/g' \
  -e 's/\([A-Za-z0-9_][A-Za-z0-9_]*\)/"\1"/g' -e 's/<"/"\\r/g'
echo '0};
' >>$m.xm

# extract all declared types into temporary file

sed <$m.h >$m.xm+ \
  -e 's/	//g' \
  -e '/@deftype/!d' \
  -e 's/[ ]*@deftype[ *]\([A-Za-z0-9_][A-Za-z0-9_]*\).*/\1/'

# generate module.xt file (exported by make file as <module/types.h>)


echo 'extern void *_'$m'_[];
' >$m.xt
sed 's/\(.*\)/extern id \1;/' <$m.xm+ >>$m.xt

# define type identifiers in generated file

sed 's/\(.*\)/id \1=0;/' <$m.xm+ >>$m.xm
echo '
#ifdef DEFINE_CLASSES
#import <'$m'/classes.h>
#endif' >>$m.xt

# generate array of defined types

echo '
void *_'$m'_types[]={' >>$m.xm
sed 's/\(.*\)/\&\1,/' <$m.xm+ >>$m.xm
echo 0, >>$m.xm
sed 's/\(.*\)/@protocol(\1),/' <$m.xm+ >>$m.xm
echo '0};
' >>$m.xm

# extract all implemented classes into temporary file

for object in $OBJECTS; do
  source=`basename $object .o`.m
  if [ -f $source ]; then sources="$sources $source"; fi
done
if [ "$sources" = "" ]; then
  echo "no files with .m suffix found to match any .o file in $(OBJECTS)"
  exit 1
fi
cat $sources | sed >$m.xm+ \
  -e 's/	//g' \
  -e '/[ ]*@implementation/!d' \
  -e 's/[ ]*@implementation[ ]*\([A-Za-z0-9_][A-Za-z0-9_]*\).*/\1/'

# generate module.xc file (exported by make file as <module/classes.h>)

sed 's/\(.*\)/extern id id_\1;/' <$m.xm+ >>$m.xc

# define class identifiers in generated file

sed 's/\(.*\)/id id_\1=0;/' <$m.xm+ >>$m.xm

# generate array of defined classes

echo '
void *_'$m'_classes[]={' >>$m.xm
sed 's/\(.*\)/\&id_\1,/' <$m.xm+ >>$m.xm
echo '0};
' >>$m.xm

# generate declarations for classes referenced below

sed 's/\(.*\)/@class \1;/' <$m.xm+ >>$m.xm

# generate initial contents of module definition object

echo '
extern void _'$m'_implement(void);
extern void _'$m'_initialize(void);

void *_'$m'_[]=
{
0,
"'$m'",
(void *)_'$m'_implement,
(void *)_'$m'_initialize,
_'$m'_types,
_'$m'_symbols,
_'$m'_classes,
};
' >>$m.xm

# generate class which initializes module

echo '
@interface Module_super_
+ self;
@end
@interface Module__'$m'_ : Module_super_
@end
@implementation Module__'$m'_
+ initialize
{
// initialize class id constants and link all classes into module' >>$m.xm
sed 's/\(.*\)/id_\1=[\1 self];/' <$m.xm+ >>$m.xm
echo '
// return module object
return (id)_'$m'_;
}
@end' >>$m.xm

# remove temporary file containing class names

rm $m.xm+
