<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "OGLImagingContext.h"

#include "../base/Exception.h"

#ifdef _WIN32
// XXX: If the following includes are not there, the MS linker optimizes away
// the classes so they can't be used by plugins anymore (!). Adding /OPT:NOREF
// to the linker flags doesn't help.
#include "IteratingGPUFilter.h"
#include "FilterGetAlpha.h"
#include "FilterErosion.h"
#include "FilterDilation.h"
#include "FilterGetAlpha.h"
#include "FilterResizeBilinear.h"
#include "FilterResizeGaussian.h"
#endif

#include <assert.h>
#include <iostream>

namespace avg {

using namespace std;

#ifdef _WIN32
LONG WINAPI imagingWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

void registerWindowClass()
{
  static char * pClassName;
  if (pClassName) {
      return;
  }
  pClassName = "GLUT";

  HINSTANCE hInstance = GetModuleHandle(NULL);
  WNDCLASS  wc;
  memset(&wc, 0, sizeof(WNDCLASS));
  wc.style = CS_OWNDC;
  wc.lpfnWndProc = (WNDPROC)imagingWindowProc;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
  wc.hbrBackground = NULL;
  wc.lpszMenuName = NULL;
  wc.lpszClassName = pClassName;

  BOOL bOK = RegisterClass(&wc);
  assert(bOK);
}
#endif

#ifdef linux
static bool s_bX11Error;
static int (*s_DefaultErrorHandler) (Display *, XErrorEvent *);

int X11ErrorHandler(Display * pDisplay, XErrorEvent * pErrEvent)
{
    cerr << "X11 error creating offscreen context: " << (int)(pErrEvent->request_code)
            << ", " << (int)(pErrEvent->minor_code) << endl;
    if ((pErrEvent->request_code == 145 || pErrEvent->request_code == 144)
            && pErrEvent->minor_code == 7)
    {
        s_bX11Error = true;
    } else {
        s_DefaultErrorHandler(pDisplay, pErrEvent);
    }
    return 0;
}
#endif

OGLImagingContext::OGLImagingContext(const IntPoint & size)
{
#ifdef __APPLE__
    GLint attributes[] = {AGL_RGBA, AGL_ALL_RENDERERS,AGL_NONE};
    AGLPixelFormat format;
    format = aglChoosePixelFormat(NULL, 0, attributes);
    assert(format);

    m_Context = aglCreateContext(format, NULL);
    assert(m_Context);
    aglDestroyPixelFormat(format);

    bool bOk = aglSetCurrentContext(m_Context);
    assert (bOk);
#else
#ifdef linux
    Display *dpy;
    dpy = XOpenDisplay(0);
    if (!dpy) {
        throw Exception(AVG_ERR_VIDEO_GENERAL, "No X windows display available.");
    }
    XVisualInfo *vi;
    static int attributes[] = {GLX_RGBA,
            GLX_RED_SIZE, 1,
            GLX_GREEN_SIZE, 1,
            GLX_BLUE_SIZE, 1,
            0};
    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
    m_Context = glXCreateContext(dpy, vi, 0, GL_TRUE);
    assert(m_Context);
    Pixmap pmp = XCreatePixmap(dpy, RootWindow(dpy, vi->screen),
            8, 8, vi->depth);
    GLXPixmap pixmap = glXCreateGLXPixmap(dpy, vi, pmp);

    s_bX11Error = false;
    s_DefaultErrorHandler = XSetErrorHandler(X11ErrorHandler);
    glXMakeCurrent(dpy, pixmap, m_Context);
    XSetErrorHandler(s_DefaultErrorHandler);

    if (s_bX11Error) {
        throw Exception(AVG_ERR_VIDEO_GENERAL, "X error creating OpenGL context.");
    }
#else
#ifdef _WIN32
    registerWindowClass();
    m_hwnd = CreateWindow("GLUT", "GLUT",
            WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
            0, 0, 500, 300, 0, 0, GetModuleHandle(NULL), 0);
    winOGLErrorCheck(m_hDC != 0, "CreateWindow");

    m_hDC = GetDC(m_hwnd);
    winOGLErrorCheck(m_hDC != 0, "GetDC");

    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int iFormat = ChoosePixelFormat(m_hDC, &pfd);
    winOGLErrorCheck(iFormat != 0, "ChoosePixelFormat");
    SetPixelFormat(m_hDC, iFormat, &pfd);
    m_Context = wglCreateContext(m_hDC);
    winOGLErrorCheck(m_Context != 0, "wglCreateContext");

    BOOL bOK = wglMakeCurrent(m_hDC, m_Context);
    winOGLErrorCheck(bOK, "wglMakeCurrent");
#endif
#endif
#endif
    glproc::init();

    if (!isSupported()) {
        throw Exception(AVG_ERR_VIDEO_GENERAL,
                "GPU imaging not supported by current OpenGL configuration.");
    }

    // Coordinates
    setSize(size);

    setStandardState(size);
//    IteratingGPUFilter f(IntPoint(100, 100), 15);
}

OGLImagingContext::~OGLImagingContext()
{
#ifdef __APPLE__
    if (m_Context) {
        aglSetCurrentContext(0);
        aglDestroyContext(m_Context);
        m_Context = 0;
    }
#endif
#ifdef _WIN32
    if (m_Context) {
        wglDeleteContext(m_Context);
        DeleteDC(m_hDC);
        DestroyWindow(m_hwnd);
    }
#endif
}

void OGLImagingContext::activate()
{
#ifdef __APPLE__
    bool bOk = aglSetCurrentContext(m_Context);
    assert(bOk);
#elif defined _WIN32
    BOOL bOk = wglMakeCurrent(m_hDC, m_Context);
    assert(bOk);
#endif
    // TODO: X version
}

void OGLImagingContext::setSize(const IntPoint& size)
{
    m_Size = size;
    setSizeState(size);
}

bool OGLImagingContext::isSupported()
{
    int glMajorVer;
    int glMinorVer;
    int slMajorVer;
    int slMinorVer;
    getGLVersion(glMajorVer, glMinorVer);
    getGLShadingLanguageVersion(slMajorVer, slMinorVer);
    // Not sure if we need shader version 1.2 as well - we'll see.
    return (glMajorVer > 1 && queryOGLExtension("GL_ARB_texture_rectangle") &&
            queryOGLExtension("GL_ARB_pixel_buffer_object") &&
            queryOGLExtension("GL_EXT_framebuffer_object"));
}

void OGLImagingContext::setStandardState(const IntPoint & size)
{
    setSizeState(size);

    // Shading etc.
    glDisable(GL_BLEND);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_BLEND)");
    glShadeModel(GL_FLAT);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glShadeModel(GL_FLAT)");
    glDisable(GL_DEPTH_TEST);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_DEPTH_TEST)");
    glDisable(GL_STENCIL_TEST);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_STENCIL_TEST)");

    // Texturing
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glTexEnvf()");
    glBlendFunc(GL_ONE, GL_ZERO);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glBlendFunc()");
    glEnable(GL_TEXTURE_RECTANGLE_ARB);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glEnable(GL_TEXTURE_RECTANGLE_ARB);");
    glDisable(GL_MULTISAMPLE);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_MULTISAMPLE);");

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

void OGLImagingContext::setSizeState(const IntPoint & size)
{
    glViewport(0, 0, size.x, size.y);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glViewport()");
    glMatrixMode(GL_PROJECTION);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glMatrixMode()");
    glLoadIdentity();
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glLoadIdentity()");
    gluOrtho2D(0, size.x, size.y, 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "gluOrtho2D()");
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glLoadIdentity()");
}

}

<commit_msg>Another possible fix for mesa testgpu crash.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "OGLImagingContext.h"

#include "../base/Exception.h"

#ifdef _WIN32
// XXX: If the following includes are not there, the MS linker optimizes away
// the classes so they can't be used by plugins anymore (!). Adding /OPT:NOREF
// to the linker flags doesn't help.
#include "IteratingGPUFilter.h"
#include "FilterGetAlpha.h"
#include "FilterErosion.h"
#include "FilterDilation.h"
#include "FilterGetAlpha.h"
#include "FilterResizeBilinear.h"
#include "FilterResizeGaussian.h"
#endif

#include <assert.h>
#include <iostream>

namespace avg {

using namespace std;

#ifdef _WIN32
LONG WINAPI imagingWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

void registerWindowClass()
{
  static char * pClassName;
  if (pClassName) {
      return;
  }
  pClassName = "GLUT";

  HINSTANCE hInstance = GetModuleHandle(NULL);
  WNDCLASS  wc;
  memset(&wc, 0, sizeof(WNDCLASS));
  wc.style = CS_OWNDC;
  wc.lpfnWndProc = (WNDPROC)imagingWindowProc;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
  wc.hbrBackground = NULL;
  wc.lpszMenuName = NULL;
  wc.lpszClassName = pClassName;

  BOOL bOK = RegisterClass(&wc);
  assert(bOK);
}
#endif

#ifdef linux
static bool s_bX11Error;
static int (*s_DefaultErrorHandler) (Display *, XErrorEvent *);

int X11ErrorHandler(Display * pDisplay, XErrorEvent * pErrEvent)
{
    cerr << "X11 error creating offscreen context: " << (int)(pErrEvent->request_code)
            << ", " << (int)(pErrEvent->minor_code) << endl;
    s_bX11Error = true;
    return 0;
}
#endif

OGLImagingContext::OGLImagingContext(const IntPoint & size)
{
#ifdef __APPLE__
    GLint attributes[] = {AGL_RGBA, AGL_ALL_RENDERERS,AGL_NONE};
    AGLPixelFormat format;
    format = aglChoosePixelFormat(NULL, 0, attributes);
    assert(format);

    m_Context = aglCreateContext(format, NULL);
    assert(m_Context);
    aglDestroyPixelFormat(format);

    bool bOk = aglSetCurrentContext(m_Context);
    assert (bOk);
#else
#ifdef linux
    Display *dpy;
    dpy = XOpenDisplay(0);
    if (!dpy) {
        throw Exception(AVG_ERR_VIDEO_GENERAL, "No X windows display available.");
    }
    XVisualInfo *vi;
    static int attributes[] = {GLX_RGBA,
            GLX_RED_SIZE, 1,
            GLX_GREEN_SIZE, 1,
            GLX_BLUE_SIZE, 1,
            0};
    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
    m_Context = glXCreateContext(dpy, vi, 0, GL_TRUE);
    assert(m_Context);
    Pixmap pmp = XCreatePixmap(dpy, RootWindow(dpy, vi->screen),
            8, 8, vi->depth);
    GLXPixmap pixmap = glXCreateGLXPixmap(dpy, vi, pmp);

    s_bX11Error = false;
    s_DefaultErrorHandler = XSetErrorHandler(X11ErrorHandler);
    glXMakeCurrent(dpy, pixmap, m_Context);
    XSetErrorHandler(s_DefaultErrorHandler);

    if (s_bX11Error) {
        throw Exception(AVG_ERR_VIDEO_GENERAL, "X error creating OpenGL context.");
    }
#else
#ifdef _WIN32
    registerWindowClass();
    m_hwnd = CreateWindow("GLUT", "GLUT",
            WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
            0, 0, 500, 300, 0, 0, GetModuleHandle(NULL), 0);
    winOGLErrorCheck(m_hDC != 0, "CreateWindow");

    m_hDC = GetDC(m_hwnd);
    winOGLErrorCheck(m_hDC != 0, "GetDC");

    PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int iFormat = ChoosePixelFormat(m_hDC, &pfd);
    winOGLErrorCheck(iFormat != 0, "ChoosePixelFormat");
    SetPixelFormat(m_hDC, iFormat, &pfd);
    m_Context = wglCreateContext(m_hDC);
    winOGLErrorCheck(m_Context != 0, "wglCreateContext");

    BOOL bOK = wglMakeCurrent(m_hDC, m_Context);
    winOGLErrorCheck(bOK, "wglMakeCurrent");
#endif
#endif
#endif
    glproc::init();

    if (!isSupported()) {
        throw Exception(AVG_ERR_VIDEO_GENERAL,
                "GPU imaging not supported by current OpenGL configuration.");
    }

    // Coordinates
    setSize(size);

    setStandardState(size);
//    IteratingGPUFilter f(IntPoint(100, 100), 15);
}

OGLImagingContext::~OGLImagingContext()
{
#ifdef __APPLE__
    if (m_Context) {
        aglSetCurrentContext(0);
        aglDestroyContext(m_Context);
        m_Context = 0;
    }
#endif
#ifdef _WIN32
    if (m_Context) {
        wglDeleteContext(m_Context);
        DeleteDC(m_hDC);
        DestroyWindow(m_hwnd);
    }
#endif
}

void OGLImagingContext::activate()
{
#ifdef __APPLE__
    bool bOk = aglSetCurrentContext(m_Context);
    assert(bOk);
#elif defined _WIN32
    BOOL bOk = wglMakeCurrent(m_hDC, m_Context);
    assert(bOk);
#endif
    // TODO: X version
}

void OGLImagingContext::setSize(const IntPoint& size)
{
    m_Size = size;
    setSizeState(size);
}

bool OGLImagingContext::isSupported()
{
    int glMajorVer;
    int glMinorVer;
    int slMajorVer;
    int slMinorVer;
    getGLVersion(glMajorVer, glMinorVer);
    getGLShadingLanguageVersion(slMajorVer, slMinorVer);
    // Not sure if we need shader version 1.2 as well - we'll see.
    return (glMajorVer > 1 && queryOGLExtension("GL_ARB_texture_rectangle") &&
            queryOGLExtension("GL_ARB_pixel_buffer_object") &&
            queryOGLExtension("GL_EXT_framebuffer_object"));
}

void OGLImagingContext::setStandardState(const IntPoint & size)
{
    setSizeState(size);

    // Shading etc.
    glDisable(GL_BLEND);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_BLEND)");
    glShadeModel(GL_FLAT);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glShadeModel(GL_FLAT)");
    glDisable(GL_DEPTH_TEST);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_DEPTH_TEST)");
    glDisable(GL_STENCIL_TEST);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_STENCIL_TEST)");

    // Texturing
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glTexEnvf()");
    glBlendFunc(GL_ONE, GL_ZERO);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glBlendFunc()");
    glEnable(GL_TEXTURE_RECTANGLE_ARB);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glEnable(GL_TEXTURE_RECTANGLE_ARB);");
    glDisable(GL_MULTISAMPLE);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glDisable(GL_MULTISAMPLE);");

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

void OGLImagingContext::setSizeState(const IntPoint & size)
{
    glViewport(0, 0, size.x, size.y);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glViewport()");
    glMatrixMode(GL_PROJECTION);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glMatrixMode()");
    glLoadIdentity();
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glLoadIdentity()");
    gluOrtho2D(0, size.x, size.y, 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "gluOrtho2D()");
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "glLoadIdentity()");
}

}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"

enum ammoTypeT {
  AMMO_NONE,                    // 0
  AMMO_10MM_PISTOL,             // 1
  AMMO_9MM_PARABELLEM_PISTOL,   // 2
  AMMO_45CAL_ACP_PISTOL,        // 3
  AMMO_50CAL_AE_PISTOL,         // 4
  AMMO_44CAL_MAGNUM_PISTOL,     // 5
  AMMO_32CAL_ACP_PISTOL,        // 6
  AMMO_50CAL_BMG_PISTOL,        // 7
  AMMO_556MM_NATO_PISTOL,       // 8
  AMMO_SS190,                   // 9
  AMMO_9MM_PARABELLEM_RIFLE,    // 10
  AMMO_45CAL_ACP_RIFLE,         // 11
  AMMO_556MM_RIFLE,             // 12
  AMMO_762MM_RIFLE,             // 13
  AMMO_30CAL_RIFLE,             // 14
  AMMO_MAX
};

const char *shelldesc [] =
{
  "None",
  "10mm pistol",
  "9mm Parabellem pistol",
  ".45cal ACP pistol",
  ".50cal Action Express",
  ".44cal Magnum",
  ".32cal ACP",
  ".50cal BMG",
  "5.56mm NATO pistol"
  "SS190",
  "9mm Parabellem rifle",
  ".45cal ACP rifle",
  "5.56mm rifle",
  "7.62mm rifle",
  "30cal rifle",
};

const char *shellkeyword [] =
{
  "None",
  "10mmPistol",
  "9mmPistol",
  "45calPistol",
  "50calAE",
  "44calMag",
  "32calACP",
  "50calBMG",
  "556mmPistol"
  "SS190",
  "9mmRifle",
  "45calRifle",
  "556mmRifle",
  "762mmRifle",
  "30calRifle"
};

const char *getAmmoKeyword(int ammo){
  if(ammo < AMMO_NONE ||
     ammo >= AMMO_MAX){
    return shellkeyword[0];
  }

  return shellkeyword[ammo];
}

const char *getAmmoDescr(int ammo){
  if(ammo < AMMO_NONE ||
     ammo >= AMMO_MAX){
    return shelldesc[0];
  }

  return shelldesc[ammo];
}

void dropSpentCasing(TRoom *roomp, int ammo){
  TObj *obj;
  char buf[256];

  int robj = real_object(13874);
  if (robj < 0 || robj >= (signed int) obj_index.size()) {
    vlogf(LOG_BUG, "dropSpentCasing(): No object (%d) in database!", 13874);
    return;
  }

  obj = read_object(robj, REAL);

  obj->swapToStrung();

  sprintf(buf, "casing spent %s", getAmmoDescr(ammo));
  delete [] obj->name;
  obj->name = mud_str_dup(buf);

  sprintf(buf, "<o>a spent %s casing<1>", getAmmoDescr(ammo));
  delete [] obj->shortDescr;
  obj->shortDescr = mud_str_dup(buf);

  sprintf(buf, "A spent <o>%s casing<1> lies here.", getAmmoDescr(ammo));
  delete [] obj->descr;
  obj->setDescr(mud_str_dup(buf));

  *roomp += *obj;

  return;
}

// ammo types
// 0 - none
// 1 - 10mm
// 2 - 9mm
// 3 - .22
// 4 - .45
// 5 - .50
// 6 - .357

void gload_usage(TBeing *tb){
  tb->sendTo("Syntax : (loading)   gload <gun> <ammo>\n\r");
  tb->sendTo("Syntax : (unloading) gload unload <gun>\n\r");
  return;
}

void TBeing::doGload(const char *arg)
{
  char    arg1[128],
          arg2[128], buf[256];
  TObj  *bow;
  TThing  *arrow;
  TGun *gun;
  TAmmo *ammo;
  int nargs;
  TBeing *tb;

  nargs=sscanf(arg, "%s %s", arg1, arg2);

  if(nargs<1 || nargs>2){
    gload_usage(this);
    return;
  }

  if(strcmp(arg1, "unload")){
    generic_find(arg1, FIND_OBJ_INV | FIND_OBJ_EQUIP, this, &tb, &bow);

    if(!bow || !(gun=dynamic_cast<TGun *>(bow))){
      gload_usage(this);
      return;
    }

    if(nargs==1){
      strcpy(arg2, getAmmoKeyword(gun->getAmmoType()));
    }

    if(!(arrow = searchLinkedListVis(this, arg2, stuff)) ||
       !(ammo=dynamic_cast<TAmmo *>(arrow))){
      gload_usage(this);
      return;
    }

    if(gun->getAmmo()){
      sprintf(buf, "unload %s", arg1);
      doGload(buf);
      if(gun->getAmmo()){
	sendTo("That gun is already loaded!\n\r");
	return;
      }
    }

    if(ammo->getAmmoType() != gun->getAmmoType()){
      sendTo("That isn't the right kind of ammunition.\n\r");
      return;
    }

    --(*ammo);
    gun->setAmmo(ammo);

    act("You load $p into $N.", TRUE, this, ammo, gun, TO_CHAR);
    act("$n loads $p into $N.", TRUE, this, ammo, gun, TO_ROOM);
    addToWait(combatRound(1));
  } else {
    generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_EQUIP, this, &tb, &bow);

    if (!bow || !(gun=dynamic_cast<TGun *>(bow))){
      gload_usage(this);
      return;
    }

    if(!(ammo=gun->getAmmo())){
      sendTo("That gun isn't loaded!\n\r");
      return;
    }

    arrow=dynamic_cast<TThing *>(ammo);

    if(ammo->getRounds() == 0){
      *roomp += *ammo;

      act("You unload $N and drop $p.", TRUE, this, ammo, gun, TO_CHAR);
      act("$n unloads $N and drops $p.", TRUE, this, ammo, gun, TO_ROOM);
    } else {
      arrow->nextThing=stuff;
      stuff=arrow;
      arrow->parent=this;

      act("You unload $N.", TRUE, this, ammo, gun, TO_CHAR);
      act("$n unloads $N.", TRUE, this, ammo, gun, TO_ROOM);
    }

    gun->setAmmo(NULL);
    addToWait(combatRound(1));
  }
}

string TGun::statObjInfo() const
{
  char buf[256];

  TObj::statObjInfo();

  sprintf(buf, "Rate of Fire: %i, Ammo Type: %s, Ammo: %i, Ammo Loaded: %s",
	  getROF(), getAmmoDescr(getAmmoType()), (ammo?ammo->getRounds():0),
	  (ammo?ammo->getName():"None"));

  string a(buf);
  return a;
}

void TGun::describeObjectSpecifics(const TBeing *ch) const
{
  if(getAmmo()){
    ch->sendTo("It has %i rounds of %s ammunition left.\n\r",
	       getAmmo()->getRounds(), getAmmoDescr(getAmmoType()));
  } else {
    // yeah yeah bad grammar, may as well be consistant though
    ch->sendTo("Is has 0 rounds of %s ammunition left.\n\r",
	       getAmmoDescr(getAmmoType()));
  }

}

void TAmmo::describeObjectSpecifics(const TBeing *ch) const
{
  ch->sendTo("It has %i rounds of %s ammunition left.\n\r",
	     getRounds(), getAmmoDescr(getAmmoType()));

}

void TGun::assignFourValues(int x1, int x2, int x3, int x4)
{
  setROF(x1);
  setWeapDamLvl(x2);
  setWeapDamDev(x3);
  setAmmoType(x4);
}

void TGun::getFourValues(int *x1, int *x2, int *x3, int *x4) const {
  *x1=getROF();
  *x2=getWeapDamLvl();
  *x3=getWeapDamDev();
  *x4=getAmmoType();
}

TGun::TGun() :
  TGenWeapon(),
  rof(1),
  ammotype(1),
  ammo(NULL)
{
  setMaxSharp(100);
  setCurSharp(100);

}

TGun::TGun(const TGun &a) :
  TGenWeapon(a),
  rof(a.rof),
  ammotype(a.ammotype),
  ammo(NULL)
{
}

TGun & TGun::operator=(const TGun &a)
{
  if (this == &a) return *this;
  TGenWeapon::operator=(a);
  return *this;
}

TGun::~TGun()
{
  delete ammo;
}

string TAmmo::statObjInfo() const
{
  char buf[256];

  sprintf(buf, "Ammo Type: %s, Rounds Remaining: %i",
	  getAmmoDescr(getAmmoType()), getRounds());

  string a(buf);
  return a;
}

TAmmo::TAmmo() :
  TObj()
{
}

TAmmo::TAmmo(const TAmmo &a) :
  TObj(a),
  ammotype(a.ammotype),
  rounds(a.rounds)
{
}

TAmmo & TAmmo::operator=(const TAmmo &a)
{
  if (this == &a) return *this;
  TObj::operator=(a);
  ammotype=a.ammotype;
  rounds=a.rounds;
  return *this;
}

TAmmo::~TAmmo()
{
}

void TAmmo::assignFourValues(int x1, int x2, int x3, int x4){
  setAmmoType(x1);
  setRounds(x2);

}

void TAmmo::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = getAmmoType();
  *x2 = getRounds();
  *x3 = 0;
  *x4 = 0;
}

<commit_msg>oops small bug<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"

enum ammoTypeT {
  AMMO_NONE,                    // 0
  AMMO_10MM_PISTOL,             // 1
  AMMO_9MM_PARABELLEM_PISTOL,   // 2
  AMMO_45CAL_ACP_PISTOL,        // 3
  AMMO_50CAL_AE_PISTOL,         // 4
  AMMO_44CAL_MAGNUM_PISTOL,     // 5
  AMMO_32CAL_ACP_PISTOL,        // 6
  AMMO_50CAL_BMG_PISTOL,        // 7
  AMMO_556MM_NATO_PISTOL,       // 8
  AMMO_SS190,                   // 9
  AMMO_9MM_PARABELLEM_RIFLE,    // 10
  AMMO_45CAL_ACP_RIFLE,         // 11
  AMMO_556MM_RIFLE,             // 12
  AMMO_762MM_RIFLE,             // 13
  AMMO_30CAL_RIFLE,             // 14
  AMMO_MAX
};

const char *shelldesc [] =
{
  "None",
  "10mm pistol",
  "9mm Parabellem pistol",
  ".45cal ACP pistol",
  ".50cal Action Express",
  ".44cal Magnum",
  ".32cal ACP",
  ".50cal BMG",
  "5.56mm NATO pistol"
  "SS190",
  "9mm Parabellem rifle",
  ".45cal ACP rifle",
  "5.56mm rifle",
  "7.62mm rifle",
  "30cal rifle",
};

const char *shellkeyword [] =
{
  "None",
  "10mmPistol",
  "9mmPistol",
  "45calPistol",
  "50calAE",
  "44calMag",
  "32calACP",
  "50calBMG",
  "556mmPistol"
  "SS190",
  "9mmRifle",
  "45calRifle",
  "556mmRifle",
  "762mmRifle",
  "30calRifle"
};

const char *getAmmoKeyword(int ammo){
  if(ammo < AMMO_NONE ||
     ammo >= AMMO_MAX){
    return shellkeyword[0];
  }

  return shellkeyword[ammo];
}

const char *getAmmoDescr(int ammo){
  if(ammo < AMMO_NONE ||
     ammo >= AMMO_MAX){
    return shelldesc[0];
  }

  return shelldesc[ammo];
}

void dropSpentCasing(TRoom *roomp, int ammo){
  TObj *obj;
  char buf[256];

  int robj = real_object(13874);
  if (robj < 0 || robj >= (signed int) obj_index.size()) {
    vlogf(LOG_BUG, "dropSpentCasing(): No object (%d) in database!", 13874);
    return;
  }

  obj = read_object(robj, REAL);

  obj->swapToStrung();

  sprintf(buf, "casing spent %s", getAmmoDescr(ammo));
  delete [] obj->name;
  obj->name = mud_str_dup(buf);

  sprintf(buf, "<o>a spent %s casing<1>", getAmmoDescr(ammo));
  delete [] obj->shortDescr;
  obj->shortDescr = mud_str_dup(buf);

  sprintf(buf, "A spent <o>%s casing<1> lies here.", getAmmoDescr(ammo));
  delete [] obj->descr;
  obj->setDescr(mud_str_dup(buf));

  *roomp += *obj;

  return;
}

// ammo types
// 0 - none
// 1 - 10mm
// 2 - 9mm
// 3 - .22
// 4 - .45
// 5 - .50
// 6 - .357

void gload_usage(TBeing *tb){
  tb->sendTo("Syntax : (loading)   gload <gun> <ammo>\n\r");
  tb->sendTo("Syntax : (unloading) gload unload <gun>\n\r");
  return;
}

void TBeing::doGload(const char *arg)
{
  char    arg1[128],
          arg2[128], buf[256];
  TObj  *bow;
  TThing  *arrow;
  TGun *gun;
  TAmmo *ammo;
  int nargs;
  TBeing *tb;

  nargs=sscanf(arg, "%s %s", arg1, arg2);

  if(nargs<1 || nargs>2){
    gload_usage(this);
    return;
  }

  if(strcmp(arg1, "unload")){
    generic_find(arg1, FIND_OBJ_INV | FIND_OBJ_EQUIP, this, &tb, &bow);

    if(!bow || !(gun=dynamic_cast<TGun *>(bow))){
      gload_usage(this);
      return;
    }

    if(nargs==1){
      strcpy(arg2, getAmmoKeyword(gun->getAmmoType()));
    }

    if(!(arrow = searchLinkedListVis(this, arg2, stuff)) ||
       !(ammo=dynamic_cast<TAmmo *>(arrow))){
      gload_usage(this);
      return;
    }

    if(gun->getAmmo()){
      sprintf(buf, "unload %s", arg1);
      doGload(buf);
      if(gun->getAmmo()){
	sendTo("That gun is already loaded!\n\r");
	return;
      }
    }

    if(ammo->getAmmoType() != gun->getAmmoType()){
      sendTo("That isn't the right kind of ammunition.\n\r");
      return;
    }

    --(*ammo);
    gun->setAmmo(ammo);

    act("You load $p into $N.", TRUE, this, ammo, gun, TO_CHAR);
    act("$n loads $p into $N.", TRUE, this, ammo, gun, TO_ROOM);
    addToWait(combatRound(1));
  } else {
    generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_EQUIP, this, &tb, &bow);

    if (!bow || !(gun=dynamic_cast<TGun *>(bow))){
      gload_usage(this);
      return;
    }

    if(!(ammo=gun->getAmmo())){
      sendTo("That gun isn't loaded!\n\r");
      return;
    }

    arrow=dynamic_cast<TThing *>(ammo);

    if(ammo->getRounds() == 0){
      *roomp += *ammo;

      act("You unload $N and drop $p.", TRUE, this, ammo, gun, TO_CHAR);
      act("$n unloads $N and drops $p.", TRUE, this, ammo, gun, TO_ROOM);
    } else {
      arrow->nextThing=stuff;
      stuff=arrow;
      arrow->parent=this;

      act("You unload $N.", TRUE, this, ammo, gun, TO_CHAR);
      act("$n unloads $N.", TRUE, this, ammo, gun, TO_ROOM);
    }

    gun->setAmmo(NULL);
    addToWait(combatRound(1));
  }
}

string TGun::statObjInfo() const
{
  char buf[256];

  TGenWeapon::statObjInfo();

  sprintf(buf, "Rate of Fire: %i, Ammo Type: %s, Ammo: %i, Ammo Loaded: %s",
	  getROF(), getAmmoDescr(getAmmoType()), (ammo?ammo->getRounds():0),
	  (ammo?ammo->getName():"None"));

  string a(buf);
  return a;
}

void TGun::describeObjectSpecifics(const TBeing *ch) const
{
  if(getAmmo()){
    ch->sendTo("It has %i rounds of %s ammunition left.\n\r",
	       getAmmo()->getRounds(), getAmmoDescr(getAmmoType()));
  } else {
    // yeah yeah bad grammar, may as well be consistant though
    ch->sendTo("Is has 0 rounds of %s ammunition left.\n\r",
	       getAmmoDescr(getAmmoType()));
  }

}

void TAmmo::describeObjectSpecifics(const TBeing *ch) const
{
  ch->sendTo("It has %i rounds of %s ammunition left.\n\r",
	     getRounds(), getAmmoDescr(getAmmoType()));

}

void TGun::assignFourValues(int x1, int x2, int x3, int x4)
{
  setROF(x1);
  setWeapDamLvl(x2);
  setWeapDamDev(x3);
  setAmmoType(x4);
}

void TGun::getFourValues(int *x1, int *x2, int *x3, int *x4) const {
  *x1=getROF();
  *x2=getWeapDamLvl();
  *x3=getWeapDamDev();
  *x4=getAmmoType();
}

TGun::TGun() :
  TGenWeapon(),
  rof(1),
  ammotype(1),
  ammo(NULL)
{
  setMaxSharp(100);
  setCurSharp(100);

}

TGun::TGun(const TGun &a) :
  TGenWeapon(a),
  rof(a.rof),
  ammotype(a.ammotype),
  ammo(NULL)
{
}

TGun & TGun::operator=(const TGun &a)
{
  if (this == &a) return *this;
  TGenWeapon::operator=(a);
  return *this;
}

TGun::~TGun()
{
  delete ammo;
}

string TAmmo::statObjInfo() const
{
  char buf[256];

  sprintf(buf, "Ammo Type: %s, Rounds Remaining: %i",
	  getAmmoDescr(getAmmoType()), getRounds());

  string a(buf);
  return a;
}

TAmmo::TAmmo() :
  TObj()
{
}

TAmmo::TAmmo(const TAmmo &a) :
  TObj(a),
  ammotype(a.ammotype),
  rounds(a.rounds)
{
}

TAmmo & TAmmo::operator=(const TAmmo &a)
{
  if (this == &a) return *this;
  TObj::operator=(a);
  ammotype=a.ammotype;
  rounds=a.rounds;
  return *this;
}

TAmmo::~TAmmo()
{
}

void TAmmo::assignFourValues(int x1, int x2, int x3, int x4){
  setAmmoType(x1);
  setRounds(x2);

}

void TAmmo::getFourValues(int *x1, int *x2, int *x3, int *x4) const
{
  *x1 = getAmmoType();
  *x2 = getRounds();
  *x3 = 0;
  *x4 = 0;
}

<|endoftext|>


<commit_before>/**
*  Copyright (C) 2021 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero 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
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "repo_license.h"
#include "repo_log.h"
#include "datastructure/repo_uuid.h"
#include "repo_exception.h"
#include "repo_utils.h"

using namespace repo::lib;

#ifdef REPO_LICENSE_CHECK
#include "cryptolens/Error.hpp"

static const std::string licenseEnvVarName = "REPO_LICENSE";
static const std::string instanceUuidEnvVarName = "REPO_INSTANCE_ID";

static const std::string pubKeyModulus = LICENSE_RSA_PUB_KEY_MOD;
static const std::string pubKeyExponent = LICENSE_RSA_PUB_KEY_EXP;
static const std::string authToken = LICENSE_AUTH_TOKEN;
static const int floatingTimeIntervalSec = LICENSE_TIMEOUT_SECONDS;
static const int productId = LICENSE_PRODUCT_ID;

std::string LicenseValidator::getInstanceUuid()
{
	instanceUuid = instanceUuid.empty() ? repo::lib::getEnvString(instanceUuidEnvVarName) : instanceUuid;
	if (instanceUuid.empty())
	{
		instanceUuid = repo::lib::RepoUUID::createUUID().toString();
		repoInfo << instanceUuidEnvVarName << " is not set. Setting machine instance ID to " << instanceUuid;
	}
	return instanceUuid;
}

std::string LicenseValidator::getLicenseString()
{
	std::string licenseStr = repo::lib::getEnvString(licenseEnvVarName);
	if (licenseStr.empty())
	{
		std::string errMsg = "License not found, please ensure " + licenseEnvVarName + " is set.";
		repoError << errMsg;
		throw repo::lib::RepoInvalidLicenseException(errMsg);
	}
	return licenseStr;
}

std::string LicenseValidator::getFormattedUtcTime(time_t timeStamp)
{
	struct tm  tstruct = *gmtime(&timeStamp);
	char buf[80];
	strftime(buf, sizeof(buf), "%Y/%m/%d %X", &tstruct);
	std::string formatedStr(buf);
	return formatedStr;
}

bool LicenseValidator::sendActivateRequest(bool verbose) {
	cryptolens::Error e;
	cryptolens::optional<cryptolens::LicenseKey> licenseKey =
		cryptolensHandle->activate_floating
		(
			e,
			authToken,
			productId,
			license,
			floatingTimeIntervalSec
		);

	if (e)
	{
		cryptolens::ActivateError error = cryptolens::ActivateError::from_reason(e.get_reason());
		std::string errMsg = error.what();
		repoError << "License activation failed: " << errMsg;
		return false;
	}
	else
	{
		bool licenseBlocked = licenseKey->get_block();
		bool licenseExpired = static_cast<bool>(licenseKey->check().has_expired(time(0)));
		if (!licenseExpired && !licenseBlocked)
		{
			if (verbose) {
				repoTrace << "****License activation summary****";
				repoTrace << "- session license ID: " << instanceUuid;
				repoTrace << "- server message: " << (licenseKey->get_notes().has_value() ? licenseKey->get_notes().value() : "");
				repoTrace << "- server respose ok: true";
				repoTrace << "- license blocked: " << licenseBlocked;
				repoTrace << "- license expired: " << licenseExpired;
				repoTrace << "- license expiry on: " << getFormattedUtcTime(licenseKey->get_expires()) << " (UTC)";
				if (licenseKey->get_activated_machines().has_value()) repoTrace << "- #activated instances: " << licenseKey->get_activated_machines()->size();
				if (licenseKey->get_maxnoofmachines().has_value()) repoTrace << "- allowed instances: " << licenseKey->get_maxnoofmachines().value();
				repoInfo << "License activated";
				repoTrace << "**********************************";
			}
			return true;
		}
		else
		{
			std::string errMsg = licenseExpired ? "License expired." : " License is blocked";
			repoError << "License activation failed: " << errMsg;
			deactivate();
			return false;
		}
	}
}

void LicenseValidator::runHeartBeatLoop() {
	auto interval = floatingTimeIntervalSec <= 10 ? floatingTimeIntervalSec / 2 : 5;
	while (true) {
		std::this_thread::sleep_for(std::chrono::seconds(interval));
		if (!sendHeartBeat.load()) {
			repoTrace << "Signal received to stop heart beat";
			break;
		}
		auto start = std::chrono::high_resolution_clock::now();
		if (!sendActivateRequest()) {
			auto stop = std::chrono::high_resolution_clock::now();
			auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
			repoError << "Heart beat to license server was not acknowledged [" << std::to_string(duration.count()) << "ms]";
			break;
		}
		auto stop = std::chrono::high_resolution_clock::now();
		auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
		repoTrace << "Heart beat acknowledged ["<< std::to_string(duration.count()) << "ms]";
	}
}

#endif

void LicenseValidator::activate()
{
#ifdef REPO_LICENSE_CHECK
	if (!instanceUuid.empty() || cryptolensHandle)
	{
		repoError << " Attempting to activate more than once, aborting activation";
		return;
	}

	license = getLicenseString();
	cryptolens::Error e;
	cryptolensHandle = std::unique_ptr<Cryptolens>(new Cryptolens(e));
	cryptolensHandle->signature_verifier.set_modulus_base64(e, pubKeyModulus);
	cryptolensHandle->signature_verifier.set_exponent_base64(e, pubKeyExponent);

	cryptolensHandle->machine_code_computer.set_machine_code(e, getInstanceUuid());

	if (e || !sendActivateRequest(true)) {
		std::string errMsg = "Failed to activate license";
		if (e) {
			cryptolens::ActivateError error = cryptolens::ActivateError::from_reason(e.get_reason());
			errMsg = error.what();
		}

		throw repo::lib::RepoInvalidLicenseException(errMsg);
	}

	// launch a thread to keep sending heart beats
	auto thread = new std::thread([](LicenseValidator *obj) {obj->runHeartBeatLoop();}, this);
	heartBeatThread = std::unique_ptr<std::thread>(thread);

#endif
}

void LicenseValidator::deactivate()
{
#ifdef REPO_LICENSE_CHECK
	if (instanceUuid.empty() || !cryptolensHandle)
	{
		repoError << " Attempting to deactivate without activation, aborting deactivation";
		return;
	}

	if (heartBeatThread) {
		repoInfo << "Waiting for heart beat thread to finish...";
		sendHeartBeat.store(false);
		heartBeatThread->join();
	}

	cryptolens::Error e;
	cryptolensHandle->deactivate(
		e,
		authToken,
		productId,
		license,
		instanceUuid,
		true);

	if (e)
	{
		repoTrace << "****License deactivation summary****";
		cryptolens::ActivateError error = cryptolens::ActivateError::from_reason(e.get_reason());
		repoTrace << "- server message: " << error.what();
		repoTrace << "- session license ID: " << instanceUuid;
		repoTrace << "- deactivation result: session not removed from license. Error trying to deactivate license. ";
		repoTrace << " this allocation will time out in less than " << floatingTimeIntervalSec << " seconds";
		repoTrace << "************************************";
		repoTrace << "License deactivation failed: " << error.what();
	}

	cryptolensHandle.reset();
	instanceUuid.clear();
#endif
}<commit_msg>ISSUE #519 remove timings<commit_after>/**
*  Copyright (C) 2021 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero 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
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "repo_license.h"
#include "repo_log.h"
#include "datastructure/repo_uuid.h"
#include "repo_exception.h"
#include "repo_utils.h"

using namespace repo::lib;

#ifdef REPO_LICENSE_CHECK
#include "cryptolens/Error.hpp"

static const std::string licenseEnvVarName = "REPO_LICENSE";
static const std::string instanceUuidEnvVarName = "REPO_INSTANCE_ID";

static const std::string pubKeyModulus = LICENSE_RSA_PUB_KEY_MOD;
static const std::string pubKeyExponent = LICENSE_RSA_PUB_KEY_EXP;
static const std::string authToken = LICENSE_AUTH_TOKEN;
static const int floatingTimeIntervalSec = LICENSE_TIMEOUT_SECONDS;
static const int productId = LICENSE_PRODUCT_ID;

std::string LicenseValidator::getInstanceUuid()
{
	instanceUuid = instanceUuid.empty() ? repo::lib::getEnvString(instanceUuidEnvVarName) : instanceUuid;
	if (instanceUuid.empty())
	{
		instanceUuid = repo::lib::RepoUUID::createUUID().toString();
		repoInfo << instanceUuidEnvVarName << " is not set. Setting machine instance ID to " << instanceUuid;
	}
	return instanceUuid;
}

std::string LicenseValidator::getLicenseString()
{
	std::string licenseStr = repo::lib::getEnvString(licenseEnvVarName);
	if (licenseStr.empty())
	{
		std::string errMsg = "License not found, please ensure " + licenseEnvVarName + " is set.";
		repoError << errMsg;
		throw repo::lib::RepoInvalidLicenseException(errMsg);
	}
	return licenseStr;
}

std::string LicenseValidator::getFormattedUtcTime(time_t timeStamp)
{
	struct tm  tstruct = *gmtime(&timeStamp);
	char buf[80];
	strftime(buf, sizeof(buf), "%Y/%m/%d %X", &tstruct);
	std::string formatedStr(buf);
	return formatedStr;
}

bool LicenseValidator::sendActivateRequest(bool verbose) {
	cryptolens::Error e;
	cryptolens::optional<cryptolens::LicenseKey> licenseKey =
		cryptolensHandle->activate_floating
		(
			e,
			authToken,
			productId,
			license,
			floatingTimeIntervalSec
		);

	if (e)
	{
		cryptolens::ActivateError error = cryptolens::ActivateError::from_reason(e.get_reason());
		std::string errMsg = error.what();
		repoError << "License activation failed: " << errMsg;
		return false;
	}
	else
	{
		bool licenseBlocked = licenseKey->get_block();
		bool licenseExpired = static_cast<bool>(licenseKey->check().has_expired(time(0)));
		if (!licenseExpired && !licenseBlocked)
		{
			if (verbose) {
				repoTrace << "****License activation summary****";
				repoTrace << "- session license ID: " << instanceUuid;
				repoTrace << "- server message: " << (licenseKey->get_notes().has_value() ? licenseKey->get_notes().value() : "");
				repoTrace << "- server respose ok: true";
				repoTrace << "- license blocked: " << licenseBlocked;
				repoTrace << "- license expired: " << licenseExpired;
				repoTrace << "- license expiry on: " << getFormattedUtcTime(licenseKey->get_expires()) << " (UTC)";
				if (licenseKey->get_activated_machines().has_value()) repoTrace << "- #activated instances: " << licenseKey->get_activated_machines()->size();
				if (licenseKey->get_maxnoofmachines().has_value()) repoTrace << "- allowed instances: " << licenseKey->get_maxnoofmachines().value();
				repoInfo << "License activated";
				repoTrace << "**********************************";
			}
			return true;
		}
		else
		{
			std::string errMsg = licenseExpired ? "License expired." : " License is blocked";
			repoError << "License activation failed: " << errMsg;
			deactivate();
			return false;
		}
	}
}

void LicenseValidator::runHeartBeatLoop() {
	auto interval = floatingTimeIntervalSec <= 10 ? floatingTimeIntervalSec / 2 : 5;
	while (true) {
		std::this_thread::sleep_for(std::chrono::seconds(interval));
		if (!sendHeartBeat.load()) {
			repoTrace << "Signal received to stop heart beat";
			break;
		}
		if (!sendActivateRequest()) {
			repoError << "Heart beat to license server was not acknowledged";
			break;
		}
	}
}

#endif

void LicenseValidator::activate()
{
#ifdef REPO_LICENSE_CHECK
	if (!instanceUuid.empty() || cryptolensHandle)
	{
		repoError << " Attempting to activate more than once, aborting activation";
		return;
	}

	license = getLicenseString();
	cryptolens::Error e;
	cryptolensHandle = std::unique_ptr<Cryptolens>(new Cryptolens(e));
	cryptolensHandle->signature_verifier.set_modulus_base64(e, pubKeyModulus);
	cryptolensHandle->signature_verifier.set_exponent_base64(e, pubKeyExponent);

	cryptolensHandle->machine_code_computer.set_machine_code(e, getInstanceUuid());

	if (e || !sendActivateRequest(true)) {
		std::string errMsg = "Failed to activate license";
		if (e) {
			cryptolens::ActivateError error = cryptolens::ActivateError::from_reason(e.get_reason());
			errMsg = error.what();
		}

		throw repo::lib::RepoInvalidLicenseException(errMsg);
	}

	// launch a thread to keep sending heart beats
	auto thread = new std::thread([](LicenseValidator *obj) {obj->runHeartBeatLoop();}, this);
	heartBeatThread = std::unique_ptr<std::thread>(thread);

#endif
}

void LicenseValidator::deactivate()
{
#ifdef REPO_LICENSE_CHECK
	if (instanceUuid.empty() || !cryptolensHandle)
	{
		repoError << " Attempting to deactivate without activation, aborting deactivation";
		return;
	}

	if (heartBeatThread) {
		repoInfo << "Waiting for heart beat thread to finish...";
		sendHeartBeat.store(false);
		heartBeatThread->join();
	}

	cryptolens::Error e;
	cryptolensHandle->deactivate(
		e,
		authToken,
		productId,
		license,
		instanceUuid,
		true);

	if (e)
	{
		repoTrace << "****License deactivation summary****";
		cryptolens::ActivateError error = cryptolens::ActivateError::from_reason(e.get_reason());
		repoTrace << "- server message: " << error.what();
		repoTrace << "- session license ID: " << instanceUuid;
		repoTrace << "- deactivation result: session not removed from license. Error trying to deactivate license. ";
		repoTrace << " this allocation will time out in less than " << floatingTimeIntervalSec << " seconds";
		repoTrace << "************************************";
		repoTrace << "License deactivation failed: " << error.what();
	}

	cryptolensHandle.reset();
	instanceUuid.clear();
#endif
}<|endoftext|>


<commit_before><commit_msg>Fixing memory leak.<commit_after><|endoftext|>


<commit_before>//
// Created by Darren Otgaar on 2016/03/22.
//

#ifndef ZAP_ENGINE_HPP
#define ZAP_ENGINE_HPP

#include <core/core.hpp>
#include <maths/maths.hpp>

#include <memory>
#include <cassert>
#include <cstdint>

#define LOGGING_ENABLED
#include "tools/log.hpp"

namespace zap { namespace engine {
    using resource_t = std::uint32_t;
    constexpr resource_t INVALID_RESOURCE = resource_t(-1);

    // Engine Definitions and Enumerations
    enum class shader_type : std::uint8_t {
        ST_VERTEX,
        ST_GEOMETRY,
        ST_FRAGMENT,
        ST_SIZE
    };

    enum class buffer_type : std::uint8_t {
        BT_ARRAY,
        BT_ELEMENT_ARRAY,
        BT_COPY_READ,
        BT_COPY_WRITE,
        BT_PIXEL_PACK,
        BT_PIXEL_UNPACK,
        BT_TEXTURE,
        BT_TRANSFORM,
        BT_UNIFORM,
        BT_SIZE
    };

    enum class buffer_usage : std::uint8_t {
        BU_STATIC_DRAW,
        BU_STATIC_READ,
        BU_STATIC_COPY,
        BU_DYNAMIC_DRAW,
        BU_DYNAMIC_READ,
        BU_DYNAMIC_COPY,
        BU_STREAM_DRAW,
        BU_STREAM_READ,
        BU_STREAM_COPY,
        BU_SIZE
    };

    enum class buffer_access : std::uint8_t {
        BA_READ_ONLY,
        BA_WRITE_ONLY,
        BA_READ_WRITE,
        BA_SIZE
    };

    enum class data_type : std::uint8_t {
        DT_VOID = 0,
        DT_UBYTE = 1,
        DT_BYTE = 2,
        DT_USHORT = 3,
        DT_SHORT = 4,
        DT_UINT = 5,
        DT_INT = 6,
        DT_HALF_FLOAT = 7,
        DT_FIXED = 8,
        DT_FLOAT = 9,
        DT_DOUBLE = 10,
        DT_SIZE = 11
    };

    enum class pixel_format : size_t {
        PF_NONE = 0,
        PF_RED,
        PF_RG,
        PF_RGB,
        PF_BGR,
        PF_RGBA,
        PF_BGRA,
        PF_DEPTH_COMPONENT,
        PF_DEPTH_STENCIL,
        PF_SIZE
    };

    enum class pixel_datatype : size_t {
        PD_NONE = 0,
        PD_UNSIGNED_BYTE_3_3_2,
        PD_UNSIGNED_BYTE,
        PD_FLOAT,
        PD_UNSIGNED_INT_24_8,
        PD_UNSIGNED_INT,
        PD_DN_UNSIGNED_BYTE, // denormalised unsigned byte
        PD_SIZE
    };

    template <typename T> struct dt_descriptor { enum { value = int(data_type::DT_VOID) }; };
    template <> struct dt_descriptor<unsigned char> { enum { value = int(data_type::DT_UBYTE) }; };
    template <> struct dt_descriptor<char> { enum { value = int(data_type::DT_BYTE) }; };
    template <> struct dt_descriptor<unsigned short> { enum { value = int(data_type::DT_USHORT) }; };
    template <> struct dt_descriptor<short> { enum { value = int(data_type::DT_SHORT) }; };
    template <> struct dt_descriptor<unsigned int> { enum { value = int(data_type::DT_UINT) }; };
    template <> struct dt_descriptor<int> { enum { value = int(data_type::DT_INT) }; };
    template <> struct dt_descriptor<float> { enum { value = int(data_type::DT_FLOAT) }; };
    template <> struct dt_descriptor<double> { enum { value = int(data_type::DT_DOUBLE) }; };

    template <data_type DT> struct dt_type { using type = void; };
    template <> struct dt_type<data_type::DT_UBYTE> { using type = unsigned char; };
    template <> struct dt_type<data_type::DT_BYTE> { using type = char; };
    template <> struct dt_type<data_type::DT_USHORT> { using type = unsigned short; };
    template <> struct dt_type<data_type::DT_SHORT> { using type = short; };
    template <> struct dt_type<data_type::DT_UINT> { using type = unsigned int; };
    template <> struct dt_type<data_type::DT_INT> { using type = int; };
    template <> struct dt_type<data_type::DT_HALF_FLOAT> { using type = void; };
    template <> struct dt_type<data_type::DT_FIXED> { using type = void; };
    template <> struct dt_type<data_type::DT_FLOAT> { using type = float; };
    template <> struct dt_type<data_type::DT_DOUBLE> { using type = double; };
    template <> struct dt_type<data_type::DT_SIZE> { using type = void; };

    inline size_t dt_bytesize(data_type dt) {
        switch(dt) {
            case data_type::DT_VOID: return 0;
            case data_type::DT_UBYTE: return sizeof(dt_type<data_type::DT_UBYTE>);
            case data_type::DT_BYTE: return sizeof(dt_type<data_type::DT_BYTE>);
            case data_type::DT_USHORT: return sizeof(dt_type<data_type::DT_USHORT>);
            case data_type::DT_SHORT: return sizeof(dt_type<data_type::DT_SHORT>);
            case data_type::DT_UINT: return sizeof(dt_type<data_type::DT_UINT>);
            case data_type::DT_INT: return sizeof(dt_type<data_type::DT_INT>);
            case data_type::DT_HALF_FLOAT: return sizeof(dt_type<data_type::DT_HALF_FLOAT>);
            case data_type::DT_FIXED: return sizeof(dt_type<data_type::DT_FIXED>);
            case data_type::DT_FLOAT: return sizeof(dt_type<data_type::DT_FLOAT>);
            case data_type::DT_DOUBLE: return sizeof(dt_type<data_type::DT_DOUBLE>);
            case data_type::DT_SIZE: return sizeof(dt_type<data_type::DT_SIZE>);
        }
    }
    enum class attribute_type : size_t {
        AT_POSITION = 1 << 0,
        AT_NORMAL = 1 << 1,
        AT_TANGENT = 1 << 2,
        AT_BINORMAL = 1 << 3,
        AT_TEXCOORD1 = 1 << 4,
        AT_TEXCOORD2 = 1 << 5,
        AT_TEXCOORD3 = 1 << 6,
        AT_TEXCOORD4 = 1 << 7,
        AT_TEXCOORD5 = 1 << 8,
        AT_TEXCOORD6 = 1 << 9,
        AT_COLOUR1 = 1 << 10,
        AT_COLOUR2 = 1 << 11,
        AT_BLENDINDEX = 1 << 12,
        AT_BLENDWEIGHT = 1 << 13,
        AT_FOGCOORD = 1 << 14,
        AT_POINTSIZE = 1 << 15,
        AT_SIZE = zap::maths::log2_pow2(1 << 16)
    };

    constexpr static const char* const attribute_name[size_t(attribute_type::AT_SIZE)] = {
            "position",
            "normal",
            "tangent",
            "binormal",
            "texcoord1",
            "texcoord2",
            "texcoord3",
            "texcoord4",
            "texcoord5",
            "texcoord6",
            "colour1",
            "colour2",
            "blendindex",
            "blendweight",
            "fogcoord",
            "pointsize"
    };

    enum class primitive_type : std::uint8_t {
        PT_NONE = 0,
        PT_POINTS = 1,
        PT_LINES = 2,
        PT_LINE_STRIP = 3,
        PT_LINE_LOOP = 4,
        PT_TRIANGLES = 5,
        PT_TRIANGLE_STRIP = 6,
        PT_TRIANGLE_FAN = 7,
        PT_SIZE = 8
    };

    enum class texture_type : std::uint8_t {
        TT_NONE = 0,
        TT_TEX1D = 1,
        TT_TEX2D = 2,
        TT_TEX3D = 3,
        TT_TEX2D_MS = 4,
        TT_CUBE_MAP = 5,
        TT_RECTANGLE = 6,
        TT_TEX1D_ARR = 7,
        TT_TEX2D_ARR = 8,
        TT_SIZE = 9
    };

    bool init();

    bool _gl_error_log(const char* file, int line);
    bool _gl_error_check();

#ifdef LOGGING_ENABLED
#define gl_error_check() _gl_error_log(__FILE__, __LINE__)
#else
#define gl_error_check() _gl_error_check()
#endif
}}

#endif //ZAP_ENGINE_HPP
<commit_msg>- Fixed sizeof operator for data_type<commit_after>//
// Created by Darren Otgaar on 2016/03/22.
//

#ifndef ZAP_ENGINE_HPP
#define ZAP_ENGINE_HPP

#include <core/core.hpp>
#include <maths/maths.hpp>

#include <memory>
#include <cassert>
#include <cstdint>

#define LOGGING_ENABLED
#include "tools/log.hpp"

namespace zap { namespace engine {
    using resource_t = std::uint32_t;
    constexpr resource_t INVALID_RESOURCE = resource_t(-1);

    // Engine Definitions and Enumerations
    enum class shader_type : std::uint8_t {
        ST_VERTEX,
        ST_GEOMETRY,
        ST_FRAGMENT,
        ST_SIZE
    };

    enum class buffer_type : std::uint8_t {
        BT_ARRAY,
        BT_ELEMENT_ARRAY,
        BT_COPY_READ,
        BT_COPY_WRITE,
        BT_PIXEL_PACK,
        BT_PIXEL_UNPACK,
        BT_TEXTURE,
        BT_TRANSFORM,
        BT_UNIFORM,
        BT_SIZE
    };

    enum class buffer_usage : std::uint8_t {
        BU_STATIC_DRAW,
        BU_STATIC_READ,
        BU_STATIC_COPY,
        BU_DYNAMIC_DRAW,
        BU_DYNAMIC_READ,
        BU_DYNAMIC_COPY,
        BU_STREAM_DRAW,
        BU_STREAM_READ,
        BU_STREAM_COPY,
        BU_SIZE
    };

    enum class buffer_access : std::uint8_t {
        BA_READ_ONLY,
        BA_WRITE_ONLY,
        BA_READ_WRITE,
        BA_SIZE
    };

    enum class data_type : std::uint8_t {
        DT_VOID = 0,
        DT_UBYTE = 1,
        DT_BYTE = 2,
        DT_USHORT = 3,
        DT_SHORT = 4,
        DT_UINT = 5,
        DT_INT = 6,
        DT_HALF_FLOAT = 7,
        DT_FIXED = 8,
        DT_FLOAT = 9,
        DT_DOUBLE = 10,
        DT_SIZE = 11
    };

    enum class pixel_format : size_t {
        PF_NONE = 0,
        PF_RED,
        PF_RG,
        PF_RGB,
        PF_BGR,
        PF_RGBA,
        PF_BGRA,
        PF_DEPTH_COMPONENT,
        PF_DEPTH_STENCIL,
        PF_SIZE
    };

    enum class pixel_datatype : size_t {
        PD_NONE = 0,
        PD_UNSIGNED_BYTE_3_3_2,
        PD_UNSIGNED_BYTE,
        PD_FLOAT,
        PD_UNSIGNED_INT_24_8,
        PD_UNSIGNED_INT,
        PD_DN_UNSIGNED_BYTE, // denormalised unsigned byte
        PD_SIZE
    };

    template <typename T> struct dt_descriptor { enum { value = int(data_type::DT_VOID) }; };
    template <> struct dt_descriptor<unsigned char> { enum { value = int(data_type::DT_UBYTE) }; };
    template <> struct dt_descriptor<char> { enum { value = int(data_type::DT_BYTE) }; };
    template <> struct dt_descriptor<unsigned short> { enum { value = int(data_type::DT_USHORT) }; };
    template <> struct dt_descriptor<short> { enum { value = int(data_type::DT_SHORT) }; };
    template <> struct dt_descriptor<unsigned int> { enum { value = int(data_type::DT_UINT) }; };
    template <> struct dt_descriptor<int> { enum { value = int(data_type::DT_INT) }; };
    template <> struct dt_descriptor<float> { enum { value = int(data_type::DT_FLOAT) }; };
    template <> struct dt_descriptor<double> { enum { value = int(data_type::DT_DOUBLE) }; };

    template <data_type DT> struct dt_type { using type = void; };
    template <> struct dt_type<data_type::DT_UBYTE> { using type = unsigned char;  };
    template <> struct dt_type<data_type::DT_BYTE> { using type = char; };
    template <> struct dt_type<data_type::DT_USHORT> { using type = unsigned short; };
    template <> struct dt_type<data_type::DT_SHORT> { using type = short; };
    template <> struct dt_type<data_type::DT_UINT> { using type = unsigned int; };
    template <> struct dt_type<data_type::DT_INT> { using type = int; };
    template <> struct dt_type<data_type::DT_HALF_FLOAT> { using type = void; };
    template <> struct dt_type<data_type::DT_FIXED> { using type = void; };
    template <> struct dt_type<data_type::DT_FLOAT> { using type = float; };
    template <> struct dt_type<data_type::DT_DOUBLE> { using type = double; };
    template <> struct dt_type<data_type::DT_SIZE> { using type = void; };

    inline size_t dt_bytesize(data_type dt) {
        switch(dt) {
            case data_type::DT_VOID: return 0;
            case data_type::DT_UBYTE: return sizeof(typename dt_type<data_type::DT_UBYTE>::type);
            case data_type::DT_BYTE: return sizeof(typename dt_type<data_type::DT_BYTE>::type);
            case data_type::DT_USHORT: return sizeof(typename dt_type<data_type::DT_USHORT>::type);
            case data_type::DT_SHORT: return sizeof(typename dt_type<data_type::DT_SHORT>::type);
            case data_type::DT_UINT: return sizeof(typename dt_type<data_type::DT_UINT>::type);
            case data_type::DT_INT: return sizeof(typename dt_type<data_type::DT_INT>::type);
            case data_type::DT_HALF_FLOAT: return 0;
            case data_type::DT_FIXED: return 0;
            case data_type::DT_FLOAT: return sizeof(dt_type<data_type::DT_FLOAT>::type);
            case data_type::DT_DOUBLE: return sizeof(dt_type<data_type::DT_DOUBLE>::type);
            case data_type::DT_SIZE: return 0;
        }
    }
    enum class attribute_type : size_t {
        AT_POSITION = 1 << 0,
        AT_NORMAL = 1 << 1,
        AT_TANGENT = 1 << 2,
        AT_BINORMAL = 1 << 3,
        AT_TEXCOORD1 = 1 << 4,
        AT_TEXCOORD2 = 1 << 5,
        AT_TEXCOORD3 = 1 << 6,
        AT_TEXCOORD4 = 1 << 7,
        AT_TEXCOORD5 = 1 << 8,
        AT_TEXCOORD6 = 1 << 9,
        AT_COLOUR1 = 1 << 10,
        AT_COLOUR2 = 1 << 11,
        AT_BLENDINDEX = 1 << 12,
        AT_BLENDWEIGHT = 1 << 13,
        AT_FOGCOORD = 1 << 14,
        AT_POINTSIZE = 1 << 15,
        AT_SIZE = zap::maths::log2_pow2(1 << 16)
    };

    constexpr static const char* const attribute_name[size_t(attribute_type::AT_SIZE)] = {
            "position",
            "normal",
            "tangent",
            "binormal",
            "texcoord1",
            "texcoord2",
            "texcoord3",
            "texcoord4",
            "texcoord5",
            "texcoord6",
            "colour1",
            "colour2",
            "blendindex",
            "blendweight",
            "fogcoord",
            "pointsize"
    };

    enum class primitive_type : std::uint8_t {
        PT_NONE = 0,
        PT_POINTS = 1,
        PT_LINES = 2,
        PT_LINE_STRIP = 3,
        PT_LINE_LOOP = 4,
        PT_TRIANGLES = 5,
        PT_TRIANGLE_STRIP = 6,
        PT_TRIANGLE_FAN = 7,
        PT_SIZE = 8
    };

    enum class texture_type : std::uint8_t {
        TT_NONE = 0,
        TT_TEX1D = 1,
        TT_TEX2D = 2,
        TT_TEX3D = 3,
        TT_TEX2D_MS = 4,
        TT_CUBE_MAP = 5,
        TT_RECTANGLE = 6,
        TT_TEX1D_ARR = 7,
        TT_TEX2D_ARR = 8,
        TT_SIZE = 9
    };

    bool init();

    bool _gl_error_log(const char* file, int line);
    bool _gl_error_check();

#ifdef LOGGING_ENABLED
#define gl_error_check() _gl_error_log(__FILE__, __LINE__)
#else
#define gl_error_check() _gl_error_check()
#endif
}}

#endif //ZAP_ENGINE_HPP
<|endoftext|>


<commit_before>#include <TypeCheckerVisitor.h>

std::shared_ptr<const std::vector<CCompilationError>> CTypeCheckerVisitor::Errors() const {
    return errors;
}

/*__________ Access Modifiers __________*/

void CTypeCheckerVisitor::Visit( const CPublicAccessModifier* modifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::ACCESS_MOD_PUBLIC );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CPrivateAccessModifier* modifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::ACCESS_MOD_PRIVATE );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

/*__________ Expressions __________*/

void CTypeCheckerVisitor::Visit( const CBinaryExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_BINARY );
    onNodeEnter( nodeName );

    expression->LeftOperand()->Accept( this );
    TTypeIdentifier leftOperandType = lastType;

    expression->RightOperand()->Accept( this );
    TTypeIdentifier RightOperandType = lastType;

    if ( leftOperandType != RightOperandType ) {
        errors->push_back( CCompilationError( ( expression )->Location(), CCompilationError::DIFFERENT_TYPES_OF_ARGUMENTS ) );
        lastType = TTypeIdentifier::NotFound;
    } else {
        lastType = leftOperandType;
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CBracketExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_BRACKET );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNumberExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NUMBER );
    onNodeEnter( nodeName );

    lastType = TTypeIdentifier::Int;

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CLogicExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_LOGIC );
    onNodeEnter( nodeName );

    lastType = TTypeIdentifier::Boolean;

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CIdExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_ID );
    onNodeEnter( nodeName );

    std::string expressionName = expression->Name();
    std::shared_ptr<const CClassDefinition> classInfo = symbolTablePtr->GetClassDefinition( lastClassName );
    if ( classInfo == nullptr ) {
        lastType = TTypeIdentifier::NotFound;
        return;
    }
    CTypeIdentifier typeId = classInfo->GetFieldType( expressionName );
    lastType = typeId.Type();

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CLengthExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_LENGTH );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_METHOD );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CThisExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_THIS );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNewArrayExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NEW_ARRAY );
    onNodeEnter( nodeName );

    expression->LengthExpression()->Accept( this );
    if ( lastType != TTypeIdentifier::Int ) {
        errors->push_back( CCompilationError( expression->Location(), CCompilationError::INVALID_LENGTH_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNewIdExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NEW_ID );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNegateExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NEGATE );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

/*__________ Statements __________*/

void CTypeCheckerVisitor::Visit( const CAssignIdStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_ASSIGN_ID );
    onNodeEnter( nodeName );

    statement->LeftPart()->Accept( this );
    TTypeIdentifier leftPartLocalType = lastType;

    statement->RightPart()->Accept( this );
    TTypeIdentifier rightPartLocalType = lastType;

    if ( leftPartLocalType != rightPartLocalType ) {
        errors->push_back( CCompilationError( ( statement->LeftPart() )->Location(), CCompilationError::DIFFERENT_TYPES_OF_ARGUMENTS ) );
        lastType = TTypeIdentifier::NotFound;
    } else {
        lastType = leftPartLocalType;
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CAssignIdWithIndexStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_ASSIGN_ID_WITH_INDEX );
    onNodeEnter( nodeName );

    statement->LeftPartId()->Accept( this );
    if ( lastType != TTypeIdentifier::Int ) {
        errors->push_back( CCompilationError( ( statement->LeftPartId() )->Location(), CCompilationError::INVALID_INDEX_TYPE ) );
    }

    // how to get type of elements in array???
    /*statement->LeftPart()->Accept( this );
    TTypeIdentifier leftPartLocalType = lastType;

    statement->RightPart()->Accept( this );
    TTypeIdentifier rightPartLocalType = lastType;

    if ( leftPartLocalType != rightPartLocalType ) {
        errors->push_back( CCompilationError( ( statement->LeftPart() )->Location(), CCompilationError::DIFFERENT_TYPES_OF_ARGUMENTS ) );
        lastType = TTypeIdentifier::NotFound;
    } else {
        lastType = leftPartLocalType;
    }
    */

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CPrintStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_PRINT );
    onNodeEnter( nodeName );

    statement->PrintTarget()->Accept( this );

    if ( lastType != TTypeIdentifier::Int ) {
        errors->push_back( CCompilationError( ( statement )->Location(), CCompilationError::INVALID_PRINT_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CConditionalStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_CONDITIONAL );
    onNodeEnter( nodeName );

    statement->Condition()->Accept( this );
    if ( lastType != TTypeIdentifier::Boolean ) {
        errors->push_back( CCompilationError( ( statement )->Location(), CCompilationError::INVALID_CONDITION_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CWhileLoopStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_WHILE_LOOP );
    onNodeEnter( nodeName );

    statement->Condition()->Accept( this );
    if ( lastType != TTypeIdentifier::Boolean ) {
        errors->push_back( CCompilationError( ( statement )->Location(), CCompilationError::INVALID_CONDITION_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CBracesStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_BRACES );
    onNodeEnter( nodeName );

    statement->List()->Accept( this );

    onNodeExit( nodeName );
}

/*__________ Type Modifiers __________*/

void CTypeCheckerVisitor::Visit( const CIntTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_INT );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CBooleanTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_BOOL );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CIntArrayTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_INT_ARRAY );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CIdTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_ID );
    onNodeEnter( nodeName );

    std::string className = typeModifier->TypeId()->Name();

    if ( symbolTablePtr->GetClassDefinition(className) == nullptr ) {
    	errors->push_back( CCompilationError( typeModifier->Location(), CCompilationError::TYPE_NOT_EXISTS ) );
    }

    onNodeExit( nodeName );
}

/*__________ Other (except lists) __________*/

void CTypeCheckerVisitor::Visit( const CVarDeclaration* declaration ) {
    std::string nodeName = generateNodeName( CAstNodeNames::VAR_DECL );
    onNodeEnter( nodeName );

    declaration->Type()->Accept( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodArgument* argument ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_ARG );
    onNodeEnter( nodeName );

    argument->Type()->Accept( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodDeclaration* declaration ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_DECL );
    onNodeEnter( nodeName );

	declaration->TypeModifier()->Accept( this );
	declaration->MethodArguments()->Accept( this );
    declaration->VarDeclarations()->Accept( this );
    declaration->Statements()->Accept( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMainClass* mainClass ) {
    std::string nodeName = generateNodeName( CAstNodeNames::MAIN_CLASS );
    onNodeEnter( nodeName );

    // write your code here

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CClassDeclaration* declaration ) {
    std::string nodeName = generateNodeName( CAstNodeNames::CLASS_DECL );
    onNodeEnter( nodeName );

    using TClassDefinition = std::shared_ptr<const CClassDefinition>;

    std::string thisClassName = declaration->ClassName()->Name();

    declaration->VarDeclarations()->Accept( this );
	declaration->MethodDeclarations()->Accept( this );

    if ( declaration->HasParent() ) {
	    std::string parentName = declaration->ExtendsClassName()->Name();
	    TClassDefinition parentClassDefinition = symbolTablePtr->GetClassDefinition(parentName);

	    if ( parentClassDefinition == nullptr ) {
	    	errors->push_back( CCompilationError( declaration->Location(), CCompilationError::PARENT_CLASS_NOT_EXISTS ) );
	    } else {
		    while ( parentClassDefinition != nullptr && parentClassDefinition->HasParent() && parentClassDefinition->ClassName() != thisClassName ) {
		    	parentName = parentClassDefinition->GetParentName();
		    	parentClassDefinition = symbolTablePtr->GetClassDefinition(parentName);
		    }

		    if ( parentName == thisClassName ) {
		    	errors->push_back( CCompilationError( declaration->Location(), CCompilationError::CYCLIC_INHERITANCE ) );
		    }
		}
	}

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CProgram* program ) {
    std::string nodeName = generateNodeName( CAstNodeNames::PROGRAM );
    onNodeEnter( nodeName );

    program->ClassDeclarations()->Accept( this );

    onNodeExit( nodeName );
}

/*__________  Lists __________*/

void CTypeCheckerVisitor::Visit( const CExpressionList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CExpression> >& expressions = list->Expressions();
    for ( auto it = expressions.rbegin(); it != expressions.rend(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CStatementList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CStatement> >& statements = list->Statements();
    for ( auto it = statements.rbegin(); it != statements.rend(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CVarDeclarationList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::VAR_DECL_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CVarDeclaration> >& varDeclarations = list->VarDeclarations();
    for ( auto it = varDeclarations.begin(); it != varDeclarations.end(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodArgumentList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_ARG_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CMethodArgument> >& methodArguments = list->MethodArguments();
    for ( auto it = methodArguments.begin(); it != methodArguments.end(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodDeclarationList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_DECL_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CMethodDeclaration> >& methodDeclarations = list->MethodDeclarations();
    for ( auto it = methodDeclarations.begin(); it != methodDeclarations.end(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CClassDeclarationList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::CLASS_DECL_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CClassDeclaration> >& classDeclarations = list->ClassDeclarations();
    for ( auto it = classDeclarations.begin(); it != classDeclarations.end(); ++it ) {
        lastClassName = ( *it )->ClassName()->Name();
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}
<commit_msg>Add all necessary visitors. Prepare for batle (testing)<commit_after>#include <TypeCheckerVisitor.h>

std::shared_ptr<const std::vector<CCompilationError>> CTypeCheckerVisitor::Errors() const {
    return errors;
}

/*__________ Access Modifiers __________*/

void CTypeCheckerVisitor::Visit( const CPublicAccessModifier* modifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::ACCESS_MOD_PUBLIC );
    onNodeEnter( nodeName );

    // TODO

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CPrivateAccessModifier* modifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::ACCESS_MOD_PRIVATE );
    onNodeEnter( nodeName );

    // TODO

    onNodeExit( nodeName );
}

/*__________ Expressions __________*/

void CTypeCheckerVisitor::Visit( const CBinaryExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_BINARY );
    onNodeEnter( nodeName );

    expression->LeftOperand()->Accept( this );
    TTypeIdentifier leftOperandType = lastType;

    expression->RightOperand()->Accept( this );
    TTypeIdentifier RightOperandType = lastType;

    if ( leftOperandType != RightOperandType ) {
        errors->push_back( CCompilationError( ( expression )->Location(), CCompilationError::DIFFERENT_TYPES_OF_ARGUMENTS ) );
        lastType = TTypeIdentifier::NotFound;
    } else {
        lastType = leftOperandType;
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CBracketExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_BRACKET );
    onNodeEnter( nodeName );

    expression->ContainerExpression()->Accept( this );
    expression->IndexExpression()->Accept( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNumberExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NUMBER );
    onNodeEnter( nodeName );

    lastType = TTypeIdentifier::Int;

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CLogicExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_LOGIC );
    onNodeEnter( nodeName );

    lastType = TTypeIdentifier::Boolean;

    onNodeExit( nodeName );
}

// ignored
void CTypeCheckerVisitor::Visit( const CIdExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_ID );
    onNodeEnter( nodeName );
<<<<<<< HEAD

    std::string expressionName = expression->Name();
    std::shared_ptr<const CClassDefinition> classInfo = symbolTablePtr->GetClassDefinition( lastClassName );
    if ( classInfo == nullptr ) {
        lastType = TTypeIdentifier::NotFound;
        return;
    }
    CTypeIdentifier typeId = classInfo->GetFieldType( expressionName );
    lastType = typeId.Type();

=======
>>>>>>> 349d093a6162efa86d6eda0a655aaf349d744eb0
    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CLengthExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_LENGTH );
    onNodeEnter( nodeName );

    expression->LengthTarget()->Accept ( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_METHOD );
    onNodeEnter( nodeName );

    expression->CallerExpression()->Accept( this );
    expression->Arguments()->Accept( this );

    onNodeExit( nodeName );
}

// ignored
void CTypeCheckerVisitor::Visit( const CThisExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_THIS );
    onNodeEnter( nodeName );
    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNewArrayExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NEW_ARRAY );
    onNodeEnter( nodeName );

    expression->LengthExpression()->Accept( this );
<<<<<<< HEAD
    if ( lastType != TTypeIdentifier::Int ) {
        errors->push_back( CCompilationError( expression->Location(), CCompilationError::INVALID_LENGTH_TYPE ) );
    }
=======
>>>>>>> 349d093a6162efa86d6eda0a655aaf349d744eb0

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNewIdExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NEW_ID );
    onNodeEnter( nodeName );

    std::string className = expression->TargetId()->Name();

    if ( symbolTablePtr->GetClassDefinition(className) == nullptr ) {
    	errors->push_back( CCompilationError( expression->Location(), CCompilationError::TYPE_NOT_EXISTS ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CNegateExpression* expression ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_NEGATE );
    onNodeEnter( nodeName );

    expression->TargetExpression()->Accept( this );

    onNodeExit( nodeName );
}

/*__________ Statements __________*/

void CTypeCheckerVisitor::Visit( const CAssignIdStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_ASSIGN_ID );
    onNodeEnter( nodeName );

    statement->LeftPart()->Accept( this );
    TTypeIdentifier leftPartLocalType = lastType;

    statement->RightPart()->Accept( this );
    TTypeIdentifier rightPartLocalType = lastType;

    if ( leftPartLocalType != rightPartLocalType ) {
        errors->push_back( CCompilationError( ( statement->LeftPart() )->Location(), CCompilationError::DIFFERENT_TYPES_OF_ARGUMENTS ) );
        lastType = TTypeIdentifier::NotFound;
    } else {
        lastType = leftPartLocalType;
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CAssignIdWithIndexStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_ASSIGN_ID_WITH_INDEX );
    onNodeEnter( nodeName );

    statement->LeftPartId()->Accept( this );
    if ( lastType != TTypeIdentifier::Int ) {
        errors->push_back( CCompilationError( ( statement->LeftPartId() )->Location(), CCompilationError::INVALID_INDEX_TYPE ) );
    }

    // how to get type of elements in array???
    /*statement->LeftPart()->Accept( this );
    TTypeIdentifier leftPartLocalType = lastType;

    statement->RightPart()->Accept( this );
    TTypeIdentifier rightPartLocalType = lastType;

    if ( leftPartLocalType != rightPartLocalType ) {
        errors->push_back( CCompilationError( ( statement->LeftPart() )->Location(), CCompilationError::DIFFERENT_TYPES_OF_ARGUMENTS ) );
        lastType = TTypeIdentifier::NotFound;
    } else {
        lastType = leftPartLocalType;
    }
    */

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CPrintStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_PRINT );
    onNodeEnter( nodeName );

    statement->PrintTarget()->Accept( this );

    if ( lastType != TTypeIdentifier::Int ) {
        errors->push_back( CCompilationError( ( statement )->Location(), CCompilationError::INVALID_PRINT_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CConditionalStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_CONDITIONAL );
    onNodeEnter( nodeName );

    statement->Condition()->Accept( this );
    if ( lastType != TTypeIdentifier::Boolean ) {
        errors->push_back( CCompilationError( ( statement )->Location(), CCompilationError::INVALID_CONDITION_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CWhileLoopStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_WHILE_LOOP );
    onNodeEnter( nodeName );

    statement->Condition()->Accept( this );
    if ( lastType != TTypeIdentifier::Boolean ) {
        errors->push_back( CCompilationError( ( statement )->Location(), CCompilationError::INVALID_CONDITION_TYPE ) );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CBracesStatement* statement ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_BRACES );
    onNodeEnter( nodeName );

    statement->List()->Accept( this );

    onNodeExit( nodeName );
}

/*__________ Type Modifiers __________*/

void CTypeCheckerVisitor::Visit( const CIntTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_INT );
    onNodeEnter( nodeName );

    // TODO

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CBooleanTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_BOOL );
    onNodeEnter( nodeName );

    // TODO

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CIntArrayTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_INT_ARRAY );
    onNodeEnter( nodeName );

    // TODO

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CIdTypeModifier* typeModifier ) {
    std::string nodeName = generateNodeName( CAstNodeNames::TYPE_MOD_ID );
    onNodeEnter( nodeName );

    std::string className = typeModifier->TypeId()->Name();

    if ( symbolTablePtr->GetClassDefinition(className) == nullptr ) {
    	errors->push_back( CCompilationError( typeModifier->Location(), CCompilationError::TYPE_NOT_EXISTS ) );
    }

    onNodeExit( nodeName );
}

/*__________ Other (except lists) __________*/

void CTypeCheckerVisitor::Visit( const CVarDeclaration* declaration ) {
    std::string nodeName = generateNodeName( CAstNodeNames::VAR_DECL );
    onNodeEnter( nodeName );

    declaration->Type()->Accept( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodArgument* argument ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_ARG );
    onNodeEnter( nodeName );

    argument->Type()->Accept( this );

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodDeclaration* declaration ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_DECL );
    onNodeEnter( nodeName );

	declaration->TypeModifier()->Accept( this );
	declaration->MethodArguments()->Accept( this );
    declaration->VarDeclarations()->Accept( this );
    declaration->Statements()->Accept( this );
    declaration->ReturnExpression()->Accept( this );

    onNodeExit( nodeName );
}

// ignored
void CTypeCheckerVisitor::Visit( const CMainClass* mainClass ) {
    std::string nodeName = generateNodeName( CAstNodeNames::MAIN_CLASS );
    onNodeEnter( nodeName );
    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CClassDeclaration* declaration ) {
    std::string nodeName = generateNodeName( CAstNodeNames::CLASS_DECL );
    onNodeEnter( nodeName );

    using TClassDefinition = std::shared_ptr<const CClassDefinition>;

    std::string thisClassName = declaration->ClassName()->Name();

    declaration->VarDeclarations()->Accept( this );
	declaration->MethodDeclarations()->Accept( this );

    if ( declaration->HasParent() ) {
	    std::string parentName = declaration->ExtendsClassName()->Name();
	    TClassDefinition parentClassDefinition = symbolTablePtr->GetClassDefinition(parentName);

	    if ( parentClassDefinition == nullptr ) {
	    	errors->push_back( CCompilationError( declaration->Location(), CCompilationError::PARENT_CLASS_NOT_EXISTS ) );
	    } else {
		    while ( parentClassDefinition != nullptr && parentClassDefinition->HasParent() && parentClassDefinition->ClassName() != thisClassName ) {
		    	parentName = parentClassDefinition->GetParentName();
		    	parentClassDefinition = symbolTablePtr->GetClassDefinition(parentName);
		    }

		    if ( parentName == thisClassName ) {
		    	errors->push_back( CCompilationError( declaration->Location(), CCompilationError::CYCLIC_INHERITANCE ) );
		    }
		}
	}

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CProgram* program ) {
    std::string nodeName = generateNodeName( CAstNodeNames::PROGRAM );
    onNodeEnter( nodeName );

    program->ClassDeclarations()->Accept( this );

    onNodeExit( nodeName );
}

/*__________  Lists __________*/

void CTypeCheckerVisitor::Visit( const CExpressionList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::EXP_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CExpression> >& expressions = list->Expressions();
    for ( auto it = expressions.rbegin(); it != expressions.rend(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CStatementList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::STAT_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CStatement> >& statements = list->Statements();
    for ( auto it = statements.rbegin(); it != statements.rend(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CVarDeclarationList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::VAR_DECL_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CVarDeclaration> >& varDeclarations = list->VarDeclarations();
    for ( auto it = varDeclarations.begin(); it != varDeclarations.end(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodArgumentList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_ARG_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CMethodArgument> >& methodArguments = list->MethodArguments();
    for ( auto it = methodArguments.begin(); it != methodArguments.end(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CMethodDeclarationList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::METH_DECL_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CMethodDeclaration> >& methodDeclarations = list->MethodDeclarations();
    for ( auto it = methodDeclarations.begin(); it != methodDeclarations.end(); ++it ) {
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}

void CTypeCheckerVisitor::Visit( const CClassDeclarationList* list ) {
    std::string nodeName = generateNodeName( CAstNodeNames::CLASS_DECL_LIST );
    onNodeEnter( nodeName );

    const std::vector< std::unique_ptr<const CClassDeclaration> >& classDeclarations = list->ClassDeclarations();
    for ( auto it = classDeclarations.begin(); it != classDeclarations.end(); ++it ) {
        lastClassName = ( *it )->ClassName()->Name();
        ( *it )->Accept( this );
    }

    onNodeExit( nodeName );
}
<|endoftext|>