<commit_before>/*
 * Copyright (c) 2003-2010, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "csv.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "journal.h"
#include "pool.h"

namespace ledger {

string csv_reader::read_field(std::istream& sin)
{
  string field;

  char c;
  if (sin.peek() == '"' || sin.peek() == '|') {
    sin.get(c);
    char x;
    while (sin.good() && ! sin.eof()) {
      sin.get(x);
      if (x == '\\') {
        sin.get(x);
      }
      else if (x == '"' && sin.peek() == '"') {
        sin.get(x);
      }
      else if (x == c) {
        if (x == '|')
          sin.unget();
        else if (sin.peek() == ',')
          sin.get(c);
        break;
      }
      if (x != '\0')
        field += x;
    }
  }
  else {
    while (sin.good() && ! sin.eof()) {
      sin.get(c);
      if (c == ',')
        break;
      if (c != '\0')
        field += c;
    }
  }
  trim(field);
  return field;
}

char * csv_reader::next_line(std::istream& sin)
{
  static char linebuf[MAX_LINE + 1];

  while (sin.good() && ! sin.eof() && sin.peek() == '#')
    sin.getline(linebuf, MAX_LINE);

  if (! sin.good() || sin.eof())
    return NULL;

  sin.getline(linebuf, MAX_LINE);

  return linebuf;
}

void csv_reader::read_index(std::istream& sin)
{
  char * line = next_line(sin);
  if (! line)
    return;

  std::istringstream instr(line);

  while (instr.good() && ! instr.eof()) {
    string field = read_field(instr);
    names.push_back(field);

    if (date_mask.match(field))
      index.push_back(FIELD_DATE);
    else if (date_eff_mask.match(field))
      index.push_back(FIELD_DATE_EFF);
    else if (code_mask.match(field))
      index.push_back(FIELD_CODE);
    else if (payee_mask.match(field))
      index.push_back(FIELD_PAYEE);
    else if (amount_mask.match(field))
      index.push_back(FIELD_AMOUNT);
    else if (cost_mask.match(field))
      index.push_back(FIELD_COST);
    else if (total_mask.match(field))
      index.push_back(FIELD_TOTAL);
    else if (note_mask.match(field))
      index.push_back(FIELD_NOTE);
    else
      index.push_back(FIELD_UNKNOWN);

    DEBUG("csv.parse", "Header field: " << field);
  }
}

xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket)
{
 restart:
  char * line = next_line(in);
  if (! line || index.empty())
    return NULL;

  std::istringstream instr(line);

  std::auto_ptr<xact_t> xact(new xact_t);
  std::auto_ptr<post_t> post(new post_t);

  xact->set_state(item_t::CLEARED);

  xact->pos           = position_t();
  xact->pos->pathname = "jww (2010-03-05): unknown";
  xact->pos->beg_pos  = in.tellg();
  xact->pos->beg_line = 0;
  xact->pos->sequence = 0;

  post->xact = xact.get();

#if 0
  post->pos           = position_t();
  post->pos->pathname = pathname;
  post->pos->beg_pos  = line_beg_pos;
  post->pos->beg_line = linenum;
  post->pos->sequence = context.sequence++;
#endif

  post->set_state(item_t::CLEARED);
  post->account = NULL;

  std::vector<int>::size_type n = 0;
  amount_t amt;
  string   total;

  while (instr.good() && ! instr.eof()) {
    string field = read_field(instr);

    switch (index[n]) {
    case FIELD_DATE:
      if (field.empty())
        goto restart;
      try {
        xact->_date = parse_date(field);
      }
      catch (date_error&) {
        goto restart;
      }
      break;

    case FIELD_DATE_EFF:
      xact->_date_eff = parse_date(field);
      break;

    case FIELD_CODE:
      if (! field.empty())
        xact->code = field;
      break;

    case FIELD_PAYEE: {
      bool found = false;
      foreach (payee_mapping_t& value, journal.payee_mappings) {
        DEBUG("csv.mappings", "Looking for payee mapping: " << value.first);
        if (value.first.match(field)) {
          xact->payee = value.second;
          found = true;
          break;
        }
      }
      if (! found)
        xact->payee = field;
      break;
    }

    case FIELD_AMOUNT: {
      std::istringstream amount_str(field);
      amt.parse(amount_str, PARSE_NO_REDUCE);
      if (! amt.has_commodity() &&
          commodity_pool_t::current_pool->default_commodity)
        amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
      post->amount = amt;
      break;
    }

    case FIELD_COST: {
      std::istringstream amount_str(field);
      amt.parse(amount_str, PARSE_NO_REDUCE);
      if (! amt.has_commodity() &&
          commodity_pool_t::current_pool->default_commodity)
        amt.set_commodity
          (*commodity_pool_t::current_pool->default_commodity);
      post->cost = amt;
      break;
    }

    case FIELD_TOTAL:
      total = field;
      break;

    case FIELD_NOTE:
      xact->note = field;
      break;

    case FIELD_UNKNOWN:
      if (! names[n].empty() && ! field.empty())
        xact->set_tag(names[n], string_value(field));
      break;
    }
    n++;
  }

#if 0
  xact->set_tag(_("Imported"),
                string(format_date(CURRENT_DATE(), FMT_WRITTEN)));
  xact->set_tag(_("Original"), string(line));
  xact->set_tag(_("SHA1"), string(sha1sum(line)));
#endif

  // Translate the account name, if we have enough information to do so

  foreach (account_mapping_t& value, journal.account_mappings) {
    if (value.first.match(xact->payee)) {
      post->account = value.second;
      break;
    }
  }

  xact->add_post(post.release());

  // Create the "balancing post", which refers to the account for this data

  post.reset(new post_t);

  post->xact = xact.get();

#if 0
  post->pos           = position_t();
  post->pos->pathname = pathname;
  post->pos->beg_pos  = line_beg_pos;
  post->pos->beg_line = linenum;
  post->pos->sequence = context.sequence++;
#endif

  post->set_state(item_t::CLEARED);
  post->account = bucket;

  if (! amt.is_null())
    post->amount = - amt;

  if (! total.empty()) {
    std::istringstream assigned_amount_str(total);
    amt.parse(assigned_amount_str, PARSE_NO_REDUCE);
    if (! amt.has_commodity() &&
        commodity_pool_t::current_pool->default_commodity)
      amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
    post->assigned_amount = amt;
  }

  xact->add_post(post.release());

  return xact.release();
}

} // namespace ledger
<commit_msg>Make CSV importer more sensitive to errors<commit_after>/*
 * Copyright (c) 2003-2010, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "csv.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "journal.h"
#include "pool.h"

namespace ledger {

string csv_reader::read_field(std::istream& sin)
{
  string field;

  char c;
  if (sin.peek() == '"' || sin.peek() == '|') {
    sin.get(c);
    char x;
    while (sin.good() && ! sin.eof()) {
      sin.get(x);
      if (x == '\\') {
        sin.get(x);
      }
      else if (x == '"' && sin.peek() == '"') {
        sin.get(x);
      }
      else if (x == c) {
        if (x == '|')
          sin.unget();
        else if (sin.peek() == ',')
          sin.get(c);
        break;
      }
      if (x != '\0')
        field += x;
    }
  }
  else {
    while (sin.good() && ! sin.eof()) {
      sin.get(c);
      if (c == ',')
        break;
      if (c != '\0')
        field += c;
    }
  }
  trim(field);
  return field;
}

char * csv_reader::next_line(std::istream& sin)
{
  static char linebuf[MAX_LINE + 1];

  while (sin.good() && ! sin.eof() && sin.peek() == '#')
    sin.getline(linebuf, MAX_LINE);

  if (! sin.good() || sin.eof())
    return NULL;

  sin.getline(linebuf, MAX_LINE);

  return linebuf;
}

void csv_reader::read_index(std::istream& sin)
{
  char * line = next_line(sin);
  if (! line)
    return;

  std::istringstream instr(line);

  while (instr.good() && ! instr.eof()) {
    string field = read_field(instr);
    names.push_back(field);

    if (date_mask.match(field))
      index.push_back(FIELD_DATE);
    else if (date_eff_mask.match(field))
      index.push_back(FIELD_DATE_EFF);
    else if (code_mask.match(field))
      index.push_back(FIELD_CODE);
    else if (payee_mask.match(field))
      index.push_back(FIELD_PAYEE);
    else if (amount_mask.match(field))
      index.push_back(FIELD_AMOUNT);
    else if (cost_mask.match(field))
      index.push_back(FIELD_COST);
    else if (total_mask.match(field))
      index.push_back(FIELD_TOTAL);
    else if (note_mask.match(field))
      index.push_back(FIELD_NOTE);
    else
      index.push_back(FIELD_UNKNOWN);

    DEBUG("csv.parse", "Header field: " << field);
  }
}

xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket)
{
  char * line = next_line(in);
  if (! line || index.empty())
    return NULL;

  std::istringstream instr(line);

  std::auto_ptr<xact_t> xact(new xact_t);
  std::auto_ptr<post_t> post(new post_t);

  xact->set_state(item_t::CLEARED);

  xact->pos           = position_t();
  xact->pos->pathname = "jww (2010-03-05): unknown";
  xact->pos->beg_pos  = in.tellg();
  xact->pos->beg_line = 0;
  xact->pos->sequence = 0;

  post->xact = xact.get();

#if 0
  post->pos           = position_t();
  post->pos->pathname = pathname;
  post->pos->beg_pos  = line_beg_pos;
  post->pos->beg_line = linenum;
  post->pos->sequence = context.sequence++;
#endif

  post->set_state(item_t::CLEARED);
  post->account = NULL;

  std::vector<int>::size_type n = 0;
  amount_t amt;
  string total;
  string field;

  try {
    while (instr.good() && ! instr.eof()) {
      field = read_field(instr);

      switch (index[n]) {
      case FIELD_DATE:
        xact->_date = parse_date(field);
        break;

      case FIELD_DATE_EFF:
        xact->_date_eff = parse_date(field);
        break;

      case FIELD_CODE:
        if (! field.empty())
          xact->code = field;
        break;

      case FIELD_PAYEE: {
        bool found = false;
        foreach (payee_mapping_t& value, journal.payee_mappings) {
          DEBUG("csv.mappings", "Looking for payee mapping: " << value.first);
          if (value.first.match(field)) {
            xact->payee = value.second;
            found = true;
            break;
          }
        }
        if (! found)
          xact->payee = field;
        break;
      }

      case FIELD_AMOUNT: {
        std::istringstream amount_str(field);
        amt.parse(amount_str, PARSE_NO_REDUCE);
        if (! amt.has_commodity() &&
            commodity_pool_t::current_pool->default_commodity)
          amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
        post->amount = amt;
        break;
      }

      case FIELD_COST: {
        std::istringstream amount_str(field);
        amt.parse(amount_str, PARSE_NO_REDUCE);
        if (! amt.has_commodity() &&
            commodity_pool_t::current_pool->default_commodity)
          amt.set_commodity
            (*commodity_pool_t::current_pool->default_commodity);
        post->cost = amt;
        break;
      }

      case FIELD_TOTAL:
        total = field;
        break;

      case FIELD_NOTE:
        xact->note = field;
        break;

      case FIELD_UNKNOWN:
        if (! names[n].empty() && ! field.empty())
          xact->set_tag(names[n], string_value(field));
        break;
      }
      n++;
    }
  }
  catch (const std::exception&) {
    add_error_context(_("While parsing CSV field:"));
    add_error_context(line_context(field));
    throw;
  }

#if 0
  xact->set_tag(_("Imported"),
                string(format_date(CURRENT_DATE(), FMT_WRITTEN)));
  xact->set_tag(_("Original"), string(line));
  xact->set_tag(_("SHA1"), string(sha1sum(line)));
#endif

  // Translate the account name, if we have enough information to do so

  foreach (account_mapping_t& value, journal.account_mappings) {
    if (value.first.match(xact->payee)) {
      post->account = value.second;
      break;
    }
  }

  xact->add_post(post.release());

  // Create the "balancing post", which refers to the account for this data

  post.reset(new post_t);

  post->xact = xact.get();

#if 0
  post->pos           = position_t();
  post->pos->pathname = pathname;
  post->pos->beg_pos  = line_beg_pos;
  post->pos->beg_line = linenum;
  post->pos->sequence = context.sequence++;
#endif

  post->set_state(item_t::CLEARED);
  post->account = bucket;

  if (! amt.is_null())
    post->amount = - amt;

  if (! total.empty()) {
    std::istringstream assigned_amount_str(total);
    amt.parse(assigned_amount_str, PARSE_NO_REDUCE);
    if (! amt.has_commodity() &&
        commodity_pool_t::current_pool->default_commodity)
      amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
    post->assigned_amount = amt;
  }

  xact->add_post(post.release());

  return xact.release();
}

} // namespace ledger
<|endoftext|>


<commit_before>/*
 * This file is part of the Topologic/GL project.
*/

/*
 * Copyright (c) 2012-2013, ef.gy Project Members
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

#ifdef __APPLE__
#include <OpenGL/gl3.h>
#include <GLUT/glut.h>          /* Open GL Util APPLE */
#else
#include <GL/glew.h>
#include <GL/glut.h>            /* FreeGLUT (hopefully) */
#endif

#include <topologic/gl.h>

#if !defined(MAXDEPTH)
#define MAXDEPTH 7
#endif

GLfloat mouseX, mouseY;
GLfloat lastMouseX, lastMouseY;

bool mouseLeft, mouseRight;

topologic::state<topologic::GLFP,MAXDEPTH> topologicState;

void displayCall(void)
{
    if (topologicState.model)
    {
        topologicState.model->render(true);
    }

    glFinish();
    glutSwapBuffers();
    glutPostRedisplay();
}

void reshape(GLint width, GLint height)
{
    glViewport(0, 0, width, height);
    glClearDepth(1.0f);

    glEnable (GL_BLEND);

    glEnable(GL_CULL_FACE);

    topologicState.width  = width;
    topologicState.height = height;
}

void idle(void)
{
    if (mouseLeft || mouseRight)
    {
        glutPostRedisplay();
    }
}

bool shiftActive;

void processMouse(int x, int y)
{
    mouseX = x;
    mouseY = y;

    if (mouseLeft || mouseRight)
    {
        double xd = (mouseX - lastMouseX);
        double yd = (mouseY - lastMouseY);

        if (shiftActive)
        {
            topologicState.interpretDrag(0,0,xd+-yd);
        }
        else
        {
            topologicState.interpretDrag(xd,yd,0);
        }

        lastMouseX = mouseX;
        lastMouseY = mouseY;
    }
}

void processMouseButton(int button, int state, int x, int y)
{
    shiftActive = (glutGetModifiers() & GLUT_ACTIVE_SHIFT);

    processMouse(x,y);

    switch (button)
    {
        case 0:
            mouseLeft = (state == 0);
            break;
        case 2:
            mouseRight = (state == 0);
            break;
        case 3:
            if (state == 0)
            {
                topologicState.interpretDrag(0,0,30);
            }
            break;
        case 4:
            if (state == 0)
            {
                topologicState.interpretDrag(0,0,-30);
            }
            break;
    }

    if (mouseLeft || mouseRight)
    {
        lastMouseX = mouseX;
        lastMouseY = mouseY;
    }
}

void processKeyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
        case '1': topologicState.setActive ( 3); break;
        case '2': topologicState.setActive ( 4); break;
        case '3': topologicState.setActive ( 5); break;
        case '4': topologicState.setActive ( 6); break;
        case '5': topologicState.setActive ( 7); break;
        case '6': topologicState.setActive ( 8); break;
        case '7': topologicState.setActive ( 9); break;
        case '8': topologicState.setActive (10); break;
        case '9': topologicState.setActive (11); break;
        case '0': topologicState.setActive (12); break;
        case 'r':
            topologicState.realign();
            glutPostRedisplay();
            break;
    }
}

int main (int argc, char* argv[])
{
    try
    {
        if (!topologic::parseArguments (topologicState, argc, argv, topologic::outGL))
        {
            return 1;
        }

        if (!topologicState.model)
        {
            std::cerr << "error: no model to render\n";
        }
        else
        {
            glutInit(&argc, argv);
            glutInitWindowSize(1280, 720);

#ifdef __APPLE__
	        glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
#else
#if defined(GLUT_CORE_PROFILE)
	        glutInitContextVersion(3, 2);
	        glutInitContextProfile(GLUT_CORE_PROFILE);
#endif
	        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
#endif
            glutCreateWindow("Topologic/GLUT");
#ifndef __APPLE__
            glewInit();
#endif

            glutDisplayFunc (displayCall);
            glutIdleFunc(idle);
            glutReshapeFunc (reshape);
            glutMouseFunc(processMouseButton);
            glutMotionFunc(processMouse);
            glutPassiveMotionFunc(processMouse);
            glutKeyboardFunc(processKeyboard);
            glutFullScreen();

            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_NORMAL_ARRAY);

            glutMainLoop();
        }
    }
    catch (std::exception &e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
        return 1;
    }
    catch (...)
    {
        std::cerr << "Unknown Exception\n";
        return 1;
    }

    return 0;
}
<commit_msg>don't need this, probably<commit_after>/*
 * This file is part of the Topologic/GL project.
*/

/*
 * Copyright (c) 2012-2013, ef.gy Project Members
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
*/

#ifdef __APPLE__
#include <OpenGL/gl3.h>
#include <GLUT/glut.h>          /* Open GL Util APPLE */
#else
#include <GL/glew.h>
#include <GL/glut.h>            /* FreeGLUT (hopefully) */
#endif

#include <topologic/gl.h>

#if !defined(MAXDEPTH)
#define MAXDEPTH 7
#endif

GLfloat mouseX, mouseY;
GLfloat lastMouseX, lastMouseY;

bool mouseLeft, mouseRight;

topologic::state<topologic::GLFP,MAXDEPTH> topologicState;

void displayCall(void)
{
    if (topologicState.model)
    {
        topologicState.model->render(true);
    }

    glFinish();
    glutSwapBuffers();
    glutPostRedisplay();
}

void reshape(GLint width, GLint height)
{
    glViewport(0, 0, width, height);
    glClearDepth(1.0f);

    glEnable (GL_BLEND);

    glEnable(GL_CULL_FACE);

    topologicState.width  = width;
    topologicState.height = height;
}

void idle(void)
{
    if (mouseLeft || mouseRight)
    {
        glutPostRedisplay();
    }
}

bool shiftActive;

void processMouse(int x, int y)
{
    mouseX = x;
    mouseY = y;

    if (mouseLeft || mouseRight)
    {
        double xd = (mouseX - lastMouseX);
        double yd = (mouseY - lastMouseY);

        if (shiftActive)
        {
            topologicState.interpretDrag(0,0,xd+-yd);
        }
        else
        {
            topologicState.interpretDrag(xd,yd,0);
        }

        lastMouseX = mouseX;
        lastMouseY = mouseY;
    }
}

void processMouseButton(int button, int state, int x, int y)
{
    shiftActive = (glutGetModifiers() & GLUT_ACTIVE_SHIFT);

    processMouse(x,y);

    switch (button)
    {
        case 0:
            mouseLeft = (state == 0);
            break;
        case 2:
            mouseRight = (state == 0);
            break;
        case 3:
            if (state == 0)
            {
                topologicState.interpretDrag(0,0,30);
            }
            break;
        case 4:
            if (state == 0)
            {
                topologicState.interpretDrag(0,0,-30);
            }
            break;
    }

    if (mouseLeft || mouseRight)
    {
        lastMouseX = mouseX;
        lastMouseY = mouseY;
    }
}

void processKeyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
        case '1': topologicState.setActive ( 3); break;
        case '2': topologicState.setActive ( 4); break;
        case '3': topologicState.setActive ( 5); break;
        case '4': topologicState.setActive ( 6); break;
        case '5': topologicState.setActive ( 7); break;
        case '6': topologicState.setActive ( 8); break;
        case '7': topologicState.setActive ( 9); break;
        case '8': topologicState.setActive (10); break;
        case '9': topologicState.setActive (11); break;
        case '0': topologicState.setActive (12); break;
        case 'r':
            topologicState.realign();
            glutPostRedisplay();
            break;
    }
}

int main (int argc, char* argv[])
{
    try
    {
        if (!topologic::parseArguments (topologicState, argc, argv, topologic::outGL))
        {
            return 1;
        }

        if (!topologicState.model)
        {
            std::cerr << "error: no model to render\n";
        }
        else
        {
            glutInit(&argc, argv);
            glutInitWindowSize(1280, 720);

#ifdef __APPLE__
	        glutInitDisplayMode(GLUT_3_2_CORE_PROFILE | GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
#else
#if defined(GLUT_CORE_PROFILE)
	        glutInitContextVersion(3, 2);
	        glutInitContextProfile(GLUT_CORE_PROFILE);
#endif
	        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
#endif
            glutCreateWindow("Topologic/GLUT");
#ifndef __APPLE__
            glewInit();
#endif

            glutDisplayFunc (displayCall);
            glutIdleFunc(idle);
            glutReshapeFunc (reshape);
            glutMouseFunc(processMouseButton);
            glutMotionFunc(processMouse);
            glutPassiveMotionFunc(processMouse);
            glutKeyboardFunc(processKeyboard);
            glutFullScreen();

            glutMainLoop();
        }
    }
    catch (std::exception &e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
        return 1;
    }
    catch (...)
    {
        std::cerr << "Unknown Exception\n";
        return 1;
    }

    return 0;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// logDetail.cpp : Plugin module for logging server events to stdout
//

#include <iostream>
#include <sstream>
#include "bzfsAPI.h"
#include "plugin_utils.h"

BZ_GET_PLUGIN_VERSION

enum action {join , auth , part};

class LogDetail:public bz_EventHandler
{
public:
  LogDetail();
  virtual ~LogDetail();
  virtual void process(bz_EventData *eventData);
private:
  std::string displayPlayerPrivs(const int playerID);
  std::string displayCallsign(const bz_ApiString &callsign);
  std::string displayCallsign(const int playerID);
  std::string displayBZid(const int playerID);
  std::string displayTeam(const bz_eTeamType team);
  virtual void listPlayers(action act, bz_PlayerJoinPartEventData_V1 *data);
};

LogDetail logDetailHandler;

BZF_PLUGIN_CALL int bz_Load(const char * /*commandLine */ )
{
  bz_registerEvent(bz_eSlashCommandEvent, &logDetailHandler);
  bz_registerEvent(bz_eRawChatMessageEvent, &logDetailHandler);
  bz_registerEvent(bz_eServerMsgEvent, &logDetailHandler);
  bz_registerEvent(bz_ePlayerJoinEvent, &logDetailHandler);
  bz_registerEvent(bz_ePlayerPartEvent, &logDetailHandler);
  bz_registerEvent(bz_ePlayerAuthEvent, &logDetailHandler);
  bz_registerEvent(bz_eMessageFilteredEvent, &logDetailHandler);
  bz_debugMessage(4, "logDetail plugin loaded");
  return 0;
}

BZF_PLUGIN_CALL int bz_Unload(void)
{
  bz_removeEvent(bz_eSlashCommandEvent, &logDetailHandler);
  bz_removeEvent(bz_eRawChatMessageEvent, &logDetailHandler);
  bz_removeEvent(bz_eServerMsgEvent, &logDetailHandler);
  bz_removeEvent(bz_ePlayerJoinEvent, &logDetailHandler);
  bz_removeEvent(bz_ePlayerPartEvent, &logDetailHandler);
  bz_removeEvent(bz_ePlayerAuthEvent, &logDetailHandler);
  bz_removeEvent(bz_eMessageFilteredEvent, &logDetailHandler);
  bz_debugMessage(4, "logDetail plugin unloaded");
  return 0;
}

LogDetail::LogDetail()
{
  bz_debugMessage(0, "SERVER-STATUS Running");
  bz_debugMessagef(0, "SERVER-MAPNAME %s", bz_getPublicDescription().c_str());
  listPlayers(join, NULL);
}

LogDetail::~LogDetail()
{
  listPlayers(part, NULL);
  bz_debugMessage(0, "SERVER-STATUS Stopped");
}

void LogDetail::process(bz_EventData *eventData)
{
  bz_ChatEventData_V1 *chatData = (bz_ChatEventData_V1 *) eventData;
  bz_ServerMsgEventData_V1 *serverMsgData = (bz_ServerMsgEventData_V1 *) eventData;
  bz_SlashCommandEventData_V1 *cmdData = (bz_SlashCommandEventData_V1 *) eventData;
  bz_PlayerJoinPartEventData_V1 *joinPartData = (bz_PlayerJoinPartEventData_V1 *) eventData;
  bz_PlayerAuthEventData_V1 *authData = (bz_PlayerAuthEventData_V1 *) eventData;
  bz_MessageFilteredEventData_V1 *filteredData = (bz_MessageFilteredEventData_V1 *) eventData;
  char temp[9] = { 0 };
  std::string bzID;
  std::string callsign, callsign2;
  std::string team;
  std::string playerPrivs;

  if (eventData) {
    switch (eventData->eventType) {
    case bz_eSlashCommandEvent:
      // Slash commands are case insensitive
      // Tokenize the stream and check the first word
      // /report -> MSG-REPORT
      // anything -> MSG-COMMAND

      strncpy(temp, cmdData->message.c_str(), 8);

      callsign = displayCallsign(cmdData->from);
      if (strcasecmp(temp, "/REPORT ") == 0) {
	bz_debugMessagef(0, "MSG-REPORT %s %s",
			 callsign.c_str(),
			 cmdData->message.c_str()+8);
      } else {
	bz_debugMessagef(0, "MSG-COMMAND %s %s",
			 callsign.c_str(),
			 cmdData->message.c_str()+1);
      }
      break;
    case bz_eRawChatMessageEvent:
      callsign = displayCallsign(chatData->from);
      team = displayTeam(chatData->team);

      if ((chatData->to == BZ_ALLUSERS) && (chatData->team == eNoTeam)) {
	bz_debugMessagef(0, "MSG-BROADCAST %s %s",
			 callsign.c_str(),
			 chatData->message.c_str());
      } else if (chatData->to == BZ_NULLUSER) {
	if (chatData->team == eAdministrators) {
	  bz_debugMessagef(0, "MSG-ADMIN %s %s",
			   callsign.c_str(),
			   chatData->message.c_str());
	} else {
	  bz_debugMessagef(0, "MSG-TEAM %s %s %s",
			   callsign.c_str(),
			   team.c_str(),
			   chatData->message.c_str());
	}
      } else {
	  bz_debugMessagef(0, "MSG-DIRECT %s %s %s",
			   callsign.c_str(),
			   displayCallsign(chatData->to).c_str(),
			   chatData->message.c_str());
      }
      break;
    case bz_eMessageFilteredEvent:
      callsign = displayCallsign(filteredData->playerID);
      bz_debugMessagef(0, "MSG-FILTERED %s %s",
		       callsign.c_str(),
		       filteredData->filteredMessage.c_str());
      break;
    case bz_eServerMsgEvent:
      if ((serverMsgData->to == BZ_ALLUSERS) && (serverMsgData->team == eNoTeam)) {
	bz_debugMessagef(0, "MSG-BROADCAST 6:SERVER %s",
			 serverMsgData->message.c_str());
      } else if (serverMsgData->to == BZ_NULLUSER) {
	if (serverMsgData->team == eAdministrators) {
	  bz_debugMessagef(0, "MSG-ADMIN 6:SERVER %s",
			   serverMsgData->message.c_str());
	} else {
	  team = displayTeam(serverMsgData->team);
	  bz_debugMessagef(0, "MSG-TEAM 6:SERVER %s %s",
			   team.c_str(),
			   serverMsgData->message.c_str());
	}
      } else {
	callsign = displayCallsign(serverMsgData->to);
	bz_debugMessagef(0, "MSG-DIRECT 6:SERVER %s %s",
			 callsign.c_str(),
			 serverMsgData->message.c_str());
      }
      break;
    case bz_ePlayerJoinEvent:
      {
	if (joinPartData->record) {
	  bzID = displayBZid(joinPartData->playerID);
	  callsign = displayCallsign(joinPartData->record->callsign);
	  team = displayTeam(joinPartData->record->team);
	  playerPrivs = displayPlayerPrivs(joinPartData->playerID);
	  bz_debugMessagef(0, "PLAYER-JOIN %s #%d%s %s %s",
			   callsign.c_str(),
			   joinPartData->playerID,
			   bzID.c_str(),
			   team.c_str(),
			   playerPrivs.c_str());
	  listPlayers(join, joinPartData);
	}
      }
      break;
    case bz_ePlayerPartEvent:
      callsign = displayCallsign(joinPartData->playerID);
      bzID = displayBZid(joinPartData->playerID);
      bz_debugMessagef(0, "PLAYER-PART %s #%d%s %s",
		       callsign.c_str(),
		       joinPartData->playerID,
		       bzID.c_str(),
		       joinPartData->reason.c_str());
      listPlayers(part, joinPartData);
      break;
    case bz_ePlayerAuthEvent:
      callsign = displayCallsign(authData->playerID);
      playerPrivs = displayPlayerPrivs(authData->playerID);
      bz_debugMessagef(0, "PLAYER-AUTH %s %s",
		       callsign.c_str(),
		       playerPrivs.c_str());
      listPlayers(join, joinPartData);
      break;
    default:
      break;
    }
  }
}

std::string LogDetail::displayBZid(const int playerID)
{
  std::ostringstream bzid;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
  if (player) {
    if (player->globalUser)
      bzid << " BZid:" << player->bzID.c_str();
    bz_freePlayerRecord( player );
  }

  return bzid.str();
}

std::string LogDetail::displayPlayerPrivs(const int playerID)
{
  std::ostringstream playerPrivs;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
  if (player) {
    playerPrivs << "IP:" << player->ipAddress.c_str();
    if (player->verified) playerPrivs << " VERIFIED";
    if (player->globalUser) playerPrivs << " GLOBALUSER";
    if (player->admin) playerPrivs << " ADMIN";
    if (player->op) playerPrivs << " OPERATOR";
    bz_freePlayerRecord(player);
  } else {
    playerPrivs << "IP:0.0.0.0";
  }

  return playerPrivs.str();
}

std::string LogDetail::displayCallsign(const bz_ApiString &callsign)
{
  std::ostringstream result;

  result << (unsigned int)strlen(callsign.c_str()) << ":" << callsign.c_str();

  return result.str();
}

std::string LogDetail::displayCallsign(const int playerID)
{
  std::ostringstream callsign;
  bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
  if (player) {
    callsign << (unsigned int)strlen(player->callsign.c_str()) << ":";
    callsign << player->callsign.c_str();
    bz_freePlayerRecord(player);
  } else {
    callsign << "7:UNKNOWN";
  }
  return callsign.str();
}

std::string LogDetail::displayTeam(const bz_eTeamType team)
{
  std::string name = bzu_GetTeamName(team);
  makeupper(name);
  return name;
}

void LogDetail::listPlayers(action act, bz_PlayerJoinPartEventData_V1 * data)
{
  bz_APIIntList *playerList = bz_newIntList();
  bz_BasePlayerRecord *player;
  std::ostringstream msg;
  char playerStatus;
  int numPlayers;

  bz_getPlayerIndexList(playerList);

  bz_debugMessage(4, "Players:");
  //
  // Count number of players
  //
  numPlayers = 0;
  for (unsigned int i = 0; i < playerList->size(); i++) {
    player = bz_getPlayerByIndex(playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID))))
	numPlayers++;
      bz_freePlayerRecord(player);
    }
  }

  //
  // Display number of players and callsign in the following format:
  //
  // PLAYERS (nn) [G]cc:callsign
  // nn - number of players
  // G  - global auth identifier (+|-| |@)
  // cc - count of characters in player callsign
  // callsign - player callsign
  //
  // eg.
  // PLAYERS (2) [@]7:Thumper() [ ]3:xxx()
  // Extra data goes in between the parenthesis (currently empty)
  //
  msg.str("");
  msg << "PLAYERS (" << numPlayers << ") ";
  for (unsigned int i = 0; i < playerList->size(); i++) {
    player = bz_getPlayerByIndex(playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID)))) {
	playerStatus = ' ';
	if (player->globalUser)
	  playerStatus = '+';
	if (player->verified)
	  playerStatus = '+';
	if (player->admin && ! bz_hasPerm(player->playerID, bz_perm_hideAdmin))
	  playerStatus = '@';
	msg << "[" << playerStatus << "]";
	msg << player->callsign.size() << ':';
	msg << player->callsign.c_str();
	msg << "() ";
      }
      bz_freePlayerRecord(player);
    }
  }
  bz_debugMessage(0, msg.str().c_str());

  bz_deleteIntList(playerList);
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Add support for callsign display of server generated messages<commit_after>/* bzflag
 * Copyright (c) 1993 - 2009 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

// logDetail.cpp : Plugin module for logging server events to stdout
//

#include <iostream>
#include <sstream>
#include "bzfsAPI.h"
#include "plugin_utils.h"

BZ_GET_PLUGIN_VERSION

enum action {join , auth , part};

class LogDetail:public bz_EventHandler
{
public:
  LogDetail();
  virtual ~LogDetail();
  virtual void process(bz_EventData *eventData);
private:
  std::string displayPlayerPrivs(const int playerID);
  std::string displayCallsign(const bz_ApiString &callsign);
  std::string displayCallsign(const int playerID);
  std::string displayBZid(const int playerID);
  std::string displayTeam(const bz_eTeamType team);
  virtual void listPlayers(action act, bz_PlayerJoinPartEventData_V1 *data);
};

LogDetail logDetailHandler;

BZF_PLUGIN_CALL int bz_Load(const char * /*commandLine */ )
{
  bz_registerEvent(bz_eSlashCommandEvent, &logDetailHandler);
  bz_registerEvent(bz_eRawChatMessageEvent, &logDetailHandler);
  bz_registerEvent(bz_eServerMsgEvent, &logDetailHandler);
  bz_registerEvent(bz_ePlayerJoinEvent, &logDetailHandler);
  bz_registerEvent(bz_ePlayerPartEvent, &logDetailHandler);
  bz_registerEvent(bz_ePlayerAuthEvent, &logDetailHandler);
  bz_registerEvent(bz_eMessageFilteredEvent, &logDetailHandler);
  bz_debugMessage(4, "logDetail plugin loaded");
  return 0;
}

BZF_PLUGIN_CALL int bz_Unload(void)
{
  bz_removeEvent(bz_eSlashCommandEvent, &logDetailHandler);
  bz_removeEvent(bz_eRawChatMessageEvent, &logDetailHandler);
  bz_removeEvent(bz_eServerMsgEvent, &logDetailHandler);
  bz_removeEvent(bz_ePlayerJoinEvent, &logDetailHandler);
  bz_removeEvent(bz_ePlayerPartEvent, &logDetailHandler);
  bz_removeEvent(bz_ePlayerAuthEvent, &logDetailHandler);
  bz_removeEvent(bz_eMessageFilteredEvent, &logDetailHandler);
  bz_debugMessage(4, "logDetail plugin unloaded");
  return 0;
}

LogDetail::LogDetail()
{
  bz_debugMessage(0, "SERVER-STATUS Running");
  bz_debugMessagef(0, "SERVER-MAPNAME %s", bz_getPublicDescription().c_str());
  listPlayers(join, NULL);
}

LogDetail::~LogDetail()
{
  listPlayers(part, NULL);
  bz_debugMessage(0, "SERVER-STATUS Stopped");
}

void LogDetail::process(bz_EventData *eventData)
{
  bz_ChatEventData_V1 *chatData = (bz_ChatEventData_V1 *) eventData;
  bz_ServerMsgEventData_V1 *serverMsgData = (bz_ServerMsgEventData_V1 *) eventData;
  bz_SlashCommandEventData_V1 *cmdData = (bz_SlashCommandEventData_V1 *) eventData;
  bz_PlayerJoinPartEventData_V1 *joinPartData = (bz_PlayerJoinPartEventData_V1 *) eventData;
  bz_PlayerAuthEventData_V1 *authData = (bz_PlayerAuthEventData_V1 *) eventData;
  bz_MessageFilteredEventData_V1 *filteredData = (bz_MessageFilteredEventData_V1 *) eventData;
  char temp[9] = { 0 };
  std::string bzID;
  std::string callsign, callsign2;
  std::string team;
  std::string playerPrivs;

  if (eventData) {
    switch (eventData->eventType) {
    case bz_eSlashCommandEvent:
      // Slash commands are case insensitive
      // Tokenize the stream and check the first word
      // /report -> MSG-REPORT
      // anything -> MSG-COMMAND

      strncpy(temp, cmdData->message.c_str(), 8);

      callsign = displayCallsign(cmdData->from);
      if (strcasecmp(temp, "/REPORT ") == 0) {
	bz_debugMessagef(0, "MSG-REPORT %s %s",
			 callsign.c_str(),
			 cmdData->message.c_str()+8);
      } else {
	bz_debugMessagef(0, "MSG-COMMAND %s %s",
			 callsign.c_str(),
			 cmdData->message.c_str()+1);
      }
      break;
    case bz_eRawChatMessageEvent:
      callsign = displayCallsign(chatData->from);
      team = displayTeam(chatData->team);

      if ((chatData->to == BZ_ALLUSERS) && (chatData->team == eNoTeam)) {
	bz_debugMessagef(0, "MSG-BROADCAST %s %s",
			 callsign.c_str(),
			 chatData->message.c_str());
      } else if (chatData->to == BZ_NULLUSER) {
	if (chatData->team == eAdministrators) {
	  bz_debugMessagef(0, "MSG-ADMIN %s %s",
			   callsign.c_str(),
			   chatData->message.c_str());
	} else {
	  bz_debugMessagef(0, "MSG-TEAM %s %s %s",
			   callsign.c_str(),
			   team.c_str(),
			   chatData->message.c_str());
	}
      } else {
	  bz_debugMessagef(0, "MSG-DIRECT %s %s %s",
			   callsign.c_str(),
			   displayCallsign(chatData->to).c_str(),
			   chatData->message.c_str());
      }
      break;
    case bz_eMessageFilteredEvent:
      callsign = displayCallsign(filteredData->playerID);
      bz_debugMessagef(0, "MSG-FILTERED %s %s",
		       callsign.c_str(),
		       filteredData->filteredMessage.c_str());
      break;
    case bz_eServerMsgEvent:
      if ((serverMsgData->to == BZ_ALLUSERS) && (serverMsgData->team == eNoTeam)) {
	bz_debugMessagef(0, "MSG-BROADCAST 6:SERVER %s",
			 serverMsgData->message.c_str());
      } else if (serverMsgData->to == BZ_NULLUSER) {
	if (serverMsgData->team == eAdministrators) {
	  bz_debugMessagef(0, "MSG-ADMIN 6:SERVER %s",
			   serverMsgData->message.c_str());
	} else {
	  team = displayTeam(serverMsgData->team);
	  bz_debugMessagef(0, "MSG-TEAM 6:SERVER %s %s",
			   team.c_str(),
			   serverMsgData->message.c_str());
	}
      } else {
	callsign = displayCallsign(serverMsgData->to);
	bz_debugMessagef(0, "MSG-DIRECT 6:SERVER %s %s",
			 callsign.c_str(),
			 serverMsgData->message.c_str());
      }
      break;
    case bz_ePlayerJoinEvent:
      {
	if (joinPartData->record) {
	  bzID = displayBZid(joinPartData->playerID);
	  callsign = displayCallsign(joinPartData->record->callsign);
	  team = displayTeam(joinPartData->record->team);
	  playerPrivs = displayPlayerPrivs(joinPartData->playerID);
	  bz_debugMessagef(0, "PLAYER-JOIN %s #%d%s %s %s",
			   callsign.c_str(),
			   joinPartData->playerID,
			   bzID.c_str(),
			   team.c_str(),
			   playerPrivs.c_str());
	  listPlayers(join, joinPartData);
	}
      }
      break;
    case bz_ePlayerPartEvent:
      callsign = displayCallsign(joinPartData->playerID);
      bzID = displayBZid(joinPartData->playerID);
      bz_debugMessagef(0, "PLAYER-PART %s #%d%s %s",
		       callsign.c_str(),
		       joinPartData->playerID,
		       bzID.c_str(),
		       joinPartData->reason.c_str());
      listPlayers(part, joinPartData);
      break;
    case bz_ePlayerAuthEvent:
      callsign = displayCallsign(authData->playerID);
      playerPrivs = displayPlayerPrivs(authData->playerID);
      bz_debugMessagef(0, "PLAYER-AUTH %s %s",
		       callsign.c_str(),
		       playerPrivs.c_str());
      listPlayers(join, joinPartData);
      break;
    default:
      break;
    }
  }
}

std::string LogDetail::displayBZid(const int playerID)
{
  std::ostringstream bzid;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
  if (player) {
    if (player->globalUser)
      bzid << " BZid:" << player->bzID.c_str();
    bz_freePlayerRecord( player );
  }

  return bzid.str();
}

std::string LogDetail::displayPlayerPrivs(const int playerID)
{
  std::ostringstream playerPrivs;

  bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
  if (player) {
    playerPrivs << "IP:" << player->ipAddress.c_str();
    if (player->verified) playerPrivs << " VERIFIED";
    if (player->globalUser) playerPrivs << " GLOBALUSER";
    if (player->admin) playerPrivs << " ADMIN";
    if (player->op) playerPrivs << " OPERATOR";
    bz_freePlayerRecord(player);
  } else {
    playerPrivs << "IP:0.0.0.0";
  }

  return playerPrivs.str();
}

std::string LogDetail::displayCallsign(const bz_ApiString &callsign)
{
  std::ostringstream result;

  result << (unsigned int)strlen(callsign.c_str()) << ":" << callsign.c_str();

  return result.str();
}

std::string LogDetail::displayCallsign(const int playerID)
{
  std::ostringstream callsign;

  if (playerID == BZ_SERVER) {
    callsign << "6:SERVER";
  } else {
    bz_BasePlayerRecord *player = bz_getPlayerByIndex(playerID);
    if (player) {
      callsign << (unsigned int)strlen(player->callsign.c_str()) << ":";
      callsign << player->callsign.c_str();
      bz_freePlayerRecord(player);
    } else {
      callsign << "7:UNKNOWN";
    }
  }
  return callsign.str();
}

std::string LogDetail::displayTeam(const bz_eTeamType team)
{
  std::string name = bzu_GetTeamName(team);
  makeupper(name);
  return name;
}

void LogDetail::listPlayers(action act, bz_PlayerJoinPartEventData_V1 * data)
{
  bz_APIIntList *playerList = bz_newIntList();
  bz_BasePlayerRecord *player;
  std::ostringstream msg;
  char playerStatus;
  int numPlayers;

  bz_getPlayerIndexList(playerList);

  bz_debugMessage(4, "Players:");
  //
  // Count number of players
  //
  numPlayers = 0;
  for (unsigned int i = 0; i < playerList->size(); i++) {
    player = bz_getPlayerByIndex(playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID))))
	numPlayers++;
      bz_freePlayerRecord(player);
    }
  }

  //
  // Display number of players and callsign in the following format:
  //
  // PLAYERS (nn) [G]cc:callsign
  // nn - number of players
  // G  - global auth identifier (+|-| |@)
  // cc - count of characters in player callsign
  // callsign - player callsign
  //
  // eg.
  // PLAYERS (2) [@]7:Thumper() [ ]3:xxx()
  // Extra data goes in between the parenthesis (currently empty)
  //
  msg.str("");
  msg << "PLAYERS (" << numPlayers << ") ";
  for (unsigned int i = 0; i < playerList->size(); i++) {
    player = bz_getPlayerByIndex(playerList->get(i));
    if (player) {
      if ((player->callsign != "") && (act == join || act == auth || (data && (player->playerID != data->playerID)))) {
	playerStatus = ' ';
	if (player->globalUser)
	  playerStatus = '+';
	if (player->verified)
	  playerStatus = '+';
	if (player->admin && ! bz_hasPerm(player->playerID, bz_perm_hideAdmin))
	  playerStatus = '@';
	msg << "[" << playerStatus << "]";
	msg << player->callsign.size() << ':';
	msg << player->callsign.c_str();
	msg << "() ";
      }
      bz_freePlayerRecord(player);
    }
  }
  bz_debugMessage(0, msg.str().c_str());

  bz_deleteIntList(playerList);
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/*
 *  VHDL code generation for expressions.
 *
 *  Copyright (C) 2008  Nick Gasson (nick@nickg.me.uk)
 *
 *  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 distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  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.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "vhdl_target.h"

#include <iostream>
#include <cassert>

/*
 * Convert a constant Verilog string to a constant VHDL string.
 */
static vhdl_expr *translate_string(ivl_expr_t e)
{
   // TODO: May need to inspect or escape parts of this
   const char *str = ivl_expr_string(e);
   return new vhdl_const_string(str);
}

/*
 * A reference to a signal in an expression. It's assumed that the
 * signal has already been defined elsewhere.
 */
static vhdl_var_ref *translate_signal(ivl_expr_t e)
{
   ivl_signal_t sig = ivl_expr_signal(e);

   const vhdl_scope *scope = find_scope_for_signal(sig);
   assert(scope);

   const char *renamed = get_renamed_signal(sig).c_str();

   const vhdl_decl *decl = scope->get_decl(strip_var(renamed));
   assert(decl);

   vhdl_type *type = new vhdl_type(*decl->get_type());

   return new vhdl_var_ref(renamed, type);
}

/*
 * A numeric literal ends up as std_logic bit string.
 */
static vhdl_expr *translate_number(ivl_expr_t e)
{
   return new vhdl_const_bits(ivl_expr_bits(e), ivl_expr_width(e),
                              ivl_expr_signed(e) != 0);
}

static vhdl_expr *translate_unary(ivl_expr_t e)
{
   vhdl_expr *operand = translate_expr(ivl_expr_oper1(e));
   if (NULL == operand)
      return NULL;

   char opcode = ivl_expr_opcode(e);
   switch (opcode) {
   case '!':
   case '~':
      return new vhdl_unaryop_expr
         (VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type()));
   case 'N':   // NOR
   case '|':
      {
         vhdl_fcall *f = new vhdl_fcall("Reduce_OR", vhdl_type::std_logic());
         f->add_expr(operand);
         if ('N' == opcode)
            return new vhdl_unaryop_expr(VHDL_UNARYOP_NOT, f, vhdl_type::std_logic());
         else
            return f;
      }
   default:
      error("No translation for unary opcode '%c'\n",
            ivl_expr_opcode(e));
      delete operand;
      return NULL;
   }
}

/*
 * Translate a numeric binary operator (+, -, etc.) to
 * a VHDL equivalent using the numeric_std package.
 */
static vhdl_expr *translate_numeric(vhdl_expr *lhs, vhdl_expr *rhs,
                                    vhdl_binop_t op)
{
   // May need to make either side Boolean for operators
   // to work
   vhdl_type boolean(VHDL_TYPE_BOOLEAN);
   if (lhs->get_type()->get_name() == VHDL_TYPE_BOOLEAN)
      rhs = rhs->cast(&boolean);
   else if (rhs->get_type()->get_name() == VHDL_TYPE_BOOLEAN)
      lhs = lhs->cast(&boolean);

   vhdl_type *rtype = new vhdl_type(*lhs->get_type());
   return new vhdl_binop_expr(lhs, op, rhs, rtype);
}

static vhdl_expr *translate_relation(vhdl_expr *lhs, vhdl_expr *rhs,
                                     vhdl_binop_t op)
{
   // Generate any necessary casts
   // Arbitrarily, the RHS is casted to the type of the LHS
   vhdl_expr *r_cast = rhs->cast(lhs->get_type());

   return new vhdl_binop_expr(lhs, op, r_cast, vhdl_type::boolean());
}

/*
 * Like translate_relation but both operands must be Boolean.
 */
static vhdl_expr *translate_logical(vhdl_expr *lhs, vhdl_expr *rhs,
                                    vhdl_binop_t op)
{
   vhdl_type boolean(VHDL_TYPE_BOOLEAN);

   return translate_relation(lhs->cast(&boolean), rhs->cast(&boolean), op);
}

static vhdl_expr *translate_shift(vhdl_expr *lhs, vhdl_expr *rhs,
                                  vhdl_binop_t op)
{
   // The RHS must be an integer
   vhdl_type integer(VHDL_TYPE_INTEGER);
   vhdl_expr *r_cast = rhs->cast(&integer);

   vhdl_type *rtype = new vhdl_type(*lhs->get_type());
   return new vhdl_binop_expr(lhs, op, r_cast, rtype);
}

static vhdl_expr *translate_binary(ivl_expr_t e)
{
   vhdl_expr *lhs = translate_expr(ivl_expr_oper1(e));
   if (NULL == lhs)
      return NULL;

   vhdl_expr *rhs = translate_expr(ivl_expr_oper2(e));
   if (NULL == rhs)
      return NULL;

   int lwidth = lhs->get_type()->get_width();
   int rwidth = rhs->get_type()->get_width();

   std::cout << "opwidth = " << ivl_expr_width(e)
             << " lwidth = " << lwidth
             << " rwidth = " << rwidth << std::endl;

   // May need to resize the left or right hand side
   /*if (lwidth < rwidth) {
      lhs = lhs->cast(rhs->get_type());
   }
   else if (rwidth < lwidth) {
      rhs = rhs->cast(lhs->get_type());
      }*/

   int result_width = ivl_expr_width(e);

   // For === and !== we need to compare std_logic_vectors
   // rather than signeds
   vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0);
   bool vectorop =
      (lhs->get_type()->get_name() == VHDL_TYPE_SIGNED
       || lhs->get_type()->get_name() == VHDL_TYPE_UNSIGNED) &&
      (rhs->get_type()->get_name() == VHDL_TYPE_SIGNED
       || rhs->get_type()->get_name() == VHDL_TYPE_UNSIGNED);

   switch (ivl_expr_opcode(e)) {
   case '+':
      return translate_numeric(lhs, rhs, VHDL_BINOP_ADD);
   case '-':
      return translate_numeric(lhs, rhs, VHDL_BINOP_SUB);
   case '*':
      return translate_numeric(lhs, rhs, VHDL_BINOP_MULT);
   case 'e':
      return translate_relation(lhs, rhs, VHDL_BINOP_EQ);
   case 'E':
      if (vectorop)
         return translate_relation(lhs->cast(&std_logic_vector),
                                   rhs->cast(&std_logic_vector), VHDL_BINOP_EQ);
      else
         return translate_relation(lhs, rhs, VHDL_BINOP_EQ);
   case 'n':
      return translate_relation(lhs, rhs, VHDL_BINOP_NEQ);
   case 'N':
      if (vectorop)
         return translate_relation(lhs->cast(&std_logic_vector),
                                   rhs->cast(&std_logic_vector), VHDL_BINOP_NEQ);
      else
         return translate_relation(lhs, rhs, VHDL_BINOP_NEQ);
   case '&':    // Bitwise AND
      return translate_numeric(lhs, rhs, VHDL_BINOP_AND);
   case 'a':    // Logical AND
      return translate_logical(lhs, rhs, VHDL_BINOP_AND);
   case '|':    // Bitwise OR
      return translate_numeric(lhs, rhs, VHDL_BINOP_OR);
   case 'o':    // Logical OR
      return translate_logical(lhs, rhs, VHDL_BINOP_OR);
   case '<':
      return translate_relation(lhs, rhs, VHDL_BINOP_LT);
   case 'L':
      return translate_relation(lhs, rhs, VHDL_BINOP_LEQ);
   case '>':
      return translate_relation(lhs, rhs, VHDL_BINOP_GT);
   case 'G':
      return translate_relation(lhs, rhs, VHDL_BINOP_GEQ);
   case 'l':
      return translate_shift(lhs, rhs, VHDL_BINOP_SL);
   case 'r':
      return translate_shift(lhs, rhs, VHDL_BINOP_SR);
   case '^':
      return translate_numeric(lhs, rhs, VHDL_BINOP_XOR);
   default:
      error("No translation for binary opcode '%c'\n",
            ivl_expr_opcode(e));
      delete lhs;
      delete rhs;
      return NULL;
   }
}

static vhdl_expr *translate_select(ivl_expr_t e)
{
   vhdl_var_ref *from =
      dynamic_cast<vhdl_var_ref*>(translate_expr(ivl_expr_oper1(e)));
   if (NULL == from)
      return NULL;

   ivl_expr_t o2 = ivl_expr_oper2(e);
   if (o2) {
      vhdl_expr *base = translate_expr(ivl_expr_oper2(e));
      if (NULL == base)
         return NULL;

      vhdl_type integer(VHDL_TYPE_INTEGER);
      from->set_slice(base->cast(&integer), ivl_expr_width(e) - 1);
      return from;
   }
   else
      return from->resize(ivl_expr_width(e));
}

static vhdl_type *expr_to_vhdl_type(ivl_expr_t e)
{
   if (ivl_expr_signed(e))
      return vhdl_type::nsigned(ivl_expr_width(e));
   else
      return vhdl_type::nunsigned(ivl_expr_width(e));
}

template <class T>
static T *translate_parms(T *t, ivl_expr_t e)
{
   int nparams = ivl_expr_parms(e);
   for (int i = 0; i < nparams; i++) {
      vhdl_expr *param = translate_expr(ivl_expr_parm(e, i));
      if (NULL == param)
         return NULL;

      t->add_expr(param);
   }

   return t;
}

static vhdl_expr *translate_ufunc(ivl_expr_t e)
{
   ivl_scope_t defscope = ivl_expr_def(e);
   ivl_scope_t parentscope = ivl_scope_parent(defscope);
   assert(ivl_scope_type(parentscope) == IVL_SCT_MODULE);

   // A function is always declared in a module, which should have
   // a corresponding entity by this point: so we can get type
   // information, etc. from the declaration
   vhdl_entity *parent_ent = find_entity(ivl_scope_tname(parentscope));
   assert(parent_ent);

   const char *funcname = ivl_scope_tname(defscope);

   vhdl_type *rettype = expr_to_vhdl_type(e);
   vhdl_fcall *fcall = new vhdl_fcall(funcname, rettype);

   return translate_parms<vhdl_fcall>(fcall, e);
}

static vhdl_expr *translate_ternary(ivl_expr_t e)
{
   error("Ternary expression only supported as RHS of assignment");

   return NULL;
}

static vhdl_expr *translate_concat(ivl_expr_t e)
{
   vhdl_type *rtype = expr_to_vhdl_type(e);
   vhdl_binop_expr *concat = new vhdl_binop_expr(VHDL_BINOP_CONCAT, rtype);

   return translate_parms<vhdl_binop_expr>(concat, e);
}

/*
 * Generate a VHDL expression from a Verilog expression.
 */
vhdl_expr *translate_expr(ivl_expr_t e)
{
   assert(e);
   ivl_expr_type_t type = ivl_expr_type(e);

   switch (type) {
   case IVL_EX_STRING:
      return translate_string(e);
   case IVL_EX_SIGNAL:
      return translate_signal(e);
   case IVL_EX_NUMBER:
      return translate_number(e);
   case IVL_EX_UNARY:
      return translate_unary(e);
   case IVL_EX_BINARY:
      return translate_binary(e);
   case IVL_EX_SELECT:
      return translate_select(e);
   case IVL_EX_UFUNC:
      return translate_ufunc(e);
   case IVL_EX_TERNARY:
      return translate_ternary(e);
   case IVL_EX_CONCAT:
      return translate_concat(e);
   default:
      error("No VHDL translation for expression at %s:%d (type = %d)",
            ivl_expr_file(e), ivl_expr_lineno(e), type);
      return NULL;
   }
}
<commit_msg>Fix casting with signed/unsigned expressions<commit_after>/*
 *  VHDL code generation for expressions.
 *
 *  Copyright (C) 2008  Nick Gasson (nick@nickg.me.uk)
 *
 *  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 distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  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.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "vhdl_target.h"

#include <iostream>
#include <cassert>

/*
 * Convert a constant Verilog string to a constant VHDL string.
 */
static vhdl_expr *translate_string(ivl_expr_t e)
{
   // TODO: May need to inspect or escape parts of this
   const char *str = ivl_expr_string(e);
   return new vhdl_const_string(str);
}

/*
 * A reference to a signal in an expression. It's assumed that the
 * signal has already been defined elsewhere.
 */
static vhdl_var_ref *translate_signal(ivl_expr_t e)
{
   ivl_signal_t sig = ivl_expr_signal(e);

   const vhdl_scope *scope = find_scope_for_signal(sig);
   assert(scope);

   const char *renamed = get_renamed_signal(sig).c_str();

   const vhdl_decl *decl = scope->get_decl(strip_var(renamed));
   assert(decl);

   vhdl_type *type = new vhdl_type(*decl->get_type());

   return new vhdl_var_ref(renamed, type);
}

/*
 * A numeric literal ends up as std_logic bit string.
 */
static vhdl_expr *translate_number(ivl_expr_t e)
{
   return new vhdl_const_bits(ivl_expr_bits(e), ivl_expr_width(e),
                              ivl_expr_signed(e) != 0);
}

static vhdl_expr *translate_unary(ivl_expr_t e)
{
   vhdl_expr *operand = translate_expr(ivl_expr_oper1(e));
   if (NULL == operand)
      return NULL;

   bool should_be_signed = ivl_expr_signed(e) != 0;

   if (operand->get_type()->get_name() == VHDL_TYPE_UNSIGNED && should_be_signed) {
      //operand->print();
      //std::cout << "^ should be signed but is not" << std::endl;

      int msb = operand->get_type()->get_msb();
      int lsb = operand->get_type()->get_lsb();
      vhdl_type u(VHDL_TYPE_SIGNED, msb, lsb);

      operand = operand->cast(&u);
   }
   else if (operand->get_type()->get_name() == VHDL_TYPE_SIGNED && !should_be_signed) {
      //operand->print();
      //std::cout << "^ should be unsigned but is not" << std::endl;

      int msb = operand->get_type()->get_msb();
      int lsb = operand->get_type()->get_lsb();
      vhdl_type u(VHDL_TYPE_UNSIGNED, msb, lsb);

      operand = operand->cast(&u);
   }

   // Need to ensure that the operand is interpreted as unsigned to get VHDL
   // to emulate Verilog behaviour
   if (operand->get_type()->get_name() == VHDL_TYPE_SIGNED) {
      int msb = operand->get_type()->get_msb();
      int lsb = operand->get_type()->get_lsb();
      vhdl_type u(VHDL_TYPE_UNSIGNED, msb, lsb);

      operand = operand->cast(&u);
   }

   char opcode = ivl_expr_opcode(e);
   switch (opcode) {
   case '!':
   case '~':
      return new vhdl_unaryop_expr
         (VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type()));
   case 'N':   // NOR
   case '|':
      {
         vhdl_fcall *f = new vhdl_fcall("Reduce_OR", vhdl_type::std_logic());
         f->add_expr(operand);
         if ('N' == opcode)
            return new vhdl_unaryop_expr(VHDL_UNARYOP_NOT, f, vhdl_type::std_logic());
         else
            return f;
      }
   default:
      error("No translation for unary opcode '%c'\n",
            ivl_expr_opcode(e));
      delete operand;
      return NULL;
   }
}

/*
 * Translate a numeric binary operator (+, -, etc.) to
 * a VHDL equivalent using the numeric_std package.
 */
static vhdl_expr *translate_numeric(vhdl_expr *lhs, vhdl_expr *rhs,
                                    vhdl_binop_t op)
{
   // May need to make either side Boolean for operators
   // to work
   vhdl_type boolean(VHDL_TYPE_BOOLEAN);
   if (lhs->get_type()->get_name() == VHDL_TYPE_BOOLEAN)
      rhs = rhs->cast(&boolean);
   else if (rhs->get_type()->get_name() == VHDL_TYPE_BOOLEAN)
      lhs = lhs->cast(&boolean);

   vhdl_type *rtype = new vhdl_type(*lhs->get_type());
   return new vhdl_binop_expr(lhs, op, rhs, rtype);
}

static vhdl_expr *translate_relation(vhdl_expr *lhs, vhdl_expr *rhs,
                                     vhdl_binop_t op)
{
   // Generate any necessary casts
   // Arbitrarily, the RHS is casted to the type of the LHS
   vhdl_expr *r_cast = rhs->cast(lhs->get_type());

   return new vhdl_binop_expr(lhs, op, r_cast, vhdl_type::boolean());
}

/*
 * Like translate_relation but both operands must be Boolean.
 */
static vhdl_expr *translate_logical(vhdl_expr *lhs, vhdl_expr *rhs,
                                    vhdl_binop_t op)
{
   vhdl_type boolean(VHDL_TYPE_BOOLEAN);

   return translate_relation(lhs->cast(&boolean), rhs->cast(&boolean), op);
}

static vhdl_expr *translate_shift(vhdl_expr *lhs, vhdl_expr *rhs,
                                  vhdl_binop_t op)
{
   // The RHS must be an integer
   vhdl_type integer(VHDL_TYPE_INTEGER);
   vhdl_expr *r_cast = rhs->cast(&integer);

   vhdl_type *rtype = new vhdl_type(*lhs->get_type());
   return new vhdl_binop_expr(lhs, op, r_cast, rtype);
}

static vhdl_expr *translate_binary(ivl_expr_t e)
{
   vhdl_expr *lhs = translate_expr(ivl_expr_oper1(e));
   if (NULL == lhs)
      return NULL;

   vhdl_expr *rhs = translate_expr(ivl_expr_oper2(e));
   if (NULL == rhs)
      return NULL;

   int lwidth = lhs->get_type()->get_width();
   int rwidth = rhs->get_type()->get_width();
   int result_width = ivl_expr_width(e);

   // For === and !== we need to compare std_logic_vectors
   // rather than signeds
   vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR, result_width-1, 0);
   vhdl_type_name_t ltype = lhs->get_type()->get_name();
   vhdl_type_name_t rtype = rhs->get_type()->get_name();
   bool vectorop =
      (ltype == VHDL_TYPE_SIGNED || ltype == VHDL_TYPE_UNSIGNED) &&
      (rtype == VHDL_TYPE_SIGNED || rtype == VHDL_TYPE_UNSIGNED);

   // May need to resize the left or right hand side
   if (vectorop) {
      if (lwidth < rwidth)
         lhs = lhs->resize(rwidth);
      else if (rwidth < lwidth)
         rhs = rhs->resize(lwidth);
   }

   vhdl_expr *result;
   switch (ivl_expr_opcode(e)) {
   case '+':
      result = translate_numeric(lhs, rhs, VHDL_BINOP_ADD);
      break;
   case '-':
      result = translate_numeric(lhs, rhs, VHDL_BINOP_SUB);
      break;
   case '*':
      result = translate_numeric(lhs, rhs, VHDL_BINOP_MULT);
      break;
   case 'e':
      result = translate_relation(lhs, rhs, VHDL_BINOP_EQ);
      break;
   case 'E':
      if (vectorop)
         result = translate_relation(lhs->cast(&std_logic_vector),
                                   rhs->cast(&std_logic_vector), VHDL_BINOP_EQ);
      else
         result = translate_relation(lhs, rhs, VHDL_BINOP_EQ);
      break;
   case 'n':
      result = translate_relation(lhs, rhs, VHDL_BINOP_NEQ);
      break;
   case 'N':
      if (vectorop)
         result = translate_relation(lhs->cast(&std_logic_vector),
                                   rhs->cast(&std_logic_vector), VHDL_BINOP_NEQ);
      else
         result = translate_relation(lhs, rhs, VHDL_BINOP_NEQ);
      break;
   case '&':    // Bitwise AND
      result = translate_numeric(lhs, rhs, VHDL_BINOP_AND);
      break;
   case 'a':    // Logical AND
      result = translate_logical(lhs, rhs, VHDL_BINOP_AND);
      break;
   case '|':    // Bitwise OR
      result = translate_numeric(lhs, rhs, VHDL_BINOP_OR);
      break;
   case 'o':    // Logical OR
      result = translate_logical(lhs, rhs, VHDL_BINOP_OR);
      break;
   case '<':
      result = translate_relation(lhs, rhs, VHDL_BINOP_LT);
      break;
   case 'L':
      result = translate_relation(lhs, rhs, VHDL_BINOP_LEQ);
      break;
   case '>':
      result = translate_relation(lhs, rhs, VHDL_BINOP_GT);
      break;
   case 'G':
      result = translate_relation(lhs, rhs, VHDL_BINOP_GEQ);
      break;
   case 'l':
      result = translate_shift(lhs, rhs, VHDL_BINOP_SL);
      break;
   case 'r':
      result = translate_shift(lhs, rhs, VHDL_BINOP_SR);
      break;
   case '^':
      result = translate_numeric(lhs, rhs, VHDL_BINOP_XOR);
      break;
   default:
      error("No translation for binary opcode '%c'\n",
            ivl_expr_opcode(e));
      delete lhs;
      delete rhs;
      return NULL;
   }

   if (NULL == result)
      return NULL;

   if (vectorop) {
      bool should_be_signed = ivl_expr_signed(e) != 0;

      if (result->get_type()->get_name() == VHDL_TYPE_UNSIGNED && should_be_signed) {
         //result->print();
         //std::cout << "^ should be signed but is not" << std::endl;

         int msb = result->get_type()->get_msb();
         int lsb = result->get_type()->get_lsb();
         vhdl_type u(VHDL_TYPE_SIGNED, msb, lsb);

         result = result->cast(&u);
      }
      else if (result->get_type()->get_name() == VHDL_TYPE_SIGNED && !should_be_signed) {
         //result->print();
         //std::cout << "^ should be unsigned but is not" << std::endl;

         int msb = result->get_type()->get_msb();
         int lsb = result->get_type()->get_lsb();
         vhdl_type u(VHDL_TYPE_SIGNED, msb, lsb);

         result = result->cast(&u);
      }

      int actual_width = result->get_type()->get_width();
      if (actual_width != result_width) {
         //result->print();
         //std::cout << "^ should be " << result_width << " but is " << actual_width << std::endl;
      }
   }

   return result;
}

static vhdl_expr *translate_select(ivl_expr_t e)
{
   vhdl_var_ref *from =
      dynamic_cast<vhdl_var_ref*>(translate_expr(ivl_expr_oper1(e)));
   if (NULL == from)
      return NULL;

   ivl_expr_t o2 = ivl_expr_oper2(e);
   if (o2) {
      vhdl_expr *base = translate_expr(ivl_expr_oper2(e));
      if (NULL == base)
         return NULL;

      vhdl_type integer(VHDL_TYPE_INTEGER);
      from->set_slice(base->cast(&integer), ivl_expr_width(e) - 1);
      return from;
   }
   else
      return from->resize(ivl_expr_width(e));
}

static vhdl_type *expr_to_vhdl_type(ivl_expr_t e)
{
   if (ivl_expr_signed(e))
      return vhdl_type::nsigned(ivl_expr_width(e));
   else
      return vhdl_type::nunsigned(ivl_expr_width(e));
}

template <class T>
static T *translate_parms(T *t, ivl_expr_t e)
{
   int nparams = ivl_expr_parms(e);
   for (int i = 0; i < nparams; i++) {
      vhdl_expr *param = translate_expr(ivl_expr_parm(e, i));
      if (NULL == param)
         return NULL;

      t->add_expr(param);
   }

   return t;
}

static vhdl_expr *translate_ufunc(ivl_expr_t e)
{
   ivl_scope_t defscope = ivl_expr_def(e);
   ivl_scope_t parentscope = ivl_scope_parent(defscope);
   assert(ivl_scope_type(parentscope) == IVL_SCT_MODULE);

   // A function is always declared in a module, which should have
   // a corresponding entity by this point: so we can get type
   // information, etc. from the declaration
   vhdl_entity *parent_ent = find_entity(ivl_scope_tname(parentscope));
   assert(parent_ent);

   const char *funcname = ivl_scope_tname(defscope);

   vhdl_type *rettype = expr_to_vhdl_type(e);
   vhdl_fcall *fcall = new vhdl_fcall(funcname, rettype);

   return translate_parms<vhdl_fcall>(fcall, e);
}

static vhdl_expr *translate_ternary(ivl_expr_t e)
{
   error("Ternary expression only supported as RHS of assignment");

   return NULL;
}

static vhdl_expr *translate_concat(ivl_expr_t e)
{
   vhdl_type *rtype = expr_to_vhdl_type(e);
   vhdl_binop_expr *concat = new vhdl_binop_expr(VHDL_BINOP_CONCAT, rtype);

   return translate_parms<vhdl_binop_expr>(concat, e);
}

/*
 * Generate a VHDL expression from a Verilog expression.
 */
vhdl_expr *translate_expr(ivl_expr_t e)
{
   assert(e);
   ivl_expr_type_t type = ivl_expr_type(e);

   switch (type) {
   case IVL_EX_STRING:
      return translate_string(e);
   case IVL_EX_SIGNAL:
      return translate_signal(e);
   case IVL_EX_NUMBER:
      return translate_number(e);
   case IVL_EX_UNARY:
      return translate_unary(e);
   case IVL_EX_BINARY:
      return translate_binary(e);
   case IVL_EX_SELECT:
      return translate_select(e);
   case IVL_EX_UFUNC:
      return translate_ufunc(e);
   case IVL_EX_TERNARY:
      return translate_ternary(e);
   case IVL_EX_CONCAT:
      return translate_concat(e);
   default:
      error("No VHDL translation for expression at %s:%d (type = %d)",
            ivl_expr_file(e), ivl_expr_lineno(e), type);
      return NULL;
   }
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2012 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
#include "config.h"
#include <algorithm>
#include <cerrno>
#include <cstdlib>
#include <string.h>
#include <strings.h>
#include <cerrno>
#include <getopt.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctype.h>

#include "cJSON.h"

using namespace std;

/**
 * Print the JSON object quoted
 */
static ostream& operator <<(ostream &out, cJSON *json)
{
    char *data = cJSON_PrintUnformatted(json);
    int ii = 0;

    out << '"';
    while (data[ii] != '\0') {
        if (data[ii] == '"') {
            out << '\\';
        }
        out << data[ii];
        ++ii;
    }

    out << '"';
    free(data);
    return out;
}

static void usage(void)
{
    cerr << "Usage: gencode -j JSON -c cfile -h headerfile -f function"
         << endl
         << "\tThe JSON file will be read to generate the c and h file."
         << endl;
    exit(EXIT_FAILURE);
}

int main(int argc, char **argv) {
    int cmd;
    const char *json = NULL;
    const char *hfile = NULL;
    const char *cfile = NULL;
    const char *function = NULL;

    while ((cmd = getopt(argc, argv, "j:c:h:f:")) != -1) {
        switch (cmd) {
        case 'j' :
            json = optarg;
            break;
        case 'c' :
            cfile = optarg;
            break;
        case 'h':
            hfile = optarg;
            break;
        case 'f':
            function = optarg;
            break;
        default:
            usage();
        }
    }

    if (json == NULL || hfile == NULL || cfile == NULL || function == NULL) {
        usage();
    }

    struct stat st;
    if (stat(json, &st) == -1) {
        cerr << "Failed to look up \"" << json << "\": "
             << strerror(errno) << endl;
        exit(EXIT_FAILURE);
    }

    char *data = new char[st.st_size + 1];
    data[st.st_size] = 0;
    ifstream input(json);
    input.read(data, st.st_size);
    input.close();

    cJSON *c = cJSON_Parse(data);
    if (c == NULL) {
        cerr << "Failed to parse JSON.. probably syntax error" << endl;
        exit(EXIT_FAILURE);
    }

    ofstream headerfile(hfile);

    std::string macro(hfile);
    std::replace(macro.begin(), macro.end(), ' ', '_');
    std::replace(macro.begin(), macro.end(), '/', '_');
    std::replace(macro.begin(), macro.end(), '-', '_');
    std::replace(macro.begin(), macro.end(), '.', '_');
    std::replace(macro.begin(), macro.end(), ':', '_');
    std::transform(macro.begin(), macro.end(), macro.begin(), ::toupper);

    headerfile
        << "/*" << endl
        << " *     Copyright 2014 Couchbase, Inc" << endl
        << " *" << endl
        << " *   Licensed under the Apache License, Version 2.0 (the \"License\");" << endl
        << " *   you may not use this file except in compliance with the License." << endl
        << " *   You may obtain a copy of the License at" << endl
        << " *" << endl
        << " *       http://www.apache.org/licenses/LICENSE-2.0" << endl
        << " *" << endl
        << " *   Unless required by applicable law or agreed to in writing, software" << endl
        << " *   distributed under the License is distributed on an \"AS IS\" BASIS," << endl
        << " *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." << endl
        << " *   See the License for the specific language governing permissions and" << endl
        << " *   limitations under the License." << endl
        << " */" << endl
        << endl
        << "/********************************" << endl
        << "** Generated file, do not edit **" << endl
        << "*********************************/" << endl
        << "#ifndef " << macro << endl
        << "#define " << macro << endl
        << endl
        << "#include \"config.h\"" << endl
        << endl
        << "#ifdef __cplusplus" << endl
        << "extern \"C\" {" << endl
        << "#endif" << endl
        << endl
        << "const char *" << function << "(void);" << endl
        << endl
        << "#ifdef __cplusplus" << endl
        << "}" << endl
        << "#endif" << endl
        << "#endif  /* " << macro << "*/" << endl;
    headerfile.close();

    ofstream sourcefile(cfile);
    sourcefile
        << "/*" << endl
        << " *     Copyright 2014 Couchbase, Inc" << endl
        << " *" << endl
        << " *   Licensed under the Apache License, Version 2.0 (the \"License\");" << endl
        << " *   you may not use this file except in compliance with the License." << endl
        << " *   You may obtain a copy of the License at" << endl
        << " *" << endl
        << " *       http://www.apache.org/licenses/LICENSE-2.0" << endl
        << " *" << endl
        << " *   Unless required by applicable law or agreed to in writing, software" << endl
        << " *   distributed under the License is distributed on an \"AS IS\" BASIS," << endl
        << " *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." << endl
        << " *   See the License for the specific language governing permissions and" << endl
        << " *   limitations under the License." << endl
        << " */" << endl
        << endl
        << "/********************************" << endl
        << "** Generated file, do not edit **" << endl
        << "*********************************/" << endl
        << "#include \"config.h\"" << endl
        << "#include \"" << hfile << "\"" << endl
        << endl
        << "const char *" << function << "(void)" << endl
        << "{" << endl
        << "    return " << c << ";" << endl
        << "}" << endl;

    cJSON_Delete(c);

    return 0;
}
<commit_msg>MB-19043: Fix memory leak in gencode<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *     Copyright 2012 Couchbase, Inc
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
#include "config.h"
#include <algorithm>
#include <cerrno>
#include <cstdlib>
#include <string.h>
#include <strings.h>
#include <cerrno>
#include <getopt.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <ctype.h>

#include "cJSON.h"

using namespace std;

/**
 * Print the JSON object quoted
 */
static ostream& operator <<(ostream &out, cJSON *json)
{
    char *data = cJSON_PrintUnformatted(json);
    int ii = 0;

    out << '"';
    while (data[ii] != '\0') {
        if (data[ii] == '"') {
            out << '\\';
        }
        out << data[ii];
        ++ii;
    }

    out << '"';
    free(data);
    return out;
}

static void usage(void)
{
    cerr << "Usage: gencode -j JSON -c cfile -h headerfile -f function"
         << endl
         << "\tThe JSON file will be read to generate the c and h file."
         << endl;
    exit(EXIT_FAILURE);
}

int main(int argc, char **argv) {
    int cmd;
    const char *json = NULL;
    const char *hfile = NULL;
    const char *cfile = NULL;
    const char *function = NULL;

    while ((cmd = getopt(argc, argv, "j:c:h:f:")) != -1) {
        switch (cmd) {
        case 'j' :
            json = optarg;
            break;
        case 'c' :
            cfile = optarg;
            break;
        case 'h':
            hfile = optarg;
            break;
        case 'f':
            function = optarg;
            break;
        default:
            usage();
        }
    }

    if (json == NULL || hfile == NULL || cfile == NULL || function == NULL) {
        usage();
    }

    struct stat st;
    if (stat(json, &st) == -1) {
        cerr << "Failed to look up \"" << json << "\": "
             << strerror(errno) << endl;
        exit(EXIT_FAILURE);
    }

    std::vector<char> data(st.st_size + 1);
    ifstream input(json);
    input.read(data.data(), st.st_size);
    input.close();

    cJSON *c = cJSON_Parse(data.data());
    if (c == NULL) {
        cerr << "Failed to parse JSON.. probably syntax error" << endl;
        exit(EXIT_FAILURE);
    }

    ofstream headerfile(hfile);

    std::string macro(hfile);
    std::replace(macro.begin(), macro.end(), ' ', '_');
    std::replace(macro.begin(), macro.end(), '/', '_');
    std::replace(macro.begin(), macro.end(), '-', '_');
    std::replace(macro.begin(), macro.end(), '.', '_');
    std::replace(macro.begin(), macro.end(), ':', '_');
    std::transform(macro.begin(), macro.end(), macro.begin(), ::toupper);

    headerfile
        << "/*" << endl
        << " *     Copyright 2014 Couchbase, Inc" << endl
        << " *" << endl
        << " *   Licensed under the Apache License, Version 2.0 (the \"License\");" << endl
        << " *   you may not use this file except in compliance with the License." << endl
        << " *   You may obtain a copy of the License at" << endl
        << " *" << endl
        << " *       http://www.apache.org/licenses/LICENSE-2.0" << endl
        << " *" << endl
        << " *   Unless required by applicable law or agreed to in writing, software" << endl
        << " *   distributed under the License is distributed on an \"AS IS\" BASIS," << endl
        << " *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." << endl
        << " *   See the License for the specific language governing permissions and" << endl
        << " *   limitations under the License." << endl
        << " */" << endl
        << endl
        << "/********************************" << endl
        << "** Generated file, do not edit **" << endl
        << "*********************************/" << endl
        << "#ifndef " << macro << endl
        << "#define " << macro << endl
        << endl
        << "#include \"config.h\"" << endl
        << endl
        << "#ifdef __cplusplus" << endl
        << "extern \"C\" {" << endl
        << "#endif" << endl
        << endl
        << "const char *" << function << "(void);" << endl
        << endl
        << "#ifdef __cplusplus" << endl
        << "}" << endl
        << "#endif" << endl
        << "#endif  /* " << macro << "*/" << endl;
    headerfile.close();

    ofstream sourcefile(cfile);
    sourcefile
        << "/*" << endl
        << " *     Copyright 2014 Couchbase, Inc" << endl
        << " *" << endl
        << " *   Licensed under the Apache License, Version 2.0 (the \"License\");" << endl
        << " *   you may not use this file except in compliance with the License." << endl
        << " *   You may obtain a copy of the License at" << endl
        << " *" << endl
        << " *       http://www.apache.org/licenses/LICENSE-2.0" << endl
        << " *" << endl
        << " *   Unless required by applicable law or agreed to in writing, software" << endl
        << " *   distributed under the License is distributed on an \"AS IS\" BASIS," << endl
        << " *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." << endl
        << " *   See the License for the specific language governing permissions and" << endl
        << " *   limitations under the License." << endl
        << " */" << endl
        << endl
        << "/********************************" << endl
        << "** Generated file, do not edit **" << endl
        << "*********************************/" << endl
        << "#include \"config.h\"" << endl
        << "#include \"" << hfile << "\"" << endl
        << endl
        << "const char *" << function << "(void)" << endl
        << "{" << endl
        << "    return " << c << ";" << endl
        << "}" << endl;

    cJSON_Delete(c);

    return 0;
}
<|endoftext|>