Segfault in Let Operator

General FreeBASIC programming questions.
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Segfault in Let Operator

Postby rolliebollocks » Mar 23, 2016 14:45

I can't seem to hunt down the reason for this segfault. I've traced the problem to the LET operator :: variable.Let( byref rhs as variable ) ::
but I can't seem to figure out how to fix it. Maybe I'm tired or my brain is fried but any help would be appreciated.

Code: Select all

#include once "parsing.bas"

#ifndef NULL
#define NULL 0
#endif

#DEFINE DBLQUOTE ascii(34)

enum varType
  _MALFORMED_ = 0
  _NUMBER_    = 1
  _STRING_    = 2
  _BOOL_      = 3
  _ARRAY_     = 4
  _OBJECT_    = 5
  _NULL_      = 6
end enum

enum JSON_BOOL
    _FALSE_ = 0
    _TRUE_  = 1
end enum

type variable_ as variable

type varArray
   
    Public:
   
        declare Destructor()
        declare sub add( byval item as variable_ ptr )
        declare function get( byval index as integer ) as variable_ ptr
        declare function getLength() as integer
        declare sub push( byval idx as integer, byval item as variable_ ptr )
        declare sub push( byval idx as integer, byref item as variable_ )
        declare sub pop( byval item as integer )
        declare sub push_back( byval item as variable_ ptr )
        declare sub clear()
           
        as integer size
        as variable_ ptr items(any)
       
end type

type varObjectField
    as string           key
    as variable_ ptr    value
end type

type varObject

    Public:
   
        declare Destructor()
        declare sub add( byval key as string, byval item as variable_ ptr )
        declare function get( byval key as string ) as variable_ ptr
        declare function getKey( byval index as integer ) as string
        declare function getValue( byval index as integer ) as variable_ ptr
        declare function getSize() as integer
           
        as integer              size
        as varObjectField ptr   fields(any)

end type

type variable

    Public:
        declare Constructor()
        declare Constructor( byref rhs as variable )
        declare Constructor( byval json as string, byval n as string = "" )
        declare Constructor( byval n as double )
        declare Destructor()
        declare Operator Let( byref rhs as variable )
        declare Operator Let( byval json as string )
        declare Operator Let( byval n as double )
       
        declare sub         init( byval s as string, byval n as string = "" )
       
        declare function    getType() as string
        declare function    getTypeNum() as vartype
        declare function    toString() as string
     
        declare function    getNumber() as double
        declare function    getString() as string
        declare function    getBoolean() as integer
        declare function    getArray() as vararray ptr
        declare function    getObject() as varobject ptr

        as string           lbl
        as varType          typ
        as double           number
        as string           strng
        as integer          bool
        as varArray ptr     array
        as varObject ptr    object

end type

Destructor varArray()
    for i as integer = 0 to this.size-1
        delete items(i)
    next
End Destructor

sub varArray.add( byval item as variable_ ptr )
    size += 1
    redim preserve items(size-1)
    items(size-1) = new variable_
    *items(size-1) = *item
end sub

sub varArray.push( byval idx as integer, byval item as variable_ ptr )
    if idx < 0 then exit sub
    if idx > size-1 then exit sub
   
    redim preserve items( size )
    items( size ) = new variable_
   
    for i as integer = size-1 to idx step -1
        swap items(i), items(i+1)
    next i
   
    *items( idx ) = *item
   
    size += 1
end sub

sub varArray.push( byval idx as integer, byref item as variable_ )
    if idx < 0 then exit sub
    if idx > size-1 then exit sub
   
    redim preserve items( size )
   
    for i as integer = size-1 to idx step -1
        swap items(i), items(i+1)
    next i
   
    *items( idx ) = item
   
    size += 1
end sub

sub varArray.push_back( byval item as variable_ ptr )   
    redim preserve items( size )
    items( size ) = new variable_
    *items( size ) = *item
    size += 1
end sub

sub varArray.pop( byval idx as integer )
    if idx < 0 then exit sub
    if idx > size-1 then exit sub
    if size = 1 then
        erase( items )
        size = 0
        exit sub
    endif
   
    for i as integer = idx+1 to size-1
        items(i-1) = items(i)
    next
   
    size -= 1
    redim preserve items( 0 to size-1 )       
end sub

sub varArray.clear()
    for i as integer = 0 to size-1
        delete items(i)
    next i
    erase items
    size = 0
end sub

function varArray.get( byval index as integer ) as variable_ ptr
    if index >= size or index < 0 then return NULL
    return items(index)
end function

function varArray.getLength() as integer
    return size
end function

Destructor varObject
    for i as integer = 0 to this.size-1
        delete fields(i)
    next i
end Destructor

sub varObject.add( byval key as string, byval item as variable_ ptr )
    size += 1
    redim preserve fields(size-1)
    fields(size-1) = new varObjectField
    fields(size-1)->key = key
    fields(size-1)->value = new variable
    *fields(size-1)->value = *item
end sub

function varObject.get( byval key as string ) as variable_ ptr
    key = chr(34)+key+chr(34)
    for i as integer = 0 to size-1
        if fields(i)->key = key then return fields(i)->value
    next i
    return 0
end function

function varObject.getKey( byval index as integer ) as string
    return fields(index)->key
end function

function varObject.getValue( byval index as integer ) as variable_ ptr
    return fields(index)->value
end function

function varObject.getSize() as integer
    return size
end function

declare Operator = ( byref lhs as variable, byref rhs as variable ) as integer

Constructor variable()
end Constructor

Constructor variable( byref rhs as variable )
    this.lbl = rhs.lbl
    this.typ = rhs.typ
   
    select case rhs.typ
        case _BOOL_
            this.bool = rhs.bool
        case _NUMBER_
            this.number = rhs.number
        case _STRING_
            this.strng = rhs.strng
        case _OBJECT_
            this.object = new varObject
            for i as integer = 0 to rhs.object->size - 1
                this.object->fields(i) = new varObjectField
                this.object->fields(i)->key = rhs.object->fields(i)->key
                *this.object->fields(i)->value = *rhs.object->fields(i)->value
            next i
        case _ARRAY_
            this.array = new varArray
            for i as integer = 0 to rhs.array->size - 1
                this.array->items(i) = new variable
                *this.array->items(i) = *rhs.array->items(i)
            next i
    end select
End Constructor

Operator variable.Let( byref rhs as variable )
    if @this <> @rhs then
        this.lbl = rhs.lbl
        this.typ = rhs.typ
       
        select case rhs.typ
            case _BOOL_
                this.bool = rhs.bool
            case _NUMBER_
                this.number = rhs.number
            case _STRING_
                this.strng = rhs.strng
            case _OBJECT_
                this.object = new varObject
                for i as integer = 0 to rhs.object->size - 1
                    this.object->fields(i) = new varObjectField
                    this.object->fields(i)->key = rhs.object->fields(i)->key
                    *this.object->fields(i)->value = *rhs.object->fields(i)->value
                next i
            case _ARRAY_
                this.array = new varArray
                for i as integer = 0 to rhs.array->size - 1
                    this.array->items(i) = new variable
                    *this.array->items(i) = *rhs.array->items(i)
                next i
        end select
    end if
end Operator

sub copy_variable( byref var1 as variable, byref var2 as variable )
    var1.lbl = var2.lbl
    var1.typ = var2.typ
   
    select case var2.typ
        case _BOOL_
            var1.bool = var2.bool
        case _NUMBER_
            var1.number = var2.number
        case _STRING_
            var1.strng = var2.strng
        case _OBJECT_
            var1.object = new varObject
            for i as integer = 0 to var2.object->size - 1
                var1.object->fields(i) = new varObjectField
                var1.object->fields(i)->key = var2.object->fields(i)->key
                *var1.object->fields(i)->value = *var2.object->fields(i)->value
            next i
        case _ARRAY_
            var1.array = new varArray
            for i as integer = 0 to var2.array->size - 1
                var1.array->items(i) = new variable
                *var1.array->items(i) = *var2.array->items(i)
            next i
    end select
end sub

Constructor variable( byval json as string, byval n as string = "" )
    init( json, n )
end Constructor

Constructor variable( byval num as double )
    this.typ = _NUMBER_
    this.number = num
end Constructor

Operator variable.Let( byval json as string )
    init( json )
end Operator

Operator variable.Let( byval num as double )
    this.typ = _NUMBER_
    this.number = num
end Operator

Operator = ( byref lhs as varObjectField, byref rhs as varObjectField ) as integer
    if lhs.key <> rhs.key then return 0
    if ( *lhs.value = *rhs.value ) = 0 then return 0
    return -1
end Operator

Operator = ( byref lhs as variable, byref rhs as variable ) as integer
    if lhs.typ <> rhs.typ then return 0
    select case lhs.typ
    case varType._NUMBER_
        if lhs.number <> rhs.number then return 0
    case varType._STRING_
        if lhs.strng <> rhs.strng then return 0
    case varType._BOOL_
        if lhs.bool <> rhs.bool then return 0
    case varType._ARRAY_
        if lhs.array->size <> rhs.array->size then return 0
        for i as integer = 0 to lhs.array->size-1
            if ( *lhs.array->items(i) = *rhs.array->items(i) ) = 0 then return 0
        next i
    case varType._OBJECT_
        if lhs.object->size <> rhs.object->size then return 0
        for i as integer = 0 to lhs.object->size-1
            if ( *lhs.object->fields(i) = *rhs.object->fields(i) ) = 0 then return 0
        next i
    end select
   
    return -1
end Operator

Destructor variable()
end Destructor

sub variable.init( byval s as string, byval n as string = "" )
    dim as integer l = len(s)
    dim as integer arrayIsOpen = 0
    dim as integer objectIsOpen = 0
    dim as integer inQuotes = 0
   
    this.lbl = n

    for i as integer = 0 to l-1
        dim as ubyte c = s[i]

        if isWhite( c ) then continue for
       
        if isNumberJson( c ) then
            if arrayIsOpen or objectIsOpen then
                this.typ = _MALFORMED_
                this.strng = s
                exit sub
            endif

            this.typ = _NUMBER_
            dim as string inNum = ""
           
            Do while IsNumberJson( s[i] )
                inNum += ascii( s[i] )
                if i > l then
                    this.typ = _MALFORMED_
                    this.strng = s
                    ? "Error: i > l"
                    exit sub
                endif
                i+=1
            loop
           
            this.number = val(inNum)
        endif

        if c = 34 then
            if arrayIsOpen or objectIsOpen then
                this.typ = _MALFORMED_
                this.strng = s
                ? "Array / Object is open"
                exit sub
            endif
           
            i+=1
            this.typ = _STRING_
            dim as string inString = ""
            dim as integer done = 0
            Do
                if s[i-1] <> asc("\") then
                    if s[i] <> 34 then
                        inString += ascii( s[i] )
                        i+=1
                    else
                        done = 1
                    endif
                else
                    inString += ascii( s[i] )
                    i+=1
                endif

                if i >= l then
                    this.typ = _MALFORMED_
                    this.strng = s
                    ? "Error: i > l"
                    done = 1
                endif
            loop until done = 1
           
            if inString <> "" then this.strng = unEscape( inString )           
         
            if i <> l-1 then
                this.typ = _MALFORMED_
                this.strng = s
                ? "Error: i <> l-1", i, l-1
                ? instring
            endif
        endif
       
        select case c
            case asc("t"),asc("T"),asc("f"),asc("F"),asc("n"), asc("N")
                if mid(s,i+1,4) = "true" then
                    this.typ = _BOOL_
                    this.bool = _TRUE_
                    i += 3
                elseif mid(s,i+1,4) = "null" then
                    this.typ = _NULL_
                    i += 3
                elseif mid(s,i+1,5) = "false" then
                    this.typ = _BOOL_
                    this.bool = _FALSE_
                    i += 4
                endif
       
            case asc("[")
                arrayIsOpen = 1
                this.typ = _ARRAY_
                this.array = new varArray
                dim as integer level = 1
                dim as string instring = ""
               
                i+=1
                Do
                    dim as ubyte char2 = s[i]
                    dim as variable tmp
                                       
                    select case char2
                       
                        case 34
                            if inQuotes = 0 then inQuotes = 1 else inQuotes = 0
                            instring += ascii( char2 )
                           
                        case asc("[")
                            level += 1
                            instring += "["
                            Do
                                i+=1
                                if s[i] = asc("[") then level += 1
                                if s[i] = asc("]") then level -= 1
                                instring += ascii( s[i] )
                            loop until level = 1
                            if instring <> "" then
                                tmp.init( instring )
                                array->add( @tmp )
                                instring = ""
                            endif
                        case asc("]")
                            if instring <> "" then
                                if isWhite( instring[0] ) = 0 then
                                    tmp.init( instring )
                                    array->add( @tmp )
                                endif
                            endif
                            instring = ""
                            level -= 1
                        case asc(",")
                            if inQuotes = 0 then
                                if instring <> "" then
                                    tmp.init( instring )
                                    array->add( @tmp )
                                    instring = ""
                                endif
                            else
                                instring += ascii( char2 )
                            endif
                        case asc("{")
                            dim as integer olevel = 1
                            instring += "{"
               
                            Do
                                i+=1
                                if s[i] = asc("{") then olevel += 1
                                if s[i] = asc("}") then olevel -= 1
                                instring += ascii( s[i] )
                            loop until olevel = 0
                           
                            if instring <> "" then
                                tmp.init( instring )
                                array->add( @tmp )
                                instring = ""
                            endif
                        case else
                            instring += ascii( char2 )
                           
                    end select
                    i+=1
                loop until level = 0
                arrayIsOpen = 0
           
            case asc("{")
                objectIsOpen = 1
                this.typ = _OBJECT_
                this.object = new varObject
                dim as integer olevel = 1, alevel, inQuotes = 0
                dim as string instring = "", key = ""
                dim as variable tmp
               
                Do
                    i+=1
                    dim as ubyte char2 = s[i]                   
                   
                    if isWhite( char2 ) AND inQuotes = 0 then continue do

                    if inQuotes = 1 then
                        if char2 <> 34 then
                            instring += ascii( char2 )
                            continue do
                        endif
                    endif
                   
                    select case char2                           
                        case asc(":")
                           key = instring
                           instring = ""
                        case asc("[")
                            alevel += 1
                            instring += ascii( char2 )
                        case asc("]")
                            alevel -= 1
                            instring += ascii( char2 )
                        case asc("{")
                            olevel += 1
                            instring += ascii( char2 )
                           
                            Do
                                i+=1
                                char2 = s[i]
                                if char2 = 34 then
                                    if inQuotes = 1 then inQuotes = 0 else inQuotes = 1
                                endif

                                if isWhite( char2 ) and inQuotes = 0 then Continue do                               
                                if char2 = asc("{") then olevel += 1
                                if char2 = asc("}") then olevel -= 1
                                if char2 = asc("[") then alevel += 1
                                if char2 = asc("]") then alevel -= 1
                                instring += ascii( char2 )
                            loop until olevel = 1 and alevel = 0
                           
                            if instring <> "" then
                                tmp.init( instring )
                                object->add( key, @tmp )
                                instring = ""
                            endif                           
                        case asc("}")
                            olevel -= 1
                            if olevel = 0 then
                                if instring <> "" then
                                    tmp.init( instring )
                                    object->add( key, @tmp )
                                    instring = ""
                                endif
                            endif
                        case asc(",")
                            if alevel = 0 then
                                if instring <> "" then
                                    tmp.init( instring )
                                    object->add( key, @tmp )
                                    instring = ""
                                endif
                            else
                                instring += ascii( char2 )
                            endif
                        case 34
                            instring += ascii( char2 )
                            if inQuotes = 1 then inQuotes = 0 else inQuotes = 1

                        case else                       
                            instring += ascii( char2 )
                    end select
                loop until olevel = 0
                objectIsOpen = 0
               
        end select
    next i
   
end sub

function variable.getType() as string
    select case typ
    case _NUMBER_:
        return "Number"
    case _STRING_:
        return "String"
    case _BOOL_:
        return "Boolean"
    case _ARRAY_:
        return "Array"
    case _OBJECT_:
        return "Object"
    case _NULL_:
        return "null"
    case _MALFORMED_:
        return "[MALFORMED]"
    end select
end function

function variable.getTypeNum() as vartype
    return typ
end function

function variable.toString() as string
    select case typ
    case _NUMBER_:
        return number & ""
    case _STRING_:
        return strng
    case _BOOL_:
        if bool then return "true"
        return "false"
    case _ARRAY_:
        return "ARRAY"
    case _OBJECT_:
        return "OBJECT"
    case _NULL_:
        return "null"
    case _MALFORMED_:
        return "[MALFORMED]"
  end select
end function

function variable.getNumber() as double
    if typ <> _NUMBER_ then return 0
    return number
end function

function variable.getString() as string
    if typ <> _STRING_ then return ""
    return strng
end function

function variable.getBoolean() as integer
    if typ <> _BOOL_ then return _FALSE_
    return bool
end function

function variable.getArray() as vararray ptr
    if typ <> _ARRAY_ then return NULL
    return array
end function

function variable.getObject() as varobject ptr
    if typ <> _OBJECT_ then return NULL
    return object
end function

declare function stringize_object( byref v as variable, byval l as integer = 0 ) as string
declare function stringize_array( byref v as variable ) as string

function stringize_array( byref v as variable ) as string
   if v.typ <> varType._ARRAY_ then return ""
   dim as integer length = v.array->size
   
   if length = 0 then return "[]"
   
   var s = "["   
   
   for i as integer = 0 to length - 1
      var tmp = *v.array->items(i)
      select case tmp.typ
         case _ARRAY_    : s += stringize_array( tmp )
         case _STRING_    :
            s += DBLQUOTE
            s += tmp.strng
            s += DBLQUOTE
         case _BOOL_      : s += tmp.toString
         case _NULL_      : s += "NULL"
         case _NUMBER_   : s &= tmp.number
         case _OBJECT_   : s += stringize_object( tmp )
      end select
      if i <> length-1 then s += "," else s += "]"
   next i
   
   return s   
end function

function stringize_object( byref v as variable, byval l as integer = 0 ) as string
   if v.typ <> varType._OBJECT_ then return ""
   dim as integer length = v.object->size
   dim as string s
    s += !"\n"
    for i2 as integer = 0 to l : s += !"\t" : next i2
    s += "{"
   
   for i as integer = 0 to length - 1
      var tkey = v.object->fields(i)->key
      s += !"\n\t"
        for i2 as integer = 0 to l : s += !"\t" : next i2
      s += tkey
      if len(tkey) > 6 then s += !":\t" else s+= !":\t\t"
      var tmp = *v.object->fields(i)->value
      select case tmp.typ
         case _ARRAY_    : s += stringize_array( tmp )
         case _BOOL_     : s += tmp.toString
         case _NULL_       : s += "NULL"
         case _NUMBER_   : s &= tmp.number
         case _OBJECT_   : s += stringize_object( tmp, l+1 )
         case _STRING_   :
            s += DBLQUOTE
            s += tmp.strng
            s += DBLQUOTE
      end select
      if i <> length-1 then
            s += ","
        else
            s += !"\n"
            for i2 as integer = 0 to l : s += !"\t" : next i2
            s += "}"
        endif
   next i
   
   return s
end function


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
dim as variable dic = "[1,2,3,4,5]"
'loadFileAsString( "Data/master.dictionary.json" )
var dic2 = dic

sleep
fxm
Posts: 9474
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Segfault in Let Operator

Postby fxm » Mar 23, 2016 15:30

Code: Select all

            case _OBJECT_
                this.object = new varObject
                for i as integer = 0 to rhs.object->size - 1
                    this.object->fields(i) = new varObjectField               '' The array 'fields()' has not been sized (Redim) before use
                    this.object->fields(i)->key = rhs.object->fields(i)->key
                    *this.object->fields(i)->value = *rhs.object->fields(i)->value
                next i
            case _ARRAY_
                this.array = new varArray
                for i as integer = 0 to rhs.array->size - 1
                    this.array->items(i) = new variable                       '' The array 'items()' has not been sized (Redim) before use
                    *this.array->items(i) = *rhs.array->items(i)
                next i

Similar problem also elsewhere, so at least:
- in 'Constructor variable( byref rhs as variable )', two times
- in 'Operator variable.Let( byref rhs as variable )', two times
- in 'sub copy_variable( byref var1 as variable, byref var2 as variable )', two times
rolliebollocks
Posts: 2655
Joined: Aug 28, 2008 10:54
Location: new york

Re: Segfault in Let Operator

Postby rolliebollocks » Mar 23, 2016 18:58

Derp. Thanks fxm. Obvious mistake.

Return to “General”

Who is online

Users browsing this forum: No registered users and 0 guests