Blame glslang/MachineIndependent/preprocessor/PpTokens.cpp

Packit Service d7a8c4
//
Packit Service d7a8c4
// Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
Packit Service d7a8c4
// Copyright (C) 2013 LunarG, Inc.
Packit Service d7a8c4
// Copyright (C) 2015-2018 Google, Inc.
Packit Service d7a8c4
//
Packit Service d7a8c4
// All rights reserved.
Packit Service d7a8c4
//
Packit Service d7a8c4
// Redistribution and use in source and binary forms, with or without
Packit Service d7a8c4
// modification, are permitted provided that the following conditions
Packit Service d7a8c4
// are met:
Packit Service d7a8c4
//
Packit Service d7a8c4
//    Redistributions of source code must retain the above copyright
Packit Service d7a8c4
//    notice, this list of conditions and the following disclaimer.
Packit Service d7a8c4
//
Packit Service d7a8c4
//    Redistributions in binary form must reproduce the above
Packit Service d7a8c4
//    copyright notice, this list of conditions and the following
Packit Service d7a8c4
//    disclaimer in the documentation and/or other materials provided
Packit Service d7a8c4
//    with the distribution.
Packit Service d7a8c4
//
Packit Service d7a8c4
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
Packit Service d7a8c4
//    contributors may be used to endorse or promote products derived
Packit Service d7a8c4
//    from this software without specific prior written permission.
Packit Service d7a8c4
//
Packit Service d7a8c4
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service d7a8c4
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service d7a8c4
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit Service d7a8c4
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit Service d7a8c4
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit Service d7a8c4
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
Packit Service d7a8c4
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Packit Service d7a8c4
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
Packit Service d7a8c4
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit Service d7a8c4
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
Packit Service d7a8c4
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit Service d7a8c4
// POSSIBILITY OF SUCH DAMAGE.
Packit Service d7a8c4
//
Packit Service d7a8c4
/****************************************************************************\
Packit Service d7a8c4
Copyright (c) 2002, NVIDIA Corporation.
Packit Service d7a8c4
Packit Service d7a8c4
NVIDIA Corporation("NVIDIA") supplies this software to you in
Packit Service d7a8c4
consideration of your agreement to the following terms, and your use,
Packit Service d7a8c4
installation, modification or redistribution of this NVIDIA software
Packit Service d7a8c4
constitutes acceptance of these terms.  If you do not agree with these
Packit Service d7a8c4
terms, please do not use, install, modify or redistribute this NVIDIA
Packit Service d7a8c4
software.
Packit Service d7a8c4
Packit Service d7a8c4
In consideration of your agreement to abide by the following terms, and
Packit Service d7a8c4
subject to these terms, NVIDIA grants you a personal, non-exclusive
Packit Service d7a8c4
license, under NVIDIA's copyrights in this original NVIDIA software (the
Packit Service d7a8c4
"NVIDIA Software"), to use, reproduce, modify and redistribute the
Packit Service d7a8c4
NVIDIA Software, with or without modifications, in source and/or binary
Packit Service d7a8c4
forms; provided that if you redistribute the NVIDIA Software, you must
Packit Service d7a8c4
retain the copyright notice of NVIDIA, this notice and the following
Packit Service d7a8c4
text and disclaimers in all such redistributions of the NVIDIA Software.
Packit Service d7a8c4
Neither the name, trademarks, service marks nor logos of NVIDIA
Packit Service d7a8c4
Corporation may be used to endorse or promote products derived from the
Packit Service d7a8c4
NVIDIA Software without specific prior written permission from NVIDIA.
Packit Service d7a8c4
Except as expressly stated in this notice, no other rights or licenses
Packit Service d7a8c4
express or implied, are granted by NVIDIA herein, including but not
Packit Service d7a8c4
limited to any patent rights that may be infringed by your derivative
Packit Service d7a8c4
works or by other works in which the NVIDIA Software may be
Packit Service d7a8c4
incorporated. No hardware is licensed hereunder.
Packit Service d7a8c4
Packit Service d7a8c4
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
Packit Service d7a8c4
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
Packit Service d7a8c4
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
Packit Service d7a8c4
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
Packit Service d7a8c4
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
Packit Service d7a8c4
PRODUCTS.
Packit Service d7a8c4
Packit Service d7a8c4
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
Packit Service d7a8c4
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
Packit Service d7a8c4
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
Packit Service d7a8c4
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
Packit Service d7a8c4
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
Packit Service d7a8c4
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
Packit Service d7a8c4
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
Packit Service d7a8c4
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service d7a8c4
\****************************************************************************/
Packit Service d7a8c4
Packit Service d7a8c4
//
Packit Service d7a8c4
// For recording and playing back the stream of tokens in a macro definition.
Packit Service d7a8c4
//
Packit Service d7a8c4
Packit Service d7a8c4
#ifndef _CRT_SECURE_NO_WARNINGS
Packit Service d7a8c4
#define _CRT_SECURE_NO_WARNINGS
Packit Service d7a8c4
#endif
Packit Service d7a8c4
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
Packit Service d7a8c4
#define snprintf sprintf_s
Packit Service d7a8c4
#endif
Packit Service d7a8c4
Packit Service d7a8c4
#include <cassert>
Packit Service d7a8c4
#include <cstdlib>
Packit Service d7a8c4
#include <cstring>
Packit Service d7a8c4
#include <cctype>
Packit Service d7a8c4
Packit Service d7a8c4
#include "PpContext.h"
Packit Service d7a8c4
#include "PpTokens.h"
Packit Service d7a8c4
Packit Service d7a8c4
namespace glslang {
Packit Service d7a8c4
Packit Service d7a8c4
// Add a token (including backing string) to the end of a macro
Packit Service d7a8c4
// token stream, for later playback.
Packit Service d7a8c4
void TPpContext::TokenStream::putToken(int atom, TPpToken* ppToken)
Packit Service d7a8c4
{
Packit Service d7a8c4
    TokenStream::Token streamToken(atom, *ppToken);
Packit Service d7a8c4
    stream.push_back(streamToken);
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
// Read the next token from a macro token stream.
Packit Service d7a8c4
int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken)
Packit Service d7a8c4
{
Packit Service d7a8c4
    if (atEnd())
Packit Service d7a8c4
        return EndOfInput;
Packit Service d7a8c4
Packit Service d7a8c4
    int atom = stream[currentPos++].get(*ppToken);
Packit Service d7a8c4
    ppToken->loc = parseContext.getCurrentLoc();
Packit Service d7a8c4
Packit Service d7a8c4
#ifndef GLSLANG_WEB
Packit Service d7a8c4
    // Check for ##, unless the current # is the last character
Packit Service d7a8c4
    if (atom == '#') {
Packit Service d7a8c4
        if (peekToken('#')) {
Packit Service d7a8c4
            parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)");
Packit Service d7a8c4
            parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, 0, "token pasting (##)");
Packit Service d7a8c4
            currentPos++;
Packit Service d7a8c4
            atom = PpAtomPaste;
Packit Service d7a8c4
        }
Packit Service d7a8c4
    }
Packit Service d7a8c4
#endif
Packit Service d7a8c4
Packit Service d7a8c4
    return atom;
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
// We are pasting if
Packit Service d7a8c4
//   1. we are preceding a pasting operator within this stream
Packit Service d7a8c4
// or
Packit Service d7a8c4
//   2. the entire macro is preceding a pasting operator (lastTokenPastes)
Packit Service d7a8c4
//      and we are also on the last token
Packit Service d7a8c4
bool TPpContext::TokenStream::peekTokenizedPasting(bool lastTokenPastes)
Packit Service d7a8c4
{
Packit Service d7a8c4
    // 1. preceding ##?
Packit Service d7a8c4
Packit Service d7a8c4
    size_t savePos = currentPos;
Packit Service d7a8c4
    // skip white space
Packit Service d7a8c4
    while (peekToken(' '))
Packit Service d7a8c4
        ++currentPos;
Packit Service d7a8c4
    if (peekToken(PpAtomPaste)) {
Packit Service d7a8c4
        currentPos = savePos;
Packit Service d7a8c4
        return true;
Packit Service d7a8c4
    }
Packit Service d7a8c4
Packit Service d7a8c4
    // 2. last token and we've been told after this there will be a ##
Packit Service d7a8c4
Packit Service d7a8c4
    if (! lastTokenPastes)
Packit Service d7a8c4
        return false;
Packit Service d7a8c4
    // Getting here means the last token will be pasted, after this
Packit Service d7a8c4
Packit Service d7a8c4
    // Are we at the last non-whitespace token?
Packit Service d7a8c4
    savePos = currentPos;
Packit Service d7a8c4
    bool moreTokens = false;
Packit Service d7a8c4
    do {
Packit Service d7a8c4
        if (atEnd())
Packit Service d7a8c4
            break;
Packit Service d7a8c4
        if (!peekToken(' ')) {
Packit Service d7a8c4
            moreTokens = true;
Packit Service d7a8c4
            break;
Packit Service d7a8c4
        }
Packit Service d7a8c4
        ++currentPos;
Packit Service d7a8c4
    } while (true);
Packit Service d7a8c4
    currentPos = savePos;
Packit Service d7a8c4
Packit Service d7a8c4
    return !moreTokens;
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
// See if the next non-white-space tokens are two consecutive #
Packit Service d7a8c4
bool TPpContext::TokenStream::peekUntokenizedPasting()
Packit Service d7a8c4
{
Packit Service d7a8c4
    // don't return early, have to restore this
Packit Service d7a8c4
    size_t savePos = currentPos;
Packit Service d7a8c4
Packit Service d7a8c4
    // skip white-space
Packit Service d7a8c4
    while (peekToken(' '))
Packit Service d7a8c4
        ++currentPos;
Packit Service d7a8c4
Packit Service d7a8c4
    // check for ##
Packit Service d7a8c4
    bool pasting = false;
Packit Service d7a8c4
    if (peekToken('#')) {
Packit Service d7a8c4
        ++currentPos;
Packit Service d7a8c4
        if (peekToken('#'))
Packit Service d7a8c4
            pasting = true;
Packit Service d7a8c4
    }
Packit Service d7a8c4
Packit Service d7a8c4
    currentPos = savePos;
Packit Service d7a8c4
Packit Service d7a8c4
    return pasting;
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
void TPpContext::pushTokenStreamInput(TokenStream& ts, bool prepasting)
Packit Service d7a8c4
{
Packit Service d7a8c4
    pushInput(new tTokenInput(this, &ts, prepasting));
Packit Service d7a8c4
    ts.reset();
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken)
Packit Service d7a8c4
{
Packit Service d7a8c4
    if (done)
Packit Service d7a8c4
        return EndOfInput;
Packit Service d7a8c4
Packit Service d7a8c4
    int ret = token;
Packit Service d7a8c4
    *ppToken = lval;
Packit Service d7a8c4
    done = true;
Packit Service d7a8c4
Packit Service d7a8c4
    return ret;
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
void TPpContext::UngetToken(int token, TPpToken* ppToken)
Packit Service d7a8c4
{
Packit Service d7a8c4
    pushInput(new tUngotTokenInput(this, token, ppToken));
Packit Service d7a8c4
}
Packit Service d7a8c4
Packit Service d7a8c4
} // end namespace glslang