blob: 9ed34b8be35dc5ea9e0449abd4ee806aafbf7a9e [file] [log] [blame]
Vladimir Marangozov58e64a82000-09-03 23:47:08 +00001/* Parse tree node implementation */
2
Tim Peters1d6a7292000-09-26 06:11:54 +00003#include "Python.h"
Vladimir Marangozov58e64a82000-09-03 23:47:08 +00004#include "node.h"
5#include "errcode.h"
6
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00007node *
Thomas Wouters23c9e002000-07-22 19:20:54 +00008PyNode_New(int type)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00009{
Guido van Rossum86bea461997-04-29 21:03:06 +000010 node *n = PyMem_NEW(node, 1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000011 if (n == NULL)
12 return NULL;
13 n->n_type = type;
14 n->n_str = NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +000015 n->n_lineno = 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000016 n->n_nchildren = 0;
17 n->n_child = NULL;
18 return n;
19}
20
Tim Peters623fdb92002-07-08 19:11:07 +000021/* See comments at XXXROUNDUP below. Returns -1 on overflow. */
Tim Peters755ebea2002-07-08 06:32:09 +000022static int
23fancy_roundup(int n)
24{
25 /* Round up to the closest power of 2 >= n. */
26 int result = 256;
27 assert(n > 128);
Tim Peters623fdb92002-07-08 19:11:07 +000028 while (result < n) {
Tim Peters755ebea2002-07-08 06:32:09 +000029 result <<= 1;
Tim Peters623fdb92002-07-08 19:11:07 +000030 if (result <= 0)
31 return -1;
32 }
Tim Peters755ebea2002-07-08 06:32:09 +000033 return result;
34}
35
36/* A gimmick to make massive numbers of reallocs quicker. The result is
37 * a number >= the input. For n=0 we must return 0.
38 * For n=1, we return 1, to avoid wasting memory in common 1-child nodes
39 * (XXX are those actually common?).
40 * Else for n <= 128, round up to the closest multiple of 4. Why 4?
41 * Rounding up to a multiple of an exact power of 2 is very efficient.
42 * Else call fancy_roundup() to grow proportionately to n. We've got an
43 * extreme case then (like test_longexp.py), and on many platforms doing
44 * anything less than proportional growth leads to exorbitant runtime
45 * (e.g., MacPython), or extreme fragmentation of user address space (e.g.,
46 * Win98).
47 * This would be straightforward if a node stored its current capacity. The
48 * code is tricky to avoid that.
49 */
50#define XXXROUNDUP(n) ((n) == 1 ? 1 : \
51 (n) <= 128 ? (((n) + 3) & ~3) : \
52 fancy_roundup(n))
53
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000054
Jeremy Hylton94988062000-06-20 19:10:44 +000055int
Thomas Wouters23c9e002000-07-22 19:20:54 +000056PyNode_AddChild(register node *n1, int type, char *str, int lineno)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000057{
Tim Peters755ebea2002-07-08 06:32:09 +000058 const int nch = n1->n_nchildren;
59 int current_capacity;
60 int required_capacity;
61 node *n;
62
Fred Drakeef8ace32000-08-24 00:32:09 +000063 if (nch == INT_MAX || nch < 0)
Jeremy Hylton94988062000-06-20 19:10:44 +000064 return E_OVERFLOW;
Tim Peters755ebea2002-07-08 06:32:09 +000065
66 current_capacity = XXXROUNDUP(nch);
67 required_capacity = XXXROUNDUP(nch + 1);
Tim Peters623fdb92002-07-08 19:11:07 +000068 if (current_capacity < 0 || required_capacity < 0)
69 return E_OVERFLOW;
Tim Peters755ebea2002-07-08 06:32:09 +000070 if (current_capacity < required_capacity) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000071 n = n1->n_child;
Tim Peters755ebea2002-07-08 06:32:09 +000072 PyMem_RESIZE(n, node, required_capacity);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000073 if (n == NULL)
Jeremy Hylton94988062000-06-20 19:10:44 +000074 return E_NOMEM;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000075 n1->n_child = n;
76 }
Tim Peters755ebea2002-07-08 06:32:09 +000077
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000078 n = &n1->n_child[n1->n_nchildren++];
79 n->n_type = type;
80 n->n_str = str;
Guido van Rossum3f5da241990-12-20 15:06:42 +000081 n->n_lineno = lineno;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000082 n->n_nchildren = 0;
83 n->n_child = NULL;
Jeremy Hylton94988062000-06-20 19:10:44 +000084 return 0;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000085}
Guido van Rossum03a24cd1990-11-18 17:37:06 +000086
Guido van Rossum3f5da241990-12-20 15:06:42 +000087/* Forward */
Tim Petersdbd9ba62000-07-09 03:09:57 +000088static void freechildren(node *);
Guido van Rossum3f5da241990-12-20 15:06:42 +000089
90
91void
Thomas Wouters23c9e002000-07-22 19:20:54 +000092PyNode_Free(node *n)
Guido van Rossum3f5da241990-12-20 15:06:42 +000093{
94 if (n != NULL) {
95 freechildren(n);
Guido van Rossum86bea461997-04-29 21:03:06 +000096 PyMem_DEL(n);
Guido van Rossum3f5da241990-12-20 15:06:42 +000097 }
98}
99
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000100static void
Thomas Wouters23c9e002000-07-22 19:20:54 +0000101freechildren(node *n)
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000102{
103 int i;
104 for (i = NCH(n); --i >= 0; )
105 freechildren(CHILD(n, i));
106 if (n->n_child != NULL)
Guido van Rossum86bea461997-04-29 21:03:06 +0000107 PyMem_DEL(n->n_child);
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000108 if (STR(n) != NULL)
Guido van Rossum86bea461997-04-29 21:03:06 +0000109 PyMem_DEL(STR(n));
Guido van Rossum03a24cd1990-11-18 17:37:06 +0000110}