/* lex.H
 * John Viega
 *
 * Jul 28, 1999
 */

#ifndef __LEX_H__
#define __LEX_H__

#include <stdio.h>
#include <ctype.h>
#include "token.H"

#define  BUFFER_SIZE 1024  

class Lex {
public:
  Lex(FILE *f, char *srcid, int cpp);
  Lex(char* str, long int len, char *srcid, unsigned int lineno, int err, int cpp); 
  ~Lex();
  TokenContainer* GetTokens()   { return token_box; }
  TokenContainer* GetComments() { return comment_box; }
  char *GetSourceIdentifier()   { return source_id; }
private:
  int                  free_input;
  int                  cpp_mode;
  TokenContainer*      token_box;
  TokenContainer*      comment_box;
  // this can be overflowed via the C standard, but the implementation is
  // undefined.  So no need to try to keep track of overflows.
  long                 chr_val;
  unsigned int         lineno;
  char*                source_id;
  // lineno_offset == How many lines back the current token started.
  unsigned int         lineno_offset;
  // We have to do this because I suck... comments can show up in
  // the middle of "tokens" because I'm lazy w/ preprocessor shit.
  unsigned int         comment_lineno_offset;
  // 01234.3  Looks octal till you get to the ., so if we think we
  // have an octal #, we have to keep around the base 10 and the base 8
  // until we are positive.
  int                  looks_octal;
  long                 oct_val;
  long                 num_val;
  long                 mant_val;
  long                 exp;
  int                  real;
  int                  unsigned_flag;
  int                  long_flag;
  int                  float_flag;
  int                  exp_neg_flag;
  char                 *str;
  int                  str_len;
  int                  str_pos;
  char                 *input;
  int                  input_size;
  int                  pos;
  int                  cpp_comment;
  int                  return_on_error;
  void Init(char* str, long len, char *id, int l, int cpp);
  void Scan();
  int  ScanLine(int preproc);
  int  LexCComment();
  void LexCPPComment();
  void StartCComment()   { cpp_comment = 0; }
  void StartCPPComment() { cpp_comment = 1; }
  void AddCharToComment(char t);
  void EndComment();
  void ParseDefine();
  void StartHexChr(char c);
  void AddHexChr(char c);
  void EndHexChr();
  void StartOctChr(char c);
  void AddOctChr(char c);
  void EndOctChr();
  void StartIdentifier(char ch);
  void ContinueIdentifier(char ch);
  void EndIdentifier();
  void StartHexNum();
  void AddHexDigit(char c);
  void EndNum();
  void StartBase10OrLowerNum(char c);
  void BeginExponent(char c);
  void AddExponent(char c);
  void AddOctDigit(char c);
  void AddDecDigit(char c);
  void MakeLong();
  void MakeUnsigned();
  void MakeFloat();
  void GenChr(long c);
  void AddCharToStr(char c);
  void EndStr();
  void GenOp(char *s);
  int GetChar();
  void UngetChar(int c);
  int  LexPreprocessorStuff();
  void LexPreprocNumber(char c);
};

#endif
