+/*-----------------------------------------------------------------*/
+/* geniCodeCritical - intermediate code for a critical statement */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeCritical (ast *tree, int lvl)
+{
+ iCode *ic;
+ operand *op = NULL;
+
+ /* If op is NULL, the original interrupt state will saved on */
+ /* the stack. Otherwise, it will be saved in op. */
+
+ /* Generate a save of the current interrupt state & disabled */
+ ic = newiCode (CRITICAL, NULL, NULL);
+ IC_RESULT (ic) = op;
+ ADDTOCHAIN (ic);
+
+ /* Generate the critical code sequence */
+ if (tree->left && tree->left->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+ else
+ ast2iCode (tree->left,lvl+1);
+
+ /* Generate a restore of the original interrupt state */
+ ic = newiCode (ENDCRITICAL, NULL, op);
+ ADDTOCHAIN (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
+/* particular case. Ie : assigning or dereferencing array or ptr */
+/*-----------------------------------------------------------------*/
+set * lvaluereqSet = NULL;
+typedef struct lvalItem
+ {
+ int req;
+ int lvl;
+ }
+lvalItem;
+
+/*-----------------------------------------------------------------*/
+/* addLvaluereq - add a flag for lvalreq for current ast level */
+/*-----------------------------------------------------------------*/
+void addLvaluereq(int lvl)
+{
+ lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
+ lpItem->req=1;
+ lpItem->lvl=lvl;
+ addSetHead(&lvaluereqSet,lpItem);
+
+}
+/*-----------------------------------------------------------------*/
+/* delLvaluereq - del a flag for lvalreq for current ast level */
+/*-----------------------------------------------------------------*/
+void delLvaluereq()
+{
+ lvalItem * lpItem;
+ lpItem = getSet(&lvaluereqSet);
+ if(lpItem) Safe_free(lpItem);
+}
+/*-----------------------------------------------------------------*/
+/* clearLvaluereq - clear lvalreq flag */
+/*-----------------------------------------------------------------*/
+void clearLvaluereq()
+{
+ lvalItem * lpItem;
+ lpItem = peekSet(lvaluereqSet);
+ if(lpItem) lpItem->req = 0;
+}
+/*-----------------------------------------------------------------*/
+/* getLvaluereq - get the last lvalreq level */
+/*-----------------------------------------------------------------*/
+int getLvaluereqLvl()
+{
+ lvalItem * lpItem;
+ lpItem = peekSet(lvaluereqSet);
+ if(lpItem) return lpItem->lvl;
+ return 0;
+}
+/*-----------------------------------------------------------------*/
+/* isLvaluereq - is lvalreq valid for this level ? */
+/*-----------------------------------------------------------------*/
+int isLvaluereq(int lvl)
+{
+ lvalItem * lpItem;
+ lpItem = peekSet(lvaluereqSet);
+ if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ast2iCode - creates an icodeList from an ast */
+/*-----------------------------------------------------------------*/
+operand *
+ast2iCode (ast * tree,int lvl)
+{
+ operand *left = NULL;
+ operand *right = NULL;
+ if (!tree)
+ return NULL;
+
+ /* set the global variables for filename & line number */
+ if (tree->filename)
+ filename = tree->filename;
+ if (tree->lineno)
+ lineno = tree->lineno;
+ if (tree->block)
+ block = tree->block;
+ if (tree->level)
+ scopeLevel = tree->level;
+
+ if (tree->type == EX_VALUE)
+ return operandFromValue (tree->opval.val);
+
+ if (tree->type == EX_LINK)
+ return operandFromLink (tree->opval.lnk);
+
+ /* if we find a nullop */
+ if (tree->type == EX_OP &&
+ (tree->opval.op == NULLOP ||
+ tree->opval.op == BLOCK))
+ {
+ if (tree->left && tree->left->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+ else
+ ast2iCode (tree->left,lvl+1);
+ if (tree->right && tree->right->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
+ else
+ ast2iCode (tree->right,lvl+1);
+ return NULL;
+ }
+
+ /* special cases for not evaluating */
+ if (tree->opval.op != ':' &&
+ tree->opval.op != '?' &&
+ tree->opval.op != CALL &&
+ tree->opval.op != IFX &&
+ tree->opval.op != LABEL &&
+ tree->opval.op != GOTO &&
+ tree->opval.op != SWITCH &&
+ tree->opval.op != FUNCTION &&
+ tree->opval.op != INLINEASM &&
+ tree->opval.op != CRITICAL)
+ {
+
+ if (IS_ASSIGN_OP (tree->opval.op) ||
+ IS_DEREF_OP (tree) ||
+ (tree->opval.op == '&' && !tree->right) ||
+ tree->opval.op == PTR_OP)
+ {
+ addLvaluereq(lvl);
+ if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
+ (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
+ clearLvaluereq();
+
+ left = operandFromAst (tree->left,lvl);
+ delLvaluereq();
+ if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
+ left = geniCodeRValue (left, TRUE);
+ }
+ else
+ {
+ left = operandFromAst (tree->left,lvl);
+ }
+ if (tree->opval.op == INC_OP ||
+ tree->opval.op == DEC_OP)
+ {
+ addLvaluereq(lvl);
+ right = operandFromAst (tree->right,lvl);
+ delLvaluereq();
+ }
+ else
+ {
+ right = operandFromAst (tree->right,lvl);
+ }
+ }
+
+ /* now depending on the type of operand */
+ /* this will be a biggy */
+ switch (tree->opval.op)
+ {
+
+ case '[': /* array operation */
+ {
+ //sym_link *ltype = operandType (left);
+ //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+ left = geniCodeRValue (left, FALSE);
+ right = geniCodeRValue (right, TRUE);
+ }
+
+ return geniCodeArray (left, right,lvl);
+
+ case '.': /* structure dereference */
+ if (IS_PTR (operandType (left)))
+ left = geniCodeRValue (left, TRUE);
+ else
+ left = geniCodeRValue (left, FALSE);
+
+ return geniCodeStruct (left, right, tree->lvalue);
+
+ case PTR_OP: /* structure pointer dereference */
+ {
+ sym_link *pType;
+ pType = operandType (left);
+ left = geniCodeRValue (left, TRUE);
+
+ setOClass (pType, getSpec (operandType (left)));
+ }
+
+ return geniCodeStruct (left, right, tree->lvalue);
+
+ case INC_OP: /* increment operator */
+ if (left)
+ return geniCodePostInc (left);
+ else
+ return geniCodePreInc (right, tree->lvalue);
+
+ case DEC_OP: /* decrement operator */
+ if (left)
+ return geniCodePostDec (left);
+ else
+ return geniCodePreDec (right, tree->lvalue);
+
+ case '&': /* bitwise and or address of operator */
+ if (right)
+ { /* this is a bitwise operator */
+ left = geniCodeRValue (left, FALSE);
+ right = geniCodeRValue (right, FALSE);
+ return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);