/* txtio.cc */ #include "txtio.h" #include "ioexception.h" #include "str.h" // const lf, ... #include "conv.h" // template functions StrToNum, NumToStr // #include "dictionary.h" #include "inf.h" // function info #include // function memset OPEN_NAMESPACE /******************************* TEXT INPUT *******************************/ TTxtInput::TTxtInput (): // FileInx (0), LinePos (0), ColPos (0), CharPos (0), // TokenFileInx (0), TokenLinePos (0), TokenColPos (0), TokenCharPos (0), InpCh (0), PrevCh (0), PrevEol (false), InpEof (false), PositionInitialized (false), DuplLen (0), DuplBuf (), ValueLen (0), ValueBuf (), TokenKind (StartToken), TokenTxt (""), TokenVal (""), SemicolonComments (false), HashComments (false) { } TTxtInput::~TTxtInput () { } /* ---------------------------------------------------------------------- */ void TTxtInput::Init () { // original method TInput::Init (); InpCh = 0; PrevCh = 0; PrevEol = false; InpEof = false; if (! PositionInitialized) { LinePos = 1; ColPos = 0; CharPos = 0; TokenLinePos = 1; TokenColPos = 0; TokenCharPos = 0; } // not necessary DuplLen = 0; memset (DuplBuf, 0, sizeof (DuplBuf)); ValueLen = 0; memset (ValueBuf, 0, sizeof (ValueBuf)); TokenKind = StartToken; TokenTxt = ""; TokenVal = ""; // read first character GetCh (); } /********************************** OPEN **********************************/ string TTxtInput::GetFileName () { return FileName; } void TTxtInput::SetFileName (const string p_filename) { FileName = p_filename; // FileInx = StoreFileName (FileName); } void TTxtInput::SetTokenLine (int p_line) { TokenLinePos = p_line; } void TTxtInput::SetTokenCol (int p_col) { TokenColPos = p_col; } /******************************** MESSAGES ********************************/ void TTxtInput::Message (MessageLevel level, const string msg) { string file_name = FileName; int line = LinePos; int column = ColPos; message (level, msg, file_name, line, column); } /* ---------------------------------------------------------------------- */ void TTxtInput::Debug (const string msg) { Message (DebugLevel, msg); } void TTxtInput::Info (const string msg) { Message (InfoLevel, msg); } void TTxtInput::Note (const string msg) { Message (NoteLevel, msg); } void TTxtInput::Warning (const string msg) { Message (WarningLevel, msg); } void TTxtInput::Flaw (const string msg) { Message (WarningLevel, msg); } void TTxtInput::Error (const string msg) { Message (ErrorLevel, msg); } void TTxtInput::Abort (const string msg) { Message (AbortLevel, msg); } /******************************* CHAR INPUT *******************************/ void TTxtInput::GetCh () { // assert (BufPos >= 0); // assert (BufPos <= BufLen); // assert (BufLen >= 0); // assert (BufLen <= BufSize); if (BufPos >= BufLen) { if (InpEof) { Error ("End of file"); } else { ReadBuf (); InpEof = (BufLen == 0); } } if (InpEof) InpCh = 0; else { // assert (BufPos >= 0); // assert (BufPos < BufLen); // assert (BufLen >= 0); // assert (BufLen <= BufSize); InpCh = (char) (Buf[BufPos]); BufPos ++; } // assert (BufPos >= 0); // assert (BufPos <= BufLen); // assert (BufLen >= 0); // assert (BufLen <= BufSize); if (PrevEol) { LinePos ++; ColPos = 0; PrevEol = false; } if (InpCh == cr) { PrevEol = true; ColPos ++; } else if (InpCh == lf) { if (PrevCh != cr) { PrevEol = true; ColPos ++; } } else { ColPos ++; } CharPos ++; PrevCh = InpCh; } /* ---------------------------------------------------------------------- */ void TTxtInput::NextCh () { if (DuplLen >= DuplMax) { Error ("Token too long"); } else { DuplLen ++; DuplBuf [DuplLen-1] = InpCh; } GetCh (); } void TTxtInput::StoreCharacter (char c) { if (ValueLen >= DuplMax) { Error ("Token too long"); } else { ValueLen ++; ValueBuf [ValueLen-1] = c; } } /* ---------------------------------------------------------------------- */ void TTxtInput::GetIdent () { DuplLen = 0; while (IsLetterOrDigit (InpCh)) NextCh (); // set length DuplBuf [DuplLen] = 0; TokenTxt = string (DuplBuf); TokenVal = ""; TokenKind = IdentToken; } void TTxtInput::GetNumber () { bool hex = false; bool any_digit = false; bool floating_point = false; DuplLen = 0; if (InpCh == '0') { NextCh (); // first digit any_digit = true; if (InpCh == 'x' || InpCh == 'X') { NextCh (); // store 'x' hex = true; while (IsHexDigit (InpCh)) NextCh (); } } if (! hex) { while (IsDigit (InpCh)) { any_digit = true; NextCh (); } if (InpCh == '.') { NextCh (); // decimal point floating_point = true; while (IsDigit (InpCh)) { any_digit = true; NextCh (); } } if (any_digit && (InpCh == 'E' || InpCh == 'e')) { NextCh (); floating_point = true; if (InpCh == '+' || InpCh == '-') NextCh (); if (! IsDigit (InpCh)) Error ("Digit expected"); while (IsDigit (InpCh)) NextCh (); } } if (any_digit) { if (floating_point) while (InpCh == 'f' || InpCh == 'F' || InpCh == 'l' || InpCh == 'L') NextCh (); else while (InpCh == 'u' || InpCh == 'U' || InpCh == 'l' || InpCh == 'L') NextCh (); } // set length DuplBuf [DuplLen] = 0; if (any_digit) { TokenTxt = string (DuplBuf); TokenVal = ""; TokenKind = NumberToken; } else { StoreSeparator ('.'); } } char TTxtInput::Character () // read one C-style character { if (InpCh != backslash) // simple character { char last = InpCh; NextCh (); return last; } else // escape sequence { NextCh (); // skip backslash if (IsOctal (InpCh)) // octal { int n = 0; int cnt = 1; while (IsOctal (InpCh) && cnt <= 3) { n = n*8 + InpCh-'0'; cnt++; NextCh (); } return char (n); } else if (InpCh == 'x' || InpCh == 'X') // hex { NextCh (); int n = 0; while (IsHexDigit (InpCh)) { int d; if (InpCh >= 'A' && InpCh <= 'F') d = InpCh - 'A' + 10; else if (InpCh >= 'a' && InpCh <= 'f') d = InpCh - 'a' + 10; else d = InpCh - '0'; n = n*16 + d; NextCh (); } return char (n); } else { char last = InpCh; NextCh (); switch (last) // other { case 'a': return '\a'; case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; case quote1: return last; case quote2: return last; case backslash: return last; case '?': return last; default: return last; } } } } void TTxtInput::GetChar () { DuplLen = 0; ValueLen = 0; NextCh (); // skip quote // if (InpCh == quote1) // Error ("Empty character constant"); while (InpCh != quote1) { if (InpEof || InpCh == cr || InpCh == lf) Error ("Character constant exceeds line"); char c = Character (); StoreCharacter (c); } NextCh (); // skip quote // set length DuplBuf [DuplLen] = 0; ValueBuf [ValueLen] = 0; TokenTxt = string (DuplBuf); // with quotes and escape sequences TokenVal = string (ValueBuf); // value without quotes and escape sequences TokenKind = CharToken; } void TTxtInput::GetString () { DuplLen = 0; ValueLen = 0; NextCh (); // skip quote while (InpCh != quote2) { if (InpEof || InpCh == cr || InpCh == lf) Error ("String exceeds line"); char c = Character (); StoreCharacter (c); } NextCh (); // skip quote // set length DuplBuf [DuplLen] = 0; ValueBuf [ValueLen] = 0; TokenTxt = string (DuplBuf); // string with quotes and escape sequences TokenVal = string (ValueBuf); // value without quotes and escape sequences TokenKind = StringToken; } /* ---------------------------------------------------------------------- */ void TTxtInput::StoreSeparator (char ch) { TokenTxt = ch; TokenVal = ""; TokenKind = SeparatorToken; } void TTxtInput::GetSeparator () { char c = InpCh; NextCh (); StoreSeparator (c); } /* ---------------------------------------------------------------------- */ void TTxtInput::SkipLine () { while (! InpEof && InpCh != cr && InpCh != lf) GetCh (); if (! InpEof && InpCh == cr) GetCh (); // skip cr if (! InpEof && InpCh == lf) GetCh (); // skip lf } void TTxtInput::SkipWhiteSpace () { again: while (! InpEof && InpCh <= ' ') // WHITE SPACE GetCh (); if (SemicolonComments && ! InpEof && InpCh == ';') { SkipLine (); goto again; } if (HashComments && ! InpEof && InpCh == '#') { SkipLine (); goto again; } if (! InpEof && InpCh == '/') { GetCh (); // skip slash if (! InpEof && InpCh == '/') // SINGLE LINE COMMENT { SkipLine (); goto again; } else if (! InpEof && InpCh == '*') // COMMENT { if (! InpEof) GetCh (); // skip asterisk char prev = ' '; while (! InpEof && ! (prev == '*' && InpCh == '/')) { prev = InpCh; GetCh (); } if (! InpEof) GetCh (); // skip slash goto again; } else StoreSeparator ('/'); // SLASH } } /* ---------------------------------------------------------------------- */ void TTxtInput::GetToken () { SkipWhiteSpace (); TokenTxt = ""; TokenVal = ""; if (InpEof) // END OF FILE TokenKind = EofToken; else if (IsLetter (InpCh)) // IDENTIFIER GetIdent (); else if (IsDigit (InpCh)) // NUMBER GetNumber (); else if (InpCh == '.') // NUMBER or PERIOD GetNumber (); else if (InpCh == quote1) // CHARACTER GetChar (); else if (InpCh == quote2) // STRING GetString (); else // SEPARATOR GetSeparator (); } /* ---------------------------------------------------------------------- */ bool TTxtInput::IsIdent (string par) { return (TokenKind == IdentToken) && (TokenTxt == par); } bool TTxtInput::IsSeparator (char par) { return (TokenKind == SeparatorToken) && (TokenTxt[0] == par); } /* ---------------------------------------------------------------------- */ void TTxtInput::CheckIdent (string par) { if (TokenKind != IdentToken || TokenTxt != par) Error (par + " expected"); GetToken (); } void TTxtInput::CheckSeparator (char par) { if (TokenKind != SeparatorToken || TokenTxt[0] != par) { // Error (CharToStr (par) + " expected"); Error (CharToStr (par) + " expected and found " + QuoteStr (TokenTxt)); } GetToken (); } void TTxtInput::CheckEof () { if (TokenKind != EofToken) Error ("End of file expected"); } /* ---------------------------------------------------------------------- */ string TTxtInput::ReadIdent () { string result; if (TokenKind != IdentToken) Error ("Identifier expected"); result = TokenTxt; GetToken (); return result; } string TTxtInput::ReadNumber () { string result; if (TokenKind != NumberToken) Error ("Number expected"); result = TokenTxt; GetToken (); return result; } string TTxtInput::ReadSignedNumber () { bool minus; string result; minus = false; if (TokenKind == SeparatorToken && TokenTxt [0] == '-') { minus = true; GetToken (); } result = ReadNumber (); if (minus) result = '-' + result; return result; } char TTxtInput::ReadChar () { char result; if (TokenKind != CharToken) Error ("Character constant expected"); result = TokenTxt [0]; GetToken (); return result; } string TTxtInput::ReadString () { string result; if (TokenKind != StringToken) Error ("String expected"); result = TokenVal; GetToken (); return result; } /*************************** INPUT - ATTRIBUTES ***************************/ #ifdef TEXT_INPUT_OUTPUT bool TTxtInput::ReadBool () { bool result; if (IsIdent ("true")) { result = true; GetToken (); } else if (IsIdent ("false")) { result = false; GetToken (); } else { Error ("Boolean value expected"); } return result; } /* ---------------------------------------------------------------------- */ template inline T ReadNum (TTxtInput * io) { T result; bool ok; StrToNum (io->ReadSignedNumber (), result, ok); return result; } int TTxtInput::ReadInt () { return ReadNum (this); } float TTxtInput::ReadFloat () { return ReadNum (this); } double TTxtInput::ReadDouble () { return ReadNum (this); } /* ---------------------------------------------------------------------- */ int8 TTxtInput::ReadInt8 () { return ReadNum (this); } int16 TTxtInput::ReadInt16 () { return ReadNum (this); } int32 TTxtInput::ReadInt32 () { return ReadNum (this); } #ifdef INT64 int64 TTxtInput::ReadInt64 () { return ReadNum (this); } #endif /* ---------------------------------------------------------------------- */ uint8 TTxtInput::ReadUInt8 () { return ReadNum (this); } uint16 TTxtInput::ReadUInt16 () { return ReadNum (this); } uint32 TTxtInput::ReadUInt32 () { return ReadNum (this); } #ifdef INT64 uint64 TTxtInput::ReadUInt64 () { return ReadNum (this); } #endif #endif // TEXT_INPUT_OUTPUT /****************************** TEXT OUTPUT *******************************/ TTxtOutput::TTxtOutput (): ShowMsg (true), StartLine (false), Indent (0), LinePos (0), ColPos (0) { } TTxtOutput::~TTxtOutput () { // Store (); // !? } /* ---------------------------------------------------------------------- */ void TTxtOutput::Init () { // original method TOutput::Init (); Indent = 0; StartLine = true; LinePos = 1; ColPos = 0; } /* ---------------------------------------------------------------------- */ void TTxtOutput::Message (MessageLevel level, const string msg) { message (level, msg, FileName, LinePos, ColPos); } /* ---------------------------------------------------------------------- */ void TTxtOutput::Debug (const string msg) { Message (InfoLevel, msg); } void TTxtOutput::Info (const string msg) { Message (InfoLevel, msg); } void TTxtOutput::Note (const string msg) { Message (NoteLevel, msg); } void TTxtOutput::Warning (const string msg) { Message (WarningLevel, msg); } void TTxtOutput::Flaw (const string msg) { Message (FlawLevel, msg); } void TTxtOutput::Error (const string msg) { Message (ErrorLevel, msg); } void TTxtOutput::Abort (const string msg) { Message (AbortLevel, msg); } /* ---------------------------------------------------------------------- */ void TTxtOutput::SetIndent (int i) { Indent = i; } void TTxtOutput::IncIndent () { Indent += 3; } void TTxtOutput::DecIndent () { Indent -= 3; } /* ---------------------------------------------------------------------- */ void TTxtOutput::PutPlainChr (char c) { WriteOneByte (c); if (c == lf) { LinePos ++; ColPos = 0; } else { ColPos ++; } } void TTxtOutput::PutPlainSpaces (int n) { WriteSameBytes (' ', n); ColPos += n; } void TTxtOutput::PutPlainStr (const string s) { for (int i = 0; i < s.length (); i ++) PutPlainChr (s[i]); } void TTxtOutput::PutPlainEol () { // PutPlainChr (cr); PutPlainChr (lf); } /* ---------------------------------------------------------------------- */ void TTxtOutput::OpenLine () { PutPlainSpaces (Indent); StartLine = false; } void TTxtOutput::CloseLine () { StartLine = true; } /* ---------------------------------------------------------------------- */ void TTxtOutput::Put (const string s) { if (StartLine) OpenLine (); PutPlainStr (s); } void TTxtOutput::PutChr (char c) { if (StartLine) OpenLine (); PutPlainChr (c); } void TTxtOutput::PutSpaces (int n) { if (StartLine) OpenLine (); PutPlainSpaces (n); } void TTxtOutput::PutEol () { PutPlainEol (); CloseLine (); } void TTxtOutput::PutCondEol () { // finish not empty line if (! StartLine) PutEol (); } void TTxtOutput::PutLn (const string s) { Put (s); PutEol (); } /* ---------------------------------------------------------------------- */ void TTxtOutput::PutBlock (const string txt) { string::size_type inx = 0; string::size_type len = txt.length (); while (inx < len) { string::size_type start = inx; while (inx < len && txt[inx] != cr && txt[inx] != lf) inx ++; if (inx > start) Put (txt.substr (start, inx-start)); if (inx < len && (txt[inx] == cr || txt[inx] == lf)) { PutEol (); if (txt[inx] == cr) { inx ++; if (inx < len && txt[inx] == lf) inx ++; } else { inx ++; } } } } /************************** OUTPUT - ATTRIBUTES ***************************/ #ifdef TEXT_INPUT_OUTPUT void TTxtOutput::WriteBool (bool value) { Put (BoolToStr (value)); } void TTxtOutput::WriteChar (char value) { WriteString (CharToStr (value)); } void TTxtOutput::WriteInt (int value) { Put (NumToStr (value)); } void TTxtOutput::WriteFloat (float value) { Put (NumToStr (value)); } void TTxtOutput::WriteDouble (double value) { Put (NumToStr (value)); } /* ---------------------------------------------------------------------- */ void TTxtOutput::WriteString (const string value) { // !? use QuoteStr size_t i; char c; const char hex [16+1] = "0123456789abcdef"; if (StartLine) OpenLine (); PutChr (quote2); for (i = 0; i < value.length (); i ++) { c = value[i]; if (c < ' ') { PutChr (backslash); switch (c) { case '\a': PutChr ('a'); break; case '\b': PutChr ('b'); break; case '\f': PutChr ('f'); break; case '\n': PutChr ('n'); break; case '\r': PutChr ('r'); break; case '\t': PutChr ('t'); break; case '\v': PutChr ('v'); break; default: PutChr ('x'); PutChr (hex [c >> 4]); PutChr (hex [c & 15]); break; } } else { if (c == quote1 || c == quote2 || c==backslash) PutChr (backslash); PutChr (c); } } PutChr (quote2); } /* ---------------------------------------------------------------------- */ void TTxtOutput::WriteInt8 (int8 value) { Put (NumToStr (value)); } void TTxtOutput::WriteInt16 (int16 value) { Put (NumToStr (value)); } void TTxtOutput::WriteInt32 (int32 value) { Put (NumToStr (value)); } #ifdef INT64 void TTxtOutput::WriteInt64 (int64 value) { Put (NumToStr (value)); } #endif /* ---------------------------------------------------------------------- */ void TTxtOutput::WriteUInt8 (uint8 value) { Put (NumToStr (value)); } void TTxtOutput::WriteUInt16 (uint16 value) { Put (NumToStr (value)); } void TTxtOutput::WriteUInt32 (uint32 value) { Put (NumToStr (value)); } #ifdef INT64 void TTxtOutput::WriteUInt64 (uint64 value) { Put (NumToStr (value)); } #endif #endif // TEXT_INPUT_OUTPUT CLOSE_NAMESPACE