+static void
+reassociate_ic_down (lineNode *shead, lineNode *stail,
+ lineNode *rhead, lineNode *rtail)
+{
+ lineNode *csl; /* current source line */
+ lineNode *crl; /* current replacement line */
+
+ csl = shead;
+ crl = rhead;
+ while (1)
+ {
+ /* skip over any comments */
+ while (csl!=stail->next && csl->isComment)
+ csl = csl->next;
+ while (crl!=rtail->next && crl->isComment)
+ crl = crl->next;
+
+ /* quit if we reach the end */
+ if ((csl==stail->next) || (crl==rtail->next) || crl->ic)
+ break;
+
+ if (matchLine(csl->line,crl->line,NULL))
+ {
+ crl->ic = csl->ic;
+ csl = csl->next;
+ crl = crl->next;
+ }
+ else
+ break;
+ }
+}
+
+static void
+reassociate_ic_up (lineNode *shead, lineNode *stail,
+ lineNode *rhead, lineNode *rtail)
+{
+ lineNode *csl; /* current source line */
+ lineNode *crl; /* current replacement line */
+
+ csl = stail;
+ crl = rtail;
+ while (1)
+ {
+ /* skip over any comments */
+ while (csl!=shead->prev && csl->isComment)
+ csl = csl->prev;
+ while (crl!=rhead->prev && crl->isComment)
+ crl = crl->prev;
+
+ /* quit if we reach the end */
+ if ((csl==shead->prev) || (crl==rhead->prev) || crl->ic)
+ break;
+
+ if (matchLine(csl->line,crl->line,NULL))
+ {
+ crl->ic = csl->ic;
+ csl = csl->prev;
+ crl = crl->prev;
+ }
+ else
+ break;
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* reassociate_ic - reassociate replacement lines with origin iCode */
+/*------------------------------------------------------------------*/
+static void
+reassociate_ic (lineNode *shead, lineNode *stail,
+ lineNode *rhead, lineNode *rtail)
+{
+ lineNode *csl; /* current source line */
+ lineNode *crl; /* current replacement line */
+ bool single_iCode;
+ iCode *ic;
+
+ /* Check to see if all the source lines (excluding comments) came
+ ** for the same iCode
+ */
+ ic = NULL;
+ for (csl=shead;csl!=stail->next;csl=csl->next)
+ if (csl->ic && !csl->isComment)
+ {
+ ic = csl->ic;
+ break;
+ }
+ single_iCode = (ic!=NULL);
+ for (csl=shead;csl!=stail->next;csl=csl->next)
+ if ((csl->ic != ic) && !csl->isComment)
+ {
+ /* More than one iCode was found. However, if it's just the
+ ** last line with the different iCode and it was not changed
+ ** in the replacement, everything else must be the first iCode.
+ */
+ if ((csl==stail) && matchLine (stail->line, rtail->line, NULL))
+ {
+ rtail->ic = stail->ic;
+ for (crl=rhead;crl!=rtail;crl=crl->next)
+ crl->ic = ic;
+ return;
+ }
+
+ single_iCode = FALSE;
+ break;
+ }
+
+ /* If all of the source lines came from the same iCode, then so have
+ ** all of the replacement lines too.
+ */
+ if (single_iCode)
+ {
+ for (crl=rhead;crl!=rtail->next;crl=crl->next)
+ crl->ic = ic;
+ return;
+ }
+
+ /* The source lines span iCodes, so we may end up with replacement
+ ** lines that we don't know which iCode(s) to associate with. Do the
+ ** best we can by using the following strategies:
+ ** 1) Start at the top and scan down. As long as the source line
+ ** matches the replacement line, they have the same iCode.
+ ** 2) Start at the bottom and scan up. As long as the source line
+ ** matches the replacement line, they have the same iCode.
+ ** 3) For any label in the source, look for a matching label in
+ ** the replacment. If found, they have the same iCode. From
+ ** these matching labels, scan down for additional matching
+ ** lines; if found, they also have the same iCode.
+ */
+
+ /* Strategy #1: Start at the top and scan down for matches
+ */
+ reassociate_ic_down(shead,stail,rhead,rtail);
+
+ /* Strategy #2: Start at the bottom and scan up for matches
+ */
+ reassociate_ic_up(shead,stail,rhead,rtail);
+
+ /* Strategy #3: Try to match labels
+ */
+ csl = shead;
+ while (1)
+ {
+ /* skip over any comments */
+ while (csl!=stail->next && csl->isComment)
+ csl = csl->next;
+ if (csl==stail->next)
+ break;
+
+ if (csl->isLabel)
+ {
+ /* found a source line label; look for it in the replacment lines */
+ crl = rhead;
+ while (1)
+ {
+ while (crl!=rtail->next && crl->isComment)
+ crl = crl->next;
+ if (crl==rtail->next)
+ break;
+ if (matchLine(csl->line, crl->line, NULL))
+ {
+ reassociate_ic_down(csl,stail,crl,rtail);
+ break;
+ }
+ else
+ crl = crl->next;
+ }
+ }
+ csl = csl->next;
+ }
+
+ /* Try to assign a meaningful iCode to any comment that is missing
+ one. Since they are comments, it's ok to make mistakes; we are just
+ trying to improve continuity to simplify other tests.
+ */
+ ic = NULL;
+ for (crl=rtail;crl!=rhead->prev;crl=crl->prev)
+ {
+ if (!crl->ic && ic && crl->isComment)
+ crl->ic = ic;
+ ic = crl->ic;
+ }
+}
+
+