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