/* vector.c */

#include "kernel.h"
#include "swis.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

typedef struct vector
{
   struct vector *link;
   int            ws;
   int            code;

} vector;

static char *VecName[] =
{
   "UserV", "ErrorV", "IrqV", "WrchV", "RdchV", "CLIV", "ByteV", "WordV",
   "FileV", "ArgsV", "BGetV", "BPutV", "GBPBV", "FindV", "ReadLineV",
   "FSControlV", "EventV", "&11", "&12", "&13", "InsV", "RemV", "CnpV",
   "UKVDU23V", "UKSWIV", "UKPLOTV", "MouseV", "VDUXV", "TickerV", "UpCallV",
   "ChangeEnvironmentV", "SpriteV", "DrawV", "EconetV", "ColourV",
   "PaletteV", "SerialV", "FontV", "PointerV", "TimeShareV",
   "LowPriorityEventV", "FastTickerV", "GraphicsV", "SpareVector5",
   "SpareVector4", "SpareVector3", "SpareVector2", "SpareVector1"
};

static vector **VecTable;

static const char *Where(int code)
{
   _kernel_swi_regs regs;
   _kernel_oserror *err;
   int *moduleBase;
   int moduleStart, moduleEnd;

   regs.r[1] = 0;
   regs.r[2] = 0;

   for (;;)
   {
      regs.r[0] = 12;
      if (err = _kernel_swi(OS_Module, &regs, &regs), err)
         break;

      moduleBase  = (int *) regs.r[3];
      moduleStart = (int) moduleBase;
      moduleEnd   = moduleStart + moduleBase[-1];

      if (code >= moduleStart && code < moduleEnd)
         return (const char *) (moduleStart + moduleBase[4]);
}

   return "";
}

static void ShowVectorChain(int v)
{
   vector *vp = VecTable[v];

   if (v < 0 || v >= sizeof(VecName) / sizeof(VecName[0]))
   {
      printf("Vector number out of range\n");
      return;
   }

   printf("Vector %s (&%02x)\n", VecName[v], v);

   for ( ; vp; vp = vp->link)
      printf("  %08x %08x %s\n", vp->code, vp->ws, Where(vp->code));
}

static int StrCmp(const char *a, const char *b)
{
   while (*a && tolower(*a) == tolower(*b))
      a++, b++;

   return tolower(*a) - tolower(*b);
}

static int ParseVecName(const char *vecName)
{
   int vecNum = 0;

   while (isspace(*vecName))
      vecName++;

   if (isdigit(*vecName))
      return atoi(vecName);
   else if (*vecName == '&')
   {
      vecNum = 0;
      vecName++;
      while (isxdigit(*vecName))
      {
         vecNum = vecNum * 16 + (isdigit(*vecName) ? (*vecName - '0')
                                                   : (tolower(*vecName) - 'a' + 10));
         vecName++;
      }

      return vecNum;
   }
   else
   {
      for (vecNum = 0; vecNum < sizeof(VecName) / sizeof(VecName[0]); vecNum++)
         if (StrCmp(vecName, VecName[vecNum]) == 0)
            return vecNum;
   }

   return -1;
}

int main(int argc, char *argv[])
{
   int i;

   VecTable = (vector **) 0x7d8;

   if (argc > 1)
   {
      for (i = 1; i < argc; i++)
         ShowVectorChain(ParseVecName(argv[i]));
   }
   else
   {
      for (i = 0; i < sizeof(VecName) / sizeof(VecName[0]); i++)
         ShowVectorChain(i);
   }

   return 0;
}
