Fix for coverity #29409 - Use char 0 instead of NULL
[supertux.git] / src / lisp / lexer.cpp
index 4e4f2fb..ef1925f 100644 (file)
@@ -1,12 +1,10 @@
-//  $Id$
-//
 //  SuperTux
 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
 //
-//  This program 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.
+//  This program 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 3 of the License, or
+//  (at your option) any later version.
 //
 //  This program is distributed in the hope that it will be useful,
 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
 //  GNU General Public License for more details.
 //
 //  You should have received a copy of the GNU General Public License
-//  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#include <config.h>
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "lisp/lexer.hpp"
 
+#include <string.h>
 #include <sstream>
 #include <stdexcept>
-#include <iostream>
-
-#include "lexer.hpp"
-
-namespace lisp
-{
-
-class EOFException
+#include <stdio.h>
+
+namespace lisp {
+
+Lexer::Lexer(std::istream& newstream) :
+  stream(newstream),
+  eof(false),
+  linenumber(0),
+  bufend(),
+  bufpos(),
+  c(),
+  token_string(),
+  token_length()
 {
-};
-
-Lexer::Lexer(std::istream& newstream)
-    : stream(newstream), eof(false), linenumber(0)
-{
-  try {
-    // trigger a refill of the buffer
-    c = 0;
-    bufend = 0;
-    nextChar();
-  } catch(EOFException& ) {
-  }
+  // trigger a refill of the buffer
+  bufpos = '\0';
+  bufend = '\0';
+  nextChar();
 }
 
 Lexer::~Lexer()
@@ -50,14 +46,15 @@ Lexer::~Lexer()
 void
 Lexer::nextChar()
 {
-  ++c;
-  if(c >= bufend) {
-    if(eof)
-      throw EOFException();
+  if(bufpos >= bufend) {
+    if(eof) {
+      c = EOF;
+      return;
+    }
     stream.read(buffer, BUFFER_SIZE);
     size_t bytes_read = stream.gcount();
 
-    c = buffer;
+    bufpos = buffer;
     bufend = buffer + bytes_read;
 
     // the following is a hack that appends an additional ' ' at the end of
@@ -69,6 +66,17 @@ Lexer::nextChar()
       ++bufend;
     }
   }
+  c = *bufpos++;
+  if(c == '\n')
+    ++linenumber;
+}
+
+void
+Lexer::addChar()
+{
+  if(token_length < MAX_TOKEN_LENGTH)
+    token_string[token_length++] = c;
+  nextChar();
 }
 
 Lexer::TokenType
@@ -76,143 +84,127 @@ Lexer::getNextToken()
 {
   static const char* delims = "\"();";
 
-  try {
-    while(isspace(*c)) {
-      if(*c == '\n')
-        ++linenumber;
-      nextChar();
-    };
+  while(isspace(c)) {
+    nextChar();
+  }
 
-    token_length = 0;
+  token_length = 0;
 
-    switch(*c) {
-      case ';': // comment
-        while(true) {
-          nextChar();
-          if(*c == '\n') {
-            ++linenumber;
-            break;
-          }
-        }
-        return getNextToken(); // and again
-      case '(':
+  switch(c) {
+    case ';': // comment
+      while(c != '\n') {
         nextChar();
-        return TOKEN_OPEN_PAREN;
-      case ')':
+      }
+      return getNextToken(); // and again
+    case '(':
+      nextChar();
+      return TOKEN_OPEN_PAREN;
+    case ')':
+      nextChar();
+      return TOKEN_CLOSE_PAREN;
+    case '"': {  // string
+      int startline = linenumber;
+      while(1) {
         nextChar();
-        return TOKEN_CLOSE_PAREN;
-      case '"': {  // string
-        int startline = linenumber;
-        try {
-          while(1) {
+        switch(c) {
+          case '"':
+            nextChar();
+            goto string_finished;
+          case '\r':
+            continue;
+          case '\n':
+            break;
+          case '\\':
             nextChar();
-            if(*c == '"')
-              break;
-            else if (*c == '\r') // XXX this breaks with pure \r EOL
-              continue;
-            else if(*c == '\n')
-              linenumber++;
-            else if(*c == '\\') {
-              nextChar();
-              switch(*c) {
-                case 'n':
-                  *c = '\n';
-                  break;
-                case 't':
-                  *c = '\t';
-                  break;
-              }
+            switch(c) {
+              case 'n':
+                c = '\n';
+                break;
+              case 't':
+                c = '\t';
+                break;
             }
-            if(token_length < MAX_TOKEN_LENGTH)
-              token_string[token_length++] = *c;
+            break;
+          case EOF: {
+            std::stringstream msg;
+            msg << "Parse error in line " << startline << ": "
+                << "EOF while parsing string.";
+            throw std::runtime_error(msg.str());
           }
-          token_string[token_length] = 0;
-        } catch(EOFException& ) {
-          std::stringstream msg;
-          msg << "Parse error in line " << startline << ": "
-            << "EOF while parsing string.";
-          throw std::runtime_error(msg.str());
+          default:
+            break;
         }
-        nextChar();
-        return TOKEN_STRING;
+        if(token_length < MAX_TOKEN_LENGTH)
+          token_string[token_length++] = c;
       }
-      case '#': // constant
-        try {
-          nextChar();
-
-          while(isalnum(*c) || *c == '_') {
-            if(token_length < MAX_TOKEN_LENGTH)
-              token_string[token_length++] = *c;
-            nextChar();
-          }
-          token_string[token_length] = 0;
-        } catch(EOFException& ) {
-          std::stringstream msg;
-          msg << "Parse Error in line " << linenumber << ": "
-            << "EOF while parsing constant.";
-          throw std::runtime_error(msg.str());
-        }
+      string_finished:
+      token_string[token_length] = 0;
+      return TOKEN_STRING;
+    }
+    case '#': // constant
+      nextChar();
 
-        if(strcmp(token_string, "t") == 0)
-          return TOKEN_TRUE;
-        if(strcmp(token_string, "f") == 0)
-          return TOKEN_FALSE;
+      while(isalnum(c) || c == '_') {
+        addChar();
+      }
+      token_string[token_length] = 0;
 
-        // we only handle #t and #f constants at the moment...
+      if(strcmp(token_string, "t") == 0)
+        return TOKEN_TRUE;
+      if(strcmp(token_string, "f") == 0)
+        return TOKEN_FALSE;
 
-        {
-          std::stringstream msg;
-          msg << "Parse Error in line " << linenumber << ": "
+      // we only handle #t and #f constants at the moment...
+      {
+        std::stringstream msg;
+        msg << "Parse Error in line " << linenumber << ": "
             << "Unknown constant '" << token_string << "'.";
-          throw std::runtime_error(msg.str());
-        }
+        throw std::runtime_error(msg.str());
+      }
 
-      default:
-        if(isdigit(*c) || *c == '-') {
-          bool have_nondigits = false;
-          bool have_digits = false;
-          int have_floating_point = 0;
+    case EOF:
+      return TOKEN_EOF;
 
-          do {
-            if(isdigit(*c))
-              have_digits = true;
-            else if(*c == '.')
-              ++have_floating_point;
-            else if(isalnum(*c) || *c == '_')
-              have_nondigits = true;
+    default:
+      if(isdigit(c) || c == '-') {
+        bool have_nondigits = false;
+        bool have_digits = false;
+        int have_floating_point = 0;
 
-            if(token_length < MAX_TOKEN_LENGTH)
-              token_string[token_length++] = *c;
+        do {
+          if(isdigit(c))
+            have_digits = true;
+          else if(c == '.')
+            ++have_floating_point;
+          else if(isalnum(c) || c == '_')
+            have_nondigits = true;
 
-            nextChar();
-          } while(!isspace(*c) && !strchr(delims, *c));
-
-          token_string[token_length] = 0;
-
-          // no nextChar
-
-          if(have_nondigits || !have_digits || have_floating_point > 1)
-            return TOKEN_SYMBOL;
-          else if(have_floating_point == 1)
-            return TOKEN_REAL;
-          else
-            return TOKEN_INTEGER;
-        } else {
-          do {
-            if(token_length < MAX_TOKEN_LENGTH)
-              token_string[token_length++] = *c;
-            nextChar();
-          } while(!isspace(*c) && !strchr(delims, *c));
-          token_string[token_length] = 0;
+          addChar();
+        } while(!isspace(c) && !strchr(delims, c));
 
-          // no nextChar
+        token_string[token_length] = 0;
 
+        // no nextChar
+
+        if(have_nondigits || !have_digits || have_floating_point > 1)
           return TOKEN_SYMBOL;
-        }
-    }
-  } catch(EOFException& ) {
-    return TOKEN_EOF;
+        else if(have_floating_point == 1)
+          return TOKEN_REAL;
+        else
+          return TOKEN_INTEGER;
+      } else {
+        do {
+          addChar();
+        } while(!isspace(c) && !strchr(delims, c));
+        token_string[token_length] = 0;
+
+        // no nextChar
+
+        return TOKEN_SYMBOL;
+      }
   }
 }
 
 } // end of namespace lisp
+
+/* EOF */