Graph mkTestGraph(int graphNum) { Graph g = NULL; if (graphNum == 0) { g = newGraph(0); assert(numV(g) == 0); assert(numE(g) == 0); } else if (graphNum == 1) { g = newGraph(1); assert(numV(g) == 1); assert(numE(g) == 0); } else if (graphNum == 2) { g = newGraph(2); assert(numV(g) == 2); assert(numE(g) == 0); } else if (graphNum == 3) { g = newGraph(5); Edge e301 = mkEdge(0, 1, 7); Edge e302 = mkEdge(0, 2, 6); Edge e303 = mkEdge(0, 3, 5); Edge e304 = mkEdge(0, 4, 4); Edge e312 = mkEdge(1, 2, 3); Edge e323 = mkEdge(2, 3, 2); Edge e334 = mkEdge(3, 4, 1); insertE(g, e301); insertE(g, e302); insertE(g, e303); insertE(g, e304); insertE(g, e312); insertE(g, e323); insertE(g, e334); assert(numV(g) == 5); assert(numE(g) == 7); } return g; }
/* Helper for FORI. Coercion. */ void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o) { if (!lj_strscan_numberobj(o)) lj_err_msg(L, LJ_ERR_FORINIT); if (!lj_strscan_numberobj(o+1)) lj_err_msg(L, LJ_ERR_FORLIM); if (!lj_strscan_numberobj(o+2)) lj_err_msg(L, LJ_ERR_FORSTEP); if (LJ_DUALNUM) { /* Ensure all slots are integers or all slots are numbers. */ int32_t k[3]; int nint = 0; ptrdiff_t i; for (i = 0; i <= 2; i++) { if (tvisint(o+i)) { k[i] = intV(o+i); nint++; } else { k[i] = lj_num2int(numV(o+i)); nint += ((lua_Number)k[i] == numV(o+i)); } } if (nint == 3) { /* Narrow to integers. */ setintV(o, k[0]); setintV(o+1, k[1]); setintV(o+2, k[2]); } else if (nint != 0) { /* Widen to numbers. */ if (tvisint(o)) setnumV(o, (lua_Number)intV(o)); if (tvisint(o+1)) setnumV(o+1, (lua_Number)intV(o+1)); if (tvisint(o+2)) setnumV(o+2, (lua_Number)intV(o+2)); } } }
static int io_file_write(lua_State *L, FILE *fp, int start) { cTValue *tv; int status = 1; for (tv = L->base+start; tv < L->top; tv++) { if (tvisstr(tv)) { MSize len = strV(tv)->len; status = status && (fwrite(strVdata(tv), 1, len, fp) == len); } else if (tvisint(tv)) { char buf[LJ_STR_INTBUF]; char *p = lj_str_bufint(buf, intV(tv)); size_t len = (size_t)(buf+LJ_STR_INTBUF-p); status = status && (fwrite(p, 1, len, fp) == len); } else if (tvisnum(tv)) { status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0); } else { lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING); } } if (LJ_52 && status) { L->top = L->base+1; if (start == 0) setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_OUTPUT)); return 1; } return luaL_fileresult(L, status, NULL); }
static void LJ_FASTCALL recff_math_degrad(jit_State *J, RecordFFData *rd) { TRef tr = lj_ir_tonum(J, J->base[0]); TRef trm = lj_ir_knum(J, numV(&J->fn->c.upvalue[0])); J->base[0] = emitir(IRTN(IR_MUL), tr, trm); UNUSED(rd); }
/* Loop optimization. */ int lj_opt_loop(jit_State *J) { IRRef nins = J->cur.nins; MSize nsnap = J->cur.nsnap; int errcode = lj_vm_cpcall(J->L, NULL, J, cploop_opt); if (LJ_UNLIKELY(errcode)) { lua_State *L = J->L; if (errcode == LUA_ERRRUN && tvisnum(L->top-1)) { /* Trace error? */ int32_t e = lj_num2int(numV(L->top-1)); switch ((TraceError)e) { case LJ_TRERR_TYPEINS: /* Type instability. */ case LJ_TRERR_GFAIL: /* Guard would always fail. */ /* Unrolling via recording fixes many cases, e.g. a flipped boolean. */ if (--J->instunroll < 0) /* But do not unroll forever. */ break; L->top--; /* Remove error object. */ loop_undo(J, nins, nsnap); return 1; /* Loop optimization failed, continue recording. */ default: break; } } lj_err_throw(L, errcode); /* Propagate all other errors. */ } return 0; /* Loop optimization is ok. */ }
/* Narrowing of power operator or math.pow. */ TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc) { lua_Number n; if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc)) lj_trace_err(J, LJ_TRERR_BADTYPE); n = numV(vc); /* Limit narrowing for pow to small exponents (or for two constants). */ if ((tref_isk(rc) && tref_isint(rc) && tref_isk(rb)) || ((J->flags & JIT_F_OPT_NARROW) && (numisint(n) && n >= -65536.0 && n <= 65536.0))) { TRef tmp; if (!tref_isinteger(rc)) { if (tref_isstr(rc)) rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); rc = emitir(IRTGI(IR_TOINT), rc, IRTOINT_CHECK); /* Guarded TOINT! */ } if (!tref_isk(rc)) { /* Range guard: -65536 <= i <= 65536 */ tmp = emitir(IRTI(IR_ADD), rc, lj_ir_kint(J, 65536-2147483647-1)); emitir(IRTGI(IR_LE), tmp, lj_ir_kint(J, 2*65536-2147483647-1)); } return emitir(IRTN(IR_POWI), rb, rc); } /* FOLD covers most cases, but some are easier to do here. */ if (tref_isk(rb) && tvispone(ir_knum(IR(tref_ref(rb))))) return rb; /* 1 ^ x ==> 1 */ rc = lj_ir_tonum(J, rc); if (tref_isk(rc) && ir_knum(IR(tref_ref(rc)))->n == 0.5) return emitir(IRTN(IR_FPMATH), rb, IRFPM_SQRT); /* x ^ 0.5 ==> sqrt(x) */ /* Split up b^c into exp2(c*log2(b)). Assembler may rejoin later. */ rb = emitir(IRTN(IR_FPMATH), rb, IRFPM_LOG2); rc = emitir(IRTN(IR_MUL), rb, rc); return emitir(IRTN(IR_FPMATH), rc, IRFPM_EXP2); }
/* Narrow the FORL index type by looking at the runtime values. */ IRType lj_opt_narrow_forl(cTValue *forbase) { lua_assert(tvisnum(&forbase[FORL_IDX]) && tvisnum(&forbase[FORL_STOP]) && tvisnum(&forbase[FORL_STEP])); /* Narrow only if the runtime values of start/stop/step are all integers. */ if (numisint(numV(&forbase[FORL_IDX])) && numisint(numV(&forbase[FORL_STOP])) && numisint(numV(&forbase[FORL_STEP]))) { /* And if the loop index can't possibly overflow. */ lua_Number step = numV(&forbase[FORL_STEP]); lua_Number sum = numV(&forbase[FORL_STOP]) + step; if (0 <= step ? sum <= 2147483647.0 : sum >= -2147483648.0) return IRT_INT; } return IRT_NUM; }
/* Parse a number literal. */ static void lex_number(LexState *ls, TValue *tv) { int c; lua_assert(lj_char_isdigit(ls->current)); do { c = ls->current; save_and_next(ls); } while (lj_char_isident(ls->current) || ls->current == '.' || ((ls->current == '-' || ls->current == '+') && ((c & ~0x20) == 'E' || (c & ~0x20) == 'P'))); #if LJ_HASFFI c &= ~0x20; if ((c == 'I' || c == 'L' || c == 'U') && !ctype_ctsG(G(ls->L))) lex_loadffi(ls->L); if (c == 'I') /* Parse imaginary part of complex number. */ ls->sb.n--; #endif save(ls, '\0'); #if LJ_HASFFI if ((c == 'L' || c == 'U') && lex_number64(ls, tv)) { /* Parse 64 bit int. */ return; } else #endif if (lj_str_numconv(ls->sb.buf, tv)) { #if LJ_HASFFI if (c == 'I') { /* Return cdata holding a complex number. */ GCcdata *cd = lj_cdata_new_(ls->L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); ((double *)cdataptr(cd))[0] = 0; ((double *)cdataptr(cd))[1] = numberVnum(tv); lj_parse_keepcdata(ls, tv, cd); } #endif if (LJ_DUALNUM && tvisnum(tv)) { int32_t k = lj_num2int(numV(tv)); if ((lua_Number)k == numV(tv)) /* -0 cannot end up here. */ setintV(tv, k); } return; } lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); }
void getFlights(Graph g, int * dfsOrdered){ int nDiffCountries = 1; int nFlights = 0; int currCountry = 0; while (nDiffCountries < numV(g)){ Edge nextFlight = getNextFlight(g, dfsOrdered, &nDiffCountries, currCountry); nFlights++; printf("Flight %d %s %s\n", nFlights, getVertexLabel(g,nextFlight.v), getVertexLabel(g,nextFlight.w)); currCountry = nextFlight.w; } }
int32_t lj_lib_checkbit(lua_State *L, int narg) { TValue *o = L->base + narg-1; if (!(o < L->top && lj_strscan_numberobj(o))) lj_err_argt(L, narg, LUA_TNUMBER); if (LJ_LIKELY(tvisint(o))) { return intV(o); } else { int32_t i = lj_num2bit(numV(o)); if (LJ_DUALNUM) setintV(o, i); return i; } }
/* Parse a number literal. */ static void lex_number(LexState *ls) { StrScanFmt fmt; TValue *tv = &ls->tokenval; int c, xp = 'e'; if (ls->current == '-' || ls->current == '+') { save_and_next(ls); } if ((c = ls->current) == '0') { save_and_next(ls); if ((ls->current | 0x20) == 'x') xp = 'p'; } while (lj_char_isident(ls->current) || ls->current == '.' || ((ls->current == '-' || ls->current == '+') && (c | 0x20) == xp)) { c = ls->current; save_and_next(ls); } save(ls, '\0'); fmt = lj_strscan_scan((const uint8_t *)ls->sb.buf, tv, (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) | (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0)); ls->token = TK_number; if (LJ_DUALNUM && fmt == STRSCAN_INT) { setitype(tv, LJ_TISNUM); } else if (fmt == STRSCAN_NUM) { /* Already in correct format. */ #if LJ_HASFFI } else if (fmt != STRSCAN_ERROR) { lua_State *L = ls->L; GCcdata *cd; lua_assert(fmt == STRSCAN_I64 || fmt == STRSCAN_U64 || fmt == STRSCAN_IMAG); if (!ctype_ctsG(G(L))) { ptrdiff_t oldtop = savestack(L, L->top); luaopen_ffi(L); /* Load FFI library on-demand. */ L->top = restorestack(L, oldtop); } if (fmt == STRSCAN_IMAG) { cd = lj_cdata_new_(L, CTID_COMPLEX_DOUBLE, 2*sizeof(double)); ((double *)cdataptr(cd))[0] = 0; ((double *)cdataptr(cd))[1] = numV(tv); } else { cd = lj_cdata_new_(L, fmt==STRSCAN_I64 ? CTID_INT64 : CTID_UINT64, 8); *(uint64_t *)cdataptr(cd) = tv->u64; } lj_parse_keepcdata(ls, tv, cd); #endif } else { lua_assert(fmt == STRSCAN_ERROR); lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER); } }
lua_Number lj_lib_checknum(lua_State *L, int narg) { TValue *o = L->base + narg-1; if (!(o < L->top && (tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o))))) lj_err_argt(L, narg, LUA_TNUMBER); if (LJ_UNLIKELY(tvisint(o))) { lua_Number n = (lua_Number)intV(o); setnumV(o, n); return n; } else { return numV(o); } }
/* Helper for arithmetic instructions. Coercion, metamethod. */ TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc, BCReg op) { MMS mm = bcmode_mm(op); TValue tempb, tempc; cTValue *b, *c; if ((b = str2num(rb, &tempb)) != NULL && (c = str2num(rc, &tempc)) != NULL) { /* Try coercion first. */ setnumV(ra, lj_vm_foldarith(numV(b), numV(c), (int)mm-MM_add)); return NULL; } else { cTValue *mo = lj_meta_lookup(L, rb, mm); if (tvisnil(mo)) { mo = lj_meta_lookup(L, rc, mm); if (tvisnil(mo)) { if (str2num(rb, &tempb) == NULL) rc = rb; lj_err_optype(L, rc, LJ_ERR_OPARITH); return NULL; /* unreachable */ } } return mmcall(L, lj_cont_ra, mo, rb, rc); } }
int main(int argc, char * argv[]){ Graph g; printf("Test newGraph\n"); g = newGraph(); showGraph(g); assert(numV(g) == NUM_MAP_LOCATIONS); assert(numE(g,LAND) == 17); assert(numE(g, SEA) == 8); showIsAdjacent(g); printf("Passed\n"); printf("Destroying graph\n"); destroyGraph(g); printf("Finished destroy \n"); return 0; }
static int io_file_write(lua_State *L, FILE *fp, int start) { cTValue *tv; int status = 1; for (tv = L->base+start; tv < L->top; tv++) { if (tvisstr(tv)) { MSize len = strV(tv)->len; status = status && (fwrite(strVdata(tv), 1, len, fp) == len); } else if (tvisnum(tv)) { status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0); } else { lj_err_argt(L, cast_int(tv - L->base) + 1, LUA_TSTRING); } } return io_pushresult(L, status, NULL); }
static int io_file_write(lua_State *L, FILE *fp, int start) { cTValue *tv; int status = 1; for (tv = L->base+start; tv < L->top; tv++) { if (tvisstr(tv)) { MSize len = strV(tv)->len; status = status && (fwrite(strVdata(tv), 1, len, fp) == len); } else if (tvisint(tv)) { char buf[LJ_STR_INTBUF]; char *p = lj_str_bufint(buf, intV(tv)); size_t len = (size_t)(buf+LJ_STR_INTBUF-p); status = status && (fwrite(p, 1, len, fp) == len); } else if (tvisnum(tv)) { status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0); } else { lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING); } } return io_pushresult(L, status, NULL); }
int main(int argc, char * argv[]){ if (argc < 2){ printf("Incorrect usage: must enter filename\n"); exit (1); } Graph g = readGraph(argv[1]); showGraph(g); printf("\n"); // TASK 1 printf("TASK 1\n"); showGraphLabels(g); printf("\n"); showData(g); printf("\n"); // TASK 2 printf("TASK 2\n"); int *dfsOrdered = malloc(numV(g) * sizeof(Vertex)); dfSearch2(g, dfsOrdered); int i; for(i=0;i< cnt;i++){ Vertex v = dfsOrdered[i]; showVertexData(g,v); } printf("\n"); // TASK 3 printf("TASK 3\n"); printf("\nFlying all over the world\n"); //Uncomment out this line when you get to task 3 getFlights(g,dfsOrdered); free(dfsOrdered); destroyGraph(g); return 0; }
/* Get runtime value of int argument. */ static int32_t argv2int(jit_State *J, TValue *o) { if (!tvisnumber(o) && !(tvisstr(o) && lj_str_tonumber(strV(o), o))) lj_trace_err(J, LJ_TRERR_BADTYPE); return tvisint(o) ? intV(o) : lj_num2int(numV(o)); }
void DfsAcyclicSubgraph::callUML ( const GraphAttributes &AG, List<edge> &arcSet) { const Graph &G = AG.constGraph(); // identify hierarchies NodeArray<int> hierarchy(G,-1); int count = 0; int treeNum = -1; node v; forall_nodes(v,G) { if(hierarchy[v] == -1) { int n = dfsFindHierarchies(AG,hierarchy,count,v); if(n > 1) treeNum = count; ++count; } } arcSet.clear(); // perform DFS on the directed graph formed by generalizations NodeArray<int> number(G,0), completion(G); int nNumber = 0, nCompletion = 0; forall_nodes(v,G) { if(number[v] == 0) dfsBackedgesHierarchies(AG,v,number,completion,nNumber,nCompletion); } // collect all backedges within a hierarchy // and compute outdeg of each vertex within its hierarchy EdgeArray<bool> reversed(G,false); NodeArray<int> outdeg(G,0); edge e; forall_edges(e,G) { if(AG.type(e) != Graph::generalization || e->isSelfLoop()) continue; node src = e->source(), tgt = e->target(); outdeg[src]++; if (hierarchy[src] == hierarchy[tgt] && number[src] >= number[tgt] && completion[src] <= completion[tgt]) reversed[e] = true; } // topologial numbering of nodes within a hierarchy (for each hierarchy) NodeArray<int> numV(G); Queue<node> Q; int countV = 0; forall_nodes(v,G) if(outdeg[v] == 0) Q.append(v); while(!Q.empty()) { v = Q.pop(); numV[v] = countV++; forall_adj_edges(e,v) { node w = e->source(); if(w != v) { if(--outdeg[w] == 0) Q.append(w); } } }
int main (int argc, char * argv[]) { printf("Blackbox tests...\n"); printf("Test 1: newGraph..."); //empty graph Graph g1a = mkTestGraph(0); destroyGraph(g1a); //single graph Graph g1b = mkTestGraph(1); destroyGraph(g1b); printf("Passed!\n"); printf("Test 1a: mkEdge..."); //zero cost edge Edge e1a = mkEdge(0, 1, 0); assert(e1a.v == 0); assert(e1a.w == 1); assert(e1a.weight == 0); Edge e1ar = mkEdge(1, 0, 0); assert(e1ar.v == 1); assert(e1ar.w == 0); assert(e1ar.weight == 0); //edge Edge e1b = mkEdge(1, 5, 10); assert(e1b.v == 1); assert(e1b.w == 5); assert(e1b.weight == 10); Edge e1br = mkEdge(5, 1, 10); assert(e1br.v == 5); assert(e1br.w == 1); assert(e1br.weight == 10); printf("Passed!\n"); printf("Test 2: insertE..."); //double graph Graph g2 = mkTestGraph(2); Edge e2 = mkEdge(0, 1, 12); insertE(g2, e2); assert(numE(g2) == 1); destroyGraph(g2); printf("Passed!\n"); printf("Test 3: isAdjacent..."); //double graph Graph g3a = mkTestGraph(2); Edge e3a = {0, 1, 12}; insertE(g3a, e3a); assert(numV(g3a) == 2); assert(numE(g3a) == 1); assert(isAdjacent(g3a, 0, 1) == 1); assert(isAdjacent(g3a, 1, 0) == 1); destroyGraph(g3a); //graph Graph g3b = mkTestGraph(3); assert(isAdjacent(g3b, 0, 1) == 1); assert(isAdjacent(g3b, 0, 2) == 1); assert(isAdjacent(g3b, 0, 3) == 1); assert(isAdjacent(g3b, 0, 4) == 1); assert(isAdjacent(g3b, 1, 2) == 1); assert(isAdjacent(g3b, 2, 3) == 1); assert(isAdjacent(g3b, 3, 4) == 1); destroyGraph(g3b); printf("Passed!\n"); printf("Test 4: adjacentVertices..."); Graph g4a = mkTestGraph(2); Edge e4a = {0, 1, 12}; insertE(g4a, e4a); Vertex adj4a[2]; //allocate space for max number of vertices assert(adjacentVertices(g4a, 0, adj4a) == 1); assert(adj4a[0] >= 0); assert(adjacentVertices(g4a, 1, adj4a) == 1); assert(adj4a[0] >= 0); destroyGraph(g4a); printf("Passed!\n"); printf("Test 5: incidentEdges..."); Graph g5 = mkTestGraph(2); Edge e5 = {0, 1, 12}; insertE(g5, e5); Edge edges5[1]; //allocate space for max num of edges assert(incidentEdges(g5, 0, edges5) == 1); int v5 = edges5[0].v; int w5 = edges5[0].w; assert( (v5 == 0 && w5 == 1) || (v5 == 1 && w5 == 0) ); assert(edges5[0].weight == 12); assert(incidentEdges(g5, 1, edges5) == 1); v5 = edges5[0].v; w5 = edges5[0].w; assert( (v5 == 0 && w5 == 1) || (v5 == 1 && w5 == 0) ); assert(edges5[0].weight == 12); destroyGraph(g5); printf("Passed!\n"); printf("Test 6: edges..."); Graph g6 = mkTestGraph(2); Edge e6 = {0, 1, 12}; insertE(g6, e6); Edge es6[1]; //allocate space for max num of edges assert(edges(es6, 1, g6) == 1); int v6 = es6[0].v; int w6 = es6[0].w; assert( (v6 == 0 && w6 == 1) || (v6 == 1 && w6 == 0) ); assert(es6[0].weight == 12); destroyGraph(g6); printf("Passed!\n"); printf("All Test Passed! You are a Beast!\n"); return EXIT_SUCCESS; }
/* Get runtime value of int argument. */ static int32_t argv2int(jit_State *J, TValue *o) { if (!lj_strscan_numberobj(o)) lj_trace_err(J, LJ_TRERR_BADTYPE); return tvisint(o) ? intV(o) : lj_num2int(numV(o)); }
/* Index C data by a TValue. Return CType and pointer. */ CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key, uint8_t **pp, CTInfo *qual) { uint8_t *p = (uint8_t *)cdataptr(cd); CType *ct = ctype_get(cts, cd->ctypeid); ptrdiff_t idx; /* Resolve reference for cdata object. */ if (ctype_isref(ct->info)) { lua_assert(ct->size == CTSIZE_PTR); p = *(uint8_t **)p; ct = ctype_child(cts, ct); } collect_attrib: /* Skip attributes and collect qualifiers. */ while (ctype_isattrib(ct->info)) { if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size; ct = ctype_child(cts, ct); } lua_assert(!ctype_isref(ct->info)); /* Interning rejects refs to refs. */ if (tvisint(key)) { idx = (ptrdiff_t)intV(key); goto integer_key; } else if (tvisnum(key)) { /* Numeric key. */ #ifdef _MSC_VER /* Workaround for MSVC bug. */ volatile #endif lua_Number n = numV(key); idx = LJ_64 ? (ptrdiff_t)n : (ptrdiff_t)lj_num2int(n); integer_key: if (ctype_ispointer(ct->info)) { CTSize sz = lj_ctype_size(cts, ctype_cid(ct->info)); /* Element size. */ if (sz == CTSIZE_INVALID) lj_err_caller(cts->L, LJ_ERR_FFI_INVSIZE); if (ctype_isptr(ct->info)) { p = (uint8_t *)cdata_getptr(p, ct->size); } else if ((ct->info & (CTF_VECTOR|CTF_COMPLEX))) { if ((ct->info & CTF_COMPLEX)) idx &= 1; *qual |= CTF_CONST; /* Valarray elements are constant. */ } *pp = p + idx*(int32_t)sz; return ct; } } else if (tviscdata(key)) { /* Integer cdata key. */ GCcdata *cdk = cdataV(key); CType *ctk = ctype_raw(cts, cdk->ctypeid); if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk); if (ctype_isinteger(ctk->info)) { lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), ctk, (uint8_t *)&idx, cdataptr(cdk), 0); goto integer_key; } } else if (tvisstr(key)) { /* String key. */ GCstr *name = strV(key); if (ctype_isstruct(ct->info)) { CTSize ofs; CType *fct = lj_ctype_getfieldq(cts, ct, name, &ofs, qual); if (fct) { *pp = p + ofs; return fct; } } else if (ctype_iscomplex(ct->info)) { if (name->len == 2) { *qual |= CTF_CONST; /* Complex fields are constant. */ if (strdata(name)[0] == 'r' && strdata(name)[1] == 'e') { *pp = p; return ct; } else if (strdata(name)[0] == 'i' && strdata(name)[1] == 'm') { *pp = p + (ct->size >> 1); return ct; } } } else if (cd->ctypeid == CTID_CTYPEID) {