Added package with the documentation and the examples
[lwc.git] / misc.c
blobf1310594f04c5b11270fa52301782a03e523fd2c
1 #include "global.h"
3 //#define errstream stdout
4 #define errstream stderr
6 /*****************************************************************************
7 check syntax patterns.
8 *****************************************************************************/
9 bool syntax_pattern (NormPtr p, Token first, ...)
11 va_list ap;
12 va_start (ap, first);
13 for (;first != -1; first = va_arg (ap, Token))
14 switch (first) {
15 default: if (CODE [p++] != first) return 0;
16 ncase VERIFY_symbol: if (!issymbol (CODE [p++])) return 0;
17 ncase VERIFY_string: if (!isvalue (CODE [p++])) return 0;
19 va_end (ap);
20 return 1;
23 /*****************************************************************************
24 -- Expression long-jumps
25 If an exception is raised with expr_error, it longjmps
26 Some allocated token strings will not be freed.
27 We know that. And we prefer to leave it that way.
28 *****************************************************************************/
30 typedef struct except_stck_t {
31 struct except_stck_t *up;
32 jmp_buf *env;
33 NormPtr location;
34 Token *expression;
35 void *scope;
36 int elevel, rlevel;
37 } except_stck;
39 static except_stck *bottom;
41 void set_catch (jmp_buf *env, NormPtr p, Token *t, int level)
43 except_stck *e = (except_stck*) malloc (sizeof * e);
44 e->location = p;
45 e->expression = t;
46 e->env = env;
47 e->up = bottom;
48 e->scope = active_scope ();
49 e->rlevel = e->elevel = level;
50 bottom = e;
53 static void dothrow (int level)
55 bottom->rlevel = level;
56 longjmp (*bottom->env, 1);
59 void clear_catch ()
61 except_stck *e = bottom;
62 int rlevel = e->rlevel;
63 int rethrow = rlevel && rlevel > e->elevel;
64 bottom = e->up;
65 restore_scope (e->scope);
66 free (e);
67 if (rethrow)
68 dothrow (rlevel);
71 void raise_skip_function ()
73 dothrow (1);
76 #define EER "expression error: "
77 #define WARN "Warning: "
79 static void throw_it (bool noerror)
81 int i;
82 char *MSG = noerror ? WARN : EER;
84 if (!bottom || (bottom->rlevel && !bottom->up))
85 parse_error (last_location, "Fatal");
87 fprintf (errstream, "%sin expression: ", MSG);
88 for (i = 0; bottom->expression [i] != -1; i++)
89 fprintf (errstream, "%s ", expand (bottom->expression [i]));
90 fprintf (errstream, "\n%sWhich is located in file %s:%i\n", MSG,
91 c_file_of (bottom->location), c_line_of (bottom->location));
92 if (in_function) fprintf (stderr, "%sin function %s();\n", MSG, expand (in_function));
93 if (noerror) return;
94 #ifdef DEBUG
95 if (debugflag.PARSE_ERRORS_SEGFAULT)
96 *((int*)0)=0;
97 if (debugflag.EXPR_ERRORS_FATAL) exit (1);
98 #endif
99 HadErrors = 1;
100 dothrow (0);
103 void expr_error (char *description)
105 fprintf (errstream, EER"%s\n", description);
106 throw_it (0);
109 void expr_errort (char *description, Token t)
111 fprintf (errstream, EER"%s `%s'\n", description, expand (t));
112 throw_it (0);
115 void expr_errortt (char *description, Token t1, Token t2)
117 fprintf (errstream, EER"%s `%s' `%s'\n", description, expand (t1), expand (t2));
118 throw_it (0);
121 void expr_warn (char *description)
123 fprintf (errstream, WARN"%s\n", description);
124 throw_it (1);
127 void expr_warnt (char *description, Token t)
129 fprintf (errstream, WARN"%s `%s'\n", description, expand (t));
130 throw_it (1);
133 void expr_warntt (char *description, Token t1, Token t2)
135 fprintf (errstream, WARN"%s `%s' `%s'\n", description, expand (t1), expand (t2));
136 throw_it (1);
139 static intnode *undeftree;
141 void expr_error_undef (Token t, int w)
143 if (intfind (undeftree, t)) dothrow (0);
144 union ival i;
145 intadd (&undeftree, t, i);
146 fprintf (errstream, EER"Un%s '%s'\n", w ? "declared function" : "defined object", expand (t));
147 throw_it (0);
150 void parse_error (NormPtr i, char *p)
152 fprintf (errstream, "%s:%i [Token %i]: %s\n", c_file_of(i), c_line_of(i), i, p);
153 NormPtr n = i - 10;
154 if (n < 0) n = 0;
155 fprintf (errstream, " Somewhere in ### ");
156 for (; n < i + 10 && CODE [n] != -1; n++)
157 fprintf (errstream, "%s ", expand (CODE [n]));
158 fprintf (errstream, " ###\n");
159 #ifdef DEBUG
160 if (debugflag.PARSE_ERRORS_SEGFAULT)
161 *((int*)0)=0;
162 #endif
163 exit (1);
166 NormPtr last_location;
167 Token in_function;
169 void parse_error_tok (Token t, char *p)
171 char *tmp = (char*) alloca (strlen (p) + strlen (expand (t)) + 8);
172 sprintf (tmp, "%s : `%s'", p, expand (t));
173 parse_error (last_location, tmp);
176 void parse_error_cpp (char *p)
178 fprintf (errstream, "Cpp error near line %i: %s\n", line, p);
179 exit (1);
182 void parse_error_toktok (Token t1, Token t2, char *p)
184 char *tmp = (char*) alloca (strlen (p) + strlen (expand (t1)) + strlen (expand (t2)) + 9);
185 sprintf (tmp, "%s : `%s' `%s'", p, expand (t1), expand (t2));
186 parse_error (last_location, tmp);
189 void parse_error_pt (NormPtr i, Token t, char *p)
191 char *tmp = (char*) alloca (strlen (p) + strlen (expand (t)) + 8);
192 sprintf (tmp, "%s : `%s'", p, expand (t));
193 parse_error (i, tmp);
196 void parse_error_ll (char *p)
198 parse_error (last_location, p);
201 void warning_tok (char *p, Token t)
203 fprintf (errstream, "Warning %s:%i %s '%s'\n", c_file_of (last_location),
204 c_line_of (last_location), p, expand (t));
206 /*************************************************************
207 * print a type. debuging routine which shalln't be used at all
208 *************************************************************/
210 #ifdef DEBUG
211 void debug_pr_type (typeID t)
213 int i;
214 PRINTF ("type[%i]: ", t);
215 int *tt = open_typeID (t);
216 PRINTF ("(%i)", tt [0]);
217 for (i = 1; tt [i] != -1; i++)
218 if (tt [i] == '*' || tt [i] == '(' || tt [i] == '[')
219 PRINTF ("%c", tt [i]);
220 else PRINTF ("|%i|", tt [i]);
221 PRINTF ("\n");
223 #endif
225 /******************************************************************************
226 name
227 ******************************************************************************/
229 void name_of_simple_type (Token *s, typeID t)
231 recID r;
232 switch (r = dbase_of (t)) {
233 default: sintprintf (s, iRESERVED_struct (r), name_of_struct (r), -1);
234 #define Case(x,...) break; case x: sintprintf (s, __VA_ARGS__, -1);
235 Case (B_SCHAR, RESERVED_char);
236 Case (B_UCHAR, RESERVED_unsigned, RESERVED_char);
237 Case (B_SSINT, RESERVED_short, RESERVED_int);
238 Case (B_USINT, RESERVED_unsigned, RESERVED_short, RESERVED_int);
239 Case (B_SINT, RESERVED_int);
240 Case (B_UINT, RESERVED_unsigned, RESERVED_int);
241 Case (B_SLONG, RESERVED_long);
242 Case (B_ULONG, RESERVED_unsigned, RESERVED_long);
243 Case (B_SLLONG, RESERVED_long, RESERVED_long);
244 Case (B_ULLONG, RESERVED_unsigned, RESERVED_long, RESERVED_long);
245 Case (B_FLOAT, RESERVED_float);
246 Case (B_DOUBLE, RESERVED_double);
247 Case (B_LDOUBLE, RESERVED_long, RESERVED_double);
248 Case (B_VOID, RESERVED_void);
249 Case (B_PURE, -1);
250 #undef Case
253 /******************************************************************************
254 miscellanery
255 ******************************************************************************/
257 /* integer/float promotion */
258 typeID bt_promotion (typeID t)
260 int *tt = open_typeID (t);
261 if (tt [1] == '[') {
262 int *tn = allocaint (intlen (tt) + 1);
263 intcpy (tn, tt);
264 tn [1] = '*';
265 return enter_type (tn);
267 if (tt [0] >= 0 || tt [1] != -1)
268 return t;
269 if (tt [0] <= B_ULLONG)
270 return typeID_int;
271 if (tt [0] <= B_LDOUBLE)
272 return typeID_float;
273 return t;
276 /* turn a type to pointer to type */
277 typeID ptrup (typeID t)
279 int *tt, *tn;
280 tt = open_typeID (t);
281 tn = allocaint (intlen (tt) + 2);
282 tn [0] = tt [0];
283 tn [1] = '*';
284 intcpy (tn + 2, tt + 1);
285 return enter_type (tn);
288 /* the effect of pointer indirection */
289 typeID ptrdown (typeID t)
291 int *tt = open_typeID (t), *tn;
292 if (tt [1] != '*' && tt [1] != '[')
293 expr_error ("* not applicable");
294 tn = allocaint (intlen (tt));
295 tn [0] = tt [0];
296 intcpy (tn + 1, tt + 2);
297 return enter_type (tn);
300 /* base type of [...] */
301 typeID elliptic_type (typeID t)
303 if (!typeID_elliptic (t))
304 return t;
305 int *tt = open_typeID (t), *tn;
306 tn = allocaint (intlen (tt));
307 tn [0] = tt [0];
308 intcpy (tn + 1, tt + 2);
309 return enter_type (tn);
312 /* given a function type return the return type */
313 typeID funcreturn (typeID t)
315 int *tt = open_typeID (t), *tn, i;
316 if (tt [1] != '(')
317 expr_error ("bug: request return type of no function");
318 for (i = 2; tt [i] != INTERNAL_ARGEND; i++);
319 tn = allocaint (intlen (&tt [i]) + 2);
320 tn [0] = tt [0];
321 intcpy (tn + 1, tt + i + 1);
322 return enter_type (tn);
325 /* take a function type and add the first rec* argument */
326 typeID makemember (typeID t, recID r)
328 int *tt = open_typeID (t), *tn;
329 if (tt [1] != '(')
330 expr_error ("bug: request to makemember on no function");
331 tn = allocaint (intlen (tt) + 4);
332 tn [0] = tt [0];
333 tn [1] = '(';
334 tn [2] = pthis_of_struct (r);
335 intcpy (tn + 3, tt + 2);
336 return enter_type (tn);
339 /* remove the reference boost */
340 typeID dereference (typeID t)
342 int *tt = open_typeID (t), *tn;
343 if (tt [0] < REFERENCE_BASE)
344 return t;
345 tn = allocaint (intlen (tt) + 1);
346 intcpy (tn, tt);
347 tn [0] -= REFERENCE_BOOST;
348 return enter_type (tn);
351 Token *build_type (typeID t, Token o, Token ret[])
353 /* XXX: elliptics */
354 if (is_reference (t))
355 t = ptrdown (dereference (t));
357 Token tmp [100], *dcls = &tmp [20], *dcle = dcls;
358 Token *st = open_typeID (t);
359 int i = 1, b = 0;
361 if (o) {
362 *(++dcle) = -1;
363 *dcls-- = o;
364 } else *dcls-- = -1;
366 for (;;i++) {
367 switch (st [i]) {
368 case '*':
369 *dcls-- = '*';
370 b = 1;
371 continue;
372 case '[':
373 if (b) *dcls-- = '(', *dcle++ = ')', b = 0;
374 *dcle++ = '['; *dcle++ = ']';
375 continue;
376 case '(':
377 if (b) *dcls-- = '(', *dcle++ = ')', b = 0;
378 *dcle++ = '(';
379 for (i++;;)
380 if (st [i] == B_ELLIPSIS) {
381 *dcle++ = ELLIPSIS;
382 break;
383 } else {
384 if (st [i] == INTERNAL_ARGEND) break;
385 Token arg [50];
386 intcpy (dcle, build_type (st [i++], 0, arg));
387 dcle += intlen (dcle);
388 *dcle++ = ',';
390 if (dcle [-1] == ',') --dcle;
391 *dcle++ = ')';
392 continue;
393 case -1: break;
394 default: PRINTF ("UNKNWOWN %i\n", st [i]);
396 break;
398 *dcle = -1;
400 if (st [0] >= 0)
401 if (ISSYMBOL (st [0])) sintprintf (ret, st [0], -1);
402 else sintprintf (ret, isunion (st [0]) ? RESERVED_union : iRESERVED_struct (st [0]),
403 name_of_struct (st [0]), -1);
404 else switch (st [0]) {
405 case B_UCHAR: sintprintf (ret, RESERVED_unsigned, RESERVED_char, -1);
406 ncase B_SCHAR: sintprintf (ret, RESERVED_char, -1);
407 ncase B_USINT: sintprintf (ret, RESERVED_unsigned, RESERVED_short, RESERVED_int, -1);
408 ncase B_SSINT: sintprintf (ret, RESERVED_short, RESERVED_int, -1);
409 ncase B_UINT: sintprintf (ret, RESERVED_unsigned, RESERVED_int, -1);
410 ncase B_SINT: sintprintf (ret, RESERVED_int, -1);
411 ncase B_ULONG: sintprintf (ret, RESERVED_unsigned, RESERVED_long, -1);
412 ncase B_SLONG: sintprintf (ret, RESERVED_long, -1);
413 ncase B_ULLONG: sintprintf (ret, RESERVED_unsigned, RESERVED_long, RESERVED_long, -1);
414 ncase B_SLLONG: sintprintf (ret, RESERVED_long, RESERVED_long, -1);
415 ncase B_FLOAT: sintprintf (ret, RESERVED_float, -1);
416 ncase B_DOUBLE: sintprintf (ret, RESERVED_double, -1);
417 ncase B_VOID: sintprintf (ret, RESERVED_void, -1);
420 intcat (ret, dcls + 1);
422 return ret;
425 typeID typeof_designator (typeID t, Token d[])
427 exprret E;
428 Token x = internal_identifier1 ();
429 Token expr [100];
431 sintprintf (expr, x, ISTR (d), -1);
432 expr [intlen (expr) - 1] = -1;
433 open_local_scope ();
434 enter_local_obj (x, t);
435 parse_expression_string (intdup (expr), &E);
436 close_local_scope ();
438 if (!E.ok) return typeID_void;
440 if (E.newExpr [0] == x)
441 intcpy (d, E.newExpr + 1), intcatc (d, '=');
442 free (E.newExpr);
444 return E.type;
447 /***************************************************************
448 overloadable
449 ***************************************************************/
450 Token isunary_overloadable (Token t)
452 switch (t) {
453 case '!': return RESERVED_oper_excl;
454 case '*': return RESERVED_oper_star;
455 case '+': return RESERVED_oper_plus;
456 case '-': return RESERVED_oper_minus;
457 case '~': return RESERVED_oper_thingy;
458 case POINTSAT: return RESERVED_oper_pointsat;
459 case PLUSPLUS: return RESERVED_oper_plusplus;
460 case MINUSMINUS: return RESERVED_oper_minusminus;
462 return 0;
465 Token isbinary_overloadable (Token t)
467 switch (t) {
468 case '%': return RESERVED_oper_mod;
469 case '|': return RESERVED_oper_or;
470 case '&': return RESERVED_oper_and;
471 case '^': return RESERVED_oper_xor;
472 case LSH: return RESERVED_oper_lsh;
473 case RSH: return RESERVED_oper_rsh;
474 case '*': return RESERVED_oper_mul;
475 case '/': return RESERVED_oper_div;
476 case '>': return RESERVED_oper_gr;
477 case '<': return RESERVED_oper_le;
478 case '+': return RESERVED_oper_add;
479 case '-': return RESERVED_oper_sub;
480 case ',': return RESERVED_oper_comma;
481 case '[': return RESERVED_oper_array;
482 case OROR: return RESERVED_oper_oror;
483 case EQCMP: return RESERVED_oper_eq;
484 case GEQCMP: return RESERVED_oper_greq;
485 case LEQCMP: return RESERVED_oper_leq;
486 case NEQCMP: return RESERVED_oper_neq;
487 case ANDAND: return RESERVED_oper_andand;
488 case '=': return RESERVED_oper_assign;
489 case ASSIGNA: return RESERVED_oper_as_a;
490 case ASSIGNS: return RESERVED_oper_as_s;
491 case ASSIGNM: return RESERVED_oper_as_m;
492 case ASSIGND: return RESERVED_oper_as_d;
493 case ASSIGNR: return RESERVED_oper_as_r;
494 case ASSIGNBA: return RESERVED_oper_as_ba;
495 case ASSIGNBX: return RESERVED_oper_as_bx;
496 case ASSIGNBO: return RESERVED_oper_as_bo;
497 case ASSIGNRS: return RESERVED_oper_as_rs;
498 case ASSIGNLS: return RESERVED_oper_as_ls;
500 return 0;
503 Token isunary_postfix_overloadable (Token t)
505 switch (t) {
506 case PLUSPLUS: return RESERVED_oper_plusplusp;
507 case MINUSMINUS: return RESERVED_oper_minusminusp;
509 return 0;
511 /***************************************************************
512 #include<>
513 ***************************************************************/
514 Token include_sys_header_s (char *s)
516 char tmp [128];
517 sprintf (tmp, "\n#include <%s>\n", s);
518 return new_symbol (strdup (tmp));
520 Token include_sys_header (Token t)
522 char fn [128];
523 strcpy (fn, expand (t) + 1);
524 fn [strlen (fn) - 1] = 0;
525 return include_sys_header_s (fn);
527 /***************************************************************
528 alias ("func")
529 ***************************************************************/
530 Token alias_func (recID r, Token f)
532 char tmp [512];
533 //xmark_function_USED (FSP (r), f);
534 sprintf (tmp, "__attribute__ ((alias (\"%s\")))", expand (f));
535 return new_symbol (strdup (tmp));
537 /***************************************************************
538 linkonce section text
539 ***************************************************************/
540 Token linkonce_data (Token s)
542 if (NoLinkonce) return BLANKT;
544 char tmp [512];
545 sprintf (tmp, "__attribute__ ((__section__(\""SECTION_LINKONCE_DATA"%s\")))",
546 expand (s));
547 return new_symbol (strdup (tmp));
550 Token linkonce_data_f (Token s)
552 if (NoLinkonce) return BLANKT;
554 char tmp [512];
555 sprintf (tmp, "__attribute__ ((__section__(\""SECTION_LINKONCE_DATA"%s_%s\")))",
556 expand (in_function), expand (s));
557 return new_symbol (strdup (tmp));
560 Token linkonce_text (Token s)
562 if (NoLinkonce) return BLANKT;
564 char tmp [512];
565 sprintf (tmp, "__attribute__ ((__section__(\""SECTION_LINKONCE_TEXT"%s\")))",
566 expand (s));
567 return new_symbol (strdup (tmp));
570 Token linkonce_rodata (Token s)
572 if (NoLinkonce) return BLANKT;
574 char tmp [512];
575 sprintf (tmp, "__attribute__ ((__section__(\""SECTION_LINKONCE_RODATA"%s\")))",
576 expand (s));
577 return new_symbol (strdup (tmp));
580 Token cleanup_func (Token s)
582 char tmp [512];
583 sprintf (tmp, "__attribute__ ((cleanup(%s)))",
584 expand (s));
585 return new_symbol (strdup (tmp));
588 Token section_vtblz (Token t)
590 char tmp [512];
591 sprintf (tmp, "__attribute__ ((section (\".rodata.vtblz%s\")))", expand (t));
592 return new_symbol (strdup (tmp));
595 /***************************************************************
596 internal typeof 'expression'
597 ***************************************************************/
598 typeID typeof_expression (NormPtr p, int i)
600 exprret E;
601 parse_expression (p, &E, i);
602 if (!E.ok) parse_error (p, "can't proceed after expression error");
603 free (E.newExpr);
604 return E.type;
606 /***************************************************************
607 This is used to do the -very useful- anonymous object
608 C++ thingy.
610 We are trying to determine wheter we have an object
611 declaration or a constructor call expression.
613 The check is lazy though. It will return true if
614 the code is DEFINITELLY an expression.
615 There are cases where it may or may not be.
616 Return false and let programmer make it obvious.
618 In a declaration valid characters are only
619 ( * ) [ ] const volatile
620 only one symbol and anything inside the[]
621 ***************************************************************/
623 bool is_expression (NormPtr p)
625 NormPtr p2 = skip_parenthesis (++p);
626 int nsym = 0;
627 Token t;
629 while (p < p2)
630 switch (t = CODE [p++]) {
631 case RESERVED_const:
632 case RESERVED_volatile:
633 case '(': case ')':
634 case '*': continue;
636 case '[': p = skip_brackets (p);
637 continue;
639 default:
640 if (ISSYMBOL (t))
641 if (nsym) return true;
642 else ++nsym;
643 else return true;
645 return false;
647 /******************************************************************************
648 As an exception to everything, __builtin_va_arg looks like a function,
649 but the second argument is a type. This breaks the entire parser
650 code. Adding a check to the parser for whether the function name
651 is "__builtin_va_arg", is not worth it.
653 This bogus here will replace the token string:
654 '__builtin_va_arg' '(' 'var' ',' 'type' ')'
655 With the pseudo value:
656 "__builtin_va_arg (var,type)"
658 which is internally treated as a constant value
659 of integer type
660 ******************************************************************************/
662 #define strspcat(x, y) strcat (strcat (x, " "), y)
664 void bogus1 ()
666 Token t = Lookup_Symbol ("__builtin_va_arg");
667 NormPtr p, pe, ps;
668 int symi = 0;
669 char tmpstr [256];
670 char *newsym [1640];
672 if (!t) return;
674 for (p = 0; CODE [p] != -1; p++)
675 if (CODE [p] == t) {
676 pe = p;
677 strcpy (tmpstr, expand (t));
678 if (CODE [++p] != '(') parse_error (p, "__builtin_va_arg");
679 ps = skip_parenthesis (p + 1);
680 while (p < ps)
681 strspcat (tmpstr, expand (CODE [p++]));
682 CODE [pe++] = symi + c_nval + VALBASE;
683 newsym [symi++] = strdup (tmpstr);
684 ps = p;
685 p = pe;
686 while ((CODE [pe++] = CODE [ps++]) != -1);
688 add_extra_values (newsym, symi);
689 CODE [++p] = -1;