Line data Source code
1 : /* do not edit automatically generated by mc from M2CaseList. */
2 : /* M2CaseList.mod implement ISO case label lists.
3 :
4 : Copyright (C) 2009-2026 Free Software Foundation, Inc.
5 : Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 :
7 : This file is part of GNU Modula-2.
8 :
9 : GNU Modula-2 is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3, or (at your option)
12 : any later version.
13 :
14 : GNU Modula-2 is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GNU Modula-2; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "gcc-consolidation.h"
26 :
27 : #include <stdbool.h>
28 : # if !defined (PROC_D)
29 : # define PROC_D
30 : typedef void (*PROC_t) (void);
31 : typedef struct { PROC_t proc; } PROC;
32 : # endif
33 :
34 : # if !defined (TRUE)
35 : # define TRUE (1==1)
36 : # endif
37 :
38 : # if !defined (FALSE)
39 : # define FALSE (1==0)
40 : # endif
41 :
42 : # include "GStorage.h"
43 : #if defined(__cplusplus)
44 : # undef NULL
45 : # define NULL 0
46 : #endif
47 : #define _M2CaseList_C
48 :
49 : #include "GM2CaseList.h"
50 : # include "GM2Debug.h"
51 : # include "GM2GCCDeclare.h"
52 : # include "GM2MetaError.h"
53 : # include "GM2Error.h"
54 : # include "GM2Range.h"
55 : # include "GM2ALU.h"
56 : # include "GIndexing.h"
57 : # include "GLists.h"
58 : # include "GNameKey.h"
59 : # include "GSymbolConversion.h"
60 : # include "GDynamicStrings.h"
61 : # include "Ggcctypes.h"
62 : # include "Gm2block.h"
63 : # include "Gm2type.h"
64 : # include "Gm2expr.h"
65 : # include "GStorage.h"
66 : # include "GM2Base.h"
67 : # include "GM2LexBuf.h"
68 : # include "GNumberIO.h"
69 : # include "GSymbolTable.h"
70 :
71 : typedef struct M2CaseList__T1_r M2CaseList__T1;
72 :
73 : typedef M2CaseList__T1 *M2CaseList_RangePair;
74 :
75 : typedef struct M2CaseList__T2_r M2CaseList__T2;
76 :
77 : typedef M2CaseList__T2 *M2CaseList_ConflictingPair;
78 :
79 : typedef struct M2CaseList__T3_r M2CaseList__T3;
80 :
81 : typedef M2CaseList__T3 *M2CaseList_CaseList;
82 :
83 : typedef struct M2CaseList__T4_r M2CaseList__T4;
84 :
85 : typedef M2CaseList__T4 *M2CaseList_CaseDescriptor;
86 :
87 : typedef struct M2CaseList__T5_r M2CaseList__T5;
88 :
89 : typedef M2CaseList__T5 *M2CaseList_SetRange;
90 :
91 : struct M2CaseList__T1_r {
92 : unsigned int low;
93 : unsigned int high;
94 : unsigned int tokenno;
95 : };
96 :
97 : struct M2CaseList__T2_r {
98 : M2CaseList_RangePair a;
99 : M2CaseList_RangePair b;
100 : };
101 :
102 : struct M2CaseList__T3_r {
103 : unsigned int maxRangeId;
104 : Indexing_Index rangeArray;
105 : M2CaseList_RangePair currentRange;
106 : unsigned int varientField;
107 : };
108 :
109 : struct M2CaseList__T4_r {
110 : bool resolved;
111 : bool elseClause;
112 : unsigned int elseField;
113 : unsigned int record;
114 : unsigned int varient;
115 : unsigned int expression;
116 : unsigned int maxCaseId;
117 : Indexing_Index caseListArray;
118 : M2CaseList_CaseList currentCase;
119 : M2CaseList_CaseDescriptor next;
120 : };
121 :
122 : struct M2CaseList__T5_r {
123 : tree low;
124 : tree high;
125 : M2CaseList_SetRange next;
126 : };
127 :
128 : static M2CaseList_CaseDescriptor caseStack;
129 : static unsigned int caseId;
130 : static Indexing_Index caseArray;
131 : static Indexing_Index conflictArray;
132 : static M2CaseList_SetRange FreeRangeList;
133 : static DynamicStrings_String errorString;
134 :
135 : /*
136 : PushCase - create a case entity and push it to an internal stack.
137 : rec is NulSym if this is a CASE statement.
138 : If rec is a record then it indicates a possible
139 : varients reside in the record to check.
140 : Both rec and va might be NulSym and then the expr
141 : will contain the selector expression to a case statement.
142 : Return the case id.
143 : */
144 :
145 : extern "C" unsigned int M2CaseList_PushCase (unsigned int rec, unsigned int va, unsigned int expr);
146 :
147 : /*
148 : PopCase - pop the top element of the case entity from the internal
149 : stack.
150 : */
151 :
152 : extern "C" void M2CaseList_PopCase (void);
153 :
154 : /*
155 : ElseCase - indicates that this case varient does have an else clause.
156 : */
157 :
158 : extern "C" void M2CaseList_ElseCase (unsigned int f);
159 :
160 : /*
161 : BeginCaseList - create a new label list.
162 : */
163 :
164 : extern "C" void M2CaseList_BeginCaseList (unsigned int v);
165 :
166 : /*
167 : EndCaseList - terminate the current label list.
168 : */
169 :
170 : extern "C" void M2CaseList_EndCaseList (void);
171 :
172 : /*
173 : AddRange - add a range to the current label list.
174 : */
175 :
176 : extern "C" void M2CaseList_AddRange (unsigned int r1, unsigned int r2, unsigned int tok);
177 :
178 : /*
179 : CaseBoundsResolved - returns TRUE if all constants in the case list, c,
180 : are known to GCC.
181 : */
182 :
183 : extern "C" bool M2CaseList_CaseBoundsResolved (unsigned int tokenno, unsigned int c);
184 :
185 : /*
186 : TypeCaseBounds - returns true if all bounds in case list, c, are
187 : compatible with the tagged type.
188 : */
189 :
190 : extern "C" bool M2CaseList_TypeCaseBounds (unsigned int c);
191 :
192 : /*
193 : OverlappingCaseBounds - returns TRUE if there were any overlapping bounds
194 : in the case list, c. It will generate an error
195 : messages for each overlapping bound found.
196 : */
197 :
198 : extern "C" bool M2CaseList_OverlappingCaseBounds (unsigned int c);
199 :
200 : /*
201 : MissingCaseBounds - returns true if there were any missing bounds
202 : in the varient record case list, c. It will
203 : generate an error message for each missing
204 : bounds found.
205 : */
206 :
207 : extern "C" bool M2CaseList_MissingCaseBounds (unsigned int tokenno, unsigned int c);
208 :
209 : /*
210 : MissingCaseStatementBounds - returns true if the case statement has a missing
211 : clause. It will also generate error messages.
212 : */
213 :
214 : extern "C" bool M2CaseList_MissingCaseStatementBounds (unsigned int tokenno, unsigned int c);
215 :
216 : /*
217 : WriteCase - dump out the case list (internal debugging).
218 : */
219 :
220 : extern "C" void M2CaseList_WriteCase (unsigned int c);
221 :
222 : /*
223 : GetVariantTagType - returns the type associated with, variant.
224 : */
225 :
226 : static unsigned int GetVariantTagType (unsigned int variant);
227 :
228 : /*
229 : CheckCaseBoundsResolved - return TRUE if all constants in the case list c are known to GCC.
230 : */
231 :
232 : static bool CheckCaseBoundsResolved (unsigned int tokenno, unsigned int c);
233 :
234 : /*
235 : ConvertNulStr2NulChar -
236 : */
237 :
238 : static void ConvertNulStr2NulChar (unsigned int tokenno, unsigned int c);
239 :
240 : /*
241 : NulStr2NulChar - if sym is a const string of length 0 then return
242 : a nul char instead otherwise return sym.
243 : */
244 :
245 : static unsigned int NulStr2NulChar (unsigned int tok, unsigned int sym);
246 :
247 : /*
248 : IsSame - return TRUE if r, s, are in, e.
249 : */
250 :
251 : static bool IsSame (M2CaseList_ConflictingPair e, M2CaseList_RangePair r, M2CaseList_RangePair s);
252 :
253 : /*
254 : SeenBefore -
255 : */
256 :
257 : static bool SeenBefore (M2CaseList_RangePair r, M2CaseList_RangePair s);
258 :
259 : /*
260 : Overlaps -
261 : */
262 :
263 : static bool Overlaps (M2CaseList_RangePair r, M2CaseList_RangePair s);
264 :
265 : /*
266 : GetCaseExpression - return the type from the expression.
267 : */
268 :
269 : static unsigned int GetCaseExpression (M2CaseList_CaseDescriptor p);
270 :
271 : /*
272 : OverlappingCaseBound - returns TRUE if, r, overlaps any case bound in the
273 : case statement, c.
274 : */
275 :
276 : static bool OverlappingCaseBound (M2CaseList_RangePair r, unsigned int c);
277 :
278 : /*
279 : NewRanges - return a new range from the freelist or heap.
280 : */
281 :
282 : static M2CaseList_SetRange NewRanges (void);
283 :
284 : /*
285 : NewSet - returns a new set based on type with the low and high fields assigned
286 : to the min and max values for the type.
287 : */
288 :
289 : static M2CaseList_SetRange NewSet (unsigned int type);
290 :
291 : /*
292 : DisposeRanges - place set and its list onto the free list.
293 : */
294 :
295 : static M2CaseList_SetRange DisposeRanges (M2CaseList_SetRange set);
296 :
297 : /*
298 : RemoveRange - removes the range descriptor h from set and return the
299 : possibly new head of set.
300 : */
301 :
302 : static M2CaseList_SetRange RemoveRange (M2CaseList_SetRange set, M2CaseList_SetRange h);
303 :
304 : /*
305 : SubBitRange - subtracts bits, lo..hi, from, set.
306 : */
307 :
308 : static M2CaseList_SetRange SubBitRange (M2CaseList_SetRange set, tree lo, tree hi, unsigned int tokenno);
309 :
310 : /*
311 : CheckLowHigh - checks to see the low value <= high value and issues an error
312 : if this is not true.
313 : */
314 :
315 : static void CheckLowHigh (M2CaseList_RangePair rp);
316 :
317 : /*
318 : ExcludeCaseRanges - excludes all case ranges found in, p, from, set
319 : */
320 :
321 : static M2CaseList_SetRange ExcludeCaseRanges (M2CaseList_SetRange set, M2CaseList_CaseDescriptor cd);
322 :
323 : /*
324 : IncludeElement - only include enumeration field into errorString if it lies between low..high.
325 : */
326 :
327 : static void IncludeElement (Lists_List enumList, unsigned int field, tree low, tree high);
328 :
329 : /*
330 : IncludeElements - only include enumeration field values low..high in errorString.
331 : */
332 :
333 : static void IncludeElements (unsigned int type, Lists_List enumList, tree low, tree high);
334 :
335 : /*
336 : ErrorRangeEnum - include enumeration fields Low to High in errorString.
337 : */
338 :
339 : static void ErrorRangeEnum (unsigned int type, M2CaseList_SetRange set, Lists_List enumList);
340 :
341 : /*
342 : ErrorRanges - return a list of all enumeration fields not present in the case statement.
343 : The return value will be nil if type is not an enumeration type.
344 : */
345 :
346 : static Lists_List ErrorRanges (unsigned int type, M2CaseList_SetRange set);
347 :
348 : /*
349 : appendString - appends str to errorString.
350 : */
351 :
352 : static void appendString (DynamicStrings_String str);
353 :
354 : /*
355 : appendEnum - appends enum to errorString.
356 : */
357 :
358 : static void appendEnum (unsigned int enum_);
359 :
360 : /*
361 : appendStr - appends str to errorString.
362 : */
363 :
364 : static void appendStr (const char *str_, unsigned int _str_high);
365 :
366 : /*
367 : EnumerateErrors - populate errorString with the contents of enumList.
368 : */
369 :
370 : static void EnumerateErrors (Lists_List enumList);
371 :
372 : /*
373 : NoOfSetElements - return the number of set elements.
374 : */
375 :
376 : static tree NoOfSetElements (M2CaseList_SetRange set);
377 :
378 : /*
379 : isPrintableChar - a cautious isprint.
380 : */
381 :
382 : static bool isPrintableChar (tree value);
383 :
384 : /*
385 : appendTree - append tree value to the errorString. It attempts to pretty print
386 : CHAR constants and will fall back to CHR (x) if necessary.
387 : */
388 :
389 : static void appendTree (tree value, unsigned int type);
390 :
391 : /*
392 : SubrangeErrors - create an errorString containing all set ranges.
393 : */
394 :
395 : static void SubrangeErrors (unsigned int subrangetype, M2CaseList_SetRange set);
396 :
397 : /*
398 : EmitMissingRangeErrors - emits a singular/plural error message for an enumeration type.
399 : */
400 :
401 : static void EmitMissingRangeErrors (unsigned int tokenno, unsigned int type, M2CaseList_SetRange set);
402 :
403 : /*
404 : checkTypes - checks to see that, constant, and, type, are compatible.
405 : */
406 :
407 : static bool checkTypes (unsigned int constant, unsigned int type);
408 :
409 : /*
410 : inRange - returns true if, min <= i <= max.
411 : */
412 :
413 : static bool inRange (unsigned int i, unsigned int min, unsigned int max);
414 :
415 :
416 : /*
417 : GetVariantTagType - returns the type associated with, variant.
418 : */
419 :
420 12750 : static unsigned int GetVariantTagType (unsigned int variant)
421 : {
422 12750 : unsigned int tag;
423 :
424 12750 : tag = SymbolTable_GetVarientTag (variant);
425 12750 : if ((SymbolTable_IsFieldVarient (tag)) || (SymbolTable_IsRecordField (tag)))
426 : {
427 12726 : return SymbolTable_GetType (tag);
428 : }
429 : else
430 : {
431 : return tag;
432 : }
433 : /* static analysis guarentees a RETURN statement will be used before here. */
434 : __builtin_unreachable ();
435 : }
436 :
437 :
438 : /*
439 : CheckCaseBoundsResolved - return TRUE if all constants in the case list c are known to GCC.
440 : */
441 :
442 9676 : static bool CheckCaseBoundsResolved (unsigned int tokenno, unsigned int c)
443 : {
444 9676 : M2CaseList_CaseDescriptor p;
445 9676 : M2CaseList_CaseList q;
446 9676 : M2CaseList_RangePair r;
447 9676 : unsigned int min;
448 9676 : unsigned int max;
449 9676 : unsigned int type;
450 9676 : unsigned int i;
451 9676 : unsigned int j;
452 :
453 9676 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
454 9676 : if (p->varient != SymbolTable_NulSym)
455 : {
456 : /* not a CASE statement, but a varient record containing without an ELSE clause */
457 8616 : type = GetVariantTagType (p->varient);
458 8616 : p->resolved = true;
459 8616 : if (! (SymbolConversion_GccKnowsAbout (type)))
460 : {
461 : /* do we need to add, type, to the list of types required to be resolved? */
462 5538 : p->resolved = false;
463 : }
464 8616 : min = M2GCCDeclare_GetTypeMin (type);
465 8616 : if (! (SymbolConversion_GccKnowsAbout (min)))
466 : {
467 5628 : M2GCCDeclare_TryDeclareConstant (tokenno, min);
468 5628 : p->resolved = false;
469 : }
470 8616 : max = M2GCCDeclare_GetTypeMax (type);
471 8616 : if (! (SymbolConversion_GccKnowsAbout (max)))
472 : {
473 5628 : M2GCCDeclare_TryDeclareConstant (tokenno, max);
474 5628 : p->resolved = false;
475 : }
476 8616 : if (! p->resolved)
477 : {
478 : return false;
479 : }
480 : }
481 : i = 1;
482 13730 : while (i <= p->maxCaseId)
483 : {
484 9766 : q = static_cast<M2CaseList_CaseList> (Indexing_GetIndice (p->caseListArray, i));
485 9766 : j = 1;
486 29306 : while (j <= q->maxRangeId)
487 : {
488 9858 : r = static_cast<M2CaseList_RangePair> (Indexing_GetIndice (q->rangeArray, j));
489 9858 : if (r->low != SymbolTable_NulSym)
490 : {
491 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
492 9858 : if (SymbolTable_IsConst (r->low))
493 : {
494 : /* avoid dangling else. */
495 9858 : M2GCCDeclare_TryDeclareConstant (tokenno, r->low);
496 9858 : if (! (SymbolConversion_GccKnowsAbout (r->low)))
497 : {
498 : return false;
499 : }
500 : }
501 : else
502 : {
503 0 : if (r->high == SymbolTable_NulSym)
504 : {
505 0 : M2MetaError_MetaError1 ((const char *) "the CASE statement variant must be defined by a constant {%1Da:is a {%1dv}}", 75, r->low);
506 : }
507 : else
508 : {
509 0 : M2MetaError_MetaError1 ((const char *) "the CASE statement variant low value in a range must be defined by a constant {%1Da:is a {%1dv}}", 96, r->low);
510 : }
511 : }
512 : }
513 9774 : if (r->high != SymbolTable_NulSym)
514 : {
515 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
516 168 : if (SymbolTable_IsConst (r->high))
517 : {
518 : /* avoid dangling else. */
519 168 : M2GCCDeclare_TryDeclareConstant (tokenno, r->high);
520 168 : if (! (SymbolConversion_GccKnowsAbout (r->high)))
521 : {
522 : return false;
523 : }
524 : }
525 : else
526 : {
527 0 : M2MetaError_MetaError1 ((const char *) "the CASE statement variant high value in a range must be defined by a constant {%1Da:is a {%1dv}}", 97, r->high);
528 : }
529 : }
530 9774 : j += 1;
531 : }
532 9682 : i += 1;
533 : }
534 : return true;
535 : /* static analysis guarentees a RETURN statement will be used before here. */
536 : __builtin_unreachable ();
537 : }
538 :
539 :
540 : /*
541 : ConvertNulStr2NulChar -
542 : */
543 :
544 3964 : static void ConvertNulStr2NulChar (unsigned int tokenno, unsigned int c)
545 : {
546 3964 : M2CaseList_CaseDescriptor p;
547 3964 : M2CaseList_CaseList q;
548 3964 : M2CaseList_RangePair r;
549 3964 : unsigned int i;
550 3964 : unsigned int j;
551 :
552 3964 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
553 3964 : i = 1;
554 17594 : while (i <= p->maxCaseId)
555 : {
556 9666 : q = static_cast<M2CaseList_CaseList> (Indexing_GetIndice (p->caseListArray, i));
557 9666 : j = 1;
558 29090 : while (j <= q->maxRangeId)
559 : {
560 9758 : r = static_cast<M2CaseList_RangePair> (Indexing_GetIndice (q->rangeArray, j));
561 9758 : r->low = NulStr2NulChar (tokenno, r->low);
562 9758 : r->high = NulStr2NulChar (tokenno, r->high);
563 9758 : j += 1;
564 : }
565 9666 : i += 1;
566 : }
567 3964 : }
568 :
569 :
570 : /*
571 : NulStr2NulChar - if sym is a const string of length 0 then return
572 : a nul char instead otherwise return sym.
573 : */
574 :
575 19516 : static unsigned int NulStr2NulChar (unsigned int tok, unsigned int sym)
576 : {
577 19516 : if (sym != SymbolTable_NulSym)
578 : {
579 9926 : if (((SymbolTable_IsConst (sym)) && (SymbolTable_IsConstString (sym))) && (SymbolConversion_GccKnowsAbout (sym)))
580 : {
581 892 : if ((SymbolTable_GetStringLength (tok, sym)) == 0)
582 : {
583 6 : sym = SymbolTable_MakeConstVar (tok, NameKey_NulName);
584 6 : SymbolTable_PutConst (sym, M2Base_Char);
585 6 : M2ALU_PushCard (0);
586 6 : SymbolTable_PopValue (sym);
587 6 : M2GCCDeclare_TryDeclareConstant (tok, sym);
588 6 : M2Debug_Assert (SymbolConversion_GccKnowsAbout (sym));
589 : }
590 : }
591 : }
592 19516 : return sym;
593 : /* static analysis guarentees a RETURN statement will be used before here. */
594 : __builtin_unreachable ();
595 : }
596 :
597 :
598 : /*
599 : IsSame - return TRUE if r, s, are in, e.
600 : */
601 :
602 24 : static bool IsSame (M2CaseList_ConflictingPair e, M2CaseList_RangePair r, M2CaseList_RangePair s)
603 : {
604 24 : return ((e->a == r) && (e->b == s)) || ((e->a == s) && (e->b == r));
605 : /* static analysis guarentees a RETURN statement will be used before here. */
606 : __builtin_unreachable ();
607 : }
608 :
609 :
610 : /*
611 : SeenBefore -
612 : */
613 :
614 48 : static bool SeenBefore (M2CaseList_RangePair r, M2CaseList_RangePair s)
615 : {
616 48 : unsigned int i;
617 48 : unsigned int h;
618 48 : M2CaseList_ConflictingPair e;
619 :
620 48 : h = Indexing_HighIndice (conflictArray);
621 48 : i = 1;
622 96 : while (i <= h)
623 : {
624 24 : e = static_cast<M2CaseList_ConflictingPair> (Indexing_GetIndice (conflictArray, i));
625 24 : if (IsSame (e, r, s))
626 : {
627 : return true;
628 : }
629 0 : i += 1;
630 : }
631 24 : Storage_ALLOCATE ((void **) &e, sizeof (M2CaseList__T2));
632 24 : e->a = r;
633 24 : e->b = s;
634 24 : Indexing_PutIndice (conflictArray, h+1, reinterpret_cast <void *> (e));
635 24 : return false;
636 : /* static analysis guarentees a RETURN statement will be used before here. */
637 : __builtin_unreachable ();
638 : }
639 :
640 :
641 : /*
642 : Overlaps -
643 : */
644 :
645 60016 : static bool Overlaps (M2CaseList_RangePair r, M2CaseList_RangePair s)
646 : {
647 60016 : unsigned int a;
648 60016 : unsigned int b;
649 60016 : unsigned int c;
650 60016 : unsigned int d;
651 :
652 60016 : a = r->low;
653 60016 : c = s->low;
654 60016 : if (r->high == SymbolTable_NulSym)
655 : {
656 : /* avoid dangling else. */
657 59512 : b = a;
658 59512 : if (s->high == SymbolTable_NulSym)
659 : {
660 : /* avoid dangling else. */
661 59176 : d = c;
662 59176 : if (M2Range_OverlapsRange (SymbolConversion_Mod2Gcc (a), SymbolConversion_Mod2Gcc (b), SymbolConversion_Mod2Gcc (c), SymbolConversion_Mod2Gcc (d)))
663 : {
664 24 : if (! (SeenBefore (r, s)))
665 : {
666 12 : M2MetaError_MetaErrorT2 (r->tokenno, (const char *) "case label {%1ad} is a duplicate with {%2ad}", 44, a, c);
667 12 : M2MetaError_MetaErrorT2 (s->tokenno, (const char *) "case label {%1ad} is a duplicate with {%2ad}", 44, c, a);
668 : }
669 24 : return true;
670 : }
671 : }
672 : else
673 : {
674 336 : d = s->high;
675 336 : if (M2Range_OverlapsRange (SymbolConversion_Mod2Gcc (a), SymbolConversion_Mod2Gcc (b), SymbolConversion_Mod2Gcc (c), SymbolConversion_Mod2Gcc (d)))
676 : {
677 6 : if (! (SeenBefore (r, s)))
678 : {
679 6 : M2MetaError_MetaErrorT3 (r->tokenno, (const char *) "case label {%1ad} is a duplicate in the range {%2ad}..{%3ad}", 60, a, c, d);
680 6 : M2MetaError_MetaErrorT3 (s->tokenno, (const char *) "case range {%2ad}..{%3ad} is a duplicate of case label {%1ad}", 61, c, d, a);
681 : }
682 6 : return true;
683 : }
684 : }
685 : }
686 : else
687 : {
688 504 : b = r->high;
689 504 : if (s->high == SymbolTable_NulSym)
690 : {
691 : /* avoid dangling else. */
692 336 : d = c;
693 336 : if (M2Range_OverlapsRange (SymbolConversion_Mod2Gcc (a), SymbolConversion_Mod2Gcc (b), SymbolConversion_Mod2Gcc (c), SymbolConversion_Mod2Gcc (d)))
694 : {
695 6 : if (! (SeenBefore (r, s)))
696 : {
697 0 : M2MetaError_MetaErrorT3 (r->tokenno, (const char *) "case range {%1ad}..{%2ad} is a duplicate with case label {%3ad}", 63, a, b, c);
698 0 : M2MetaError_MetaErrorT3 (s->tokenno, (const char *) "case label {%1ad} is a duplicate with case range %{2ad}..{%3ad}", 63, c, a, b);
699 : }
700 6 : return true;
701 : }
702 : }
703 : else
704 : {
705 168 : d = s->high;
706 168 : if (M2Range_OverlapsRange (SymbolConversion_Mod2Gcc (a), SymbolConversion_Mod2Gcc (b), SymbolConversion_Mod2Gcc (c), SymbolConversion_Mod2Gcc (d)))
707 : {
708 12 : if (! (SeenBefore (r, s)))
709 : {
710 6 : M2MetaError_MetaErrorT4 (r->tokenno, (const char *) "case range {%1ad}..{%2ad} overlaps case range {%3ad}..{%4ad}", 60, a, b, c, d);
711 6 : M2MetaError_MetaErrorT4 (s->tokenno, (const char *) "case range {%1ad}..{%2ad} overlaps case range {%3ad}..{%4ad}", 60, c, d, a, b);
712 : }
713 12 : return true;
714 : }
715 : }
716 : }
717 : return false;
718 : /* static analysis guarentees a RETURN statement will be used before here. */
719 : __builtin_unreachable ();
720 : }
721 :
722 :
723 : /*
724 : GetCaseExpression - return the type from the expression.
725 : */
726 :
727 156 : static unsigned int GetCaseExpression (M2CaseList_CaseDescriptor p)
728 : {
729 156 : unsigned int type;
730 :
731 156 : if (p->expression == SymbolTable_NulSym)
732 : {
733 : type = SymbolTable_NulSym;
734 : }
735 : else
736 : {
737 152 : type = SymbolTable_SkipType (SymbolTable_GetType (p->expression));
738 : }
739 156 : return type;
740 : /* static analysis guarentees a RETURN statement will be used before here. */
741 : __builtin_unreachable ();
742 : }
743 :
744 :
745 : /*
746 : OverlappingCaseBound - returns TRUE if, r, overlaps any case bound in the
747 : case statement, c.
748 : */
749 :
750 9758 : static bool OverlappingCaseBound (M2CaseList_RangePair r, unsigned int c)
751 : {
752 9758 : M2CaseList_CaseDescriptor p;
753 9758 : M2CaseList_CaseList q;
754 9758 : M2CaseList_RangePair s;
755 9758 : unsigned int i;
756 9758 : unsigned int j;
757 9758 : bool overlap;
758 :
759 9758 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
760 9758 : overlap = false;
761 9758 : i = 1;
762 88958 : while (i <= p->maxCaseId)
763 : {
764 69442 : q = static_cast<M2CaseList_CaseList> (Indexing_GetIndice (p->caseListArray, i));
765 69442 : j = 1;
766 208658 : while (j <= q->maxRangeId)
767 : {
768 69774 : s = static_cast<M2CaseList_RangePair> (Indexing_GetIndice (q->rangeArray, j));
769 69774 : if ((s != r) && (Overlaps (r, s)))
770 : {
771 : overlap = true;
772 : }
773 69774 : j += 1;
774 : }
775 69442 : i += 1;
776 : }
777 9758 : return overlap;
778 : /* static analysis guarentees a RETURN statement will be used before here. */
779 : __builtin_unreachable ();
780 : }
781 :
782 :
783 : /*
784 : NewRanges - return a new range from the freelist or heap.
785 : */
786 :
787 1318 : static M2CaseList_SetRange NewRanges (void)
788 : {
789 1318 : M2CaseList_SetRange s;
790 :
791 1318 : if (FreeRangeList == NULL)
792 : {
793 1290 : Storage_ALLOCATE ((void **) &s, sizeof (M2CaseList__T5));
794 : }
795 : else
796 : {
797 28 : s = FreeRangeList;
798 28 : FreeRangeList = FreeRangeList->next;
799 : }
800 1318 : s->next = NULL;
801 1318 : return s;
802 : /* static analysis guarentees a RETURN statement will be used before here. */
803 : __builtin_unreachable ();
804 : }
805 :
806 :
807 : /*
808 : NewSet - returns a new set based on type with the low and high fields assigned
809 : to the min and max values for the type.
810 : */
811 :
812 1282 : static M2CaseList_SetRange NewSet (unsigned int type)
813 : {
814 1282 : M2CaseList_SetRange s;
815 :
816 1282 : s = NewRanges ();
817 1282 : s->low = SymbolConversion_Mod2Gcc (M2GCCDeclare_GetTypeMin (type));
818 1282 : s->high = SymbolConversion_Mod2Gcc (M2GCCDeclare_GetTypeMax (type));
819 1282 : s->next = NULL;
820 1282 : return s;
821 : /* static analysis guarentees a RETURN statement will be used before here. */
822 : __builtin_unreachable ();
823 : }
824 :
825 :
826 : /*
827 : DisposeRanges - place set and its list onto the free list.
828 : */
829 :
830 2510 : static M2CaseList_SetRange DisposeRanges (M2CaseList_SetRange set)
831 : {
832 2510 : M2CaseList_SetRange t;
833 :
834 2510 : if (set != NULL)
835 : {
836 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
837 1288 : if (FreeRangeList == NULL)
838 : {
839 1282 : FreeRangeList = set;
840 : }
841 : else
842 : {
843 : t = set;
844 6 : while (t->next != NULL)
845 : {
846 : t = t->next;
847 : }
848 6 : t->next = FreeRangeList;
849 6 : FreeRangeList = set;
850 : }
851 : }
852 2510 : return NULL;
853 : /* static analysis guarentees a RETURN statement will be used before here. */
854 : __builtin_unreachable ();
855 : }
856 :
857 :
858 : /*
859 : RemoveRange - removes the range descriptor h from set and return the
860 : possibly new head of set.
861 : */
862 :
863 1228 : static M2CaseList_SetRange RemoveRange (M2CaseList_SetRange set, M2CaseList_SetRange h)
864 : {
865 1228 : M2CaseList_SetRange i;
866 :
867 1228 : if (h == set)
868 : {
869 1222 : set = set->next;
870 1222 : h->next = NULL;
871 1222 : h = DisposeRanges (h);
872 : }
873 : else
874 : {
875 : i = set;
876 6 : while (i->next != h)
877 : {
878 : i = i->next;
879 : }
880 6 : i->next = h->next;
881 6 : i = h;
882 6 : h = h->next;
883 6 : i->next = NULL;
884 6 : i = DisposeRanges (i);
885 : }
886 1228 : return set;
887 : /* static analysis guarentees a RETURN statement will be used before here. */
888 : __builtin_unreachable ();
889 : }
890 :
891 :
892 : /*
893 : SubBitRange - subtracts bits, lo..hi, from, set.
894 : */
895 :
896 2692 : static M2CaseList_SetRange SubBitRange (M2CaseList_SetRange set, tree lo, tree hi, unsigned int tokenno)
897 : {
898 2692 : M2CaseList_SetRange h;
899 2692 : M2CaseList_SetRange i;
900 :
901 2692 : h = set;
902 : /* Check to see if a single set element h is obliterated by lo..hi. */
903 6884 : while (h != NULL)
904 : {
905 4204 : if ((h->high == NULL) || (M2Range_IsEqual (h->high, h->low)))
906 : {
907 2474 : if ((M2Range_IsEqual (h->low, lo)) || (M2Range_OverlapsRange (lo, hi, h->low, h->low)))
908 : {
909 1216 : set = RemoveRange (set, h);
910 1216 : h = set;
911 : }
912 : else
913 : {
914 1258 : h = h->next;
915 : }
916 : /* Now check to see if the lo..hi match exactly with the set range. */
917 : }
918 1730 : else if (((h->high != NULL) && (M2Range_IsEqual (lo, h->low))) && (M2Range_IsEqual (hi, h->high)))
919 : {
920 : /* avoid dangling else. */
921 : /* Remove h and return as lo..hi have been removed. */
922 12 : return RemoveRange (set, h);
923 : }
924 : else
925 : {
926 : /* avoid dangling else. */
927 : /* All other cases require modifying the existing set range. */
928 1718 : if (M2Range_OverlapsRange (lo, hi, h->low, h->high))
929 : {
930 1458 : if ((M2Range_IsGreater (h->low, lo)) || (M2Range_IsGreater (hi, h->high)))
931 : {
932 0 : M2MetaError_MetaErrorT0 (tokenno, (const char *) "variant case range lies outside tag value", 41);
933 : }
934 : else
935 : {
936 1458 : if (M2Range_IsEqual (h->low, lo))
937 : {
938 1364 : M2ALU_PushIntegerTree (hi);
939 1364 : M2ALU_PushInt (1);
940 1364 : M2ALU_Addn ();
941 1364 : h->low = M2ALU_PopIntegerTree ();
942 : }
943 94 : else if (M2Range_IsEqual (h->high, hi))
944 : {
945 : /* avoid dangling else. */
946 58 : M2ALU_PushIntegerTree (lo);
947 58 : M2ALU_PushInt (1);
948 58 : M2ALU_Sub ();
949 58 : h->high = M2ALU_PopIntegerTree ();
950 : }
951 : else
952 : {
953 : /* avoid dangling else. */
954 : /* lo..hi exist inside range h^.low..h^.high */
955 36 : i = NewRanges ();
956 36 : i->next = h->next;
957 36 : h->next = i;
958 36 : i->high = h->high;
959 36 : M2ALU_PushIntegerTree (lo);
960 36 : M2ALU_PushInt (1);
961 36 : M2ALU_Sub ();
962 36 : h->high = M2ALU_PopIntegerTree ();
963 36 : M2ALU_PushIntegerTree (hi);
964 36 : M2ALU_PushInt (1);
965 36 : M2ALU_Addn ();
966 36 : i->low = M2ALU_PopIntegerTree ();
967 : }
968 : }
969 : }
970 : else
971 : {
972 260 : h = h->next;
973 : }
974 : }
975 : }
976 : return set;
977 : /* static analysis guarentees a RETURN statement will be used before here. */
978 : __builtin_unreachable ();
979 : }
980 :
981 :
982 : /*
983 : CheckLowHigh - checks to see the low value <= high value and issues an error
984 : if this is not true.
985 : */
986 :
987 66 : static void CheckLowHigh (M2CaseList_RangePair rp)
988 : {
989 66 : tree lo;
990 66 : tree hi;
991 66 : unsigned int temp;
992 :
993 66 : lo = SymbolConversion_Mod2Gcc (rp->low);
994 66 : hi = SymbolConversion_Mod2Gcc (rp->high);
995 66 : if (M2Range_IsGreater (lo, hi))
996 : {
997 0 : M2MetaError_MetaErrorT2 (rp->tokenno, (const char *) "case range should be low..high rather than high..low, range specified as {%1Euad}..{%2Euad}", 91, rp->low, rp->high);
998 0 : temp = rp->high;
999 0 : rp->high = rp->low;
1000 0 : rp->low = temp;
1001 : }
1002 66 : }
1003 :
1004 :
1005 : /*
1006 : ExcludeCaseRanges - excludes all case ranges found in, p, from, set
1007 : */
1008 :
1009 1282 : static M2CaseList_SetRange ExcludeCaseRanges (M2CaseList_SetRange set, M2CaseList_CaseDescriptor cd)
1010 : {
1011 1282 : unsigned int i;
1012 1282 : unsigned int j;
1013 1282 : M2CaseList_CaseList cl;
1014 1282 : M2CaseList_RangePair rp;
1015 :
1016 1282 : i = 1;
1017 3924 : while (i <= cd->maxCaseId)
1018 : {
1019 2642 : cl = static_cast<M2CaseList_CaseList> (Indexing_GetIndice (cd->caseListArray, i));
1020 2642 : j = 1;
1021 7976 : while (j <= cl->maxRangeId)
1022 : {
1023 2692 : rp = static_cast<M2CaseList_RangePair> (Indexing_GetIndice (cl->rangeArray, j));
1024 2692 : if (rp->high == SymbolTable_NulSym)
1025 : {
1026 2626 : set = SubBitRange (set, SymbolConversion_Mod2Gcc (rp->low), SymbolConversion_Mod2Gcc (rp->low), rp->tokenno);
1027 : }
1028 : else
1029 : {
1030 66 : CheckLowHigh (rp);
1031 66 : set = SubBitRange (set, SymbolConversion_Mod2Gcc (rp->low), SymbolConversion_Mod2Gcc (rp->high), rp->tokenno);
1032 : }
1033 2692 : j += 1;
1034 : }
1035 2642 : i += 1;
1036 : }
1037 1282 : return set;
1038 : /* static analysis guarentees a RETURN statement will be used before here. */
1039 : __builtin_unreachable ();
1040 : }
1041 :
1042 :
1043 : /*
1044 : IncludeElement - only include enumeration field into errorString if it lies between low..high.
1045 : */
1046 :
1047 18 : static void IncludeElement (Lists_List enumList, unsigned int field, tree low, tree high)
1048 : {
1049 18 : tree fieldTree;
1050 :
1051 18 : if (field != SymbolTable_NulSym)
1052 : {
1053 18 : fieldTree = SymbolConversion_Mod2Gcc (field);
1054 18 : if (M2Range_OverlapsRange (fieldTree, fieldTree, low, high))
1055 : {
1056 6 : Lists_IncludeItemIntoList (enumList, field);
1057 : }
1058 : }
1059 18 : }
1060 :
1061 :
1062 : /*
1063 : IncludeElements - only include enumeration field values low..high in errorString.
1064 : */
1065 :
1066 6 : static void IncludeElements (unsigned int type, Lists_List enumList, tree low, tree high)
1067 : {
1068 6 : unsigned int field;
1069 6 : unsigned int i;
1070 6 : unsigned int NoElements;
1071 :
1072 6 : NoElements = SymbolTable_NoOfElements (type);
1073 6 : i = 1;
1074 30 : while (i <= NoElements)
1075 : {
1076 18 : field = SymbolTable_GetNth (type, i);
1077 18 : IncludeElement (enumList, field, low, high);
1078 18 : i += 1;
1079 : }
1080 6 : }
1081 :
1082 :
1083 : /*
1084 : ErrorRangeEnum - include enumeration fields Low to High in errorString.
1085 : */
1086 :
1087 6 : static void ErrorRangeEnum (unsigned int type, M2CaseList_SetRange set, Lists_List enumList)
1088 : {
1089 6 : tree Low;
1090 6 : tree High;
1091 :
1092 6 : Low = set->low;
1093 6 : High = set->high;
1094 6 : if (Low == NULL)
1095 : {
1096 0 : Low = High;
1097 : }
1098 6 : if (High == NULL)
1099 : {
1100 0 : High = Low;
1101 : }
1102 6 : if ((Low != NULL) && (High != NULL))
1103 : {
1104 6 : IncludeElements (type, enumList, Low, High);
1105 : }
1106 6 : }
1107 :
1108 :
1109 : /*
1110 : ErrorRanges - return a list of all enumeration fields not present in the case statement.
1111 : The return value will be nil if type is not an enumeration type.
1112 : */
1113 :
1114 6 : static Lists_List ErrorRanges (unsigned int type, M2CaseList_SetRange set)
1115 : {
1116 6 : Lists_List enumSet;
1117 :
1118 6 : type = SymbolTable_SkipType (type);
1119 6 : if (SymbolTable_IsEnumeration (type))
1120 : {
1121 6 : Lists_InitList (&enumSet);
1122 18 : while (set != NULL)
1123 : {
1124 6 : ErrorRangeEnum (type, set, enumSet);
1125 6 : set = set->next;
1126 : }
1127 6 : return enumSet;
1128 : }
1129 : return static_cast<Lists_List> (NULL);
1130 : /* static analysis guarentees a RETURN statement will be used before here. */
1131 : __builtin_unreachable ();
1132 : }
1133 :
1134 :
1135 : /*
1136 : appendString - appends str to errorString.
1137 : */
1138 :
1139 450 : static void appendString (DynamicStrings_String str)
1140 : {
1141 450 : errorString = DynamicStrings_ConCat (errorString, str);
1142 450 : }
1143 :
1144 :
1145 : /*
1146 : appendEnum - appends enum to errorString.
1147 : */
1148 :
1149 6 : static void appendEnum (unsigned int enum_)
1150 : {
1151 6 : appendString (DynamicStrings_Mark (DynamicStrings_InitStringCharStar (NameKey_KeyToCharStar (SymbolTable_GetSymName (enum_)))));
1152 6 : }
1153 :
1154 :
1155 : /*
1156 : appendStr - appends str to errorString.
1157 : */
1158 :
1159 162 : static void appendStr (const char *str_, unsigned int _str_high)
1160 : {
1161 162 : char str[_str_high+1];
1162 :
1163 : /* make a local copy of each unbounded array. */
1164 162 : memcpy (str, str_, _str_high+1);
1165 :
1166 162 : appendString (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) str, _str_high)));
1167 162 : }
1168 :
1169 :
1170 : /*
1171 : EnumerateErrors - populate errorString with the contents of enumList.
1172 : */
1173 :
1174 6 : static void EnumerateErrors (Lists_List enumList)
1175 : {
1176 6 : unsigned int i;
1177 6 : unsigned int n;
1178 :
1179 6 : n = Lists_NoOfItemsInList (enumList);
1180 6 : if ((enumList != NULL) && (n > 0))
1181 : {
1182 6 : if (n == 1)
1183 : {
1184 6 : errorString = DynamicStrings_InitString ((const char *) "{%W}the missing enumeration field is: ", 38);
1185 : }
1186 : else
1187 : {
1188 0 : errorString = DynamicStrings_InitString ((const char *) "{%W}the missing enumeration fields are: ", 40);
1189 : }
1190 6 : appendEnum (Lists_GetItemFromList (enumList, 1));
1191 6 : if (n > 1)
1192 : {
1193 0 : if (n > 2)
1194 : {
1195 : i = 2;
1196 0 : while (i <= (n-1))
1197 : {
1198 0 : appendStr ((const char *) ", ", 2);
1199 0 : appendEnum (Lists_GetItemFromList (enumList, i));
1200 0 : i += 1;
1201 : }
1202 : }
1203 0 : appendStr ((const char *) " and ", 5);
1204 0 : appendEnum (Lists_GetItemFromList (enumList, n));
1205 : }
1206 : }
1207 6 : }
1208 :
1209 :
1210 : /*
1211 : NoOfSetElements - return the number of set elements.
1212 : */
1213 :
1214 42 : static tree NoOfSetElements (M2CaseList_SetRange set)
1215 : {
1216 42 : M2ALU_PushInt (0);
1217 156 : while (set != NULL)
1218 : {
1219 72 : if (((set->low != NULL) && (set->high == NULL)) || ((set->low == NULL) && (set->high != NULL)))
1220 : {
1221 0 : M2ALU_PushInt (1);
1222 0 : M2ALU_Addn ();
1223 : }
1224 72 : else if ((set->low != NULL) && (set->high != NULL))
1225 : {
1226 : /* avoid dangling else. */
1227 72 : M2ALU_PushIntegerTree (set->high);
1228 72 : M2ALU_PushIntegerTree (set->low);
1229 72 : M2ALU_Sub ();
1230 72 : M2ALU_PushInt (1);
1231 72 : M2ALU_Addn ();
1232 72 : M2ALU_Addn ();
1233 : }
1234 72 : set = set->next;
1235 : }
1236 42 : return M2ALU_PopIntegerTree ();
1237 : /* static analysis guarentees a RETURN statement will be used before here. */
1238 : __builtin_unreachable ();
1239 : }
1240 :
1241 :
1242 : /*
1243 : isPrintableChar - a cautious isprint.
1244 : */
1245 :
1246 60 : static bool isPrintableChar (tree value)
1247 : {
1248 60 : if (((m2expr_CSTIntToChar (value)) >= 'a') && ((m2expr_CSTIntToChar (value)) <= 'z'))
1249 : {
1250 : return true;
1251 : }
1252 18 : else if (((m2expr_CSTIntToChar (value)) >= 'A') && ((m2expr_CSTIntToChar (value)) <= 'Z'))
1253 : {
1254 : return true;
1255 : }
1256 18 : else if (((m2expr_CSTIntToChar (value)) >= '0') && ((m2expr_CSTIntToChar (value)) <= '9'))
1257 : {
1258 : return true;
1259 : }
1260 18 : else if (((m2expr_CSTIntToChar (value)) == '!') || ((m2expr_CSTIntToChar (value)) == '@'))
1261 : {
1262 0 : return true;
1263 : }
1264 18 : else if (((m2expr_CSTIntToChar (value)) == '#') || ((m2expr_CSTIntToChar (value)) == '$'))
1265 : {
1266 0 : return true;
1267 : }
1268 18 : else if (((m2expr_CSTIntToChar (value)) == '%') || ((m2expr_CSTIntToChar (value)) == '^'))
1269 : {
1270 0 : return true;
1271 : }
1272 18 : else if (((m2expr_CSTIntToChar (value)) == '&') || ((m2expr_CSTIntToChar (value)) == '*'))
1273 : {
1274 0 : return true;
1275 : }
1276 18 : else if (((m2expr_CSTIntToChar (value)) == '(') || ((m2expr_CSTIntToChar (value)) == ')'))
1277 : {
1278 0 : return true;
1279 : }
1280 18 : else if (((m2expr_CSTIntToChar (value)) == '[') || ((m2expr_CSTIntToChar (value)) == ']'))
1281 : {
1282 0 : return true;
1283 : }
1284 18 : else if (((m2expr_CSTIntToChar (value)) == '{') || ((m2expr_CSTIntToChar (value)) == '}'))
1285 : {
1286 0 : return true;
1287 : }
1288 18 : else if (((m2expr_CSTIntToChar (value)) == '-') || ((m2expr_CSTIntToChar (value)) == '+'))
1289 : {
1290 0 : return true;
1291 : }
1292 18 : else if (((m2expr_CSTIntToChar (value)) == '_') || ((m2expr_CSTIntToChar (value)) == '='))
1293 : {
1294 0 : return true;
1295 : }
1296 18 : else if (((m2expr_CSTIntToChar (value)) == ':') || ((m2expr_CSTIntToChar (value)) == ';'))
1297 : {
1298 0 : return true;
1299 : }
1300 18 : else if (((m2expr_CSTIntToChar (value)) == '\'') || ((m2expr_CSTIntToChar (value)) == '"'))
1301 : {
1302 0 : return true;
1303 : }
1304 18 : else if (((m2expr_CSTIntToChar (value)) == ',') || ((m2expr_CSTIntToChar (value)) == '.'))
1305 : {
1306 0 : return true;
1307 : }
1308 18 : else if (((m2expr_CSTIntToChar (value)) == '<') || ((m2expr_CSTIntToChar (value)) == '>'))
1309 : {
1310 0 : return true;
1311 : }
1312 18 : else if (((m2expr_CSTIntToChar (value)) == '/') || ((m2expr_CSTIntToChar (value)) == '?'))
1313 : {
1314 0 : return true;
1315 : }
1316 18 : else if (((m2expr_CSTIntToChar (value)) == '\\') || ((m2expr_CSTIntToChar (value)) == '|'))
1317 : {
1318 0 : return true;
1319 : }
1320 18 : else if (((m2expr_CSTIntToChar (value)) == '~') || ((m2expr_CSTIntToChar (value)) == '`'))
1321 : {
1322 6 : return true;
1323 : }
1324 12 : else if (((m2expr_CSTIntToChar (value)) == ' '))
1325 : {
1326 : return true;
1327 : }
1328 :
1329 : else {
1330 : return false;
1331 : }
1332 : /* static analysis guarentees a RETURN statement will be used before here. */
1333 : __builtin_unreachable ();
1334 : }
1335 :
1336 :
1337 : /*
1338 : appendTree - append tree value to the errorString. It attempts to pretty print
1339 : CHAR constants and will fall back to CHR (x) if necessary.
1340 : */
1341 :
1342 120 : static void appendTree (tree value, unsigned int type)
1343 : {
1344 120 : if ((SymbolTable_SkipType (SymbolTable_GetType (type))) == M2Base_Char)
1345 : {
1346 60 : if (isPrintableChar (value))
1347 : {
1348 48 : if ((m2expr_CSTIntToChar (value)) == '\'')
1349 : {
1350 0 : appendString (DynamicStrings_InitStringChar ('"'));
1351 0 : appendString (DynamicStrings_InitStringChar (m2expr_CSTIntToChar (value)));
1352 0 : appendString (DynamicStrings_InitStringChar ('"'));
1353 : }
1354 : else
1355 : {
1356 48 : appendString (DynamicStrings_InitStringChar ('\''));
1357 48 : appendString (DynamicStrings_InitStringChar (m2expr_CSTIntToChar (value)));
1358 48 : appendString (DynamicStrings_InitStringChar ('\''));
1359 : }
1360 : }
1361 : else
1362 : {
1363 12 : appendString (DynamicStrings_InitString ((const char *) "CHR (", 5));
1364 12 : appendString (DynamicStrings_InitStringCharStar (reinterpret_cast <void *> (m2expr_CSTIntToString (value))));
1365 12 : appendString (DynamicStrings_InitStringChar (')'));
1366 : }
1367 : }
1368 : else
1369 : {
1370 60 : appendString (DynamicStrings_InitStringCharStar (reinterpret_cast <void *> (m2expr_CSTIntToString (value))));
1371 : }
1372 120 : }
1373 :
1374 :
1375 : /*
1376 : SubrangeErrors - create an errorString containing all set ranges.
1377 : */
1378 :
1379 42 : static void SubrangeErrors (unsigned int subrangetype, M2CaseList_SetRange set)
1380 : {
1381 42 : M2CaseList_SetRange sr;
1382 42 : unsigned int rangeNo;
1383 42 : tree nMissing;
1384 42 : tree zero;
1385 42 : tree one;
1386 :
1387 42 : nMissing = NoOfSetElements (set);
1388 42 : M2ALU_PushInt (0);
1389 42 : zero = M2ALU_PopIntegerTree ();
1390 42 : if (M2Range_IsGreater (nMissing, zero))
1391 : {
1392 42 : M2ALU_PushInt (1);
1393 42 : one = M2ALU_PopIntegerTree ();
1394 42 : if (M2Range_IsGreater (nMissing, one))
1395 : {
1396 30 : errorString = DynamicStrings_InitString ((const char *) "{%W}there are a total of ", 25);
1397 : }
1398 : else
1399 : {
1400 12 : errorString = DynamicStrings_InitString ((const char *) "{%W}there is a total of ", 24);
1401 : }
1402 42 : appendString (DynamicStrings_InitStringCharStar (reinterpret_cast <void *> (m2expr_CSTIntToString (nMissing))));
1403 42 : appendStr ((const char *) " missing values in the subrange, the {%kCASE} statement needs labels (or an {%kELSE} statement)", 95);
1404 42 : appendStr ((const char *) " for the following values: ", 27);
1405 42 : sr = set;
1406 42 : rangeNo = 0;
1407 156 : while (sr != NULL)
1408 : {
1409 72 : rangeNo += 1;
1410 72 : if (rangeNo > 1)
1411 : {
1412 : /* avoid gcc warning by using compound statement even if not strictly necessary. */
1413 30 : if (sr->next == NULL)
1414 : {
1415 24 : appendStr ((const char *) " and ", 5);
1416 : }
1417 : else
1418 : {
1419 6 : appendStr ((const char *) ", ", 2);
1420 : }
1421 : }
1422 72 : if (sr->low == NULL)
1423 : {
1424 0 : appendTree (sr->high, subrangetype);
1425 : }
1426 72 : else if ((sr->high == NULL) || (M2Range_IsEqual (sr->low, sr->high)))
1427 : {
1428 : /* avoid dangling else. */
1429 24 : appendTree (sr->low, subrangetype);
1430 : }
1431 : else
1432 : {
1433 : /* avoid dangling else. */
1434 48 : appendTree (sr->low, subrangetype);
1435 48 : appendStr ((const char *) "..", 2);
1436 48 : appendTree (sr->high, subrangetype);
1437 : }
1438 72 : sr = sr->next;
1439 : }
1440 : }
1441 42 : }
1442 :
1443 :
1444 : /*
1445 : EmitMissingRangeErrors - emits a singular/plural error message for an enumeration type.
1446 : */
1447 :
1448 60 : static void EmitMissingRangeErrors (unsigned int tokenno, unsigned int type, M2CaseList_SetRange set)
1449 : {
1450 60 : errorString = static_cast<DynamicStrings_String> (NULL);
1451 60 : if (SymbolTable_IsEnumeration (type))
1452 : {
1453 6 : EnumerateErrors (ErrorRanges (type, set));
1454 : }
1455 54 : else if (SymbolTable_IsSubrange (type))
1456 : {
1457 : /* avoid dangling else. */
1458 42 : SubrangeErrors (type, set);
1459 : }
1460 60 : if (errorString != NULL)
1461 : {
1462 48 : M2MetaError_MetaErrorStringT0 (tokenno, errorString);
1463 : }
1464 60 : }
1465 :
1466 :
1467 : /*
1468 : checkTypes - checks to see that, constant, and, type, are compatible.
1469 : */
1470 :
1471 12036 : static bool checkTypes (unsigned int constant, unsigned int type)
1472 : {
1473 12036 : unsigned int consttype;
1474 :
1475 12036 : if ((constant != SymbolTable_NulSym) && (SymbolTable_IsConst (constant)))
1476 : {
1477 6018 : consttype = SymbolTable_GetType (constant);
1478 6018 : if (! (M2Base_IsExpressionCompatible (consttype, type)))
1479 : {
1480 0 : M2MetaError_MetaError2 ((const char *) "the case statement variant tag {%1ad} must be type compatible with the constant {%2Da:is a {%2dv}}", 98, type, constant);
1481 0 : return false;
1482 : }
1483 : }
1484 : return true;
1485 : /* static analysis guarentees a RETURN statement will be used before here. */
1486 : __builtin_unreachable ();
1487 : }
1488 :
1489 :
1490 : /*
1491 : inRange - returns true if, min <= i <= max.
1492 : */
1493 :
1494 6018 : static bool inRange (unsigned int i, unsigned int min, unsigned int max)
1495 : {
1496 6018 : return M2Range_OverlapsRange (SymbolConversion_Mod2Gcc (i), SymbolConversion_Mod2Gcc (i), SymbolConversion_Mod2Gcc (min), SymbolConversion_Mod2Gcc (max));
1497 : /* static analysis guarentees a RETURN statement will be used before here. */
1498 : __builtin_unreachable ();
1499 : }
1500 :
1501 :
1502 : /*
1503 : PushCase - create a case entity and push it to an internal stack.
1504 : rec is NulSym if this is a CASE statement.
1505 : If rec is a record then it indicates a possible
1506 : varients reside in the record to check.
1507 : Both rec and va might be NulSym and then the expr
1508 : will contain the selector expression to a case statement.
1509 : Return the case id.
1510 : */
1511 :
1512 3964 : extern "C" unsigned int M2CaseList_PushCase (unsigned int rec, unsigned int va, unsigned int expr)
1513 : {
1514 3964 : M2CaseList_CaseDescriptor c;
1515 :
1516 3964 : caseId += 1;
1517 3964 : Storage_ALLOCATE ((void **) &c, sizeof (M2CaseList__T4));
1518 3964 : if (c == NULL)
1519 : {
1520 0 : M2Error_InternalError ((const char *) "out of memory error", 19);
1521 : }
1522 : else
1523 : {
1524 3964 : c->resolved = false;
1525 3964 : c->elseClause = false;
1526 3964 : c->elseField = SymbolTable_NulSym;
1527 3964 : c->record = rec;
1528 3964 : c->varient = va;
1529 3964 : c->expression = expr;
1530 3964 : c->maxCaseId = 0;
1531 3964 : c->caseListArray = Indexing_InitIndex (1);
1532 3964 : c->next = caseStack;
1533 3964 : c->currentCase = NULL;
1534 3964 : caseStack = c;
1535 3964 : Indexing_PutIndice (caseArray, caseId, reinterpret_cast <void *> (c));
1536 : }
1537 3964 : return caseId;
1538 : /* static analysis guarentees a RETURN statement will be used before here. */
1539 : __builtin_unreachable ();
1540 : }
1541 :
1542 :
1543 : /*
1544 : PopCase - pop the top element of the case entity from the internal
1545 : stack.
1546 : */
1547 :
1548 3964 : extern "C" void M2CaseList_PopCase (void)
1549 : {
1550 3964 : if (caseStack == NULL)
1551 : {
1552 0 : M2Error_InternalError ((const char *) "case stack is empty", 19);
1553 : }
1554 3964 : caseStack = caseStack->next;
1555 3964 : }
1556 :
1557 :
1558 : /*
1559 : ElseCase - indicates that this case varient does have an else clause.
1560 : */
1561 :
1562 602 : extern "C" void M2CaseList_ElseCase (unsigned int f)
1563 : {
1564 602 : caseStack->elseClause = true;
1565 602 : caseStack->elseField = f;
1566 602 : }
1567 :
1568 :
1569 : /*
1570 : BeginCaseList - create a new label list.
1571 : */
1572 :
1573 9666 : extern "C" void M2CaseList_BeginCaseList (unsigned int v)
1574 : {
1575 9666 : M2CaseList_CaseList l;
1576 :
1577 9666 : Storage_ALLOCATE ((void **) &l, sizeof (M2CaseList__T3));
1578 9666 : if (l == NULL)
1579 : {
1580 0 : M2Error_InternalError ((const char *) "out of memory error", 19);
1581 : }
1582 9666 : l->maxRangeId = 0;
1583 9666 : l->rangeArray = Indexing_InitIndex (1);
1584 9666 : l->currentRange = NULL;
1585 9666 : l->varientField = v;
1586 9666 : caseStack->maxCaseId += 1;
1587 9666 : Indexing_PutIndice (caseStack->caseListArray, caseStack->maxCaseId, reinterpret_cast <void *> (l));
1588 9666 : caseStack->currentCase = l;
1589 9666 : }
1590 :
1591 :
1592 : /*
1593 : EndCaseList - terminate the current label list.
1594 : */
1595 :
1596 9666 : extern "C" void M2CaseList_EndCaseList (void)
1597 : {
1598 9666 : caseStack->currentCase = NULL;
1599 9666 : }
1600 :
1601 :
1602 : /*
1603 : AddRange - add a range to the current label list.
1604 : */
1605 :
1606 9758 : extern "C" void M2CaseList_AddRange (unsigned int r1, unsigned int r2, unsigned int tok)
1607 : {
1608 9758 : M2CaseList_RangePair r;
1609 :
1610 9758 : Storage_ALLOCATE ((void **) &r, sizeof (M2CaseList__T1));
1611 9758 : if (r == NULL)
1612 : {
1613 0 : M2Error_InternalError ((const char *) "out of memory error", 19);
1614 : }
1615 : else
1616 : {
1617 9758 : r->low = r1;
1618 9758 : r->high = r2;
1619 9758 : r->tokenno = tok;
1620 9758 : caseStack->currentCase->maxRangeId += 1;
1621 9758 : Indexing_PutIndice (caseStack->currentCase->rangeArray, caseStack->currentCase->maxRangeId, reinterpret_cast <void *> (r));
1622 9758 : caseStack->currentCase->currentRange = r;
1623 : }
1624 9758 : }
1625 :
1626 :
1627 : /*
1628 : CaseBoundsResolved - returns TRUE if all constants in the case list, c,
1629 : are known to GCC.
1630 : */
1631 :
1632 9676 : extern "C" bool M2CaseList_CaseBoundsResolved (unsigned int tokenno, unsigned int c)
1633 : {
1634 9676 : M2CaseList_CaseDescriptor p;
1635 :
1636 9676 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
1637 9676 : if (p->resolved)
1638 : {
1639 : return true;
1640 : }
1641 : else
1642 : {
1643 9676 : if (CheckCaseBoundsResolved (tokenno, c))
1644 : {
1645 3964 : ConvertNulStr2NulChar (tokenno, c);
1646 3964 : return true;
1647 : }
1648 : else
1649 : {
1650 : return false;
1651 : }
1652 : }
1653 : /* static analysis guarentees a RETURN statement will be used before here. */
1654 : __builtin_unreachable ();
1655 : }
1656 :
1657 :
1658 : /*
1659 : TypeCaseBounds - returns true if all bounds in case list, c, are
1660 : compatible with the tagged type.
1661 : */
1662 :
1663 3964 : extern "C" bool M2CaseList_TypeCaseBounds (unsigned int c)
1664 : {
1665 3964 : M2CaseList_CaseDescriptor p;
1666 3964 : M2CaseList_CaseList q;
1667 3964 : M2CaseList_RangePair r;
1668 3964 : unsigned int min;
1669 3964 : unsigned int max;
1670 3964 : unsigned int type;
1671 3964 : unsigned int i;
1672 3964 : unsigned int j;
1673 3964 : bool compatible;
1674 :
1675 3964 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
1676 3964 : type = SymbolTable_NulSym;
1677 3964 : type = SymbolTable_NulSym;
1678 3964 : if (p->varient != SymbolTable_NulSym)
1679 : {
1680 : /* not a CASE statement, but a varient record containing without an ELSE clause */
1681 2988 : type = GetVariantTagType (p->varient);
1682 2988 : min = M2GCCDeclare_GetTypeMin (type);
1683 2988 : max = M2GCCDeclare_GetTypeMax (type);
1684 : }
1685 2988 : if (type == SymbolTable_NulSym)
1686 : {
1687 976 : return true;
1688 : }
1689 : compatible = true;
1690 : i = 1;
1691 8964 : while (i <= p->maxCaseId)
1692 : {
1693 5976 : q = static_cast<M2CaseList_CaseList> (Indexing_GetIndice (p->caseListArray, i));
1694 5976 : j = 1;
1695 17970 : while (j <= q->maxRangeId)
1696 : {
1697 6018 : r = static_cast<M2CaseList_RangePair> (Indexing_GetIndice (q->rangeArray, j));
1698 6018 : if ((r->low != SymbolTable_NulSym) && (! (inRange (r->low, min, max))))
1699 : {
1700 0 : M2MetaError_MetaError2 ((const char *) "the CASE statement variant range {%1ad} exceeds that of the tag type {%2ad}", 75, r->low, type);
1701 0 : compatible = false;
1702 : }
1703 6018 : if (! (checkTypes (r->low, type)))
1704 : {
1705 0 : compatible = false;
1706 : }
1707 6018 : if ((r->high != SymbolTable_NulSym) && (! (inRange (r->high, min, max))))
1708 : {
1709 0 : M2MetaError_MetaError2 ((const char *) "the CASE statement variant range {%1ad} exceeds that of the tag type {%2ad}", 75, r->high, type);
1710 0 : compatible = false;
1711 : }
1712 6018 : if (! (checkTypes (r->high, type)))
1713 : {
1714 0 : compatible = false;
1715 : }
1716 6018 : j += 1;
1717 : }
1718 5976 : i += 1;
1719 : }
1720 : return compatible;
1721 : /* static analysis guarentees a RETURN statement will be used before here. */
1722 : __builtin_unreachable ();
1723 : }
1724 :
1725 :
1726 : /*
1727 : OverlappingCaseBounds - returns TRUE if there were any overlapping bounds
1728 : in the case list, c. It will generate an error
1729 : messages for each overlapping bound found.
1730 : */
1731 :
1732 3964 : extern "C" bool M2CaseList_OverlappingCaseBounds (unsigned int c)
1733 : {
1734 3964 : M2CaseList_CaseDescriptor p;
1735 3964 : M2CaseList_CaseList q;
1736 3964 : M2CaseList_RangePair r;
1737 3964 : unsigned int i;
1738 3964 : unsigned int j;
1739 3964 : bool overlap;
1740 :
1741 3964 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
1742 3964 : overlap = false;
1743 3964 : i = 1;
1744 17594 : while (i <= p->maxCaseId)
1745 : {
1746 9666 : q = static_cast<M2CaseList_CaseList> (Indexing_GetIndice (p->caseListArray, i));
1747 9666 : j = 1;
1748 29090 : while (j <= q->maxRangeId)
1749 : {
1750 9758 : r = static_cast<M2CaseList_RangePair> (Indexing_GetIndice (q->rangeArray, j));
1751 9758 : if (OverlappingCaseBound (r, c))
1752 : {
1753 48 : overlap = true;
1754 : }
1755 9758 : j += 1;
1756 : }
1757 9666 : i += 1;
1758 : }
1759 3964 : return overlap;
1760 : /* static analysis guarentees a RETURN statement will be used before here. */
1761 : __builtin_unreachable ();
1762 : }
1763 :
1764 :
1765 : /*
1766 : MissingCaseBounds - returns true if there were any missing bounds
1767 : in the varient record case list, c. It will
1768 : generate an error message for each missing
1769 : bounds found.
1770 : */
1771 :
1772 1496 : extern "C" bool M2CaseList_MissingCaseBounds (unsigned int tokenno, unsigned int c)
1773 : {
1774 1496 : M2CaseList_CaseDescriptor p;
1775 1496 : unsigned int type;
1776 1496 : bool missing;
1777 1496 : M2CaseList_SetRange set;
1778 :
1779 1496 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
1780 1496 : missing = false;
1781 1496 : if (! p->elseClause)
1782 : {
1783 1394 : if ((p->record != SymbolTable_NulSym) && (p->varient != SymbolTable_NulSym))
1784 : {
1785 : /* Not a case statement, but a varient record without an else clause. */
1786 1146 : type = GetVariantTagType (p->varient);
1787 1146 : set = NewSet (type);
1788 1146 : set = ExcludeCaseRanges (set, p);
1789 1146 : if (set != NULL)
1790 : {
1791 12 : missing = true;
1792 12 : M2MetaError_MetaErrorT2 (tokenno, (const char *) "not all variant record alternatives in the {%kCASE} clause are specified, hint you either need to specify each value of {%2ad} or use an {%kELSE} clause", 152, p->varient, type);
1793 12 : EmitMissingRangeErrors (tokenno, type, set);
1794 : }
1795 1146 : set = DisposeRanges (set);
1796 : }
1797 : }
1798 1496 : return missing;
1799 : /* static analysis guarentees a RETURN statement will be used before here. */
1800 : __builtin_unreachable ();
1801 : }
1802 :
1803 :
1804 : /*
1805 : MissingCaseStatementBounds - returns true if the case statement has a missing
1806 : clause. It will also generate error messages.
1807 : */
1808 :
1809 212 : extern "C" bool M2CaseList_MissingCaseStatementBounds (unsigned int tokenno, unsigned int c)
1810 : {
1811 212 : M2CaseList_CaseDescriptor p;
1812 212 : unsigned int type;
1813 212 : bool missing;
1814 212 : M2CaseList_SetRange set;
1815 :
1816 212 : p = static_cast<M2CaseList_CaseDescriptor> (Indexing_GetIndice (caseArray, c));
1817 212 : missing = false;
1818 212 : if (! p->elseClause)
1819 : {
1820 156 : type = GetCaseExpression (p);
1821 156 : if (type != SymbolTable_NulSym)
1822 : {
1823 152 : if ((SymbolTable_IsEnumeration (type)) || (SymbolTable_IsSubrange (type)))
1824 : {
1825 : /* A case statement sequence without an else clause but
1826 : selecting using an enumeration type. */
1827 136 : set = NewSet (type);
1828 136 : set = ExcludeCaseRanges (set, p);
1829 136 : if (set != NULL)
1830 : {
1831 48 : missing = true;
1832 48 : M2MetaError_MetaErrorT1 (tokenno, (const char *) "not all {%1Wd} values in the {%kCASE} statements are specified, hint you either need to specify each value of {%1ad} or use an {%kELSE} clause", 142, type);
1833 48 : EmitMissingRangeErrors (tokenno, type, set);
1834 : }
1835 136 : set = DisposeRanges (set);
1836 : }
1837 : }
1838 : }
1839 212 : return missing;
1840 : /* static analysis guarentees a RETURN statement will be used before here. */
1841 : __builtin_unreachable ();
1842 : }
1843 :
1844 :
1845 : /*
1846 : WriteCase - dump out the case list (internal debugging).
1847 : */
1848 :
1849 0 : extern "C" void M2CaseList_WriteCase (unsigned int c)
1850 : {
1851 : /* this debugging PROCEDURE should be finished. */
1852 0 : NumberIO_WriteCard (c, 0);
1853 0 : }
1854 :
1855 14952 : extern "C" void _M2_M2CaseList_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
1856 : {
1857 14952 : caseStack = NULL;
1858 14952 : caseId = 0;
1859 14952 : caseArray = Indexing_InitIndex (1);
1860 14952 : conflictArray = Indexing_InitIndex (1);
1861 14952 : FreeRangeList = NULL;
1862 14952 : }
1863 :
1864 0 : extern "C" void _M2_M2CaseList_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
1865 : {
1866 0 : }
|