<commit_before>/*
    Title:      Address scanner

    Copyright (c) 2006 David C.J. Matthews

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/
#ifdef WIN32
#include "winconfig.h"
#else
#include "config.h"
#endif

#ifdef HAVE_ASSERT_H
#include <assert.h>
#define ASSERT(x) assert(x)
#else
#define ASSERT(x) 0
#endif

#include "globals.h"
#include "scanaddrs.h"
#include "machine_dep.h"
#include "check_objects.h"
#include "diagnostics.h"

// Process the value at a given location and update it as necessary.
POLYUNSIGNED ScanAddress::ScanAddressAt(PolyWord *pt)
{
    PolyWord val = *pt;
    if (IS_INT(val) || val == PolyWord::FromUnsigned(0))
    {
        // We can get zeros in the constant area if we garbage collect
        //  while compiling some code. */
    }
    else if (val.IsCodePtr())
    {
        // We can get code pointers either in the stack as return addresses or
        // handler pointers or in constants in code segments as the addresses of
        // exception handlers.

        // Find the start of the code segment
        PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject;
        // Mustn't use ScanAddressAt here.  That's only valid if the value points
        // into the area being updated.
        PolyObject *newObject = ScanObjectAddress(oldObject);
        *pt = PolyWord::FromCodePtr((byte*)newObject + offset);
    }
    else
    {
        ASSERT(OBJ_IS_DATAPTR(val));
        // Database pointer, local pointer or IO pointer.
        // We need to include IO area pointers when we produce an object module.
        *pt = ScanObjectAddress(val.AsObjPtr());
    }
    return 0;
}

// Process a value within the stack.
PolyWord ScanAddress::ScanStackAddress(PolyWord val, StackObject *base, bool isCode)
{
    PolyWord *end = (PolyWord*)base + base->Length();

    ASSERT(base->ContainsNormalLengthWord());
    ASSERT(base->IsStackObject());

    // If isCode is set we definitely have a code address.  It may have the
    // bottom bit set or it may be word aligned.
    if (isCode || val.IsCodePtr())
    {
        /* Find the start of the code segment */
        PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject;
        PolyObject *newObject = ScanObjectAddress(oldObject);
        return PolyWord::FromCodePtr((byte*)newObject + offset);
    }

    else if (val.IsTagged() || (val.AsAddress() > base && val.AsAddress() < end))
            /* We don't need to process tagged integers (now we've checked it isn't
               a code address) and we don't need to process addresses within the
               current stack.  If the containing stack has moved the stack addresses
               will have been updated by CopyStack. */
           return val;

    else
    {
        ASSERT(val.IsDataPtr());
        return ScanObjectAddress(val.AsObjPtr());
    }
}

// General purpose object processor,  Processes all the addresses in an object.
// Handles the various kinds of object that may contain addresses.
void ScanAddress::ScanAddressesInObject(PolyObject *obj, POLYUNSIGNED lengthWord)
{
    do
    {
        ASSERT (OBJ_IS_LENGTH(lengthWord));

        CheckObjectL (obj, lengthWord);

        if (OBJ_IS_BYTE_OBJECT(lengthWord))
            return; /* Nothing more to do */

        POLYUNSIGNED length = OBJ_OBJECT_LENGTH(lengthWord);
        PolyWord *baseAddr = (PolyWord*)obj;

        if (OBJ_IS_STACK_OBJECT(lengthWord))
        {
            StackObject *stack = (StackObject *) obj;
            PolyWord *stackPtr = stack->p_sp; // Save this BEFORE we update
            PolyWord *stackEnd = (PolyWord*)obj + length;

            // Either this is TAGGED(0) indicating a retry or it's a code pointer.
            if (stack->p_pc != TAGGED(0).AsCodePtr())
                stack->p_pc = ScanStackAddress (PolyWord::FromCodePtr(stack->p_pc), stack, true).AsCodePtr();

            // Stack pointer and handler pointers
            stack->p_sp =
                ScanStackAddress (PolyWord::FromStackAddr(stack->p_sp), stack, false).AsStackAddr();
            stack->p_hr =
                ScanStackAddress (PolyWord::FromStackAddr(stack->p_hr), stack, false).AsStackAddr();

            // The checked registers.
            for (POLYUNSIGNED i = 0; i < stack->p_nreg; i++)
                stack->p_reg[i] = ScanStackAddress(stack->p_reg[i], stack, false);

            // Now the values on the stack.
            for (PolyWord *q = stackPtr; q < stackEnd; q++)
                *q = ScanStackAddress(*q,stack, false);
            return; // We're done.
        }
        else if (OBJ_IS_CODE_OBJECT(lengthWord))
        {
            // Scan constants within the code.
            machineDependent->ScanConstantsWithinCode(obj, obj, length, this);

            // Skip to the constants and get ready to scan them.
            obj->GetConstSegmentForCode(length, baseAddr, length);

        } // else it's a normal object,

        PolyWord *endWord = baseAddr + length;

        // We want to minimise the actual recursion we preform so we try to
        // use tail recursion if we can.  We first scan from the end and
        // remove any words that don't need recursion.
        POLYUNSIGNED lastLengthWord = 0;
        while (endWord != baseAddr)
        {
            PolyWord wordAt = endWord[-1];
            if (IS_INT(wordAt) || wordAt == PolyWord::FromUnsigned(0))
                endWord--; // Don't need to look at this.
            else if ((lastLengthWord = ScanAddressAt(endWord-1)) != 0)
                // We need to process this one
                break;
            else endWord--; // We're not interested in this.
        }

        if (endWord == baseAddr)
            return; // We've done everything.

        // There is at least one word that needs to be processed, the
        // one at endWord-1.
        // Now process from the beginning forward to see if there are
        // any words before this that need to be handled.  This way we are more
        // likely to handle the head of a list by recursion and the
        // tail by looping (tail recursion).
        while (baseAddr < endWord-1)
        {
            PolyWord wordAt = *baseAddr;
            if (IS_INT(wordAt) || wordAt == PolyWord::FromUnsigned(0))
                baseAddr++; // Don't need to look at this.
            else
            {
                POLYUNSIGNED lengthWord = ScanAddressAt(baseAddr);
                if (lengthWord != 0)
                {
                    wordAt = *baseAddr; // Reload because it may have been side-effected
                     // We really have to process this recursively.
                    if (wordAt.IsCodePtr())
                        ScanAddressesInObject(ObjCodePtrToPtr(wordAt.AsCodePtr()), lengthWord);
                    else
                        ScanAddressesInObject(wordAt.AsObjPtr(), lengthWord);
                    baseAddr++;
                }
                else baseAddr++;
            }
        }

        // Finally process the last word we found that has to be processed.
        // Do this by looping rather than recursion.
        PolyWord wordAt = *baseAddr; // Last word to do.
        // This must be an address
        if (wordAt.IsCodePtr())
            obj = ObjCodePtrToPtr(wordAt.AsCodePtr());
        else
            obj = wordAt.AsObjPtr();

        lengthWord = lastLengthWord;

    } while(1);
}

void ScanAddress::ScanAddressesInRegion(PolyWord *region, POLYUNSIGNED length)
{
    PolyWord *end = region + length;
    PolyWord *pt = region;
    while (pt < end)
    {
        pt++; // Skip length word.
        // pt actually points AT the object here.
        PolyObject *obj = (PolyObject*)pt;
        if (obj->ContainsForwardingPtr())    /* skip over moved object */
        {
            // We can now get multiple forwarding pointers as a result
            // of applying ShareData repeatedly.  Perhaps we should
            // turn the forwarding pointers back into normal words in
            // an extra pass.
            while (obj->ContainsForwardingPtr())
                obj = obj->GetForwardingPtr();
            ASSERT(obj->ContainsNormalLengthWord());
            CheckObject(obj);
            pt += obj->Length();
        }
        else
        {
            ASSERT(obj->ContainsNormalLengthWord());
            POLYUNSIGNED length = obj->Length();
            if (pt+length > end)
                Crash("Malformed object at %p - length %lu\n", pt, length);
            if (length != 0)
                ScanAddressesInObject(obj);
            pt += length;
        }
    }
}

// Extract a constant from the code.
PolyWord ScanAddress::GetConstantValue(byte *addressOfConstant, ScanRelocationKind code)
{
    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 or 64 bit address of target
        {
            POLYUNSIGNED valu;
            unsigned i;
            byte *pt = addressOfConstant;
            if (*pt & 0x80) valu = 0-1; else valu = 0;
            for (i = sizeof(PolyWord); i > 0; i--)
                valu = (valu << 8) | pt[i-1];

            /* The old code generator generated reverse subtraction
               of words using a move immediate which loaded a register
               with a the tagged value plus one.  In practice the only
               reverse subtraction of a constant is 0-x so for backwards
               compatibility we need to treat 2 specially. */
            ASSERT(valu != 2);

            return PolyWord::FromUnsigned(valu);
        }
    case PROCESS_RELOC_I386RELATIVE:         // 32 or 64 bit relative address
        {
            POLYSIGNED disp;
            byte *pt = addressOfConstant;
            // Get the displacement. This is signed.
            if (*pt & 0x80) disp = -1; else disp = 0; // Set the sign just in case.
            for(unsigned i = sizeof(PolyWord); i > 0; i--) disp = (disp << 8) | pt[i-1];

            byte *absAddr = pt + disp + sizeof(PolyWord); // The address is relative to AFTER the constant

            return PolyWord::FromCodePtr(absAddr);
        }
    case PROCESS_RELOC_PPCDUAL16SIGNED:       // Power PC - two consecutive words
    case PROCESS_RELOC_PPCDUAL16UNSIGNED:
        {
            // The second word may be a sign-extending "add" instruction or
            // a non-signing extending "or" instruction.
            bool isSigned = code == PROCESS_RELOC_PPCDUAL16SIGNED;
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            // Put together the two halves.
            POLYUNSIGNED hi = pt[0] & 0xffff;
            POLYUNSIGNED lo = pt[1] & 0xffff;
            if (lo >= 32768 && isSigned) hi--; // Correct for sign extension.

            return PolyWord::FromUnsigned((hi << 16) + lo);
        }
    case PROCESS_RELOC_SPARCDUAL:  // Sparc - Sethi and Add instruction pair.
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            // Put together the two halves.
            POLYUNSIGNED valu = (pt[0] << 10) | (pt[1] & 0x3ff);
            return PolyWord::FromUnsigned(valu);
        }
    case PROCESS_RELOC_SPARCRELATIVE: // Call instruction with 30-bit word displacement
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYSIGNED disp = (*pt) & 0x3fffffff;
            // This will work on a 32-bit machine because shifting the 30 bits will set the
            // sign bit.
            return PolyWord::FromStackAddr((PolyWord*)pt + disp);
        }
    default:
        ASSERT(false);
        return TAGGED(0);
    }
}

// Store a constant value.  Also used with a patch table when importing a saved heap which has
// been exported using the C exporter.
void ScanAddress::SetConstantValue(byte *addressOfConstant, PolyWord p, ScanRelocationKind code)
{

    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 or 64 bit address of target
        {
            POLYUNSIGNED valu = p.AsUnsigned();
            for (unsigned i = 0; i < sizeof(PolyWord); i++)
            {
                addressOfConstant[i] = (byte)(valu & 255);
                valu >>= 8;
            }
        }
        break;
    case PROCESS_RELOC_I386RELATIVE:         // 32 or 64 bit relative address
        {
            POLYSIGNED newDisp = p.AsCodePtr() - addressOfConstant - sizeof(PolyWord);
            for (unsigned i = 0; i < sizeof(PolyWord); i++) {
                addressOfConstant[i] = (byte)(newDisp & 0xff);
                newDisp >>= 8;
            }
        }
        break;
    case PROCESS_RELOC_PPCDUAL16SIGNED:       // Power PC - two consecutive words
    case PROCESS_RELOC_PPCDUAL16UNSIGNED:
        {
            // The second word may be a sign-extending "add" instruction or
            // a non-signing extending "or" instruction.
            bool isSigned = code == PROCESS_RELOC_PPCDUAL16SIGNED;
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYUNSIGNED hi = p.AsUnsigned() >> 16;
            POLYUNSIGNED lo = p.AsUnsigned() & 0xffff;
            if ((lo & 0x8000) && isSigned) hi++; // Adjust the for sign extension.
            pt[0] = (pt[0] & 0xffff0000) | hi;
            pt[1] = (pt[1] & 0xffff0000) | lo;
        }
        break;
    case PROCESS_RELOC_SPARCDUAL:           // Sparc - SETHI has top 22 bits, ADD has low 10 bits.
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYUNSIGNED valu = p.AsUnsigned();
            pt[0] = (pt[0] & 0xffc00000) | (valu >> 10);
            pt[1] = (pt[1] & 0xfffff000) | (valu & 0x3ff);
        }
        break;
    case PROCESS_RELOC_SPARCRELATIVE: // Call instruction with 30-bit word displacement
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYSIGNED newDisp = p.AsStackAddr() - (PolyWord*)addressOfConstant;
            *pt = (newDisp & 0x3fffffff) | 0x40000000;
        }
        break;
    }
}

// The default action is to call the DEFAULT ScanAddressAt NOT the virtual which means that it calls
// ScanObjectAddress for the base address of the object referred to.
void ScanAddress::ScanConstant(byte *addressOfConstant, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addressOfConstant, code);

    if (! IS_INT(p))
    {
        PolyWord oldValue = p;
        ScanAddress::ScanAddressAt(&p);
        if (p != oldValue) // Update it if it has changed.
            SetConstantValue(addressOfConstant, p, code);
    }
}

<commit_msg>When checking a pointer within a stack object include the possibility that it may be equal to the end of the stack.  This can occur, at least on the Sparc, in the stack of a thread after it has called kill_self.<commit_after>/*
    Title:      Address scanner

    Copyright (c) 2006 David C.J. Matthews

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/
#ifdef WIN32
#include "winconfig.h"
#else
#include "config.h"
#endif

#ifdef HAVE_ASSERT_H
#include <assert.h>
#define ASSERT(x) assert(x)
#else
#define ASSERT(x) 0
#endif

#include "globals.h"
#include "scanaddrs.h"
#include "machine_dep.h"
#include "check_objects.h"
#include "diagnostics.h"

// Process the value at a given location and update it as necessary.
POLYUNSIGNED ScanAddress::ScanAddressAt(PolyWord *pt)
{
    PolyWord val = *pt;
    if (IS_INT(val) || val == PolyWord::FromUnsigned(0))
    {
        // We can get zeros in the constant area if we garbage collect
        //  while compiling some code. */
    }
    else if (val.IsCodePtr())
    {
        // We can get code pointers either in the stack as return addresses or
        // handler pointers or in constants in code segments as the addresses of
        // exception handlers.

        // Find the start of the code segment
        PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject;
        // Mustn't use ScanAddressAt here.  That's only valid if the value points
        // into the area being updated.
        PolyObject *newObject = ScanObjectAddress(oldObject);
        *pt = PolyWord::FromCodePtr((byte*)newObject + offset);
    }
    else
    {
        ASSERT(OBJ_IS_DATAPTR(val));
        // Database pointer, local pointer or IO pointer.
        // We need to include IO area pointers when we produce an object module.
        *pt = ScanObjectAddress(val.AsObjPtr());
    }
    return 0;
}

// Process a value within the stack.
PolyWord ScanAddress::ScanStackAddress(PolyWord val, StackObject *base, bool isCode)
{
    PolyWord *end = (PolyWord*)base + base->Length();

    ASSERT(base->ContainsNormalLengthWord());
    ASSERT(base->IsStackObject());

    // If isCode is set we definitely have a code address.  It may have the
    // bottom bit set or it may be word aligned.
    if (isCode || val.IsCodePtr())
    {
        /* Find the start of the code segment */
        PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject;
        PolyObject *newObject = ScanObjectAddress(oldObject);
        return PolyWord::FromCodePtr((byte*)newObject + offset);
    }

    else if (val.IsTagged() || (val.AsAddress() > base && val.AsAddress() <= end))
            /* We don't need to process tagged integers (now we've checked it isn't
               a code address) and we don't need to process addresses within the
               current stack.  If the containing stack has moved the stack addresses
               will have been updated by CopyStack. */
            /* N.B. We have "<= end" rather than "< end" because it is possible for
               the stack to be completely empty on a terminated thread. */
           return val;

    else
    {
        ASSERT(val.IsDataPtr());
        return ScanObjectAddress(val.AsObjPtr());
    }
}

// General purpose object processor,  Processes all the addresses in an object.
// Handles the various kinds of object that may contain addresses.
void ScanAddress::ScanAddressesInObject(PolyObject *obj, POLYUNSIGNED lengthWord)
{
    do
    {
        ASSERT (OBJ_IS_LENGTH(lengthWord));

        CheckObjectL (obj, lengthWord);

        if (OBJ_IS_BYTE_OBJECT(lengthWord))
            return; /* Nothing more to do */

        POLYUNSIGNED length = OBJ_OBJECT_LENGTH(lengthWord);
        PolyWord *baseAddr = (PolyWord*)obj;

        if (OBJ_IS_STACK_OBJECT(lengthWord))
        {
            StackObject *stack = (StackObject *) obj;
            PolyWord *stackPtr = stack->p_sp; // Save this BEFORE we update
            PolyWord *stackEnd = (PolyWord*)obj + length;

            // Either this is TAGGED(0) indicating a retry or it's a code pointer.
            if (stack->p_pc != TAGGED(0).AsCodePtr())
                stack->p_pc = ScanStackAddress (PolyWord::FromCodePtr(stack->p_pc), stack, true).AsCodePtr();

            // Stack pointer and handler pointers
            stack->p_sp =
                ScanStackAddress (PolyWord::FromStackAddr(stack->p_sp), stack, false).AsStackAddr();
            stack->p_hr =
                ScanStackAddress (PolyWord::FromStackAddr(stack->p_hr), stack, false).AsStackAddr();

            // The checked registers.
            for (POLYUNSIGNED i = 0; i < stack->p_nreg; i++)
                stack->p_reg[i] = ScanStackAddress(stack->p_reg[i], stack, false);

            // Now the values on the stack.
            for (PolyWord *q = stackPtr; q < stackEnd; q++)
                *q = ScanStackAddress(*q,stack, false);
            return; // We're done.
        }
        else if (OBJ_IS_CODE_OBJECT(lengthWord))
        {
            // Scan constants within the code.
            machineDependent->ScanConstantsWithinCode(obj, obj, length, this);

            // Skip to the constants and get ready to scan them.
            obj->GetConstSegmentForCode(length, baseAddr, length);

        } // else it's a normal object,

        PolyWord *endWord = baseAddr + length;

        // We want to minimise the actual recursion we preform so we try to
        // use tail recursion if we can.  We first scan from the end and
        // remove any words that don't need recursion.
        POLYUNSIGNED lastLengthWord = 0;
        while (endWord != baseAddr)
        {
            PolyWord wordAt = endWord[-1];
            if (IS_INT(wordAt) || wordAt == PolyWord::FromUnsigned(0))
                endWord--; // Don't need to look at this.
            else if ((lastLengthWord = ScanAddressAt(endWord-1)) != 0)
                // We need to process this one
                break;
            else endWord--; // We're not interested in this.
        }

        if (endWord == baseAddr)
            return; // We've done everything.

        // There is at least one word that needs to be processed, the
        // one at endWord-1.
        // Now process from the beginning forward to see if there are
        // any words before this that need to be handled.  This way we are more
        // likely to handle the head of a list by recursion and the
        // tail by looping (tail recursion).
        while (baseAddr < endWord-1)
        {
            PolyWord wordAt = *baseAddr;
            if (IS_INT(wordAt) || wordAt == PolyWord::FromUnsigned(0))
                baseAddr++; // Don't need to look at this.
            else
            {
                POLYUNSIGNED lengthWord = ScanAddressAt(baseAddr);
                if (lengthWord != 0)
                {
                    wordAt = *baseAddr; // Reload because it may have been side-effected
                     // We really have to process this recursively.
                    if (wordAt.IsCodePtr())
                        ScanAddressesInObject(ObjCodePtrToPtr(wordAt.AsCodePtr()), lengthWord);
                    else
                        ScanAddressesInObject(wordAt.AsObjPtr(), lengthWord);
                    baseAddr++;
                }
                else baseAddr++;
            }
        }

        // Finally process the last word we found that has to be processed.
        // Do this by looping rather than recursion.
        PolyWord wordAt = *baseAddr; // Last word to do.
        // This must be an address
        if (wordAt.IsCodePtr())
            obj = ObjCodePtrToPtr(wordAt.AsCodePtr());
        else
            obj = wordAt.AsObjPtr();

        lengthWord = lastLengthWord;

    } while(1);
}

void ScanAddress::ScanAddressesInRegion(PolyWord *region, POLYUNSIGNED length)
{
    PolyWord *end = region + length;
    PolyWord *pt = region;
    while (pt < end)
    {
        pt++; // Skip length word.
        // pt actually points AT the object here.
        PolyObject *obj = (PolyObject*)pt;
        if (obj->ContainsForwardingPtr())    /* skip over moved object */
        {
            // We can now get multiple forwarding pointers as a result
            // of applying ShareData repeatedly.  Perhaps we should
            // turn the forwarding pointers back into normal words in
            // an extra pass.
            while (obj->ContainsForwardingPtr())
                obj = obj->GetForwardingPtr();
            ASSERT(obj->ContainsNormalLengthWord());
            CheckObject(obj);
            pt += obj->Length();
        }
        else
        {
            ASSERT(obj->ContainsNormalLengthWord());
            POLYUNSIGNED length = obj->Length();
            if (pt+length > end)
                Crash("Malformed object at %p - length %lu\n", pt, length);
            if (length != 0)
                ScanAddressesInObject(obj);
            pt += length;
        }
    }
}

// Extract a constant from the code.
PolyWord ScanAddress::GetConstantValue(byte *addressOfConstant, ScanRelocationKind code)
{
    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 or 64 bit address of target
        {
            POLYUNSIGNED valu;
            unsigned i;
            byte *pt = addressOfConstant;
            if (*pt & 0x80) valu = 0-1; else valu = 0;
            for (i = sizeof(PolyWord); i > 0; i--)
                valu = (valu << 8) | pt[i-1];

            /* The old code generator generated reverse subtraction
               of words using a move immediate which loaded a register
               with a the tagged value plus one.  In practice the only
               reverse subtraction of a constant is 0-x so for backwards
               compatibility we need to treat 2 specially. */
            ASSERT(valu != 2);

            return PolyWord::FromUnsigned(valu);
        }
    case PROCESS_RELOC_I386RELATIVE:         // 32 or 64 bit relative address
        {
            POLYSIGNED disp;
            byte *pt = addressOfConstant;
            // Get the displacement. This is signed.
            if (*pt & 0x80) disp = -1; else disp = 0; // Set the sign just in case.
            for(unsigned i = sizeof(PolyWord); i > 0; i--) disp = (disp << 8) | pt[i-1];

            byte *absAddr = pt + disp + sizeof(PolyWord); // The address is relative to AFTER the constant

            return PolyWord::FromCodePtr(absAddr);
        }
    case PROCESS_RELOC_PPCDUAL16SIGNED:       // Power PC - two consecutive words
    case PROCESS_RELOC_PPCDUAL16UNSIGNED:
        {
            // The second word may be a sign-extending "add" instruction or
            // a non-signing extending "or" instruction.
            bool isSigned = code == PROCESS_RELOC_PPCDUAL16SIGNED;
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            // Put together the two halves.
            POLYUNSIGNED hi = pt[0] & 0xffff;
            POLYUNSIGNED lo = pt[1] & 0xffff;
            if (lo >= 32768 && isSigned) hi--; // Correct for sign extension.

            return PolyWord::FromUnsigned((hi << 16) + lo);
        }
    case PROCESS_RELOC_SPARCDUAL:  // Sparc - Sethi and Add instruction pair.
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            // Put together the two halves.
            POLYUNSIGNED valu = (pt[0] << 10) | (pt[1] & 0x3ff);
            return PolyWord::FromUnsigned(valu);
        }
    case PROCESS_RELOC_SPARCRELATIVE: // Call instruction with 30-bit word displacement
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYSIGNED disp = (*pt) & 0x3fffffff;
            // This will work on a 32-bit machine because shifting the 30 bits will set the
            // sign bit.
            return PolyWord::FromStackAddr((PolyWord*)pt + disp);
        }
    default:
        ASSERT(false);
        return TAGGED(0);
    }
}

// Store a constant value.  Also used with a patch table when importing a saved heap which has
// been exported using the C exporter.
void ScanAddress::SetConstantValue(byte *addressOfConstant, PolyWord p, ScanRelocationKind code)
{

    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 or 64 bit address of target
        {
            POLYUNSIGNED valu = p.AsUnsigned();
            for (unsigned i = 0; i < sizeof(PolyWord); i++)
            {
                addressOfConstant[i] = (byte)(valu & 255);
                valu >>= 8;
            }
        }
        break;
    case PROCESS_RELOC_I386RELATIVE:         // 32 or 64 bit relative address
        {
            POLYSIGNED newDisp = p.AsCodePtr() - addressOfConstant - sizeof(PolyWord);
            for (unsigned i = 0; i < sizeof(PolyWord); i++) {
                addressOfConstant[i] = (byte)(newDisp & 0xff);
                newDisp >>= 8;
            }
        }
        break;
    case PROCESS_RELOC_PPCDUAL16SIGNED:       // Power PC - two consecutive words
    case PROCESS_RELOC_PPCDUAL16UNSIGNED:
        {
            // The second word may be a sign-extending "add" instruction or
            // a non-signing extending "or" instruction.
            bool isSigned = code == PROCESS_RELOC_PPCDUAL16SIGNED;
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYUNSIGNED hi = p.AsUnsigned() >> 16;
            POLYUNSIGNED lo = p.AsUnsigned() & 0xffff;
            if ((lo & 0x8000) && isSigned) hi++; // Adjust the for sign extension.
            pt[0] = (pt[0] & 0xffff0000) | hi;
            pt[1] = (pt[1] & 0xffff0000) | lo;
        }
        break;
    case PROCESS_RELOC_SPARCDUAL:           // Sparc - SETHI has top 22 bits, ADD has low 10 bits.
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYUNSIGNED valu = p.AsUnsigned();
            pt[0] = (pt[0] & 0xffc00000) | (valu >> 10);
            pt[1] = (pt[1] & 0xfffff000) | (valu & 0x3ff);
        }
        break;
    case PROCESS_RELOC_SPARCRELATIVE: // Call instruction with 30-bit word displacement
        {
            POLYUNSIGNED *pt = (POLYUNSIGNED *)addressOfConstant;
            POLYSIGNED newDisp = p.AsStackAddr() - (PolyWord*)addressOfConstant;
            *pt = (newDisp & 0x3fffffff) | 0x40000000;
        }
        break;
    }
}

// The default action is to call the DEFAULT ScanAddressAt NOT the virtual which means that it calls
// ScanObjectAddress for the base address of the object referred to.
void ScanAddress::ScanConstant(byte *addressOfConstant, ScanRelocationKind code)
{
    PolyWord p = GetConstantValue(addressOfConstant, code);

    if (! IS_INT(p))
    {
        PolyWord oldValue = p;
        ScanAddress::ScanAddressAt(&p);
        if (p != oldValue) // Update it if it has changed.
            SetConstantValue(addressOfConstant, p, code);
    }
}

<|endoftext|>


<commit_before>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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.
 *
 */

#include <map>

#include "config.h"
#include "generator_helpers.h"
#include "node_generator.h"
#include "node_generator_helpers.h"

using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;

namespace grpc_node_generator {
namespace {

// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
  // This scheme could technically cause problems if a file includes any 2 of:
  //   foo/bar_baz.proto
  //   foo_bar_baz.proto
  //   foo_bar/baz.proto
  //
  // We'll worry about this problem if/when we actually see it.  This name isn't
  // exposed to users so we can change it later if we need to.
  grpc::string basename = grpc_generator::StripProto(filename);
  basename = grpc_generator::StringReplace(basename, "-", "$");
  basename = grpc_generator::StringReplace(basename, "/", "_");
  basename = grpc_generator::StringReplace(basename, ".", "_");
  return basename + "_pb";
}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
  grpc::string name = filename;
  return grpc_generator::StripProto(name) + "_pb.js";
}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
                         const grpc::string& to_filename) {
  if (to_filename.find("google/protobuf") == 0) {
    // Well-known types (.proto files in the google/protobuf directory) are
    // assumed to come from the 'google-protobuf' npm package.  We may want to
    // generalize this exception later by letting others put generated code in
    // their own npm packages.
    return "google-protobuf/";
  }
  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
  if (slashes == 0) {
    return "./";
  }
  grpc::string result = "";
  for (size_t i = 0; i < slashes; i++) {
    result += "../";
  }
  return result;
}

// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
                             const grpc::string& to_file) {
  return GetRootPath(from_file, to_file) + to_file;
}

/* Finds all message types used in all services in the file, and returns them
 * as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(
    const FileDescriptor* file) {
  map<grpc::string, const Descriptor*> message_types;
  for (int service_num = 0; service_num < file->service_count();
       service_num++) {
    const ServiceDescriptor* service = file->service(service_num);
    for (int method_num = 0; method_num < service->method_count();
         method_num++) {
      const MethodDescriptor* method = service->method(method_num);
      const Descriptor* input_type = method->input_type();
      const Descriptor* output_type = method->output_type();
      message_types[input_type->full_name()] = input_type;
      message_types[output_type->full_name()] = output_type;
    }
  }
  return message_types;
}

grpc::string MessageIdentifierName(const grpc::string& name) {
  return grpc_generator::StringReplace(name, ".", "_");
}

grpc::string NodeObjectPath(const Descriptor* descriptor) {
  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
  grpc::string name = descriptor->full_name();
  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
  return module_alias + "." + name;
}

// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor* descriptor, Printer* out,
                             const Parameters& params) {
  map<grpc::string, grpc::string> template_vars;
  grpc::string full_name = descriptor->full_name();
  template_vars["identifier_name"] = MessageIdentifierName(full_name);
  template_vars["name"] = full_name;
  template_vars["node_name"] = NodeObjectPath(descriptor);
  // Print the serializer
  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
  out->Indent();
  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
  out->Indent();
  out->Print(template_vars,
             "throw new Error('Expected argument of type $name$');\n");
  out->Outdent();
  out->Print("}\n");
  if (params.minimum_node_version > 5) {
    // Node version is > 5, we should use Buffer.from
    out->Print("return Buffer.from(arg.serializeBinary());\n");
  } else {
    out->Print("return new Buffer(arg.serializeBinary());\n");
  }
  out->Outdent();
  out->Print("}\n\n");

  // Print the deserializer
  out->Print(template_vars,
             "function deserialize_$identifier_name$(buffer_arg) {\n");
  out->Indent();
  out->Print(
      template_vars,
      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
  out->Outdent();
  out->Print("}\n\n");
}

void PrintMethod(const MethodDescriptor* method, Printer* out) {
  const Descriptor* input_type = method->input_type();
  const Descriptor* output_type = method->output_type();
  map<grpc::string, grpc::string> vars;
  vars["service_name"] = method->service()->full_name();
  vars["name"] = method->name();
  vars["input_type"] = NodeObjectPath(input_type);
  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
  vars["output_type"] = NodeObjectPath(output_type);
  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
  vars["client_stream"] = method->client_streaming() ? "true" : "false";
  vars["server_stream"] = method->server_streaming() ? "true" : "false";
  out->Print("{\n");
  out->Indent();
  out->Print(vars, "path: '/$service_name$/$name$',\n");
  out->Print(vars, "requestStream: $client_stream$,\n");
  out->Print(vars, "responseStream: $server_stream$,\n");
  out->Print(vars, "requestType: $input_type$,\n");
  out->Print(vars, "responseType: $output_type$,\n");
  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
  out->Outdent();
  out->Print("}");
}

// Prints out the service descriptor object
void PrintService(const ServiceDescriptor* service, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  out->Print(GetNodeComments(service, true).c_str());
  template_vars["name"] = service->name();
  out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
  out->Indent();
  for (int i = 0; i < service->method_count(); i++) {
    grpc::string method_name =
        grpc_generator::LowercaseFirstLetter(service->method(i)->name());
    out->Print(GetNodeComments(service->method(i), true).c_str());
    out->Print("$method_name$: ", "method_name", method_name);
    PrintMethod(service->method(i), out);
    out->Print(",\n");
    out->Print(GetNodeComments(service->method(i), false).c_str());
  }
  out->Outdent();
  out->Print("};\n\n");
  out->Print(template_vars,
             "exports.$name$Client = "
             "grpc.makeGenericClientConstructor($name$Service);\n");
  out->Print(GetNodeComments(service, false).c_str());
}

void PrintImports(const FileDescriptor* file, Printer* out) {
  out->Print("var grpc = require('grpc');\n");
  if (file->message_type_count() > 0) {
    grpc::string file_path =
        GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->name()), "file_path", file_path);
  }

  for (int i = 0; i < file->dependency_count(); i++) {
    grpc::string file_path = GetRelativePath(
        file->name(), GetJSMessageFilename(file->dependency(i)->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->dependency(i)->name()), "file_path",
               file_path);
  }
  out->Print("\n");
}

void PrintTransformers(const FileDescriptor* file, Printer* out,
                       const Parameters& params) {
  map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
  for (std::map<grpc::string, const Descriptor*>::iterator it =
           messages.begin();
       it != messages.end(); it++) {
    PrintMessageTransformer(it->second, out, params);
  }
  out->Print("\n");
}

void PrintServices(const FileDescriptor* file, Printer* out) {
  for (int i = 0; i < file->service_count(); i++) {
    PrintService(file->service(i), out);
  }
}
}  // namespace

grpc::string GenerateFile(const FileDescriptor* file,
                          const Parameters& params) {
  grpc::string output;
  {
    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    if (file->service_count() == 0) {
      return output;
    }
    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");

    grpc::string leading_comments = GetNodeComments(file, true);
    if (!leading_comments.empty()) {
      out.Print("// Original file comments:\n");
      out.PrintRaw(leading_comments.c_str());
    }

    out.Print("'use strict';\n");

    PrintImports(file, &out);

    PrintTransformers(file, &out, params);

    PrintServices(file, &out);

    out.Print(GetNodeComments(file, false).c_str());
  }
  return output;
}

}  // namespace grpc_node_generator
<commit_msg>Generate JS file even if no services are defined in proto file; fix #574<commit_after>/*
 *
 * Copyright 2016 gRPC authors.
 *
 * 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.
 *
 */

#include <map>

#include "config.h"
#include "generator_helpers.h"
#include "node_generator.h"
#include "node_generator_helpers.h"

using grpc::protobuf::Descriptor;
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;

namespace grpc_node_generator {
namespace {

// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
  // This scheme could technically cause problems if a file includes any 2 of:
  //   foo/bar_baz.proto
  //   foo_bar_baz.proto
  //   foo_bar/baz.proto
  //
  // We'll worry about this problem if/when we actually see it.  This name isn't
  // exposed to users so we can change it later if we need to.
  grpc::string basename = grpc_generator::StripProto(filename);
  basename = grpc_generator::StringReplace(basename, "-", "$");
  basename = grpc_generator::StringReplace(basename, "/", "_");
  basename = grpc_generator::StringReplace(basename, ".", "_");
  return basename + "_pb";
}

// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
  grpc::string name = filename;
  return grpc_generator::StripProto(name) + "_pb.js";
}

// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& from_filename,
                         const grpc::string& to_filename) {
  if (to_filename.find("google/protobuf") == 0) {
    // Well-known types (.proto files in the google/protobuf directory) are
    // assumed to come from the 'google-protobuf' npm package.  We may want to
    // generalize this exception later by letting others put generated code in
    // their own npm packages.
    return "google-protobuf/";
  }
  size_t slashes = std::count(from_filename.begin(), from_filename.end(), '/');
  if (slashes == 0) {
    return "./";
  }
  grpc::string result = "";
  for (size_t i = 0; i < slashes; i++) {
    result += "../";
  }
  return result;
}

// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
                             const grpc::string& to_file) {
  return GetRootPath(from_file, to_file) + to_file;
}

/* Finds all message types used in all services in the file, and returns them
 * as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(
    const FileDescriptor* file) {
  map<grpc::string, const Descriptor*> message_types;
  for (int service_num = 0; service_num < file->service_count();
       service_num++) {
    const ServiceDescriptor* service = file->service(service_num);
    for (int method_num = 0; method_num < service->method_count();
         method_num++) {
      const MethodDescriptor* method = service->method(method_num);
      const Descriptor* input_type = method->input_type();
      const Descriptor* output_type = method->output_type();
      message_types[input_type->full_name()] = input_type;
      message_types[output_type->full_name()] = output_type;
    }
  }
  return message_types;
}

grpc::string MessageIdentifierName(const grpc::string& name) {
  return grpc_generator::StringReplace(name, ".", "_");
}

grpc::string NodeObjectPath(const Descriptor* descriptor) {
  grpc::string module_alias = ModuleAlias(descriptor->file()->name());
  grpc::string name = descriptor->full_name();
  grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
  return module_alias + "." + name;
}

// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor* descriptor, Printer* out,
                             const Parameters& params) {
  map<grpc::string, grpc::string> template_vars;
  grpc::string full_name = descriptor->full_name();
  template_vars["identifier_name"] = MessageIdentifierName(full_name);
  template_vars["name"] = full_name;
  template_vars["node_name"] = NodeObjectPath(descriptor);
  // Print the serializer
  out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
  out->Indent();
  out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
  out->Indent();
  out->Print(template_vars,
             "throw new Error('Expected argument of type $name$');\n");
  out->Outdent();
  out->Print("}\n");
  if (params.minimum_node_version > 5) {
    // Node version is > 5, we should use Buffer.from
    out->Print("return Buffer.from(arg.serializeBinary());\n");
  } else {
    out->Print("return new Buffer(arg.serializeBinary());\n");
  }
  out->Outdent();
  out->Print("}\n\n");

  // Print the deserializer
  out->Print(template_vars,
             "function deserialize_$identifier_name$(buffer_arg) {\n");
  out->Indent();
  out->Print(
      template_vars,
      "return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
  out->Outdent();
  out->Print("}\n\n");
}

void PrintMethod(const MethodDescriptor* method, Printer* out) {
  const Descriptor* input_type = method->input_type();
  const Descriptor* output_type = method->output_type();
  map<grpc::string, grpc::string> vars;
  vars["service_name"] = method->service()->full_name();
  vars["name"] = method->name();
  vars["input_type"] = NodeObjectPath(input_type);
  vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
  vars["output_type"] = NodeObjectPath(output_type);
  vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
  vars["client_stream"] = method->client_streaming() ? "true" : "false";
  vars["server_stream"] = method->server_streaming() ? "true" : "false";
  out->Print("{\n");
  out->Indent();
  out->Print(vars, "path: '/$service_name$/$name$',\n");
  out->Print(vars, "requestStream: $client_stream$,\n");
  out->Print(vars, "responseStream: $server_stream$,\n");
  out->Print(vars, "requestType: $input_type$,\n");
  out->Print(vars, "responseType: $output_type$,\n");
  out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
  out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
  out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
  out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
  out->Outdent();
  out->Print("}");
}

// Prints out the service descriptor object
void PrintService(const ServiceDescriptor* service, Printer* out) {
  map<grpc::string, grpc::string> template_vars;
  out->Print(GetNodeComments(service, true).c_str());
  template_vars["name"] = service->name();
  out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
  out->Indent();
  for (int i = 0; i < service->method_count(); i++) {
    grpc::string method_name =
        grpc_generator::LowercaseFirstLetter(service->method(i)->name());
    out->Print(GetNodeComments(service->method(i), true).c_str());
    out->Print("$method_name$: ", "method_name", method_name);
    PrintMethod(service->method(i), out);
    out->Print(",\n");
    out->Print(GetNodeComments(service->method(i), false).c_str());
  }
  out->Outdent();
  out->Print("};\n\n");
  out->Print(template_vars,
             "exports.$name$Client = "
             "grpc.makeGenericClientConstructor($name$Service);\n");
  out->Print(GetNodeComments(service, false).c_str());
}

void PrintImports(const FileDescriptor* file, Printer* out) {
  out->Print("var grpc = require('grpc');\n");
  if (file->message_type_count() > 0) {
    grpc::string file_path =
        GetRelativePath(file->name(), GetJSMessageFilename(file->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->name()), "file_path", file_path);
  }

  for (int i = 0; i < file->dependency_count(); i++) {
    grpc::string file_path = GetRelativePath(
        file->name(), GetJSMessageFilename(file->dependency(i)->name()));
    out->Print("var $module_alias$ = require('$file_path$');\n", "module_alias",
               ModuleAlias(file->dependency(i)->name()), "file_path",
               file_path);
  }
  out->Print("\n");
}

void PrintTransformers(const FileDescriptor* file, Printer* out,
                       const Parameters& params) {
  map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
  for (std::map<grpc::string, const Descriptor*>::iterator it =
           messages.begin();
       it != messages.end(); it++) {
    PrintMessageTransformer(it->second, out, params);
  }
  out->Print("\n");
}

void PrintServices(const FileDescriptor* file, Printer* out) {
  for (int i = 0; i < file->service_count(); i++) {
    PrintService(file->service(i), out);
  }
}
}  // namespace

grpc::string GenerateFile(const FileDescriptor* file,
                          const Parameters& params) {
  grpc::string output;
  {
    StringOutputStream output_stream(&output);
    Printer out(&output_stream, '$');

    if (file->service_count() == 0) {
      output = "// GENERATED CODE -- NO SERVICES IN PROTO";
      return output;
    }
    out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");

    grpc::string leading_comments = GetNodeComments(file, true);
    if (!leading_comments.empty()) {
      out.Print("// Original file comments:\n");
      out.PrintRaw(leading_comments.c_str());
    }

    out.Print("'use strict';\n");

    PrintImports(file, &out);

    PrintTransformers(file, &out, params);

    PrintServices(file, &out);

    out.Print(GetNodeComments(file, false).c_str());
  }
  return output;
}

}  // namespace grpc_node_generator
<|endoftext|>


<commit_before>#include "stack.h"
#include <string>
#include <cassert>
#include <unordered_map>

NS_BEGIN(elloop);

/*
 *
 *  1  : oper1 > oper2
 *  0  : oper1 == oper2
 *  -1 : oper1 < oper2
 *
 */
int compareOper(char oper1, char oper2) {
    using OperMap = std::unordered_map<char, std::unordered_map<char, int>>;

    OperMap operMap;

    operMap['+']['+'] = 1;                          operMap['*']['+'] = 1;
    operMap['+']['-'] = 1;                          operMap['*']['-'] = 1;
    operMap['+']['*'] = -1;                         operMap['*']['*'] = 1;
    operMap['+']['/'] = -1;                         operMap['*']['/'] = 1;
    operMap['+']['('] = -1;                         operMap['*']['('] = -1;
    operMap['+'][')'] = 1;                          operMap['*'][')'] = 1;
    operMap['+']['#'] = 1;                          operMap['*']['#'] = 1;

                            operMap['-']['+'] = 1;
                            operMap['-']['-'] = 1;
                            operMap['-']['*'] = -1;
                            operMap['-']['/'] = -1;
                            operMap['-']['('] = -1;
                            operMap['-'][')'] = 1;
                            operMap['-']['#'] = 1;

     operMap[')']['+'] = 1;                         operMap['#']['+'] = -1;
     operMap[')']['-'] = 1;                         operMap['#']['-'] = -1;
     operMap[')']['*'] = 1;                         operMap['#']['*'] = -1;
     operMap[')']['/'] = 1;                         operMap['#']['/'] = -1;
     operMap[')']['('] = 2;                         operMap['#']['('] = -1;
     operMap[')'][')'] = 1;                         operMap['#'][')'] = 2;
     operMap[')']['#'] = 1;                         operMap['#']['#'] = 0;

     operMap['/']['+'] = 1;                          operMap['(']['+'] = -1;
     operMap['/']['-'] = 1;                          operMap['(']['-'] = -1;
     operMap['/']['*'] = 1;                          operMap['(']['*'] = -1;
     operMap['/']['/'] = 1;                          operMap['(']['/'] = -1;
     operMap['/']['('] = -1;                         operMap['(']['('] = -1;
     operMap['/'][')'] = 1;                          operMap['('][')'] = 0;
     operMap['/']['#'] = 1;                          operMap['(']['#'] = 2;

    // auto isSpecial = [ ](char c) -> bool { return (c == ')' || c == '(' || c == '#'); };
    // auto isAdvance = [ ](char c) -> bool { return (c == '*' || c == '/'); };
    // auto isNormal  = [ ](char c) -> bool { return (c == '+' || c == '-'); };

    // if (oper1 == oper2) {
    //     if (!isSpecial(oper1)) {
    //         return 1;
    //     }
    //     else {
    //         if (oper1 == '(') {
    //             return -1;
    //         }
    //         else if (oper1 == ')') {
    //             return 1;
    //         }
    //         else if (oper1 == '#') {
    //             return 0;
    //         }
    //         else {
    //             // should be unreachable.
    //             assert(false);
    //         }
    //     }
    // }
    // else {

    // }
}

double evalExpression(const std::string &s) {
    double res(0);

    Stack<char> operStack;
    Stack<char> opndStack;
    operStack.push('#');

    auto isOper = [](char c) -> bool {
        return (std::string("+-*/()#").find(c) != std::string::npos);
    }

    size_t i(0);
    while (s[i] != '#' && operStack.top() != '#') {
        if (!isOper(s[i])) {
            opndStack.push(s[i]);
        }
        else {

        }
    }
    return res;
}

RUN_GTEST(StackTest, EvalExpression, @@);

std::string epress("(1+2+3+4)*2+3*4+10/2");
psln(evalExpression(epress));

END_TEST;

NS_END(elloop);
    // auto isSpecial = [ ](char c) -> bool { return (c == ')' || c == '(' || c == '#'); };
    // auto isAdvance = [ ](char c) -> bool { return (c == '*' || c == '/'); };
    // auto isNormal  = [ ](char c) -> bool { return (c == '+' || c == '-'); };

    // if (oper1 == oper2) {
    //     if (!isSpecial(oper1)) {
    //         return 1;
    //     }
    //     else {
    //         if (oper1 == '(') {
    //             return -1;
    //         }
    //         else if (oper1 == ')') {
    //             return 1;
    //         }
    //         else if (oper1 == '#') {
    //             return 0;
    //         }
    //         else {
    //             // should be unreachable.
    //             assert(false);
    //         }
    //     }
    // }
    // else {

    // }
}

double evalExpression(const std::string &s) {
    double res(0);

    Stack<char> operStack;
    Stack<char> opndStack;
    operStack.push('#');

    auto isOper = [](char c) -> bool {
        return (std::string("+-*/()#").find(c) != std::string::npos);
    }

    size_t i(0);
    while (s[i] != '#' && operStack.top() != '#') {
        if (!isOper(s[i])) {
            opndStack.push(s[i]);
        }
        else {

        }
    }
    return res;
}

RUN_GTEST(StackTest, EvalExpression, @@);

std::string epress("(1+2+3+4)*2+3*4+10/2");
psln(evalExpression(epress));

END_TEST;

NS_END(elloop);
<commit_msg>fetch an elem<commit_after>#include "stack.h"
#include <string>
#include <cassert>
#include <unordered_map>

NS_BEGIN(elloop);

/*
 *
 *  1  : oper1 > oper2
 *  0  : oper1 == oper2
 *  -1 : oper1 < oper2
 *
 */
int compareOper(char oper1, char oper2) {
    using OperMap = std::unordered_map<char, std::unordered_map<char, int>>;

    OperMap operMap;

    operMap['+']['+'] = 1;   operMap['-']['+'] = 1;   operMap['*']['+'] = 1;
    operMap['+']['-'] = 1;   operMap['-']['-'] = 1;   operMap['*']['-'] = 1;
    operMap['+']['*'] = -1;  operMap['-']['*'] = -1;  operMap['*']['*'] = 1;
    operMap['+']['/'] = -1;  operMap['-']['/'] = -1;  operMap['*']['/'] = 1;
    operMap['+']['('] = -1;  operMap['-']['('] = -1;  operMap['*']['('] = -1;
    operMap['+'][')'] = 1;   operMap['-'][')'] = 1;   operMap['*'][')'] = 1;
    operMap['+']['#'] = 1;   operMap['-']['#'] = 1;   operMap['*']['#'] = 1;

                                                      operMap['/']['+'] = 1;
                                                      operMap['/']['-'] = 1;
                                                      operMap['/']['*'] = 1;
                                                      operMap['/']['/'] = 1;
                                                      operMap['/']['('] = -1;
                                                      operMap['/'][')'] = 1;
                                                      operMap['/']['#'] = 1;

                                                      operMap['#']['+'] = -1;
                                                      operMap['#']['-'] = -1;
                                                      operMap['#']['*'] = -1;
                                                      operMap['#']['/'] = -1;
                                                      operMap['#']['('] = -1;
                                                      operMap['#'][')'] = 2;
                                                      operMap['#']['#'] = 0;

                                                      operMap[')']['+'] = 1;
                                                      operMap[')']['-'] = 1;
                                                      operMap[')']['*'] = 1;
                                                      operMap[')']['/'] = 1;
                                                      operMap[')']['('] = 2;
                                                      operMap[')'][')'] = 1;
                                                      operMap[')']['#'] = 1;

                                                      operMap['(']['+'] = -1;
                                                      operMap['(']['-'] = -1;
                                                      operMap['(']['*'] = -1;
                                                      operMap['(']['/'] = -1;
                                                      operMap['(']['('] = -1;
                                                      operMap['('][')'] = 0;
                                                      operMap['(']['#'] = 1;
    return operMap[oper1][oper2];

    // auto isSpecial = [ ](char c) -> bool { return (coperMap['(']['#'] = 2;   == ')' || c == '(' || c == '#'); };
    // auto isAdvance = [ ](char c) -> bool { return (c == '*' || c == '/'); };
    // auto isNormal  = [ ](char c) -> bool { return (c == '+' || c == '-'); };

    // if (oper1 == oper2) {
    //     if (!isSpecial(oper1)) {
    //         return 1;
    //     }
    //     else {
    //         if (oper1 == '(') {
    //             return -1;
    //         }
    //         else if (oper1 == ')') {
    //             return 1;
    //         }
    //         else if (oper1 == '#') {
    //             return 0;
    //         }
    //         else {
    //             // should be unreachable.
    //             assert(false);
    //         }
    //     }
    // }
    // else {

    // }
}

double evalBinaryOper(double opnd1, char oper, double opnd2) {
    double res(0);
    switch (oper) {
        case '+':
            res = opnd1 + opnd2;
            break;
        case '-':
            res = opnd1 - opnd2;
            break;
        case '*':
            res = opnd1 * opnd2;
            break;
        case '/':
            assert(opnd2 != 0);
            res = opnd1 / opnd2;
            break;
        default:
            assert(false);
    }
    return 0;
}

double evalExpression(const std::string &s) {
    double res(0);

    Stack<double> operStack;
    Stack<char> opndStack;
    operStack.push('#');

    auto isOper = [](char c) -> bool {
        return (std::string("+-*/()#").find(c) != std::string::npos);
    };

    auto fetchAnElem = [isOper] (const std::string &s, size_t &index, std::string &ret) -> bool {
        ret.clear();
        if (index >= s.length() || index < 0) { return false; }
        if (isOper(s[index])) {
            ret = s[index++];
        }
        else {
            while (index < s.length() && !isOper(s[index])) {
                ret.append(1, s[index++]);
            }
        }
        return true;
    };

    auto testFetch = [&] () {
        std::string ret;
        size_t j(0);
        psln(j);
        while (fetchAnElem(s, j, ret)) {
            psln(ret);
            psln(j);
        }
    };

    size_t i(0);
    std::string ret;
    while (fetchAnElem(s, i, ret)  && ret != '#' && operStack.top() != '#') {
        if (!isOper(ret[0])) {
            // opndStack.push(folly::convertToDoulbe(ret));
        }
        else {
            auto top = operStack.top();
            switch (compareOper(top, s[i])) {
                case -1:
                    operStack.push(s[i]);
                    break;
                case 0:
                    operStack.pop();
                    break;
                case 1:
                    auto opnd1 = opndStack.top(); opndStack.pop();
                    auto opnd2 = opndStack.top(); opndStack.pop();
                    opndStack.push(evalBinaryOper(opnd1, top, opnd2));
                    operStack.pop();
                    break;
            }
        }
    }
    return res;
}

RUN_GTEST(StackTest, EvalExpression, @@);

std::string epress("(1+2+3+4)*2+3*4+10/2");
psln(evalExpression(epress));

END_TEST;

NS_END(elloop);
<|endoftext|>


<commit_before>// arm-poky-linux-gnueabi-gcc -lopencv_video -lopencv_core -lopencv_highgui -lopencv_imgproc -lstdc++ -lpthread -shared-libgcc opencv.cpp -o opencv

#include "evision.h"
#include "tracer.h"
#include "gpio.h"

// Global variables
GPIO pwm_right(1, "out"), pwm_left(3, "out"); // led_right(2 , "out");
GPIO led_front(5, "out"), led_R(4, "out"), start(7 ,"out"); // 0,2,6 bulit
int high_right = 600, high_left = 600, period = 20000; //PWM high time in us

// GUI globals
cv::Mat guiframe;
bool new_frame = false;
bool running = true;

// Window titles
char main_window_name[] = "Lightning Asystant :: Team eVision";
char settings_window_name[] = "Settings :: Team eVision";

// Settings variables
int settings_show_step = 0;
int settings_contrast = 0;
int settings_blur = 1;
int settings_threshold = 128;

//Functions declaration
void pwm_control(int, int);

int main(int argc, char** argv)
{
    pthread_t processing_thread, pwm_thread;
    long time_old;
    int fps_counter = 0;
    int gui_key;

	// for cpu affinity
	cpu_set_t cpuset;
	int cpu = 0;

	CPU_ZERO(&cpuset);       //clears the cpuset
	CPU_SET( cpu , &cpuset); //set CPU 2 on cpuset
	sched_setaffinity(0, sizeof(cpuset), &cpuset);

    // process priority
    setpriority(PRIO_PROCESS, 0, -20);

    // GUI setup
	cv::namedWindow(main_window_name);

	// Setup window
	cv::namedWindow(settings_window_name);
	cv::createTrackbar("Show Step   ", settings_window_name, &settings_show_step, LAST_STEP-1);
	cv::createTrackbar("Contrast    ", settings_window_name, &settings_contrast, 1);
	cv::createTrackbar("Mean Blur   ", settings_window_name, &settings_blur, 1);
	cv::createTrackbar("Threshold   ", settings_window_name, &settings_threshold, 255);
	cv::createTrackbar("Servo Right ", settings_window_name, &high_right, 3000);
	cv::createTrackbar("Servo Left  ", settings_window_name, &high_left, 3000);

	pthread_create(&processing_thread, NULL, processing_thread_function, NULL);
	//pthread_create(&pwm_thread, NULL, pwm_thread_function, NULL);

    while(running){

    	while(!new_frame){ } // loop

		cv::imshow(main_window_name, guiframe);

		// calculate fps
		if(time(NULL) != time_old){
			add_info(fps_counter);
			fps_counter = 1;
			time_old = time(NULL);
		} else {
			fps_counter++;
		}

		new_frame = 0;

		gui_key = cv::waitKey(5);
		if(gui_key >= 0) {
			gui_key %= 0xFF;

			// ESC
			if((gui_key == 43) || (gui_key == 27)){
				running = false;
			} else if(gui_key == 49) {
				start.high(); // 1 = start/stop
				usleep(10000);
				start.low();
			} else if(gui_key == 50) {
				led_front.toggle(); // 2 = faruri
			} else if(gui_key == 51) {
				led_R.toggle(); // 3 = far pieton
			} else {
				std::cout << gui_key << std::endl;
			}
		}
    }

	pthread_join(processing_thread, NULL);

    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

void send_frame_to_gui(cv::Mat &frame, int step){
	if((new_frame == 0) && (step == settings_show_step)){
		//cv::pyrUp(frame, guiframe);
		frame.copyTo(guiframe);
		new_frame = 1;
	}
}

bool contour_area(std::vector<cv::Point> a, std::vector<cv::Point> b){
	return cv::contourArea(a) > cv::contourArea(b);
}

void *processing_thread_function(void* unsused)
{
	cv::VideoCapture 	cap(0); // camera interface
    cv::Mat 			frame, cam_frame, bw_frame, blur_frame, contrast_frame;
    cv::Mat				threshold_frame, canny_frame, contour_frame;
    Tracer				processing_tracer;
    // for cpu affinity
	cpu_set_t cpuset;
	int cpu = 1;
	int local_hr = 0, local_hl = 0; //local variables for pwm control

	CPU_ZERO(&cpuset);       //clears the cpuset
	CPU_SET( cpu , &cpuset); //set CPU 2 on cpuset
	sched_setaffinity(0, sizeof(cpuset), &cpuset);

    if(!cap.isOpened())  // check if we succeeded
    {
        std::cout << "Could not open default video device" << std::endl;
        pthread_exit(NULL);

    }

   	while(running) {

   		if((high_right != local_hr)||(high_left != local_hl)){
   			local_hr = high_right;
   			local_hl = high_left;
   			pwm_control(local_hr, local_hl);
   		}

		if( !cap.read(frame) ){
			std::cout << "Camera was disconected";
			break;
		}

		cv::pyrDown(frame, cam_frame);
		send_frame_to_gui(cam_frame, SENSOR_IMAGE);
		processing_tracer.start();

		// All processing are done on gray image
		cv::cvtColor(cam_frame, bw_frame, CV_BGR2GRAY);
		processing_tracer.event("Convert to Gray");
		send_frame_to_gui(bw_frame, GRAY_IMAGE);

		// Increase contrast by distributing color histogram to contain all values
		if(settings_contrast){
			cv::equalizeHist(bw_frame, contrast_frame);
		} else {
			contrast_frame = bw_frame;
		}
		processing_tracer.event("Equalize histogram");
		send_frame_to_gui(contrast_frame, CONTRAST_IMAGE);

		// Apply a special blur filter which preserves edges
		if(settings_blur){
			cv::medianBlur(contrast_frame, blur_frame, 7);
		} else {
			blur_frame = contrast_frame;
		}
		processing_tracer.event("Median blur");
		send_frame_to_gui(blur_frame, BLUR_IMAGE);

		// detect edges using histeresys
		cv::Canny(contrast_frame, canny_frame, 30, 100);
		processing_tracer.event("Edge detection");
		send_frame_to_gui(canny_frame, CANNY_IMAGE);

		// Apply threshhold
		threshold(blur_frame, threshold_frame, settings_threshold, 255, CV_THRESH_BINARY);
		processing_tracer.event("Appling threshold");
		send_frame_to_gui(threshold_frame, THRESHOLD_IMAGE);

		// detect and paint contours

		std::vector<std::vector<cv::Point>> contours, road(1);
		std::vector<cv::Vec4i> hierarchy;
		contour_frame = blur_frame;

		cv::findContours(threshold_frame, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
		if(contours.size() > 1){
			std::sort(contours.begin(), contours.end(), contour_area);
			cv::approxPolyDP(cv::Mat(contours[0]), road[0], 20, true);
			cv::drawContours(cam_frame, road, -1, cv::Scalar(0, 255 ,0), 2);

			cv::approxPolyDP(cv::Mat(contours[1]), road[0], 20, true);
			cv::drawContours(cam_frame, road, -1, cv::Scalar(255, 0, 0), 2);
		}
		processing_tracer.event("Contour detection");
		send_frame_to_gui(cam_frame, CONTOUR_IMAGE);
	}

	processing_tracer.end();
	pthread_exit(NULL);
}

	void pwm_control(int h_r, int h_l){
		for(int i = 0; i < 2; i++){
			pwm_right.high();
			pwm_left.high();
			usleep(std::min(h_r, h_l));
			if(h_r > h_l)
				pwm_left.low();
			else
				pwm_right.low();
			usleep(abs(h_r - h_l));
			if(h_r > h_l)
				pwm_right.low();
			else
				pwm_left.low();
			usleep(period - std::max(h_r, h_l));
		}
	}

void add_info(int fps){
	// white canvas
	cv::Mat img_info (25, 320, CV_8UC3, cv::Scalar(255, 255, 255));

	cv::putText(img_info, std::string("FPS: ") + std::to_string(fps), cv::Point(5, 20),
			cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0,0,255), 1, CV_AA);

	cv::imshow(settings_window_name, img_info);
}
<commit_msg>modified start signal period<commit_after>// arm-poky-linux-gnueabi-gcc -lopencv_video -lopencv_core -lopencv_highgui -lopencv_imgproc -lstdc++ -lpthread -shared-libgcc opencv.cpp -o opencv

#include "evision.h"
#include "tracer.h"
#include "gpio.h"

// Global variables
GPIO pwm_right(1, "out"), pwm_left(3, "out"); // led_right(2 , "out");
GPIO led_front(5, "out"), led_R(4, "out"), start(7 ,"out"); // 0,2,6 bulit
int high_right = 600, high_left = 600, period = 20000; //PWM high time in us

// GUI globals
cv::Mat guiframe;
bool new_frame = false;
bool running = true;

// Window titles
char main_window_name[] = "Lightning Asystant :: Team eVision";
char settings_window_name[] = "Settings :: Team eVision";

// Settings variables
int settings_show_step = 0;
int settings_contrast = 0;
int settings_blur = 1;
int settings_threshold = 128;

//Functions declaration
void pwm_control(int, int);

int main(int argc, char** argv)
{
    pthread_t processing_thread, pwm_thread;
    long time_old;
    int fps_counter = 0;
    int gui_key;

	// for cpu affinity
	cpu_set_t cpuset;
	int cpu = 0;

	CPU_ZERO(&cpuset);       //clears the cpuset
	CPU_SET( cpu , &cpuset); //set CPU 2 on cpuset
	sched_setaffinity(0, sizeof(cpuset), &cpuset);

    // process priority
    setpriority(PRIO_PROCESS, 0, -20);

    // GUI setup
	cv::namedWindow(main_window_name);

	// Setup window
	cv::namedWindow(settings_window_name);
	cv::createTrackbar("Show Step   ", settings_window_name, &settings_show_step, LAST_STEP-1);
	cv::createTrackbar("Contrast    ", settings_window_name, &settings_contrast, 1);
	cv::createTrackbar("Mean Blur   ", settings_window_name, &settings_blur, 1);
	cv::createTrackbar("Threshold   ", settings_window_name, &settings_threshold, 255);
	cv::createTrackbar("Servo Right ", settings_window_name, &high_right, 3000);
	cv::createTrackbar("Servo Left  ", settings_window_name, &high_left, 3000);

	pthread_create(&processing_thread, NULL, processing_thread_function, NULL);
	//pthread_create(&pwm_thread, NULL, pwm_thread_function, NULL);

    while(running){

    	while(!new_frame){ } // loop

		cv::imshow(main_window_name, guiframe);

		// calculate fps
		if(time(NULL) != time_old){
			add_info(fps_counter);
			fps_counter = 1;
			time_old = time(NULL);
		} else {
			fps_counter++;
		}

		new_frame = 0;

		gui_key = cv::waitKey(5);
		if(gui_key >= 0) {
			gui_key %= 0xFF;

			// ESC
			if((gui_key == 43) || (gui_key == 27)){
				running = false;
			} else if(gui_key == 49) {
				start.high(); // 1 = start/stop
				usleep(50000);
				start.low();
			} else if(gui_key == 50) {
				led_front.toggle(); // 2 = faruri
			} else if(gui_key == 51) {
				led_R.toggle(); // 3 = far pieton
			} else {
				std::cout << gui_key << std::endl;
			}
		}
    }

	pthread_join(processing_thread, NULL);

    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

void send_frame_to_gui(cv::Mat &frame, int step){
	if((new_frame == 0) && (step == settings_show_step)){
		//cv::pyrUp(frame, guiframe);
		frame.copyTo(guiframe);
		new_frame = 1;
	}
}

bool contour_area(std::vector<cv::Point> a, std::vector<cv::Point> b){
	return cv::contourArea(a) > cv::contourArea(b);
}

void *processing_thread_function(void* unsused)
{
	cv::VideoCapture 	cap(0); // camera interface
    cv::Mat 			frame, cam_frame, bw_frame, blur_frame, contrast_frame;
    cv::Mat				threshold_frame, canny_frame, contour_frame;
    Tracer				processing_tracer;
    // for cpu affinity
	cpu_set_t cpuset;
	int cpu = 1;
	int local_hr = 0, local_hl = 0; //local variables for pwm control

	CPU_ZERO(&cpuset);       //clears the cpuset
	CPU_SET( cpu , &cpuset); //set CPU 2 on cpuset
	sched_setaffinity(0, sizeof(cpuset), &cpuset);

    if(!cap.isOpened())  // check if we succeeded
    {
        std::cout << "Could not open default video device" << std::endl;
        pthread_exit(NULL);

    }

   	while(running) {

   		if((high_right != local_hr)||(high_left != local_hl)){
   			local_hr = high_right;
   			local_hl = high_left;
   			pwm_control(local_hr, local_hl);
   		}

		if( !cap.read(frame) ){
			std::cout << "Camera was disconected";
			break;
		}

		cv::pyrDown(frame, cam_frame);
		send_frame_to_gui(cam_frame, SENSOR_IMAGE);
		processing_tracer.start();

		// All processing are done on gray image
		cv::cvtColor(cam_frame, bw_frame, CV_BGR2GRAY);
		processing_tracer.event("Convert to Gray");
		send_frame_to_gui(bw_frame, GRAY_IMAGE);

		// Increase contrast by distributing color histogram to contain all values
		if(settings_contrast){
			cv::equalizeHist(bw_frame, contrast_frame);
		} else {
			contrast_frame = bw_frame;
		}
		processing_tracer.event("Equalize histogram");
		send_frame_to_gui(contrast_frame, CONTRAST_IMAGE);

		// Apply a special blur filter which preserves edges
		if(settings_blur){
			cv::medianBlur(contrast_frame, blur_frame, 7);
		} else {
			blur_frame = contrast_frame;
		}
		processing_tracer.event("Median blur");
		send_frame_to_gui(blur_frame, BLUR_IMAGE);

		// detect edges using histeresys
		cv::Canny(contrast_frame, canny_frame, 30, 100);
		processing_tracer.event("Edge detection");
		send_frame_to_gui(canny_frame, CANNY_IMAGE);

		// Apply threshhold
		threshold(blur_frame, threshold_frame, settings_threshold, 255, CV_THRESH_BINARY);
		processing_tracer.event("Appling threshold");
		send_frame_to_gui(threshold_frame, THRESHOLD_IMAGE);

		// detect and paint contours

		std::vector<std::vector<cv::Point>> contours, road(1);
		std::vector<cv::Vec4i> hierarchy;
		contour_frame = blur_frame;

		cv::findContours(threshold_frame, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
		if(contours.size() > 1){
			std::sort(contours.begin(), contours.end(), contour_area);
			cv::approxPolyDP(cv::Mat(contours[0]), road[0], 20, true);
			cv::drawContours(cam_frame, road, -1, cv::Scalar(0, 255 ,0), 2);

			cv::approxPolyDP(cv::Mat(contours[1]), road[0], 20, true);
			cv::drawContours(cam_frame, road, -1, cv::Scalar(255, 0, 0), 2);
		}
		processing_tracer.event("Contour detection");
		send_frame_to_gui(cam_frame, CONTOUR_IMAGE);
	}

	processing_tracer.end();
	pthread_exit(NULL);
}

	void pwm_control(int h_r, int h_l){
		for(int i = 0; i < 2; i++){
			pwm_right.high();
			pwm_left.high();
			usleep(std::min(h_r, h_l));
			if(h_r > h_l)
				pwm_left.low();
			else
				pwm_right.low();
			usleep(abs(h_r - h_l));
			if(h_r > h_l)
				pwm_right.low();
			else
				pwm_left.low();
			usleep(period - std::max(h_r, h_l));
		}
	}

void add_info(int fps){
	// white canvas
	cv::Mat img_info (25, 320, CV_8UC3, cv::Scalar(255, 255, 255));

	cv::putText(img_info, std::string("FPS: ") + std::to_string(fps), cv::Point(5, 20),
			cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0,0,255), 1, CV_AA);

	cv::imshow(settings_window_name, img_info);
}
<|endoftext|>


<commit_before>#include "source/common/common/assert.h"

#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_join.h"
#include "absl/synchronization/mutex.h"

namespace Envoy {
namespace Assert {

class ActionRegistrationImpl : public ActionRegistration {
public:
  ActionRegistrationImpl(std::function<void(const char* location)> action) : action_(action) {
    next_action_ = debug_assertion_failure_record_action_;
    debug_assertion_failure_record_action_ = this;
  }

  ~ActionRegistrationImpl() override {
    ASSERT(debug_assertion_failure_record_action_ == this);
    debug_assertion_failure_record_action_ = next_action_;
  }

  void invoke(const char* location) {
    action_(location);
    if (next_action_) {
      next_action_->invoke(location);
    }
  }

  static void invokeAction(const char* location) {
    if (debug_assertion_failure_record_action_ != nullptr) {
      debug_assertion_failure_record_action_->invoke(location);
    }
  }

private:
  std::function<void(const char* location)> action_;
  ActionRegistrationImpl* next_action_ = nullptr;

  // Pointer to the first action in the chain or nullptr if no action is currently registered.
  static ActionRegistrationImpl* debug_assertion_failure_record_action_;
};

// This class implements the logic for triggering ENVOY_BUG logs and actions. Logging and actions
// will be triggered with exponential back-off per file and line bug.
class EnvoyBugRegistrationImpl : public ActionRegistration {
public:
  EnvoyBugRegistrationImpl(std::function<void(const char* location)> action) : action_(action) {
    next_action_ = envoy_bug_failure_record_action_;
    envoy_bug_failure_record_action_ = this;

    // Reset counters when a registration is added.
    absl::MutexLock lock(&mutex_);
    counters_.clear();
  }

  ~EnvoyBugRegistrationImpl() override {
    ASSERT(envoy_bug_failure_record_action_ == this);
    envoy_bug_failure_record_action_ = next_action_;
  }

  // This method is invoked when an ENVOY_BUG condition fails. It increments a per file and line
  // counter for every ENVOY_BUG hit in a mutex guarded map.
  // The implementation may also be a inline static counter per-file and line. There is no benchmark
  // to show that the performance of this mutex is any worse than atomic counters. Acquiring and
  // releasing a mutex is cheaper than a cache miss, but the mutex here is contended for every
  // ENVOY_BUG failure rather than per individual bug. Hitting ENVOY_BUGs is not a performance
  // critical path, and mutex contention would indicate that there is a serious failure.
  // Currently, this choice reduces code size and has the advantage that behavior is easier to
  // understand and debug, and test behavior is predictable.
  static bool shouldLogAndInvoke(absl::string_view bug_name) {
    // Increment counter, inserting first if counter does not exist.
    uint64_t counter_value = 0;
    {
      absl::MutexLock lock(&mutex_);
      counter_value = ++counters_[bug_name];
    }

    // Check if counter is power of two by its bitwise representation.
    return (counter_value & (counter_value - 1)) == 0;
  }

  void invoke(const char* location) {
    action_(location);
    if (next_action_) {
      next_action_->invoke(location);
    }
  }

  static void invokeAction(const char* location) {
    if (envoy_bug_failure_record_action_ != nullptr) {
      envoy_bug_failure_record_action_->invoke(location);
    }
  }

  static void resetEnvoyBugCounters() {
    {
      absl::MutexLock lock(&mutex_);
      counters_.clear();
    }
  }

private:
  std::function<void(const char* location)> action_;
  EnvoyBugRegistrationImpl* next_action_ = nullptr;

  // Pointer to the first action in the chain or nullptr if no action is currently registered.
  static EnvoyBugRegistrationImpl* envoy_bug_failure_record_action_;

  using EnvoyBugMap = absl::flat_hash_map<std::string, uint64_t>;
  static absl::Mutex mutex_;
  static EnvoyBugMap counters_ ABSL_GUARDED_BY(mutex_);
};

ActionRegistrationImpl* ActionRegistrationImpl::debug_assertion_failure_record_action_ = nullptr;
EnvoyBugRegistrationImpl* EnvoyBugRegistrationImpl::envoy_bug_failure_record_action_ = nullptr;
EnvoyBugRegistrationImpl::EnvoyBugMap EnvoyBugRegistrationImpl::counters_;
absl::Mutex EnvoyBugRegistrationImpl::mutex_;

ActionRegistrationPtr
addDebugAssertionFailureRecordAction(const std::function<void(const char* location)>& action) {
  return std::make_unique<ActionRegistrationImpl>(action);
}

ActionRegistrationPtr
addEnvoyBugFailureRecordAction(const std::function<void(const char* location)>& action) {
  return std::make_unique<EnvoyBugRegistrationImpl>(action);
}

void invokeDebugAssertionFailureRecordActionForAssertMacroUseOnly(const char* location) {
  ActionRegistrationImpl::invokeAction(location);
}

void invokeEnvoyBugFailureRecordActionForEnvoyBugMacroUseOnly(const char* location) {
  EnvoyBugRegistrationImpl::invokeAction(location);
}

bool shouldLogAndInvokeEnvoyBugForEnvoyBugMacroUseOnly(absl::string_view bug_name) {
  return EnvoyBugRegistrationImpl::shouldLogAndInvoke(bug_name);
}

void resetEnvoyBugCountersForTest() { EnvoyBugRegistrationImpl::resetEnvoyBugCounters(); }

} // namespace Assert
} // namespace Envoy
<commit_msg>assert: Avoid static-init-order fiasco for ENVOY_BUG macro impl (#19277)<commit_after>#include "source/common/common/assert.h"

#include "absl/container/flat_hash_map.h"
#include "absl/strings/str_join.h"
#include "absl/synchronization/mutex.h"

namespace Envoy {
namespace Assert {

class ActionRegistrationImpl : public ActionRegistration {
public:
  ActionRegistrationImpl(std::function<void(const char* location)> action) : action_(action) {
    next_action_ = debug_assertion_failure_record_action_;
    debug_assertion_failure_record_action_ = this;
  }

  ~ActionRegistrationImpl() override {
    ASSERT(debug_assertion_failure_record_action_ == this);
    debug_assertion_failure_record_action_ = next_action_;
  }

  void invoke(const char* location) {
    action_(location);
    if (next_action_) {
      next_action_->invoke(location);
    }
  }

  static void invokeAction(const char* location) {
    if (debug_assertion_failure_record_action_ != nullptr) {
      debug_assertion_failure_record_action_->invoke(location);
    }
  }

private:
  std::function<void(const char* location)> action_;
  ActionRegistrationImpl* next_action_ = nullptr;

  // Pointer to the first action in the chain or nullptr if no action is currently registered.
  static ActionRegistrationImpl* debug_assertion_failure_record_action_;
};

class EnvoyBugState {
public:
  static EnvoyBugState& get() { MUTABLE_CONSTRUCT_ON_FIRST_USE(EnvoyBugState); }

  void clear() {
    absl::MutexLock lock(&mutex_);
    counters_.clear();
  }

  uint64_t inc(absl::string_view bug_name) {
    absl::MutexLock lock(&mutex_);
    return ++counters_[bug_name];
  }

private:
  absl::Mutex mutex_;
  absl::flat_hash_map<std::string, uint64_t> counters_ ABSL_GUARDED_BY(mutex_);
};

// This class implements the logic for triggering ENVOY_BUG logs and actions. Logging and actions
// will be triggered with exponential back-off per file and line bug.
class EnvoyBugRegistrationImpl : public ActionRegistration {
public:
  EnvoyBugRegistrationImpl(std::function<void(const char* location)> action) : action_(action) {
    next_action_ = envoy_bug_failure_record_action_;
    envoy_bug_failure_record_action_ = this;

    // Reset counters when a registration is added.
    EnvoyBugState::get().clear();
  }

  ~EnvoyBugRegistrationImpl() override {
    ASSERT(envoy_bug_failure_record_action_ == this);
    envoy_bug_failure_record_action_ = next_action_;
  }

  // This method is invoked when an ENVOY_BUG condition fails. It increments a per file and line
  // counter for every ENVOY_BUG hit in a mutex guarded map.
  // The implementation may also be a inline static counter per-file and line. There is no benchmark
  // to show that the performance of this mutex is any worse than atomic counters. Acquiring and
  // releasing a mutex is cheaper than a cache miss, but the mutex here is contended for every
  // ENVOY_BUG failure rather than per individual bug. Hitting ENVOY_BUGs is not a performance
  // critical path, and mutex contention would indicate that there is a serious failure.
  // Currently, this choice reduces code size and has the advantage that behavior is easier to
  // understand and debug, and test behavior is predictable.
  static bool shouldLogAndInvoke(absl::string_view bug_name) {
    // Increment counter, inserting first if counter does not exist.
    const uint64_t counter_value = EnvoyBugState::get().inc(bug_name);

    // Check if counter is power of two by its bitwise representation.
    return (counter_value & (counter_value - 1)) == 0;
  }

  void invoke(const char* location) {
    action_(location);
    if (next_action_) {
      next_action_->invoke(location);
    }
  }

  static void invokeAction(const char* location) {
    if (envoy_bug_failure_record_action_ != nullptr) {
      envoy_bug_failure_record_action_->invoke(location);
    }
  }

  static void resetEnvoyBugCounters() { EnvoyBugState::get().clear(); }

private:
  std::function<void(const char* location)> action_;
  EnvoyBugRegistrationImpl* next_action_ = nullptr;

  // Pointer to the first action in the chain or nullptr if no action is currently registered.
  static EnvoyBugRegistrationImpl* envoy_bug_failure_record_action_;
};

ActionRegistrationImpl* ActionRegistrationImpl::debug_assertion_failure_record_action_ = nullptr;
EnvoyBugRegistrationImpl* EnvoyBugRegistrationImpl::envoy_bug_failure_record_action_ = nullptr;

ActionRegistrationPtr
addDebugAssertionFailureRecordAction(const std::function<void(const char* location)>& action) {
  return std::make_unique<ActionRegistrationImpl>(action);
}

ActionRegistrationPtr
addEnvoyBugFailureRecordAction(const std::function<void(const char* location)>& action) {
  return std::make_unique<EnvoyBugRegistrationImpl>(action);
}

void invokeDebugAssertionFailureRecordActionForAssertMacroUseOnly(const char* location) {
  ActionRegistrationImpl::invokeAction(location);
}

void invokeEnvoyBugFailureRecordActionForEnvoyBugMacroUseOnly(const char* location) {
  EnvoyBugRegistrationImpl::invokeAction(location);
}

bool shouldLogAndInvokeEnvoyBugForEnvoyBugMacroUseOnly(absl::string_view bug_name) {
  return EnvoyBugRegistrationImpl::shouldLogAndInvoke(bug_name);
}

void resetEnvoyBugCountersForTest() { EnvoyBugRegistrationImpl::resetEnvoyBugCounters(); }

} // namespace Assert
} // namespace Envoy
<|endoftext|>


<commit_before>#ifndef FORWARD_HPP_INCLUDED
#define FORWARD_HPP_INCLUDED

namespace Factorem { namespace Server { namespace RestApi {

    class RestConnection;
    class RestServer;

} // namespace RestApi
} // namespace Server
} // namespace Factorem

#endif // FORWARD_HPP_INCLUDED
<commit_msg>Just renaming the namespace.<commit_after>#ifndef FORWARD_HPP_INCLUDED
#define FORWARD_HPP_INCLUDED

namespace Carbonide { namespace Server { namespace RestApi {

    class RestConnection;
    class RestServer;

} // namespace RestApi
} // namespace Server
} // namespace Carbonide

#endif // FORWARD_HPP_INCLUDED
<|endoftext|>