Revision 07d422a97efd13e2c9cc89135ae2b9c9c982136f authored by Mike Stewart on 07 August 2019, 06:38:15 UTC, committed by Mike Stewart on 07 August 2019, 06:38:15 UTC
1 parent 047a9d2
Raw File
SymbolPass.c
/*
 * Copyright 2003,2016 Ronald S. Burkey <info@sandroid.org>
 *
 * This file is part of yaAGC.
 *
 * yaAGC 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 2 of the License, or
 * (at your option) any later version.
 *
 * yaAGC 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 yaAGC; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Filename:	SymbolPass.c
 * Purpose:	A pass intended to do nothing but to identify symbols
 * 		defined in the program.  (Basically, anything beginning
 *		in column 1, but not beginning with # or $.
 * Mode:	04/17/03 RSB.	Began.
 *		11/11/16 RSB.	Added provision for .yul.
 */

#include "yaYUL.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

//-------------------------------------------------------------------------
// Some global data.

// We allow a certain number of levels of include files.  To handle this,
// we need a stack of input files.
#define MAX_STACKED_INCLUDES 5
static int NumStackedIncludes = 0;
typedef struct {
  FILE *InputFile;
  Line_t InputFilename;
  int CurrentLineInFile;
  int yulType;
} StackedInclude_t;
static StackedInclude_t StackedIncludes[MAX_STACKED_INCLUDES];

// Some dummy strings for parsing an input line.
static Line_t Fields[6];
static int NumFields = 0;

//-------------------------------------------------------------------------

void 
SymbolPass (const char *InputFilename)
{
  Line_t CurrentFilename;
  Line_t s;
  char *Comment, *Label, *FalseLabel, *Operator, *Operand, *Mod1, *Mod2;
  FILE *InputFile;
  int CurrentLineAll = 0, CurrentLineInFile = 0, yulType;
  int i;				// dummies.
  char *ss;				// dummies.
  
  // Open the input file.
  strcpy (CurrentFilename, InputFilename);
  InputFile = fopen (CurrentFilename, "r");
  if (InputFile == NULL)
    goto Done;
  yulType = (NULL != strstr(CurrentFilename, ".yul"));

  // Loop on the lines of the input file.  
  s[sizeof (s) - 1] = 0;
  for (;;)
    {
      // Get the next line from the file.
      ss = fgets (s, sizeof (s) - 1, InputFile);
      // At end of the file?
      if (NULL == ss)
        {
	  // We've reached the end of this input file.  Need to switch
	  // files (if we were within an include-file) or to end the pass.
	  if (NumStackedIncludes)
	    {
	      fclose (InputFile);
	      NumStackedIncludes--;
	      InputFile = StackedIncludes[NumStackedIncludes].InputFile;
	      strcpy (CurrentFilename, 
	              StackedIncludes[NumStackedIncludes].InputFilename);
	      CurrentLineInFile = StackedIncludes[NumStackedIncludes].CurrentLineInFile; 
	      yulType = StackedIncludes[NumStackedIncludes].yulType;
	      continue;
	    }
	  else
	    {
	      // All done!
	      break;
	    }  
	}
      else
        {
	  // No, not at end of file, so we've just read a new line.
	  CurrentLineAll++;
	  CurrentLineInFile++;
	}
	
      if (HtmlCheck (0, InputFile, s, sizeof (s), CurrentFilename, &CurrentLineAll, &CurrentLineInFile))
        continue;
		
      // Analyze the input line.  Is it an "include" directive?	
      if (s[0] == '$')
        {
	  // This is a directive to include another file.
	  if (NumStackedIncludes == MAX_STACKED_INCLUDES)
	    {
	      printf ("Too many levels of include-files.\n");
	      goto Done;
	    }
	  StackedIncludes[NumStackedIncludes].InputFile = InputFile;
	  strcpy (StackedIncludes[NumStackedIncludes].InputFilename,
	  	  CurrentFilename);
	  StackedIncludes[NumStackedIncludes].CurrentLineInFile = CurrentLineInFile;
	  StackedIncludes[NumStackedIncludes].yulType = yulType;
	  NumStackedIncludes++;
	  if (1 != sscanf (s, "$%s", CurrentFilename))
	    {
	      printf ("Include-directive has no filename.\n");
	      goto Done;
	    }
	  CurrentLineInFile = 0;
	  InputFile = fopen (CurrentFilename, "r");
	  if (InputFile == NULL)
	    {
	      printf ("Include-file \"%s\" does not exist.\n", CurrentFilename);
	      goto Done;
	    }	    
	  yulType = (NULL != strstr(CurrentFilename, ".yul"));
	  continue;
	} 
    
      // Frankly, tabs and newlines will cause me a lot of problems further down, since
      // there are actually a couple of things we need to use column alignment to check
      // out.  So let's just start by expanding all tabs to spaces.
      ss = strstr(s, "\n");
      if (ss != NULL)
        *ss = 0;
      s[sizeof(s) - 1] = 0;
      for (ss = s; *ss;)
        {
          if (*ss == '\t')
            {
              int pos, tabStop, len;
              pos = ss - s;
              tabStop = ((pos + 8) & ~7);
              len = strlen(ss + 1);
              if (tabStop + len >= sizeof(s))
                len = sizeof(s) - tabStop - 1;
              if (len > 0)
                memmove(&s[tabStop], &s[pos + 1], len + 1);
              else
                s[tabStop] = 0;
              for (; pos < tabStop && pos < sizeof(s); pos++)
                s[pos] = ' ';
              ss = &s[tabStop];
            }
          else
            ss++;
        }
      *ss = 0;

      if (yulType)
	yul2agc(s);

      // Set up appropriate default values for various fields.
      Label = FalseLabel = Operator = Operand = Mod1 = Mod2 = "";
    
      // Find and remove the comment field, if any.
      for (Comment = s; *Comment && *Comment != COMMENT_SEPARATOR; Comment++);
      if (*Comment == '#')
        {
          *Comment++ = 0;
	  // Trim the newline at the end:
	  for (ss = Comment; *ss; ss++)
	    if (*ss == '\n')
	      *ss = 0;
        }
	
      // Suck in all other fields.
      NumFields = sscanf (s, "%s%s%s%s%s%s", Fields[0], Fields[1],
      			  Fields[2], Fields[3], Fields[4], Fields[5]);	
      if (NumFields >= 1)
        {			  
	  i = 0;
	  if (*s && !isspace (*s))
	    Label = Fields[i++];
	  else if (*Fields[0] == '+' || *Fields[0] == '-')
	    FalseLabel = Fields[i++];
	  if (i < NumFields)
	    Operator = Fields[i++];
	  if (i < NumFields)
	    Operand = Fields[i++];
	  if (i < NumFields)
	    Mod1 = Fields[i++];
	  if (i < NumFields)
	    Mod2 = Fields[i++];
	}
	
      if (*Label != 0 && strcmp(Operator, "MEMORY") && strcmp(Operator, "CHECK="))
        {
	  //if (!strcmp (Label, "ATMAGAD"))
	  //  printf ("***** %s, %d, %d, %s", CurrentFilename, CurrentLineAll, CurrentLineInFile, s);
	  if (AddSymbol (Label))
	    {
	      printf ("Out of memory (2).\n");
	      goto Done;
	    }	
	}
    }

  // Done with this pass.
Done:  
  if (InputFile != NULL)
    fclose (InputFile);
  for (i = 0; i < NumStackedIncludes; i++)
    fclose (StackedIncludes[i].InputFile); 
  NumStackedIncludes = 0; 
}

  

back to top