2 * 'sparse' library helper routines.
4 * Copyright (C) 2003 Transmeta Corp.
6 * Licensed under the Open Software License version 1.1
19 #include "expression.h"
22 struct token
*skip_to(struct token
*token
, int op
)
24 while (!match_op(token
, op
) && !eof_token(token
))
29 struct token
*expect(struct token
*token
, int op
, const char *where
)
31 if (!match_op(token
, op
)) {
32 static struct token bad_token
;
33 if (token
!= &bad_token
) {
34 bad_token
.next
= token
;
35 warn(token
->pos
, "Expected %s %s", show_special(op
), where
);
36 warn(token
->pos
, "got %s", show_token(token
));
39 return skip_to(token
, op
);
45 unsigned int hexval(unsigned int c
)
53 retval
= c
- 'a' + 10;
56 retval
= c
- 'A' + 10;
63 * Simple allocator for data that doesn't get partially free'd.
64 * The tokenizer and parser allocate a _lot_ of small data structures
65 * (often just two-three bytes for things like small integers),
66 * and since they all depend on each other you can't free them
67 * individually _anyway_. So do something that is very space-
68 * efficient: allocate larger "blobs", and give out individual
69 * small bits and pieces of it with no maintenance overhead.
71 struct allocation_blob
{
72 struct allocation_blob
*next
;
73 unsigned int left
, offset
;
78 #define blob_alloc(size) mmap(NULL, ((size)+4095) & ~4095, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
79 #define blob_free(addr,size) munmap((addr), ((size)+4095) & ~4095)
81 struct allocator_struct
{
83 struct allocation_blob
*blobs
;
84 unsigned int alignment
;
85 unsigned int chunking
;
87 unsigned int allocations
, total_bytes
, useful_bytes
;
90 void drop_all_allocations(struct allocator_struct
*desc
)
92 struct allocation_blob
*blob
= desc
->blobs
;
95 desc
->allocations
= 0;
96 desc
->total_bytes
= 0;
97 desc
->useful_bytes
= 0;
99 struct allocation_blob
*next
= blob
->next
;
100 blob_free(blob
, desc
->chunking
);
105 void *allocate(struct allocator_struct
*desc
, unsigned int size
)
107 unsigned long alignment
= desc
->alignment
;
108 struct allocation_blob
*blob
= desc
->blobs
;
112 desc
->useful_bytes
+= size
;
113 size
= (size
+ alignment
- 1) & ~(alignment
-1);
114 if (!blob
|| blob
->left
< size
) {
115 unsigned int offset
, chunking
= desc
->chunking
;
116 struct allocation_blob
*newblob
= blob_alloc(chunking
);
118 die("out of memory");
119 desc
->total_bytes
+= chunking
;
120 newblob
->next
= blob
;
122 desc
->blobs
= newblob
;
123 offset
= offsetof(struct allocation_blob
, data
);
124 if (alignment
> offset
)
126 blob
->left
= chunking
- offset
;
127 blob
->offset
= offset
- offsetof(struct allocation_blob
, data
);
129 retval
= blob
->data
+ blob
->offset
;
130 blob
->offset
+= size
;
135 static void show_allocations(struct allocator_struct
*x
)
137 fprintf(stderr
, "%s: %d allocations, %d bytes (%d total bytes, "
138 "%6.2f%% usage, %6.2f average size)\n",
139 x
->name
, x
->allocations
, x
->useful_bytes
, x
->total_bytes
,
140 100 * (double) x
->useful_bytes
/ x
->total_bytes
,
141 (double) x
->useful_bytes
/ x
->allocations
);
144 struct allocator_struct ident_allocator
= { "identifiers", NULL
, __alignof__(struct ident
), CHUNK
};
145 struct allocator_struct token_allocator
= { "tokens", NULL
, __alignof__(struct token
), CHUNK
};
146 struct allocator_struct symbol_allocator
= { "symbols", NULL
, __alignof__(struct symbol
), CHUNK
};
147 struct allocator_struct expression_allocator
= { "expressions", NULL
, __alignof__(struct expression
), CHUNK
};
148 struct allocator_struct statement_allocator
= { "statements", NULL
, __alignof__(struct statement
), CHUNK
};
149 struct allocator_struct string_allocator
= { "strings", NULL
, __alignof__(struct statement
), CHUNK
};
150 struct allocator_struct scope_allocator
= { "scopes", NULL
, __alignof__(struct scope
), CHUNK
};
151 struct allocator_struct bytes_allocator
= { "bytes", NULL
, 1, CHUNK
};
153 #define __ALLOCATOR(type, size, x) \
154 type *__alloc_##x(int extra) \
156 return allocate(&x##_allocator, size+extra); \
158 void show_##x##_alloc(void) \
160 show_allocations(&x##_allocator); \
162 void clear_##x##_alloc(void) \
164 drop_all_allocations(&x##_allocator); \
166 #define ALLOCATOR(x) __ALLOCATOR(struct x, sizeof(struct x), x)
168 ALLOCATOR(ident
); ALLOCATOR(token
); ALLOCATOR(symbol
);
169 ALLOCATOR(expression
); ALLOCATOR(statement
); ALLOCATOR(string
);
170 ALLOCATOR(scope
); __ALLOCATOR(void, 0, bytes
);
172 int ptr_list_size(struct ptr_list
*head
)
177 struct ptr_list
*list
= head
;
180 } while ((list
= list
->next
) != head
);
185 void iterate(struct ptr_list
*head
, void (*callback
)(void *, void *, int), void *data
)
187 struct ptr_list
*list
= head
;
188 int flag
= ITERATE_FIRST
;
194 for (i
= 0; i
< list
->nr
; i
++) {
195 if (i
== list
->nr
-1 && list
->next
== head
)
196 flag
|= ITERATE_LAST
;
197 callback(list
->list
[i
], data
, flag
);
201 } while (list
!= head
);
204 void add_ptr_list(struct ptr_list
**listp
, void *ptr
)
206 struct ptr_list
*list
= *listp
;
209 if (!list
|| (nr
= list
->nr
) >= LIST_NODE_NR
) {
210 struct ptr_list
*newlist
= malloc(sizeof(*newlist
));
212 die("out of memory for symbol/statement lists");
213 memset(newlist
, 0, sizeof(*newlist
));
215 newlist
->next
= newlist
;
216 newlist
->prev
= newlist
;
219 newlist
->next
= list
;
220 newlist
->prev
= list
->prev
;
221 list
->prev
->next
= newlist
;
222 list
->prev
= newlist
;
227 list
->list
[nr
] = ptr
;
232 static void do_warn(const char *type
, struct position pos
, const char * fmt
, va_list args
)
234 static char buffer
[512];
237 vsprintf(buffer
, fmt
, args
);
238 name
= input_streams
[pos
.stream
].name
;
240 fprintf(stderr
, "%s: %s:%d:%d: %s\n",
241 type
, name
, pos
.line
, pos
.pos
, buffer
);
244 void warn(struct position pos
, const char * fmt
, ...)
246 static int warnings
= 0;
249 if (warnings
> 100) {
253 fmt
= "too many warnings";
258 do_warn("warning", pos
, fmt
, args
);
263 void error(struct position pos
, const char * fmt
, ...)
267 do_warn("error", pos
, fmt
, args
);
272 void die(const char *fmt
, ...)
275 static char buffer
[512];
278 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
281 fprintf(stderr
, "%s\n", buffer
);