1.1 --- a/generator.py Sun Nov 27 22:47:09 2016 +0100
1.2 +++ b/generator.py Sun Nov 27 22:48:35 2016 +0100
1.3 @@ -53,6 +53,7 @@
1.4
1.5 function_type = "__builtins__.core.function"
1.6 type_error_type = "__builtins__.core.TypeError"
1.7 + memory_error_type = "__builtins__.core.MemoryError"
1.8
1.9 # NOTE: These must be synchronised with the library.
1.10
1.11 @@ -350,11 +351,13 @@
1.12 #define __FUNCTION_TYPE %s
1.13 #define __FUNCTION_INSTANCE_SIZE %s
1.14 #define __TYPE_ERROR_INSTANTIATOR %s
1.15 +#define __MEMORY_ERROR_INSTANTIATOR %s
1.16
1.17 #endif /* __PROGTYPES_H__ */""" % (
1.18 encode_path(self.function_type),
1.19 encode_size("<instance>", self.function_type),
1.20 - encode_instantiator_pointer(self.type_error_type)
1.21 + encode_instantiator_pointer(self.type_error_type),
1.22 + encode_instantiator_pointer(self.memory_error_type)
1.23 )
1.24
1.25 print >>f_signatures, """\
2.1 --- a/lib/__builtins__/__init__.py Sun Nov 27 22:47:09 2016 +0100
2.2 +++ b/lib/__builtins__/__init__.py Sun Nov 27 22:48:35 2016 +0100
2.3 @@ -20,7 +20,7 @@
2.4 """
2.5
2.6 from __builtins__.core import function, get_using, object, type, \
2.7 - BaseException, Exception, TypeError, \
2.8 + BaseException, Exception, MemoryError, TypeError, \
2.9 UnboundMethodInvocation, Warning
2.10
2.11 # Exceptions.
2.12 @@ -43,7 +43,6 @@
2.13 KeyError,
2.14 KeyboardInterrupt,
2.15 LookupError,
2.16 - MemoryError,
2.17 NameError,
2.18 NotImplementedError,
2.19 OSError,
3.1 --- a/lib/__builtins__/core.py Sun Nov 27 22:47:09 2016 +0100
3.2 +++ b/lib/__builtins__/core.py Sun Nov 27 22:48:35 2016 +0100
3.3 @@ -91,6 +91,7 @@
3.4 pass
3.5
3.6 class Exception(BaseException): pass
3.7 +class MemoryError(Exception): pass
3.8 class TypeError(Exception): pass
3.9 class UnboundMethodInvocation(Exception): pass
3.10 class Warning(object): pass
4.1 --- a/lib/__builtins__/exception/__init__.py Sun Nov 27 22:47:09 2016 +0100
4.2 +++ b/lib/__builtins__/exception/__init__.py Sun Nov 27 22:48:35 2016 +0100
4.3 @@ -69,7 +69,6 @@
4.4
4.5 from __builtins__.exception.system import (
4.6 EnvironmentError,
4.7 - MemoryError,
4.8 OSError,
4.9 RuntimeError,
4.10 RuntimeWarning,
5.1 --- a/lib/__builtins__/exception/system.py Sun Nov 27 22:47:09 2016 +0100
5.2 +++ b/lib/__builtins__/exception/system.py Sun Nov 27 22:48:35 2016 +0100
5.3 @@ -3,7 +3,7 @@
5.4 """
5.5 System exception objects.
5.6
5.7 -Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
5.8 +Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
5.9
5.10 This program is free software; you can redistribute it and/or modify it under
5.11 the terms of the GNU General Public License as published by the Free Software
5.12 @@ -20,7 +20,6 @@
5.13 """
5.14
5.15 class EnvironmentError(Exception): pass
5.16 -class MemoryError(Exception): pass
5.17 class OSError(Exception): pass
5.18 class RuntimeError(Exception): pass
5.19 class RuntimeWarning(Warning): pass
6.1 --- a/templates/native.c Sun Nov 27 22:47:09 2016 +0100
6.2 +++ b/templates/native.c Sun Nov 27 22:48:35 2016 +0100
6.3 @@ -1,4 +1,4 @@
6.4 -#include <stdlib.h> /* calloc, exit, realloc */
6.5 +#include <stdlib.h> /* exit */
6.6 #include <unistd.h> /* read, write */
6.7 #include <math.h> /* ceil, log10, pow */
6.8 #include <string.h> /* strcmp, strncpy, strlen */
6.9 @@ -252,7 +252,7 @@
6.10 /* self.__data__ interpreted as int */
6.11 int i = __load_via_object(self->value, __pos___data__).intvalue;
6.12 int n = i != 0 ? (int) ceil(log10(i+1)) + 1 : 2;
6.13 - char *s = calloc(n, sizeof(char));
6.14 + char *s = (char *) __ALLOCATE(n, sizeof(char));
6.15
6.16 if (i < 0) n++;
6.17 snprintf(s, n, "%d", i);
6.18 @@ -269,7 +269,7 @@
6.19 char *s = __load_via_object(self->value, __pos___data__).strvalue;
6.20 char *o = __load_via_object(other->value, __pos___data__).strvalue;
6.21 int n = strlen(s) + strlen(o) + 1;
6.22 - char *r = calloc(n, sizeof(char));
6.23 + char *r = (char *) __ALLOCATE(n, sizeof(char));
6.24
6.25 strncpy(r, s, n);
6.26 strncpy(r + strlen(s), o, n - strlen(s));
6.27 @@ -340,7 +340,7 @@
6.28 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;
6.29
6.30 /* Allocate space for the list. */
6.31 - __fragment *data = calloc(1, __FRAGMENT_SIZE(n));
6.32 + __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(n));
6.33 __attr attr = {0, .data=data};
6.34
6.35 /* The initial capacity is the same as the given size. */
6.36 @@ -377,7 +377,7 @@
6.37 {
6.38 /* NOTE: Consider various restrictions on capacity increases. */
6.39 n = capacity ? capacity * 2 : 1;
6.40 - newdata = realloc(data, __FRAGMENT_SIZE(n));
6.41 + newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));
6.42 newdata->capacity = n;
6.43 }
6.44
6.45 @@ -407,7 +407,7 @@
6.46 if (size + other_size >= capacity)
6.47 {
6.48 n = size + other_size;
6.49 - newdata = realloc(data, __FRAGMENT_SIZE(n));
6.50 + newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));
6.51 newdata->capacity = n;
6.52 }
6.53
6.54 @@ -479,7 +479,7 @@
6.55 size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);
6.56
6.57 /* Reserve space for a new string. */
6.58 - s = calloc(size + 1, sizeof(char));
6.59 + s = (char *) __ALLOCATE(size + 1, sizeof(char));
6.60
6.61 /* Build a single string from the buffer contents. */
6.62 for (i = 0, j = 0; i < data->size; i++)
7.1 --- a/templates/ops.c Sun Nov 27 22:47:09 2016 +0100
7.2 +++ b/templates/ops.c Sun Nov 27 22:48:35 2016 +0100
7.3 @@ -5,6 +5,9 @@
7.4 #include "progconsts.h"
7.5 #include "progtypes.h"
7.6
7.7 +extern void __raise_type_error();
7.8 +extern void __raise_memory_error();
7.9 +
7.10 /* Direct access and manipulation of static objects. */
7.11
7.12 __attr __load_static(__ref parent, __ref obj)
7.13 @@ -272,11 +275,29 @@
7.14 return obj->pos;
7.15 }
7.16
7.17 +/* Memory allocation. */
7.18 +
7.19 +void *__ALLOCATE(size_t nmemb, size_t size)
7.20 +{
7.21 + void *ptr = calloc(nmemb, size);
7.22 + if (ptr == NULL)
7.23 + __raise_memory_error();
7.24 + return ptr;
7.25 +}
7.26 +
7.27 +void *__REALLOCATE(void *ptr, size_t size)
7.28 +{
7.29 + void *nptr = realloc(ptr, size);
7.30 + if (nptr == NULL)
7.31 + __raise_memory_error();
7.32 + return nptr;
7.33 +}
7.34 +
7.35 /* Copying of structures. */
7.36
7.37 __ref __COPY(__ref obj, int size)
7.38 {
7.39 - __ref copy = calloc(1, size);
7.40 + __ref copy = (__ref) __ALLOCATE(1, size);
7.41 memcpy(copy, obj, size);
7.42 return copy;
7.43 }
8.1 --- a/templates/ops.h Sun Nov 27 22:47:09 2016 +0100
8.2 +++ b/templates/ops.h Sun Nov 27 22:48:35 2016 +0100
8.3 @@ -89,6 +89,11 @@
8.4 #define __ATTRCODE(__ATTRNAME) (__code_##__ATTRNAME)
8.5 #define __ATTRPOS(__ATTRNAME) (__pos_##__ATTRNAME)
8.6
8.7 +/* Memory allocation. */
8.8 +
8.9 +void *__ALLOCATE(size_t nmemb, size_t size);
8.10 +void *__REALLOCATE(void *ptr, size_t size);
8.11 +
8.12 /* Copying of structures. */
8.13
8.14 __ref __COPY(__ref obj, int size);
9.1 --- a/templates/progops.c Sun Nov 27 22:47:09 2016 +0100
9.2 +++ b/templates/progops.c Sun Nov 27 22:48:35 2016 +0100
9.3 @@ -14,7 +14,7 @@
9.4
9.5 __attr __new(const __table * table, __ref cls, size_t size)
9.6 {
9.7 - __ref obj = (__ref) calloc(1, size);
9.8 + __ref obj = (__ref) __ALLOCATE(1, size);
9.9 __attr self = {obj, obj};
9.10 __attr tmp = {0, cls};
9.11 obj->table = table;
9.12 @@ -28,7 +28,7 @@
9.13 {
9.14 /* Calculate the size of the fragment. */
9.15
9.16 - __fragment *data = (__fragment *) calloc(1, __FRAGMENT_SIZE(number));
9.17 + __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(number));
9.18 __attr attr = {0, .data=data};
9.19 unsigned int i, j;
9.20
9.21 @@ -51,6 +51,15 @@
9.22 __Raise(exc);
9.23 }
9.24
9.25 +/* A helper for raising memory errors within common operations. */
9.26 +
9.27 +void __raise_memory_error()
9.28 +{
9.29 + __attr args[1];
9.30 + __attr exc = __MEMORY_ERROR_INSTANTIATOR(args);
9.31 + __Raise(exc);
9.32 +}
9.33 +
9.34 /* Generic invocation operations. */
9.35
9.36 /* Invoke the given callable, supplying keyword argument details in the given