2 Copyright (C) 2005,2006,2007,2008 Eugene K. Ressler, Jr.
4 This file is part of Sketch, a small, simple system for making
5 3d drawings with LaTeX and the PSTricks or TikZ package.
7 Sketch is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 Sketch is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Sketch; see the file COPYING.txt. If not, see
19 http://www.gnu.org/copyleft */
27 // dragon book hash function due to as&u.
36 if ((g
= h
& 0xf0000000L
) != 0)
45 // chain a new scope onto an existing symbol table (or NULL)
46 // and return the new table
48 new_scope (SYMBOL_TABLE
* sym_tab
)
51 SYMBOL_TABLE
*new_sym_tab
= safe_malloc (sizeof *new_sym_tab
);
52 new_sym_tab
->enclosing
= sym_tab
;
53 for (i
= 0; i
< ARRAY_SIZE (new_sym_tab
->head
); i
++)
54 new_sym_tab
->head
[i
] = NULL
;
58 // unchain the inner scope from an existing symbol table
59 // and return the next outer scope or NULL if this was
60 // the outermost scope; as a side effect, warns of unused
63 // we are not worrying about freeing storage; the def nodes
64 // are needed for object names anyway
66 old_scope (SYMBOL_TABLE
* sym_tab
)
69 SYMBOL
*sym
, *sym_next
;
70 SYMBOL_TABLE
*sym_tab_enclosing
;
72 // warn of unreferenced symbols
73 for (i
= 0; i
< ARRAY_SIZE (sym_tab
->head
); i
++)
75 for (sym
= sym_tab
->head
[i
]; sym
; sym
= sym_next
)
78 if (sym
->n_references
== 0 && !sym
->def_line
.include_p
)
81 warn (sym
->def_line
, "%s '%s' is never referenced",
82 object_type_str
[sym
->obj
->tag
], sym
->name
);
84 warn (sym
->def_line
, "'%s' is never referenced", sym
->name
);
89 sym_tab_enclosing
= sym_tab
->enclosing
;
91 return sym_tab_enclosing
;
95 lookup_in_inner_scope (SYMBOL_TABLE
* sym_tab
, char *name
, unsigned index
)
99 for (sym
= sym_tab
->head
[index
]; sym
; sym
= sym
->next
)
100 if (strncmp (name
, sym
->name
, sizeof sym
->name
- 1) == 0)
106 lookup (SYMBOL_TABLE
* sym_tab
, char *name
)
111 index
= hash (name
) % ARRAY_SIZE (sym_tab
->head
);
114 sym
= lookup_in_inner_scope (sym_tab
, name
, index
);
120 sym_tab
= sym_tab
->enclosing
;
127 lookup_with_type_check (SYMBOL_TABLE
* sym_tab
,
128 OBJECT_TYPE tag
, SRC_LINE line
, char *name
)
130 SYMBOL
*sym
= lookup (sym_tab
, name
);
135 if (sym
->obj
->tag
== tag
)
138 err (line
, "expected %s to be a %s and instead it's a %s",
139 name
, object_type_str
[tag
], object_type_str
[sym
->obj
->tag
]);
143 err (line
, "%s has a null definition", name
);
148 err (line
, "found undefined identifier %s while looking for %s",
149 name
, object_type_str
[tag
]);
155 look_up_tag (SYMBOL_TABLE
* sym_tab
, int *exists_p
, SRC_LINE line
, char *name
)
161 sym
= lookup (sym_tab
, name
);
162 *exists_p
= sym
&& sym
->obj
&& sym
->obj
->tag
== O_TAG_DEF
;
171 tag_exists_p (SYMBOL_TABLE
* sym_tab
, char *name
)
174 look_up_tag (sym_tab
, &exists_p
, no_line
, name
);
176 err (no_line
, "undefined tag %s", name
);
181 look_up_opts (SYMBOL_TABLE
* sym_tab
, OPTS
** r
, SRC_LINE line
, char *name
)
184 (OPTS_DEF
*) lookup_with_type_check (sym_tab
, O_OPTS_DEF
, line
,
186 *r
= def
? def
->opts
: NULL
;
190 look_up_and_append_to_opts(SYMBOL_TABLE
* sym_tab
, OPTS
** r
, SRC_LINE line
, char *name
)
193 look_up_opts(sym_tab
, &opts
, line
, name
);
204 look_up_scalar (SYMBOL_TABLE
* sym_tab
, FLOAT
* r
, SRC_LINE line
, char *name
)
207 (SCALAR_DEF
*) lookup_with_type_check (sym_tab
, O_SCALAR_DEF
, line
,
209 *r
= def
? def
->val
: 0;
213 look_up_point (SYMBOL_TABLE
* sym_tab
, POINT_3D r
, SRC_LINE line
, char *name
)
216 (POINT_DEF
*) lookup_with_type_check (sym_tab
, O_POINT_DEF
, line
,
219 copy_pt_3d (r
, def
->p
);
221 r
[X
] = r
[Y
] = r
[Z
] = 0;
225 look_up_vector (SYMBOL_TABLE
* sym_tab
, VECTOR_3D r
, SRC_LINE line
,
229 (VECTOR_DEF
*) lookup_with_type_check (sym_tab
, O_VECTOR_DEF
, line
,
232 copy_vec_3d (r
, def
->v
);
238 look_up_transform (SYMBOL_TABLE
* sym_tab
, TRANSFORM r
, SRC_LINE line
,
242 (TRANSFORM_DEF
*) lookup_with_type_check (sym_tab
, O_TRANSFORM_DEF
,
245 copy_transform (r
, def
->xf
);
251 look_up_drawable (SYMBOL_TABLE
* sym_tab
, OBJECT
** r
, SRC_LINE line
,
254 SYMBOL
*sym
= lookup (sym_tab
, name
);
260 if (is_drawable (sym
->obj
))
261 *r
= copy_drawable (sym
->obj
); // copy needed so concat of lookup result is ok
265 "expected %s to be a drawable object and instead it's a %s",
266 name
, object_type_str
[sym
->obj
->tag
]);
271 err (line
, "%s contains no drawable objects", name
);
277 "found undefined identifier %s while looking for a drawable object",
283 remove_from_inner_scope (SYMBOL_TABLE
* sym_tab
, char *name
, unsigned index
)
286 SYMBOL
*sym
, *prev_sym
;
288 for (prev_sym
= NULL
, sym
= sym_tab
->head
[index
]; sym
;
289 prev_sym
= sym
, sym
= sym
->next
)
290 if (strncmp (name
, sym
->name
, sizeof sym
->name
- 1) == 0)
293 prev_sym
->next
= sym
->next
;
295 sym_tab
->head
[index
] = sym
->next
;
304 remove_symbol (SYMBOL_TABLE
* sym_tab
, char *name
, SRC_LINE line
)
309 index
= hash (name
) % ARRAY_SIZE (sym_tab
->head
);
312 obj
= remove_from_inner_scope (sym_tab
, name
, index
);
315 sym_tab
= sym_tab
->enclosing
;
322 new_symbol (SYMBOL_TABLE
* sym_tab
, char *name
, char *tag
,
323 OBJECT
* obj
, SRC_LINE def_line
)
329 if (!name
|| !name
[0])
332 index
= hash (name
) % ARRAY_SIZE (sym_tab
->head
);
334 // def has a tag that is undefined, so ignore it
337 look_up_tag (sym_tab
, &exists_p
, def_line
, tag
);
342 sym
= lookup_in_inner_scope (sym_tab
, name
, index
);
344 // ok to redefine if tag is given and the existing definition
345 // is default and no uses have yet occurred
346 if (sym
&& !(tag
&& !sym
->tag
[0] && sym
->n_references
== 0))
348 // symbol already defined in the inner scope; this is an error
349 if (is_no_line_p (sym
->def_line
))
350 err (def_line
, "name %s is already defined", name
);
352 err (def_line
, "name %s is already defined on line %d",
353 name
, sym
->def_line
.number
);
357 warn (def_line
, "def of '%s' with tag '%s' after default", name
, tag
);
359 // create a new symbol and fill it in
360 sym
= safe_malloc (sizeof *sym
);
362 // copy up chars that fit then make sure the last is \0
363 strncpy (sym
->name
, name
, sizeof sym
->name
);
364 sym
->name
[sizeof sym
->name
- 1] = '\0';
366 if (strlen (name
) > sizeof sym
->name
- 1)
367 warn (def_line
, "long identifier shortened to '%s'", sym
->name
);
371 strncpy (sym
->tag
, tag
, sizeof sym
->tag
);
372 sym
->tag
[sizeof sym
->tag
- 1] = '\0';
378 sym
->def_line
= def_line
;
379 sym
->n_references
= 0;
382 // push onto hash table list
383 sym
->next
= sym_tab
->head
[index
];
384 sym_tab
->head
[index
] = sym
;