#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../globals.h"
#include "../functions.h"

/*
JScript Token Types:

0: EOF
1: number
2: keyword
3: =
4: identifier
5: EOL
6: %>
7: +,-,*,/,%
8: >,<,<=,>=,<>,==,!=,!
9: &,|,^
10: "    "
11: '    '
12: (,)
13: :
14: .
15: comment
16: ,
17: ;
18: &&,||
19: ? 
20: {,}

*/

int gettoken_j(char *token)
{
int ptr=0,tokentype=2;
int ch,sflag=0,r=0;
int quote=0;
int equals=0;

  if (tokenpush2[0]!=0)
  {
    strcpy(token,tokenpush2);
    tokenpush2[0]=0;
    return tokentypepush2;
  }

  if (tokenpush[0]!=0)
  {
    strcpy(token,tokenpush);
    tokenpush[0]=0;
    return tokentypepush;
  }

  token[1]=0;

  while(1)
  {
    if (pushback!=-1)
    { ch=pushback; pushback=-1; }
      else
    { ch=getc(in); }

    column++;

    if (ch==EOF) break;

    if (equals==1)
    {
      if (ch=='=')
      {
        token[ptr++]=ch;
        token[ptr++]=0;
        return 8;
      }
        else
      {
        pushback=ch;
        token[ptr++]=0;
        return 3;
      }
    }

    if (quote=='\'' && sflag!=1)
    {
      if (ch=='\n' || ch=='\r')
      { 
        token[0]='/';
        for (r=ptr; r>0; r--)
        { token[r]=token[r-1]; }
        token[ptr+1]='\n';
        token[ptr+2]=0;
        return 15;
      }
        else
      if (ch=='%')
      {
        ch=getc(in);

        if (ch=='>')
        {
          push("%>",6);
          token[0]='/';
          for (r=ptr; r>0; r--)
          { token[r]=token[r-1]; }
          token[ptr+1]=' ';
          token[ptr+2]=0;
          return 15;
        }
          else
        {
          pushback=ch;
        }
      }
    }

    if (sflag==1)
    {
      if (ch!=quote)
      {
	pushback=ch;
        token[ptr]=0;
	if (ch=='\"') return 10;
	return 11;
      }

      sflag=0;
    }

    if (ch=='\"' || ch=='\'')
    {
      if (ptr==0)
      { quote=ch; }
	else
      if (quote==ch)
      {
	if (token[ptr-1]==ch && sflag!=3)
        {
	  if (ptr==1)
	  {
	    ch=getc(in);
            pushback=ch;
	    if (ch!=quote)
	    {
	      token[ptr]=quote;
	      token[ptr+1]=0;
	      if (quote=='\'') return 11; else return 10;
	    }
	    sflag=1;
	  }
	    else
	  if (sflag!=3)
          { token[ptr-1]='\\'; sflag=3; token[ptr++]=ch; continue; }
        }
	  else
        { sflag=1; }
      }
/*
        else
      {
printf("pushback=ch; break;\n");
        pushback=ch; break;
      }
*/
    }

    if (sflag==3) sflag=0;

    if (quote!=0)
    {
      token[ptr++]=ch;
      continue;
    }

    if ((ch=='>' && ptr==1) && token[ptr-1]=='%')
    { token[1]='>'; token[2]=0; return 6; }

    if (sflag==2)
    {
      if (ch=='=' || (ch=='>' && token[0]=='<'))
      { token[1]=ch; token[2]=0; }
	else
      { pushback=ch; token[1]=0; }
      return 8;
    }

    if (ch=='>' || ch=='<')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { sflag=2; tokentype=8; }
    }

    if (ch=='(' || ch==')')
    { 
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 12; }
    }

    if (ch=='{' || ch=='}')
    { 
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 20; }
    }

    if (ch=='|' && token[ptr-1]=='|')
    {
      token[ptr++]='|';
      token[ptr]=0;
      return 18;
    }

    if (ch=='=' && token[ptr-1]=='!')
    {
      token[ptr++]='=';
      token[ptr]=0;
      return 8;
    }

    if (ch=='&' && token[ptr-1]=='&')
    {
      token[ptr++]='&';
      token[ptr]=0;
      return 18;
    }

    if (ch=='&')
    { tokentype=9; }

    if (ch=='|')
    { tokentype=9; }

    if (ch=='%')
    { tokentype=7; }

    if (ch=='!')
    { tokentype=8; }

    if (ch=='?')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 19; }
    }

    if (ch=='=')
    {
      if (ptr!=0)
      { 
        pushback=ch;
        token[ptr]=0;
        break; 
      }
	else
      { 
         token[0]=ch; 
         equals=1;
         /* return 8; */
      }
    }

/*
    if (ch=='=')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 8; }
    }
*/

    if (ch=='&')
    {
      if (ptr!=0)
      {
	if (ptr==1 && (ch=='h' || ch=='H'))
        {
	  token[0]='0';
	  token[1]='x';
	  tokentype=1;
        }
	  else
	{ pushback=ch; token[ptr]=0; break; }
      }
	else
      { token[0]=ch; return 9; }
    }

    if (ch==':')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 13; }
    }

    if (ch==';')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 17; }
    }

    if (ch==',')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 16; }
    }

    if (ch=='.')
    {
      if (ptr!=0)
      { pushback=ch; token[ptr]=0; break; }
	else
      { token[0]=ch; return 14; }
    }

    if ((ch=='+' || ch=='-') || (ch=='*' || ch=='/'))
    {
      if (ptr==0)
      { token[0]=ch; token[1]=0; return 7; }
	else
      {
	pushback=ch;
        break;
      }
    }

/*
    if (ch=='_')
    {
      if (ptr==0)
      {
	token[0]=ch;
	while ((ch=getc(in))!=EOF)
        {
	  if (ch=='\n' || ch=='\r')
          {
            line++;
	    r=getc(in);
            if (r=='\r' || r=='\n')
            { if (ch==r) pushback=r; }
	      else
	    { pushback=r; }
	    return 3;
	  }
        }
        return 0;
      }
	else
      if (tokentype==2)
      { token[ptr++]=ch; continue; }
	else
      { pushback=ch; break; }
    }
*/

    if (ch=='\r' || ch=='\n')
    {
      if (ptr==0)
      {
        token[0]='\n';
        column=0;
        line++;
	r=getc(in);
        if (r=='\r' || r=='\n')
        { if (ch==r) pushback=r; }
	  else
	{ pushback=r; }
        return 5;
      }
	else
      { pushback=ch; break; }
    }

    if (ch==' ' || ch=='\t')
    {
      if (ptr==0)
      { /* putc(ch,out); */ continue; }
	else
      {
	pushback=ch;
        token[ptr]=0;
	return tokentype;
      }
    }

    if (tokentype==1)
    {
      if (ch<'0' || ch>'9')
      { pushback=ch; break; }
    }

    if (ch>='0' && ch<='9')
    {
      if (ptr==0)
      { tokentype=1; }
    }

    token[ptr++]=(char)ch;
  }

  if (ptr==0) return 0;

  token[ptr]=0;
  return tokentype;
}

