diff --git a/cirilisp.c b/cirilisp.c index 419b4cf..dd183a4 100644 --- a/cirilisp.c +++ b/cirilisp.c @@ -58,6 +58,7 @@ void init() addSymbolInternal("ниска?", &stringQInt, 0); addSymbolInternal("карактер?", &charQInt, 0); addSymbolInternal("листа?", &listQInt, 0); + addSymbolInternal("надовежи", &appendInt, 0); addSymbolInternal("конс", &consInt, 0); addSymbolInternal("сар", &carInt, 0); addSymbolInternal("сдр", &cdrInt, 0); @@ -66,6 +67,8 @@ void init() addSymbolInternal("прикажи", &displayInt, 0); addSymbolInternal("штампај", &printInt, 0); addSymbolInternal("почни", &beginInt, 0); + addSymbolInternal("направи-ниску", &makeStrInt, 0); + addSymbolInternal("дужина-ниске", &strLengthInt, 0); if (!load(DESTDIR"/usr/local/lib/cirilisp/инит.ћ")) { diff --git a/internals.c b/internals.c index e7f20b5..da9423a 100644 --- a/internals.c +++ b/internals.c @@ -1,10 +1,12 @@ #include #include #include +#include #include "util.h" -#include "print.h" +#include "read.h" #include "eval.h" +#include "print.h" int allNums(object list) /* проверава да ли је објекат листа чији је сваки члан број, претпоставља да је @@ -533,6 +535,57 @@ object listQInt(object parameters) return result; } +int validAppendArgs(object parameters) +{ + int length = listLength(parameters); + if (length == 0 || length == 1) + { + return 1; + } + else if (!properList(CAR(parameters))) + { + return 0; + } + else + { + return validAppendArgs(CDR(parameters)); + } +} + +object appendAux(object parameters) +{ + object result; + if (listLength(parameters) == 0) + { + TYPE(result) = nilObject; + } + else if (listLength(parameters) == 1) + { + result = copyObject(CAR(parameters)); + } + else + { + object rest = appendAux(CDR(parameters)); + result = copyObject(CAR(parameters)); + object *end = &result; + while (TYPE(*end) != nilObject) + { + end = &CDR(*end); + } + *end = rest; + } + return result; +} + +object appendInt(object parameters) +{ + if (!validAppendArgs(parameters)) + { + SIGERR(typeError); + } + return appendAux(parameters); +} + object consInt(object parameters) { if (listLength(parameters) != 2) @@ -704,3 +757,69 @@ object beginInt(object parameters) } return last; } + +object makeStrInt(object parameters) +{ + object result; + if (listLength(parameters) != 2) + { + SIGERR(argumentNumberError); + } + if (TYPE(CAR(parameters)) != numberObject || !integer(CAR(parameters)) + || TYPE(CAR(CDR(parameters))) != charObject) + { + SIGERR(typeError); + } + TYPE(result) = stringObject; + if (CHR(CAR(CDR(parameters))) == L'\0') + { + STR(result) = malloc(sizeof(char)); + STR(result)[0] = '\0'; + return result; + } + STR(result) = malloc((MB_CUR_MAX * NUM_NUMER(CAR(parameters)) + 1) * + sizeof(char)); + if (STR(result) == NULL) + { + SIGERR(outOfMemoryError); + } + int i, index; + for (i = 0, index = 0; i < NUM_NUMER(CAR(parameters)); ++i, + index += wctomb(STR(result) + index, + CHR(CAR(CDR(parameters))))) + ; + STR(result)[index] = '\0'; + + return result; +} + +object strLengthInt(object parameters) +{ + object result; + if (listLength(parameters) != 1) + { + SIGERR(argumentNumberError); + } + if (TYPE(CAR(parameters)) != stringObject) + { + SIGERR(typeError); + } + TYPE(result) = numberObject; + NUM_TYPE(result) = fractionNum; + NUM_DENOM(result) = 1; + + wchar_t current; + int i = 0, length = 0; + int cLength; + do + { + cLength = + mbtowc(¤t, &STR(CAR(parameters))[i], MB_CUR_MAX); + i += cLength; + ++length; + } while (current != L'\0'); + length -= 1; /* одузима се дужина нул карактера */ + NUM_NUMER(result) = length; + + return result; +} diff --git a/internals.h b/internals.h index 37dcb06..83c245a 100644 --- a/internals.h +++ b/internals.h @@ -24,6 +24,7 @@ object boolQInt(object parameters); object stringQInt(object parameters); object charQInt(object parameters); object listQInt(object parameters); +object appendInt(object parameters); object consInt(object parameters); object carInt(object parameters); object cdrInt(object parameters); @@ -32,3 +33,5 @@ object applyInt(object parameters, env currentEnv); object displayInt(object parameters); object printInt(object parameters); object beginInt(object parameters); +object makeStrInt(object parameters); +object strLengthInt(object parameters); diff --git a/print.c b/print.c index c31871e..5733bee 100644 --- a/print.c +++ b/print.c @@ -16,6 +16,7 @@ char *errors[] = "Невалидна тараба-секвенца", "Неочекивани крај фајла", "Неочекивана заграда", + "Недовољно меморије доступно" }; void printValue(object input); diff --git a/util.c b/util.c index ee4a945..c7f56e3 100644 --- a/util.c +++ b/util.c @@ -491,6 +491,15 @@ int cmp(object a, object b) } } +int integer(object a) +{ + if (NUM_TYPE(a) != fractionNum || NUM_DENOM(a) != 1) + { + return 0; + } + return 1; +} + object intToBool(int boolean) { object result; diff --git a/util.h b/util.h index 7e4d884..6454095 100644 --- a/util.h +++ b/util.h @@ -64,6 +64,7 @@ typedef enum invalidHashSequenceError, unexpectedEOFError, unmatchedParenError, + outOfMemoryError } error; typedef enum @@ -197,6 +198,9 @@ object inverseNum(object a); int cmp(object a, object b); /* пореди два броја и враћа -1, 0, 1 у зависности од односа истих, претпоставља * да су објекти бројеви */ +int integer(object a); +/* проверава да ли је дати број разломачки и такође цео, претпоставља да је + * дати објекат број */ object intToBool(int boolean);