<commit_before>#pragma once

#include <stdint.h>
#include <type_traits>

namespace faze
{
  // lets just use 64bits for this
  // we can reduce the size later if needed
  struct ResourceHandle
  {
    union
    {
      struct
      {
        uint64_t id : 20; // million is too much for id's
        uint64_t generation : 8; // generous generation id
        uint64_t type : 6; // ... I don't really want to write this much api types
        uint64_t gpuid : 16; // this should just be a bitfield, one bit for gpu, starting with modest 16 gpu's =D
        uint64_t unused : 14; // honestly could be more bits here, lets just see how things go on
      };
      uint64_t rawValue;
    };
    ResourceHandle(uint64_t id, uint64_t generation, uint64_t type, uint64_t gpuID)
      : id(id)
      , generation(generation)
      , type(type)
      , gpuid(gpuID)
    {
      static_assert(std::is_standard_layout<ResourceHandle>::value,  "ResourceHandle should be trivial to destroy.");
    }

    // returns positive value when single gpu
    // -1 when every gpu owns its own
    // -2 is mysterious error situation.
    int ownerGpuId() const
    {
      uint64_t c_gpuid = gpuid;
      uint64_t count = 0;
      if (c_gpuid == 65535)
      {
        return -1;
      }
      while(count < 16) // valid id's 0-15
      {
        if (c_gpuid & (1 << count))
        {
          return int(count);
        }
      }
      return -2;
    }

    // shared resource means it's a handle that can be opened on another api/gpu device
    // otherwise all gpu's have their own version of this resource.
    bool sharedResource() const
    {
      return ownerGpuId() >= 0; // false for now
    }
  };

  /*
  Problem is how we allocate these and ...
  There probably should be a manager that we can use for checks

  Ideally we want to check generation on each access of resource.
  So we could have something that gives out id's and offers functions to check if those id's are expired.
  So we would need
    - Allocate Handle
      - get id from pool
        - if no id in pool, make a new one
    - Delete Handle
      - mostly just, return to pool as usable
    - check if alive
      - array to check current status of the id and match generation for id check
  */
}<commit_msg>handle updates<commit_after>#pragma once

#include <core/datastructures/proxy.hpp>
#include <core/global_debug.hpp>

#include <stdint.h>
#include <type_traits>

namespace faze
{
  // lets just use 64bits for this
  // we can reduce the size later if needed
  struct ResourceHandle
  {
    static const uint64_t InvalidId = (1ull << 20ull) - 1;
    union
    {
      struct
      {
        uint64_t id : 20; // million is too much for id's
        uint64_t generation : 8; // generous generation id
        uint64_t type : 6; // ... I don't really want to write this much api types
        uint64_t gpuid : 16; // this should just be a bitfield, one bit for gpu, starting with modest 16 gpu's =D
        uint64_t unused : 14; // honestly could be more bits here, lets just see how things go on
      };
      uint64_t rawValue;
    };
    ResourceHandle(uint64_t id, uint64_t generation, uint64_t type, uint64_t gpuID)
      : id(id)
      , generation(generation)
      , type(type)
      , gpuid(gpuID)
    {
      static_assert(std::is_standard_layout<ResourceHandle>::value,  "ResourceHandle should be trivial to destroy.");
    }

    // returns positive value when single gpu
    // -1 when every gpu owns its own
    // -2 is mysterious error situation.
    int ownerGpuId() const
    {
      uint64_t c_gpuid = gpuid;
      uint64_t count = 0;
      if (c_gpuid == 65535)
      {
        return -1;
      }
      while(count < 16) // valid id's 0-15
      {
        if (c_gpuid & (1 << count))
        {
          return int(count);
        }
      }
      return -2;
    }

    // shared resource means it's a handle that can be opened on another api/gpu device
    // otherwise all gpu's have their own version of this resource.
    bool sharedResource() const
    {
      return ownerGpuId() >= 0; // false for now
    }
  };

  /*
  Problem is how we allocate these and ...
  There probably should be a manager that we can use for checks

  Ideally we want to check generation on each access of resource.
  So we could have something that gives out id's and offers functions to check if those id's are expired.
  So we would need
    - Allocate Handle
      - get id from pool
        - if no id in pool, make a new one
    - Delete Handle
      - mostly just, return to pool as usable
    - check if alive
      - array to check current status of the id and match generation for id check
  */

  // we need legopiece to generate id's which knows how to reuse them
  // we need "type" amount of these lego pieces, all ranges begin from 0 till something

  class HandlePool
  {
    vector<uint32_t> m_freelist;
    vector<uint8_t> m_generation;
    uint64_t m_type = 0;
    int m_size = 0;
  public:
    HandlePool(uint64_t type, int size)
      : m_type(type)
      , m_size(size)
    {
      for (int i = size; i >= 0; i--)
      {
        m_freelist.push_back(i);
      }
      m_generation.resize(m_size);
      for (int i = 0; i < m_size; ++i)
      {
        m_generation[i] = 0;
      }
    }

    ResourceHandle allocate()
    {
      if (m_freelist.empty())
      {
        F_ASSERT(false, "No handles left, what.");
        return ResourceHandle{ResourceHandle::InvalidId, 0, m_type, 0};
      }
      auto id = m_freelist.back();
      m_freelist.pop_back();
      auto generation = m_generation[id]; // take current generation
      return ResourceHandle{id, generation, m_type, 0};
    }

    void release(ResourceHandle val)
    {
      F_ASSERT(val.id != ResourceHandle::InvalidId
                && val.id < m_size
                && val.generation == m_generation[val.id]
                , "Invalid handle was released.");
      m_freelist.push_back(val.id);
      m_generation[val.id]++; // offset the generation to detect double free's
    }

    bool valid(ResourceHandle handle)
    {
      F_ASSERT(handle.id != ResourceHandle::InvalidId
                && handle.id < m_size
                , "Invalid handle was passed.");
      return handle.generation == m_generation[handle.id];
    }

    size_t size() const
    {
      return m_freelist.size();
    }
  };

}<|endoftext|>


<commit_before>#include <stdint.h>

#ifndef __clockid_t_defined
#define __clockid_t_defined 1

typedef int32_t clockid_t;

#define CLOCK_REALTIME               0
#define CLOCK_MONOTONIC              1
#define CLOCK_PROCESS_CPUTIME_ID     2
#define CLOCK_THREAD_CPUTIME_ID      3
#define CLOCK_MONOTONIC_RAW          4
#define CLOCK_REALTIME_COARSE        5
#define CLOCK_MONOTONIC_COARSE       6
#define CLOCK_BOOTTIME               7
#define CLOCK_REALTIME_ALARM         8
#define CLOCK_BOOTTIME_ALARM         9

#endif  // __clockid_t_defined

#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC

struct timespec {
    long tv_sec;            /* Seconds.  */
    long tv_nsec;           /* Nanoseconds.  */
};

#endif  // _STRUCT_TIMESPEC

extern "C" {

extern int clock_gettime(clockid_t clk_id, struct timespec *tp);

WEAK bool halide_reference_clock_inited = false;
WEAK timespec halide_reference_clock;

WEAK int halide_start_clock() {
    // Guard against multiple calls
    if (!halide_reference_clock_inited) {
      clock_gettime(CLOCK_REALTIME, &halide_reference_clock);
      halide_reference_clock_inited = true;
    }
    return 0;
}

WEAK int64_t halide_current_time_ns() {
    timespec now;
    clock_gettime(CLOCK_REALTIME, &now);
    int64_t d = int64_t(now.tv_sec - halide_reference_clock.tv_sec)*1000000000;
    int64_t nd = (now.tv_nsec - halide_reference_clock.tv_nsec);
    return d + nd;
}

}
<commit_msg>Made linux_clock do the syscall directly to dodge linking woes.<commit_after>#include <stdint.h>

#ifndef __clockid_t_defined
#define __clockid_t_defined 1

typedef int32_t clockid_t;

#define CLOCK_REALTIME               0
#define CLOCK_MONOTONIC              1
#define CLOCK_PROCESS_CPUTIME_ID     2
#define CLOCK_THREAD_CPUTIME_ID      3
#define CLOCK_MONOTONIC_RAW          4
#define CLOCK_REALTIME_COARSE        5
#define CLOCK_MONOTONIC_COARSE       6
#define CLOCK_BOOTTIME               7
#define CLOCK_REALTIME_ALARM         8
#define CLOCK_BOOTTIME_ALARM         9

#endif  // __clockid_t_defined

#ifndef _STRUCT_TIMESPEC
#define _STRUCT_TIMESPEC

struct timespec {
    long tv_sec;            /* Seconds.  */
    long tv_nsec;           /* Nanoseconds.  */
};

#endif  // _STRUCT_TIMESPEC

// Should be safe to include these, given that we know we're on linux
// if we're compiling this file.
#include <sys/syscall.h>
#include <unistd.h>

extern "C" {

WEAK bool halide_reference_clock_inited = false;
WEAK timespec halide_reference_clock;

WEAK int halide_start_clock() {
    // Guard against multiple calls
    if (!halide_reference_clock_inited) {
        syscall(SYS_clock_gettime, CLOCK_REALTIME, &halide_reference_clock);
        halide_reference_clock_inited = true;
    }
    return 0;
}

WEAK int64_t halide_current_time_ns() {
    timespec now;
    // To avoid requiring people to link -lrt, we just make the syscall directly.
    syscall(SYS_clock_gettime, CLOCK_REALTIME, &now);
    int64_t d = int64_t(now.tv_sec - halide_reference_clock.tv_sec)*1000000000;
    int64_t nd = (now.tv_nsec - halide_reference_clock.tv_nsec);
    return d + nd;
}

}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "internal/iso8601_converter.hxx"
#include "internal/utilities.hxx"

#include <sstream>
#include <iomanip>

//-----------------------------------
/* Converts ISO 8601 conform date/time
   represenation to the representation
   conforming to the current locale
*/
std::wstring iso8601_date_to_local_date(const std::wstring& isoDate )
{
    const std::wstring CONST_SPACE(L" ");
    ::std::wstring ws8601DateTime(isoDate);

    if ( ws8601DateTime.length() == 19 )
    {
        std::string asDateTime = WStringToString( ws8601DateTime );
        SYSTEMTIME DateTime;
        DateTime.wYear         = ( unsigned short )strtol( asDateTime.substr( 0, 4 ).c_str(), NULL, 10 );
        DateTime.wMonth        = ( unsigned short )strtol( asDateTime.substr( 5, 2 ).c_str(), NULL, 10 );
        DateTime.wDayOfWeek    =  0;
        DateTime.wDay          = ( unsigned short )strtol( asDateTime.substr( 8, 2 ).c_str(), NULL, 10 );
        DateTime.wHour         = ( unsigned short )strtol( asDateTime.substr( 11,2 ).c_str(), NULL, 10 );
        DateTime.wMinute       = ( unsigned short )strtol( asDateTime.substr( 14,2 ).c_str(), NULL, 10 );
        DateTime.wSecond       = ( unsigned short )strtol( asDateTime.substr( 17,2 ).c_str(), NULL, 10 );
        DateTime.wMilliseconds =  0;

        //get Date info from structure
        WCHAR DateBuffer[ MAX_PATH ];
        int DateSize = GetDateFormatW(
            LOCALE_SYSTEM_DEFAULT,
            0,
            &DateTime,
            NULL,
            DateBuffer,
            MAX_PATH );

        if ( DateSize )
            ws8601DateTime.assign(DateBuffer);
        else
            ws8601DateTime = StringToWString( asDateTime );

        //get Time info from structure
        WCHAR TimeBuffer[ MAX_PATH ];

        int TimeSize =  GetTimeFormatW(
            LOCALE_SYSTEM_DEFAULT,
            0,
            &DateTime,
            NULL,
            TimeBuffer,
            MAX_PATH );

        if ( TimeSize )
        {
            ws8601DateTime.append(L" ");
            ws8601DateTime.append(TimeBuffer);
        }
        else
            ws8601DateTime = StringToWString( asDateTime );
    }

    return ws8601DateTime;
}

//------------------------------------
/* Converts ISO 8601 conform duration
   representation to the representation
   conforming to the current locale

   Expect format PTnHnMnS according to
   ISO 8601 where n is abitrary number
   of digits
*/

std::wstring iso8601_duration_to_local_duration(const std::wstring& iso8601duration)
{
    std::wstring days;
    std::wstring hours;
    std::wstring minutes;
    std::wstring seconds;

    std::wstring::const_iterator iter     = iso8601duration.begin();
    std::wstring::const_iterator iter_end = iso8601duration.end();

    std::wstring num;

    for (/**/; iter != iter_end; ++iter)
    {
        if (isdigit(*iter))
        {
            num += *iter;
        }
        else
        {
            if (*iter == L'D' || *iter == L'd')
                days = num;
            else if (*iter == L'H' || *iter == L'h')
                hours = num;
            else if (*iter == L'M' || *iter == L'm')
                minutes = num;
            else if (*iter == L'S' || *iter == L's')
                seconds = num;

            num.clear();
        }
    }

    if (days.length() > 0)
    {
        int h = ((_wtoi(days.c_str()) * 24) + _wtoi(hours.c_str()));
        wchar_t buff[10];
        _itow(h, buff, 10);
        hours = buff;
    }

#if defined(_MSC_VER) //&& defined(_M_X64)
    std::wostringstream oss;
    oss << std::setw(2) << std::setfill(wchar_t('0')) << hours   << L":" <<
           std::setw(2) << std::setfill(wchar_t('0')) << minutes << L":" <<
           std::setw(2) << std::setfill(wchar_t('0')) << seconds;
    return oss.str();
#elif defined( __MINGW32__ )
#define ADD_AS_PREFILLED( st, out ) \
    if ( st.length() == 0 ) \
        out += L"00"; \
    else if ( st.length() == 1 ) \
        out += L"0"; \
    out += st;

    std::wstring result;
    ADD_AS_PREFILLED( hours, result )
    result += L":";
    ADD_AS_PREFILLED( minutes, result )
    result += L":";
    ADD_AS_PREFILLED( seconds, result )

    return result;
#undef ADD_AS_PREFILLED
#endif
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Missing include<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "sal/config.h"

#include <stdlib.h>

#include "internal/iso8601_converter.hxx"
#include "internal/utilities.hxx"

#include <sstream>
#include <iomanip>

//-----------------------------------
/* Converts ISO 8601 conform date/time
   represenation to the representation
   conforming to the current locale
*/
std::wstring iso8601_date_to_local_date(const std::wstring& isoDate )
{
    const std::wstring CONST_SPACE(L" ");
    ::std::wstring ws8601DateTime(isoDate);

    if ( ws8601DateTime.length() == 19 )
    {
        std::string asDateTime = WStringToString( ws8601DateTime );
        SYSTEMTIME DateTime;
        DateTime.wYear         = ( unsigned short )strtol( asDateTime.substr( 0, 4 ).c_str(), NULL, 10 );
        DateTime.wMonth        = ( unsigned short )strtol( asDateTime.substr( 5, 2 ).c_str(), NULL, 10 );
        DateTime.wDayOfWeek    =  0;
        DateTime.wDay          = ( unsigned short )strtol( asDateTime.substr( 8, 2 ).c_str(), NULL, 10 );
        DateTime.wHour         = ( unsigned short )strtol( asDateTime.substr( 11,2 ).c_str(), NULL, 10 );
        DateTime.wMinute       = ( unsigned short )strtol( asDateTime.substr( 14,2 ).c_str(), NULL, 10 );
        DateTime.wSecond       = ( unsigned short )strtol( asDateTime.substr( 17,2 ).c_str(), NULL, 10 );
        DateTime.wMilliseconds =  0;

        //get Date info from structure
        WCHAR DateBuffer[ MAX_PATH ];
        int DateSize = GetDateFormatW(
            LOCALE_SYSTEM_DEFAULT,
            0,
            &DateTime,
            NULL,
            DateBuffer,
            MAX_PATH );

        if ( DateSize )
            ws8601DateTime.assign(DateBuffer);
        else
            ws8601DateTime = StringToWString( asDateTime );

        //get Time info from structure
        WCHAR TimeBuffer[ MAX_PATH ];

        int TimeSize =  GetTimeFormatW(
            LOCALE_SYSTEM_DEFAULT,
            0,
            &DateTime,
            NULL,
            TimeBuffer,
            MAX_PATH );

        if ( TimeSize )
        {
            ws8601DateTime.append(L" ");
            ws8601DateTime.append(TimeBuffer);
        }
        else
            ws8601DateTime = StringToWString( asDateTime );
    }

    return ws8601DateTime;
}

//------------------------------------
/* Converts ISO 8601 conform duration
   representation to the representation
   conforming to the current locale

   Expect format PTnHnMnS according to
   ISO 8601 where n is abitrary number
   of digits
*/

std::wstring iso8601_duration_to_local_duration(const std::wstring& iso8601duration)
{
    std::wstring days;
    std::wstring hours;
    std::wstring minutes;
    std::wstring seconds;

    std::wstring::const_iterator iter     = iso8601duration.begin();
    std::wstring::const_iterator iter_end = iso8601duration.end();

    std::wstring num;

    for (/**/; iter != iter_end; ++iter)
    {
        if (isdigit(*iter))
        {
            num += *iter;
        }
        else
        {
            if (*iter == L'D' || *iter == L'd')
                days = num;
            else if (*iter == L'H' || *iter == L'h')
                hours = num;
            else if (*iter == L'M' || *iter == L'm')
                minutes = num;
            else if (*iter == L'S' || *iter == L's')
                seconds = num;

            num.clear();
        }
    }

    if (days.length() > 0)
    {
        int h = ((_wtoi(days.c_str()) * 24) + _wtoi(hours.c_str()));
        wchar_t buff[10];
        _itow(h, buff, 10);
        hours = buff;
    }

#if defined(_MSC_VER) //&& defined(_M_X64)
    std::wostringstream oss;
    oss << std::setw(2) << std::setfill(wchar_t('0')) << hours   << L":" <<
           std::setw(2) << std::setfill(wchar_t('0')) << minutes << L":" <<
           std::setw(2) << std::setfill(wchar_t('0')) << seconds;
    return oss.str();
#elif defined( __MINGW32__ )
#define ADD_AS_PREFILLED( st, out ) \
    if ( st.length() == 0 ) \
        out += L"00"; \
    else if ( st.length() == 1 ) \
        out += L"0"; \
    out += st;

    std::wstring result;
    ADD_AS_PREFILLED( hours, result )
    result += L":";
    ADD_AS_PREFILLED( minutes, result )
    result += L":";
    ADD_AS_PREFILLED( seconds, result )

    return result;
#undef ADD_AS_PREFILLED
#endif
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "XalanParsedURI.hpp"

#include "XalanUnicode.hpp"

XALAN_CPP_NAMESPACE_BEGIN

#if defined(XALAN_INLINE_INITIALIZATION) && !defined(XALAN_INLINE_INITIALIZATION_IS_DEFINITION_BUG)
const int	XalanParsedURI::d_scheme;
const int	XalanParsedURI::d_authority;
const int	XalanParsedURI::d_query;
const int	XalanParsedURI::d_fragment;
#endif

/* Merge the components back into a complete URI string */
XalanDOMString XalanParsedURI::make() const
{
	XalanDOMString uri;
	if (m_defined & d_scheme)
	{
		uri += m_scheme;
		uri += XalanUnicode::charColon;
	}
	if (m_defined & d_authority)
	{
		uri += XalanUnicode::charSolidus;
		uri += XalanUnicode::charSolidus;
		uri += m_authority;
	}
	uri += m_path;
	if (m_defined & d_query)
	{
		uri += XalanUnicode::charQuestionMark;
		uri += m_query;
	}
	if (m_defined & d_fragment)
	{
		uri += XalanUnicode::charNumberSign;
		uri += m_fragment;
	}
	return uri;
}

/* Parse a URI into component parts.
   Essentially implements the regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 */
void XalanParsedURI::parse(
	const XalanDOMChar*			uriString,
	XalanDOMString::size_type	uriStringLen
)
{
	XalanDOMString::size_type index = 0;

	// Clear the components present mask
	m_defined = 0;

	// Scheme portion
	while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charColon &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}

	if (index > 0 && uriString[index] == XalanUnicode::charColon)
	{
		m_scheme = XalanDOMString(uriString, index);
		++index;
		m_defined |= d_scheme;
	}
	else
	{
		index = 0;
		m_scheme.clear();
	}

	// Authority portion
	if (index < uriStringLen - 1 &&
		uriString[index] == XalanUnicode::charSolidus &&
		uriString[index+1] == XalanUnicode::charSolidus)
	{
		index += 2;
		XalanDOMString::size_type authority = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_authority = XalanDOMString(uriString + authority, index - authority);
		m_defined |= d_authority;
	}
	else
	{
		m_authority.clear();
	}

	// Path portion
	XalanDOMString::size_type path = index;
	while (index < uriStringLen &&
			uriString[index] != XalanUnicode::charQuestionMark &&
			uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}
	m_path = XalanDOMString(uriString + path, index - path);

	// Query portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charQuestionMark)
	{
		++index;
		XalanDOMString::size_type query = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_query = XalanDOMString(uriString + query, index - query);
		m_defined |= d_query;
	}
	else
	{
		m_query.clear();
	}

	// Fragment portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charNumberSign)
	{
		++index;
		m_fragment = XalanDOMString(uriString + index, uriStringLen - index);
		m_defined |= d_fragment;
	}
	else
	{
		m_fragment.clear();
	}
}

/* Case insensitive comparison for URIs.  Limited to A-Za-z */
static int ci_equals(const XalanDOMString &s1, const XalanDOMString &s2)
{
	if (s1.length() != s2.length())
		return false;

	const XalanDOMChar *p1 = s1.c_str(), *p2 = s2.c_str();
	for ( ; *p1 ; p1++, p2++)
	{
		XalanDOMChar c1 = *p1, c2 = *p2;
		if (c1 >= XalanUnicode::charLetter_A && c1 <= XalanUnicode::charLetter_Z)
			c1 = XalanUnicode::charLetter_a + (c1 - XalanUnicode::charLetter_A);
		if (c2 >= XalanUnicode::charLetter_A && c2 <= XalanUnicode::charLetter_Z)
			c2 = XalanUnicode::charLetter_a + (c2 - XalanUnicode::charLetter_A);
		if (c1 != c2)
			return false;
	}

	return true;
}

/* Resolve this URI relative to another according to RFC2396, section 5.2 */
void XalanParsedURI::resolve(
	const XalanParsedURI &base
)
{
	// Handle references to the current document (step 2)
	if ((m_defined & (d_scheme | d_authority | d_query)) == 0 &&
		m_path.empty())
	{
		m_scheme	= base.m_scheme;
		m_authority = base.m_authority;
		m_path		= base.m_path;
		m_query		= base.m_query;

		// There is an error/unclarity in the specification in step 2 in that
		// it doesn't state that the fragment should be inherited; however
		// it is clear from the examples that it should be
		if (!(m_defined & d_fragment))
		{
			m_fragment = base.m_fragment;
		}

		m_defined |= base.m_defined;
		return;
	}

	// A defined scheme component implies that this is an absolute URI (step 3)
	// Also allow a scheme without authority that matches the base scheme to be
	// interpreted as a relative URI
	if (!(m_defined & d_scheme) || (
			(base.m_defined & d_scheme) && !(m_defined & d_authority)
			&& ci_equals(m_scheme, base.m_scheme)))
	{
		// Inherit the base scheme
		m_scheme = base.m_scheme;
		m_defined |= d_scheme;

		// Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7
		if (!(m_defined & d_authority))
		{
			// Inherit the base authority
			m_authority = base.m_authority;
			m_defined |= d_authority;

			// Step 5: if the path starts with a / then it is absolute
			if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus))
			{
				// Step 6: merge relative path components

				// a) strip off characters after the right most slash in the base path
				XalanDOMString::size_type pathEnd = base.m_path.length();
				while (pathEnd > 0 && base.m_path[pathEnd - 1] != XalanUnicode::charSolidus)
				{
					--pathEnd;
				}

				if (pathEnd > 0)
				{
					// b) append relative path
					// This inserts the path portion from base...
					m_path.insert(0, base.m_path, 0, pathEnd);
				}
				else
				{
					// TODO, maybe raise an error here as this
					// is a severely wonky looking URI
				}

				// c)->g remove various "./" and "../" segments
				for (XalanDOMString::size_type index = 0; index < m_path.length(); )
				{
					// remove '<segment>/../' and ./
					if (m_path[index] == XalanUnicode::charFullStop)
					{
						if (index < m_path.length()-1 &&
							m_path[index+1] == XalanUnicode::charSolidus) // ./
						{
							m_path.erase(index,2);
							continue;
						}
						else if (index == m_path.length()-1) // trailing /.
						{
							m_path.erase(index,1);
							continue;
						}
						// Note: also strips leading ../ in an attempt to get
						// something out of a bad m_path
						else if (index < m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop &&
									m_path[index+2] == XalanUnicode::charSolidus) // ../
						{
							int end = index+2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							if (index > 0) --index;
							m_path.erase(index,end-index);
							continue;
						}
						else if (index == m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop) // trailing /..
						{
							int end = index+2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							m_path.erase(index,end-index);
							continue;
						}
					}
					for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index)
					{
					}
					++index;
				}
			}
		}
	}
}

/* Static helper function to perform a resolve without mucking about with this class */
XalanDOMString XalanParsedURI::resolve(
	const XalanDOMChar			*relative,
	XalanDOMString::size_type	relativeLen,
	const XalanDOMChar			*base,
	XalanDOMString::size_type	baseLen
)
{
	XalanParsedURI relativeURI(relative, relativeLen);
	XalanParsedURI baseURI(base, baseLen);

	relativeURI.resolve(baseURI);
	return relativeURI.make();
}

XALAN_CPP_NAMESPACE_END
<commit_msg>Fixed inappropriate uses of int instead of XalanDOMString::size_type.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "XalanParsedURI.hpp"

#include "XalanUnicode.hpp"

XALAN_CPP_NAMESPACE_BEGIN

#if defined(XALAN_INLINE_INITIALIZATION) && !defined(XALAN_INLINE_INITIALIZATION_IS_DEFINITION_BUG)
const int	XalanParsedURI::d_scheme;
const int	XalanParsedURI::d_authority;
const int	XalanParsedURI::d_query;
const int	XalanParsedURI::d_fragment;
#endif

/* Merge the components back into a complete URI string */
XalanDOMString XalanParsedURI::make() const
{
	XalanDOMString uri;
	if (m_defined & d_scheme)
	{
		uri += m_scheme;
		uri += XalanUnicode::charColon;
	}
	if (m_defined & d_authority)
	{
		uri += XalanUnicode::charSolidus;
		uri += XalanUnicode::charSolidus;
		uri += m_authority;
	}
	uri += m_path;
	if (m_defined & d_query)
	{
		uri += XalanUnicode::charQuestionMark;
		uri += m_query;
	}
	if (m_defined & d_fragment)
	{
		uri += XalanUnicode::charNumberSign;
		uri += m_fragment;
	}
	return uri;
}

/* Parse a URI into component parts.
   Essentially implements the regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 */
void XalanParsedURI::parse(
	const XalanDOMChar*			uriString,
	XalanDOMString::size_type	uriStringLen
)
{
	XalanDOMString::size_type index = 0;

	// Clear the components present mask
	m_defined = 0;

	// Scheme portion
	while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charColon &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}

	if (index > 0 && uriString[index] == XalanUnicode::charColon)
	{
		m_scheme = XalanDOMString(uriString, index);
		++index;
		m_defined |= d_scheme;
	}
	else
	{
		index = 0;
		m_scheme.clear();
	}

	// Authority portion
	if (index < uriStringLen - 1 &&
		uriString[index] == XalanUnicode::charSolidus &&
		uriString[index+1] == XalanUnicode::charSolidus)
	{
		index += 2;
		XalanDOMString::size_type authority = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_authority = XalanDOMString(uriString + authority, index - authority);
		m_defined |= d_authority;
	}
	else
	{
		m_authority.clear();
	}

	// Path portion
	XalanDOMString::size_type path = index;
	while (index < uriStringLen &&
			uriString[index] != XalanUnicode::charQuestionMark &&
			uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}
	m_path = XalanDOMString(uriString + path, index - path);

	// Query portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charQuestionMark)
	{
		++index;
		XalanDOMString::size_type query = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_query = XalanDOMString(uriString + query, index - query);
		m_defined |= d_query;
	}
	else
	{
		m_query.clear();
	}

	// Fragment portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charNumberSign)
	{
		++index;
		m_fragment = XalanDOMString(uriString + index, uriStringLen - index);
		m_defined |= d_fragment;
	}
	else
	{
		m_fragment.clear();
	}
}

/* Case insensitive comparison for URIs.  Limited to A-Za-z */
static int ci_equals(const XalanDOMString &s1, const XalanDOMString &s2)
{
	if (s1.length() != s2.length())
		return false;

	const XalanDOMChar *p1 = s1.c_str(), *p2 = s2.c_str();
	for ( ; *p1 ; p1++, p2++)
	{
		XalanDOMChar c1 = *p1, c2 = *p2;
		if (c1 >= XalanUnicode::charLetter_A && c1 <= XalanUnicode::charLetter_Z)
			c1 = XalanUnicode::charLetter_a + (c1 - XalanUnicode::charLetter_A);
		if (c2 >= XalanUnicode::charLetter_A && c2 <= XalanUnicode::charLetter_Z)
			c2 = XalanUnicode::charLetter_a + (c2 - XalanUnicode::charLetter_A);
		if (c1 != c2)
			return false;
	}

	return true;
}

/* Resolve this URI relative to another according to RFC2396, section 5.2 */
void XalanParsedURI::resolve(
	const XalanParsedURI &base
)
{
	// Handle references to the current document (step 2)
	if ((m_defined & (d_scheme | d_authority | d_query)) == 0 &&
		m_path.empty())
	{
		m_scheme	= base.m_scheme;
		m_authority = base.m_authority;
		m_path		= base.m_path;
		m_query		= base.m_query;

		// There is an error/unclarity in the specification in step 2 in that
		// it doesn't state that the fragment should be inherited; however
		// it is clear from the examples that it should be
		if (!(m_defined & d_fragment))
		{
			m_fragment = base.m_fragment;
		}

		m_defined |= base.m_defined;
		return;
	}

	// A defined scheme component implies that this is an absolute URI (step 3)
	// Also allow a scheme without authority that matches the base scheme to be
	// interpreted as a relative URI
	if (!(m_defined & d_scheme) || (
			(base.m_defined & d_scheme) && !(m_defined & d_authority)
			&& ci_equals(m_scheme, base.m_scheme)))
	{
		// Inherit the base scheme
		m_scheme = base.m_scheme;
		m_defined |= d_scheme;

		// Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7
		if (!(m_defined & d_authority))
		{
			// Inherit the base authority
			m_authority = base.m_authority;
			m_defined |= d_authority;

			// Step 5: if the path starts with a / then it is absolute
			if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus))
			{
				// Step 6: merge relative path components

				// a) strip off characters after the right most slash in the base path
				XalanDOMString::size_type pathEnd = base.m_path.length();
				while (pathEnd > 0 && base.m_path[pathEnd - 1] != XalanUnicode::charSolidus)
				{
					--pathEnd;
				}

				if (pathEnd > 0)
				{
					// b) append relative path
					// This inserts the path portion from base...
					m_path.insert(0, base.m_path, 0, pathEnd);
				}
				else
				{
					// TODO, maybe raise an error here as this
					// is a severely wonky looking URI
				}

				// c)->g remove various "./" and "../" segments
				for (XalanDOMString::size_type index = 0; index < m_path.length(); )
				{
					// remove '<segment>/../' and ./
					if (m_path[index] == XalanUnicode::charFullStop)
					{
						if (index < m_path.length()-1 &&
							m_path[index+1] == XalanUnicode::charSolidus) // ./
						{
							m_path.erase(index,2);
							continue;
						}
						else if (index == m_path.length()-1) // trailing /.
						{
							m_path.erase(index,1);
							continue;
						}
						// Note: also strips leading ../ in an attempt to get
						// something out of a bad m_path
						else if (index < m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop &&
									m_path[index+2] == XalanUnicode::charSolidus) // ../
						{
							const XalanDOMString::size_type		end = index + 2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							if (index > 0) --index;
							m_path.erase(index, end - index);
							continue;
						}
						else if (index == m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop) // trailing /..
						{
							const XalanDOMString::size_type		end = index + 2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							m_path.erase(index, end - index);
							continue;
						}
					}
					for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index)
					{
					}
					++index;
				}
			}
		}
	}
}

/* Static helper function to perform a resolve without mucking about with this class */
XalanDOMString XalanParsedURI::resolve(
	const XalanDOMChar			*relative,
	XalanDOMString::size_type	relativeLen,
	const XalanDOMChar			*base,
	XalanDOMString::size_type	baseLen
)
{
	XalanParsedURI relativeURI(relative, relativeLen);
	XalanParsedURI baseURI(base, baseLen);

	relativeURI.resolve(baseURI);
	return relativeURI.make();
}

XALAN_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s -std=c++0x

struct S {
  virtual ~S();

  auto a; // expected-error{{'auto' not allowed in struct member}}
  auto *b; // expected-error{{'auto' not allowed in struct member}}
  const auto c; // expected-error{{'auto' not allowed in struct member}}

  void f() throw (auto); // expected-error{{'auto' not allowed here}}

  friend auto; // expected-error{{'auto' not allowed in struct member}}

  operator auto(); // expected-error{{'auto' not allowed here}}
};

typedef auto *AutoPtr; // expected-error{{'auto' not allowed in typedef}}
typedef auto Fun(int a) -> decltype(a + a);

void g(auto a) { // expected-error{{'auto' not allowed in function prototype}}
  try { }
  catch (auto &a) { } // expected-error{{'auto' not allowed in exception declaration}}
  catch (const auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
  try { } catch (auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
}

void h(auto a[10]) { // expected-error{{'auto' not allowed in function prototype}}
}

void i(const auto a) { // expected-error{{'auto' not allowed in function prototype}}
}

namespace std {
  class type_info;
}

template<typename T> struct U {};

void j() {
  (void)typeid(auto); // expected-error{{'auto' not allowed here}}
  (void)sizeof(auto); // expected-error{{'auto' not allowed here}}
  (void)__alignof(auto); // expected-error{{'auto' not allowed here}}

  // FIXME: don't issue the second diagnostic for this error.
  U<auto> v; // expected-error{{'auto' not allowed in template argument}} unexpected-error{{C++ requires a type specifier}}

  int n;
  (void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}}
  (void)static_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
  (void)reinterpret_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
  (void)const_cast<auto>(n); // expected-error{{'auto' not allowed here}}
  (void)*(auto*)(&n); // expected-error{{'auto' not allowed here}}
  (void)auto(n); // expected-error{{expected expression}}
  (void)auto{n}; // expected-error{{expected expression}}
}

template <auto a = 10> class C { }; // expected-error{{'auto' not allowed in template parameter}}
int ints[] = {1, 2, 3};
template <const auto (*a)[3] = &ints> class D { }; // expected-error{{'auto' not allowed in template parameter}}
enum E : auto {}; // expected-error{{'auto' not allowed here}}
struct F : auto {}; // expected-error{{expected class name}}
template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}}

using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}}

// Whether this is illegal depends on the interpretation of [decl.spec.auto]p2 and p3,
// and in particular the "Otherwise, ..." at the start of p3.
namespace TrailingReturnType {
  // FIXME: don't issue the second diagnostic for this error.
  auto f() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}}
  int g();
  auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}}
  auto (*i)() = &g; // ok; auto deduced as int.
  auto (*j)() -> int = i; // ok; no deduction.
}
<commit_msg>Add reference to PR 9278 for archaeologists.<commit_after>// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s -std=c++0x

struct S {
  virtual ~S();

  auto a; // expected-error{{'auto' not allowed in struct member}}
  auto *b; // expected-error{{'auto' not allowed in struct member}}
  const auto c; // expected-error{{'auto' not allowed in struct member}}

  void f() throw (auto); // expected-error{{'auto' not allowed here}}

  friend auto; // expected-error{{'auto' not allowed in struct member}}

  operator auto(); // expected-error{{'auto' not allowed here}}
};

// PR 9278: auto is not allowed in typedefs, except with a trailing return type.
typedef auto *AutoPtr; // expected-error{{'auto' not allowed in typedef}}
typedef auto Fun(int a) -> decltype(a + a);

void g(auto a) { // expected-error{{'auto' not allowed in function prototype}}
  try { }
  catch (auto &a) { } // expected-error{{'auto' not allowed in exception declaration}}
  catch (const auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
  try { } catch (auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
}

void h(auto a[10]) { // expected-error{{'auto' not allowed in function prototype}}
}

void i(const auto a) { // expected-error{{'auto' not allowed in function prototype}}
}

namespace std {
  class type_info;
}

template<typename T> struct U {};

void j() {
  (void)typeid(auto); // expected-error{{'auto' not allowed here}}
  (void)sizeof(auto); // expected-error{{'auto' not allowed here}}
  (void)__alignof(auto); // expected-error{{'auto' not allowed here}}

  // FIXME: don't issue the second diagnostic for this error.
  U<auto> v; // expected-error{{'auto' not allowed in template argument}} unexpected-error{{C++ requires a type specifier}}

  int n;
  (void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}}
  (void)static_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
  (void)reinterpret_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
  (void)const_cast<auto>(n); // expected-error{{'auto' not allowed here}}
  (void)*(auto*)(&n); // expected-error{{'auto' not allowed here}}
  (void)auto(n); // expected-error{{expected expression}}
  (void)auto{n}; // expected-error{{expected expression}}
}

template <auto a = 10> class C { }; // expected-error{{'auto' not allowed in template parameter}}
int ints[] = {1, 2, 3};
template <const auto (*a)[3] = &ints> class D { }; // expected-error{{'auto' not allowed in template parameter}}
enum E : auto {}; // expected-error{{'auto' not allowed here}}
struct F : auto {}; // expected-error{{expected class name}}
template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed here}}

using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}}

// Whether this is illegal depends on the interpretation of [decl.spec.auto]p2 and p3,
// and in particular the "Otherwise, ..." at the start of p3.
namespace TrailingReturnType {
  // FIXME: don't issue the second diagnostic for this error.
  auto f() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}}
  int g();
  auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}}
  auto (*i)() = &g; // ok; auto deduced as int.
  auto (*j)() -> int = i; // ok; no deduction.
}
<|endoftext|>


<commit_before>#include "assert.hh"

#include "exception.hh"
#include "debug.hh"

#include <sys/types.h>
#include <unistd.h>

namespace Kakoune
{

struct assert_failed : logic_error
{
    assert_failed(const String& message)
        : m_message(message) {}

    const char* what() const override { return m_message.c_str(); }
private:
    String m_message;
};

void on_assert_failed(const char* message)
{
    String debug_info = "pid: " + to_string(getpid());
    write_debug("assert failed: '"_str + message + "' " + debug_info);

    int res = system(("xmessage -buttons 'quit:0,ignore:1' '"_str +
                      message + "\n[Debug Infos]\n" + debug_info + "'").c_str());
    switch (res)
    {
    case -1:
    case  0:
        throw assert_failed(message);
    case 1:
        return;
    }
}

}
<commit_msg>Use Win32 MessageBox for asserts on cygwin<commit_after>#include "assert.hh"

#include "exception.hh"
#include "debug.hh"

#if defined(__CYGWIN__)
#include <windows.h>
#endif

#include <sys/types.h>
#include <unistd.h>

namespace Kakoune
{

struct assert_failed : logic_error
{
    assert_failed(const String& message)
        : m_message(message) {}

    const char* what() const override { return m_message.c_str(); }
private:
    String m_message;
};

void on_assert_failed(const char* message)
{
    String debug_info = "pid: " + to_string(getpid());
    write_debug("assert failed: '"_str + message + "' " + debug_info);

    const auto msg = message + "\n[Debug Infos]\n"_str + debug_info;
#if defined(__CYGWIN__)
    int res = MessageBox(NULL, msg.c_str(), "Kakoune: assert failed",
                         MB_OKCANCEL | MB_ICONERROR);
    switch (res)
    {
    case IDCANCEL:
        throw assert_failed(message);
    case IDOK:
        return;
    }
#else
    int res = system(("xmessage -buttons 'quit:0,ignore:1' '" + msg + "'").c_str());
    switch (res)
    {
    case -1:
    case  0:
        throw assert_failed(message);
    case 1:
        return;
    }
#endif
}

}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_STATE_HPP
#define SOL_STATE_HPP

#include "error.hpp"
#include "table.hpp"
#include <memory>

namespace sol {
namespace detail {
template<class T, class...>
struct are_same : std::true_type {};

template<class T, class U, class... Args>
struct are_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && are_same<T, Args...>::value> {};

int atpanic(lua_State* L) {
    std::string err = lua_tostring(L, -1);
    throw sol_error(err);
}
} // detail

enum class lib : char {
    base,
    package,
    coroutine,
    string,
    os,
    math,
    table,
    debug,
    bit32,
    io,
    count
};

class state {
private:
    std::unique_ptr<lua_State, void(*)(lua_State*)> L;
    table reg;
    table global;
public:
    state():
    L(luaL_newstate(), lua_close),
    reg(L.get(), LUA_REGISTRYINDEX),
    global(reg.get<table>(LUA_RIDX_GLOBALS)) {
        lua_atpanic(L.get(), detail::atpanic);
    }

    template<typename... Args>
    void open_libraries(Args&&... args) {
        static_assert(detail::are_same<lib, Args...>::value, "all types must be libraries");
        if(sizeof...(args) == 0) {
            luaL_openlibs(L.get());
            return;
        }

        lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... };

        for(auto&& library : libraries) {
            switch(library) {
            case lib::base:
                luaL_requiref(L.get(), "base", luaopen_base, 1);
                break;
            case lib::package:
                luaL_requiref(L.get(), "package", luaopen_package, 1);
                break;
            case lib::coroutine:
                luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1);
                break;
            case lib::string:
                luaL_requiref(L.get(), "string", luaopen_string, 1);
                break;
            case lib::table:
                luaL_requiref(L.get(), "table", luaopen_table, 1);
                break;
            case lib::math:
                luaL_requiref(L.get(), "math", luaopen_math, 1);
                break;
            case lib::bit32:
                luaL_requiref(L.get(), "bit32", luaopen_bit32, 1);
                break;
            case lib::io:
                luaL_requiref(L.get(), "io", luaopen_io, 1);
                break;
            case lib::os:
                luaL_requiref(L.get(), "os", luaopen_os, 1);
                break;
            case lib::debug:
                luaL_requiref(L.get(), "debug", luaopen_debug, 1);
                break;
            case lib::count:
                break;
            }
        }
    }

    void script(const std::string& code) {
        if(luaL_dostring(L.get(), code.c_str())) {
            lua_error(L.get());
        }
    }

    void open_file(const std::string& filename) {
        if (luaL_dofile(L.get(), filename.c_str())) {
            lua_error(L.get());
        }
    }

    template<typename... Args, typename... Keys>
    typename multi_return<Args...>::type get(Keys&&... keys) const {
       return global.get(types<Args...>(), std::forward<Keys>(keys)...);
    }

    template<typename T, typename U>
    state& set(T&& key, U&& value) {
        global.set(std::forward<T>(key), std::forward<U>(value));
        return *this;
    }

    template<typename T, typename TFx>
    state& set_function(T&& key, TFx&& fx) {
        global.set_function(std::forward<T>(key), std::forward<TFx>(fx));
        return *this;
    }

    template<typename T, typename TFx, typename TM>
    state& set_function(T&& key, TFx&& fx, TM& mem) {
        global.set_function(std::forward<T>(key), std::forward<TFx>(fx), mem);
        return *this;
    }

    template<typename T>
    table create_table(T&& key, int narr = 0, int nrec = 0) {
        lua_createtable(L.get(), narr, nrec);
        table result(L.get());
        lua_pop(L.get(), 1);
        global.set(std::forward<T>(key), result);
        return result;
    }

    table create_table(int narr = 0, int nrec = 0) {
        lua_createtable(L.get(), narr, nrec);
        table result(L.get());
        lua_pop(L.get(), 1);
        return result;
    }

    table global_table() const {
        return global;
    }

    table registry() const {
        return reg;
    }

    template <typename T>
    proxy<table, T> operator[](T&& key) {
        return global[std::forward<T>(key)];
    }

    template <typename T>
    proxy<const table, T> operator[](T&& key) const {
        return global[std::forward<T>(key)];
    }
};
} // sol

#endif // SOL_STATE_HPP<commit_msg>Add lua_state function to retrieve the lua_State pointer<commit_after>// The MIT License (MIT)

// Copyright (c) 2013 Danny Y., Rapptz

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_STATE_HPP
#define SOL_STATE_HPP

#include "error.hpp"
#include "table.hpp"
#include <memory>

namespace sol {
namespace detail {
template<class T, class...>
struct are_same : std::true_type {};

template<class T, class U, class... Args>
struct are_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && are_same<T, Args...>::value> {};

int atpanic(lua_State* L) {
    std::string err = lua_tostring(L, -1);
    throw sol_error(err);
}
} // detail

enum class lib : char {
    base,
    package,
    coroutine,
    string,
    os,
    math,
    table,
    debug,
    bit32,
    io,
    count
};

class state {
private:
    std::unique_ptr<lua_State, void(*)(lua_State*)> L;
    table reg;
    table global;
public:
    state():
    L(luaL_newstate(), lua_close),
    reg(L.get(), LUA_REGISTRYINDEX),
    global(reg.get<table>(LUA_RIDX_GLOBALS)) {
        lua_atpanic(L.get(), detail::atpanic);
    }

    template<typename... Args>
    void open_libraries(Args&&... args) {
        static_assert(detail::are_same<lib, Args...>::value, "all types must be libraries");
        if(sizeof...(args) == 0) {
            luaL_openlibs(L.get());
            return;
        }

        lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... };

        for(auto&& library : libraries) {
            switch(library) {
            case lib::base:
                luaL_requiref(L.get(), "base", luaopen_base, 1);
                break;
            case lib::package:
                luaL_requiref(L.get(), "package", luaopen_package, 1);
                break;
            case lib::coroutine:
                luaL_requiref(L.get(), "coroutine", luaopen_coroutine, 1);
                break;
            case lib::string:
                luaL_requiref(L.get(), "string", luaopen_string, 1);
                break;
            case lib::table:
                luaL_requiref(L.get(), "table", luaopen_table, 1);
                break;
            case lib::math:
                luaL_requiref(L.get(), "math", luaopen_math, 1);
                break;
            case lib::bit32:
                luaL_requiref(L.get(), "bit32", luaopen_bit32, 1);
                break;
            case lib::io:
                luaL_requiref(L.get(), "io", luaopen_io, 1);
                break;
            case lib::os:
                luaL_requiref(L.get(), "os", luaopen_os, 1);
                break;
            case lib::debug:
                luaL_requiref(L.get(), "debug", luaopen_debug, 1);
                break;
            case lib::count:
                break;
            }
        }
    }

    void script(const std::string& code) {
        if(luaL_dostring(L.get(), code.c_str())) {
            lua_error(L.get());
        }
    }

    void open_file(const std::string& filename) {
        if (luaL_dofile(L.get(), filename.c_str())) {
            lua_error(L.get());
        }
    }

    template<typename... Args, typename... Keys>
    typename multi_return<Args...>::type get(Keys&&... keys) const {
       return global.get(types<Args...>(), std::forward<Keys>(keys)...);
    }

    template<typename T, typename U>
    state& set(T&& key, U&& value) {
        global.set(std::forward<T>(key), std::forward<U>(value));
        return *this;
    }

    template<typename T, typename TFx>
    state& set_function(T&& key, TFx&& fx) {
        global.set_function(std::forward<T>(key), std::forward<TFx>(fx));
        return *this;
    }

    template<typename T, typename TFx, typename TM>
    state& set_function(T&& key, TFx&& fx, TM& mem) {
        global.set_function(std::forward<T>(key), std::forward<TFx>(fx), mem);
        return *this;
    }

    template<typename T>
    table create_table(T&& key, int narr = 0, int nrec = 0) {
        lua_createtable(L.get(), narr, nrec);
        table result(L.get());
        lua_pop(L.get(), 1);
        global.set(std::forward<T>(key), result);
        return result;
    }

    table create_table(int narr = 0, int nrec = 0) {
        lua_createtable(L.get(), narr, nrec);
        table result(L.get());
        lua_pop(L.get(), 1);
        return result;
    }

    table global_table() const {
        return global;
    }

    table registry() const {
        return reg;
    }

    template <typename T>
    proxy<table, T> operator[](T&& key) {
        return global[std::forward<T>(key)];
    }

    template <typename T>
    proxy<const table, T> operator[](T&& key) const {
        return global[std::forward<T>(key)];
    }

    lua_State* lua_state() const {
        return L.get();
    }
};
} // sol

#endif // SOL_STATE_HPP<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_OS_WINDOWS_SHELL_HPP__
#define __STOUT_OS_WINDOWS_SHELL_HPP__

#include <process.h>
#include <stdarg.h> // For va_list, va_start, etc.

#include <ostream>
#include <string>

#include <stout/try.hpp>

#include <stout/os/raw/argv.hpp>

namespace os {

namespace Shell {

  // Canonical constants used as platform-dependent args to `exec` calls.
  // `name` is the command name, `arg0` is the first argument received
  // by the callee, usually the command name and `arg1` is the second
  // command argument received by the callee.
  constexpr const char* name = "cmd.exe";
  constexpr const char* arg0 = "cmd";
  constexpr const char* arg1 = "/c";

} // namespace Shell {

/**
 * Runs a shell command with optional arguments.
 *
 * This assumes that a successful execution will result in the exit code
 * for the command to be `EXIT_SUCCESS`; in this case, the contents
 * of the `Try` will be the contents of `stdout`.
 *
 * If the exit code is non-zero or the process was signaled, we will
 * return an appropriate error message; but *not* `stderr`.
 *
 * If the caller needs to examine the contents of `stderr` it should
 * be redirected to `stdout` (using, e.g., "2>&1 || true" in the command
 * string).  The `|| true` is required to obtain a success exit
 * code in case of errors, and still obtain `stderr`, as piped to
 * `stdout`.
 *
 * @param fmt the formatting string that contains the command to execute
 *   in the underlying shell.
 * @param t optional arguments for `fmt`.
 *
 * @return the output from running the specified command with the shell; or
 *   an error message if the command's exit code is non-zero.
 */
template <typename... T>
Try<std::string> shell(const std::string& fmt, const T&... t)
{
  const Try<std::string> command = strings::internal::format(fmt, t...);
  if (command.isError()) {
    return Error(command.error());
  }

  FILE* file;
  std::ostringstream stdoutstr;

  if ((file = _popen(command.get().c_str(), "r")) == nullptr) {
    return Error("Failed to run '" + command.get() + "'");
  }

  char line[1024];
  // NOTE(vinod): Ideally the if and while loops should be interchanged. But
  // we get a broken pipe error if we don't read the output and simply close.
  while (fgets(line, sizeof(line), file) != nullptr) {
    stdoutstr << line;
  }

  if (ferror(file) != 0) {
    _pclose(file); // Ignoring result since we already have an error.
    return Error("Error reading output of '" + command.get() + "'");
  }

  int status;
  if ((status = _pclose(file)) == -1) {
    return Error("Failed to get status of '" + command.get() + "'");
  }

  return stdoutstr.str();
}

// Executes a command by calling "cmd /c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error.
//
// The returned value from `_spawnlp` represents child exit code when
// `_P_WAIT` is used.
inline int system(const std::string& command)
{
  return static_cast<int>(::_spawnlp(
    _P_WAIT, Shell::name, Shell::arg0, Shell::arg1, command.c_str(), nullptr));
}

// Executes a command by calling "<command> <arguments...>", and
// returns after the command has been completed. Returns 0 if
// succeeds, and -1 on error.
inline int spawn(
    const std::string& command,
    const std::vector<std::string>& arguments)
{
  return ::_spawnvp(_P_WAIT, command.c_str(), os::raw::Argv(arguments));
}

// On Windows, the `_spawnlp` call creates a new process.
// In order to emulate the semantics of `execlp`, we spawn with `_P_WAIT`,
// which forces the parent process to block on the child. When the child exits,
// the exit code is propagated back through the parent via `exit()`.
//
// The returned value from `_spawnlp` represents child exit code when
// `_P_WAIT` is used.
template<typename... T>
inline int execlp(const char* file, T... t)
{
  exit(static_cast<int>(::_spawnlp(_P_WAIT, file, t...));
  return 0;
}

// On Windows, the `_spawnvp` call creates a new process.
// In order to emulate the semantics of `execvp`, we spawn with `_P_WAIT`,
// which forces the parent process to block on the child. When the child exits,
// the exit code is propagated back through the parent via `exit()`.
//
// The returned value from `_spawnlp` represents child exit code when
// `_P_WAIT` is used.
inline int execvp(const char* file, char* const argv[])
{
  exit(static_cast<int>(::_spawnvp(_P_WAIT, file, argv));
  return 0;
}

// Concatenates multiple command-line arguments and escapes the values.
// If `arg` is not specified (or takes the value `0`), the function will
// scan `argv` until a `nullptr` is encountered.
inline std::string stringify_args(char** argv, unsigned long argc = 0)
{
  std::string arg_line = "";
  unsigned long index = 0;
  while ((argc == 0 || index < argc) && argv[index] != nullptr) {
    // TODO(dpravat): (MESOS-5522) Format these args for all cases.
    // Specifically, we need to:
    //   (1) Add double quotes around arguments that contain special
    //       characters, like spaces and tabs.
    //   (2) Escape any existing double quotes and backslashes.
    arg_line = strings::join(" ", arg_line, argv[index++]);
  }

  return arg_line;
}

} // namespace os {

#endif // __STOUT_OS_WINDOWS_SHELL_HPP__
<commit_msg>Windows: Fix typo in `windows/shell.hpp`.<commit_after>// 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.

#ifndef __STOUT_OS_WINDOWS_SHELL_HPP__
#define __STOUT_OS_WINDOWS_SHELL_HPP__

#include <process.h>
#include <stdarg.h> // For va_list, va_start, etc.

#include <ostream>
#include <string>

#include <stout/try.hpp>

#include <stout/os/raw/argv.hpp>

namespace os {

namespace Shell {

  // Canonical constants used as platform-dependent args to `exec` calls.
  // `name` is the command name, `arg0` is the first argument received
  // by the callee, usually the command name and `arg1` is the second
  // command argument received by the callee.
  constexpr const char* name = "cmd.exe";
  constexpr const char* arg0 = "cmd";
  constexpr const char* arg1 = "/c";

} // namespace Shell {

/**
 * Runs a shell command with optional arguments.
 *
 * This assumes that a successful execution will result in the exit code
 * for the command to be `EXIT_SUCCESS`; in this case, the contents
 * of the `Try` will be the contents of `stdout`.
 *
 * If the exit code is non-zero or the process was signaled, we will
 * return an appropriate error message; but *not* `stderr`.
 *
 * If the caller needs to examine the contents of `stderr` it should
 * be redirected to `stdout` (using, e.g., "2>&1 || true" in the command
 * string).  The `|| true` is required to obtain a success exit
 * code in case of errors, and still obtain `stderr`, as piped to
 * `stdout`.
 *
 * @param fmt the formatting string that contains the command to execute
 *   in the underlying shell.
 * @param t optional arguments for `fmt`.
 *
 * @return the output from running the specified command with the shell; or
 *   an error message if the command's exit code is non-zero.
 */
template <typename... T>
Try<std::string> shell(const std::string& fmt, const T&... t)
{
  const Try<std::string> command = strings::internal::format(fmt, t...);
  if (command.isError()) {
    return Error(command.error());
  }

  FILE* file;
  std::ostringstream stdoutstr;

  if ((file = _popen(command.get().c_str(), "r")) == nullptr) {
    return Error("Failed to run '" + command.get() + "'");
  }

  char line[1024];
  // NOTE(vinod): Ideally the if and while loops should be interchanged. But
  // we get a broken pipe error if we don't read the output and simply close.
  while (fgets(line, sizeof(line), file) != nullptr) {
    stdoutstr << line;
  }

  if (ferror(file) != 0) {
    _pclose(file); // Ignoring result since we already have an error.
    return Error("Error reading output of '" + command.get() + "'");
  }

  int status;
  if ((status = _pclose(file)) == -1) {
    return Error("Failed to get status of '" + command.get() + "'");
  }

  return stdoutstr.str();
}

// Executes a command by calling "cmd /c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error.
//
// The returned value from `_spawnlp` represents child exit code when
// `_P_WAIT` is used.
inline int system(const std::string& command)
{
  return static_cast<int>(::_spawnlp(
    _P_WAIT, Shell::name, Shell::arg0, Shell::arg1, command.c_str(), nullptr));
}

// Executes a command by calling "<command> <arguments...>", and
// returns after the command has been completed. Returns 0 if
// succeeds, and -1 on error.
inline int spawn(
    const std::string& command,
    const std::vector<std::string>& arguments)
{
  return ::_spawnvp(_P_WAIT, command.c_str(), os::raw::Argv(arguments));
}

// On Windows, the `_spawnlp` call creates a new process.
// In order to emulate the semantics of `execlp`, we spawn with `_P_WAIT`,
// which forces the parent process to block on the child. When the child exits,
// the exit code is propagated back through the parent via `exit()`.
//
// The returned value from `_spawnlp` represents child exit code when
// `_P_WAIT` is used.
template<typename... T>
inline int execlp(const char* file, T... t)
{
  exit(static_cast<int>(::_spawnlp(_P_WAIT, file, t...)));
  return 0;
}

// On Windows, the `_spawnvp` call creates a new process.
// In order to emulate the semantics of `execvp`, we spawn with `_P_WAIT`,
// which forces the parent process to block on the child. When the child exits,
// the exit code is propagated back through the parent via `exit()`.
//
// The returned value from `_spawnlp` represents child exit code when
// `_P_WAIT` is used.
inline int execvp(const char* file, char* const argv[])
{
  exit(static_cast<int>(::_spawnvp(_P_WAIT, file, argv)));
  return 0;
}

// Concatenates multiple command-line arguments and escapes the values.
// If `arg` is not specified (or takes the value `0`), the function will
// scan `argv` until a `nullptr` is encountered.
inline std::string stringify_args(char** argv, unsigned long argc = 0)
{
  std::string arg_line = "";
  unsigned long index = 0;
  while ((argc == 0 || index < argc) && argv[index] != nullptr) {
    // TODO(dpravat): (MESOS-5522) Format these args for all cases.
    // Specifically, we need to:
    //   (1) Add double quotes around arguments that contain special
    //       characters, like spaces and tabs.
    //   (2) Escape any existing double quotes and backslashes.
    arg_line = strings::join(" ", arg_line, argv[index++]);
  }

  return arg_line;
}

} // namespace os {

#endif // __STOUT_OS_WINDOWS_SHELL_HPP__
<|endoftext|>


<commit_before>// 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.

#ifndef __STOUT_OS_WINDOWS_SHELL_HPP__
#define __STOUT_OS_WINDOWS_SHELL_HPP__

#include <process.h>
#include <processthreadsapi.h>
#include <shellapi.h>
#include <synchapi.h>

#include <stdarg.h> // For va_list, va_start, etc.

#include <algorithm>
#include <array>
#include <map>
#include <string>
#include <vector>

#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/none.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>

#include <stout/os/int_fd.hpp>
#include <stout/os/pipe.hpp>

#include <stout/os/windows/exec.hpp>

namespace os {
namespace Shell {

// Canonical constants used as platform-dependent args to `exec` calls.
// `name` is the command name, `arg0` is the first argument received
// by the callee, usually the command name and `arg1` is the second
// command argument received by the callee.
constexpr const char* name = "cmd.exe";
constexpr const char* arg0 = "cmd.exe";
constexpr const char* arg1 = "/c";

} // namespace Shell {

template <typename... T>
Try<std::string> shell(const std::string& fmt, const T&... t)
{
  using std::array;
  using std::string;
  using std::vector;

  const Try<string> command = strings::format(fmt, t...);
  if (command.isError()) {
    return Error(command.error());
  }

  // This function is intended to pass the arguments to the default
  // shell, so we first add the arguments `cmd.exe cmd.exe /c`,
  // followed by the command and arguments given.
  vector<string> args = {os::Shell::name, os::Shell::arg0, os::Shell::arg1};

  { // Minimize the lifetime of the system allocated buffer.
    //
    // NOTE: This API returns a pointer to an array of `wchar_t*`,
    // similar to `argv`. Each pointer to a null-terminated Unicode
    // string represents an individual argument found on the command
    // line. We use this because we cannot just split on whitespace.
    int argc;
    const std::unique_ptr<wchar_t*, decltype(&::LocalFree)> argv(
      ::CommandLineToArgvW(wide_stringify(command.get()).data(), &argc),
      &::LocalFree);
    if (argv == nullptr) {
      return WindowsError();
    }

    for (int i = 0; i < argc; ++i) {
      args.push_back(stringify(std::wstring(argv.get()[i])));
    }
  }

  // This function is intended to return only the `stdout` of the
  // command; but since we have to redirect all of `stdin`, `stdout`,
  // `stderr` if we want to redirect any one of them, we redirect
  // `stdin` and `stderr` to `NUL`, and `stdout` to a pipe.
  Try<int_fd> stdin_ = os::open(os::DEV_NULL, O_RDONLY);
  if (stdin_.isError()) {
    return Error(stdin_.error());
  }

  Try<array<int_fd, 2>> stdout_ = os::pipe();
  if (stdout_.isError()) {
    return Error(stdout_.error());
  }

  Try<int_fd> stderr_ = os::open(os::DEV_NULL, O_WRONLY);
  if (stderr_.isError()) {
    return Error(stderr_.error());
  }

  // Ensure the file descriptors are closed when we leave this scope.
  struct Closer
  {
    vector<int_fd> fds;
    ~Closer()
    {
      foreach (int_fd& fd, fds) {
        os::close(fd);
      }
    }
  } closer = {{stdin_.get(), stdout_.get()[0], stderr_.get()}};

  array<int_fd, 3> pipes = {stdin_.get(), stdout_.get()[1], stderr_.get()};

  using namespace os::windows::internal;

  Try<ProcessData> process_data =
    create_process(args.front(), args, None(), false, pipes);

  if (process_data.isError()) {
    return Error(process_data.error());
  }

  // Close the child end of the stdout pipe and then read until EOF.
  os::close(stdout_.get()[1]);
  string out;
  Result<string> part = None();
  do {
    part = os::read(stdout_.get()[0], 1024);
    if (part.isSome()) {
      out += part.get();
    }
  } while (part.isSome());

  // Wait for the process synchronously.
  ::WaitForSingleObject(process_data->process_handle.get_handle(), INFINITE);

  DWORD status;
  if (!::GetExitCodeProcess(
        process_data->process_handle.get_handle(), &status)) {
    return Error("Failed to `GetExitCodeProcess`: " + command.get());
  }

  if (status == 0) {
    return out;
  }

  return Error(
    "Failed to execute '" + command.get() +
    "'; the command was either "
    "not found or exited with a non-zero exit status: " +
    stringify(status));
}

inline Option<int> system(const std::string& command)
{
  return os::spawn(Shell::name, {Shell::arg0, Shell::arg1, command});
}

} // namespace os {

#endif // __STOUT_OS_WINDOWS_SHELL_HPP__
<commit_msg>Fixed a compilation issue on Windows with os::spawn.<commit_after>// 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.

#ifndef __STOUT_OS_WINDOWS_SHELL_HPP__
#define __STOUT_OS_WINDOWS_SHELL_HPP__

#include <process.h>
#include <processthreadsapi.h>
#include <shellapi.h>
#include <synchapi.h>

#include <stdarg.h> // For va_list, va_start, etc.

#include <algorithm>
#include <array>
#include <map>
#include <string>
#include <vector>

#include <stout/error.hpp>
#include <stout/foreach.hpp>
#include <stout/none.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>

#include <stout/os/int_fd.hpp>
#include <stout/os/pipe.hpp>

#include <stout/os/windows/exec.hpp>

namespace os {
namespace Shell {

// Canonical constants used as platform-dependent args to `exec` calls.
// `name` is the command name, `arg0` is the first argument received
// by the callee, usually the command name and `arg1` is the second
// command argument received by the callee.
constexpr const char* name = "cmd.exe";
constexpr const char* arg0 = "cmd.exe";
constexpr const char* arg1 = "/c";

} // namespace Shell {

template <typename... T>
Try<std::string> shell(const std::string& fmt, const T&... t)
{
  using std::array;
  using std::string;
  using std::vector;

  const Try<string> command = strings::format(fmt, t...);
  if (command.isError()) {
    return Error(command.error());
  }

  // This function is intended to pass the arguments to the default
  // shell, so we first add the arguments `cmd.exe cmd.exe /c`,
  // followed by the command and arguments given.
  vector<string> args = {os::Shell::name, os::Shell::arg0, os::Shell::arg1};

  { // Minimize the lifetime of the system allocated buffer.
    //
    // NOTE: This API returns a pointer to an array of `wchar_t*`,
    // similar to `argv`. Each pointer to a null-terminated Unicode
    // string represents an individual argument found on the command
    // line. We use this because we cannot just split on whitespace.
    int argc;
    const std::unique_ptr<wchar_t*, decltype(&::LocalFree)> argv(
      ::CommandLineToArgvW(wide_stringify(command.get()).data(), &argc),
      &::LocalFree);
    if (argv == nullptr) {
      return WindowsError();
    }

    for (int i = 0; i < argc; ++i) {
      args.push_back(stringify(std::wstring(argv.get()[i])));
    }
  }

  // This function is intended to return only the `stdout` of the
  // command; but since we have to redirect all of `stdin`, `stdout`,
  // `stderr` if we want to redirect any one of them, we redirect
  // `stdin` and `stderr` to `NUL`, and `stdout` to a pipe.
  Try<int_fd> stdin_ = os::open(os::DEV_NULL, O_RDONLY);
  if (stdin_.isError()) {
    return Error(stdin_.error());
  }

  Try<array<int_fd, 2>> stdout_ = os::pipe();
  if (stdout_.isError()) {
    return Error(stdout_.error());
  }

  Try<int_fd> stderr_ = os::open(os::DEV_NULL, O_WRONLY);
  if (stderr_.isError()) {
    return Error(stderr_.error());
  }

  // Ensure the file descriptors are closed when we leave this scope.
  struct Closer
  {
    vector<int_fd> fds;
    ~Closer()
    {
      foreach (int_fd& fd, fds) {
        os::close(fd);
      }
    }
  } closer = {{stdin_.get(), stdout_.get()[0], stderr_.get()}};

  array<int_fd, 3> pipes = {stdin_.get(), stdout_.get()[1], stderr_.get()};

  using namespace os::windows::internal;

  Try<ProcessData> process_data =
    create_process(args.front(), args, None(), false, pipes);

  if (process_data.isError()) {
    return Error(process_data.error());
  }

  // Close the child end of the stdout pipe and then read until EOF.
  os::close(stdout_.get()[1]);
  string out;
  Result<string> part = None();
  do {
    part = os::read(stdout_.get()[0], 1024);
    if (part.isSome()) {
      out += part.get();
    }
  } while (part.isSome());

  // Wait for the process synchronously.
  ::WaitForSingleObject(process_data->process_handle.get_handle(), INFINITE);

  DWORD status;
  if (!::GetExitCodeProcess(
        process_data->process_handle.get_handle(), &status)) {
    return Error("Failed to `GetExitCodeProcess`: " + command.get());
  }

  if (status == 0) {
    return out;
  }

  return Error(
    "Failed to execute '" + command.get() +
    "'; the command was either "
    "not found or exited with a non-zero exit status: " +
    stringify(status));
}

inline Option<int> system(const std::string& command)
{
  return os::spawn(Shell::name, {Shell::arg0, Shell::arg1, command}, None());
}

} // namespace os {

#endif // __STOUT_OS_WINDOWS_SHELL_HPP__
<|endoftext|>