15 struct token
*skip_to(struct token
*token
, int op
)
17 while (!match_op(token
, op
) && !eof_token(token
))
22 struct token
*expect(struct token
*token
, int op
, const char *where
)
24 if (!match_op(token
, op
)) {
25 static struct token bad_token
;
26 if (token
!= &bad_token
) {
27 bad_token
.next
= token
;
28 warn(token
, "Expected %s %s", show_special(op
), where
);
29 warn(token
, "got %s", show_token(token
));
32 return skip_to(token
, op
);
38 unsigned int hexval(unsigned int c
)
46 retval
= c
- 'a' + 10;
49 retval
= c
- 'A' + 10;
56 * Simple allocator for data that doesn't get partially free'd.
57 * The tokenizer and parser allocate a _lot_ of small data structures
58 * (often just two-three bytes for things like small integers),
59 * and since they all depend on each other you can't free them
60 * individually _anyway_. So do something that is very space-
61 * efficient: allocate larger "blobs", and give out individual
62 * small bits and pieces of it with no maintenance overhead.
64 struct allocation_blob
{
65 struct allocation_blob
*next
;
66 unsigned int left
, offset
;
70 struct allocator_struct
{
72 struct allocation_blob
*blobs
;
73 unsigned int alignment
;
74 unsigned int chunking
;
76 unsigned int allocations
, total_bytes
, useful_bytes
;
79 void drop_all_allocations(struct allocator_struct
*desc
)
81 struct allocation_blob
*blob
= desc
->blobs
;
84 desc
->allocations
= 0;
85 desc
->total_bytes
= 0;
86 desc
->useful_bytes
= 0;
88 struct allocation_blob
*next
= blob
->next
;
94 void *allocate(struct allocator_struct
*desc
, unsigned int size
)
96 unsigned long alignment
= desc
->alignment
;
97 struct allocation_blob
*blob
= desc
->blobs
;
101 desc
->useful_bytes
+= size
;
102 size
= (size
+ alignment
- 1) & ~(alignment
-1);
103 if (!blob
|| blob
->left
< size
) {
104 unsigned int offset
, chunking
= desc
->chunking
;
105 struct allocation_blob
*newblob
= malloc(chunking
);
107 die("out of memory");
108 desc
->total_bytes
+= chunking
;
109 newblob
->next
= blob
;
111 desc
->blobs
= newblob
;
112 offset
= offsetof(struct allocation_blob
, data
);
113 if (alignment
> offset
)
115 blob
->left
= chunking
- offset
;
116 blob
->offset
= offset
- offsetof(struct allocation_blob
, data
);
118 retval
= blob
->data
+ blob
->offset
;
119 blob
->offset
+= size
;
124 static void show_allocations(struct allocator_struct
*x
)
126 fprintf(stderr
, "%s: %d allocations, %d bytes (%d total bytes, "
127 "%6.2f%% usage, %6.2f average size)\n",
128 x
->name
, x
->allocations
, x
->useful_bytes
, x
->total_bytes
,
129 100 * (double) x
->useful_bytes
/ x
->total_bytes
,
130 (double) x
->useful_bytes
/ x
->allocations
);
133 struct allocator_struct ident_allocator
= { "identifiers", NULL
, __alignof__(struct ident
), 8192 };
134 struct allocator_struct token_allocator
= { "tokens", NULL
, __alignof__(struct token
), 8192 };
135 struct allocator_struct symbol_allocator
= { "symbols", NULL
, __alignof__(struct symbol
), 8192 };
136 struct allocator_struct expression_allocator
= { "expressions", NULL
, __alignof__(struct expression
), 8192 };
137 struct allocator_struct statement_allocator
= { "statements", NULL
, __alignof__(struct statement
), 8192 };
138 struct allocator_struct string_allocator
= { "strings", NULL
, __alignof__(struct statement
), 8192 };
139 struct allocator_struct bytes_allocator
= { "bytes", NULL
, 1, 8192 };
141 #define __ALLOCATOR(type, size, prepare, x) \
142 type *__alloc_##x(int extra) \
144 type *ret = allocate(&x##_allocator, \
149 void show_##x##_alloc(void) \
151 show_allocations(&x##_allocator); \
153 void clear_##x##_alloc(void) \
155 drop_all_allocations(&x##_allocator); \
157 #define ALLOCATOR(x) __ALLOCATOR(struct x, sizeof(struct x), memset(ret, 0, sizeof(struct x)), x)
159 ALLOCATOR(ident
); ALLOCATOR(token
); ALLOCATOR(symbol
);
160 ALLOCATOR(expression
); ALLOCATOR(statement
); ALLOCATOR(string
);
161 __ALLOCATOR(void, 0, , bytes
);
163 void iterate(struct ptr_list
*head
, void (*callback
)(void *))
165 struct ptr_list
*list
= head
;
170 for (i
= 0; i
< list
->nr
; i
++)
171 callback(list
->list
[i
]);
173 } while (list
!= head
);
176 void add_ptr_list(struct ptr_list
**listp
, void *ptr
)
178 struct ptr_list
*list
= *listp
;
181 if (!list
|| (nr
= list
->nr
) >= LIST_NODE_NR
) {
182 struct ptr_list
*newlist
= malloc(sizeof(*newlist
));
184 die("out of memory for symbol/statement lists");
185 memset(newlist
, 0, sizeof(*newlist
));
187 newlist
->next
= newlist
;
188 newlist
->prev
= newlist
;
191 newlist
->next
= list
;
192 newlist
->prev
= list
->prev
;
193 list
->prev
->next
= newlist
;
194 list
->prev
= newlist
;
199 list
->list
[nr
] = ptr
;
204 static void do_warn(const char *type
, struct token
*token
, const char * fmt
, va_list args
)
206 static char buffer
[512];
210 vsprintf(buffer
, fmt
, args
);
215 name
= input_streams
[token
->stream
].name
;
220 fprintf(stderr
, "%s: %s:%d:%d: %s\n",
221 type
, name
, line
, pos
, buffer
);
224 void warn(struct token
*token
, const char * fmt
, ...)
226 static int warnings
= 0;
229 do_warn("warning", token
, fmt
, args
);
233 error(token
, "too many warnings");
236 void error(struct token
*token
, const char * fmt
, ...)
240 do_warn("error", token
, fmt
, args
);
245 void die(const char *fmt
, ...)
248 static char buffer
[512];
251 vsnprintf(buffer
, sizeof(buffer
), fmt
, args
);
254 fprintf(stderr
, "%s\n", buffer
);