<commit_before>#include "YokogawaInterface.hh"

namespace yokogawa_interface {
   //___________________________________________________________________________
   int set_mode(int mode){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      switch(mode){
	 case kVOLTAGE:
	    sprintf(cmd,":SOUR:FUNC VOLT");
	    break;
	 case kCURRENT:
	    sprintf(cmd,":SOUR:FUNC CURR");
	    break;
	 default:
	    // invalid mode, return with error
	    return -1;
      }
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_range(double r){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG %.5E",r);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_range_min(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG MIN");
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_range_max(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG MAX");
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_level(double lvl){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:LEV %.5lf",lvl);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_output_state(int state){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":OUTP:STAT %d",state);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_clock_time(int hr,int min,int sec){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:TIME %2d:%2d:%2d",hr,min,sec);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_clock_date(int day,int month,int year){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:DATE %4d/%2d/%2d",year,month,day);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int self_test(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,"*TST?");
      buf = ask(cmd);
      int rc = atoi(buf);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int error_check(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYSTem::ERRor?");
      buf    = ask(cmd);
      int rc = atoi(buf);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int get_output_state(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,"OUTP?");
      buf    = ask(cmd);
      int rc = atoi(buf);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int get_mode(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:FUNC?");
      buf = ask(cmd);
      int rc=-1;
      int res = strcmp(buf,"CURR");
      if (res==0) {
	 rc = kCURRENT;
      } else {
         rc = kVOLTAGE;
      }
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   double get_level(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:LEV?");
      buf = ask(cmd);
      double lvl = atof(buf);
      delete cmd;
      return lvl;
   }
   //___________________________________________________________________________
   double get_range(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG?");
      buf = ask(cmd);
      double r = atof(buf);
      delete cmd;
      return r;
   }
   //___________________________________________________________________________
   char *get_device_id(){
      const int SIZE = 100;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,"*IDN?");
      buf = ask(cmd);
      delete cmd;
      return buf;
   }
   //___________________________________________________________________________
   char *get_clock_time(){
      const int SIZE = 100;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:TIME?");
      buf = ask(cmd);
      delete cmd;
      return buf;
   }
   //___________________________________________________________________________
   char *get_clock_date(){
      const int SIZE = 100;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:DATE?");
      buf = ask(cmd);
      delete cmd;
      return buf;
   }
   //___________________________________________________________________________
   int write(const char *cmd){
      int rc = vxi11_send(clink,cmd);
      return rc;
   }
   //___________________________________________________________________________
   char *ask(const char *cmd){
      int rc = write(cmd);
      int bytes_rec=0;
      const int SIZE = 100;
      strcpy(REC_BUF,"");   // clear the receive buffer
      if(rc!=0){
	 // error!
	 sprintf(REC_BUF,"ERROR, can't send query: %s \n",cmd);
      }else{
	 bytes_rec = vxi11_receive(clink,REC_BUF,SIZE);
         if(bytes_rec<=0){
	    sprintf(REC_BUF,"ERROR, can't read result of query: %s \n",cmd);
         }
      }
      return REC_BUF;
   }
   //___________________________________________________________________________
   int open_connection(const char *ip_addr){
      buf     = new char[YOKO_BUF_SIZE+1];
      REC_BUF = new char[YOKO_BUF_SIZE+1];
      sprintf(DeviceIP,ip_addr);
      printf("Attempting to open the connection to IP address %s... \n",ip_addr);
      int rc = vxi11_open_device(DeviceIP,clink);
      printf("Returning... \n");
      return rc;
   }
   //___________________________________________________________________________
   int close_connection(){
      int rc = vxi11_close_device(DeviceIP,clink);
      delete buf;
      delete REC_BUF;
      return rc;
   }
}
<commit_msg>Small update to the yokogawa code<commit_after>#include "YokogawaInterface.hh"

namespace yokogawa_interface {
   //___________________________________________________________________________
   int set_mode(int mode){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      switch(mode){
	 case kVOLTAGE:
	    sprintf(cmd,":SOUR:FUNC VOLT");
	    break;
	 case kCURRENT:
	    sprintf(cmd,":SOUR:FUNC CURR");
	    break;
	 default:
	    // invalid mode, return with error
	    return -1;
      }
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_range(double r){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG %.5E",r);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_range_min(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG MIN");
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_range_max(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG MAX");
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_level(double lvl){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:LEV %.5lf",lvl);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_output_state(int state){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":OUTP:STAT %d",state);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_clock_time(int hr,int min,int sec){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:TIME %2d:%2d:%2d",hr,min,sec);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int set_clock_date(int day,int month,int year){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:DATE %4d/%2d/%2d",year,month,day);
      int rc = write(cmd);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int self_test(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,"*TST?");
      buf = ask(cmd);
      int rc = atoi(buf);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int error_check(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYSTem::ERRor?");
      buf    = ask(cmd);
      int rc = atoi(buf);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int get_output_state(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,"OUTP?");
      buf    = ask(cmd);
      int rc = atoi(buf);
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   int get_mode(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:FUNC?");
      buf = ask(cmd);
      int rc=-1;
      int res = strcmp(buf,"CURR");
      if (res==0) {
	 rc = kCURRENT;
      } else {
         rc = kVOLTAGE;
      }
      delete cmd;
      return rc;
   }
   //___________________________________________________________________________
   double get_level(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:LEV?");
      buf = ask(cmd);
      double lvl = atof(buf);
      delete cmd;
      return lvl;
   }
   //___________________________________________________________________________
   double get_range(){
      const int SIZE = 20;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SOUR:RANG?");
      buf = ask(cmd);
      double r = atof(buf);
      delete cmd;
      return r;
   }
   //___________________________________________________________________________
   char *get_device_id(){
      const int SIZE = 100;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,"*IDN?");
      buf = ask(cmd);
      delete cmd;
      return buf;
   }
   //___________________________________________________________________________
   char *get_clock_time(){
      const int SIZE = 100;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:TIME?");
      buf = ask(cmd);
      delete cmd;
      return buf;
   }
   //___________________________________________________________________________
   char *get_clock_date(){
      const int SIZE = 100;
      char *cmd = new char[SIZE+1];
      sprintf(cmd,":SYST:CLOC:DATE?");
      buf = ask(cmd);
      delete cmd;
      return buf;
   }
   //___________________________________________________________________________
   int write(const char *cmd){
      int rc = vxi11_send(clink,cmd);
      return rc;
   }
   //___________________________________________________________________________
   char *ask(const char *cmd){
      const int SIZE = 100;
      strcpy(REC_BUF,"");   // clear the receive buffer
      int rc = vxi11_send_and_receive(clink,cmd,REC_BUF,SIZE,100);  // last argument is a timeout
      if(rc!=0) strcpy(REC_BUF,"NO RESPONSE");                      // comms failed
      return REC_BUF;
   }
   //___________________________________________________________________________
   int open_connection(const char *ip_addr){
      buf     = new char[YOKO_BUF_SIZE+1];
      REC_BUF = new char[YOKO_BUF_SIZE+1];
      sprintf(DeviceIP,ip_addr);
      printf("Attempting to open the connection to IP address %s... \n",ip_addr);
      int rc = vxi11_open_device(DeviceIP,clink);
      printf("Returning... \n");
      return rc;
   }
   //___________________________________________________________________________
   int close_connection(){
      int rc = vxi11_close_device(DeviceIP,clink);
      delete buf;
      delete REC_BUF;
      return rc;
   }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of the Qt Build Suite.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "vsenvironmentdetector.h"

#include "msvcinfo.h"
#include <logging/translator.h>
#include <tools/qbsassert.h>

#include <QDebug>
#include <QDir>
#include <QProcess>
#include <QTemporaryFile>
#include <QTextStream>

#ifdef Q_OS_WIN
#include <qt_windows.h>
#include <ShlObj.h>
#endif

using qbs::Internal::Tr;

static QString windowsSystem32Path()
{
#ifdef Q_OS_WIN
    wchar_t str[MAX_PATH];
    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, str)))
        return QString::fromUtf16(reinterpret_cast<ushort*>(str));
#endif
    return QString();
}

VsEnvironmentDetector::VsEnvironmentDetector(MSVC *msvc)
    : m_msvc(msvc)
    , m_windowsSystemDirPath(windowsSystem32Path())
{
}

bool VsEnvironmentDetector::start()
{
    m_msvc->environments.clear();
    const QString vcvarsallbat = QDir::cleanPath(m_msvc->installPath
                                                     + QLatin1String("/../vcvarsall.bat"));
    if (!QFile::exists(vcvarsallbat)) {
        m_errorString = Tr::tr("Cannot find '%1'.").arg(QDir::toNativeSeparators(vcvarsallbat));
        return false;
    }

    QTemporaryFile tmpFile(QDir::tempPath() + QLatin1Char('/') + QLatin1String("XXXXXX.bat"));
    if (!tmpFile.open()) {
        m_errorString = Tr::tr("Cannot open temporary file '%1' for writing.").arg(
                    tmpFile.fileName());
        return false;
    }

    writeBatchFile(&tmpFile, vcvarsallbat);
    tmpFile.flush();

    QProcess process;
    const QString shellFilePath = QLatin1String("cmd.exe");
    process.start(shellFilePath, QStringList()
                  << QLatin1String("/C") << tmpFile.fileName());
    if (!process.waitForStarted()) {
        m_errorString = Tr::tr("Failed to start '%1'.").arg(shellFilePath);
        return false;
    }
    process.waitForFinished(-1);
    if (process.exitStatus() != QProcess::NormalExit) {
        m_errorString = Tr::tr("Process '%1' did not exit normally.").arg(shellFilePath);
        return false;
    }
    if (process.exitCode() != 0) {
        m_errorString = Tr::tr("Failed to detect Visual Studio environment.");
        return false;
    }
    parseBatOutput(process.readAllStandardOutput());
    return true;
}

static void batClearVars(QTextStream &s, const QStringList &varnames)
{
    foreach (const QString &varname, varnames)
        s << "set " << varname << '=' << endl;
}

static void batPrintVars(QTextStream &s, const QStringList &varnames)
{
    foreach (const QString &varname, varnames)
        s << "echo " << varname << "=%" << varname << '%' << endl;
}

static QString vcArchitecture(const QString &arch)
{
    if (arch == QLatin1String("armv7"))
        return QLatin1String("arm");
    if (arch == QLatin1String("x86_64"))
        return QLatin1String("amd64");
    return arch;
}

void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcvarsallbat) const
{
    const QStringList varnames = QStringList() << QLatin1String("PATH")
            << QLatin1String("INCLUDE") << QLatin1String("LIB");
    QTextStream s(device);
    s << "@echo off" << endl;
    foreach (const QString &architecture, m_msvc->architectures) {
        s << "echo --" << architecture << "--" << endl
          << "setlocal" << endl;
        batClearVars(s, varnames);
        s << "set PATH=" << m_windowsSystemDirPath << endl; // vcvarsall.bat needs tools from here
        s << "call \"" << vcvarsallbat << "\" " << vcArchitecture(architecture)
          << " || exit /b 1" << endl;
        batPrintVars(s, varnames);
        s << "endlocal" << endl;
    }
}

void VsEnvironmentDetector::parseBatOutput(const QByteArray &output)
{
    QString arch;
    QProcessEnvironment *targetEnv = 0;
    foreach (QByteArray line, output.split('\n')) {
        line = line.trimmed();
        if (line.isEmpty())
            continue;

        if (line.startsWith("--") && line.endsWith("--")) {
            line.remove(0, 2);
            line.chop(2);
            arch = QString::fromLocal8Bit(line);
            targetEnv = &m_msvc->environments[arch];
        } else {
            int idx = line.indexOf('=');
            if (idx < 0)
                continue;
            QBS_CHECK(targetEnv);
            const QString name = QString::fromLocal8Bit(line.left(idx));
            QString value = QString::fromLocal8Bit(line.mid(idx + 1));
            if (name.compare(QLatin1String("PATH"), Qt::CaseInsensitive) == 0)
                value.remove(m_windowsSystemDirPath);
            if (value.endsWith(QLatin1Char(';')))
                value.chop(1);
            if (value.endsWith(QLatin1Char('\\')))
                value.chop(1);
            targetEnv->insert(name, value);
        }
    }
}
<commit_msg>Fix Visual Studio environment detector.<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of the Qt Build Suite.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "vsenvironmentdetector.h"

#include "msvcinfo.h"
#include <logging/translator.h>
#include <tools/qbsassert.h>

#include <QDebug>
#include <QDir>
#include <QProcess>
#include <QTemporaryFile>
#include <QTextStream>

#ifdef Q_OS_WIN
#include <qt_windows.h>
#include <ShlObj.h>
#endif

using qbs::Internal::Tr;

static QString windowsSystem32Path()
{
#ifdef Q_OS_WIN
    wchar_t str[MAX_PATH];
    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, str)))
        return QString::fromUtf16(reinterpret_cast<ushort*>(str));
#endif
    return QString();
}

VsEnvironmentDetector::VsEnvironmentDetector(MSVC *msvc)
    : m_msvc(msvc)
    , m_windowsSystemDirPath(windowsSystem32Path())
{
}

bool VsEnvironmentDetector::start()
{
    m_msvc->environments.clear();
    const QString vcvarsallbat = QDir::cleanPath(m_msvc->installPath
                                                     + QLatin1String("/../vcvarsall.bat"));
    if (!QFile::exists(vcvarsallbat)) {
        m_errorString = Tr::tr("Cannot find '%1'.").arg(QDir::toNativeSeparators(vcvarsallbat));
        return false;
    }

    QTemporaryFile tmpFile(QDir::tempPath() + QLatin1Char('/') + QLatin1String("XXXXXX.bat"));
    if (!tmpFile.open()) {
        m_errorString = Tr::tr("Cannot open temporary file '%1' for writing.").arg(
                    tmpFile.fileName());
        return false;
    }

    writeBatchFile(&tmpFile, vcvarsallbat);
    tmpFile.flush();

    QProcess process;
    const QString shellFilePath = QLatin1String("cmd.exe");
    process.start(shellFilePath, QStringList()
                  << QLatin1String("/C") << tmpFile.fileName());
    if (!process.waitForStarted()) {
        m_errorString = Tr::tr("Failed to start '%1'.").arg(shellFilePath);
        return false;
    }
    process.waitForFinished(-1);
    if (process.exitStatus() != QProcess::NormalExit) {
        m_errorString = Tr::tr("Process '%1' did not exit normally.").arg(shellFilePath);
        return false;
    }
    if (process.exitCode() != 0) {
        m_errorString = Tr::tr("Failed to detect Visual Studio environment.");
        return false;
    }
    parseBatOutput(process.readAllStandardOutput());
    return true;
}

static void batClearVars(QTextStream &s, const QStringList &varnames)
{
    foreach (const QString &varname, varnames)
        s << "set " << varname << '=' << endl;
}

static void batPrintVars(QTextStream &s, const QStringList &varnames)
{
    foreach (const QString &varname, varnames)
        s << "echo " << varname << "=%" << varname << '%' << endl;
}

static void findSupportedArchitectures(MSVC *msvc)
{
    if (QFile::exists(msvc->clPath())
            || QFile::exists(msvc->clPath(QLatin1String("amd64_x86"))))
        msvc->architectures += QLatin1String("x86");
    if (QFile::exists(msvc->clPath(QLatin1String("amd64")))
            || QFile::exists(msvc->clPath(QLatin1String("x86_amd64"))))
        msvc->architectures += QLatin1String("x86_64");
    if (QFile::exists(msvc->clPath(QLatin1String("ia64")))
            || QFile::exists(msvc->clPath(QLatin1String("x86_ia64"))))
        msvc->architectures += QLatin1String("ia64");
    if (QFile::exists(msvc->clPath(QLatin1String("x86_arm")))
            || QFile::exists(msvc->clPath(QLatin1String("amd64_arm"))))
        msvc->architectures += QLatin1String("armv7");
}

static QString vcArchitecture(MSVC *msvc, const QString &targetArch)
{
    QString vcArch = targetArch;
    if (targetArch == QLatin1String("armv7"))
        vcArch = QLatin1String("arm");
    if (targetArch == QLatin1String("x86_64"))
        vcArch = QLatin1String("amd64");

    // Empty string for the native compiler (preferred)
    for (const QString &hostPrefix :
         QStringList({QString(), QStringLiteral("amd64_"), QStringLiteral("x86_")})) {
        if (QFile::exists(msvc->clPath(hostPrefix + vcArch))) {
            vcArch.prepend(hostPrefix);
            break;
        }
    }

    return vcArch;
}

void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcvarsallbat) const
{
    const QStringList varnames = QStringList() << QLatin1String("PATH")
            << QLatin1String("INCLUDE") << QLatin1String("LIB");
    QTextStream s(device);
    s << "@echo off" << endl;
    foreach (const QString &architecture, m_msvc->architectures) {
        s << "echo --" << architecture << "--" << endl
          << "setlocal" << endl;
        batClearVars(s, varnames);
        s << "set PATH=" << m_windowsSystemDirPath << endl; // vcvarsall.bat needs tools from here
        s << "call \"" << vcvarsallbat << "\" " << vcArchitecture(m_msvc, architecture)
          << " || exit /b 1" << endl;
        batPrintVars(s, varnames);
        s << "endlocal" << endl;
    }
}

void VsEnvironmentDetector::parseBatOutput(const QByteArray &output)
{
    QString arch;
    QProcessEnvironment *targetEnv = 0;
    foreach (QByteArray line, output.split('\n')) {
        line = line.trimmed();
        if (line.isEmpty())
            continue;

        if (line.startsWith("--") && line.endsWith("--")) {
            line.remove(0, 2);
            line.chop(2);
            arch = QString::fromLocal8Bit(line);
            targetEnv = &m_msvc->environments[arch];
        } else {
            int idx = line.indexOf('=');
            if (idx < 0)
                continue;
            QBS_CHECK(targetEnv);
            const QString name = QString::fromLocal8Bit(line.left(idx));
            QString value = QString::fromLocal8Bit(line.mid(idx + 1));
            if (name.compare(QLatin1String("PATH"), Qt::CaseInsensitive) == 0)
                value.remove(m_windowsSystemDirPath);
            if (value.endsWith(QLatin1Char(';')))
                value.chop(1);
            if (value.endsWith(QLatin1Char('\\')))
                value.chop(1);
            targetEnv->insert(name, value);
        }
    }
}
<|endoftext|>


<commit_before>
int main(int argc, char* argv[]) {

  return 0;
}
<commit_msg>Add CLI Parsing<commit_after>#include <string.h>
#include <iostream>

#define OPT_TRANSFORM "-o"
#define OPT_PRINT "-p"
#define OPT_STATIC "-a"
#define OPT_EXEC "-e"

using namespace std;

int main(int argc, char* argv[]) {
  bool transformEnabled = false;
  bool printEnabled = false;
  bool staticEnabled = false;
  bool execEnabled = false;
  char* fileName = NULL;

  for(int i = 1; i < argc; i++) {
    char* arg = argv[i];
    if(strcmp(arg, OPT_TRANSFORM)) {
      transformEnabled = true;
    } else if(strcmp(arg, OPT_PRINT)) {
      printEnabled = true;
    } else if(strcmp(arg, OPT_STATIC)) {
      staticEnabled = true;
    } else if(strcmp(arg, OPT_EXEC)) {
      execEnabled = true;
    } else {
      fileName = arg;
    }
  }

  if(fileName == NULL) {
    cerr << "No input file provided";
    return 1;
  }

  // LEXER
  // PARSER
  if(transformEnabled) {
    // TRANSFORM
  }
  if(printEnabled) {
    // PRINT
  }
  if(staticEnabled) {
    // STATIC
  }
  if(execEnabled) {
    // EXEC
  }

  return 0;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2011-2014, Robert J. Hansen <rjh@secret-alchemy.com>
 * and others.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Code standards:
 *   This is a small enough project we don't need a formal coding standard.
 *   That said, here are some helpful tips for people who want to submit
 *   patches:
 *
 *   - If it's not 100% ISO C++11, it won't get in.
 *   - It must compile cleanly and without warnings under both GNU G++
 *     and Clang++, even with "-W -Wextra -ansi -pedantic".
 *     (Exceptions can be made for warnings that are actually compiler
 *     conformance issues: for instance, Clang++ will warn that 'long long'
 *     is a C++11 extension, even when you run it in -std=C++11 mode.)
 *   - C++ offers 'and', 'or' and 'not' keywords instead of &&, || and !.
 *     I like these: I think they're more readable.  Please use them.
 *   - C++11 uniform initialization syntax, please.
 *   - Please try to follow the formatting conventions.  It's mostly
 *     straight-up astyle format, with occasional tweaks where necessary
 *     to get nice hardcopy printouts.
 *   - If you write a new function it must have a Doxygen block
 *     documenting it.
 *
 * Contributor history:
 *
 * Robert J. Hansen <rjh@secret-alchemy.com>
 *   - most everything
 */

#include "../config.h"
#include <sstream>
#include <sys/stat.h>
#include <syslog.h>
#include <set>
#include <string>
#include <time.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <algorithm>
#include <limits.h>
#include "handler.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <utility>

/* Additional defines necessary on FreeBSD: */
/* Necessary for sockaddr and sockaddr_in structures */
#ifdef __FreeBSD__
#include <sys/socket.h>
#include <netinet/in.h>
#endif

using std::stringstream;
using std::string;
using std::set;
using std::transform;
using std::find_if;
using std::not1;
using std::ptr_fun;
using std::ifstream;
using std::cerr;
using std::vector;
using std::remove_if;
using std::sort;
using std::pair;
using std::unique_ptr;

typedef unsigned long long ULONG64;
typedef pair<ULONG64, ULONG64> pair64;

#define INFO LOG_MAKEPRI(LOG_USER, LOG_INFO)
#define WARN LOG_MAKEPRI(LOG_USER, LOG_WARNING)
#define DEBUG LOG_MAKEPRI(LOG_USER, LOG_DEBUG)
#define CRITICAL LOG_MAKEPRI(LOG_USER, LOG_CRIT)
#define ALERT LOG_MAKEPRI(LOG_USER, LOG_ALERT)
#define EMERGENCY LOG_MAKEPRI(LOG_USER, LOG_EMERG)
#define MAX_PENDING_REQUESTS 20
#define BUFFER_SIZE 128

namespace
{
/** Tracks whether the server should only support protocol 1.0. */
bool old_only { false };

/** Tracks whether the server should support status queries. */
bool status_enabled { false };

/** Tracks whether the server should run as a daemon. */
bool standalone { false };

/** Our set of hashes, represented as a block of contiguous memory.
  * Note that the current NSRL library contains approximately 40
  * million values, each at roughly 32 bytes (rounded to binary
  * powers to make the math easier).  This is 2**25 values times
  * 2**5 bytes each = 2**30 bytes, or about a gig of RAM.
  *
  * Moral of the story: populating this set is computationally
  * expensive. */
vector<pair64> hash_set;

/** Tracks where we look for the location of the
  * reference data set. */
string RDS_LOC { PKGDATADIR "/hashes.txt" };

/** Which port to listen on */
uint16_t PORT { 9120 };

/** Determines whether a string represents a valid uppercase
  * MD5 hash. */

auto good_line(const string& line)
{
    if (line.size() != 32)
        return false;

    auto iter = line.cbegin();
    auto end = line.cend();
    while (iter != end and
            ((*iter >= '0' and *iter <= '9') or
             (*iter >= 'A' and *iter <= 'F')))
        ++iter;
    return (iter == end) ? true : false;
}

/** Loads hashes from disk and stores them in a fast-accessing
  * in-memory data structure.  This will be slow. */
void load_hashes()
{
    vector<char> buf(BUFFER_SIZE, 0);
    uint32_t line_count { 0 }, hash_count { 0 };
    ifstream infile { RDS_LOC.c_str() };

	hash_set.reserve(40000000);

    if (not infile)
    {
        syslog(WARN, "couldn't open hashes file %s",
               RDS_LOC.c_str());
        exit(EXIT_FAILURE);
    }

    while (infile)
    {
        memset(static_cast<void*>(&buf[0]), 0, BUFFER_SIZE);
        infile.getline(&buf[0], BUFFER_SIZE);
        line_count += 1;
        const string line(buf.cbegin(), find(buf.cbegin(), buf.cend(), 0));

        if (0 == line.size())
        {
            continue;
        }

        if (! good_line(line))
        {
            syslog(ALERT, "hash file appears corrupt!  Loading no hashes.");
            syslog(ALERT, "offending line is #%d", line_count);
            syslog(ALERT, "offending line has %d bytes", (int) line.size());
            syslog(ALERT, "Content follows:");
            syslog(ALERT, "%s", line.c_str());
            syslog(ALERT, "shutting down!");
            exit(EXIT_FAILURE);
            return;
        }
        hash_count += 1;

        if (0 == hash_count % 1000000)
        {
            syslog(INFO, "loaded %u million hashes", hash_count / 1000000);
        }

        hash_set.push_back(to_pair64(line));
    }
    infile.close();
    syslog(INFO, "read in %u unique hashes",
           static_cast<uint32_t>(hash_set.size()));
    sort(hash_set.begin(), hash_set.end());
}

/** Converts our application into a proper daemon. */
void daemonize()
{
    const auto pid = fork();
    if (pid < 0)
    {
        syslog(WARN, "couldn't fork!");
        exit(EXIT_FAILURE);
    }
    else if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }

    syslog(INFO, "daemon started");
    umask(0);

    if (setsid() < 0)
    {
        syslog(WARN, "couldn't set sid");
        exit(EXIT_FAILURE);
    }
    // Technically, the root directory is the only one guaranteed
    // to exist on the filesystem.  Therefore, it's the only safe
    // directory to point our daemon at.  I doubt this is strictly
    // necessary, but remembering to completely rebase a daemon is
    // part of just good hacking etiquette.
    if (0 > chdir("/"))
    {
        syslog(WARN, "couldn't chdir to root");
        exit(EXIT_FAILURE);
    }
    // No extraneous filehandles for us.  Daemons lack stdio, so
    // shut 'em on down.
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
}

/** Creates a server socket that will listen for clients. */
auto make_socket()
{
    const auto sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
    if (sock < 0)
    {
        syslog(WARN, "couldn't create a server socket");
        exit(EXIT_FAILURE);
    }

    sockaddr_in server;
    memset(static_cast<void*>(&server), 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(PORT);
    if (0 > bind(sock, reinterpret_cast<sockaddr*>(&server),
                 sizeof(server)))
    {
        syslog(WARN, "couldn't bind to port 9120");
        exit(EXIT_FAILURE);
    }
    if (0 > listen(sock, MAX_PENDING_REQUESTS))
    {
        syslog(WARN, "couldn't listen for clients");
        exit(EXIT_FAILURE);
    }
    syslog(INFO, "ready for clients");
    return sock;
}

/** Checks a string to see if it's a valid base-10 number. */
auto is_num(const string& num)
{
    auto b = num.cbegin();
    auto e = num.cend();

    return (e == find_if(b, e, not1(ptr_fun(::isdigit))))
           ? ::atoi(num.c_str())
           : -1;
}

void show_usage(const char* program_name)
{
    cerr <<
         "Usage: " << program_name << " [-vbhsSo -f FILE -p PORT -t TIMEOUT]\n\n" <<
         "-v : print version information\n" <<
         "-b : get information on reporting bugs\n" <<
         "-f : specify an alternate RDS (default: "<< PKGDATADIR <<
         "/NSRLFile.txt)\n" <<
         "-s : allow clients to query server status (default: disabled)\n" <<
         "-h : show this help message\n" <<
         "-p : listen on PORT, between 1024 and 65535 (default: 9120)\n\n";
    exit(EXIT_FAILURE);
}

void parse_options(int argc, char* argv[])
{
    int32_t opt { 0 };

    while (-1 != (opt = getopt(argc, argv, "bsvof:hp:t:S")))
    {
        switch (opt)
        {
        case 'v':
            cerr << argv[0] << " " << PACKAGE_VERSION << "\n\n";
            exit(0);
            break;
        case 'b':
            cerr << argv[0] << " " << PACKAGE_VERSION
                 << "\n" << PACKAGE_URL << "\n" <<
                 "Praise, blame and bug reports to " << PACKAGE_BUGREPORT << ".\n\n" <<
                 "Please be sure to include your operating system, version of your\n" <<
                 "operating system, and a detailed description of how to recreate\n" <<
                 "your bug.\n\n";
            exit(0);
            break;
        case 'f':
			{
            	RDS_LOC = string((const char*) optarg);
            	ifstream infile { RDS_LOC.c_str() };
            	if (not infile)
            	{
                	cerr <<
                    	 "Error: the specified dataset file could not be found.\n\n";
                	exit(EXIT_FAILURE);
            	}
			}
            break;
        case 'h':
            show_usage(argv[0]);
            exit(0);
            break;
        case 'p':
			{
            	auto port_num = string(optarg);
				stringstream ss;
				ss << port_num;
				ss >> PORT;
				if (! ss)
				{
					show_usage(argv[0]);
					exit(EXIT_FAILURE);
				}
			}
            break;
        case 's':
            status_enabled = true;
            break;
        default:
            show_usage(argv[0]);
            exit(EXIT_FAILURE);
        }
    }
}

}
/** An externally available const reference to the hash set. */
const vector<pair64>& hashes { hash_set };

/** An externally available const reference to the variable storing
  * whether or not status checking should be enabled. */
const bool& enable_status { status_enabled };

/** magic happens here */
int main(int argc, char* argv[])
{
    parse_options(argc, argv);
    daemonize();
    load_hashes();

	int32_t client_sock {0};
    int32_t svr_sock { make_socket() };
	sockaddr_in client;
	socklen_t client_length { sizeof(client) };
    bool in_parent = true;

    signal(SIGCHLD, SIG_IGN);

SERVER_LOOP:
    if (0 > (client_sock = accept(svr_sock,
                                  reinterpret_cast<sockaddr*>(&client),
                                  &client_length)))
    {
        syslog(WARN, "dropped a connection");
        goto SERVER_LOOP;
    }

	string ipaddr { inet_ntoa(client.sin_addr) };
	if (0 == fork()) {
		handle_client(client_sock, ipaddr);
    } else {
        close(client_sock);
        goto SERVER_LOOP;
    }
}
<commit_msg>Some UNIXes require signal.h to be explicitly included<commit_after>/* Copyright (c) 2011-2014, Robert J. Hansen <rjh@secret-alchemy.com>
 * and others.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Code standards:
 *   This is a small enough project we don't need a formal coding standard.
 *   That said, here are some helpful tips for people who want to submit
 *   patches:
 *
 *   - If it's not 100% ISO C++11, it won't get in.
 *   - It must compile cleanly and without warnings under both GNU G++
 *     and Clang++, even with "-W -Wextra -ansi -pedantic".
 *     (Exceptions can be made for warnings that are actually compiler
 *     conformance issues: for instance, Clang++ will warn that 'long long'
 *     is a C++11 extension, even when you run it in -std=C++11 mode.)
 *   - C++ offers 'and', 'or' and 'not' keywords instead of &&, || and !.
 *     I like these: I think they're more readable.  Please use them.
 *   - C++11 uniform initialization syntax, please.
 *   - Please try to follow the formatting conventions.  It's mostly
 *     straight-up astyle format, with occasional tweaks where necessary
 *     to get nice hardcopy printouts.
 *   - If you write a new function it must have a Doxygen block
 *     documenting it.
 *
 * Contributor history:
 *
 * Robert J. Hansen <rjh@secret-alchemy.com>
 *   - most everything
 */

#include "../config.h"
#include <sstream>
#include <sys/stat.h>
#include <syslog.h>
#include <set>
#include <string>
#include <time.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <algorithm>
#include <limits.h>
#include "handler.hpp"
#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <utility>
#include <signal.h>

/* Additional defines necessary on FreeBSD: */
/* Necessary for sockaddr and sockaddr_in structures */
#ifdef __FreeBSD__
#include <sys/socket.h>
#include <netinet/in.h>
#endif

using std::stringstream;
using std::string;
using std::set;
using std::transform;
using std::find_if;
using std::not1;
using std::ptr_fun;
using std::ifstream;
using std::cerr;
using std::vector;
using std::remove_if;
using std::sort;
using std::pair;
using std::unique_ptr;

typedef unsigned long long ULONG64;
typedef pair<ULONG64, ULONG64> pair64;

#define INFO LOG_MAKEPRI(LOG_USER, LOG_INFO)
#define WARN LOG_MAKEPRI(LOG_USER, LOG_WARNING)
#define DEBUG LOG_MAKEPRI(LOG_USER, LOG_DEBUG)
#define CRITICAL LOG_MAKEPRI(LOG_USER, LOG_CRIT)
#define ALERT LOG_MAKEPRI(LOG_USER, LOG_ALERT)
#define EMERGENCY LOG_MAKEPRI(LOG_USER, LOG_EMERG)
#define MAX_PENDING_REQUESTS 20
#define BUFFER_SIZE 128

namespace
{
/** Tracks whether the server should only support protocol 1.0. */
bool old_only { false };

/** Tracks whether the server should support status queries. */
bool status_enabled { false };

/** Tracks whether the server should run as a daemon. */
bool standalone { false };

/** Our set of hashes, represented as a block of contiguous memory.
  * Note that the current NSRL library contains approximately 40
  * million values, each at roughly 32 bytes (rounded to binary
  * powers to make the math easier).  This is 2**25 values times
  * 2**5 bytes each = 2**30 bytes, or about a gig of RAM.
  *
  * Moral of the story: populating this set is computationally
  * expensive. */
vector<pair64> hash_set;

/** Tracks where we look for the location of the
  * reference data set. */
string RDS_LOC { PKGDATADIR "/hashes.txt" };

/** Which port to listen on */
uint16_t PORT { 9120 };

/** Determines whether a string represents a valid uppercase
  * MD5 hash. */

auto good_line(const string& line)
{
    if (line.size() != 32)
        return false;

    auto iter = line.cbegin();
    auto end = line.cend();
    while (iter != end and
            ((*iter >= '0' and *iter <= '9') or
             (*iter >= 'A' and *iter <= 'F')))
        ++iter;
    return (iter == end) ? true : false;
}

/** Loads hashes from disk and stores them in a fast-accessing
  * in-memory data structure.  This will be slow. */
void load_hashes()
{
    vector<char> buf(BUFFER_SIZE, 0);
    uint32_t line_count { 0 }, hash_count { 0 };
    ifstream infile { RDS_LOC.c_str() };

	hash_set.reserve(40000000);

    if (not infile)
    {
        syslog(WARN, "couldn't open hashes file %s",
               RDS_LOC.c_str());
        exit(EXIT_FAILURE);
    }

    while (infile)
    {
        memset(static_cast<void*>(&buf[0]), 0, BUFFER_SIZE);
        infile.getline(&buf[0], BUFFER_SIZE);
        line_count += 1;
        const string line(buf.cbegin(), find(buf.cbegin(), buf.cend(), 0));

        if (0 == line.size())
        {
            continue;
        }

        if (! good_line(line))
        {
            syslog(ALERT, "hash file appears corrupt!  Loading no hashes.");
            syslog(ALERT, "offending line is #%d", line_count);
            syslog(ALERT, "offending line has %d bytes", (int) line.size());
            syslog(ALERT, "Content follows:");
            syslog(ALERT, "%s", line.c_str());
            syslog(ALERT, "shutting down!");
            exit(EXIT_FAILURE);
            return;
        }
        hash_count += 1;

        if (0 == hash_count % 1000000)
        {
            syslog(INFO, "loaded %u million hashes", hash_count / 1000000);
        }

        hash_set.push_back(to_pair64(line));
    }
    infile.close();
    syslog(INFO, "read in %u unique hashes",
           static_cast<uint32_t>(hash_set.size()));
    sort(hash_set.begin(), hash_set.end());
}

/** Converts our application into a proper daemon. */
void daemonize()
{
    const auto pid = fork();
    if (pid < 0)
    {
        syslog(WARN, "couldn't fork!");
        exit(EXIT_FAILURE);
    }
    else if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }

    syslog(INFO, "daemon started");
    umask(0);

    if (setsid() < 0)
    {
        syslog(WARN, "couldn't set sid");
        exit(EXIT_FAILURE);
    }
    // Technically, the root directory is the only one guaranteed
    // to exist on the filesystem.  Therefore, it's the only safe
    // directory to point our daemon at.  I doubt this is strictly
    // necessary, but remembering to completely rebase a daemon is
    // part of just good hacking etiquette.
    if (0 > chdir("/"))
    {
        syslog(WARN, "couldn't chdir to root");
        exit(EXIT_FAILURE);
    }
    // No extraneous filehandles for us.  Daemons lack stdio, so
    // shut 'em on down.
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
}

/** Creates a server socket that will listen for clients. */
auto make_socket()
{
    const auto sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ;
    if (sock < 0)
    {
        syslog(WARN, "couldn't create a server socket");
        exit(EXIT_FAILURE);
    }

    sockaddr_in server;
    memset(static_cast<void*>(&server), 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    server.sin_port = htons(PORT);
    if (0 > bind(sock, reinterpret_cast<sockaddr*>(&server),
                 sizeof(server)))
    {
        syslog(WARN, "couldn't bind to port 9120");
        exit(EXIT_FAILURE);
    }
    if (0 > listen(sock, MAX_PENDING_REQUESTS))
    {
        syslog(WARN, "couldn't listen for clients");
        exit(EXIT_FAILURE);
    }
    syslog(INFO, "ready for clients");
    return sock;
}

/** Checks a string to see if it's a valid base-10 number. */
auto is_num(const string& num)
{
    auto b = num.cbegin();
    auto e = num.cend();

    return (e == find_if(b, e, not1(ptr_fun(::isdigit))))
           ? ::atoi(num.c_str())
           : -1;
}

void show_usage(const char* program_name)
{
    cerr <<
         "Usage: " << program_name << " [-vbhsSo -f FILE -p PORT -t TIMEOUT]\n\n" <<
         "-v : print version information\n" <<
         "-b : get information on reporting bugs\n" <<
         "-f : specify an alternate RDS (default: "<< PKGDATADIR <<
         "/NSRLFile.txt)\n" <<
         "-s : allow clients to query server status (default: disabled)\n" <<
         "-h : show this help message\n" <<
         "-p : listen on PORT, between 1024 and 65535 (default: 9120)\n\n";
    exit(EXIT_FAILURE);
}

void parse_options(int argc, char* argv[])
{
    int32_t opt { 0 };

    while (-1 != (opt = getopt(argc, argv, "bsvof:hp:t:S")))
    {
        switch (opt)
        {
        case 'v':
            cerr << argv[0] << " " << PACKAGE_VERSION << "\n\n";
            exit(0);
            break;
        case 'b':
            cerr << argv[0] << " " << PACKAGE_VERSION
                 << "\n" << PACKAGE_URL << "\n" <<
                 "Praise, blame and bug reports to " << PACKAGE_BUGREPORT << ".\n\n" <<
                 "Please be sure to include your operating system, version of your\n" <<
                 "operating system, and a detailed description of how to recreate\n" <<
                 "your bug.\n\n";
            exit(0);
            break;
        case 'f':
			{
            	RDS_LOC = string((const char*) optarg);
            	ifstream infile { RDS_LOC.c_str() };
            	if (not infile)
            	{
                	cerr <<
                    	 "Error: the specified dataset file could not be found.\n\n";
                	exit(EXIT_FAILURE);
            	}
			}
            break;
        case 'h':
            show_usage(argv[0]);
            exit(0);
            break;
        case 'p':
			{
            	auto port_num = string(optarg);
				stringstream ss;
				ss << port_num;
				ss >> PORT;
				if (! ss)
				{
					show_usage(argv[0]);
					exit(EXIT_FAILURE);
				}
			}
            break;
        case 's':
            status_enabled = true;
            break;
        default:
            show_usage(argv[0]);
            exit(EXIT_FAILURE);
        }
    }
}

}
/** An externally available const reference to the hash set. */
const vector<pair64>& hashes { hash_set };

/** An externally available const reference to the variable storing
  * whether or not status checking should be enabled. */
const bool& enable_status { status_enabled };

/** magic happens here */
int main(int argc, char* argv[])
{
    parse_options(argc, argv);
    daemonize();
    load_hashes();

	int32_t client_sock {0};
    int32_t svr_sock { make_socket() };
	sockaddr_in client;
	socklen_t client_length { sizeof(client) };
    bool in_parent = true;

    signal(SIGCHLD, SIG_IGN);

SERVER_LOOP:
    if (0 > (client_sock = accept(svr_sock,
                                  reinterpret_cast<sockaddr*>(&client),
                                  &client_length)))
    {
        syslog(WARN, "dropped a connection");
        goto SERVER_LOOP;
    }

	string ipaddr { inet_ntoa(client.sin_addr) };
	if (0 == fork()) {
		handle_client(client_sock, ipaddr);
    } else {
        close(client_sock);
        goto SERVER_LOOP;
    }
}
<|endoftext|>


<commit_before>/* -*- C++ -*- */
/*
 * Copyright 2016 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Implements a textual writer of filter s-expressions */

#include "sexp/TextWriter.h"

//#include <cctype>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>

#include "sexp/Ast.h"
#include "stream/WriteUtils.h"
#include "utils/Casting.h"

namespace wasm {

using namespace utils;

namespace filt {

namespace {

constexpr const char* IndentString = "  ";

}  // end of anonyous namespace

bool TextWriter::DefaultShowInternalStructure = false;

TextWriter::TextWriter()
    : File(nullptr),
      IndentCount(0),
      LineEmpty(true),
      ShowInternalStructure(DefaultShowInternalStructure) {
}

TextWriter::Indent::Indent(TextWriter* Writer, bool AddNewline)
    : Writer(Writer), AddNewline(AddNewline) {
  Writer->writeIndent();
}

TextWriter::Indent::~Indent() {
  Writer->maybeWriteNewline(AddNewline);
}

TextWriter::Parenthesize::Parenthesize(TextWriter* Writer,
                                       NodeType Type,
                                       bool AddNewline)
    : Writer(Writer), AddNewline(AddNewline) {
  Writer->writeIndent();
  fputc('(', Writer->File);
  Writer->writeName(Type);
  Writer->LineEmpty = false;
  ++Writer->IndentCount;
}

TextWriter::Parenthesize::~Parenthesize() {
  --Writer->IndentCount;
  Writer->writeIndent();
  fputc(')', Writer->File);
  Writer->LineEmpty = false;
  Writer->maybeWriteNewline(AddNewline);
}

charstring TextWriter::getNodeName(NodeType Type) const {
  return ShowInternalStructure ? getNodeTypeName(Type) : getNodeSexpName(Type);
}

charstring TextWriter::getNodeName(const Node* Nd) const {
  return getNodeName(Nd->getType());
}

void TextWriter::writeName(NodeType Type) {
  fputs(getNodeName(Type), File);
}

void TextWriter::write(FILE* File, SymbolTable* Symtab) {
  write(File, Symtab->getInstalledRoot());
  Symtab = Symtab->getEnclosingScope().get();
  while (Symtab != nullptr) {
    writeIndent();
    fprintf(File, "Enclosing scope:\n");
    write(File, Symtab->getInstalledRoot());
    Symtab = Symtab->getEnclosingScope().get();
  }
}

void TextWriter::write(FILE* File, const Node* Root) {
  initialize(File);
  writeNode(Root, true);
}

void TextWriter::writeAbbrev(FILE* File, const Node* Root) {
  initialize(File);
  writeNodeAbbrev(Root, true);
}

void TextWriter::initialize(FILE* File) {
  this->File = File;
  IndentCount = 0;
  LineEmpty = true;
}

void TextWriter::writeIndent(int Adjustment) {
  if (!LineEmpty)
    return;
  size_t Limit = IndentCount + Adjustment;
  for (size_t i = 0; i < Limit; ++i)
    fputs(IndentString, File);
  LineEmpty = IndentCount == 0;
}

void TextWriter::writeNodeKids(const Node* Nd, bool EmbeddedInParent) {
  // Write out with number of kids specified to be on same line,
  // with remaining kids on separate (indented) lines.
  int Count = 0;
  const AstTraitsType* Traits = getAstTraits(Nd->getType());
  int KidsSameLine = Traits->NumTextArgs;
  int MaxKidsSameLine = KidsSameLine + Traits->AdditionalTextArgs;
  int NumKids = Nd->getNumKids();
  if (NumKids <= MaxKidsSameLine)
    KidsSameLine = MaxKidsSameLine;
  Node* LastKid = Nd->getLastKid();
  bool HasHiddenSeq = Traits->HidesSeqInText;
  bool ForceNewline = false;
  for (auto* Kid : *Nd) {
    if (Kid == LastKid && !ShowInternalStructure) {
      bool IsEmbedded = (HasHiddenSeq && isa<SequenceNode>(LastKid)) ||
                        (isa<CaseNode>(Nd) && isa<CaseNode>(Kid));
      if (IsEmbedded) {
        writeNewline();
        writeNode(Kid, true, true);
        return;
      }
    }
    ++Count;
    if (ForceNewline) {
      writeNode(Kid, true);
      continue;
    }
    if (getAstTraits(Kid->getType())->NeverSameLineInText) {
      if (!(Count == 1 && EmbeddedInParent))
        writeNewline();
      ForceNewline = true;
      writeNode(Kid, true);
      continue;
    }
    if (Count < KidsSameLine) {
      writeSpace();
      writeNode(Kid, false);
      continue;
    }
    if (Count == KidsSameLine) {
      writeSpace();
      ForceNewline = Count < NumKids;
      writeNode(Kid, ForceNewline);
      continue;
    }
    if (Count > KidsSameLine)
      writeNewline();
    ForceNewline = true;
    writeNode(Kid, true);
  }
}

void TextWriter::writeNode(const Node* Nd,
                           bool AddNewline,
                           bool EmbedInParent) {
  if (Nd == nullptr) {
    Indent _(this, AddNewline);
    fprintf(File, "null");
    LineEmpty = false;
    maybeWriteNewline(AddNewline);
    return;
  }
  NodeType Type = Nd->getType();
  if (isa<IntegerNode>(Nd))
    return writeIntegerNode(cast<IntegerNode>(Nd), AddNewline);
  switch (Type) {
    default: {
      if (!(EmbedInParent && !ShowInternalStructure))
        break;
      if (isa<CaseNode>(Nd)) {
        writeIndent(-1);
        writeSpace();
        writeName(OpCase);
      }
      writeNodeKids(Nd, true);
      return;
    }
    case OpFile: {
      if (ShowInternalStructure)
        break;
      // Treat like hidden node. That is, visually just a list of
      // s-expressions.
      for (auto* Kid : *Nd)
        writeNode(Kid, true);
      return;
    }
    case OpLiteralUse:
    case OpLiteralActionUse:
      if (ShowInternalStructure)
        break;
      writeNode(Nd->getKid(0), AddNewline, EmbedInParent);
      return;
    case OpSection:
      if (ShowInternalStructure)
        break;
      { Parenthesize _(this, Type, true); }
      for (auto* Kid : *Nd)
        writeNode(Kid, true, false);
      return;
    case OpSymbolDefn: {
      Parenthesize _(this, Type, AddNewline);
      writeSpace();
      writeNode(cast<SymbolDefnNode>(Nd)->getSymbol(), false);
      return;
    }
    case OpSymbol: {
      return writeSymbolNode(cast<SymbolNode>(Nd), AddNewline);
    }
  }
  // Default case.
  Parenthesize _(this, Type, AddNewline);
  writeNodeKids(Nd, false);
}

void TextWriter::writeNodeKidsAbbrev(const Node* Nd, bool EmbeddedInParent) {
  // Write out with number of kids specified to be on same line,
  // with remaining kids on separate (indented) lines.

  const AstTraitsType* Traits = getAstTraits(Nd->getType());
  int KidsSameLine = Traits->NumTextArgs;
  int MaxKidsSameLine = KidsSameLine + Traits->AdditionalTextArgs;
  int NumKids = Nd->getNumKids();
  if (NumKids <= MaxKidsSameLine)
    KidsSameLine = MaxKidsSameLine;
  bool HasHiddenSeq = Traits->HidesSeqInText;
  for (int i = 0; i < NumKids; ++i) {
    Node* Kid = Nd->getKid(i);
    bool LastKid = i + 1 == NumKids;
    if (HasHiddenSeq && LastKid && isa<SequenceNode>(Kid)) {
      fprintf(File, " ...[%d]", Kid->getNumKids());
      return;
    }
    if (getAstTraits(Kid->getType())->NeverSameLineInText) {
      fprintf(File, " ...[%d]", NumKids - i);
      return;
    }
    int Count = i + 1;
    if (Count < KidsSameLine) {
      writeSpace();
      writeNodeAbbrev(Kid, false);
      continue;
    }
    if (Count == KidsSameLine) {
      writeSpace();
      writeNodeAbbrev(Kid, false);
      if (!LastKid)
        fprintf(File, " ...[%d]", NumKids - Count);
      return;
    }
    if (Count == 1 && EmbeddedInParent) {
      fprintf(File, " ...[%d]", NumKids);
      return;
    }
    writeSpace();
    writeNodeAbbrev(Kid, false);
    if (!LastKid)
      fprintf(File, " ...[%d]", NumKids - Count);
    return;
  }
}

void TextWriter::writeNodeAbbrev(const Node* Nd,
                                 bool AddNewline,
                                 bool EmbedInParent) {
  if (Nd == nullptr) {
    fprintf(File, "null");
    LineEmpty = false;
    maybeWriteNewline(AddNewline);
    return;
  }
  if (isa<IntegerNode>(Nd))
    return writeIntegerNode(cast<IntegerNode>(Nd), AddNewline);
  NodeType Type = Nd->getType();
  switch (Type) {
    default: {
      if (!EmbedInParent)
        break;
      fprintf(File, " ...");
      return;
    }
    case OpSection:
    case OpFile: {
      // Treat like hidden node. That is, visually just a list of s-expressions.
      fprintf(File, "(%s ...)\n", getNodeName(Nd));
      return;
    }
    case OpSymbol:
      return writeSymbolNode(cast<SymbolNode>(Nd), AddNewline);
    case OpSymbolDefn:
      writeNode(Nd, AddNewline, EmbedInParent);
      return;
    case OpLiteralUse:
    case OpLiteralActionUse:
      if (ShowInternalStructure)
        break;
      writeNodeAbbrev(Nd->getKid(0), AddNewline, EmbedInParent);
      return;
  }
  Parenthesize _(this, Type, AddNewline);
  writeNodeKidsAbbrev(Nd, false);
}

void TextWriter::writeSymbolName(std::string Name) {
  fputc('\'', File);
  for (char V : Name) {
    switch (V) {
      case '\\':
        fputc('\\', File);
        fputc('\\', File);
        continue;
      case '\f':
        fputc('\\', File);
        fputc('f', File);
        continue;
      case '\n':
        fputc('\\', File);
        fputc('n', File);
        continue;
      case '\r':
        fputc('\\', File);
        fputc('r', File);
        continue;
      case '\t':
        fputc('\\', File);
        fputc('t', File);
        continue;
      case '\v':
        fputc('\\', File);
        fputc('v', File);
        continue;
    }
    if (isprint(V)) {
      fputc(V, File);
      continue;
    }
    fputc('\\', File);
    uint8_t BitsPerOctal = 3;
    uint8_t Shift = 2 * BitsPerOctal;
    for (int Count = 3; Count > 0; --Count) {
      uint8_t Digit = V >> Shift;
      fputc('0' + Digit, File);
      V &= ((1 << Shift) - 1);
      Shift -= BitsPerOctal;
    }
  }
  fputc('\'', File);
}

void TextWriter::writeSymbolNode(const SymbolNode* Sym, bool AddNewline) {
  if (ShowInternalStructure) {
    Parenthesize _(this, Sym->getType(), AddNewline);
    writeSpace();
    writeSymbolName(Sym->getName());
  } else {
    Indent _(this, AddNewline);
    writeSymbolName(Sym->getName());
    LineEmpty = false;
  }
  return;
}

void TextWriter::writeIntegerNode(const IntegerNode* Int, bool AddNewline) {
  Parenthesize _(this, Int->getType(), AddNewline);
  if (!Int->isDefaultValue()) {
    fputc(' ', File);
    writeInt(File, Int->getValue(), Int->getFormat());
    if (const auto* Accept = dyn_cast<BinaryAcceptNode>(Int)) {
      fputc(':', File);
      fprintf(File, "%u", Accept->getNumBits());
    }
  }
  LineEmpty = false;
  return;
}

void TextWriter::writeNewline() {
  if (!LineEmpty)
    fputc('\n', File);
  LineEmpty = true;
}

void TextWriter::maybeWriteNewline(bool Yes) {
  if (Yes)
    writeNewline();
}

void TextWriter::writeSpace() {
  fputc(' ', File);
  LineEmpty = false;
}

}  // end of namespace filt

}  // end of namespace wasm
<commit_msg>Change whitespace to test if Travis is working. (#556)<commit_after>/* -*- C++ -*- */
/*
 * Copyright 2016 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* Implements a textual writer of filter s-expressions */

#include "sexp/TextWriter.h"

//#include <cctype>
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>

#include "sexp/Ast.h"
#include "stream/WriteUtils.h"
#include "utils/Casting.h"

namespace wasm {

using namespace utils;

namespace filt {

namespace {
constexpr const char* IndentString = "  ";
}  // end of anonyous namespace

bool TextWriter::DefaultShowInternalStructure = false;

TextWriter::TextWriter()
    : File(nullptr),
      IndentCount(0),
      LineEmpty(true),
      ShowInternalStructure(DefaultShowInternalStructure) {
}

TextWriter::Indent::Indent(TextWriter* Writer, bool AddNewline)
    : Writer(Writer), AddNewline(AddNewline) {
  Writer->writeIndent();
}

TextWriter::Indent::~Indent() {
  Writer->maybeWriteNewline(AddNewline);
}

TextWriter::Parenthesize::Parenthesize(TextWriter* Writer,
                                       NodeType Type,
                                       bool AddNewline)
    : Writer(Writer), AddNewline(AddNewline) {
  Writer->writeIndent();
  fputc('(', Writer->File);
  Writer->writeName(Type);
  Writer->LineEmpty = false;
  ++Writer->IndentCount;
}

TextWriter::Parenthesize::~Parenthesize() {
  --Writer->IndentCount;
  Writer->writeIndent();
  fputc(')', Writer->File);
  Writer->LineEmpty = false;
  Writer->maybeWriteNewline(AddNewline);
}

charstring TextWriter::getNodeName(NodeType Type) const {
  return ShowInternalStructure ? getNodeTypeName(Type) : getNodeSexpName(Type);
}

charstring TextWriter::getNodeName(const Node* Nd) const {
  return getNodeName(Nd->getType());
}

void TextWriter::writeName(NodeType Type) {
  fputs(getNodeName(Type), File);
}

void TextWriter::write(FILE* File, SymbolTable* Symtab) {
  write(File, Symtab->getInstalledRoot());
  Symtab = Symtab->getEnclosingScope().get();
  while (Symtab != nullptr) {
    writeIndent();
    fprintf(File, "Enclosing scope:\n");
    write(File, Symtab->getInstalledRoot());
    Symtab = Symtab->getEnclosingScope().get();
  }
}

void TextWriter::write(FILE* File, const Node* Root) {
  initialize(File);
  writeNode(Root, true);
}

void TextWriter::writeAbbrev(FILE* File, const Node* Root) {
  initialize(File);
  writeNodeAbbrev(Root, true);
}

void TextWriter::initialize(FILE* File) {
  this->File = File;
  IndentCount = 0;
  LineEmpty = true;
}

void TextWriter::writeIndent(int Adjustment) {
  if (!LineEmpty)
    return;
  size_t Limit = IndentCount + Adjustment;
  for (size_t i = 0; i < Limit; ++i)
    fputs(IndentString, File);
  LineEmpty = IndentCount == 0;
}

void TextWriter::writeNodeKids(const Node* Nd, bool EmbeddedInParent) {
  // Write out with number of kids specified to be on same line,
  // with remaining kids on separate (indented) lines.
  int Count = 0;
  const AstTraitsType* Traits = getAstTraits(Nd->getType());
  int KidsSameLine = Traits->NumTextArgs;
  int MaxKidsSameLine = KidsSameLine + Traits->AdditionalTextArgs;
  int NumKids = Nd->getNumKids();
  if (NumKids <= MaxKidsSameLine)
    KidsSameLine = MaxKidsSameLine;
  Node* LastKid = Nd->getLastKid();
  bool HasHiddenSeq = Traits->HidesSeqInText;
  bool ForceNewline = false;
  for (auto* Kid : *Nd) {
    if (Kid == LastKid && !ShowInternalStructure) {
      bool IsEmbedded = (HasHiddenSeq && isa<SequenceNode>(LastKid)) ||
                        (isa<CaseNode>(Nd) && isa<CaseNode>(Kid));
      if (IsEmbedded) {
        writeNewline();
        writeNode(Kid, true, true);
        return;
      }
    }
    ++Count;
    if (ForceNewline) {
      writeNode(Kid, true);
      continue;
    }
    if (getAstTraits(Kid->getType())->NeverSameLineInText) {
      if (!(Count == 1 && EmbeddedInParent))
        writeNewline();
      ForceNewline = true;
      writeNode(Kid, true);
      continue;
    }
    if (Count < KidsSameLine) {
      writeSpace();
      writeNode(Kid, false);
      continue;
    }
    if (Count == KidsSameLine) {
      writeSpace();
      ForceNewline = Count < NumKids;
      writeNode(Kid, ForceNewline);
      continue;
    }
    if (Count > KidsSameLine)
      writeNewline();
    ForceNewline = true;
    writeNode(Kid, true);
  }
}

void TextWriter::writeNode(const Node* Nd,
                           bool AddNewline,
                           bool EmbedInParent) {
  if (Nd == nullptr) {
    Indent _(this, AddNewline);
    fprintf(File, "null");
    LineEmpty = false;
    maybeWriteNewline(AddNewline);
    return;
  }
  NodeType Type = Nd->getType();
  if (isa<IntegerNode>(Nd))
    return writeIntegerNode(cast<IntegerNode>(Nd), AddNewline);
  switch (Type) {
    default: {
      if (!(EmbedInParent && !ShowInternalStructure))
        break;
      if (isa<CaseNode>(Nd)) {
        writeIndent(-1);
        writeSpace();
        writeName(OpCase);
      }
      writeNodeKids(Nd, true);
      return;
    }
    case OpFile: {
      if (ShowInternalStructure)
        break;
      // Treat like hidden node. That is, visually just a list of
      // s-expressions.
      for (auto* Kid : *Nd)
        writeNode(Kid, true);
      return;
    }
    case OpLiteralUse:
    case OpLiteralActionUse:
      if (ShowInternalStructure)
        break;
      writeNode(Nd->getKid(0), AddNewline, EmbedInParent);
      return;
    case OpSection:
      if (ShowInternalStructure)
        break;
      { Parenthesize _(this, Type, true); }
      for (auto* Kid : *Nd)
        writeNode(Kid, true, false);
      return;
    case OpSymbolDefn: {
      Parenthesize _(this, Type, AddNewline);
      writeSpace();
      writeNode(cast<SymbolDefnNode>(Nd)->getSymbol(), false);
      return;
    }
    case OpSymbol: {
      return writeSymbolNode(cast<SymbolNode>(Nd), AddNewline);
    }
  }
  // Default case.
  Parenthesize _(this, Type, AddNewline);
  writeNodeKids(Nd, false);
}

void TextWriter::writeNodeKidsAbbrev(const Node* Nd, bool EmbeddedInParent) {
  // Write out with number of kids specified to be on same line,
  // with remaining kids on separate (indented) lines.

  const AstTraitsType* Traits = getAstTraits(Nd->getType());
  int KidsSameLine = Traits->NumTextArgs;
  int MaxKidsSameLine = KidsSameLine + Traits->AdditionalTextArgs;
  int NumKids = Nd->getNumKids();
  if (NumKids <= MaxKidsSameLine)
    KidsSameLine = MaxKidsSameLine;
  bool HasHiddenSeq = Traits->HidesSeqInText;
  for (int i = 0; i < NumKids; ++i) {
    Node* Kid = Nd->getKid(i);
    bool LastKid = i + 1 == NumKids;
    if (HasHiddenSeq && LastKid && isa<SequenceNode>(Kid)) {
      fprintf(File, " ...[%d]", Kid->getNumKids());
      return;
    }
    if (getAstTraits(Kid->getType())->NeverSameLineInText) {
      fprintf(File, " ...[%d]", NumKids - i);
      return;
    }
    int Count = i + 1;
    if (Count < KidsSameLine) {
      writeSpace();
      writeNodeAbbrev(Kid, false);
      continue;
    }
    if (Count == KidsSameLine) {
      writeSpace();
      writeNodeAbbrev(Kid, false);
      if (!LastKid)
        fprintf(File, " ...[%d]", NumKids - Count);
      return;
    }
    if (Count == 1 && EmbeddedInParent) {
      fprintf(File, " ...[%d]", NumKids);
      return;
    }
    writeSpace();
    writeNodeAbbrev(Kid, false);
    if (!LastKid)
      fprintf(File, " ...[%d]", NumKids - Count);
    return;
  }
}

void TextWriter::writeNodeAbbrev(const Node* Nd,
                                 bool AddNewline,
                                 bool EmbedInParent) {
  if (Nd == nullptr) {
    fprintf(File, "null");
    LineEmpty = false;
    maybeWriteNewline(AddNewline);
    return;
  }
  if (isa<IntegerNode>(Nd))
    return writeIntegerNode(cast<IntegerNode>(Nd), AddNewline);
  NodeType Type = Nd->getType();
  switch (Type) {
    default: {
      if (!EmbedInParent)
        break;
      fprintf(File, " ...");
      return;
    }
    case OpSection:
    case OpFile: {
      // Treat like hidden node. That is, visually just a list of s-expressions.
      fprintf(File, "(%s ...)\n", getNodeName(Nd));
      return;
    }
    case OpSymbol:
      return writeSymbolNode(cast<SymbolNode>(Nd), AddNewline);
    case OpSymbolDefn:
      writeNode(Nd, AddNewline, EmbedInParent);
      return;
    case OpLiteralUse:
    case OpLiteralActionUse:
      if (ShowInternalStructure)
        break;
      writeNodeAbbrev(Nd->getKid(0), AddNewline, EmbedInParent);
      return;
  }
  Parenthesize _(this, Type, AddNewline);
  writeNodeKidsAbbrev(Nd, false);
}

void TextWriter::writeSymbolName(std::string Name) {
  fputc('\'', File);
  for (char V : Name) {
    switch (V) {
      case '\\':
        fputc('\\', File);
        fputc('\\', File);
        continue;
      case '\f':
        fputc('\\', File);
        fputc('f', File);
        continue;
      case '\n':
        fputc('\\', File);
        fputc('n', File);
        continue;
      case '\r':
        fputc('\\', File);
        fputc('r', File);
        continue;
      case '\t':
        fputc('\\', File);
        fputc('t', File);
        continue;
      case '\v':
        fputc('\\', File);
        fputc('v', File);
        continue;
    }
    if (isprint(V)) {
      fputc(V, File);
      continue;
    }
    fputc('\\', File);
    uint8_t BitsPerOctal = 3;
    uint8_t Shift = 2 * BitsPerOctal;
    for (int Count = 3; Count > 0; --Count) {
      uint8_t Digit = V >> Shift;
      fputc('0' + Digit, File);
      V &= ((1 << Shift) - 1);
      Shift -= BitsPerOctal;
    }
  }
  fputc('\'', File);
}

void TextWriter::writeSymbolNode(const SymbolNode* Sym, bool AddNewline) {
  if (ShowInternalStructure) {
    Parenthesize _(this, Sym->getType(), AddNewline);
    writeSpace();
    writeSymbolName(Sym->getName());
  } else {
    Indent _(this, AddNewline);
    writeSymbolName(Sym->getName());
    LineEmpty = false;
  }
  return;
}

void TextWriter::writeIntegerNode(const IntegerNode* Int, bool AddNewline) {
  Parenthesize _(this, Int->getType(), AddNewline);
  if (!Int->isDefaultValue()) {
    fputc(' ', File);
    writeInt(File, Int->getValue(), Int->getFormat());
    if (const auto* Accept = dyn_cast<BinaryAcceptNode>(Int)) {
      fputc(':', File);
      fprintf(File, "%u", Accept->getNumBits());
    }
  }
  LineEmpty = false;
  return;
}

void TextWriter::writeNewline() {
  if (!LineEmpty)
    fputc('\n', File);
  LineEmpty = true;
}

void TextWriter::maybeWriteNewline(bool Yes) {
  if (Yes)
    writeNewline();
}

void TextWriter::writeSpace() {
  fputc(' ', File);
  LineEmpty = false;
}

}  // end of namespace filt

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