#include <sys/types.h>
#include <sys/syscall.h>

#include <stdio.h>

struct syscall {
  char *name;
  int   vec;
} syscalls[] = {
#define SYSTEM_CALL(func,vec) { #func, vec},
#include <sys/syscall.def>
#undef SYSTEM_CALL
};

int nsyscall = sizeof(syscalls) / sizeof (syscalls[0]);

#define BASEREL 			\
".globl _%s;				\
_%s: movel a4@(_ixemulbase:W), a0;	\
jmp a0@(%d:w)\n"

#define BASEREL_IX_GETA4		\
".globl _%s;				\
_%s: movel _ixemulbase, a0;		\
jmp a0@(%d:w)\n"

#define NOBASEREL			\
".globl _%s;				\
_%s: movel _ixemulbase, a0;		\
jmp a0@(%d:w)\n"

#define PROFILING			\
".globl _%s;				\
_%s:					\
.data;					\
PROF%s:;				\
.long 0;				\
.text;					\
link a5,#0;				\
lea PROF%s,a0;				\
jsr mcount;				\
unlk a5;				\
movel _ixemulbase, a0;			\
jmp a0@(%d:w)\n"

void usage(void)
{
  fprintf(stderr, "Usage: gen_glue baserel | no-baserel | profiling\n");
  exit(1);
}

int main(int argc, char **argv)
{
  FILE *fp;
  struct syscall *sc;
  int i, v, baserel = 0, profiling = 0;

  if (argc != 2)
    usage();
  if (!strcmp(argv[1], "baserel"))
    {
      baserel = 1; profiling = 0;
    }
  else if (!strcmp(argv[1], "no-baserel"))
    {
      baserel = 0; profiling = 0;
    }
  else if (!strcmp(argv[1], "profiling"))
    {
      baserel = 0; profiling = 1;
    }
  else usage();
  
  for (i = 0, sc = syscalls; i < nsyscall; i++, sc++)
    {
      char name[strlen (sc->name) + 3];

      if (!memcmp(sc->name, "__obsolete", 10))
        continue;
      if (!memcmp(sc->name, "__must_recompile", 16))
        continue;
      if (!memcmp(sc->name, "__stk", 5))
        continue;
      v = -(sc->vec + 4)*6;
      sprintf (name, "%s.s", sc->name);

      fp = fopen (name, "w");
      
      if (!fp)
        {
          perror (sc->name);
          exit (20);
        }

      if (baserel)
        if (sc->vec == SYS_ix_geta4)
          fprintf (fp, BASEREL_IX_GETA4, sc->name, sc->name, v);
	else
          fprintf (fp, BASEREL, sc->name, sc->name, v);
      else if (profiling)
        fprintf (fp, PROFILING, sc->name, sc->name, sc->name, sc->name, v);
      else
        fprintf (fp, NOBASEREL, sc->name, sc->name, v);
      fclose (fp);
    }
  return (0);
}
