fix: String_IsNull/String_Offset helpers + remove pointer-to-int casts
- Add String_IsNull and String_Offset wrappers in lib/String.bux - Add bux_str_is_null and bux_str_offset runtime functions in rt/runtime.c - Update String_Replace to use String_IsNull instead of String_Len(pos)==0 - Replace pointer-to-uint casts (as uint == 0, pointer arithmetic) across apps/ - Parser newline skipping fixes in src/parser.bux
This commit is contained in:
@@ -5,7 +5,7 @@ module Boko {
|
|||||||
|
|
||||||
import Std::Io::{PrintLine, Print, PrintInt};
|
import Std::Io::{PrintLine, Print, PrintInt};
|
||||||
import Std::Net::{Net_Create, Net_SetReuse, Net_Bind, Net_Listen, Net_Accept, Net_Send, Net_Recv, Net_Close, Net_LastError};
|
import Std::Net::{Net_Create, Net_SetReuse, Net_Bind, Net_Listen, Net_Accept, Net_Send, Net_Recv, Net_Close, Net_LastError};
|
||||||
import Std::String::{String_Len, String_Eq, String_StartsWith, String_Contains};
|
import Std::String::{String_Len, String_Eq, String_StartsWith, String_Contains, String_Offset};
|
||||||
import Std::Task::{Task_Join, TaskHandle};
|
import Std::Task::{Task_Join, TaskHandle};
|
||||||
|
|
||||||
extern func bux_alloc(size: uint) -> *void;
|
extern func bux_alloc(size: uint) -> *void;
|
||||||
@@ -239,8 +239,8 @@ func Query_Parse(req: *Request, queryString: String) {
|
|||||||
let eqPos: String = bux_strstr(pair, "=");
|
let eqPos: String = bux_strstr(pair, "=");
|
||||||
var key: String = pair;
|
var key: String = pair;
|
||||||
var value: String = "";
|
var value: String = "";
|
||||||
if eqPos as uint != 0 {
|
if String_Len(eqPos) > 0 {
|
||||||
let keyLen: uint = eqPos as uint - pair as uint;
|
let keyLen: uint = String_Offset(eqPos, pair);
|
||||||
key = bux_str_slice(pair, 0, keyLen);
|
key = bux_str_slice(pair, 0, keyLen);
|
||||||
let valStart: uint = keyLen + 1;
|
let valStart: uint = keyLen + 1;
|
||||||
let pairLen: uint = bux_strlen(pair);
|
let pairLen: uint = bux_strlen(pair);
|
||||||
@@ -267,15 +267,15 @@ func Request_Parse(raw: String) -> Request {
|
|||||||
req.queryCount = 0;
|
req.queryCount = 0;
|
||||||
req.pathParamCount = 0;
|
req.pathParamCount = 0;
|
||||||
|
|
||||||
if raw as uint == 0 { return req; }
|
if String_Len(raw) == 0 { return req; }
|
||||||
let rawLen: uint = bux_strlen(raw);
|
let rawLen: uint = bux_strlen(raw);
|
||||||
if rawLen == 0 { return req; }
|
if rawLen == 0 { return req; }
|
||||||
|
|
||||||
// Find header/body boundary
|
// Find header/body boundary
|
||||||
let boundary: String = bux_strstr(raw, "\r\n\r\n");
|
let boundary: String = bux_strstr(raw, "\r\n\r\n");
|
||||||
var headerLen: uint = rawLen;
|
var headerLen: uint = rawLen;
|
||||||
if boundary as uint != 0 {
|
if String_Len(boundary) > 0 {
|
||||||
headerLen = boundary as uint - raw as uint;
|
headerLen = String_Offset(boundary, raw);
|
||||||
let bodyStart: uint = headerLen + 4;
|
let bodyStart: uint = headerLen + 4;
|
||||||
if bodyStart < rawLen {
|
if bodyStart < rawLen {
|
||||||
req.body = bux_str_slice(raw, bodyStart, rawLen - bodyStart);
|
req.body = bux_str_slice(raw, bodyStart, rawLen - bodyStart);
|
||||||
@@ -299,8 +299,8 @@ func Request_Parse(raw: String) -> Request {
|
|||||||
let fullPath: String = bux_str_split_part(requestLine, " ", 1);
|
let fullPath: String = bux_str_split_part(requestLine, " ", 1);
|
||||||
// Split path and query string
|
// Split path and query string
|
||||||
let qmark: String = bux_strstr(fullPath, "?");
|
let qmark: String = bux_strstr(fullPath, "?");
|
||||||
if qmark as uint != 0 {
|
if String_Len(qmark) > 0 {
|
||||||
let pathLen: uint = qmark as uint - fullPath as uint;
|
let pathLen: uint = String_Offset(qmark, fullPath);
|
||||||
req.path = bux_str_slice(fullPath, 0, pathLen);
|
req.path = bux_str_slice(fullPath, 0, pathLen);
|
||||||
let qsStart: uint = pathLen + 1;
|
let qsStart: uint = pathLen + 1;
|
||||||
let fullLen: uint = bux_strlen(fullPath);
|
let fullLen: uint = bux_strlen(fullPath);
|
||||||
@@ -322,8 +322,8 @@ func Request_Parse(raw: String) -> Request {
|
|||||||
while i < lineCount {
|
while i < lineCount {
|
||||||
let line: String = bux_str_split_part(headerBlock, "\r\n", i);
|
let line: String = bux_str_split_part(headerBlock, "\r\n", i);
|
||||||
let colonPos: String = bux_strstr(line, ": ");
|
let colonPos: String = bux_strstr(line, ": ");
|
||||||
if colonPos as uint != 0 {
|
if String_Len(colonPos) > 0 {
|
||||||
let keyLen: uint = colonPos as uint - line as uint;
|
let keyLen: uint = String_Offset(colonPos, line);
|
||||||
let key: String = bux_str_slice(line, 0, keyLen);
|
let key: String = bux_str_slice(line, 0, keyLen);
|
||||||
let valStart: uint = keyLen + 2;
|
let valStart: uint = keyLen + 2;
|
||||||
let lineLen: uint = bux_strlen(line);
|
let lineLen: uint = bux_strlen(line);
|
||||||
@@ -378,8 +378,8 @@ func Path_Match(pattern: String, path: String, req: *Request) -> bool {
|
|||||||
let braceOpen: uint = 1; // skip "{"
|
let braceOpen: uint = 1; // skip "{"
|
||||||
let braceClose: String = bux_strstr(patPart, "}");
|
let braceClose: String = bux_strstr(patPart, "}");
|
||||||
var nameLen: uint = 0;
|
var nameLen: uint = 0;
|
||||||
if braceClose as uint != 0 {
|
if String_Len(braceClose) > 0 {
|
||||||
nameLen = braceClose as uint - patPart as uint - 1;
|
nameLen = String_Offset(braceClose, patPart) - 1;
|
||||||
}
|
}
|
||||||
let name: String = bux_str_slice(patPart, braceOpen, nameLen);
|
let name: String = bux_str_slice(patPart, braceOpen, nameLen);
|
||||||
req.pathParamKeys[req.pathParamCount] = name;
|
req.pathParamKeys[req.pathParamCount] = name;
|
||||||
@@ -416,7 +416,7 @@ func Boko_Router(req: Request) -> Response;
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
func App_HandleConnection(clientFd: int) {
|
func App_HandleConnection(clientFd: int) {
|
||||||
let raw: String = Net_Recv(clientFd, 8192);
|
let raw: String = Net_Recv(clientFd, 8192);
|
||||||
if raw as uint == 0 { return; }
|
if String_Len(raw) == 0 { return; }
|
||||||
if bux_strlen(raw) == 0 { return; }
|
if bux_strlen(raw) == 0 { return; }
|
||||||
|
|
||||||
let req: Request = Request_Parse(raw);
|
let req: Request = Request_Parse(raw);
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ func ResolveKey(alg: JwtAlg, keyArg: String) -> String {
|
|||||||
alg.tag == JwtAlg_ES256 || alg.tag == JwtAlg_ES384 {
|
alg.tag == JwtAlg_ES256 || alg.tag == JwtAlg_ES384 {
|
||||||
if bux_file_exists(keyArg) != 0 {
|
if bux_file_exists(keyArg) != 0 {
|
||||||
let pem: String = bux_read_file(keyArg);
|
let pem: String = bux_read_file(keyArg);
|
||||||
if pem as uint != 0 && String_Len(pem) > 0 {
|
if String_Len(pem) > 0 && String_Len(pem) > 0 {
|
||||||
return pem;
|
return pem;
|
||||||
}
|
}
|
||||||
Print("ERROR: could not read PEM file: ");
|
Print("ERROR: could not read PEM file: ");
|
||||||
|
|||||||
+11
-11
@@ -9,7 +9,7 @@ module Main {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
import Std::Io::{PrintLine, Print, PrintInt};
|
import Std::Io::{PrintLine, Print, PrintInt};
|
||||||
import Std::Net::{Net_Create, Net_SetReuse, Net_Bind, Net_Listen, Net_Accept, Net_Send, Net_Recv, Net_Close, Net_LastError};
|
import Std::Net::{Net_Create, Net_SetReuse, Net_Bind, Net_Listen, Net_Accept, Net_Send, Net_Recv, Net_Close, Net_LastError};
|
||||||
import Std::String::{String_Len, String_Eq, String_StartsWith, String_EndsWith, String_Contains, String_Trim, String_FromInt};
|
import Std::String::{String_Len, String_Eq, String_StartsWith, String_EndsWith, String_Contains, String_Trim, String_FromInt, String_Offset};
|
||||||
import Std::Task::{Task_Join, TaskHandle};
|
import Std::Task::{Task_Join, TaskHandle};
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
@@ -170,15 +170,15 @@ func Http_ParseRequest(raw: String) -> HttpRequest {
|
|||||||
RequestHeader_Init(&req);
|
RequestHeader_Init(&req);
|
||||||
|
|
||||||
// Guard: null/empty input
|
// Guard: null/empty input
|
||||||
if raw as uint == 0 { return req; }
|
if String_Len(raw) == 0 { return req; }
|
||||||
let rawLen: uint = bux_strlen(raw);
|
let rawLen: uint = bux_strlen(raw);
|
||||||
if rawLen == 0 { return req; }
|
if rawLen == 0 { return req; }
|
||||||
|
|
||||||
// Find \r\n\r\n separating headers from body
|
// Find \r\n\r\n separating headers from body
|
||||||
let boundary: String = bux_strstr(raw, "\r\n\r\n");
|
let boundary: String = bux_strstr(raw, "\r\n\r\n");
|
||||||
var headerLen: uint = rawLen;
|
var headerLen: uint = rawLen;
|
||||||
if boundary as uint != 0 {
|
if String_Len(boundary) > 0 {
|
||||||
headerLen = boundary as uint - raw as uint;
|
headerLen = String_Offset(boundary, raw);
|
||||||
let bodyStart: uint = headerLen + 4;
|
let bodyStart: uint = headerLen + 4;
|
||||||
if bodyStart < rawLen {
|
if bodyStart < rawLen {
|
||||||
req.body = bux_str_slice(raw, bodyStart, rawLen - bodyStart);
|
req.body = bux_str_slice(raw, bodyStart, rawLen - bodyStart);
|
||||||
@@ -198,7 +198,7 @@ func Http_ParseRequest(raw: String) -> HttpRequest {
|
|||||||
if bux_strlen(requestLine) > 0 {
|
if bux_strlen(requestLine) > 0 {
|
||||||
req.method = Http_ParseMethod(bux_str_split_part(requestLine, " ", 0));
|
req.method = Http_ParseMethod(bux_str_split_part(requestLine, " ", 0));
|
||||||
req.path = bux_str_split_part(requestLine, " ", 1);
|
req.path = bux_str_split_part(requestLine, " ", 1);
|
||||||
if String_Eq(req.path, "") || req.path as uint == 0 {
|
if String_Eq(req.path, "") || req.String_Len(path) == 0 {
|
||||||
req.path = "/";
|
req.path = "/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,8 +215,8 @@ func Http_ParseRequest(raw: String) -> HttpRequest {
|
|||||||
var key: String = "";
|
var key: String = "";
|
||||||
var value: String = "";
|
var value: String = "";
|
||||||
|
|
||||||
if colonPos as uint != 0 {
|
if String_Len(colonPos) > 0 {
|
||||||
let keyLen: uint = colonPos as uint - line as uint;
|
let keyLen: uint = String_Offset(colonPos, line);
|
||||||
key = bux_str_slice(line, 0, keyLen);
|
key = bux_str_slice(line, 0, keyLen);
|
||||||
let valStart: uint = keyLen + 2;
|
let valStart: uint = keyLen + 2;
|
||||||
if valStart < lineLen {
|
if valStart < lineLen {
|
||||||
@@ -225,8 +225,8 @@ func Http_ParseRequest(raw: String) -> HttpRequest {
|
|||||||
} else {
|
} else {
|
||||||
// Try ":" without space
|
// Try ":" without space
|
||||||
let colonPos2: String = bux_strstr(line, ":");
|
let colonPos2: String = bux_strstr(line, ":");
|
||||||
if colonPos2 as uint != 0 {
|
if String_Len(colonPos2) > 0 {
|
||||||
let keyLen: uint = colonPos2 as uint - line as uint;
|
let keyLen: uint = String_Offset(colonPos2, line);
|
||||||
key = bux_str_slice(line, 0, keyLen);
|
key = bux_str_slice(line, 0, keyLen);
|
||||||
let valStart: uint = keyLen + 1;
|
let valStart: uint = keyLen + 1;
|
||||||
if valStart < lineLen {
|
if valStart < lineLen {
|
||||||
@@ -341,7 +341,7 @@ func ServeStaticFile(requestPath: String) -> HttpResponse {
|
|||||||
|
|
||||||
// Read and serve
|
// Read and serve
|
||||||
let content: String = bux_read_file(fullPath);
|
let content: String = bux_read_file(fullPath);
|
||||||
if content as uint == 0 {
|
if String_Len(content) == 0 {
|
||||||
return Http_NewResponse(500, "text/plain; charset=utf-8", "Internal Server Error");
|
return Http_NewResponse(500, "text/plain; charset=utf-8", "Internal Server Error");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +444,7 @@ func HandleConnection(clientFd: int) {
|
|||||||
let raw: String = Net_Recv(clientFd, 8192);
|
let raw: String = Net_Recv(clientFd, 8192);
|
||||||
|
|
||||||
// Empty read → client disconnected
|
// Empty read → client disconnected
|
||||||
if raw as uint == 0 { return; }
|
if String_Len(raw) == 0 { return; }
|
||||||
if bux_strlen(raw) == 0 { return; }
|
if bux_strlen(raw) == 0 { return; }
|
||||||
|
|
||||||
// HTTP/2 connection preface detection
|
// HTTP/2 connection preface detection
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ module Main {
|
|||||||
|
|
||||||
import Std::Io::{PrintLine, Print, PrintInt, ReadFile, WriteFile, FileExists};
|
import Std::Io::{PrintLine, Print, PrintInt, ReadFile, WriteFile, FileExists};
|
||||||
import Std::Os::{Os_ArgsCount, Os_Args};
|
import Std::Os::{Os_ArgsCount, Os_Args};
|
||||||
import Std::String::{String_Len, String_Eq, String_StartsWith, String_Find, String_Slice};
|
import Std::String::{String_Len, String_Eq, String_StartsWith, String_Find, String_Slice, String_Offset};
|
||||||
|
|
||||||
extern func bux_strlen(s: String) -> uint;
|
extern func bux_strlen(s: String) -> uint;
|
||||||
extern func bux_strstr(haystack: String, needle: String) -> String;
|
extern func bux_strstr(haystack: String, needle: String) -> String;
|
||||||
@@ -46,7 +46,7 @@ func DB_Load(self: *Database) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let raw: String = ReadFile(self.path);
|
let raw: String = ReadFile(self.path);
|
||||||
if raw as uint == 0 || bux_strlen(raw) == 0 {
|
if String_Len(raw) == 0 || bux_strlen(raw) == 0 {
|
||||||
self.loaded = true;
|
self.loaded = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ func DB_Get(self: *Database, key: String) -> String {
|
|||||||
let line: String = bux_str_split_part(raw, "\n", i);
|
let line: String = bux_str_split_part(raw, "\n", i);
|
||||||
if String_StartsWith(line, key) {
|
if String_StartsWith(line, key) {
|
||||||
let eqPos: String = String_Find(line, "=");
|
let eqPos: String = String_Find(line, "=");
|
||||||
if eqPos as uint != 0 {
|
if String_Len(eqPos) > 0 {
|
||||||
let keyLen: uint = bux_strlen(key);
|
let keyLen: uint = bux_strlen(key);
|
||||||
let valStart: uint = keyLen + 1;
|
let valStart: uint = keyLen + 1;
|
||||||
let lineLen: uint = bux_strlen(line);
|
let lineLen: uint = bux_strlen(line);
|
||||||
@@ -102,7 +102,7 @@ func DB_Set(self: *Database, key: String, value: String) {
|
|||||||
if bux_strlen(line) > 0 {
|
if bux_strlen(line) > 0 {
|
||||||
if String_StartsWith(line, key) {
|
if String_StartsWith(line, key) {
|
||||||
let eqPos: String = String_Find(line, "=");
|
let eqPos: String = String_Find(line, "=");
|
||||||
if eqPos as uint != 0 {
|
if String_Len(eqPos) > 0 {
|
||||||
bux_sb_append(newSb, key);
|
bux_sb_append(newSb, key);
|
||||||
SB_AppendChar(newSb, 61);
|
SB_AppendChar(newSb, 61);
|
||||||
bux_sb_append(newSb, value);
|
bux_sb_append(newSb, value);
|
||||||
@@ -144,7 +144,7 @@ func DB_Del(self: *Database, key: String) {
|
|||||||
if bux_strlen(line) > 0 {
|
if bux_strlen(line) > 0 {
|
||||||
if String_StartsWith(line, key) {
|
if String_StartsWith(line, key) {
|
||||||
let eqPos: String = String_Find(line, "=");
|
let eqPos: String = String_Find(line, "=");
|
||||||
if eqPos as uint != 0 {
|
if String_Len(eqPos) > 0 {
|
||||||
delCount = delCount + 1;
|
delCount = delCount + 1;
|
||||||
} else {
|
} else {
|
||||||
bux_sb_append(newSb, line);
|
bux_sb_append(newSb, line);
|
||||||
@@ -188,8 +188,8 @@ func DB_Keys(self: *Database) -> *String {
|
|||||||
let line: String = bux_str_split_part(raw, "\n", i);
|
let line: String = bux_str_split_part(raw, "\n", i);
|
||||||
if bux_strlen(line) > 0 {
|
if bux_strlen(line) > 0 {
|
||||||
let eqPos: String = String_Find(line, "=");
|
let eqPos: String = String_Find(line, "=");
|
||||||
if eqPos as uint != 0 {
|
if String_Len(eqPos) > 0 {
|
||||||
let keyLen: uint = eqPos as uint - line as uint;
|
let keyLen: uint = String_Offset(eqPos, line);
|
||||||
keys[found] = bux_str_slice(line, 0, keyLen);
|
keys[found] = bux_str_slice(line, 0, keyLen);
|
||||||
found = found + 1;
|
found = found + 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-2
@@ -8,6 +8,8 @@ extern func bux_strcat(dest: *char8, src: String) -> *char8;
|
|||||||
extern func bux_strncpy(dest: *char8, src: String, n: uint) -> *char8;
|
extern func bux_strncpy(dest: *char8, src: String, n: uint) -> *char8;
|
||||||
extern func bux_strstr(haystack: String, needle: String) -> String;
|
extern func bux_strstr(haystack: String, needle: String) -> String;
|
||||||
extern func bux_str_contains(haystack: String, needle: String) -> int;
|
extern func bux_str_contains(haystack: String, needle: String) -> int;
|
||||||
|
extern func bux_str_offset(pos: String, base: String) -> uint;
|
||||||
|
extern func bux_str_is_null(s: String) -> int;
|
||||||
extern func bux_str_slice(s: String, start: uint, len: uint) -> String;
|
extern func bux_str_slice(s: String, start: uint, len: uint) -> String;
|
||||||
extern func bux_str_trim_left(s: String) -> String;
|
extern func bux_str_trim_left(s: String) -> String;
|
||||||
extern func bux_str_trim_right(s: String) -> String;
|
extern func bux_str_trim_right(s: String) -> String;
|
||||||
@@ -32,6 +34,10 @@ func String_Len(s: String) -> uint {
|
|||||||
return bux_strlen(s);
|
return bux_strlen(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func String_IsNull(s: String) -> bool {
|
||||||
|
return bux_str_is_null(s) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
func String_Eq(a: String, b: String) -> bool {
|
func String_Eq(a: String, b: String) -> bool {
|
||||||
return bux_strcmp(a, b) == 0;
|
return bux_strcmp(a, b) == 0;
|
||||||
}
|
}
|
||||||
@@ -170,13 +176,17 @@ func String_Find(haystack: String, needle: String) -> String {
|
|||||||
return bux_strstr(haystack, needle);
|
return bux_strstr(haystack, needle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func String_Offset(pos: String, base: String) -> uint {
|
||||||
|
return bux_str_offset(pos, base);
|
||||||
|
}
|
||||||
|
|
||||||
func String_Replace(s: String, old: String, new: String) -> String {
|
func String_Replace(s: String, old: String, new: String) -> String {
|
||||||
let pos: String = bux_strstr(s, old);
|
let pos: String = bux_strstr(s, old);
|
||||||
if pos as uint == 0 {
|
if String_IsNull(pos) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
let oldLen: uint = bux_strlen(old);
|
let oldLen: uint = bux_strlen(old);
|
||||||
let prefixLen: uint = pos as uint - s as uint;
|
let prefixLen: uint = String_Offset(pos, s);
|
||||||
let prefix: String = bux_str_slice(s, 0, prefixLen);
|
let prefix: String = bux_str_slice(s, 0, prefixLen);
|
||||||
let suffix: String = bux_str_slice(s, prefixLen + oldLen, bux_strlen(s) - prefixLen - oldLen);
|
let suffix: String = bux_str_slice(s, prefixLen + oldLen, bux_strlen(s) - prefixLen - oldLen);
|
||||||
let temp: String = String_Concat(prefix, new);
|
let temp: String = String_Concat(prefix, new);
|
||||||
|
|||||||
@@ -232,11 +232,22 @@ const char* bux_strstr(const char* haystack, const char* needle) {
|
|||||||
return strstr(haystack, needle);
|
return strstr(haystack, needle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* String offset: byte offset of pos within base (both must point into same string) */
|
||||||
|
unsigned int bux_str_offset(const char* pos, const char* base) {
|
||||||
|
if (!pos || !base) return 0;
|
||||||
|
return (unsigned int)(pos - base);
|
||||||
|
}
|
||||||
|
|
||||||
/* String contains: returns 1 if haystack contains needle, 0 otherwise */
|
/* String contains: returns 1 if haystack contains needle, 0 otherwise */
|
||||||
int bux_str_contains(const char* haystack, const char* needle) {
|
int bux_str_contains(const char* haystack, const char* needle) {
|
||||||
return bux_strstr(haystack, needle) != NULL;
|
return bux_strstr(haystack, needle) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* String is null: returns 1 if string is NULL */
|
||||||
|
int bux_str_is_null(const char* s) {
|
||||||
|
return s == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* String slice: extract substring from start, length len */
|
/* String slice: extract substring from start, length len */
|
||||||
char* bux_str_slice(const char* s, unsigned int start, unsigned int len) {
|
char* bux_str_slice(const char* s, unsigned int start, unsigned int len) {
|
||||||
if (!s) return NULL;
|
if (!s) return NULL;
|
||||||
|
|||||||
@@ -920,6 +920,12 @@ func parserParseParamList(p: *Parser) -> *Decl {
|
|||||||
|
|
||||||
discard parserExpect(p, tkLParen, "expected '('");
|
discard parserExpect(p, tkLParen, "expected '('");
|
||||||
while !parserCheck(p, tkRParen) && parserPeek(p, 0) != tkEndOfFile {
|
while !parserCheck(p, tkRParen) && parserPeek(p, 0) != tkEndOfFile {
|
||||||
|
while parserCheck(p, tkNewLine) || parserCheck(p, tkSemicolon) {
|
||||||
|
discard parserAdvance(p);
|
||||||
|
}
|
||||||
|
if parserCheck(p, tkRParen) || parserPeek(p, 0) == tkEndOfFile {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if d.paramCount >= 9 { break; }
|
if d.paramCount >= 9 { break; }
|
||||||
let nameTok: LexToken = parserExpectIdentOrKeyword(p, "expected parameter name");
|
let nameTok: LexToken = parserExpectIdentOrKeyword(p, "expected parameter name");
|
||||||
discard parserExpect(p, tkColon, "expected ':' in parameter");
|
discard parserExpect(p, tkColon, "expected ':' in parameter");
|
||||||
|
|||||||
Reference in New Issue
Block a user