/***************************************************************************** * * casesin takes a list of selections 'tptr' and returns the number of * distinct selections (including an ELSE if one present). * *****************************************************************************/ PRIVATE int casesin (treenode * tptr) { int n = 0; for (; !EndOfList (tptr); tptr = NextItem (tptr)) { treenode *thisguard = CondGuardOf (skipspecifications (ThisItem (tptr))); if (TagOf (thisguard) == S_ELSE) n++; else n += listitems (thisguard); } return (n); }
Item *ConcatLists(Item *list1, Item *list2) /* Notes: * Refrain from freeing list2 after using ConcatLists * list1 must have at least one element in it */ { if (list1 == NULL) { ProgrammingError("ConcatLists: first argument must have at least one element"); } Item *tail = EndOfList(list1); assert(tail != CF_UNDEFINED_ITEM); assert(tail->next == NULL); /* If any entry in list1 is in list2, so is tail; so this is a * sufficient check that we're not creating a loop: */ assert(!ItemIsInList(list2, tail)); tail->next = list2; return list1; }
void AppendItem(Item **liststart, const char *itemstring, const char *classes) { Item *ip = xcalloc(1, sizeof(Item)); ip->name = xstrdup(itemstring); if (classes) { ip->classes = xstrdup(classes); /* unused now */ } if (*liststart == NULL) { *liststart = ip; } else { Item *lp = EndOfList(*liststart); assert(lp != CF_UNDEFINED_ITEM); lp->next = ip; } }
/***************************************************************************** * * tcase generates code for a case process tptr * *****************************************************************************/ PUBLIC void tcase (treenode * tptr) { /*{{{ save globals */ caseentry *const oldcasetable = casetable; const int olddefaultlab = defaultlab; const int olddefaultjumpdest = defaultjumpdest; const int oldselectortype = selectortype; treenode *const oldselectorexp = selectorexp; /*}}} */ BOOL makedefault = TRUE; treenode *selectionlist = RHSOf (tptr); const int joinlab = newlab (); int maxcase = 0; treenode *defaultp = NULL; /*{{{ initialise globals */ defaultlab = NO_LABEL; defaultjumpdest = FALSE; selectorexp = LHSOf (tptr); selectortype = ntypeof (selectorexp); /* make sure that we don't call memalloc with zero bytes */ casetable = (caseentry *) memalloc (sizeof (caseentry) * casesin (selectionlist) + 1); /*}}} */ /*{{{ evaluate the selector, if neccessary */ tpreexp (selectorexp); simplify (P_EXP, selectorexp); /*}}} */ /*{{{ build up table of selections, and generate jumps into case body */ { treenode *slist; for (slist = selectionlist; !EndOfList (slist); slist = NextItem (slist)) { treenode *thisselection = skipspecifications (ThisItem (slist)); treenode *v = CondGuardOf (thisselection); const int l = newlab (); if (TagOf (v) == S_ELSE) { defaultlab = l; defaultp = ThisItem (slist); makedefault = FALSE; } else /*{{{ set up labels and values */ for (; !EndOfList (v); v = NextItem (v)) { treenode *thisconstant = ThisItem (v); caseentry *caseentryptr = &(casetable[maxcase]); caseentryptr->label = l; caseentryptr->jumpdest = FALSE; caseentryptr->lowvalue = LoValOf (thisconstant); caseentryptr->highvalue = HiValOf (thisconstant); caseentryptr->selectionexp = thisconstant; caseentryptr->selectionp = ThisItem (slist); maxcase++; } /*}}} */ } if (makedefault) defaultlab = newlab (); #if 0 sup_qsort (casetable, maxcase, sizeof (caseentry), fitsinword (selectortype) ? comparecases : doublecomparecases); #else sup_qsort (casetable, maxcase, sizeof (caseentry), (bytesinscalar (selectortype) <= 4) ? comparecases : doublecomparecases); #endif tjumptable (0, maxcase - 1, FALSE); } /*}}} */ /*{{{ generate case body */ { int casesdone = 0; /*{{{ generate default process */ setlab (defaultlab); if (makedefault) { if (NEED_ERRORS) /* bug TS/2071 29/01/93 */ tstop (tptr); } else { if (defaultjumpdest) genstartblock (); tselection (defaultp, joinlab); } /*}}} */ while (casesdone < maxcase) { treenode *thisprocess; int i; BOOL jdest; /* Find a process to generate */ for (i = 0; (i < maxcase) && (casetable[i].selectionp == NULL); i++) /* skip */ ; thisprocess = casetable[i].selectionp; /* Generate thisprocess */ setlab (casetable[i].label); jdest = casetable[i].jumpdest; /*{{{ find and delete other entries for this process */ { int j; for (j = i + 1; j < maxcase; j++) if (casetable[j].selectionp == thisprocess) { /* Delete the process, so we only generate it once */ jdest = jdest | casetable[j].jumpdest; casetable[j].selectionp = NULL; casesdone++; } } /*}}} */ if (jdest) genstartblock (); tselection (thisprocess, joinlab); casetable[i].selectionp = NULL; casesdone++; } setlab (joinlab); genstartblock (); } /*}}} */ /*{{{ restore globals */ memfree (casetable); casetable = oldcasetable; defaultlab = olddefaultlab; defaultjumpdest = olddefaultjumpdest; selectortype = oldselectortype; selectorexp = oldselectorexp; /*}}} */ }