diff --git a/src/env.c b/src/env.c index 4881023..2b9c7a4 100644 --- a/src/env.c +++ b/src/env.c @@ -89,9 +89,7 @@ void addToEnv(struct Environment* env, const char* name, const Object obj) existing->data = o.data; return; } - char* symbol = malloc(sizeof(char) * (strlen(name) + 1)); - strcpy(symbol, name); - addToTable(&env->table, symbol, cloneObject(obj)); + addToTable(&env->table, strdup(name), cloneObject(obj)); } /** @@ -261,7 +259,7 @@ void printEnv(struct Environment* env, int printPointers) } else { size_t length; // SAFETY: Casting to Object is fine because stringObj() doesn't touch .forward - char* s = stringObj((Object *) &env->table.elements[i].object, &length); + char* s = stringObj((Object*) &env->table.elements[i].object, &length); printColored(s); if (env->table.elements[i].object.type == TYPE_STRING) { printf("\""); @@ -420,8 +418,8 @@ Object help(Object* params, int length, struct Environment* env) for (int i = 0; i < dictionary.structCount; i++) { if (strcmp(dictionary.structDefs[i].name, symbol) == 0) { - char structDef[128] = {'{', ' ', '\0'}; - for(int field = 0; field < dictionary.structDefs[i].fieldCount; field++) { + char structDef[128] = { '{', ' ', '\0' }; + for (int field = 0; field < dictionary.structDefs[i].fieldCount; field++) { strcat(structDef, dictionary.structDefs[i].names[field]); strcat(structDef, " "); } @@ -505,7 +503,7 @@ int runTests(int detailed, int specificTest) int passCount = 0; int isSpecificTest = specificTest != -1; - if(isSpecificTest) { + if (isSpecificTest) { struct helpText h = helpTexts[specificTest]; runHelpTests(h, detailed, &failureCount, &passCount); return failureCount; diff --git a/src/main.c b/src/main.c index 97d010c..07b3763 100644 --- a/src/main.c +++ b/src/main.c @@ -69,8 +69,7 @@ char* completionGenerator(const char* text, int state) struct ObjectTable* table = &global()->table; for (; i < table->capacity; i++) { if (table->elements[i].symbol && strncmp(table->elements[i].symbol, text, completionLength) == 0) { - char* symbol = malloc(sizeof(char) * (strlen(table->elements[i].symbol) + 1)); - strcpy(symbol, table->elements[i].symbol); + char* symbol = strdup(table->elements[i].symbol); i++; return symbol; } diff --git a/src/object.c b/src/object.c index 32e90c4..f0692b9 100644 --- a/src/object.c +++ b/src/object.c @@ -813,23 +813,20 @@ inline Object errorObject(enum errorCode err) #ifndef SIMPLE_ERRORS -inline void errorAddContext(Object* o, const char* context, int lineNo, const char* fileName) +inline Object +errorWithAllocatedContextLineNo(enum errorCode code, char* context, int lineNo, const char* fileName) { - o->error->context = malloc(sizeof(char) * RESULT_LENGTH); - char* cursor = o->error->context; - cursor += sprintf(cursor, "%s", context); - if (fileName) { - sprintf(cursor, " %s:%d", fileName, lineNo); - } + Object o = errorObject(code); + sprintf(context + strlen(context), " %s:%d", fileName, lineNo); + o.error->context = context; + return o; } inline Object errorWithContextLineNo(enum errorCode code, const char* context, int lineNo, const char* fileName) { - Object o = errorObject(code); - if (context) { - errorAddContext(&o, context, lineNo, fileName); - } - return o; + char* copiedContext = malloc(sizeof(char) * ERR_LEN); + strcpy(copiedContext, context); + return errorWithAllocatedContextLineNo(code, copiedContext, lineNo, fileName); } #endif diff --git a/src/object.h b/src/object.h index 3d8bde2..ad52d47 100644 --- a/src/object.h +++ b/src/object.h @@ -10,6 +10,8 @@ #else +#define ERR_LEN 256 + #ifdef DEBUG #define printd(...) printf(__VA_ARGS__) #else @@ -248,17 +250,17 @@ Object errorObject(enum errorCode err); Object errorWithContextLineNo(enum errorCode code, const char* context, int lineNo, const char* fileName); +Object errorWithAllocatedContextLineNo(enum errorCode code, char* context, int lineNo, const char* fileName); + #ifdef SIMPLE_ERRORS #define errorWithContext(code, context) errorObject(code) #define errorAddContext(x, y, z, a) ; #define throw(_code, ...) return errorObject(_code) #else -char ERROR_CONTEXT[128]; -#define throw(_code, ...) sprintf(ERROR_CONTEXT, __VA_ARGS__); return errorWithContext(_code, ERROR_CONTEXT) +#define throw(_code, ...) do { char* ERROR_CONTEXT = malloc(sizeof(char) * ERR_LEN); sprintf(ERROR_CONTEXT, __VA_ARGS__); \ + return errorWithAllocatedContextLineNo(_code, ERROR_CONTEXT, __LINE__, __FILE__); } while (0) #define errorWithContext(_code, _context) errorWithContextLineNo(_code, _context, __LINE__, __FILE__) -void errorAddContext(Object* o, const char* context, int lineNo, const char* fileName); - #endif struct Error noError(); diff --git a/src/pebblisp.c b/src/pebblisp.c index e02a695..252b19d 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -50,16 +50,14 @@ Object evalStructArgs(const Object* symbol, const Object* fields, unused struct int fieldCount = listLength(fields); struct StructDef def = { - .name = malloc(sizeof(char) * (strlen(name) + 1)), + .name = strdup(name), .fieldCount = fieldCount, .names = malloc(sizeof(char*) * fieldCount), }; - strcpy(def.name, name); int i = 0; FOR_POINTER_IN_LIST(fields) { - def.names[i] = malloc(sizeof(char) * (strlen(POINTER->string) + 1)); - strcpy(def.names[i], POINTER->string); + def.names[i] = strdup(POINTER->string); i++; } @@ -317,12 +315,14 @@ Object structAccess(Object* params, unused int length, unused struct Environment } if (isNumber(field)) { if (structDef->fieldCount < field.number || field.number < 0) { - throw(NULL_PARSE, "Could not find struct field at index %ld. Struct `%s` has %d fields.", field.number, structDef->name, structDef->fieldCount); + throw(NULL_PARSE, "Could not find struct field at index %ld. Struct `%s` has %d fields.", field.number, + structDef->name, structDef->fieldCount); } return cloneObject(structo.structObject->fields[field.number]); } - throw(BAD_PARAMS, "Struct fields should be indexed with a string or a number, but received a %s", getTypeName(&field)); + throw(BAD_PARAMS, "Struct fields should be indexed with a string or a number, but received a %s", + getTypeName(&field)); } Result parse(struct Slice* slices) @@ -429,6 +429,7 @@ Object parseBin(struct Slice* s) struct InlinedFunction { Object (* func)(Object*, int, struct Environment*); + Object* arguments; int argCount; //struct Environment* env; @@ -514,28 +515,32 @@ Object parseEval(const char* input, struct Environment* env) parens--; } - if (parens == 0) { - cleanObject(&obj); - Object parsed = parse(tok).obj; - if (parsed.type == TYPE_ERROR) { - obj = parsed; // TODO Check necessity + if (parens != 0) { + i++; + continue; + } + + cleanObject(&obj); + Object parsed = parse(tok).obj; + if (parsed.type == TYPE_ERROR) { + obj = parsed; // TODO Check necessity #ifdef STANDALONE - obj.error->plContext = malloc(sizeof(struct Slice)); - *obj.error->plContext = *lastOpen; + obj.error->plContext = malloc(sizeof(struct Slice)); + *obj.error->plContext = *lastOpen; #endif - break; - } - if (tok[i].text[0] == ')') { - // Skip `tok` past end of list that just closed - tok = &tok[i + 1]; - i = -1; - } - if (parsed.type == TYPE_SLIST) { - obj = parsed; - } else { - obj = eval(&parsed, env); - cleanObject(&parsed); - } + break; + } + + if (tok[i].text[0] == ')') { + // Skip `tok` past end of list that just closed + tok = &tok[i + 1]; + i = -1; + } + if (parsed.type == TYPE_SLIST) { + obj = parsed; + } else { + obj = eval(&parsed, env); + cleanObject(&parsed); } i++; diff --git a/src/tests.sh b/src/tests.sh index c947876..20f3052 100755 --- a/src/tests.sh +++ b/src/tests.sh @@ -167,9 +167,8 @@ check "MinRight" "(min 8429 192449)" "8429" check "MinLeft" "(min 17294722 17294721)" "17294721" title "Lambdas" -check "Multi-Statement" "(def yee (fn (a) (* 10 a))) ; (yee 5)" "50" -check "Multi-Statement, No Semicolon" "(def yee (fn (a) (* 10 a)))(yee 5)" "50" -check "Pre-Defined Map" "(def yee (fn (a) (* 10 a))) ; (map yee (5 10 2 (+ 12 0)))" "( 50 100 20 120 )" +check "Multi-Statement" "(def yee (fn (a) (* 10 a))) (yee 5)" "50" +check "Pre-Defined Map" "(def yee (fn (a) (* 10 a))) (map yee (5 10 2 (+ 12 0)))" "( 50 100 20 120 )" check "AnonymousLambda" "\ (map (fn (a) (* a a)) (5 6 7))" "( 25 36 49 )" check "FbnciSeq" "\ @@ -177,17 +176,17 @@ check "FbnciSeq" "\ (if (< a 2) \ a \ (+ (fib (- a 1)) (fib (- a 2))) \ - )));\ + )))\ (fib 11)" "89" check "Factorial" "\ (def fac (fn (a) \ (if (= a 1) \ 1 \ (* a (fac (- a 1)) ) \ - )));\ + )))\ (fac 11)" "39916800" check "Lambda Clone" "(def y (fn (a) (* 10 a))) (def b y) (def y 12345) ((b 5) y)" "( 50 12345 )" -check "Duplicate" "(def dupe (fn (a) (() (a a a))));(dupe (* 10 10))" "( 100 100 100 )" +check "Duplicate" "(def dupe (fn (a) (() (a a a)))) (dupe (* 10 10))" "( 100 100 100 )" title "Cat" check "Basic Cat" '(cat "Big" " Kitty")' "Big Kitty" diff --git a/src/tokens.c b/src/tokens.c index 5e3d207..e0a55bf 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -2,8 +2,6 @@ #include -#define ERR_LEN 256 - /* * Grammar: * token @@ -42,11 +40,18 @@ int isWhitespace(const char c) return c == ' ' || c == '\t' || c == '\n'; } +void buildErrFromInput(struct Error* err, enum errorCode code, int i, const char* input) +{ + err->context = malloc(sizeof(char) * ERR_LEN + 1); + err->code = code; + int start = i > ERR_LEN ? i - ERR_LEN : 0; + strncpy(err->context, &input[start], ERR_LEN); +} + struct Slice* nf_tokenize(const char* input, struct Error* err) { if (!input) { - err->context = malloc(sizeof(char) * ERR_LEN); - strcpy(err->context, "no input"); + err->context = strdup("no input"); return NULL; } @@ -63,8 +68,8 @@ struct Slice* nf_tokenize(const char* input, struct Error* err) int parens = 0; while (input[i] != '\0') { - int l = 1; - if (isWhitespace(input[i]) || input[i] == ';') { + int length = 1; + if (isWhitespace(input[i])) { if (input[i] == '\n') { lineNumber++; } @@ -77,10 +82,7 @@ struct Slice* nf_tokenize(const char* input, struct Error* err) } else if (input[i] == ')') { parens--; if (parens < 0) { - err->context = malloc(sizeof(char) * ERR_LEN + 1); - err->code = MISMATCHED_PARENS; - int start = i > ERR_LEN ? i - ERR_LEN : 0; - strncpy(err->context, &input[start], ERR_LEN); + buildErrFromInput(err, MISMATCHED_PARENS, i, input); //free(slices); return NULL; } @@ -104,12 +106,9 @@ struct Slice* nf_tokenize(const char* input, struct Error* err) if (input[i] == '\n') { lineNumber++; } - l++; + length++; if (input[i] == '\0' || input[i + 1] == '\0' || input[i + 2] == '\0') { - err->context = malloc(sizeof(char) * ERR_LEN + 1); - err->code = UNEXPECTED_EOF; - int start = i > ERR_LEN ? i - ERR_LEN : 0; - strncpy(err->context, &input[start], ERR_LEN); + buildErrFromInput(err, UNEXPECTED_EOF, i, input); //free(slices); return NULL; } @@ -120,25 +119,22 @@ struct Slice* nf_tokenize(const char* input, struct Error* err) if (input[i] == '\n') { lineNumber++; } - l++; + length++; } } i++; } else { while (!isWhitespace(input[++i]) && !isSingle(input[i]) && input[i] != '"' && input[i] != '\0') { - l++; + length++; } } - slices[slice].length = l; + slices[slice].length = length; slice++; } if (parens != 0) { - err->context = malloc(sizeof(char) * ERR_LEN); - err->code = MISMATCHED_PARENS; - int start = i > ERR_LEN ? i - ERR_LEN : 0; - strncpy(err->context, &input[start], ERR_LEN); + buildErrFromInput(err, MISMATCHED_PARENS, i, input); //free(slices); return NULL; } diff --git a/src/web.c b/src/web.c index ad2c66a..2d214b9 100644 --- a/src/web.c +++ b/src/web.c @@ -150,8 +150,7 @@ int start(int port) void addRouteO(Object path, Object textFunc, struct Environment* env, enum RouteType type) { - char* p = malloc(sizeof(char) * strlen(path.string) + 1); - strcpy(p, path.string); + char* p = strdup(path.string); struct Route r; r.path = p;