#!/usr/bin/env bash

if echo "hello" | grep --text "hello" &>/dev/null
then
   GREP="grep --text"
else
   GREP="grep"
fi

which tac &> /dev/null || tac() {
   local a=()
   local i=0
   while read line
   do
      a[i]="$line"
      i=$[i+1]
   done < "$1"
   for ((j = i - 1; j >= 0; j--))
   do
      echo "${a[$j]}"
   done
}

process() {
   grep -q "^$1$" order.txt &> /dev/null && return
   for need in `cat "$1" | $GREP '//#needs ' | sed 's,//#needs ,,'`
   do process $need.c "$2"
   done
   "$2" "$1"
   processed=("${processed[@]}" "$1")
   echo "$1" >> order.txt
}

do_all() {
if [ -e order.txt ]
then
   for i in `cat order.txt`
   do "$1" "$i"
   done
else
   processed=( )
   for i in *.c
   do process "$i" "$1"
   done
fi
}

if [ "$1" = "Prototypes.h" ]
then
   
   new="Prototypes.h.new"
   old="Prototypes.h"

   ################################
   echo -n "Function prototypes..."
   ################################
   
   echo "#ifndef Prototypes_HEADER" > "$new"
   echo "#define Prototypes_HEADER" >> "$new"
   echo >> "$new"
   echo '#define _GNU_SOURCE' >> "$new"
   echo '#include <stdbool.h>' >> "$new"
   echo '#include <stdio.h>' >> "$new"
   echo '#include <string.h>' >> "$new"
   echo '#include <unistd.h>' >> "$new"
   echo >> "$new"
   echo '#include "Structures.h"' >> "$new"
   echo >> "$new"
   
   includes() {
      cat "$1" | $GREP "^#include"
   }

   defines() {
      cat "$1" | $GREP "^#define Display_.*"
   }
   
   proto() {
      cat "$1" | grep -v "#include" | cpp 2> /dev/null |\
      $GREP -i -v "^static" | grep '^[^ ].*) {$' |\
      sed 's,) {$,);,;s,inline,,' >> "$new"
   }
   
   {
   if [ `ls *.c | wc -l` != `cat order.txt | wc -l` ]
   then rm -f order.txt
   fi
   } &> /dev/null
   
   do_all includes | sort -u | tac >> "$new"
   do_all proto
   echo "#if HAVE_CURSES" >> "$new"
   do_all defines >> "$new"
   echo "#endif" >> "$new"
   
   echo >> "$new"
   echo '#include <stdlib.h>' >> "$new"
   echo '#include "debug.h"' >> "$new"
   echo '#include <assert.h>' >> "$new"
   echo >> "$new"
   echo "#endif" >> "$new"

else
   
   new="Structures.h.new"
   old="Structures.h"

   #######################
   echo -n "Structures..."
   #######################
   
   echo "#ifndef Structures_HEADER" > "$new"
   echo "#define Structures_HEADER" >> "$new"
   echo "#include \"config.h\"" >> "$new"
   echo >> "$new"
   
   cat *.c | gawk '
      BEGIN {
         reading=0
      }
      /\/*{/ {
         reading=1
      }
      /}*\// {
         reading=0
      }
      /^struct .* {$/ {
         if (reading)
            print "typedef struct " $2 " " substr($2, 1, length($2)-1) ";"
      }
   ' >> "$new"
   
   struct() {
   cat "$1" | gawk '
      BEGIN {
         writing=0
      }
      /\/\*{/ {
         writing=1
      }
      /}\*\// {
         writing=0
      }
      {
         if (writing==1)
            writing=2
         else if (writing == 2)
            print
      }
   ' >> "$new"
   }
   
   do_all struct
   
   echo "#endif" >> "$new"
   
fi

####
echo
####

if [ -e "$old" ]
then
   if ! diff -q "$new" "$old"
   then mv -f "$new" "$old"
   fi
else
   mv -f "$new" "$old"
fi
