mes_string.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* -*-comment-start: "//";comment-end:""-*-
  2. * GNU Mes --- Maxwell Equations of Software
  3. * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
  4. * Copyright © 2019 Jeremiah Orians
  5. *
  6. * This file is part of GNU Mes.
  7. *
  8. * GNU Mes is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or (at
  11. * your option) any later version.
  12. *
  13. * GNU Mes is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include "mes.h"
  22. /* Imported functions */
  23. char* ntoab(SCM x, int base, int signed_p);
  24. struct cell* findsym(char *name);
  25. struct cell* make_char(int a);
  26. struct cell* make_int(int a);
  27. struct cell* make_string(char* a, int length);
  28. struct cell* make_sym(char* name);
  29. int string_size(char* a)
  30. {
  31. int i = 0;
  32. while(0 != a[i]) i = i + 1;
  33. return i;
  34. }
  35. struct cell* string_length(struct cell* a)
  36. {
  37. require(a->type == STRING, "Wrong type recieved\n");
  38. return make_int(a->length);
  39. }
  40. struct cell* string_eq(struct cell* a, struct cell* b)
  41. {
  42. require(a->type == STRING, "Wrong type recieved\n");
  43. require(b->type == STRING, "Wrong type recieved\n");
  44. if(a->length != b->length) return cell_f;
  45. if(match(a->string, b->string)) return cell_t;
  46. return cell_f;
  47. }
  48. /****************************************************************
  49. * Functions for reducing wasted memory *
  50. ****************************************************************/
  51. void reset_block(char* a)
  52. {
  53. int c;
  54. do
  55. {
  56. c = a[0];
  57. a[0] = 0;
  58. a = a + 1;
  59. } while(0 != c);
  60. }
  61. char* copy_string(char* target, char* source, int length)
  62. {
  63. int i = 0;
  64. while(i <= length)
  65. {
  66. target[i] = source[i];
  67. i = i + 1;
  68. }
  69. return target;
  70. }
  71. char* string_append(char* a, char* b)
  72. {
  73. if(NULL == a) return b;
  74. if(NULL == b) return a;
  75. int a_size = string_size(a);
  76. int buffer_size = a_size + string_size(b) + 1;
  77. char* buffer = calloc(buffer_size, sizeof(char));
  78. copy_string(buffer, a, a_size);
  79. copy_string(buffer + a_size, b, string_size(b));
  80. return buffer;
  81. }
  82. char* substring(char* s, int start, int end)
  83. {
  84. char* r = calloc((end - start) + 1, sizeof(char));
  85. int i = 0;
  86. while(start <= end)
  87. {
  88. r[i] = s[start];
  89. start = start + 1;
  90. i = i + 1;
  91. }
  92. return r;
  93. }
  94. /* Exposed primitives */
  95. struct cell* builtin_stringp(struct cell* args)
  96. {
  97. require(nil != args, "string? requires arguments\n");
  98. require(nil == args->cdr, "string? recieved too many arguments\n");
  99. if(STRING == args->car->type) return cell_t;
  100. return cell_f;
  101. }
  102. struct cell* builtin_stringeq(struct cell* args)
  103. {
  104. require(nil != args, "string=? requires arguments\n");
  105. require(STRING == args->car->type, "string=? received non-string\n");
  106. struct cell* temp = args->car;
  107. for(args = args->cdr; nil != args; args = args->cdr)
  108. {
  109. require(STRING == args->car->type, "string=? received non-string\n");
  110. if(cell_t != string_eq(temp, args->car))
  111. {
  112. return cell_f;
  113. }
  114. }
  115. return cell_t;
  116. }
  117. struct cell* builtin_string_size(struct cell* args)
  118. {
  119. require(nil != args, "string-length requires an argument\n");
  120. require(nil == args->cdr, "string-length only allows a single argument\n");
  121. return string_length(args->car);
  122. }
  123. struct cell* builtin_string_index(struct cell* args)
  124. {
  125. int i = 0;
  126. int length;
  127. char* s;
  128. char find;
  129. require(nil != args, "string-index requires arguments\n");
  130. require(STRING == args->car->type, "string-index requires a string\n");
  131. s = args->car->string;
  132. length = args->car->length;
  133. require(nil != args->cdr, "string-index requires more argument(s)\n");
  134. require(CHAR == args->cdr->car->type, "string-index requires a char\n");
  135. find = args->cdr->car->value;
  136. /* Deal with (string-index "abcde" #\c) case */
  137. if(nil == args->cdr->cdr)
  138. {
  139. while(i <= length)
  140. {
  141. if(find == s[i]) return make_int(i);
  142. i = i + 1;
  143. }
  144. /* Deal with (string-index "abcde" #\z) case */
  145. return cell_f;
  146. }
  147. require(INT == args->cdr->cdr->car->type, "string-index requires an INT\n");
  148. i = args->cdr->cdr->car->value;
  149. require(length >= i, "string-index recieved an int greater than length of string");
  150. /* Deal with (string-index "abcde" #\c 0) case */
  151. if(nil == args->cdr->cdr->cdr)
  152. {
  153. while(i <= length)
  154. {
  155. if(find == s[i]) return make_int(i);
  156. i = i + 1;
  157. }
  158. /* Deal with (string-index "abcde" #\c 3) case */
  159. return cell_f;
  160. }
  161. require(INT == args->cdr->cdr->cdr->car->type, "string-index requires an INT\n");
  162. require(length >= args->cdr->cdr->cdr->car->value, "string-index received and int greater than length of string");
  163. length = args->cdr->cdr->cdr->car->value;
  164. if(nil == args->cdr->cdr->cdr->cdr)
  165. {
  166. while(i < length)
  167. {
  168. if(find == s[i]) return make_int(i);
  169. i = i + 1;
  170. }
  171. /* Deal with (string-index "abcde" #\c 0 2) case */
  172. return cell_f;
  173. }
  174. require(FALSE, "string-index recieved too many arguments\n");
  175. exit(EXIT_FAILURE);
  176. }
  177. struct cell* builtin_string_ref(struct cell* args)
  178. {
  179. require(nil != args, "string-ref requires an argument\n");
  180. require(STRING == args->car->type, "string-ref requires a string\n");
  181. char* s = args->car->string;
  182. require(nil != args->cdr, "string-ref requires another argument\n");
  183. require(INT == args->cdr->car->type, "string-ref requires an integer\n");
  184. require(nil == args->cdr->cdr, "string-ref recieved too many arguments\n");
  185. int index = args->cdr->car->value;
  186. require(args->car->length >= index, "string-ref value longer than string\n");
  187. require(index >= 0, "string-ref value is negative\n");
  188. return make_char(s[index]);
  189. }
  190. struct cell* builtin_string_to_number(struct cell* args)
  191. {
  192. require(nil != args, "string->number requires an argument\n");
  193. require(nil == args->cdr, "string->number only supports a single argument (currently)\n");
  194. require(STRING == args->car->type, "string->number requires a string\n");
  195. int i;
  196. if('+' == args->car->string[0])
  197. {
  198. if('-' == args->car->string[1]) return cell_f;
  199. i = numerate_string(args->car->string + 1);
  200. }
  201. else i = numerate_string(args->car->string);
  202. if(0 != i) return make_int(i);
  203. if('0' == args->car->string[0]) return make_int(i);
  204. return cell_f;
  205. }
  206. struct cell* builtin_string_to_symbol(struct cell* args)
  207. {
  208. require(nil != args, "string->symbol requires an argument\n");
  209. require(nil == args->cdr, "string->symbol only supports a single argument\n");
  210. require(STRING == args->car->type, "string->symbol requires a string\n");
  211. struct cell* r = findsym(args->car->string);
  212. if(nil != r) return r->car;
  213. struct cell* newsym = make_sym(args->car->string);
  214. all_symbols = make_cons(newsym, all_symbols);
  215. return newsym;
  216. }
  217. struct cell* builtin_symbol_to_string(struct cell* args)
  218. {
  219. require(nil != args, "symbol->string requires an argument\n");
  220. require(nil == args->cdr, "symbol->string only supports a single argument\n");
  221. require(SYM == args->car->type, "symbol->string requires a symbol\n");
  222. return make_string(args->car->string, string_size(args->car->string));
  223. }
  224. struct cell* builtin_number_to_string(struct cell* args)
  225. {
  226. require(nil != args, "number->string requires an argument\n");
  227. require(INT == args->car->type, "number->string requires an integer\n");
  228. char* r;
  229. if(nil == args->cdr)
  230. {
  231. r = ntoab(args->car->value, 10, TRUE);
  232. return make_string(r, string_size(r));
  233. }
  234. require(INT == args->cdr->car->type, "number->string only accepts integer ranges\n");
  235. require(2 <= args->cdr->car->value, "number->string Value out of range 2 to 36\n");
  236. require(36 >= args->cdr->car->value, "number->string Value out of range 2 to 36\n");
  237. require(nil == args->cdr->cdr, "number->string does not support more than 2 arguments\n");
  238. r = ntoab(args->car->value, args->cdr->car->value, TRUE);
  239. return make_string(r, string_size(r));
  240. }
  241. struct cell* builtin_substring(struct cell* args)
  242. {
  243. require(nil != args, "substring requires arguments\n");
  244. require(STRING == args->car->type, "substring only works on strings\n");
  245. require(nil != args->cdr, "substring requires a starting index\n");
  246. require(INT == args->cdr->car->type, "substring's starting index must be an integer\n");
  247. int start = args->cdr->car->value;
  248. require(((start >= 0) && (start <= args->car->length )), "substring's starting index must be between 0 and the length of the string\n");
  249. if(nil == args->cdr->cdr)
  250. {
  251. return make_string(substring(args->car->string, start, args->car->length), (args->car->length - start));
  252. }
  253. require(INT == args->cdr->cdr->car->type, "substring's ending index must be an integer\n");
  254. int end = args->cdr->cdr->car->value;
  255. require(((end >= start) && (end <= args->car->length)), "substring's ending index must be between the starting index and the length of the string\n");
  256. return make_string(substring(args->car->string, start, end), (end - start));
  257. }
  258. struct cell* builtin_make_string(struct cell* args)
  259. {
  260. require(nil != args, "make-string requires arguments\n");
  261. require(INT == args->car->type, "make-string requires an integer to express the number of bytes the string needs to be\n");
  262. char* s = calloc(args->car->value + 1, sizeof(char));
  263. struct cell* r = make_string(s, args->car->value);
  264. if(nil != args->cdr)
  265. {
  266. require(CHAR == args->cdr->car->type, "make-string second argument can only be a char\n");
  267. int c = args->cdr->car->value;
  268. int i = args->car->value;
  269. while(0 <= i)
  270. {
  271. s[i] = c;
  272. i = i - 1;
  273. }
  274. require(nil == args->cdr->cdr, "make-string does not support additional arguments\n");
  275. return r;
  276. }
  277. return r;
  278. }
  279. struct cell* builtin_string_set(struct cell* args)
  280. {
  281. require(nil != args, "string-set! requires arguments\n");
  282. require(STRING == args->car->type, "string-set! requires a string\n");
  283. require(nil != args->cdr, "string-set! requires 2 more arguments\n");
  284. require(INT == args->cdr->car->type, "string-set! requires an integer index\n");
  285. require(nil != args->cdr->cdr, "string-set! requires 1 more arguments\n");
  286. require(CHAR == args->cdr->cdr->car->type, "string-set! requires a char value to set\n");
  287. require(nil == args->cdr->cdr->cdr, "string-set! does not accept extra arguments\n");
  288. char* s = args->car->string;
  289. int index = args->cdr->car->value;
  290. require(0 <= index, "string-set! index must be greater than 0\n");
  291. require(args->car->length >= index, "string-set! index must be less than the length of the string\n");
  292. s[index] = args->cdr->cdr->car->value;
  293. return cell_unspecified;
  294. }
  295. struct cell* builtin_string_append(struct cell* args)
  296. {
  297. struct cell* n = args;
  298. int size = 0;
  299. while(nil != n)
  300. {
  301. require(STRING == n->car->type, "string-append only accepts strings\n");
  302. size = size + n->car->length;
  303. n = n->cdr;
  304. }
  305. char* d = calloc(size + 1, sizeof(char));
  306. int i = 0;
  307. int j;
  308. n = args;
  309. while(nil != n)
  310. {
  311. j = 0;
  312. while(j < n->car->length)
  313. {
  314. d[i] = n->car->string[j];
  315. i = i + 1;
  316. j = j + 1;
  317. }
  318. n = n->cdr;
  319. }
  320. return make_string(d, size);
  321. }