/* symtab.c - simple linear search symbol table. Symbols have a print name and a value.
 *  Copyright (C) 2022 by Jed Marti
 *   This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see https://www.gnu.org/licenses/.
 */

#include <C8051F380.h>
#include <stdint.h>

#include "lfxmit.h"
#include "config.h"
#include "serial.h"
#include "strings.h"
#include "storage.h"


// The symbol table.
__xdata SymtabEntry    S[SSIZE];             // Main storage.
__xdata uint8_t        SINDEX;               // First available free space.

extern __xdata uint8_t D[];                  // Dynamic data space.
extern uint16_t        DREG;                 // For accessing it - the address.

extern __bit           errorThrown;          // Indicates an error has occured.


uint8_t lookupPName(char *q)
// Search the table for an identifier and return its index if found or 0xFF if not found in
// the table.
{
  uint8_t i;

  for (i = 0; i < SINDEX; ++i)
    if (strEq(&D[S[i].pname + 3], q)) return i;
  return 0xFF;
}



uint8_t createSymbol(void)
//    A string in STR, copy to D space, put in symbol table. Error if symbol table full.  The
// symbol print name is in lexical STR. Crank up the index. It's assumed that the symbol is not
// already in the table.
{
  // Check for overflow.
  if (SINDEX >= SSIZE)
  {
    putstring("Symtab overflow\n");
    errorThrown = 1;
    return 0xFF;
  }

  // Copy the string in STR there, return the index.
  S[SINDEX].pname = newStringSTR(),
    S[SINDEX].addr = 0xFFFF;
  return SINDEX++;
}
 
 


uint16_t newSymbol(uint8_t indx)
// Creates a new symbol and return the D spoace offset. This allows us to pass the symbol around
// as a data type.
{
  DREG = dmalloc(1);
  setTag(DESC_SYMBOL);
  DREG += 3;
  setByte(indx);
  return DREG - 3;
}



void dumpSymtab(void)
{
  uint8_t i;
  for (i = 0; i < SINDEX; ++i)
  {
    putstring(&D[S[i].pname + 3]);
    putstring("  ");
    if (S[i].addr == 0xFFFF) putstring("*");
    else puthexbyte(D[S[i].addr]);
    terpri();
  }
}


void initSymtab(void)
//     Clear the symbol table by resetting the index.
{
  SINDEX = 0;
}



// EOF
