//Actually creates the quads by recursing; //We will return the quad that was the last result or -1 if we have no result int CG(ast_node n) { //printf("Called CG\n"); //temporaries we're going to use throughout the CG function, just for //convenience Address ar1, ar2, ar3, ar4, ar5, tqa, ta, topatch, e, nq; int lrp, rrp; int tq, t, testq, gq; int typer; SymNode *sn; value v; ast_node next; ast_node x; if (n == NULL) { //printf("Error CG called on NULL node\n"); return -1; } switch (n->node_type) { case CONTINUE_ST: e.kind = Empty; GenQuad(con, e, e, e); break; case BREAK_ST: e.kind = Empty; GenQuad(brk, e, e, e); break; //just has id which we set its attr to constant case CONSTANT: //first we get the id lrp = CG(n->left_child); //id ar1 = quads[lrp]->addr1; sn = LookupInSymbolTable(symtab, ar1.contents.name); SetFlagsAttr(sn, 1); break; case OP_SIZEOF: //first we get the id lrp = CG(n->left_child); //id ar1 = quads[lrp]->addr1; sn = LookupInSymbolTable(symtab, ar1.contents.name); t = GetTypeAttr(sn); switch (t) { case IntT: tq = 4; break; case DouT: tq = 8; break; case IArT: gq = GetSizeAttr(sn); tq = 4*gq; break; case DArT: gq = GetSizeAttr(sn); tq = 8*gq; break; default: tq = 4; break; } //Address ar1, ar2, ar3; ar1.kind = String; ar1.contents.name = NewTemp(4); //we are assigning this literal value to ar1 ar2.kind = IntConst; ar2.contents.val = tq; //we don't need ar3 ar3.kind = Empty; return GenQuad(asn, ar1, ar2, ar3); break; case ARRAY_PULL: //printf("ARRAY_PULL Case in CG\n"); e.kind = Empty; //first we get the id, the name lrp = CG(n->left_child); //then we get the left child, right sibling, which is the index of the array rrp = CG(n->left_child->right_sibling); //id ar1 = quads[lrp]->addr1; //index ar2 = quads[rrp]->addr1; ar3.kind = String; sn = LookupInSymbolTable(symtab, ar1.contents.name); //if int array if (GetTypeAttr(sn) == IArT) { typer = 4; } //if double array else { typer = 8; } t = GetOffsetAttr(sn); //we have a constant if (ar2.kind != String) { tq = ar2.contents.val; } //temporary must be changed else { tq = 4; } if (typer == 4) { ar3.contents.name = NewTemp(4); } else { ar3.contents.name = NewTemp(8); } sn = LookupInSymbolTable(symtab, ar3.contents.name); if (typer == 4) { SetTypeAttr(sn, IntT); SetOffsetAttr(sn, t-(tq*typer)); } else { SetTypeAttr(sn, DouT); SetOffsetAttr(sn, t-(tq*typer)); } return GenQuad(sym, ar3, e, e); break; case INT_ARRAY_DEC: //printf("INT_ARRAY_DEC Case in CG\n"); //first we get the id, the name lrp = CG(n->left_child); //then we get the left child, right sibling, which is the size of the array rrp = CG(n->left_child->right_sibling); //id ar1 = quads[lrp]->addr1; //size ar2 = quads[rrp]->addr1; if (ar2.kind == IntConst) { t = ar2.contents.val; } //otherwise we have a string else { sn = LookupInSymbolTable(symtab, ar2.contents.name); v = GetValueAttr(sn); t = v.ival; } e.kind = Empty; //going to insert into symbol table //printf("inserting int int array id into sym table \n"); //printf("%s is the symbol going in\n", ar1.contents.name); sn = InsertIntoSymbolTable(symtab, ar1.contents.name); //printf("Setting type attribute for that\n"); SetTypeAttr(sn, IArT); //printf("Set type successfully\n"); SetSizeAttr(sn, t); //printf("Set size successfully\n"); if (sn->level == 1) { SetOffsetAttr(sn, goffset); goffset -= 4*t; } else { SetOffsetAttr(sn, foffset); foffset -= 4*t; } //PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to int break; case DOU_ARRAY_DEC: //printf("DOU_ARRAY_DEC Case in CG\n"); //first we get the id, the name lrp = CG(n->left_child); //then we get the left child, right sibling, which is the size of the array rrp = CG(n->left_child->right_sibling); //id ar1 = quads[lrp]->addr1; //size ar2 = quads[rrp]->addr1; if (ar2.kind == IntConst) { t = ar2.contents.val; } //otherwise we have a string else { sn = LookupInSymbolTable(symtab, ar2.contents.name); v = GetValueAttr(sn); t = v.ival; } e.kind = Empty; //going to insert into symbol table //printf("inserting int int array id into sym table \n"); //printf("%s is the symbol going in\n", ar1.contents.name); sn = InsertIntoSymbolTable(symtab, ar1.contents.name); //printf("Setting type attribute for that\n"); SetTypeAttr(sn, DArT); //printf("Set type successfully\n"); SetSizeAttr(sn, t); //printf("Set size successfully\n"); if (sn->level == 1) { SetOffsetAttr(sn, goffset); goffset -= 8*t; } else { SetOffsetAttr(sn, foffset); foffset -= 8*t; } //PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to int break; case SWITCH_ST: //this is the id or int we compare against lrp = CG(n->left_child); ar1 = quads[lrp]->addr1; e.kind = Empty; //traverse the cases next = n->left_child->right_sibling; while (next->node_type == SWITCH_CASE) { //get the case rrp = CG(next->left_child); ar2 = quads[rrp]->addr1; //if the values are not equal, skip this case gq = GenQuad(jne, e, ar2, ar1); //process the sequence CG(next->left_child->right_sibling); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(gq, 1, nq); next=next->right_sibling; } //last node should be the default CG(next); break; case SWITCH_CASE: break; //we have a function with parameters //Based on Louden p 442 case FUNC_DEF: //printf("In FUNC_DEF Case\n"); //add the function name to the symbol table // e.kind = Empty; //we must reset f-offset for memory management purposes foffset = -4; //this will generate a sym quad which is the start of the function //it's also a dummy quad for integer defintions //we're using it like ENT in this case in Louden lrp = CG(n->left_child); //we expect an ID, so add it to the symbol table sn = InsertIntoSymbolTable(symtab, quads[lrp]->addr1.contents.name); //this is the quad where we'll need to jump if this function is called v.ival = lrp; SetValueAttr(sn, v); //we're going to ignore the parameters as per louden p 441 next = n->left_child->right_sibling; while (next->node_type == FUNC_PARAM) { next=next->right_sibling; } //now we're done so we should be at the SEQ of actual instructions CG(next); //finish it off with a ret GenQuad(ret, e, e, e); break; //has id and parameters - we jump to the quad of the id //Based on Louden p 442 case FUNC_CALL: //printf("FUNC_CALL in Switch of CG\n"); e.kind = Empty; //load all the params next = n->left_child; while (next->node_type == FUNC_PARAM) { //we're telling the assembler we want it to load parameters for a function call lrp = CG(next); GenQuad(loadpar, quads[lrp]->addr1, e, e); next=next->right_sibling; } //the id has in the symbol table a value associated with it //which represents the quad we want to jump to lrp = CG(next); //get the name of the ID and look up its place sn = LookupInSymbolTable(symtab, quads[lrp]->addr1.contents.name); v = GetValueAttr(sn); t = v.ival; ar1.kind = IntConst; ar1.contents.val = t; GenQuad(gotoq, ar1, e, e); //jump to the location of the id break; case FUNC_PARAM: return CG(n->left_child); break; case RETURN_S: //printf("In RETURN Case\n"); gq = GenQuad(ret, e, e, e); //if we have a return after the statement if(n->left_child != NULL) { lrp = CG(n->left_child); PatchQuad(gq, 1, quads[lrp]->addr1); } break; // "==" (IS EQUAL TO) operation case OP_EQUALS: //printf("In OP_EQUALS Case\n"); //Address ar1, ar2, ar3; ar1.kind = String; ar1.contents.name = NewTemp(4); //left result needs to be put in if (n->left_child == NULL) { printf("Error child is null\n"); } lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //printf("%s the value\n", ar2.contents.name); //right child's result needs to be the other operand if (n->left_child->right_sibling == NULL) { printf("Error left_child->right sibling is null\n"); } rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; //printf("%s the value\n", ar3.contents.name); return GenQuad(eq, ar1, ar2, ar3); break; //ROOT is nothing in itself, so we just start recursing down the tree case ROOT: //printf("In ROOT case\n"); CG(n->left_child); break; // "!=" (IS NOT EQUAL TO) operation case OP_NOT_EQUALS: ar1.kind = String; ar1.contents.name = NewTemp(4); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; return GenQuad(neq, ar1, ar2, ar3); break; // ">" (GREATER THAN) operation case OP_GREATER_THAN: ar1.kind = String; ar1.contents.name = NewTemp(4); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; return GenQuad(gt, ar1, ar2, ar3); break; // "<" (LESS THAN) operation case OP_LESS_THAN: //printf("LESS THAN Case in CG\n"); ar1.kind = String; ar1.contents.name = NewTemp(4); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; return GenQuad(lt, ar1, ar2, ar3); break; // ">=" (GREATER THAN OR EQUAL TO) operation case OP_GREATER_EQUALS: ar1.kind = String; ar1.contents.name = NewTemp(4); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; return GenQuad(gteq, ar1, ar2, ar3); break; // "<=" (LESS THAN OR EQUAL TO) operation case OP_LESS_EQUALS: ar1.kind = String; ar1.contents.name = NewTemp(4); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; return GenQuad(lteq, ar1, ar2, ar3); break; // "||" (OR) operation case OP_OR: ar1.kind = String; ar1.contents.name = NewTemp(4); ar2.kind = IntConst; ar2.contents.val = 1; ar3.kind = IntConst; ar3.contents.val = 0; ar4.kind = String; ar4.contents.name = NewTemp(4); e.kind = Empty; lrp = CG(n->left_child); ta = quads[lrp]->addr1; gq = GenQuad(if_f, ta, e, e); GenQuad(asn, ar4, ar2, e); typer = GenQuad(gotoq, e, e, e); t = CG(n->left_child->right_sibling); ar5.kind = IntConst; ar5.contents.val = t; ta = quads[t]->addr1; testq = GenQuad(if_f, ta, e, e); GenQuad(asn, ar4, ar2, e); tq = GenQuad(gotoq, e, e, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(testq, 2, nq); GenQuad(asn, ar4, ar3, e); PatchQuad(typer, 1, nq); PatchQuad(gq, 2, ar5); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(tq, 1, nq); rrp = GenQuad(asn, ar1, ar4, e); return rrp; break; // "&&" (AND) operation - based on THC code case OP_AND: ar1.kind = String; ar1.contents.name = NewTemp(4); ar2.kind = IntConst; ar2.contents.val = 1; ar3.kind = IntConst; ar3.contents.val = 0; ar4.kind = String; ar4.contents.name = NewTemp(4); e.kind = Empty; lrp = CG(n->left_child); ta = quads[lrp]->addr1; gq = GenQuad(if_f, ta, e, e); t = CG(n->left_child->right_sibling); ta = quads[t]->addr1; testq = GenQuad(if_f, ta, e, e); GenQuad(asn, ar4, ar2, e); tq = GenQuad(gotoq, e, e, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(gq, 2, nq); PatchQuad(testq, 2, nq); GenQuad(asn, ar4, ar3, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(tq, 1, nq); rrp = GenQuad(asn, ar1, ar4, e); return rrp; break; case OP_NOT: ar1.kind = String; ar1.contents.name = NewTemp(4); ar2.kind = IntConst; ar2.contents.val = 1; ar3.kind = IntConst; ar3.contents.val = 0; ar4.kind = String; ar4.contents.name = NewTemp(4); e.kind = Empty; t = CG(n->left_child); ta = quads[t]->addr1; //if false go to the end and give it a 0 gq = GenQuad(if_f, ta, e, e); GenQuad(asn, ar4, ar2, e); tq = GenQuad(gotoq, e, e, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(gq, 2, nq); GenQuad(asn, ar4, ar3, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(tq, 1, nq); rrp = GenQuad(asn, ar1, ar4, e); return rrp; break; //if it's a SEQ, we want to just recursively produce code for all the children case SEQ: //adapted from THC if code e.kind = Empty; //EnterScope(symtab); //we must tell the assembly generator we've entered a new scope GenQuad(ens, e, e, e); x = n->left_child; while (x != NULL) { CG(x); x = x->right_sibling; } GenQuad(exs, e, e, e); //we must tell the assembly generator we've exited a scope //LeaveScope(symtab); break; //Here we do the addition and then we return the position so higher up nodes can find the result case OP_PLUS: //printf("OP_PLUS Case in CG\n"); ar1.kind = String; //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; ar1.contents.name = NewTemp(MaxType(ar2, ar3)); return GenQuad(add, ar1, ar2, ar3); break; case OP_MINUS: ar1.kind = String; //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; ar1.contents.name = NewTemp(MaxType(ar2, ar3)); return GenQuad(sub, ar1, ar2, ar3); break; case OP_TIMES: //printf("OP_TIMES Case in CG\n"); ar1.kind = String; //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; ar1.contents.name = NewTemp(MaxType(ar2, ar3)); return GenQuad(mul, ar1, ar2, ar3); break; case OP_DIVIDE: ar1.kind = String; //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar3 = quads[rrp]->addr1; ar1.contents.name = NewTemp(MaxType(ar2, ar3)); return GenQuad(divi, ar1, ar2, ar3); break; //negate a number case OP_NEGATIVE: //printf("OP_NEGATIVE Case in CG\n"); ar1.kind = String; //this should only have one child lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //we need to subtract from 0 ar3.kind = IntConst; ar3.contents.val = 0; ar1.contents.name = NewTemp(MaxType(ar2, ar3)); return GenQuad(sub, ar1, ar3, ar2); break; case INT_LITERAL: //printf("INT_LITERAL Case in CG\n"); //Address ar1, ar2, ar3; ar1.kind = String; ar1.contents.name = NewTemp(4); //we are assigning this literal value to ar1 ar2.kind = IntConst; //printf("n->value.int_value %d \n", n->value.int_value); ar2.contents.val = n->value.int_value; //we don't need ar3 ar3.kind = Empty; return GenQuad(asn, ar1, ar2, ar3); break; case DOUBLE_LITERAL: //printf("DOUBLE_LITERAL Case in CG\n"); ar1.kind = String; ar1.contents.name = NewTemp(8); //we are assigning this literal value to ar1 ar2.kind = DouConst; ar2.contents.dval = n->value.double_value; //we don't need ar3 ar3.kind = Empty; return GenQuad(asn, ar1, ar2, ar3); break; case STRING_LITERAL: ar1.kind = String; ar1.contents.name = NewTemp(240); //we are assigning this literal value to ar1 ar2.kind = String; ar2.contents.name = n->value.string; //we don't need ar3 ar3.kind = Empty; return GenQuad(asn, ar1, ar2, ar3); break; //we must insert in the symbol table the child's name case INT_DEC: //printf("INT_DEC Case in CG\n"); lrp = CG(n->left_child); ar1 = quads[lrp]->addr1; ar2.kind = Empty; ar3.kind = Empty; //going to insert into symbol table //printf("inserting int dec id into sym table \n"); //printf("%s is the symbol going in\n", ar1.contents.name); sn = InsertIntoSymbolTable(symtab, ar1.contents.name); //printf("Setting type attribute for that\n"); SetTypeAttr(sn, IntT); //printf("Set type successfully\n"); if (sn->level == 1) { SetOffsetAttr(sn, goffset); goffset -= 4; } else { SetOffsetAttr(sn, foffset); foffset -= 4; } //PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to int break; //we must insert the child in the symbol table case DOU_DEC: //printf("DOU_DEC Case in CG\n"); lrp = CG(n->left_child); ar1 = quads[lrp]->addr1; ar2.kind = Empty; ar3.kind = Empty; sn = InsertIntoSymbolTable(symtab, ar1.contents.name); SetTypeAttr(sn, DouT); if (sn->level == 1) { SetOffsetAttr(sn, goffset); goffset -= 8; } else { SetOffsetAttr(sn, foffset); foffset -= 8; } //PLACEHOLDER - Need to set the TYPE ATTRIBUTE in the symbol table to double break; case FOR_LOOP: //printf("FORLOOP Case in CG\n"); //the first statement is always executed CG(n->left_child); //the inequality is statement two t = CG(n->left_child->right_sibling); ta = quads[t]->addr1; testq = GenQuad(if_f, ta, topatch, e); //we do the sequence before the final statement CG(n->left_child->right_sibling->right_sibling->right_sibling); //now we do the third statement in the for-loop header CG(n->left_child->right_sibling->right_sibling); //then we loop around e.kind = Empty; nq.kind = IntConst; nq.contents.val = t; GenQuad(gotoq, nq, e, e); //finally we must patch the inequality nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(testq, 2, nq); break; case OP_PRE_INCR: //printf("PRE++ Case in CG\n"); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand ar3.kind = IntConst; ar3.contents.val = 1; return GenQuad(add, ar2, ar2, ar3); break; case OP_POST_INCR: //printf("POST++ Case in CG\n"); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand ar3.kind = IntConst; ar3.contents.val = 1; return GenQuad(add, ar2, ar2, ar3); break; case OP_PRE_DECR: //printf("PRE-- Case in CG\n"); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand ar3.kind = IntConst; ar3.contents.val = 1; return GenQuad(sub, ar2, ar2, ar3); break; case OP_POST_DECR: //printf("POST-- Case in CG\n"); //left result needs to be put in lrp = CG(n->left_child); ar2 = quads[lrp]->addr1; //right child's result needs to be the other operand ar3.kind = IntConst; ar3.contents.val = 1; return GenQuad(sub, ar2, ar2, ar3); break; case IF_ELSE: //printf("IF_ELSE Case in CG\n"); t = CG(n->left_child); ta = quads[t]->addr1; topatch.kind = Empty; e.kind = Empty; testq = GenQuad(if_f, ta, topatch, e); CG(n->left_child->right_sibling); gq = GenQuad(gotoq, e, e, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(testq, 2, nq); CG(n->left_child->right_sibling->right_sibling); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(gq, 1, nq); break; case IF: //printf("IF Case in CG\n"); t = CG(n->left_child); ta = quads[t]->addr1; topatch.kind = Empty; e.kind = Empty; //this is where we would switch the order for the dowhile testq = GenQuad(if_f, ta, topatch, e); CG(n->left_child->right_sibling); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(testq, 2, nq); break; //adapted from THC's code in class //MUST TYPE CHECK THAT t RETURNS AN INT FOR COMPARISON case WHILE_LOOP: //printf("WHILE Case in CG\n"); tq = NextQuad(); t = CG(n->left_child); tqa.kind = IntConst; tqa.contents.val = tq; ta = quads[t]->addr1; topatch.kind = Empty; e.kind = Empty; //this is where we would switch the order for the dowhile testq = GenQuad(if_f, ta, topatch, e); CG(n->left_child->right_sibling); GenQuad(gotoq, tqa, e, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(testq, 2, nq); break; //we're still assuming the comparison is the left child //not the left child->right sibling case DO_WHILE_LOOP: tq = NextQuad(); t = CG(n->left_child); //just do the other stuff first and then we potentially loop or leave CG(n->left_child->right_sibling); tqa.kind = IntConst; tqa.contents.val = tq; ta = quads[t]->addr1; topatch.kind = Empty; e.kind = Empty; //this is where we would switch the order for the dowhile testq = GenQuad(if_f, ta, topatch, e); GenQuad(gotoq, tqa, e, e); nq.kind = IntConst; nq.contents.val = NextQuad(); PatchQuad(testq, 2, nq); break; //the assembler has a built in read facility, so this is very simple //NEED TO DEAL WITH DOUBLES HERE TOO BASED ON TYPE CHECK of CHILD's ATTRIBUTE case READ: //printf("READ Case in CG\n"); lrp = CG(n->left_child); //printf("read back in for real\n"); ar1 = quads[lrp]->addr1; //printf("read back in\n"); ar2.kind = Empty; ar3.kind = Empty; gq = GenQuad(rd, ar1, ar2, ar3); //PUT VALUE IN SYMBOL TABLE UNDER READ's CHILD return gq; break; //the assembler has a built in write facility, so this is very simple //NEED TO HANDLE DOUBLES HERE TOO BASED ON TYPE CHECK of CHILD's TYPE ATTRIBUTE case WRITE: //printf("WRITE Case in CG\n"); lrp = CG(n->left_child); ar1 = quads[lrp]->addr1; ar2.kind = Empty; ar3.kind = Empty; GenQuad(wri, ar1, ar2, ar3); break; //we put in a dummy just so that higher ups can use it, also put in symbol table case ID: //printf("ID Case in CG\n"); ar1.contents.name = strdup(n->value.string); //printf("%s is the id\n", ar1.contents.name); //printf("tried strdup\n"); //if (ar1.contents.name == NULL) { // printf("NULL STRING?!\n"); // } //printf("%s is the id\n", ar1.contents.name); ar1.kind = String; //ar1.contents.name = n->value.string; //printf("%s is the id", n->value.string); ar2.kind = Empty; ar3.kind = Empty; return GenQuad(sym, ar1, ar2, ar3); break; //we put in a dummy just so that higher ups can use it, also put in symbol table case OP_ASSIGN: //left result needs to be put in lrp = CG(n->left_child); ar1 = quads[lrp]->addr1; //right child's result needs to be the other operand rrp = CG(n->left_child->right_sibling); ar2 = quads[rrp]->addr1; ar3.kind = Empty; return GenQuad(asn, ar1, ar2, ar3); break; //MISSING CONST, RETURN, SWITCH, BREAK, CONTINUE //RETURN NEEDS TO GO TOGETHER WITH FUNCTIONS I THINK... MAYBE WE NEED TO TYPE CHECK WITH ANOTHER //SWITCH WITHIN THE CASE OF A FUNCTION CALL default: break; } //default, we return -1 which means no result from the previous call... return -1; }
Error _dxf_quadsToQmesh (xfieldT *xf, void *globals) { DEFGLOBALDATA(globals) ; Quadruple *neighbors ; /* neighbors array gives a quad's neighbors */ Qstrip *stripArray = 0 ; /* temp array of strips */ int point[MaxQstripSize] ; /* array into which to build point list */ char *usedArray = 0 ; /* marks quads already used */ int nStrips = 0 ; /* number of strips generated */ int nStrippedPts = 0 ; /* number of points stripped */ int nPtsInStrip ; /* number of points in current strip */ int start_quad ; /* first quad of the strip */ int quad ; /* the current quad */ int dir, i0, i1, i2, i3 ; /* the 4 indexes into quads[quad].p[?] */ int prev_quad, prev_i0, /* used to determine the same current info */ prev_i1,prev_i2,prev_i3 ; Quadruple *quads ; /* array of original quad connections */ int nquads ; /* number of original quad connections */ int i, j, k ; /* misc. indices */ QMesh qmesh = NULL; dxObject qmesho = NULL; ENTRY(("_dxf_quadsToQmesh(0x%x)", xf)); qmesho = _dxf_QueryObject(MESHHASH, (dxObject)xf->field); if (qmesho) { xf->meshObject = DXReference(qmesho); qmesh = (QMesh)DXGetPrivateData((Private)qmesho); _installQMeshInfo(xf, qmesh); return OK; } if (xf->connectionType != ct_quads) { EXIT(("xf->connectionType not ct_quads")); return OK ; } PRINT(("invalid connections: %d", xf->invCntns? DXGetInvalidCount(xf->invCntns): 0)) ; neighbors = getNeighbors(xf); /* get quad connection info; quad connections are replaced by strips */ quads = DXGetArrayData(xf->connections_array) ; nquads = xf->nconnections ; /*npoints = xf->npositions ;*/ xf->origNConnections = nquads; xf->origConnections_array = xf->connections_array; xf->connections_array = NULL; /* allocate temporary array to hold maximum possible number of strips */ if (!(stripArray = (Qstrip *) tdmAllocate(sizeof(Qstrip) * nquads))) { PRINT(("out of memory")); DXErrorGoto (ERROR_NO_MEMORY, "#13000") ; } if (neighbors) { /* quad connections expressed explicitly, we need usedArray */ if (!(usedArray = tdmAllocateZero(sizeof(char) * Bytes(nquads)))) { PRINT(("out of memory")); DXErrorGoto (ERROR_NO_MEMORY, "#13000") ; } /* strip the field, placing strip info into temporary arrays */ for (start_quad = 0; start_quad < nquads; start_quad++) { if (GoodQuad(start_quad)) { nPtsInStrip = 0 ; quad = start_quad ; InitFirstQuad(i0,i1,i2,i3) ; /* pick 1st quad initial vertices */ AddPoint(quad,i1) ; /* add the 1st two... */ AddPoint(quad,i0) ; /* ...points to the mesh */ while (quad >= 0) /* while there's a valid quad... */ { AddPoint(quad,i3) ; /* add another quad to the strip */ AddPoint(quad,i2) ; MarkQuad(quad) ; /* mark it as used */ NextQuad(quad) ; /* move on to next quad */ } /* save strip points */ AllocateAndCopyQstripPointArray() ; } } tdmFree((Pointer)usedArray) ; usedArray = NULL; } else { /* quad connections expressed in compact mesh array form */ int n, counts[100] ; if (!DXQueryGridConnections (xf->origConnections_array, &n, counts) || n != 2) DXErrorGoto (ERROR_INTERNAL, "#13140") ; PRINT(("counts[0] = %d", counts[0])); PRINT(("counts[1] = %d", counts[1])); for (n = 0, i = 0 ; i < counts[0]-1 ; i++) { j = 0 ; while (j < counts[1]-1) { for ( ; j < counts[1]-1 && !ValidQuad(xf->invCntns, n) ; j++, n++) /* skip invalid quads up to end of row/column */ ; if (j == counts[1]-1) break ; /* start triangle strip */ nPtsInStrip = 0 ; point[nPtsInStrip++] = n + i ; point[nPtsInStrip++] = n + i + counts[1] ; while (j < counts[1]-1 && nPtsInStrip < MaxQstripSize && ValidQuad(xf->invCntns, n)) { /* add valid quads up to end of row/column or strip limit */ point[nPtsInStrip++] = n + i + 1 ; point[nPtsInStrip++] = n + i + 1 + counts[1] ; j++ ; n++ ; } /* save strip points */ AllocateAndCopyQstripPointArray() ; } } } PRINT(("stripped %d quadrangles", (nStrippedPts - 2*nStrips)/2)); PRINT(("generated %d triangle strips", nStrips)); PRINT(("average number of triangles per strip: %f", nStrips? (nStrippedPts - 2*nStrips)/(float)nStrips: 0)); if (! _newQMesh(nStrips, nStrippedPts, &qmesh, &qmesho)) goto error; for (i=j=k=0 ; i<nStrips ; i++) { qmesh->meshes[j++] = k; qmesh->meshes[j++] = stripArray[i].points; memcpy(qmesh->connections+k, stripArray[i].point, stripArray[i].points*sizeof(int)); k += stripArray[i].points; } _dxf_InsertObject(MESHHASH, (dxObject)(xf->field), (dxObject)qmesho); xf->meshObject = DXReference(qmesho); _installQMeshInfo(xf, qmesh); /* free temporary array of strips */ if (usedArray) tdmFree((Pointer)usedArray); if (stripArray) FreeTempStrips() ; EXIT(("OK")); return OK ; error: if (usedArray) tdmFree((Pointer)usedArray); if (stripArray) FreeTempStrips() ; EXIT(("ERROR")); return 0 ; }