<commit_before>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/SVD>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
  + "denoise DWI data and estimate the noise level based on the optimal threshold for PCA.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier.gmail.com)";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
  + Option ("size", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + ")")
    + Argument ("window").type_integer (0, 50)

  + Option ("noise", "the output noise map.")
    + Argument ("level").type_image_out();

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor
{
public:
  DenoisingFunctor (ImageType& dwi, int size)
    : extent(size/2),
      m(dwi.size(3)),
      n(size*size*size),
      r((m<n) ? m : n),
      X(m,n), Xm(m),
      pos{0, 0, 0}
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    // Load data in local window
    load_data(dwi);
    // Centre data
    Xm = X.rowwise().mean();
    X.colwise() -= Xm;
    // Compute SVD
    Eigen::JacobiSVD<Eigen::MatrixXf> svd (X, Eigen::ComputeThinU | Eigen::ComputeThinV);
    Eigen::VectorXf s = svd.singularValues();
    Eigen::VectorXf lam = s.array().square() / n;
    Eigen::VectorXf clam (r);
    float cs = 0.0;
    for (size_t i = r; i != 0; --i) {
      cs += lam[i-1];
      clam[i-1] = cs;
    }
    float sigsq1, sigsq2, gam;
    size_t p;
    for (p = 0; p < r; ++p) {
      gam = float(m-p) / float(n);
      // First estimation of sigma
      sigsq1 = clam[p] / (r-p) / ((gam<1.0) ? 1.0 : gam);
      // Second estimation of sigma
      sigsq2 = (lam[p] - lam[r]) / 4 / std::sqrt(gam);
      // sigsq2 > sigsq1 if signal
      if (sigsq2 < sigsq1)
        break;
    }
    s.tail(r-p).setZero();
    // Restore DWI data
    X = svd.matrixU() * s.asDiagonal() * svd.matrixV().adjoint();
    X.colwise() += Xm;
    // Store output
    assign_pos_of(dwi).to(out);
    out.row(3) = X.col(n/2).template cast<value_type>();
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent; dwi.index(2) <= pos[2]+extent; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent; dwi.index(1) <= pos[1]+extent; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent; dwi.index(0) <= pos[0]+extent; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi))
            X.col(k) = dwi.row(3).template cast<float>();
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  int extent;
  size_t m, n, r;
  Eigen::MatrixXf X;
  Eigen::VectorXf Xm;
  ssize_t pos[3];

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  int extent = get_option_value("size", DEFAULT_SIZE);

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent);

  ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
    .run (func, dwi_in, dwi_out);

}

<commit_msg>Export noise level to optional output image.<commit_after>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include "command.h"
#include "image.h"
#include <Eigen/Dense>
#include <Eigen/SVD>

#define DEFAULT_SIZE 5

using namespace MR;
using namespace App;

void usage ()
{
  DESCRIPTION
  + "denoise DWI data and estimate the noise level based on the optimal threshold for PCA.";

  AUTHOR = "Daan Christiaens (daan.christiaens@kuleuven.be) & Jelle Veraart (jelle.veraart@nyumc.org) & J-Donald Tournier (jdtournier.gmail.com)";

  ARGUMENTS
  + Argument ("dwi", "the input diffusion-weighted image.").type_image_in ()

  + Argument ("out", "the output denoised DWI image.").type_image_out ();

  OPTIONS
  + Option ("size", "set the window size of the denoising filter. (default = " + str(DEFAULT_SIZE) + ")")
    + Argument ("window").type_integer (0, 50)

  + Option ("noise", "the output noise map.")
    + Argument ("level").type_image_out();

}

typedef float value_type;

template <class ImageType>
class DenoisingFunctor
{
public:
  DenoisingFunctor (ImageType& dwi, int size)
    : extent(size/2),
      m(dwi.size(3)),
      n(size*size*size),
      r((m<n) ? m : n),
      X(m,n), Xm(m),
      pos{0, 0, 0}
  { }

  void operator () (ImageType& dwi, ImageType& out)
  {
    // Load data in local window
    load_data(dwi);
    // Centre data
    Xm = X.rowwise().mean();
    X.colwise() -= Xm;
    // Compute SVD
    Eigen::JacobiSVD<Eigen::MatrixXf> svd (X, Eigen::ComputeThinU | Eigen::ComputeThinV);
    Eigen::VectorXf s = svd.singularValues();
    Eigen::VectorXf lam = s.array().square() / n;
    Eigen::VectorXf clam (r);
    float cs = 0.0;
    for (size_t i = r; i != 0; --i) {
      cs += lam[i-1];
      clam[i-1] = cs;
    }
    float sigsq1, sigsq2, gam;
    size_t p;
    for (p = 0; p < r; ++p) {
      gam = float(m-p) / float(n);
      // First estimation of sigma
      sigsq1 = clam[p] / (r-p) / ((gam<1.0) ? 1.0 : gam);
      // Second estimation of sigma
      sigsq2 = (lam[p] - lam[r]) / 4 / std::sqrt(gam);
      // sigsq2 > sigsq1 if signal
      if (sigsq2 < sigsq1)
        break;
    }
    s.tail(r-p).setZero();
    sigma = (p==r) ? NaN : std::sqrt(sigsq1);
    // Restore DWI data
    X = svd.matrixU() * s.asDiagonal() * svd.matrixV().adjoint();
    X.colwise() += Xm;
    // Store output
    assign_pos_of(dwi).to(out);
    out.row(3) = X.col(n/2).template cast<value_type>();
  }

  void operator () (ImageType& dwi, ImageType& out, ImageType& noise)
  {
    operator ()(dwi, out);
    assign_pos_of(dwi).to(noise);
    noise.value() = sigma;
  }

  void load_data (ImageType& dwi)
  {
    pos[0] = dwi.index(0); pos[1] = dwi.index(1); pos[2] = dwi.index(2);
    X.setZero();
    ssize_t k = 0;
    for (dwi.index(2) = pos[2]-extent; dwi.index(2) <= pos[2]+extent; ++dwi.index(2))
      for (dwi.index(1) = pos[1]-extent; dwi.index(1) <= pos[1]+extent; ++dwi.index(1))
        for (dwi.index(0) = pos[0]-extent; dwi.index(0) <= pos[0]+extent; ++dwi.index(0), ++k)
          if (! is_out_of_bounds(dwi))
            X.col(k) = dwi.row(3).template cast<float>();
    // reset image position
    dwi.index(0) = pos[0];
    dwi.index(1) = pos[1];
    dwi.index(2) = pos[2];
  }

private:
  int extent;
  size_t m, n, r;
  Eigen::MatrixXf X;
  Eigen::VectorXf Xm;
  ssize_t pos[3];
  float sigma;

};

void run ()
{
  auto dwi_in = Image<value_type>::open (argument[0]).with_direct_io(3);

  auto header = Header (dwi_in);
  header.datatype() = DataType::Float32;
  auto dwi_out = Image<value_type>::create (argument[1], header);

  int extent = get_option_value("size", DEFAULT_SIZE);

  DenoisingFunctor< Image<value_type> > func (dwi_in, extent);

  auto opt = get_options("noise");
  if (opt.size())
  {
    header.set_ndim(3);
    auto noise = Image<value_type>::create (opt[0][0], header);
    ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
      .run (func, dwi_in, dwi_out, noise);
  }
  else
  {
    ThreadedLoop ("running MP-PCA denoising", dwi_in, 0, 3)
      .run (func, dwi_in, dwi_out);
  }

}

<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexCPP.cxx
 ** Lexer for C++, C, Java, and Javascript.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool IsOKBeforeRE(const int ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

inline bool IsADoxygenChar(const int ch) {
	return (islower(ch) || ch == '$' || ch == '@' ||
		    ch == '\\' || ch == '&' || ch == '<' ||
			ch == '>' || ch == '#' || ch == '{' ||
			ch == '}' || ch == '[' || ch == ']');
}

inline bool IsStateComment(const int state) {
	return ((state == SCE_C_COMMENT) ||
		      (state == SCE_C_COMMENTLINE) ||
		      (state == SCE_C_COMMENTDOC) ||
		      (state == SCE_C_COMMENTDOCKEYWORD) ||
		      (state == SCE_C_COMMENTDOCKEYWORDERROR));
}

inline bool IsStateString(const int state) {
	return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
}

static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];

	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;

	// Do not leak onto next line
	if (initStyle == SCE_C_STRINGEOL)
		initStyle = SCE_C_DEFAULT;

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	bool lastWordWasUUID = false;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.Match("\\\n")) {
				sc.Forward();
				sc.Forward();
				continue;
			}
			if (sc.Match("\\\r\n")) {
				sc.Forward();
				sc.Forward();
				sc.Forward();
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_C_OPERATOR) {
			sc.SetState(SCE_C_DEFAULT);
		} else if (sc.state == SCE_C_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					lastWordWasUUID = strcmp(s, "uuid") == 0;
					sc.ChangeState(SCE_C_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_C_WORD2);
				}
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else {
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '@' || sc.ch == '\\') {
				sc.SetState(SCE_C_COMMENTDOCKEYWORD);
			}
		} else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
			if (sc.Match('*', '/')) {
				sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (!IsADoxygenChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (!isspace(sc.ch) || !keywords3.InList(s+1)) {
					sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				}
				sc.SetState(SCE_C_COMMENTDOC);
			}
		} else if (sc.state == SCE_C_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_CHARACTER) {
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			} else if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_REGEX) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '\\') {
				// Gobble up the quoted character
				if (sc.chNext == '\\' || sc.chNext == '/') {
					sc.Forward();
				}
			}
		} else if (sc.state == SCE_C_VERBATIM) {
			if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_UUID) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
				sc.SetState(SCE_C_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_C_DEFAULT) {
			if (sc.Match('@', '\"')) {
				sc.SetState(SCE_C_VERBATIM);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_NUMBER);
				}
			} else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_IDENTIFIER);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTDOC);
				} else {
					sc.SetState(SCE_C_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("///") || sc.Match("//!"))	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTLINEDOC);
				else
					sc.SetState(SCE_C_COMMENTLINE);
			} else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
				sc.SetState(SCE_C_REGEX);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_C_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_C_CHARACTER);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_C_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ') && (sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_C_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			chPrevNonWhite = ' ';
			visibleChars = 0;
			lastWordWasUUID = false;
		}
		if (!IsASpace(sc.ch)) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment &&
			(style == SCE_C_COMMENT || style == SCE_C_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_C_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc, "cpp", FoldCppDoc);
LexerModule lmTCL(SCLEX_TCL, ColouriseCppDoc, "tcl", FoldCppDoc);
<commit_msg>Fixed what looks like a gcc compiler bug returning true for ':' when function declared as inline rather than static inline.<commit_after>// Scintilla source code edit control
/** @file LexCPP.cxx
 ** Lexer for C++, C, Java, and Javascript.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool IsOKBeforeRE(const int ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

static inline bool IsAWordChar(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}

inline bool IsAWordStart(const int ch) {
	return (ch < 0x80) && (isalnum(ch) || ch == '_');
}

inline bool IsADoxygenChar(const int ch) {
	return (islower(ch) || ch == '$' || ch == '@' ||
		    ch == '\\' || ch == '&' || ch == '<' ||
			ch == '>' || ch == '#' || ch == '{' ||
			ch == '}' || ch == '[' || ch == ']');
}

inline bool IsStateComment(const int state) {
	return ((state == SCE_C_COMMENT) ||
		      (state == SCE_C_COMMENTLINE) ||
		      (state == SCE_C_COMMENTDOC) ||
		      (state == SCE_C_COMMENTDOCKEYWORD) ||
		      (state == SCE_C_COMMENTDOCKEYWORDERROR));
}

inline bool IsStateString(const int state) {
	return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
}

static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];

	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;

	// Do not leak onto next line
	if (initStyle == SCE_C_STRINGEOL)
		initStyle = SCE_C_DEFAULT;

	int chPrevNonWhite = ' ';
	int visibleChars = 0;
	bool lastWordWasUUID = false;

	StyleContext sc(startPos, length, initStyle, styler);

	for (; sc.More(); sc.Forward()) {

		// Handle line continuation generically.
		if (sc.ch == '\\') {
			if (sc.Match("\\\n")) {
				sc.Forward();
				sc.Forward();
				continue;
			}
			if (sc.Match("\\\r\n")) {
				sc.Forward();
				sc.Forward();
				sc.Forward();
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_C_OPERATOR) {
			sc.SetState(SCE_C_DEFAULT);
		} else if (sc.state == SCE_C_NUMBER) {
			if (!IsAWordChar(sc.ch)) {
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					lastWordWasUUID = strcmp(s, "uuid") == 0;
					sc.ChangeState(SCE_C_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_C_WORD2);
				}
				sc.SetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_PREPROCESSOR) {
			if (stylingWithinPreprocessor) {
				if (IsASpace(sc.ch)) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else {
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_COMMENT) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_COMMENTDOC) {
			if (sc.Match('*', '/')) {
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '@' || sc.ch == '\\') {
				sc.SetState(SCE_C_COMMENTDOCKEYWORD);
			}
		} else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
			if (sc.atLineEnd) {
				sc.SetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
			if (sc.Match('*', '/')) {
				sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				sc.Forward();
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (!IsADoxygenChar(sc.ch)) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (!isspace(sc.ch) || !keywords3.InList(s+1)) {
					sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
				}
				sc.SetState(SCE_C_COMMENTDOC);
			}
		} else if (sc.state == SCE_C_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			}
		} else if (sc.state == SCE_C_CHARACTER) {
			if (sc.atLineEnd) {
				sc.ChangeState(SCE_C_STRINGEOL);
				sc.ForwardSetState(SCE_C_DEFAULT);
				visibleChars = 0;
			} else if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			}
		} else if (sc.state == SCE_C_REGEX) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
				sc.ForwardSetState(SCE_C_DEFAULT);
			} else if (sc.ch == '\\') {
				// Gobble up the quoted character
				if (sc.chNext == '\\' || sc.chNext == '/') {
					sc.Forward();
				}
			}
		} else if (sc.state == SCE_C_VERBATIM) {
			if (sc.ch == '\"') {
				if (sc.chNext == '\"') {
					sc.Forward();
				} else {
					sc.ForwardSetState(SCE_C_DEFAULT);
				}
			}
		} else if (sc.state == SCE_C_UUID) {
			if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
				sc.SetState(SCE_C_DEFAULT);
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_C_DEFAULT) {
			if (sc.Match('@', '\"')) {
				sc.SetState(SCE_C_VERBATIM);
				sc.Forward();
			} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_NUMBER);
				}
			} else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
				if (lastWordWasUUID) {
					sc.SetState(SCE_C_UUID);
					lastWordWasUUID = false;
				} else {
					sc.SetState(SCE_C_IDENTIFIER);
				}
			} else if (sc.Match('/', '*')) {
				if (sc.Match("/**") || sc.Match("/*!")) {	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTDOC);
				} else {
					sc.SetState(SCE_C_COMMENT);
				}
				sc.Forward();	// Eat the * so it isn't used for the end of the comment
			} else if (sc.Match('/', '/')) {
				if (sc.Match("///") || sc.Match("//!"))	// Support of Qt/Doxygen doc. style
					sc.SetState(SCE_C_COMMENTLINEDOC);
				else
					sc.SetState(SCE_C_COMMENTLINE);
			} else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
				sc.SetState(SCE_C_REGEX);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_C_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_C_CHARACTER);
			} else if (sc.ch == '#' && visibleChars == 0) {
				// Preprocessor commands are alone on their line
				sc.SetState(SCE_C_PREPROCESSOR);
				// Skip whitespace between # and preprocessor word
				do {
					sc.Forward();
				} while ((sc.ch == ' ') && (sc.ch == '\t') && sc.More());
				if (sc.atLineEnd) {
					sc.SetState(SCE_C_DEFAULT);
				}
			} else if (isoperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_C_OPERATOR);
			}
		}

		if (sc.atLineEnd) {
			// Reset states to begining of colourise so no surprises
			// if different sets of lines lexed.
			chPrevNonWhite = ' ';
			visibleChars = 0;
			lastWordWasUUID = false;
		}
		if (!IsASpace(sc.ch)) {
			chPrevNonWhite = sc.ch;
			visibleChars++;
		}
	}
	sc.Complete();
}

static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                            Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int stylePrev = style;
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment &&
			(style == SCE_C_COMMENT || style == SCE_C_COMMENTDOC)) {
			if (style != stylePrev) {
				levelCurrent++;
			} else if ((style != styleNext) && !atEOL) {
				// Comments don't end at end of line and the next character may be unstyled.
				levelCurrent--;
			}
		}
		if (style == SCE_C_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc, "cpp", FoldCppDoc);
LexerModule lmTCL(SCLEX_TCL, ColouriseCppDoc, "tcl", FoldCppDoc);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 1998-2001, The University of Queensland
 * Copyright (C) 2000-2001, Sun Microsystems, Inc
 * Copyright (C) 2002, Trent Waddington
 *
 * See the file "LICENSE.TERMS" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 *
 */

/***************************************************************************//**
 * \file       rtl.cpp
 * \brief   Implementation of the classes that describe a low level RTL (
 *               register transfer list)
 ******************************************************************************/

/*
 * $Revision$    // 1.33.2.3
 *
 * 08 Apr 02 - Mike: Changes for boomerang
 * 13 May 02 - Mike: expList is no longer a pointer
 * 15 May 02 - Mike: Fixed a nasty bug in updateExp (when update with same
 *                expression as existing)
 * 25 Jul 02 - Mike: RTL is now list of Statements
 */

#include <cassert>
#if defined(_MSC_VER) && _MSC_VER <= 1200
#pragma warning(disable:4786)
#endif

#include <iomanip>            // For setfill
#include <sstream>
#include <cstring>
#include "types.h"
#include "statement.h"
#include "exp.h"
#include "type.h"
#include "register.h"
#include "cfg.h"
#include "proc.h"            // For printing proc names
#include "rtl.h"
#include "prog.h"
#include "hllcode.h"
#include "util.h"
#include "boomerang.h"
#include "visitor.h"
#include "log.h"
// For some reason, MSVC 5.00 complains about use of undefined types a lot
#if defined(_MSC_VER) && _MSC_VER <= 1100
#include "signature.h"        // For MSVC 5.00
#endif

/******************************************************************************
 * RTL methods.
 * Class RTL represents low-level register transfer lists.
 *****************************************************************************/

RTL::RTL()
  : nativeAddr(ADDRESS::g(0L))
{ }

/***************************************************************************//**
 * \brief   Constructor.
 * \param   instNativeAddr - the native address of the instruction
 * \param   listStmt - ptr to existing list of Statement
 *
 ******************************************************************************/
RTL::RTL(ADDRESS instNativeAddr, const std::list<Statement*>* listStmt /*= nullptr*/)
    : nativeAddr(instNativeAddr) {
    if (listStmt)
        *(std::list<Statement*>*)this = *listStmt;
}

/***************************************************************************//**
 * \brief        Copy constructor. A deep clone is made of the given object
 *                    so that the lists of Exps do not share memory.
 * \param        other RTL to copy from
 ******************************************************************************/
RTL::RTL(const RTL& other) : nativeAddr(other.nativeAddr) {
    for (auto it = other.begin(); it != other.end(); it++) {
        push_back((*it)->clone());
    }
}

/***************************************************************************//**
 * \brief        Assignment copy (deep).
 * \param        other - RTL to copy
 * \returns             a reference to this object
 ******************************************************************************/
RTL& RTL::operator=(const RTL& other) {
    if (this != &other) {
        // Do a deep copy always
        clear();
        const_iterator it;
        for (it = other.begin(); it != other.end(); it++)
            push_back((*it)->clone());

        nativeAddr = other.nativeAddr;
    }
    return *this;
}

// Return a deep copy, including a deep copy of the list of Statements
/***************************************************************************//**
 * \brief        Deep copy clone; deleting the clone will not affect this
 *                     RTL object
 * \returns             Pointer to a new RTL that is a clone of this one
 ******************************************************************************/
RTL* RTL::clone() const {
    std::list<Statement*> le;
    for (const_iterator it = begin(); it != end(); it++) {
        le.push_back((*it)->clone());
    }
    return new RTL(nativeAddr, &le);
}

/***************************************************************************//**
 * \brief        Make a copy of this RTLs list of Exp* to the given list
 * \param        dest Ref to empty list to copy to
 ******************************************************************************/
void RTL::deepCopyList(std::list<Statement*>& dest) const {
    for (Statement * it : *this) {
        dest.push_back(it->clone());
    }
}

/***************************************************************************//**
 * \brief        Append the given Statement at the end of this RTL
 * \note            Exception: Leaves any flag call at the end (so may push exp
 *                     to second last position, instead of last)
 * \note            stmt is NOT copied. This is different to how UQBT was!
 * \param        s pointer to Statement to append
 ******************************************************************************/
void RTL::appendStmt(Statement* s) {
    assert(s!=nullptr);
    if (not empty()) {
        if (back()->isFlagAssgn()) {
            iterator it = end();
            insert(--it, s);
            return;
        }
    }
    push_back(s);
}

/***************************************************************************//**
 * \brief        Append a given list of Statements to this RTL
 * \note            A copy of the Statements in le are appended
 * \param        rtl list of Statements to insert
 ******************************************************************************/
void RTL::appendListStmt(std::list<Statement*>& le) {
    for (Statement * it : le) {
        push_back(it->clone());
    }
}

/***************************************************************************//**
 * \brief   Prints this object to a stream in text form.
 * \param   os - stream to output to (often cout or cerr)
 ******************************************************************************/
void RTL::print(std::ostream& os /*= cout*/, bool html /*=false*/) const {

    if (html)
        os << "
";
    // print out the instruction address of this RTL
    os << std::hex << std::setfill('0') << std::setw(8) << nativeAddr;
    os << std::dec << std::setfill(' ');      // Ugh - why is this needed?
    if (html)
        os << "	";

    // Print the statements
    // First line has 8 extra chars as above
    bool bFirst = true;
    for (Statement * stmt : *this) {
        if (html) {
            if (!bFirst) os << "
	";
            os << "";
        } else {
            if (bFirst) os << " ";
            else        os << std::setw(9) << " ";
        }
        if (stmt)
            stmt->print(os, html);
        // Note: we only put newlines where needed. So none at the end of
        // Statement::print; one here to separate from other statements
        if (html)
            os << "
";
        os << "\n";
        bFirst = false;
    }
    if (empty())
        os << std::endl;       // New line for NOP
}

void RTL::dump() {
    print(std::cerr);
}

extern char debug_buffer[];

char* RTL::prints() const {
    std::ostringstream ost;
    print(ost);
    strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
    debug_buffer[DEBUG_BUFSIZE-1] = '\0';
    return debug_buffer;
}

/***************************************************************************//**
 * \brief   Output operator for RTL*
 *          Just makes it easier to use e.g. std::cerr << myRTLptr
 * \param   os output stream to send to
 * \param   r ptr to RTL to print to the stream
 * \returns os (for concatenation)
 ******************************************************************************/
std::ostream& operator<<(std::ostream& os, const RTL* r) {
    if (r == nullptr) {
        os << "nullptr ";
        return os;
    }
    r->print(os);
    return os;
}

/***************************************************************************//**
 * \brief      Return true if this RTL affects the condition codes
 * \note          Assumes that if there is a flag call Exp, then it is the last
 * \returns           Boolean as above
 ******************************************************************************/
bool RTL::areFlagsAffected() {
    if (this->empty())
        return false;
    Statement *e = this->back();
    // If it is a flag call, then the CCs are affected
    return e->isFlagAssgn();
}

void RTL::simplify() {
    for (iterator it = this->begin(); it != this->end(); ) {
        Statement *s = *it;
        s->simplify();
        if (s->isBranch()) {
            Exp *cond =     ((BranchStatement*)s)->getCondExpr();
            if (cond && cond->getOper() == opIntConst) {
                if (((Const*)cond)->getInt() == 0) {
                    if (VERBOSE)
                        LOG << "removing branch with false condition at " << getAddress()  << " " << *it << "\n";
                    it = this->erase(it);
                    continue;
                } else {
                    if (VERBOSE)
                        LOG << "replacing branch with true condition with goto at " << getAddress() << " " << *it <<
                               "\n";
                    *it = new GotoStatement(((BranchStatement*)s)->getFixedDest());
                }
            }
        } else if (s->isAssign()) {
            Exp* guard = ((Assign*)s)->getGuard();
            if (guard && (guard->isFalse() || (guard->isIntConst() && ((Const*)guard)->getInt() == 0))) {
                // This assignment statement can be deleted
                if (VERBOSE)
                    LOG << "removing assignment with false guard at " << getAddress() << " " << *it << "\n";
                it = this->erase(it);
                continue;
            }
        }
        it++;
    }
}
// Is this RTL a compare instruction? If so, the passed register and compared value (a semantic string) are set.

bool RTL::isCall() {
    if (this->empty())
        return false;
    Statement* last = this->back();
    return last->getKind() == STMT_CALL;
}

// Use this slow function when you can't be sure that the HL Statement is last
// Get the "special" (High Level) Statement this RTL (else nullptr)
Statement* RTL::getHlStmt() {
    reverse_iterator rit;
    for (rit = this->rbegin(); rit != this->rend(); rit++) {
        if ((*rit)->getKind() != STMT_ASSIGN)
            return *rit;
    }
    return nullptr;
}

//int RTL::setConscripts(int n, bool bClear) {
//    StmtConscriptSetter ssc(n, bClear);
//    accept(&ssc);
//    return ssc.getLast();
//}
<commit_msg>A small cleanup for rtl.cpp<commit_after>/*
 * Copyright (C) 1998-2001, The University of Queensland
 * Copyright (C) 2000-2001, Sun Microsystems, Inc
 * Copyright (C) 2002, Trent Waddington
 *
 * See the file "LICENSE.TERMS" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 *
 */

/***************************************************************************//**
 * \file       rtl.cpp
 * \brief   Implementation of the classes that describe a low level RTL (
 *               register transfer list)
 ******************************************************************************/

/*
 * $Revision$    // 1.33.2.3
 *
 * 08 Apr 02 - Mike: Changes for boomerang
 * 13 May 02 - Mike: expList is no longer a pointer
 * 15 May 02 - Mike: Fixed a nasty bug in updateExp (when update with same
 *                expression as existing)
 * 25 Jul 02 - Mike: RTL is now list of Statements
 */

#include <cassert>
#if defined(_MSC_VER) && _MSC_VER <= 1200
#pragma warning(disable:4786)
#endif

#include <iomanip>            // For setfill
#include <sstream>
#include <cstring>
#include "types.h"
#include "statement.h"
#include "exp.h"
#include "type.h"
#include "register.h"
#include "cfg.h"
#include "proc.h"            // For printing proc names
#include "rtl.h"
#include "prog.h"
#include "hllcode.h"
#include "util.h"
#include "boomerang.h"
#include "visitor.h"
#include "log.h"
// For some reason, MSVC 5.00 complains about use of undefined types a lot
#if defined(_MSC_VER) && _MSC_VER <= 1100
#include "signature.h"        // For MSVC 5.00
#endif

/******************************************************************************
 * RTL methods.
 * Class RTL represents low-level register transfer lists.
 *****************************************************************************/

RTL::RTL()
  : nativeAddr(ADDRESS::g(0L))
{ }

/***************************************************************************//**
 * \brief   Constructor.
 * \param   instNativeAddr - the native address of the instruction
 * \param   listStmt - ptr to existing list of Statement
 *
 ******************************************************************************/
RTL::RTL(ADDRESS instNativeAddr, const std::list<Statement*>* listStmt /*= nullptr*/)
    : nativeAddr(instNativeAddr) {
    if (listStmt)
        *(std::list<Statement*>*)this = *listStmt;
}

/***************************************************************************//**
 * \brief        Copy constructor. A deep clone is made of the given object
 *                    so that the lists of Exps do not share memory.
 * \param        other RTL to copy from
 ******************************************************************************/
RTL::RTL(const RTL& other) : nativeAddr(other.nativeAddr) {
    for (auto it = other.begin(); it != other.end(); it++) {
        push_back((*it)->clone());
    }
}

/***************************************************************************//**
 * \brief        Assignment copy (deep).
 * \param        other - RTL to copy
 * \returns             a reference to this object
 ******************************************************************************/
RTL& RTL::operator=(const RTL& other) {
    if (this != &other) {
        // Do a deep copy always
        clear();
        const_iterator it;
        for (it = other.begin(); it != other.end(); it++)
            push_back((*it)->clone());

        nativeAddr = other.nativeAddr;
    }
    return *this;
}

// Return a deep copy, including a deep copy of the list of Statements
/***************************************************************************//**
 * \brief        Deep copy clone; deleting the clone will not affect this
 *                     RTL object
 * \returns             Pointer to a new RTL that is a clone of this one
 ******************************************************************************/
RTL* RTL::clone() const {
    std::list<Statement*> le;
    for (const_iterator it = begin(); it != end(); it++) {
        le.push_back((*it)->clone());
    }
    return new RTL(nativeAddr, &le);
}

/***************************************************************************//**
 * \brief        Make a copy of this RTLs list of Exp* to the given list
 * \param        dest Ref to empty list to copy to
 ******************************************************************************/
void RTL::deepCopyList(std::list<Statement*>& dest) const {
    for (Statement * it : *this) {
        dest.push_back(it->clone());
    }
}

/***************************************************************************//**
 * \brief        Append the given Statement at the end of this RTL
 * \note            Exception: Leaves any flag call at the end (so may push exp
 *                     to second last position, instead of last)
 * \note            stmt is NOT copied. This is different to how UQBT was!
 * \param        s pointer to Statement to append
 ******************************************************************************/
void RTL::appendStmt(Statement* s) {
    assert(s!=nullptr);
    if (not empty()) {
        if (back()->isFlagAssgn()) {
            iterator it = end();
            insert(--it, s);
            return;
        }
    }
    push_back(s);
}

/***************************************************************************//**
 * \brief        Append a given list of Statements to this RTL
 * \note            A copy of the Statements in le are appended
 * \param        rtl list of Statements to insert
 ******************************************************************************/
void RTL::appendListStmt(std::list<Statement*>& le) {
    for (Statement * it : le) {
        push_back(it->clone());
    }
}

/***************************************************************************//**
 * \brief   Prints this object to a stream in text form.
 * \param   os - stream to output to (often cout or cerr)
 ******************************************************************************/
void RTL::print(std::ostream& os /*= cout*/, bool html /*=false*/) const {

    if (html)
        os << "
";
    // print out the instruction address of this RTL
    os << std::hex << std::setfill('0') << std::setw(8) << nativeAddr;
    os << std::dec << std::setfill(' ');      // Ugh - why is this needed?
    if (html)
        os << "	";

    // Print the statements
    // First line has 8 extra chars as above
    bool bFirst = true;
    for (Statement * stmt : *this) {
        if (html) {
            if (!bFirst) os << "
	";
            os << "";
        } else {
            if (bFirst) os << " ";
            else        os << std::setw(9) << " ";
        }
        if (stmt)
            stmt->print(os, html);
        // Note: we only put newlines where needed. So none at the end of
        // Statement::print; one here to separate from other statements
        if (html)
            os << "
";
        os << "\n";
        bFirst = false;
    }
    if (empty())
        os << std::endl;       // New line for NOP
}

void RTL::dump() {
    print(std::cerr);
}

extern char debug_buffer[];

char* RTL::prints() const {
    std::ostringstream ost;
    print(ost);
    strncpy(debug_buffer, ost.str().c_str(), DEBUG_BUFSIZE-1);
    debug_buffer[DEBUG_BUFSIZE-1] = '\0';
    return debug_buffer;
}

/***************************************************************************//**
 * \brief   Output operator for RTL*
 *          Just makes it easier to use e.g. std::cerr << myRTLptr
 * \param   os output stream to send to
 * \param   r ptr to RTL to print to the stream
 * \returns os (for concatenation)
 ******************************************************************************/
std::ostream& operator<<(std::ostream& os, const RTL* r) {
    if (r == nullptr) {
        os << "nullptr ";
        return os;
    }
    r->print(os);
    return os;
}

/***************************************************************************//**
 * \brief      Return true if this RTL affects the condition codes
 * \note          Assumes that if there is a flag call Exp, then it is the last
 * \returns           Boolean as above
 ******************************************************************************/
bool RTL::areFlagsAffected() {
    if (this->empty())
        return false;
    Statement *e = this->back();
    // If it is a flag call, then the CCs are affected
    return e->isFlagAssgn();
}

void RTL::simplify() {
    for (iterator it = begin(); it != end(); ) {
        Statement *s = *it;
        s->simplify();
        if (s->isBranch()) {
            Exp *cond =     ((BranchStatement*)s)->getCondExpr();
            if (cond && cond->getOper() == opIntConst) {
                if (((Const*)cond)->getInt() == 0) {
                    LOG_VERBOSE(1) << "removing branch with false condition at " << getAddress()  << " " << *it << "\n";
                    it = this->erase(it);
                    continue;
                }
                LOG_VERBOSE(1) << "replacing branch with true condition with goto at " << getAddress() << " " << *it <<
                       "\n";
                *it = new GotoStatement(((BranchStatement*)s)->getFixedDest());
            }
        } else if (s->isAssign()) {
            Exp* guard = ((Assign*)s)->getGuard();
            if (guard && (guard->isFalse() || (guard->isIntConst() && ((Const*)guard)->getInt() == 0))) {
                // This assignment statement can be deleted
                LOG_VERBOSE(1) << "removing assignment with false guard at " << getAddress() << " " << *it << "\n";
                it = erase(it);
                continue;
            }
        }
        it++;
    }
}
// Is this RTL a compare instruction? If so, the passed register and compared value (a semantic string) are set.

bool RTL::isCall() {
    if (empty())
        return false;
    Statement* last = this->back();
    return last->getKind() == STMT_CALL;
}

// Use this slow function when you can't be sure that the HL Statement is last
// Get the "special" (High Level) Statement this RTL (else nullptr)
Statement* RTL::getHlStmt() {
    reverse_iterator rit;
    for (rit = this->rbegin(); rit != this->rend(); rit++) {
        if ((*rit)->getKind() != STMT_ASSIGN)
            return *rit;
    }
    return nullptr;
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

inline bool isLuaOperator(char ch) {
	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
	        ch == '(' || ch == ')' || ch == '=' ||
	        ch == '{' || ch == '}' || ch == '~' ||
	        ch == '[' || ch == ']' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' ||
	        ch == '.' || ch == '^' || ch == '%' || ch == ':')
		return true;
	return false;
}

static void classifyWordLua(unsigned int start,
                            unsigned int end,
                            WordList	&keywords,
                            Accessor	&styler) {
	char s[100];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');

	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}

	char chAttr = SCE_LUA_IDENTIFIER;

	if (wordIsNumber)
		chAttr = SCE_LUA_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LUA_WORD;
		}
	}
	styler.ColourTo(end, chAttr);
}

static void ColouriseLuaDoc(unsigned int startPos,
                            int length,
                            int initStyle,
                            WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);
	styler.GetLine(startPos);

	int state = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	bool firstChar = true;
	int literalString = 0;

	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i <= lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_LUA_STRINGEOL) {
			if (ch != '\r' && ch != '\n') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_DEFAULT;
			}
		}

		if (state == SCE_LUA_LITERALSTRING && ch == '[' && chNext == '[') {
			literalString++;
		} else if (state == SCE_LUA_DEFAULT) {
			if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (ch == '[' && chNext == '[') {
				state = SCE_LUA_LITERALSTRING;
				literalString = 1;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_CHARACTER;
			} else if (ch == '$' && firstChar) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_PREPROCESSOR;
			} else if (ch == '#' && firstChar)	// Should be only on the first line of the file! Cannot be tested here
			{
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (isLuaOperator(ch)) {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
			} else if (iswordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_WORD;
			}
		} else if (state == SCE_LUA_WORD) {
			if (!iswordchar(ch)) {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_LUA_DEFAULT;
				if (ch == '[' && chNext == '[') {
					literalString = 1;
					state = SCE_LUA_LITERALSTRING;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			} else if (ch == '.' && chNext == '.') {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
				state = SCE_LUA_DEFAULT;
			}
		} else {
			if (state == SCE_LUA_LITERALSTRING) {
				if (ch == ']' && (chPrev == ']') && (--literalString == 0)) {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_PREPROCESSOR) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_STRING) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_LUA_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			}

			if (state == SCE_LUA_DEFAULT) {
				if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (iswordstart(ch)) {
					state = SCE_LUA_WORD;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			}
		}
		chPrev = ch;
		firstChar = (ch == '\r' || ch == '\n');
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLuaDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	char s[10];
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD)
			if ( ch == 'e' || ch == 't' || ch == 'd' || ch == 'f') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) break;
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "do") == 0)
				        || (strcmp(s, "function") == 0))
					levelCurrent++;
				if (strcmp(s, "end") == 0) levelCurrent--;
			}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc);
<commit_msg>Simplified because of warnings.<commit_after>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

inline bool isLuaOperator(char ch) {
	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
	        ch == '(' || ch == ')' || ch == '=' ||
	        ch == '{' || ch == '}' || ch == '~' ||
	        ch == '[' || ch == ']' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' ||
	        ch == '.' || ch == '^' || ch == '%' || ch == ':')
		return true;
	return false;
}

static void classifyWordLua(unsigned int start,
                            unsigned int end,
                            WordList	&keywords,
                            Accessor	&styler) {
	char s[100];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');

	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}

	char chAttr = SCE_LUA_IDENTIFIER;

	if (wordIsNumber)
		chAttr = SCE_LUA_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LUA_WORD;
		}
	}
	styler.ColourTo(end, chAttr);
}

static void ColouriseLuaDoc(unsigned int startPos,
                            int length,
                            int initStyle,
                            WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);
	styler.GetLine(startPos);

	int state = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	bool firstChar = true;
	int literalString = 0;

	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i <= lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_LUA_STRINGEOL) {
			if (ch != '\r' && ch != '\n') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_DEFAULT;
			}
		}

		if (state == SCE_LUA_LITERALSTRING && ch == '[' && chNext == '[') {
			literalString++;
		} else if (state == SCE_LUA_DEFAULT) {
			if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (ch == '[' && chNext == '[') {
				state = SCE_LUA_LITERALSTRING;
				literalString = 1;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_CHARACTER;
			} else if (ch == '$' && firstChar) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_PREPROCESSOR;
			} else if (ch == '#' && firstChar)	// Should be only on the first line of the file! Cannot be tested here
			{
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (isLuaOperator(ch)) {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
			} else if (iswordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_WORD;
			}
		} else if (state == SCE_LUA_WORD) {
			if (!iswordchar(ch)) {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_LUA_DEFAULT;
				if (ch == '[' && chNext == '[') {
					literalString = 1;
					state = SCE_LUA_LITERALSTRING;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			} else if (ch == '.' && chNext == '.') {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
				state = SCE_LUA_DEFAULT;
			}
		} else {
			if (state == SCE_LUA_LITERALSTRING) {
				if (ch == ']' && (chPrev == ']') && (--literalString == 0)) {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_PREPROCESSOR) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_STRING) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_LUA_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			}

			if (state == SCE_LUA_DEFAULT) {
				if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (iswordstart(ch)) {
					state = SCE_LUA_WORD;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			}
		}
		chPrev = ch;
		firstChar = (ch == '\r' || ch == '\n');
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	char s[10];
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD)
			if ( ch == 'e' || ch == 't' || ch == 'd' || ch == 'f') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) break;
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "do") == 0)
				        || (strcmp(s, "function") == 0))
					levelCurrent++;
				if (strcmp(s, "end") == 0) levelCurrent--;
			}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc);
<|endoftext|>


<commit_before>#include "Method.hpp"

namespace Ethereum{namespace ABI{

std::string Method::Encode(const char *name)
{
    return Encode(name, strlen(name));
}

std::string Method::Encode(const std::string &name)
{
    return Encode(name.data(), name.size());
}

std::string Method::Encode(const char *name, size_t size)
{
    CryptoPP::SHA3_256 hash;
    byte digest[32];
    std::string result;
    result.reserve(10);
    result.resize(8);
    hash.CalculateDigest( digest, (const byte*) name, size);
    boost::algorithm::hex(digest, digest+4, result.begin());
    result.insert(0, "0x");
    return result;
}

std::string Method::Encode(const std::string &name, const Arguments &args)
{
    return Encode(name.data(), name.size(), args);
}

std::string Method::Encode(const char *name, const Arguments &args)
{
    return Encode(name, strlen(name), args);
}

std::string Method::Encode(const char *name, size_t size, const Arguments &args)
{
    return Encode(name, size) + args.toHex();
}

}}
<commit_msg>using unsigned char<commit_after>#include "Method.hpp"

namespace Ethereum{namespace ABI{

std::string Method::Encode(const char *name)
{
    return Encode(name, strlen(name));
}

std::string Method::Encode(const std::string &name)
{
    return Encode(name.data(), name.size());
}

std::string Method::Encode(const char *name, size_t size)
{
    CryptoPP::SHA3_256 hash;
    unsigned char digest[32];
    std::string result;
    result.reserve(10);
    result.resize(8);
    hash.CalculateDigest( digest, (const unsigned char*) name, size);
    boost::algorithm::hex(digest, digest+4, result.begin());
    result.insert(0, "0x");
    return result;
}

std::string Method::Encode(const std::string &name, const Arguments &args)
{
    return Encode(name.data(), name.size(), args);
}

std::string Method::Encode(const char *name, const Arguments &args)
{
    return Encode(name, strlen(name), args);
}

std::string Method::Encode(const char *name, size_t size, const Arguments &args)
{
    return Encode(name, size) + args.toHex();
}

}}
<|endoftext|>


<commit_before>#include <Refal2.h>

namespace Refal2 {

//-----------------------------------------------------------------------------

CProgram::CProgram( int numberOfModules ) :
	modulesSize( numberOfModules ),
	modules( new CRuntimeModule[modulesSize] )
{
	assert( modulesSize > 0 );
	assert( modules != 0 );
}

CProgram::~CProgram()
{
	delete[] modules;
}

CRuntimeModule& CProgram::Module( TRuntimeModuleId moduleId )
{
	assert( moduleId >= 0 && moduleId < modulesSize );
	return modules[moduleId];
}

//-----------------------------------------------------------------------------

class CGlobalFunctionData {
public:
	CGlobalFunctionData() :
		preparatoryFunction( 0 ),
		embeddedFunction( 0 ),
		runtimeModuleId( 0 )
	{
	}

	bool IsEmbeddedFunction() const
	{
		return ( embeddedFunction != 0 );
	}

	bool IsPreparatoryFunction() const
	{
		return ( preparatoryFunction != 0 );
	}

	bool IsDefined() const
	{
		return ( IsEmbeddedFunction() || IsPreparatoryFunction() );
	}

	void SetPreparatoryFunction(
		const CPreparatoryFunction* const _preparatoryFunction,
		const TRuntimeModuleId _runtimeModuleId )
	{
		assert( !IsDefined() );
		assert( _preparatoryFunction != 0 );
		preparatoryFunction = _preparatoryFunction;
		runtimeModuleId = _runtimeModuleId;
	}

	const CPreparatoryFunction* PreparatoryFunction() const
	{
		assert( IsPreparatoryFunction() );
		return preparatoryFunction;
	}

	const TRuntimeModuleId RuntimeModuleId() const
	{
		assert( IsPreparatoryFunction() );
		return runtimeModuleId;
	}

	void SetEmbeddedFunction( const TEmbeddedFunctionPtr _embeddedFunction )
	{
		assert( !IsDefined() );
		assert( _embeddedFunction != 0 );
		embeddedFunction = _embeddedFunction;
	}

	TEmbeddedFunctionPtr EmbeddedFunction() const
	{
		assert( IsEmbeddedFunction() );
		return embeddedFunction;
	}

private:
	const CPreparatoryFunction* preparatoryFunction;
	TEmbeddedFunctionPtr embeddedFunction;
	TRuntimeModuleId runtimeModuleId;
};

//-----------------------------------------------------------------------------

class CExternalFunctionData {
public:
	CExternalFunctionData( int _globalIndex,
			CPreparatoryFunction* _preparatoryFunction ) :
		globalIndex( _globalIndex ),
		preparatoryFunction( _preparatoryFunction )
	{
		assert( globalIndex >= 0 );
		assert( preparatoryFunction != 0 );
	}

	int GlobalIndex() const { return globalIndex; }
	CPreparatoryFunction* PreparatoryFunction() const
		{ return preparatoryFunction; }

private:
	int globalIndex;
	CPreparatoryFunction* preparatoryFunction;
};

//-----------------------------------------------------------------------------

class CPreparatoryRuntimeFunction : public CRuntimeFunction {
public:
	CPreparatoryRuntimeFunction( CPreparatoryFunction* const function,
		const TRuntimeModuleId moduleId );

	CPreparatoryFunction* PreparatoryFunction() const { return function; }
	TRuntimeModuleId RuntimeModuleId() const { return moduleId; }

private:
	CPreparatoryFunction* const function;
	const TRuntimeModuleId moduleId;

	static TRuntimeFunctionType convertType(
		const CPreparatoryFunction* const function );
};

CPreparatoryRuntimeFunction::CPreparatoryRuntimeFunction(
		CPreparatoryFunction* const _function,
		const TRuntimeModuleId _moduleId ) :
	CRuntimeFunction( convertType( _function ) ),
	function( _function ),
	moduleId( _moduleId )
{
}

TRuntimeFunctionType CPreparatoryRuntimeFunction::convertType(
	const CPreparatoryFunction* const function )
{
	assert( function != 0 );
	switch( function->GetType() ) {
		case PFT_Ordinary:
			return RFT_Ordinary;
		case PFT_Empty:
			return RFT_Empty;
		case PFT_External:
			return RFT_External;
		case PFT_Declared:
		case PFT_Defined:
		case PFT_Compiled:
		case PFT_Embedded:
		default:
			break;
	}
	assert( false );
	return RFT_Empty;
}

//-----------------------------------------------------------------------------

class CInternalProgramBuilder {
public:
	static CProgramPtr Build( CModuleDataVector& modules,
		CErrorsHelper& errors );

private:
	CErrorsHelper& errors;
	typedef std::vector<CExternalFunctionData> CExternals;
	CExternals externals;
	CDictionary<CGlobalFunctionData, std::string> globals;
	CProgramPtr program;

	CInternalProgramBuilder( CErrorsHelper& _errors, int numberOfModules ) :
		errors( _errors ),
		program( new CProgram( numberOfModules ) )
	{
		assert( static_cast<bool>( program ) );
	}

	void addFunction( CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );
	void addFunctions( const CModuleData& module, CRuntimeModule& runtimeModule,
		const TRuntimeModuleId runtimeModuleId );
	void collect( CModuleDataVector& modules );
	void check();
	void compile();
	void link();
};

//-----------------------------------------------------------------------------

CProgramPtr CInternalProgramBuilder::Build( CModuleDataVector& modules,
	CErrorsHelper& errors )
{
	assert( !errors.HasErrors() );
	assert( !modules.empty() );
	CInternalProgramBuilder builder( errors, modules.size() );
	builder.collect( modules );
	if( errors.HasErrors() ) {
		return nullptr;
	}
	builder.check();
	if( errors.HasErrors() ) {
		return nullptr;
	}
	builder.compile();
	assert( !errors.HasErrors() );
	builder.link();
	assert( !errors.HasErrors() );
	return CProgramPtr( builder.program.release() );
}

void CInternalProgramBuilder::addFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId runtimeModuleId )
{
	const bool isExternal = function->IsExternal();
	const bool isGlobal = function->IsEntry();
	if( !( isExternal || isGlobal ) ) {
		return;
	}
	int globalIndex = globals.AddKey( function->ExternalName() );
	if( isGlobal ) {
		assert( !isExternal );
		CGlobalFunctionData& global = globals.GetData( globalIndex );
		if( global.IsDefined() ) {
			errors.Error( "already defined" );
		} else {
			global.SetPreparatoryFunction( function, runtimeModuleId );
		}
	} else {
		assert( isExternal );
		externals.push_back( CExternalFunctionData( globalIndex, function ) );
	}
}
void CInternalProgramBuilder::addFunctions( const CModuleData& module,
	CRuntimeModule& runtimeModule, const TRuntimeModuleId runtimeModuleId )
{
	const CPreparatoryFunctions& functions = module.Functions;
	for( int i = 0; i < functions.Size(); i++ ) {
		CPreparatoryFunction* function = functions.GetData( i ).get();
		CRuntimeFunctionPtr& runtimeFunction = runtimeModule.Functions.GetData(
			runtimeModule.Functions.AddKey( function->Name() ) );
		assert( !static_cast<bool>( runtimeFunction ) );
		runtimeFunction.reset( new CPreparatoryRuntimeFunction( function,
			runtimeModuleId ) );
		addFunction( function, runtimeModuleId );
	}
}

void CInternalProgramBuilder::collect( CModuleDataVector& modules )
{
	TRuntimeModuleId currentModuleId = 0;
	for( CModuleDataVector::const_iterator module = modules.begin();
		module != modules.end(); ++module )
	{
		addFunctions( *( *module ), program->Module( currentModuleId ),
			currentModuleId );
		currentModuleId++;
	}
	modules.clear();
}

void CInternalProgramBuilder::check()
{
	for( CExternals::const_iterator	function = externals.begin();
		function != externals.end(); ++function )
	{
		const int globalIndex = function->GlobalIndex();
		if( !globals.GetData( globalIndex ).IsDefined() ) {
			errors.Error( "link error" );
		}
	}
}

void CInternalProgramBuilder::compile()
{
	CFunctionCompiler compiler;
	for( int moduleId = 0; moduleId < program->NumberOfModules(); moduleId++ )
	{
		const CRuntimeFunctions& functions =
			program->Module( moduleId ).Functions;
		for( int i = 0; i < functions.Size(); i++ ) {
			const CPreparatoryRuntimeFunction& function = static_cast<
				CPreparatoryRuntimeFunction&>( *functions.GetData( i ) );
			if( function.PreparatoryFunction()->IsOrdinary() ) {
				function.PreparatoryFunction()->Compile( compiler );
			}
		}
	}
}

void CInternalProgramBuilder::link()
{
	for( CExternals::iterator function = externals.begin();
		function != externals.end(); ++function )
	{
		function->PreparatoryFunction();
		const int globalIndex = function->GlobalIndex();
		const CGlobalFunctionData& global = globals.GetData( globalIndex );
		assert( global.IsDefined() );
		if( global.IsEmbeddedFunction() ) {
			function->PreparatoryFunction()->SetEmbedded(
				global.EmbeddedFunction() );
		} else {
			assert( !global.IsPreparatoryFunction() );
			function->PreparatoryFunction()->Link(
				*global.PreparatoryFunction() );
		}
	}

	for( int moduleId = 0; moduleId < program->NumberOfModules(); moduleId++ )
	{
		const CRuntimeFunctions& functions =
			program->Module( moduleId ).Functions;
		for( int i = 0; i < functions.Size(); i++ ) {
			const CPreparatoryRuntimeFunction& function = static_cast<
				CPreparatoryRuntimeFunction&>( *functions.GetData( i ) );
			const CPreparatoryFunction* preparatoryFunction =
				function.PreparatoryFunction();
			CRuntimeFunctionPtr newRuntimeFunction;
			switch( function.Type() ) {
				case RFT_Empty:
					assert( preparatoryFunction->IsEmpty() );
					newRuntimeFunction.reset( new CEmptyFunction );
					break;
				case RFT_Embedded:
					assert( preparatoryFunction->IsEmbedded() );
					newRuntimeFunction.reset( new CEmbeddedFunction(
						preparatoryFunction->EmbeddedFunction() ) );
					break;
				case RFT_External:
					assert( preparatoryFunction->IsEmpty()
						|| preparatoryFunction->IsEmbedded()
						|| preparatoryFunction->IsOrdinary() );
					// todo: ---
					newRuntimeFunction.reset( new CExternalFunction( 0,
						function.RuntimeModuleId() ) );
					break;
				case RFT_Ordinary:
					assert( preparatoryFunction->IsOrdinary() );
					// todo: ---
					newRuntimeFunction.reset( new COrdinaryFunction( 0 ) );
					break;
				default:
					assert( false );
					break;
			}
		}
	}
}

//-----------------------------------------------------------------------------

CProgramBuilder::CProgramBuilder( IErrorHandler* errorHandler ) :
	CFunctionBuilder( errorHandler )
{
	Reset();
}

void CProgramBuilder::Reset()
{
	CFunctionBuilder::Reset();
}

void CProgramBuilder::AddModule( CModuleDataPtr& module )
{
	modules.push_back( CModuleDataPtr( module.release() ) );
}

void CProgramBuilder::BuildProgram()
{
	CInternalProgramBuilder::Build( modules, *this );
}

//-----------------------------------------------------------------------------

} // end of namespace Refal2
<commit_msg>add error messages<commit_after>#include <Refal2.h>

namespace Refal2 {

//-----------------------------------------------------------------------------
// CProgram

CProgram::CProgram( int numberOfModules ) :
	modulesSize( numberOfModules ),
	modules( new CRuntimeModule[modulesSize] )
{
	assert( modulesSize > 0 );
	assert( modules != 0 );
}

CProgram::~CProgram()
{
	delete[] modules;
}

CRuntimeModule& CProgram::Module( TRuntimeModuleId moduleId )
{
	assert( moduleId >= 0 && moduleId < modulesSize );
	return modules[moduleId];
}

//-----------------------------------------------------------------------------
// Standart embedded functions

//-----------------------------------------------------------------------------
// CGlobalFunctionData

class CGlobalFunctionData {
public:
	CGlobalFunctionData() :
		preparatoryFunction( 0 ),
		embeddedFunction( 0 ),
		runtimeModuleId( 0 )
	{
	}

	bool IsEmbeddedFunction() const
	{
		return ( embeddedFunction != 0 );
	}

	bool IsPreparatoryFunction() const
	{
		return ( preparatoryFunction != 0 );
	}

	bool IsDefined() const
	{
		return ( IsEmbeddedFunction() || IsPreparatoryFunction() );
	}

	void SetPreparatoryFunction(
		const CPreparatoryFunction* const _preparatoryFunction,
		const TRuntimeModuleId _runtimeModuleId )
	{
		assert( !IsDefined() );
		assert( _preparatoryFunction != 0 );
		preparatoryFunction = _preparatoryFunction;
		runtimeModuleId = _runtimeModuleId;
	}

	const CPreparatoryFunction* PreparatoryFunction() const
	{
		assert( IsPreparatoryFunction() );
		return preparatoryFunction;
	}

	const TRuntimeModuleId RuntimeModuleId() const
	{
		assert( IsPreparatoryFunction() );
		return runtimeModuleId;
	}

	void SetEmbeddedFunction( const TEmbeddedFunctionPtr _embeddedFunction )
	{
		assert( !IsDefined() );
		assert( _embeddedFunction != 0 );
		embeddedFunction = _embeddedFunction;
	}

	TEmbeddedFunctionPtr EmbeddedFunction() const
	{
		assert( IsEmbeddedFunction() );
		return embeddedFunction;
	}

private:
	const CPreparatoryFunction* preparatoryFunction;
	TEmbeddedFunctionPtr embeddedFunction;
	TRuntimeModuleId runtimeModuleId;
};

//-----------------------------------------------------------------------------
// CExternalFunctionData

class CExternalFunctionData {
public:
	CExternalFunctionData( int _globalIndex,
			CPreparatoryFunction* _preparatoryFunction ) :
		globalIndex( _globalIndex ),
		preparatoryFunction( _preparatoryFunction )
	{
		assert( globalIndex >= 0 );
		assert( preparatoryFunction != 0 );
	}

	int GlobalIndex() const { return globalIndex; }
	CPreparatoryFunction* PreparatoryFunction() const
		{ return preparatoryFunction; }

private:
	int globalIndex;
	CPreparatoryFunction* preparatoryFunction;
};

//-----------------------------------------------------------------------------
// CPreparatoryRuntimeFunction

class CPreparatoryRuntimeFunction : public CRuntimeFunction {
public:
	CPreparatoryRuntimeFunction( CPreparatoryFunction* const function,
		const TRuntimeModuleId moduleId );

	CPreparatoryFunction* PreparatoryFunction() const { return function; }
	TRuntimeModuleId RuntimeModuleId() const { return moduleId; }

private:
	CPreparatoryFunction* const function;
	const TRuntimeModuleId moduleId;

	static TRuntimeFunctionType convertType(
		const CPreparatoryFunction* const function );
};

CPreparatoryRuntimeFunction::CPreparatoryRuntimeFunction(
		CPreparatoryFunction* const _function,
		const TRuntimeModuleId _moduleId ) :
	CRuntimeFunction( convertType( _function ) ),
	function( _function ),
	moduleId( _moduleId )
{
}

TRuntimeFunctionType CPreparatoryRuntimeFunction::convertType(
	const CPreparatoryFunction* const function )
{
	assert( function != 0 );
	switch( function->GetType() ) {
		case PFT_Ordinary:
			return RFT_Ordinary;
		case PFT_Empty:
			return RFT_Empty;
		case PFT_External:
			return RFT_External;
		case PFT_Declared:
		case PFT_Defined:
		case PFT_Compiled:
		case PFT_Embedded:
		default:
			break;
	}
	assert( false );
	return RFT_Empty;
}

//-----------------------------------------------------------------------------
// CInternalProgramBuilder

class CInternalProgramBuilder {
public:
	static CProgramPtr Build( CModuleDataVector& modules,
		CErrorsHelper& errors );

private:
	CErrorsHelper& errors;
	typedef std::vector<CExternalFunctionData> CExternals;
	CExternals externals;
	CDictionary<CGlobalFunctionData, std::string> globals;
	CProgramPtr program;

	CInternalProgramBuilder( CErrorsHelper& _errors, int numberOfModules ) :
		errors( _errors ),
		program( new CProgram( numberOfModules ) )
	{
		assert( static_cast<bool>( program ) );
	}

	void addFunction( CPreparatoryFunction* function,
		const TRuntimeModuleId runtimeModuleId );
	void addFunctions( const CModuleData& module, CRuntimeModule& runtimeModule,
		const TRuntimeModuleId runtimeModuleId );
	void collect( CModuleDataVector& modules );
	void check();
	void compile();
	void link();
};

//-----------------------------------------------------------------------------

CProgramPtr CInternalProgramBuilder::Build( CModuleDataVector& modules,
	CErrorsHelper& errors )
{
	assert( !errors.HasErrors() );
	assert( !modules.empty() );
	CInternalProgramBuilder builder( errors, modules.size() );
	builder.collect( modules );
	if( errors.HasErrors() ) {
		return nullptr;
	}
	builder.check();
	if( errors.HasErrors() ) {
		return nullptr;
	}
	builder.compile();
	assert( !errors.HasErrors() );
	builder.link();
	assert( !errors.HasErrors() );
	return CProgramPtr( builder.program.release() );
}

void CInternalProgramBuilder::addFunction( CPreparatoryFunction* function,
	const TRuntimeModuleId runtimeModuleId )
{
	const bool isExternal = function->IsExternal();
	const bool isGlobal = function->IsEntry();
	if( !( isExternal || isGlobal ) ) {
		return;
	}
	int globalIndex = globals.AddKey( function->ExternalName() );
	if( isGlobal ) {
		assert( !isExternal );
		CGlobalFunctionData& global = globals.GetData( globalIndex );
		if( global.IsDefined() ) {
			std::ostringstream stringStream;
			stringStream << "function with external name `"
				<< function->ExternalNameToken().word
				<< "` already defined in program";
			errors.Error( stringStream.str() );
		} else {
			global.SetPreparatoryFunction( function, runtimeModuleId );
		}
	} else {
		assert( isExternal );
		externals.push_back( CExternalFunctionData( globalIndex, function ) );
	}
}
void CInternalProgramBuilder::addFunctions( const CModuleData& module,
	CRuntimeModule& runtimeModule, const TRuntimeModuleId runtimeModuleId )
{
	const CPreparatoryFunctions& functions = module.Functions;
	for( int i = 0; i < functions.Size(); i++ ) {
		CPreparatoryFunction* function = functions.GetData( i ).get();
		CRuntimeFunctionPtr& runtimeFunction = runtimeModule.Functions.GetData(
			runtimeModule.Functions.AddKey( function->Name() ) );
		assert( !static_cast<bool>( runtimeFunction ) );
		runtimeFunction.reset( new CPreparatoryRuntimeFunction( function,
			runtimeModuleId ) );
		addFunction( function, runtimeModuleId );
	}
}

void CInternalProgramBuilder::collect( CModuleDataVector& modules )
{
	TRuntimeModuleId currentModuleId = 0;
	for( CModuleDataVector::const_iterator module = modules.begin();
		module != modules.end(); ++module )
	{
		addFunctions( *( *module ), program->Module( currentModuleId ),
			currentModuleId );
		currentModuleId++;
	}
	modules.clear();
}

void CInternalProgramBuilder::check()
{
	for( CExternals::const_iterator	function = externals.begin();
		function != externals.end(); ++function )
	{
		const int globalIndex = function->GlobalIndex();
		if( !globals.GetData( globalIndex ).IsDefined() ) {
			std::ostringstream stringStream;
			stringStream << "function with external name `"
				<< globals.GetKey( globalIndex )
				<< "` was not defined in program";
			errors.Error( stringStream.str() );
		}
	}
}

void CInternalProgramBuilder::compile()
{
	CFunctionCompiler compiler;
	for( int moduleId = 0; moduleId < program->NumberOfModules(); moduleId++ )
	{
		const CRuntimeFunctions& functions =
			program->Module( moduleId ).Functions;
		for( int i = 0; i < functions.Size(); i++ ) {
			const CPreparatoryRuntimeFunction& function = static_cast<
				CPreparatoryRuntimeFunction&>( *functions.GetData( i ) );
			if( function.PreparatoryFunction()->IsOrdinary() ) {
				function.PreparatoryFunction()->Compile( compiler );
			}
		}
	}
}

void CInternalProgramBuilder::link()
{
	for( CExternals::iterator function = externals.begin();
		function != externals.end(); ++function )
	{
		function->PreparatoryFunction();
		const int globalIndex = function->GlobalIndex();
		const CGlobalFunctionData& global = globals.GetData( globalIndex );
		assert( global.IsDefined() );
		if( global.IsEmbeddedFunction() ) {
			function->PreparatoryFunction()->SetEmbedded(
				global.EmbeddedFunction() );
		} else {
			assert( !global.IsPreparatoryFunction() );
			function->PreparatoryFunction()->Link(
				*global.PreparatoryFunction() );
		}
	}

	for( int moduleId = 0; moduleId < program->NumberOfModules(); moduleId++ )
	{
		const CRuntimeFunctions& functions =
			program->Module( moduleId ).Functions;
		for( int i = 0; i < functions.Size(); i++ ) {
			const CPreparatoryRuntimeFunction& function = static_cast<
				CPreparatoryRuntimeFunction&>( *functions.GetData( i ) );
			const CPreparatoryFunction* preparatoryFunction =
				function.PreparatoryFunction();
			CRuntimeFunctionPtr newRuntimeFunction;
			switch( function.Type() ) {
				case RFT_Empty:
					assert( preparatoryFunction->IsEmpty() );
					newRuntimeFunction.reset( new CEmptyFunction );
					break;
				case RFT_Embedded:
					assert( preparatoryFunction->IsEmbedded() );
					newRuntimeFunction.reset( new CEmbeddedFunction(
						preparatoryFunction->EmbeddedFunction() ) );
					break;
				case RFT_External:
					assert( preparatoryFunction->IsEmpty()
						|| preparatoryFunction->IsEmbedded()
						|| preparatoryFunction->IsOrdinary() );
					// todo: ---
					newRuntimeFunction.reset( new CExternalFunction( 0,
						function.RuntimeModuleId() ) );
					break;
				case RFT_Ordinary:
					assert( preparatoryFunction->IsOrdinary() );
					// todo: ---
					newRuntimeFunction.reset( new COrdinaryFunction( 0 ) );
					break;
				default:
					assert( false );
					break;
			}
		}
	}
}

//-----------------------------------------------------------------------------
// CProgramBuilder

CProgramBuilder::CProgramBuilder( IErrorHandler* errorHandler ) :
	CFunctionBuilder( errorHandler )
{
	Reset();
}

void CProgramBuilder::Reset()
{
	CFunctionBuilder::Reset();
}

void CProgramBuilder::AddModule( CModuleDataPtr& module )
{
	modules.push_back( CModuleDataPtr( module.release() ) );
}

void CProgramBuilder::BuildProgram()
{
	CInternalProgramBuilder::Build( modules, *this );
}

//-----------------------------------------------------------------------------

} // end of namespace Refal2
<|endoftext|>


<commit_before>#include "Paging.h"
#include "utility.h"
#include "globals.h"

const uint HF_BEGIN = THREEGB;

PageDirectoryEntry PDElower[1024];
PageDirectoryEntry* PDE = (PageDirectoryEntry*)((uint)PDElower + HF_BEGIN);
PageTable PT[1<<20];
const int MAX_INIT_PAGE = 2;

void PageDirectoryEntry::setAddr(void* a) {
    setAddr((uint)a);
}

void PageDirectoryEntry::setAddr(uint a) {
    assert((a & ((1<<12)-1)) == 0);
    PTaddr = a >> 12;
}

void PageTable::setAddr(void* a) {
    setAddr((uint)a);
}

void PageTable::setAddr(uint a) {
    assert((a & ((1<<12)-1)) == 0);
    addr = a >> 12;
}

void* PageTable::getAddr() {
    return (void*)(addr << 12);
}

void setupBasicPaging() {
    for(int i = 0; i < 1024; ++i) {
        PDElower[i].present = false;
        PDElower[i].readWrite = true;
        PDElower[i].user = false;
        PDElower[i].writeThrough = true;
        PDElower[i].cacheDisable = false;
        PDElower[i].accessed = false;
        PDElower[i].zero = false;
        PDElower[i].isSizeMega = false;
        PDElower[i].nothing = 0;
        PDElower[i].PTaddr = 0;
    }
    //Identity map the first 4Mb
    PDElower[0].present = true;
    PDElower[0].isSizeMega = true;
    PDElower[0].PTaddr = 0;

    //For the higher half kernel
    for(int i = 0; i < MAX_INIT_PAGE; ++i) {
        PDElower[768+i].present = true;
        PDElower[768+i].isSizeMega = true;
        PDElower[768+i].PTaddr = i<<10;
    }
}

Paging::Paging() : _brk(HF_BEGIN + MAX_INIT_PAGE*4*1024*1024), _truebrk(_brk) {
    for(int i = MAX_INIT_PAGE; i < 256; ++i) {
        PDE[768+i].PTaddr = (((uint)&PT[1024*i])-HF_BEGIN) >> 12;
    }
}

static inline PageTable* getPT(uint addr) {
    return &PT[(addr-HF_BEGIN)>>12];
}

static inline PageDirectoryEntry* getPDE(uint addr) {
    return &PDE[addr >> 22];
}

static inline void invlpg(uint addr) {
    asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
}

int Paging::brk(void* paddr) {
    uint addr = (uint)paddr;
    if(addr > _truebrk) {
        while(addr > _truebrk) {
            if((_truebrk & ((1<<22)-1)) == 0) {
                for(int i = 0; i < 1024; ++i) {
                    getPT(_truebrk)[i].present = false;
                }
                getPDE(_truebrk)->present = true;
            }
            getPT(_truebrk)->setAddr((uint)physmemalloc.alloc());
            getPT(_truebrk)->present = true;
            invlpg(_truebrk);
            _truebrk += 0x1000;
        }
    } else {
        while(_truebrk - 0x1000 >= addr) {
            _truebrk -= 0x1000;
            physmemalloc.free(getPT(_truebrk)->getAddr());
            getPT(_truebrk)->present = false;
            getPT(_truebrk)->setAddr(nullptr);
            if((_truebrk & ((1<<22)-1)) == 0) {
                getPDE(_truebrk)->present = false;
                getPDE(_truebrk)->setAddr(nullptr);
            }
            invlpg(_truebrk);
        }
    }
    _brk = addr;
    return 0;
}

void* Paging::sbrk(int inc) {
    void* res = (void*)_brk;
    brk(((char*)_brk) + inc);
    return res;
}

static MallocHeader* firstHeader;

void initkmalloc() {
    MallocHeader* head = (MallocHeader*)paging.sbrk(4);
    head->size = 0;
    head->flags = 0;
    firstHeader = head;
}

static inline void* headerToPtr(MallocHeader* head) {
    return (void*)((char*)head + sizeof(MallocHeader));
}

static inline MallocHeader* ptrToHeader(void* ptr) {
    return (MallocHeader*)((char*)ptr - sizeof(MallocHeader));
}

static inline MallocHeader* nextHeader(MallocHeader* head) {
    return (MallocHeader*)((char*)head + head->getSize() + 4);
}

static inline uint align4(uint n) {
    return n + 4 - (n%4);
}

static const int ALLOCATED = 1;

void* kmalloc(uint size) {
    MallocHeader* head = firstHeader;
    while(true) {
        if(head->size == 0) {
            uint trueSize = align4(size);
            assert(headerToPtr(head) == paging.sbrk(4+trueSize));
            head->setSize(trueSize);
            head->flags |= ALLOCATED;
            MallocHeader* nextHead = nextHeader(head);
            nextHead->size = 0;
            nextHead->flags = 0;
            return headerToPtr(head);
        }
        if((head->flags & ALLOCATED) == 0 && head->getSize() >= size) {
            head->flags |= ALLOCATED;
            return headerToPtr(head);
        }
        head = nextHeader(head);
    }
}

void kfree(void* ptr) {
    MallocHeader* head = ptrToHeader(ptr);
    assert((head->flags & ALLOCATED) != 0);
    head->flags &= ~ALLOCATED;
}

<commit_msg>Improve kmalloc<commit_after>#include "Paging.h"
#include "utility.h"
#include "globals.h"

const uint HF_BEGIN = THREEGB;

PageDirectoryEntry PDElower[1024];
PageDirectoryEntry* PDE = (PageDirectoryEntry*)((uint)PDElower + HF_BEGIN);
PageTable PT[1<<20];
const int MAX_INIT_PAGE = 2;

void PageDirectoryEntry::setAddr(void* a) {
    setAddr((uint)a);
}

void PageDirectoryEntry::setAddr(uint a) {
    assert((a & ((1<<12)-1)) == 0);
    PTaddr = a >> 12;
}

void PageTable::setAddr(void* a) {
    setAddr((uint)a);
}

void PageTable::setAddr(uint a) {
    assert((a & ((1<<12)-1)) == 0);
    addr = a >> 12;
}

void* PageTable::getAddr() {
    return (void*)(addr << 12);
}

void setupBasicPaging() {
    for(int i = 0; i < 1024; ++i) {
        PDElower[i].present = false;
        PDElower[i].readWrite = true;
        PDElower[i].user = false;
        PDElower[i].writeThrough = true;
        PDElower[i].cacheDisable = false;
        PDElower[i].accessed = false;
        PDElower[i].zero = false;
        PDElower[i].isSizeMega = false;
        PDElower[i].nothing = 0;
        PDElower[i].PTaddr = 0;
    }
    //Identity map the first 4Mb
    PDElower[0].present = true;
    PDElower[0].isSizeMega = true;
    PDElower[0].PTaddr = 0;

    //For the higher half kernel
    for(int i = 0; i < MAX_INIT_PAGE; ++i) {
        PDElower[768+i].present = true;
        PDElower[768+i].isSizeMega = true;
        PDElower[768+i].PTaddr = i<<10;
    }
}

Paging::Paging() : _brk(HF_BEGIN + MAX_INIT_PAGE*4*1024*1024), _truebrk(_brk) {
    for(int i = MAX_INIT_PAGE; i < 256; ++i) {
        PDE[768+i].PTaddr = (((uint)&PT[1024*i])-HF_BEGIN) >> 12;
    }
}

static inline PageTable* getPT(uint addr) {
    return &PT[(addr-HF_BEGIN)>>12];
}

static inline PageDirectoryEntry* getPDE(uint addr) {
    return &PDE[addr >> 22];
}

static inline void invlpg(uint addr) {
    asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
}

int Paging::brk(void* paddr) {
    uint addr = (uint)paddr;
    if(addr > _truebrk) {
        while(addr > _truebrk) {
            if((_truebrk & ((1<<22)-1)) == 0) {
                for(int i = 0; i < 1024; ++i) {
                    getPT(_truebrk)[i].present = false;
                }
                getPDE(_truebrk)->present = true;
            }
            getPT(_truebrk)->setAddr((uint)physmemalloc.alloc());
            getPT(_truebrk)->present = true;
            invlpg(_truebrk);
            _truebrk += 0x1000;
        }
    } else {
        while(_truebrk - 0x1000 >= addr) {
            _truebrk -= 0x1000;
            physmemalloc.free(getPT(_truebrk)->getAddr());
            getPT(_truebrk)->present = false;
            getPT(_truebrk)->setAddr(nullptr);
            if((_truebrk & ((1<<22)-1)) == 0) {
                getPDE(_truebrk)->present = false;
                getPDE(_truebrk)->setAddr(nullptr);
            }
            invlpg(_truebrk);
        }
    }
    _brk = addr;
    return 0;
}

void* Paging::sbrk(int inc) {
    void* res = (void*)_brk;
    brk(((char*)_brk) + inc);
    return res;
}

static MallocHeader* firstHeader;

static const int FREE = 1;
static const int PREV_FREE = 2;

void initkmalloc() {
    MallocHeader* head = (MallocHeader*)paging.sbrk(4);
    head->size = 0;
    head->flags = 0;
    firstHeader = head;
}

static inline void* headerToPtr(MallocHeader* head) {
    return (void*)((char*)head + sizeof(MallocHeader));
}

static inline MallocHeader* ptrToHeader(void* ptr) {
    return (MallocHeader*)((char*)ptr - sizeof(MallocHeader));
}

static inline MallocHeader* getPrevBoundaryTag(MallocHeader* head) {
    return (MallocHeader*)((char*)head - sizeof(MallocHeader));
}

static inline MallocHeader* getNextBoundaryTag(MallocHeader* head) {
    return (MallocHeader*)((char*)head + head->getSize());
}

static inline MallocHeader* nextHeader(MallocHeader* head) {
    return (MallocHeader*)((char*)head + head->getSize() + sizeof(MallocHeader));
}

static inline uint align4(uint n) {
    return n + 4 - (n%4);
}

void* kmalloc(uint size) {
    size = align4(size);
    MallocHeader* head = firstHeader;
    while(true) {
        //if we are at the end of the linked list
        if(head->size == 0) {
            //allocate enough space
            assert(headerToPtr(head) == paging.sbrk(4+size));
            //setup header
            head->setSize(size);
            head->flags &= ~FREE;
            //setup the next "end of list" header
            MallocHeader* nextHead = nextHeader(head);
            nextHead->size = 0;
            nextHead->flags = 0;
            //return result
            return headerToPtr(head);
            //we didn't do anything with boundary tags because there is nothing to do.
            //(if the previous block is free, head->flags already contains PREV_FREE)
        }
        //if there is a free block with enough space
        if((head->flags & FREE) != 0 && head->getSize() >= size) {
            //change the flag
            head->flags &= ~FREE;
            //if there is enough space to split this block in two
            if(head->getSize() - size >= 2*sizeof(MallocHeader)) {
                MallocHeader* oldNxtHead = nextHeader(head); //only used in the assert
                uint oldSize = head->getSize();
                //setup the current header
                head->setSize(size);
                MallocHeader* nxtHead = nextHeader(head);
                //setup the header of the next block
                nxtHead->setSize(oldSize - size - sizeof(MallocHeader));
                nxtHead->flags = 0; //it's free and its previous block is allocated
                assert(oldNxtHead == nextHeader(nxtHead));
                //nxtHead is free: copy its boundary tag
                *getNextBoundaryTag(nxtHead) = *nxtHead;
                //oldNxtHead->flags already contains PREV_FREE
                assert((oldNxtHead->flags & PREV_FREE) != 0);
            }
            //remove the PREV_FREE flag of next block
            nextHeader(head)->flags &= ~PREV_FREE;
            return headerToPtr(head);
        }
        head = nextHeader(head);
    }
}

void kfree(void* ptr) {
    MallocHeader* head = ptrToHeader(ptr);
    //free the block
    assert((head->flags & FREE) == 0);
    head->flags |= FREE;

    //set the PREV_FREE flag on the next block
    nextHeader(head)->flags |= PREV_FREE;

    //try to merge with the next block
    MallocHeader* nxtHead = nextHeader(head);
    if(nxtHead->size != 0 && (nxtHead->flags & FREE) != 0) {
        MallocHeader* oldNxtNxtHead = nextHeader(nxtHead); //only used in the assert
        //merge
        head->setSize(head->getSize() + nxtHead->getSize() + sizeof(MallocHeader));
        assert(oldNxtNxtHead == nextHeader(head));
        //copy boundary tag
        *getNextBoundaryTag(head) = *head;
    }

    //try to merge with the previous block
    if((head->flags & PREV_FREE) != 0) {
        MallocHeader* oldNxtHead = nextHeader(head); //only used in the assert
        //retrieve the previous header using the boundary tag
        MallocHeader* boundTag = getPrevBoundaryTag(head);
        MallocHeader* prevHead = (MallocHeader*)((char*)boundTag - boundTag->getSize());
        assert(nextHeader(prevHead) == head);
        //merge
        prevHead->setSize(prevHead->getSize() + head->getSize() + sizeof(MallocHeader));
        assert(nextHeader(prevHead) == oldNxtHead);
        //copy boundary tag
        *getNextBoundaryTag(prevHead) = *prevHead;
    }
}

<|endoftext|>