diff --git a/include/std/math.e b/include/std/math.e
index a2572b900..30265afde 100644
--- a/include/std/math.e
+++ b/include/std/math.e
@@ -1483,6 +1483,9 @@ end function
--****
-- === Bitwise Operations
--
+-- Arguments passed to bitwise operations are interpreted as sequences of bits and these sequences are operated on and the result is returned, which is another sequence of bits, is returned as a number. The numbers passed when using ix86 and ARM archetecture must use no more than 32-bits and have no fraction part. Numbers that use no more than 32-bits are numbers between -2_147_483_648 to 4_294_967_295. Numbers that have a fraction part or are outside this range will not yield the results that a calculator that uses more bits would get.
+--
+--
--****
-- Signature:
@@ -1507,7 +1510,7 @@ end function
--
-- If you intend to manipulate full 32-bit values, you should declare your variables as atom, rather than integer. Euphoria's integer type is limited to 31-bits.
--
--- Results are treated as signed numbers. They will be negative when the highest-order bit is 1.
+-- Results are treated as unsigned numbers. They will never be negative.
--
-- To understand the binary representation of a number you should display it in hexadecimal notation.
-- Use the %x format of [[:printf]]. Using [[:int_to_bits]] is an even more direct approach.
@@ -1527,10 +1530,7 @@ end function
-- Example 3:
--
-- a = and_bits(#FFFFFFFF, #FFFFFFFF)
--- -- a is -1
--- -- Note that #FFFFFFFF is a positive number,
--- -- but the result of a bitwise operation is interpreted
--- -- as a signed 32-bit number, so it's negative.
+-- -- a is #FFFFFFFF
--
--
-- See Also:
@@ -1558,7 +1558,7 @@ end function
--
-- If you intend to manipulate full 32-bit values, you should declare your variables as atom, rather than integer. Euphoria's integer type is limited to 31-bits.
--
--- Results are treated as signed numbers. They will be negative when the highest-order bit is 1.
+-- Results are treated as unsigned numbers. They will never be negative.
--
-- Example 1:
--
@@ -1590,7 +1590,7 @@ end function
--
-- If you intend to manipulate full 32-bit values, you should declare your variables as atom, rather than integer. Euphoria's integer type is limited to 31-bits.
--
--- Results are treated as signed numbers. They will be negative when the highest-order bit is 1.
+-- Results are treated as unsigned numbers. They will never be negative.
--
-- Example 1:
--
@@ -1628,14 +1628,14 @@ end function
--
-- If you intend to manipulate full 32-bit values, you should declare your variables as atom, rather than integer. Euphoria's integer type is limited to 31-bits.
--
--- Results are treated as signed numbers. They will be negative when the highest-order bit is 1.
+-- Results are treated as unsigned numbers. They will never be negative.
--
--- A simple equality holds for an atom ##a##: ##a + not_bits(a) = -1##.
+-- A simple equality holds for an atom ##a##: ##a + not_bits(a) + 1 = power(2,32)##.
--
-- Example 1:
--
-- a = not_bits(#000000F7)
--- -- a is -248 (i.e. FFFFFF08 interpreted as a negative number)
+-- -- a is #FFFFFF08 (interpreted as a positive number)
--
--
-- See Also:
@@ -1662,20 +1662,26 @@ end function
--
-- Example 1:
--
--- ? shift_bits((7, -3) --> 56
--- ? shift_bits((0, -9) --> 0
--- ? shift_bits((4, -7) --> 512
--- ? shift_bits((8, -4) --> 128
--- ? shift_bits((0xFE427AAC, -7) --> 0x213D5600
--- ? shift_bits((-7, -3) --> -56 which is 0xFFFFFFC8
--- ? shift_bits((131, 0) --> 131
--- ? shift_bits((184.464, 0) --> 184
--- ? shift_bits((999_999_999_999_999, 0) --> -1530494977 which is 0xA4C67FFF
--- ? shift_bits((184, 3) -- 23
--- ? shift_bits((48, 2) --> 12
--- ? shift_bits((121, 3) --> 15
--- ? shift_bits((0xFE427AAC, 7) --> 0x01FC84F5
--- ? shift_bits((-7, 3) --> 0x1FFFFFFF
+-- ? shift_bits(7, -3) --> shift_bits(0b111, -3) -> 0b111000 (which is 56)
+-- ? shift_bits(0, -9) --> shift_bits(0b0, -9) -> 0b0000000000 -> 0
+-- ? shift_bits(4, -7) --> shift_bits(0b100, -7) -> 0b1000000000 (which is 512)
+-- ? shift_bits(8, -4) --> shift_bits(0b1000, -4) -> 0b1000_0000 (which is 128)
+-- ? shift_bits(0xFE427AAC, -7) --> shift_bits(0b11111110010000100111101010101100, -7)
+-- --> 0b00100001001111010101011000000000
+-- -- (which is 557_667_840)
+-- ? shift_bits(-7, -3) -->
+-- --> shift_bits(0b11111111111111111111111111111001, -3)
+-- --> 0b11111111111111111111111111001000 ( which is 4_294_967_240)
+-- ? shift_bits(131, 0) --> 131
+-- ? shift_bits(184.464, 0) --> 184
+-- ? shift_bits(999_999_999_999_999, 0) --> 0xA4C67FFF
+-- ? shift_bits(184, 3) -- 23
+-- ? shift_bits(48, 2) --> 12
+-- ? shift_bits(121, 3) --> 15
+-- ? shift_bits(0xFE427AAC, 7) --> 0x01FC84F5
+-- ? shift_bits(-7, 3) --> 0x1FFFFFFF (which is 536_870_911)
+-- --> shift_bits(0b11111111111111111111111111111001, 3)
+-- --> 0b00011111111111111111111111111111 ( which is 536_870_911)
-- ? shift_bits({48, 121}, 2) --> {12, 30}
--
--
@@ -1739,13 +1745,13 @@ end function
-- ? rotate_bits(4, -7) --> 512
-- ? rotate_bits(8, -4) --> 128
-- ? rotate_bits(0xFE427AAC, -7) --> 0x213D567F
--- ? rotate_bits(-7, -3) --> -49 which is 0xFFFFFFCF
+-- ? rotate_bits(-7, -3) --> 4_294_967_247 which is 0xFFFFFFCF
-- ? rotate_bits(131, 0) --> 131
-- ? rotate_bits(184.464, 0) --> 184
--- ? rotate_bits(999_999_999_999_999, 0) --> -1530494977 which is 0xA4C67FFF
+-- ? rotate_bits(999_999_999_999_999, 0) --> 2_764_472_319 which is 0xA4C67FFF
-- ? rotate_bits(184, 3) -- 23
-- ? rotate_bits(48, 2) --> 12
--- ? rotate_bits(121, 3) --> 536870927
+-- ? rotate_bits(121, 3) --> 536_870_927
-- ? rotate_bits(0xFE427AAC, 7) --> 0x59FC84F5
-- ? rotate_bits(-7, 3) --> 0x3FFFFFFF
-- ? rotate_bits({48, 121}, 2) --> {12, 1073741854}
diff --git a/include/std/net/http.e b/include/std/net/http.e
index 07886b67c..544761392 100644
--- a/include/std/net/http.e
+++ b/include/std/net/http.e
@@ -13,10 +13,10 @@ include std/sequence.e
include std/socket.e as sock
include std/text.e
include std/types.e
-
+include std/search.e
include std/net/dns.e
include std/net/url.e as url
-
+include std/get.e
include euphoria/info.e
ifdef not EUC_DLL then
@@ -106,17 +106,23 @@ function format_base_request(sequence request_type, sequence url, object headers
-- only specify the port in the request if the caller did so explicitly
-- some sites, such as euphoria.pastey.net, will break otherwise
+ -- HTTP/1.0 lacks the host header field. Use HTTP/1.1.
if noport then
- request = sprintf("%s %s HTTP/1.0\r\nHost: %s\r\n", {
- request_type, path, host })
+ request = sprintf("%s %s HTTP/1.1\r\nHost: %s\r\n", {
+ request_type, path, host })
else
- request = sprintf("%s %s HTTP/1.0\r\nHost: %s:%d\r\n", {
- request_type, path, host, port })
+ request = sprintf("%s %s HTTP/1.1\r\nHost: %s:%d\r\n", {
+ request_type, path, host, port })
end if
integer has_user_agent = 0
integer has_connection = 0
+ if sequence(parsedUrl[URL_USER]) and sequence(parsedUrl[URL_PASSWORD]) then
+ --request &= sprintf("%s: %s:%s\r\n", {"Authorization",parsedUrl[URL_USER],parsedUrl[URL_PASSWORD]})
+
+ end if
+
if sequence(headers) then
for i = 1 to length(headers) do
object header = headers[i]
@@ -235,7 +241,8 @@ function execute_request(sequence host, integer port, sequence request, integer
sock:socket sock = sock:create(sock:AF_INET, sock:SOCK_STREAM, 0)
- if sock:connect(sock, addrinfo[3][1], conn_port) != sock:OK then
+ if sock:connect(sock, addrinfo[3][1], port) != sock:OK then
+ sock:close(sock)
return ERR_CONNECT_FAILED
end if
@@ -262,6 +269,7 @@ function execute_request(sequence host, integer port, sequence request, integer
-- a disconnect.
exit "top"
else
+ sock:close(sock)
return ERR_RECEIVE_FAILED
end if
end if
@@ -299,11 +307,31 @@ function execute_request(sequence host, integer port, sequence request, integer
end if
end while
+ sock:close(sock)
return { headers, content }
end function
--****
-- === Configuration Routines
+--@nodoc@
+-- When returned headers redirect to another url, return a fully
+-- qualified proper url.
+function redirect_url(sequence request, sequence headers)
+ for i = 1 to length(headers) do
+ sequence headers_i = headers[i]
+ if equal(headers_i[1],"location") then
+ sequence new_url = headers_i[2]
+ if new_url[1] = '/' then
+ if not find(request[R_PORT], {0,""}) then
+ new_url = ":" & request[R_PORT] & new_url
+ end if
+ new_url = "http://" & request[R_HOST] & new_url
+ end if
+ return new_url
+ end if
+ end for
+ return sprintf("http://%s:%s/%s", { request[R_HOST], request[R_PORT], request[R_PATH] })
+end function
sequence proxy_ip = {}
integer proxy_port = 0
@@ -378,71 +406,102 @@ end procedure
-- See Also:
-- [[:http_get]]
--
-
public function http_post(sequence url, object data, object headers = 0,
natural follow_redirects = 10, natural timeout = 15)
+
if not sequence(data) or length(data) = 0 then
return ERR_INVALID_DATA
end if
- object request = format_base_request("POST", url, headers)
- if atom(request) then
- return request
- end if
-
- integer data_type
- if ascii_string(data) or sequence(data[1]) then
- data_type = FORM_URLENCODED
- else
- if data[1] < 1 or data[1] > 2 then
- return ERR_INVALID_DATA_ENCODING
+ object content, request
+ sequence content_1
+ while follow_redirects > 0 and length(content)=2 and length(content_1) >= 1 and length(content_1[1]) >= 2 and equal(content_1[2][2], "303") with entry do
+ follow_redirects -= 1
+ --sequence http_response_code = content[1][1][2]
+ -- 301, 302, 307 : must not be redirected without user interaction (RFC 2616)
+ url = redirect_url(request, content_1)
+ entry
+
+ request = format_base_request("POST", url, headers)
+ if atom(request) then
+ return request
end if
-
- data_type = data[1]
- data = data[2]
- end if
-
- -- data now contains either a string sequence already encoded or
- -- a sequence of key/value pairs to be encoded. We know the length
- -- is greater than 0, so check the first element to see if it's a
- -- sequence or an atom. That will tell us what we have.
- --
- -- If we have key/value pairs then we will need to encode that data
- -- according to our data_type.
-
- sequence content_type = ENCODING_STRINGS[data_type]
- if sequence(data[1]) then
- -- We have key/value pairs
- if data_type = FORM_URLENCODED then
- data = form_urlencode(data)
+
+ integer data_type
+ if ascii_string(data) or sequence(data[1]) then
+ data_type = FORM_URLENCODED
else
- sequence boundary = random_boundary(20)
- content_type &= "; boundary=" & boundary
- data = multipart_form_data_encode(data, boundary)
+ if data[1] < 1 or data[1] > 2 then
+ return ERR_INVALID_DATA_ENCODING
+ end if
+
+ data_type = data[1]
+ data = data[2]
end if
- end if
-
- request[R_REQUEST] &= sprintf("Content-Type: %s\r\n", { content_type })
- request[R_REQUEST] &= sprintf("Content-Length: %d\r\n", { length(data) })
- request[R_REQUEST] &= "\r\n"
- request[R_REQUEST] &= data
-
- object content = execute_request(request[R_HOST], request[R_PORT], request[R_REQUEST], timeout)
- if follow_redirects and length(content)=2 then
- sequence content_1 = content[1]
- if length(content_1) >= 1 and length(content_1[1]) >= 2 and equal(content_1[2][2], "303") then
- --sequence http_response_code = content[1][1][2]
- -- 301, 302, 307 : must not be redirected without user interaction (RFC 2616)
- for i = 1 to length(content_1) do
- sequence headers_i = content_1[i]
- if equal(headers_i[1],"location") then
- return http_get(headers_i[2], headers, follow_redirects-1, timeout)
- end if
- end for
+
+ -- data now contains either a string sequence already encoded or
+ -- a sequence of key/value pairs to be encoded. We know the length
+ -- is greater than 0, so check the first element to see if it's a
+ -- sequence or an atom. That will tell us what we have.
+ --
+ -- If we have key/value pairs then we will need to encode that data
+ -- according to our data_type.
+
+ sequence content_type = ENCODING_STRINGS[data_type]
+ if sequence(data[1]) then
+ -- We have key/value pairs
+ if data_type = FORM_URLENCODED then
+ data = form_urlencode(data)
+ else
+ sequence boundary = random_boundary(20)
+ content_type &= "; boundary=" & boundary
+ data = multipart_form_data_encode(data, boundary)
+ end if
+ end if
+ request = format_base_request("POST", url, headers)
+ request[R_REQUEST] &= sprintf("Content-Type: %s\r\n", { content_type })
+ request[R_REQUEST] &= sprintf("Content-Length: %d\r\n", { length(data) })
+ request[R_REQUEST] &= "\r\n"
+ request[R_REQUEST] &= data
+ content = execute_request(request[R_HOST], request[R_PORT], request[R_REQUEST], timeout)
+ if length(content) != 2 or atom(content[1]) then
+ return ERR_INVALID_DATA_ENCODING
end if
+ content_1 = content[1]
+ end while
+
+ -- The value in content[2] is in Chunked Transfer encoding.
+ -- See:http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
+
+ -- We get in content[2] something like "7\r\nsucess\r\n0\r\n"
+ -- ^ ^
+ -- | |
+ -- | eo_chunk
+ -- bo_chunk
+ --
+ sequence chunk_size = value(content[2])
+ integer bo_chunk = match({13,10}, content[2]) + 2
+
+ if bo_chunk = 2 or -- no size specified
+ chunk_size[1] != GET_SUCCESS or -- size wasn't a readable object
+ not integer(chunk_size[2]) or -- size wasn't an integer
+ bo_chunk+chunk_size[2] > length(content[2]) then -- end of chunk theoretically extends past content[2]
+ return ERR_INVALID_DATA_ENCODING
end if
+ -- Using chunk_size[2] as the length causes this code to fail a unit test.
+ -- So don't do that. Even though that is what the RFC specifies.
+
+ -- Don't trust chunk_size[2] instead ensure the chunk extends up to the next \r\n
+
+ -- We use a forward search from chunk_size[2].
+ integer eo_chunk = match({13,10}, content[2], bo_chunk+chunk_size[2]-1)-1
+
+ if eo_chunk = -1 then
+ return ERR_INVALID_DATA_ENCODING
+ end if
+ content[2] = content[2][bo_chunk..eo_chunk]
return content
end function
@@ -481,30 +540,28 @@ end function
public function http_get(sequence url, object headers = 0, natural follow_redirects = 10,
natural timeout = 15)
- object request
-
- request = format_base_request("GET", url, headers)
+ object request, content
+ sequence content_1
- if atom(request) then
- return request
- end if
-
- -- No more work necessary, terminate the request with our ending CR LF
- request[R_REQUEST] &= "\r\n"
-
- object content = execute_request(request[R_HOST], request[R_PORT], request[R_REQUEST], timeout)
- if follow_redirects and length(content)=2 then
- sequence content_1 = content[1]
- if length(content_1) >= 1 and length(content_1[1]) >= 2 and
- find(content_1[1][2], {"301","302","303","307","308"}) then
- for i = 1 to length(content_1) do
- sequence headers_i = content_1[i]
- if equal(headers_i[1],"location") then
- return http_get(headers_i[2], headers, follow_redirects-1, timeout)
- end if
- end for
+ while follow_redirects > 0 and length(content_1) >= 1 and length(content_1[1]) >= 2 and
+ find(content_1[1][2], {"301","302","303","307","308"}) with entry do
+ follow_redirects -= 1
+
+ url = redirect_url(request, content_1)
+ entry
+ request = format_base_request("GET", url, headers)
+
+ if atom(request) then
+ return request
end if
- end if
+ -- No more work necessary, terminate the request with our ending CR LF
+ request[R_REQUEST] &= "\r\n"
+ content = execute_request(request[R_HOST], request[R_PORT], request[R_REQUEST], timeout)
+ if length(content) != 2 then
+ exit
+ end if
+ content_1 = content[1]
+ end while
return content
end function
diff --git a/include/std/utils.e b/include/std/utils.e
index 426ea16c0..39145521f 100644
--- a/include/std/utils.e
+++ b/include/std/utils.e
@@ -57,6 +57,40 @@ public function iif(atom test, object ifTrue, object ifFalse)
return ifFalse
end function
+public function assign(integer i1, object val1,
+ integer i2 = 0, object val2 = 0,
+ integer i3 = 0, object val3 = 0,
+ integer i4 = 0, object val4 = 0,
+ integer i5 = 0, object val5 = 0,
+ integer i6 = 0, object val6 = 0,
+ integer i7 = 0, object val7 = 0,
+ integer i8 = 0, object val8 = 0,
+ integer i9 = 0, object val9 = 0,
+ integer i10 = 0, object val10 = 0)
+ sequence s = {i1, val1, i2, val2, i3, val3, i4, val4, i5, val5, i6, val6, i7, val7, i8, val8, i9, val9, i10, val10}
+ for i = 3 to 19 by 2 do
+ if s[i] = 0 then
+ return assign_s(s[1..i-1])
+ end if
+ end for
+ return assign_s(s)
+end function
+
+function assign_s(sequence s)
+ integer maxi
+ sequence ret
+ maxi=0
+ for i = 1 to length(s) by 2 do
+ if s[i] > maxi then
+ maxi = s[i]
+ end if
+ end for
+ ret = repeat(0,maxi)
+ for i = 1 to length(s) by 2 do
+ ret[s[i]] = s[i+1]
+ end for
+ return ret
+end function
--**
-- @nodoc@
diff --git a/source/common.e b/source/common.e
index f13f21450..6b386c385 100644
--- a/source/common.e
+++ b/source/common.e
@@ -9,6 +9,8 @@ elsedef
without type_check
end ifdef
+with type_check
+
include std/os.e
include std/filesys.e
include std/search.e
@@ -22,6 +24,7 @@ public constant
DIRECT_OR_PUBLIC_INCLUDE = DIRECT_INCLUDE + PUBLIC_INCLUDE,
ANY_INCLUDE = DIRECT_OR_PUBLIC_INCLUDE + INDIRECT_INCLUDE
+
public sequence SymTab = {} -- the symbol table
public sequence known_files = {}
diff --git a/source/parser.e b/source/parser.e
index 482cb4cca..b77d9ecc1 100644
--- a/source/parser.e
+++ b/source/parser.e
@@ -3446,7 +3446,7 @@ function Global_declaration(integer type_ptr, integer scope)
token tok
object tsym
object prevtok = 0
- symtab_index sym, valsym
+ symtab_index sym, valsym, prevsym = 0, deltasym = 0
integer h, count = 0
atom val = 1, usedval
integer deltafunc = '+'
@@ -3499,6 +3499,8 @@ function Global_declaration(integer type_ptr, integer scope)
negate = 1
ptok = next_token()
end if
+
+
if ptok[T_ID] != ATOM then
CompileErr( A_NUMERIC_LITERAL_WAS_EXPECTED)
end if
@@ -3519,7 +3521,16 @@ function Global_declaration(integer type_ptr, integer scope)
end switch
+ if integer(delta) then
+ deltasym = NewIntSym(delta)
+ else
+ deltasym = NewDoubleSym(delta)
+ end if
else
+ deltasym = NewIntSym(1)
+ if deltasym > 0 then
+ SymTab[deltasym][S_USAGE] = U_READ
+ end if
putback(ptok)
end if
end if
@@ -3572,7 +3583,7 @@ function Global_declaration(integer type_ptr, integer scope)
SymTab[sym][S_USAGE] = U_WRITTEN
if TRANSLATE then
SymTab[sym][S_GTYPE] = TYPE_OBJECT
- SymTab[sym][S_OBJ] = NOVALUE -- distinguish from literals
+ SymTab[sym][S_OBJ] = NOVALUE -- distinguish from literals
end if
valsym = Top()
@@ -3603,6 +3614,8 @@ function Global_declaration(integer type_ptr, integer scope)
end if
end if
+
+ -- end CONSTANT
elsif type_ptr = -1 and not is_fwd_ref then
-- ENUM
StartSourceLine(FALSE, , COVERAGE_OVERRIDE )
@@ -3610,77 +3623,87 @@ function Global_declaration(integer type_ptr, integer scope)
-- temporarily hide sym so it can't be used in defining itself
buckets[SymTab[sym][S_HASHVAL]] = SymTab[sym][S_SAMEHASH]
tok = next_token()
-
-
+ StartSourceLine(FALSE, , COVERAGE_OVERRIDE)
emit_opnd(sym)
if tok[T_ID] = EQUALS then
- integer negate = 1
+ Expr()
+ buckets[SymTab[sym][S_HASHVAL]] = sym
+ SymTab[sym][S_USAGE] = U_WRITTEN
- tok = next_token()
- if tok[T_ID] = MINUS then
- negate = -1
- tok = next_token()
+ valsym = Top()
+
+ if TRANSLATE then
+ SymTab[sym][S_GTYPE] = TYPE_OBJECT
+ SymTab[sym][S_OBJ] = NOVALUE -- distinguish from literals
end if
- if tok[T_ID] = ATOM then
- valsym = tok[T_SYM]
- elsif tok[T_SYM] > 0 then
- tsym = SymTab[tok[T_SYM]]
- if tsym[S_MODE] = M_CONSTANT then
- if length(tsym) >= S_CODE and tsym[S_CODE] then
- valsym = tsym[S_CODE]
-
- elsif not equal( tsym[S_OBJ], NOVALUE ) then
- if is_integer(tsym[S_OBJ]) then
- valsym = tok[T_SYM]
- else
- CompileErr(AN_ENUM_CONSTANT_MUST_BE_AN_INTEGER)
- end if
- else
- CompileErr(ENUM_CONSTANTS_MUST_BE_ASSIGNED_AN_INTEGER)
- end if
- elsif tsym[S_OBJ] = NOVALUE then
- -- forward reference
- CompileErr(ENUM_FWD_REFERENCES_NOT_SUPPORTED)
- else
- CompileErr(INTEGER_OR_CONSTANT_EXPECTED)
-
- end if
- else -- tok[T_ID] != ATOM and tok[T_SYM] !> 0
- CompileErr(INTEGER_OR_CONSTANT_EXPECTED)
- end if
- valsym = tok[T_SYM]
- if not atom( SymTab[valsym][S_OBJ] ) and tsym[S_SCOPE] != SC_UNDEFINED then
- CompileErr(ENUM_CONSTANTS_MUST_BE_INTEGERS)
- end if
- val = SymTab[valsym][S_OBJ] * negate
- if is_integer(val) then
- Push(NewIntSym(val))
+ valsym = Top()
+
+ emit_op(ASSIGN)
+ if Last_op() = ASSIGN then
+ valsym = get_assigned_sym()
else
- Push(NewDoubleSym(val))
+ -- something else happened...could be a built-in
+ valsym = -1
end if
- usedval = val
- if deltafunc = '+' then
- val += delta
- else
- val *= delta
+ if valsym > 0 and compare( SymTab[valsym][S_OBJ], NOVALUE ) then
+ -- need to remember this for select/case statements
+ SymTab[sym][S_CODE] = valsym
end if
- else
- putback(tok)
- if is_integer(val) then
- Push(NewIntSym(val))
- else
- Push(NewDoubleSym(val))
+
+ if TRANSLATE then
+ count += 1
+ if count = 10 then
+ count = 0
+ -- break up really long declarations
+ emit_op( RETURNT )
+ end if
+ SymTab[sym][S_USAGE] = U_READ
+ valsym = get_assigned_sym()
end if
- usedval = val
- if deltafunc = '+' then
- val += delta
+
+ else
+
+ buckets[SymTab[sym][S_HASHVAL]] = sym
+ SymTab[sym][S_USAGE] = U_WRITTEN
+ if prevsym = 0 then
+ symtab_index one = NewIntSym(1)
+ SymTab[one][S_USAGE] = U_USED
+ emit_opnd(sym)
+ emit_opnd(one)
+ SymTab[sym][S_CODE] = one
+ emit_op(ASSIGN)
+ valsym = Top()
else
- val *= delta
+ emit_opnd(deltasym)
+ emit_opnd(prevsym)
+ SymTab[deltasym][S_USAGE] = U_READ
+ switch deltafunc do
+ case '+', '-' then
+ emit_op(reserved:PLUS)
+ case else
+ emit_op(reserved:MULTIPLY)
+ end switch
+ SymTab[Top()][S_USAGE] = U_READ
+ emit_opnd(sym)
+ emit_opnd(Top())
+ emit_op(ASSIGN)
+
+ SymTab[sym][S_USAGE] = U_READ
+ valsym = get_assigned_sym()
end if
+ if valsym > 0 and compare( SymTab[valsym][S_OBJ], NOVALUE ) then
+ -- need to remember this for select/case statements
+ SymTab[sym][S_CODE] = valsym
+ end if
+ putback(tok)
valsym = 0
end if
+ -- forbid sequences
+ emit_opnd(sym)
+ op_info1 = sym
+ emit_op(ATOM_CHECK)
buckets[SymTab[sym][S_HASHVAL]] = sym
SymTab[sym][S_USAGE] = U_WRITTEN
@@ -3689,41 +3712,7 @@ function Global_declaration(integer type_ptr, integer scope)
SymTab[sym][S_OBJ] = NOVALUE -- distinguish from literals
end if
- if valsym < 0 then
- -- fwd reference
-
- end if
-
- if valsym and compare( SymTab[valsym][S_OBJ], NOVALUE ) then
- -- need to remember this for select/case statements
- SymTab[sym][S_CODE] = valsym
- SymTab[sym][S_OBJ] = usedval
-
- if TRANSLATE then
- -- Let the translator know about its value
- SymTab[sym][S_GTYPE] = SymTab[valsym][S_GTYPE]
- SymTab[sym][S_SEQ_ELEM] = SymTab[valsym][S_SEQ_ELEM]
- SymTab[sym][S_OBJ_MIN] = usedval
- SymTab[sym][S_OBJ_MAX] = usedval
- SymTab[sym][S_SEQ_LEN] = SymTab[valsym][S_SEQ_LEN]
- end if
- else
- SymTab[sym][S_OBJ] = usedval
- if TRANSLATE then
- -- Let the translator know about its value
- if is_integer( usedval ) then
- SymTab[sym][S_GTYPE] = TYPE_INTEGER
- else
- SymTab[sym][S_GTYPE] = TYPE_DOUBLE
- end if
- SymTab[sym][S_SEQ_ELEM] = 0
- SymTab[sym][S_OBJ_MIN] = usedval
- SymTab[sym][S_OBJ_MAX] = usedval
- SymTab[sym][S_SEQ_LEN] = 0 --SymTab[valsym][S_SEQ_LEN]
- end if
- end if
- valsym = Pop()
- valsym = Pop()
+ -- end of ENUM
else
-- variable
SymTab[sym][S_MODE] = M_NORMAL
@@ -3752,6 +3741,7 @@ function Global_declaration(integer type_ptr, integer scope)
exit
end if
prevtok = tok
+ prevsym = sym
end while
putback(tok)
return new_symbols
@@ -4105,7 +4095,6 @@ procedure SubProg(integer prog_type, integer scope, integer deprecated)
integer first_def_arg
integer again
integer type_enum
- object seq_sym
object i1_sym
sequence enum_syms = {}
integer type_enum_gline, real_gline
@@ -4140,7 +4129,6 @@ procedure SubProg(integer prog_type, integer scope, integer deprecated)
-- range of the enum is accepted
-- as valid.
i1_sym = keyfind("i1",-1)
- seq_sym = NewStringSym(seq_symbol)
putback(keyfind("return",-1))
putback({RIGHT_ROUND,0})
putback(i1_sym)
@@ -4379,25 +4367,29 @@ procedure SubProg(integer prog_type, integer scope, integer deprecated)
-- Parse a list of statements
stmt_nest += 1
tok_match(RETURN)
- putback({RIGHT_ROUND,0})
- putback({VARIABLE,seq_sym})
- putback({COMMA,0})
- putback(i1_sym)
- putback({LEFT_ROUND,0})
- putback(keyfind("find",-1))
- if not TRANSLATE then
- if OpTrace then
- emit_op(ERASE_PRIVATE_NAMES)
- emit_addr(CurrentSub)
- end if
- end if
- Expr()
- FuncReturn = TRUE
+ emit_opnd(i1_sym[T_SYM])
+ emit_opnd(enum_syms[1])
+ emit_op(EQUAL)
+ SymTab[Top()][S_USAGE] = U_USED
+ for ei = 2 to length(enum_syms) do
+ symtab_index last_comparison = Top()
+ emit_opnd(i1_sym[T_SYM])
+ emit_opnd(enum_syms[ei])
+ emit_op(EQUAL)
+ SymTab[Top()][S_USAGE] = U_USED
+ emit_opnd(Top())
+ emit_opnd(last_comparison)
+ emit_op(OR)
+ SymTab[Top()][S_USAGE] = U_USED
+ end for
+ emit_opnd(Top())
emit_op(RETURNF)
flush_temps()
stmt_nest -= 1
InitDelete()
flush_temps()
+ FuncReturn = TRUE
+ tok_match(END)
else
Statement_list()
-- parse routine end.
diff --git a/source/scanner.e b/source/scanner.e
index 5b403dc08..23f1d0fde 100644
--- a/source/scanner.e
+++ b/source/scanner.e
@@ -1217,7 +1217,7 @@ function my_sscanf(sequence yytext)
elsifdef BITS64 then
mantissa = scientific_to_atom( yytext, EXTENDED )
elsedef
- InternalErr( 351, "Scanning scientific notation in my_sscanf" )
+ InternalErr( ERROR_IN_PARSING_SCIENTIFIC_NOTATION, "Scanning scientific notation in my_sscanf" )
end ifdef
goto "floating_point_check"
end if
@@ -1229,8 +1229,7 @@ function my_sscanf(sequence yytext)
yytext &= 0 -- end marker
c = yytext[1]
i = 2
-
-
+
while c >= '0' and c <= '9' do
ndigits += 1
mantissa = mantissa * 10.0 + (c - '0')
@@ -1238,31 +1237,59 @@ function my_sscanf(sequence yytext)
i += 1
end while
- if fenv:test(FE_OVERFLOW) then
- real_overflow = 1
- end if
-
- if c = '.' then
+ -- indicates whether the value the user entered was not zero
+ integer not_zero = 0
+ if c = '.' and not fenv:test(FE_OVERFLOW) then
-- get fraction
c = yytext[i]
i += 1
+ -- backup value of dec
+ atom back_dec
+ -- the denomonator of the fraction part
dec = 1.0
- atom frac = 0
+ -- its backup and the numerator of the fraction part
+ atom num_back, num = 0
while c >= '0' and c <= '9' do
ndigits += 1
- frac = frac * 10 + (c - '0')
+ if c != '0' then
+ not_zero = 1
+ end if
+ num_back = num
+ num = num_back * 10 + (c - '0')
+ -- if num = PINF, so also will be dec in this iteration
+ back_dec = dec
dec *= 10.0
c = yytext[i]
i += 1
+ if dec = PINF then
+ -- clear FE_OVERFLOW, for it only means there
+ -- are more digits after the decimal than we
+ -- can use to calculate a fraction.
+ fenv:clear(fenv:FE_OVERFLOW)
+ num = num_back
+ dec = back_dec
+ exit
+ end if
end while
- mantissa += frac / dec
+ -- keep looking for non-zero digits.
+ while c >= '0' and c <= '9' do
+ if c != '0' then
+ not_zero = 1
+ exit
+ end if
+ c = yytext[i]
+ i += 1
+ end while
+ atom frac
+ frac = num / dec
+ mantissa += frac
+ if frac = 0 and not_zero then
+ -- the literal represents a non-zero number that
+ -- is too small to be representable as an atom.
+ fenv:raise(fenv:FE_UNDERFLOW)
+ end if
end if
- if fenv:test(fenv:FE_OVERFLOW) and not real_overflow then
- fenv:clear(fenv:FE_OVERFLOW)
- fenv:raise(fenv:FE_UNDERFLOW)
- end if
-
if ndigits = 0 then
CompileErr(NUMBER_NOT_FORMED_CORRECTLY) -- no digits
end if
diff --git a/tests/t_881-1.e b/tests/t_881-1.e
index 2c149588d..c4732e9ed 100644
--- a/tests/t_881-1.e
+++ b/tests/t_881-1.e
@@ -1,11 +1,10 @@
---Code is: { (63)FLOOR_DIV match, (149)ASSIGN_OP_SUBS b, (145)SC2_NULL , (154)SYSTEM_EXEC foo_1__tmp_at1, (56)AND_BITS gets, (154)SYSTEM_EXEC foo_1__tmp_at1, (147)SC1_OR_IF , (151)PROFILE s0, (159)NOP
function foo(integer x)
return and_bits(floor(x/{#40,#08,#1}), #7)
end function
constant b = #AA
-sequence s0 = foo(b)
+sequence s0 = foo(b)
include std/unittest.e
diff --git a/tests/t_c_enum_strings.d/control.err b/tests/t_c_enum_strings.d/control.err
index e15d07c17..c4a3e4ec2 100644
--- a/tests/t_c_enum_strings.d/control.err
+++ b/tests/t_c_enum_strings.d/control.err
@@ -1,17 +1,4 @@
t_c_enum_strings.e:4
-<0030>:: An enum constant must be an integer
- MONDAY = "Monday",
- ^
+type_check failure, MONDAY is {77'M',111'o',110'n',100'd',97'a',121'y'}
---- Defined Words ---
-EU4
-EU400
-EU40000
-WINDOWS
-WIN32
-WIN32_CONSOLE
-UNITTEST
-CRASH
-EUI
--------------------
diff --git a/tests/t_c_enum_strings_sneaky.d/control.err b/tests/t_c_enum_strings_sneaky.d/control.err
new file mode 100644
index 000000000..5bc38f1c0
--- /dev/null
+++ b/tests/t_c_enum_strings_sneaky.d/control.err
@@ -0,0 +1,6 @@
+t_c_enum_strings_sneaky.e:4
+type_check failure, FLAG1 is {0,1}
+
+
+Public & Export & Global & Local Variables
+
diff --git a/tests/t_c_enum_strings_sneaky.e b/tests/t_c_enum_strings_sneaky.e
new file mode 100644
index 000000000..6d20f9d13
--- /dev/null
+++ b/tests/t_c_enum_strings_sneaky.e
@@ -0,0 +1,9 @@
+include std/unittest.e
+
+enum type w32flagsAndEx by *2
+ FLAG1 = 0 & 1,
+ FLAG2 = 0 & 2,
+ FLAG3 = 0 & 4
+end type
+
+test_pass("t_c_enum_strings_sneaky")
diff --git a/tests/t_c_fwd_enum_type.d/control.err b/tests/t_c_fwd_enum_type.d/control.err
index 7d95a380d..8b1256562 100644
--- a/tests/t_c_fwd_enum_type.d/control.err
+++ b/tests/t_c_fwd_enum_type.d/control.err
@@ -1,7 +1,6 @@
t_c_fwd_enum_type.e:11
-<0331>:: Forward references are not supported for enums
- THURSDAY = foo,
- ^
-
-
+<0074>:: Errors resolving the following references:
+ 'foo' (t_c_fwd_enum_type.e:11) has not been declared.
+ THURSDAY = foo,
+ ^
diff --git a/tests/t_enum_expressions.e b/tests/t_enum_expressions.e
new file mode 100644
index 000000000..6286c0be3
--- /dev/null
+++ b/tests/t_enum_expressions.e
@@ -0,0 +1,20 @@
+include std/unittest.e
+
+enum type numbers
+ one,
+ two,
+ three = two + one,
+ four = three + one
+end type
+
+switch 3 do
+ case one then
+ puts(1, "one")
+ case two then
+ puts(1, "two")
+ case three then
+ puts(1, "three")
+end switch
+
+test_pass("type enum expressions")
+test_report()
diff --git a/tests/t_goto_.e b/tests/t_goto_.e
index b3b24fda6..2c2b233de 100644
--- a/tests/t_goto_.e
+++ b/tests/t_goto_.e
@@ -2,7 +2,6 @@ include std/unittest.e
include std/error.e
warning_file(-1)
-with trace
integer n,m,c
n = 0
diff --git a/tests/t_literals.e b/tests/t_literals.e
index c0afcdc03..af248e138 100644
--- a/tests/t_literals.e
+++ b/tests/t_literals.e
@@ -217,4 +217,7 @@ test_equal( "Something looks bigger than it is #2", 0, scientific_to_atom("00000
test_equal( "0b1.11111111e53", power(2,53)-1, 9007199254740991 )
test_equal( "0b1.11111111e-55", 1 - power(2,-53), 0.99999999999999988897769753748434595763683319091796875 )
+-- ridiculously long literals:
+test_false("Excessively long 0 doesn't cause an error and is read as 0", 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
+test_equal("Excessively long 1/9 doesn't cause an error", 1, 9 * 0.1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)
test_report()
diff --git a/tests/t_net_http.e b/tests/t_net_http.e
index 3d6101305..1ade5418e 100644
--- a/tests/t_net_http.e
+++ b/tests/t_net_http.e
@@ -5,6 +5,9 @@ include std/math.e
include std/os.e
ifdef not NOINET_TESTS then
+ -- this gives the server user:pass of devel:devel
+ constant authorize_header = {"Authorization", "Basic ZGV2ZWw6ZGV2ZWw="}
+
object content
content = http_get("http://www.iana.org/")
@@ -14,10 +17,10 @@ ifdef not NOINET_TESTS then
content = http_get("http://www.iana.org")
assert("content readable http_get no path", length(content) > 1)
test_not_equal("content non-empty with http_get no path", length(content[2]), 0)
-
+
content = http_get("http://www.iana.org/domains/example/")
if atom(content) then
- test_fail("content readable from http_get with a path")
+ test_fail(sprintf("content readable from http_get with a path %d", {content}))
else
assert("content readable from http_get with a path", length(content) = 2)
test_true("content correct form from http_get with a path", match("", "" & content[2]))
@@ -36,7 +39,8 @@ ifdef not NOINET_TESTS then
sequence data = {
{ "data", num }
}
- content = http_post("http://test.openeuphoria.org/post_test.ex", data)
+ content = http_post("http://test.openeuphoria.org/post_test.ex", data,
+ {authorize_header})
if atom(content) or length(content) < 2 then
test_fail("http_post post #1")
else
@@ -44,9 +48,10 @@ ifdef not NOINET_TESTS then
end if
sequence headers = {
- { "Cache-Control", "no-cache" }
+ { "Cache-Control", "no-cache" },
+ authorize_header
}
- content = http_get("http://test.openeuphoria.org/post_test.txt", headers)
+ content = http_get("http://test.openeuphoria.org/post_test.txt", headers )
if atom(content) or length(content) < 2 then
test_true("http_get with headers #2", sequence(content))
test_fail("http_get with headers #3")
@@ -63,7 +68,7 @@ ifdef not NOINET_TESTS then
-- Test already encoded string
num = sprintf("%d", { rand_range(1000,10000) })
data = sprintf("data=%s", { num })
- content = http_post("http://test.openeuphoria.org/post_test.ex", data)
+ content = http_post("http://test.openeuphoria.org/post_test.ex", data, {authorize_header})
assert("http_get with headers #5", length(content) = 2)
test_equal("http_get with headers #6", "success", content[2])
@@ -82,7 +87,7 @@ ifdef not NOINET_TESTS then
-- post file script gets size and file parameters, calls decode_base64, and sends
-- back SIZE\nDECODED_FILE_CONTENTS. The test script is written in Perl to test against
-- modules we did not code, i.e. CGI and Base64 in this case.
- content = http_post("http://test.openeuphoria.org/post_file.cgi", { MULTIPART_FORM_DATA, data })
+ content = http_post("http://test.openeuphoria.org/post_file.cgi", { MULTIPART_FORM_DATA, data }, {authorize_header})
if atom(content) or length(content) < 2 then
test_fail("multipart form file upload")
else
diff --git a/tests/t_socket.e b/tests/t_socket.e
index fffef6b4b..7caa954b4 100644
--- a/tests/t_socket.e
+++ b/tests/t_socket.e
@@ -68,10 +68,10 @@ object p = pipe:exec(interpreter & " " & build_commandline( option_switches() )
if atom(p) then
test_fail("could not launch temporary server")
else
- -- Give the server a second to actually launch
- sleep(1)
integer maxwait = 10
for i = 1 to maxwait do
+ -- Give the server up to ten seconds to actually launch
+ sleep(1)
_ = sock:connect(socket, "127.0.0.1:"&port)
if _ = 0 then
exit