#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
using namespace std;

#include "nwcc.h"
#include "nwcclex.h"
  
#include	<stdio.h>
#include	<string.h>
#include	<stdarg.h>
char TOKEN[TOKEN_LEN];
int tokenPt = 0;
int Char;
int ErrorFlg = 0;
FILE * RdFp, *pr;
const char *MESG = NULL;
int EndFlg = 0;
char OutputFileName[MAXPATHLEN + 1];
extern const char *InputSuffix;
extern const char *OutputSuffix;
int
main (int argc, char **argv) 
{
  int c, i;
  if (strcmp (InputSuffix, OutputSuffix) == 0)
    {
      fprintf (stderr, "input/output suffix error %s == %s \n", InputSuffix,
		OutputSuffix);
    }
  if ((argc <= 1) || (argc > 2))
    {
      fprintf (stderr, " %s <source> \n", argv[0]);
      exit (1);
    }
  if ((RdFp = fopen (argv[1], "rb")) == NULL)
    {
      fprintf (stderr, "not File : %s \n", argv[1]);
      exit (1);
    }
  strncpy (OutputFileName, argv[1], MAXPATHLEN);
  OutputFileName[MAXPATHLEN] = 0;
  for (i = sizeof (OutputFileName); i > 0; i--)
    {
      if (OutputFileName[i] == '.')
	{
	  break;
	}
    }
  if (strncmp (OutputFileName + i + 1, InputSuffix, sizeof (InputSuffix)) ==
       0)
    {
      OutputFileName[i + 1] = '\0';
      strncat (OutputFileName, OutputSuffix, MAXPATHLEN-strlen(OutputFileName));
    }
  else
    {
      fprintf (stderr, "input file must be *.%s : %s \n", InputSuffix,
		argv[1]);
      exit (1);
    }
  if ((pr = fopen (OutputFileName, "w")) == NULL)
    {
      fprintf (stderr, "Can't open output File : %s \n", OutputFileName);
      exit (1);
    }
  NwccMain ();
  fclose (pr);
  fclose (RdFp);
  exit (0);
}
long
FilePointSave () 
{
  return ftell (RdFp);
}
void
FilePointResume (long tellpt) 
{
  fseek (RdFp, tellpt, 0);
} void
SkipComment (int &Char) 
{
  for (;;)
    {
      if (Char == '/')
	{
	  int c = fgetc (RdFp);
	  if (c == '/')
	    {
	      for (;;)
		{
		  c = fgetc (RdFp);
		  if (c == '\n')
		    {
		      break;
		    }
		}
	      Char = fgetc (RdFp);
	    }
	  else if (c == '*')
	    {
	      for (;;)
		{
		  c = fgetc (RdFp);
		  if (c == '*')
		    {
		      c = fgetc (RdFp);
		      if (c == '/')
			{
			  break;
			}
		      else
			{
			  ungetc (c, RdFp);
			}
		    }
		  else if (c == '/')
		    {
		      if ((c = fgetc (RdFp)) == '*')
			{
			  ungetc ('*', RdFp);
			  Char = '/';
			  SkipComment (Char);
			}
		    }
		}
	      Char = fgetc (RdFp);
	    }
	  else
	    {
	      ungetc (c, RdFp);
	      break;
	    }
	}
      else
	{
	  return;
	}
    }
}
int
GetChar () 
{
  Char = fgetc (RdFp);
  SkipComment (Char);
  return Char;
}
void
UnGetChar (int c) 
{
  ungetc (c, RdFp);
} void
PutChar (int Char) 
{
  if (fputc (Char, pr) == EOF)
    {
      ErrorStop ("can't write file ");
    }
}
void
SkipSpace () 
{
  int c;
  
  do
    {
      c = GetChar ();
    }
  while (isspace (c));
  UnGetChar (c);
}
int
CHECK (const char *Pt) 
{
  long TelSav;
  int r;
  TelSav = FilePointSave ();
  r = COMP (Pt);
  FilePointResume (TelSav);
  return r;
}
int
NotSkipSpCOMP (const char *Pt) 
{
  long TelSav;
  int c;
  TelSav = FilePointSave ();
  c = GetChar ();
  if ((char) c != *Pt)
    {
      FilePointResume (TelSav);
      return -1;
    }
  Pt++;
  while (*Pt)
    {
      c = GetChar ();
      if ((char) Char != *Pt)
	{
	  FilePointResume (TelSav);
	  return -1;
	}
      Pt++;
    }
  return 0;
}
int
COMP (const char *Pt) 
{
  long TelSav;
  int r, c;
  TelSav = FilePointSave ();
  SkipSpace ();
  r = NotSkipSpCOMP (Pt);
  if (r != 0)
    {
      FilePointResume (TelSav);
      return r;
    }
  else
    {
      fseek (RdFp, ftell (RdFp) - 1, 0);
      if (!isalpha (GetChar ()))
	{
	  return 0;
	}
      c = GetChar ();
      UnGetChar (c);
      if (isalpha (c) || (c == '_'))
	{
	  FilePointResume (TelSav);
	  return -1;
	}
      return 0;
    }
}
int
LineNumber () 
{
  int LineNo = 1;
  long TelSav;
  int c;
  TelSav = FilePointSave ();
  rewind (RdFp);
  while (TelSav != FilePointSave ())
    {
      c = fgetc (RdFp);
      if (c == '\n')
	{
	  LineNo++;
	}
      if (c == EOF)
	break;
    }
  FilePointResume (TelSav);
  return LineNo;
}
static char errorbuf[1024];
void
ErrorStop (const char *fmt, ...) 
{
  va_list argptr;
  int LineNo = 1;
  long TelSav;
  LineNo = LineNumber ();
  errorbuf[0] = '\0';
  va_start (argptr, fmt);
  vsprintf (errorbuf, fmt, argptr);
  va_end (argptr);
  if (strlen (errorbuf) == 0)
    {
      strncpy (errorbuf, "Syntax Error ", 1023);
    }
  fprintf (stderr, "# %d : error... %s\n", LineNo, errorbuf);
  fclose (pr);
  ErrorFlg = -1;
  exit (1);
}
void
UNTIL (const char *s) 
{
  const char *Pt;
  int c;
  int matchFlg = 0;
  long tellsave;
  while (matchFlg == 0)
    {
      Pt = s;
      while ((char) (c = GetChar ()) != *Pt)
	{
	  PutChar (c);
	} matchFlg = 1;
      Pt++;
      tellsave = FilePointSave () - 1;
      while (*Pt)
	{
	  c = GetChar ();
	  if ((char) c != *Pt)
	    {
	      FilePointResume (tellsave);
	      c = GetChar ();
	      PutChar (c);
	      matchFlg = 0;
	      break;
	    }
	  Pt++;
	}
    }
}
void
SKIP (const char *s) 
{
  const char *Pt;
  int c;
  int matchFlg = 0;
  while (matchFlg == 0)
    {
      Pt = s;
      while ((char) (c = GetChar ()) != *Pt)
	;
      matchFlg = 1;
      Pt++;
      while (*Pt)
	{
	  c = GetChar ();
	  if ((char) c != *Pt)
	    {
	      matchFlg = 0;
	      break;
	    }
	  Pt++;
	}
    }
}
int
NotSkipSpNOT (const char *s) 
{
  long TelSav;
  int rc;
  TelSav = FilePointSave ();
  rc = !NotSkipSpCOMP (s);
  FilePointResume (TelSav);
  return rc;
}
int
NOT (const char *s) 
{
  long TelSav;
  int rc;
  TelSav = FilePointSave ();
  rc = !COMP (s);
  FilePointResume (TelSav);
  return rc;
}
int
C () 
{
  Char = GetChar ();
  return 0;
}
int
Eof () 
{
  int c;
  
  do
    {
      c = fgetc (RdFp);
      if (c == EOF)
	{
	  return 0;
	}
    }
  while (isspace (c));
  ungetc (c, RdFp);
  return -1;
}
int
NotEof () 
{
  int c;
  
  do
    {
      c = fgetc (RdFp);
      if (c == EOF)
	{
	  return -1;
	}
    }
  while (isspace (c));
  ungetc (c, RdFp);
  return 0;
}
int
N () 
{
  C ();
  if (!isdigit (Char))
    {
      UnGetChar (Char);
      return -1;
    }
  return 0;
}
int
A () 
{
  C ();
  if (!isalpha (Char) && (Char != '_'))
    {
      UnGetChar (Char);
      return -1;
    }
  return 0;
}
int
AN () 
{
  C ();
  if (!isalnum (Char) && (Char != '_'))
    {
      UnGetChar (Char);
      return -1;
    }
  return 0;
}
int
SPACE () 
{
  C ();
  if (!isspace (Char))
    {
      UnGetChar (Char);
      return -1;
    }
  return 0;
}
void
SetToken (int c) 
{
  if (tokenPt >= TOKEN_LEN)
    {
      ErrorStop ("Too long token ");
    }
  if (c & 0xff00)
    {
      TOKEN[tokenPt] = (c >> 8);
      tokenPt++;
      TOKEN[tokenPt] = (c & 0xff);
      tokenPt++;
    }
  else
    {
      TOKEN[tokenPt] = c;
      tokenPt++;
    }
}
int
FNUM () 
{
  int dot = 0;
  SkipSpace ();
  tokenPt = 0;
  C ();
  if ((!isdigit (Char)) && (Char != '.'))
    {
      UnGetChar (Char);
      return -1;
    }
  if (Char == '.')
    {
      dot++;
    }
  SetToken (Char);
  for (;;)
    {
      C ();
      if (Char == '.')
	{
	  if (dot)
	    {
	      UnGetChar (Char);
	      return -1;
	    }
	  dot++;
	  SetToken (Char);
	}
      else if ((Char == 'e') || (Char == 'E'))
	{
	  SetToken (Char);
	  C ();
	  if ((Char == '+') || (Char == '-'))
	    {
	      SetToken (Char);
	      for (;;)
		{
		  C ();
		  if (!isdigit (Char))
		    {
		      UnGetChar (Char);
		      SetToken ('\0');
		      return 0;
		    }
		  SetToken (Char);
		}
	    }
	  else
	    {
	      UnGetChar (Char);
	      return -1;
	    }
	}
      else if (!isdigit (Char))
	{
	  UnGetChar (Char);
	  SetToken ('\0');
	  return 0;
	}
      else
	{
	  SetToken (Char);
	}
    }
  return 0;
}
int
STRINGS () 
{
  char qt;
  SkipSpace ();
  tokenPt = 0;
  C ();
  if ((Char != '\"') && (Char != '\''))
    {
      UnGetChar (Char);
      return -1;
    }
  qt = Char;
  for (;;)
    {
      C ();
      if (Char == qt)
	{
	  SetToken (0);
	  return 0;
	}
      else
	{
	  SetToken (Char);
	}
    }
  SetToken (0);
  return -1;
}
int
CR () 
{
  for (;;)
    {
      C ();
      if (Char == '\n')
	{
	  return 0;
	}
      else if (Char == EOF)
	{
	  return 0;
	}
      else if (Char > ' ')
	{
	  UnGetChar (Char);
	  return -1;
	}
    }
}
int
ANY () 
{
  ErrorFlg = 0;
  MESG = NULL;
  
  do
    {
      long chktell1, chktell2;
      chktell1 = FilePointSave ();
      int AN ();
      ErrorFlg = AN ();
      MESG = "AN is missing ";
      if (ErrorFlg)
	{
	}
      if (!ErrorFlg)
	{
	}
      chktell2 = FilePointSave ();
      if ((chktell1 == chktell2) && !ErrorFlg)
	ErrorStop ("endless loop occured");
    }
  while (!ErrorFlg);
  ErrorFlg = 0;
  MESG = NULL;
  if (!ErrorFlg)
    {
    }
  return ErrorFlg;
}
int
WRD () 
{
  
  {
    long tellsave;
    tokenPt = 0;
    tellsave = FilePointSave ();
    SkipSpace ();
    ErrorFlg = 0;
    MESG = NULL;
    int AN ();
    ErrorFlg = AN ();
    MESG = "AN is missing ";
    if (ErrorFlg)
      {
	
	{
	  FilePointResume (tellsave);
	}
      }
    if (!ErrorFlg)
      {
	SetToken (Char);
	
	do
	  {
	    long chktell1, chktell2;
	    chktell1 = FilePointSave ();
	    int AN ();
	    ErrorFlg = AN ();
	    MESG = "AN is missing ";
	    if (ErrorFlg)
	      {
	      }
	    if (!ErrorFlg)
	      {
		SetToken (Char);
	      }
	    chktell2 = FilePointSave ();
	    if ((chktell1 == chktell2) && !ErrorFlg)
	      ErrorStop ("endless loop occured");
	  }
	while (!ErrorFlg);
	ErrorFlg = 0;
	MESG = NULL;
	if (ErrorFlg)
	  ErrorStop (MESG);
	SetToken ('\0');
      }
  }
  return ErrorFlg;
}
int
NUM () 
{
  
  {
    long tellsave;
    tokenPt = 0;
    tellsave = FilePointSave ();
    SkipSpace ();
    ErrorFlg = 0;
    MESG = NULL;
    int N ();
    ErrorFlg = N ();
    MESG = "N is missing ";
    if (ErrorFlg)
      {
	
	{
	  FilePointResume (tellsave);
	}
      }
    if (!ErrorFlg)
      {
	SetToken (Char);
	
	do
	  {
	    long chktell1, chktell2;
	    chktell1 = FilePointSave ();
	    int N ();
	    ErrorFlg = N ();
	    MESG = "N is missing ";
	    if (ErrorFlg)
	      {
	      }
	    if (!ErrorFlg)
	      {
		SetToken (Char);
	      }
	    chktell2 = FilePointSave ();
	    if ((chktell1 == chktell2) && !ErrorFlg)
	      ErrorStop ("endless loop occured");
	  }
	while (!ErrorFlg);
	ErrorFlg = 0;
	MESG = NULL;
	if (ErrorFlg)
	  ErrorStop (MESG);
	SetToken ('\0');
      }
  }
  return ErrorFlg;
}
int
ID () 
{
  
  {
    long tellsave;
    tokenPt = 0;
    tellsave = FilePointSave ();
    SkipSpace ();
    ErrorFlg = 0;
    MESG = NULL;
    int A ();
    ErrorFlg = A ();
    MESG = "A is missing ";
    if (ErrorFlg)
      {
	
	{
	  FilePointResume (tellsave);
	}
      }
    if (!ErrorFlg)
      {
	SetToken (Char);
	
	do
	  {
	    long chktell1, chktell2;
	    chktell1 = FilePointSave ();
	    int AN ();
	    ErrorFlg = AN ();
	    MESG = "AN is missing ";
	    if (ErrorFlg)
	      {
	      }
	    if (!ErrorFlg)
	      {
		SetToken (Char);
	      }
	    chktell2 = FilePointSave ();
	    if ((chktell1 == chktell2) && !ErrorFlg)
	      ErrorStop ("endless loop occured");
	  }
	while (!ErrorFlg);
	ErrorFlg = 0;
	MESG = NULL;
	if (ErrorFlg)
	  ErrorStop (MESG);
	SetToken ('\0');
      }
  }
  return ErrorFlg;
}


