recording::type * builtins_manager::get_type (enum jit_builtin_type type_id) { if (!m_types[type_id]) m_types[type_id] = make_type (type_id); return m_types[type_id]; }
type_t *type_new_module(char *name) { type_t *type = make_type(RPC_FC_MODULE, NULL); type->name = name; /* FIXME: register type to detect multiple definitions */ return type; }
/** Makes a tuple type with the specified types */ inline type make_tuple(const type &tp0) { nd::array field_types = nd::empty(1, make_type()); unchecked_fixed_dim_get_rw<type>(field_types, 0) = tp0; field_types.flag_as_immutable(); return make_tuple(field_types); }
// Resolve a name that refers to a type. Type& make_type(Context& cxt, Name& n) { if (Simple_id* id = as<Simple_id>(&n)) return make_type(cxt, *id); lingo_unhandled(n); }
type_t *type_new_function(var_list_t *args) { type_t *t = make_type(RPC_FC_FUNCTION, NULL); t->details.function = xmalloc(sizeof(*t->details.function)); t->details.function->args = args; t->details.function->idx = -1; return t; }
/** Makes a tuple type with the specified types */ inline type make_tuple(const type &tp0, const type &tp1, const type &tp2, const type &tp3) { nd::array field_types = nd::empty(4, make_type()); unchecked_fixed_dim_get_rw<type>(field_types, 0) = tp0; unchecked_fixed_dim_get_rw<type>(field_types, 1) = tp1; unchecked_fixed_dim_get_rw<type>(field_types, 2) = tp2; unchecked_fixed_dim_get_rw<type>(field_types, 3) = tp3; field_types.flag_as_immutable(); return make_tuple(field_types); }
type_t *type_new_array(const char *name, type_t *element, int declarray, unsigned long dim, expr_t *size_is, expr_t *length_is) { type_t *t = make_type(RPC_FC_LGFARRAY, element); if (name) t->name = xstrdup(name); t->declarray = declarray; t->details.array.length_is = length_is; if (size_is) t->details.array.size_is = size_is; else t->details.array.dim = dim; return t; }
void switchboard (void) { extern void kbicho (void *msg); static type_s *tty_request; static type_s *kbicho_request; ki_t key; int rc; rc = sw_register(getprogname()); if (rc) eprintf("sw_register %d", rc); tty_request = make_type("tty_request", sw_died, tty_connection, NULL); key = make_gate( &tty_request, RESOURCE | PASS_OTHER); rc = sw_request("tty", key); if (rc) eprintf("sw_request tty %d", rc); kbicho_request = make_type("kbicho_request", sw_died, kbicho, NULL); key = make_gate( &kbicho_request, RESOURCE | PASS_OTHER); rc = sw_request("kbicho", key); if (rc) eprintf("sw_request kbicho %d", rc); }
void tty_connection (void *msg) { static type_s *tty_connection; msg_s *m = msg; ki_t reply = m->q.q_passed_key; int rc; tty_connection = make_type("tty_connection", tty_died, get_line); m->q.q_passed_key = make_gate( &tty_connection, RESOURCE | PASS_REPLY); m->m_method = 0; rc = send_key_tau(reply, m); if (rc) eprintf("send_key_tau %d", rc); destroy_key_tau(reply); }
static void init_net (void) { ki_t key; int rc; FN; if (init_msg_tau(getprogname())) { exit(2); } sw_register(getprogname()); Sage.s_type = make_type("sage", NULL, next_fm, NULL); key = make_gate( &Sage, REQUEST | PASS_REPLY); rc = sw_post("sage", key); if (rc) failure("sw_post", rc); }
void string_instrumentationt::do_strerror( goto_programt &dest, goto_programt::targett it, code_function_callt &call) { if(call.lhs().is_nil()) { it->make_skip(); return; } irep_idt identifier_buf="c::__strerror_buffer"; irep_idt identifier_size="c::__strerror_buffer_size"; if(context.symbols.find(identifier_buf)==context.symbols.end()) { symbolt new_symbol_size; new_symbol_size.base_name="__strerror_buffer_size"; new_symbol_size.pretty_name=new_symbol_size.base_name; new_symbol_size.name=identifier_size; new_symbol_size.mode="C"; new_symbol_size.type=uint_type(); new_symbol_size.is_statevar=true; new_symbol_size.lvalue=true; new_symbol_size.static_lifetime=true; array_typet type; type.subtype()=char_type(); type.size()=symbol_expr(new_symbol_size); symbolt new_symbol_buf; new_symbol_buf.mode="C"; new_symbol_buf.type=type; new_symbol_buf.is_statevar=true; new_symbol_buf.lvalue=true; new_symbol_buf.static_lifetime=true; new_symbol_buf.base_name="__strerror_buffer"; new_symbol_buf.pretty_name=new_symbol_buf.base_name; new_symbol_buf.name="c::"+id2string(new_symbol_buf.base_name); context.move(new_symbol_buf); context.move(new_symbol_size); } const symbolt &symbol_size=ns.lookup(identifier_size); const symbolt &symbol_buf=ns.lookup(identifier_buf); goto_programt tmp; { goto_programt::targett assignment1=tmp.add_instruction(ASSIGN); exprt nondet_size=side_effect_expr_nondett(uint_type()); assignment1->code=code_assignt(symbol_expr(symbol_size), nondet_size); assignment1->location=it->location; goto_programt::targett assumption1=tmp.add_instruction(); assumption1->make_assumption(binary_relation_exprt( symbol_expr(symbol_size), "notequal", gen_zero(symbol_size.type))); assumption1->location=it->location; } // return a pointer to some magic buffer exprt index=exprt("index", char_type()); index.copy_to_operands(symbol_expr(symbol_buf), gen_zero(uint_type())); exprt ptr=exprt("address_of", pointer_typet()); ptr.type().subtype()=char_type(); ptr.copy_to_operands(index); // make that zero-terminated { goto_programt::targett assignment2=tmp.add_instruction(ASSIGN); assignment2->code=code_assignt(is_zero_string(ptr, true), true_exprt()); assignment2->location=it->location; } // assign address { goto_programt::targett assignment3=tmp.add_instruction(ASSIGN); exprt rhs=ptr; make_type(rhs, call.lhs().type()); assignment3->code=code_assignt(call.lhs(), rhs); assignment3->location=it->location; } it->make_skip(); dest.insert_before_swap(it, tmp); }
Expression *expression_unary(int op, Expression *only) { Tac *temp; Tac *result; Symbol *temp_variable; debug("Unary: %d Symbol: %s Type: %d", op, only->result->name, only->result->type->code); //Constant folding if (only->result->type->code == TYPE_NATURAL) { //Fix 5-19-2011 //Since each symbol is added to the constant table only once //if we delete a symbol that was used previously //We wil have problems //Instead - make a new symbol, and do the wiring //Remove from symbol table //symboltable_delete(constantTable, only->result); Symbol *fold_result = make_symbol(); fold_result->type = make_type(TYPE_NATURAL); fold_result->name = (char*)safe_malloc(sizeof(char) * 12); switch (op) { case TAC_NEGATIVE: //only->result->value.integer = - only->result->value.integer; fold_result->value.integer = - only->result->value.integer; //Make new name, overwriting old name //sprintf(only->result->name, "%d", only->result->value.integer); break; } //rewire expression to use new result only->result = fold_result; //Fix name sprintf(only->result->name, "%d", only->result->value.integer); //Reinsert symboltable_insert(constantTable, only->result); //debug("Folded constant to %d", only->result->value.integer); return only; } temp_variable = make_temp(); temp_variable->type = make_type(TYPE_VARIABLE);//Generic variable type //Since we dont have a constant, we make a new tac with a temporary symbol temp = make_tac(TAC_VARIABLE, temp_variable, NULL, NULL); temp->prev = only->tac; //This is result of "calling" operator //FIX 5-19-2011 //The backend looks for the only operand in operand1, not operand 2 //result = make_tac(op, temp->result, NULL, only->result); result = make_tac(op, temp->result, only->result, NULL); result->prev = temp; //Rewire the expression struct to point to the true result only->result = temp->result; only->tac = result; return only; }
inline type make_empty_tuple() { // TODO: return a static instance nd::array field_types = nd::empty(0, make_type()); return make_tuple(field_types); }
void string_instrumentationt::do_strerror( goto_programt &dest, goto_programt::targett it, code_function_callt &call) { if(call.lhs().is_nil()) { it->make_skip(); return; } irep_idt identifier_buf="__strerror_buffer"; irep_idt identifier_size="__strerror_buffer_size"; if(symbol_table.symbols.find(identifier_buf)==symbol_table.symbols.end()) { symbolt new_symbol_size; new_symbol_size.base_name="__strerror_buffer_size"; new_symbol_size.pretty_name=new_symbol_size.base_name; new_symbol_size.name=identifier_size; new_symbol_size.mode=ID_C; new_symbol_size.type=size_type(); new_symbol_size.is_state_var=true; new_symbol_size.is_lvalue=true; new_symbol_size.is_static_lifetime=true; array_typet type; type.subtype()=char_type(); type.size()=new_symbol_size.symbol_expr(); symbolt new_symbol_buf; new_symbol_buf.mode=ID_C; new_symbol_buf.type=type; new_symbol_buf.is_state_var=true; new_symbol_buf.is_lvalue=true; new_symbol_buf.is_static_lifetime=true; new_symbol_buf.base_name="__strerror_buffer"; new_symbol_buf.pretty_name=new_symbol_buf.base_name; new_symbol_buf.name=new_symbol_buf.base_name; symbol_table.move(new_symbol_buf); symbol_table.move(new_symbol_size); } const symbolt &symbol_size=ns.lookup(identifier_size); const symbolt &symbol_buf=ns.lookup(identifier_buf); goto_programt tmp; { goto_programt::targett assignment1=tmp.add_instruction(ASSIGN); exprt nondet_size=side_effect_expr_nondett(size_type()); assignment1->code=code_assignt(symbol_size.symbol_expr(), nondet_size); assignment1->source_location=it->source_location; goto_programt::targett assumption1=tmp.add_instruction(); assumption1->make_assumption( binary_relation_exprt( symbol_size.symbol_expr(), ID_notequal, from_integer(0, symbol_size.type))); assumption1->source_location=it->source_location; } // return a pointer to some magic buffer index_exprt index( symbol_buf.symbol_expr(), from_integer(0, index_type()), char_type()); address_of_exprt ptr(index); // make that zero-terminated { goto_programt::targett assignment2=tmp.add_instruction(ASSIGN); assignment2->code=code_assignt(is_zero_string(ptr, true), true_exprt()); assignment2->source_location=it->source_location; } // assign address { goto_programt::targett assignment3=tmp.add_instruction(ASSIGN); exprt rhs=ptr; make_type(rhs, call.lhs().type()); assignment3->code=code_assignt(call.lhs(), rhs); assignment3->source_location=it->source_location; } it->make_skip(); dest.insert_before_swap(it, tmp); }
void printf_formattert::process_format(std::ostream &out) { exprt tmp; format_constantt format_constant; format_constant.precision=6; format_constant.min_width=0; format_constant.zero_padding=false; char ch=next(); if(ch=='0') // leading zeros { format_constant.zero_padding=true; ch=next(); } while(isdigit(ch)) // width { format_constant.min_width*=10; format_constant.min_width+=ch-'0'; ch=next(); } if(ch=='.') // precision { format_constant.precision=0; ch=next(); while(isdigit(ch)) { format_constant.precision*=10; format_constant.precision+=ch-'0'; ch=next(); } } switch(ch) { case '%': out << ch; break; case 'e': case 'E': format_constant.style=format_spect::stylet::SCIENTIFIC; if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), double_type())); break; case 'f': case 'F': format_constant.style=format_spect::stylet::DECIMAL; if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), double_type())); break; case 'g': case 'G': format_constant.style=format_spect::stylet::AUTOMATIC; if(format_constant.precision==0) format_constant.precision=1; if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), double_type())); break; case 's': { if(next_operand==operands.end()) break; // this is the address of a string const exprt &op=*(next_operand++); if(op.id()==ID_address_of && op.operands().size()==1 && op.op0().id()==ID_index && op.op0().operands().size()==2 && op.op0().op0().id()==ID_string_constant) out << format_constant(op.op0().op0()); } break; case 'd': if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), signed_int_type())); break; case 'D': if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), signed_long_int_type())); break; case 'u': if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), unsigned_int_type())); break; case 'U': if(next_operand==operands.end()) break; out << format_constant( make_type(*(next_operand++), unsigned_long_int_type())); break; default: out << '%' << ch; } }
void tokenize_cleanup(void) { LOG_FUNC_ENTRY(); chunk_t *pc = chunk_get_head(); chunk_t *prev = NULL; chunk_t *next; chunk_t *tmp; chunk_t *tmp2; bool in_type_cast = false; cpd.unc_stage = US_TOKENIZE_CLEANUP; /* Since [] is expected to be TSQUARE for the 'operator', we need to make * this change in the first pass. */ for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next_ncnl(pc)) { if (pc->type == CT_SQUARE_OPEN) { next = chunk_get_next_ncnl(pc); if (chunk_is_token(next, CT_SQUARE_CLOSE)) { /* Change '[' + ']' into '[]' */ set_chunk_type(pc, CT_TSQUARE); pc->str = "[]"; // bug # 664 // The original orig_col_end of CT_SQUARE_CLOSE is stored at orig_col_end of CT_TSQUARE. // pc->orig_col_end += 1; pc->orig_col_end = next->orig_col_end; chunk_del(next); } } if ((pc->type == CT_SEMICOLON) && (pc->flags & PCF_IN_PREPROC) && !chunk_get_next_ncnl(pc, CNAV_PREPROC)) { LOG_FMT(LNOTE, "%s:%d Detected a macro that ends with a semicolon. Possible failures if used.\n", cpd.filename, pc->orig_line); } } /* We can handle everything else in the second pass */ pc = chunk_get_head(); next = chunk_get_next_ncnl(pc); while ((pc != NULL) && (next != NULL)) { if ((pc->type == CT_DOT) && (cpd.lang_flags & LANG_ALLC)) { set_chunk_type(pc, CT_MEMBER); } if ((pc->type == CT_NULLCOND) && (cpd.lang_flags & LANG_CS)) { set_chunk_type(pc, CT_MEMBER); } /* Determine the version stuff (D only) */ if (pc->type == CT_D_VERSION) { if (next->type == CT_PAREN_OPEN) { set_chunk_type(pc, CT_D_VERSION_IF); } else { if (next->type != CT_ASSIGN) { LOG_FMT(LERR, "%s:%d %s: version: Unexpected token %s\n", cpd.filename, pc->orig_line, __func__, get_token_name(next->type)); cpd.error_count++; } set_chunk_type(pc, CT_WORD); } } /* Determine the scope stuff (D only) */ if (pc->type == CT_D_SCOPE) { if (next->type == CT_PAREN_OPEN) { set_chunk_type(pc, CT_D_SCOPE_IF); } else { set_chunk_type(pc, CT_TYPE); } } /** * Change CT_BASE before CT_PAREN_OPEN to CT_WORD. * public myclass() : base() { * } */ if ((pc->type == CT_BASE) && (next->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_WORD); } if ((pc->type == CT_ENUM) && (next->type == CT_CLASS)) { set_chunk_type(next, CT_ENUM_CLASS); } /** * Change CT_WORD after CT_ENUM, CT_UNION, or CT_STRUCT to CT_TYPE * Change CT_WORD before CT_WORD to CT_TYPE */ if (next->type == CT_WORD) { if ((pc->type == CT_ENUM) || (pc->type == CT_ENUM_CLASS) || (pc->type == CT_UNION) || (pc->type == CT_STRUCT)) { set_chunk_type(next, CT_TYPE); } if (pc->type == CT_WORD) { set_chunk_type(pc, CT_TYPE); } } /* change extern to qualifier if extern isn't followed by a string or * an open paren */ if (pc->type == CT_EXTERN) { if (next->type == CT_STRING) { /* Probably 'extern "C"' */ } else if (next->type == CT_PAREN_OPEN) { /* Probably 'extern (C)' */ } else { /* Something else followed by a open brace */ tmp = chunk_get_next_ncnl(next); if ((tmp == NULL) || (tmp->type != CT_BRACE_OPEN)) { set_chunk_type(pc, CT_QUALIFIER); } } } /** * Change CT_STAR to CT_PTR_TYPE if preceded by CT_TYPE, * CT_QUALIFIER, or CT_PTR_TYPE. */ if ((next->type == CT_STAR) && ((pc->type == CT_TYPE) || (pc->type == CT_QUALIFIER) || (pc->type == CT_PTR_TYPE))) { set_chunk_type(next, CT_PTR_TYPE); } if ((pc->type == CT_TYPE_CAST) && (next->type == CT_ANGLE_OPEN)) { set_chunk_parent(next, CT_TYPE_CAST); in_type_cast = true; } /** * Change angle open/close to CT_COMPARE, if not a template thingy */ if ((pc->type == CT_ANGLE_OPEN) && (pc->parent_type != CT_TYPE_CAST)) { /* pretty much all languages except C use <> for something other than * comparisons. "#include<xxx>" is handled elsewhere. */ if (cpd.lang_flags & (LANG_CPP | LANG_CS | LANG_JAVA | LANG_VALA | LANG_OC)) { // bug #663 check_template(pc); } else { /* convert CT_ANGLE_OPEN to CT_COMPARE */ set_chunk_type(pc, CT_COMPARE); } } if ((pc->type == CT_ANGLE_CLOSE) && (pc->parent_type != CT_TEMPLATE)) { if (in_type_cast) { in_type_cast = false; set_chunk_parent(pc, CT_TYPE_CAST); } else { next = handle_double_angle_close(pc); } } if (cpd.lang_flags & LANG_D) { /* Check for the D string concat symbol '~' */ if ((pc->type == CT_INV) && ((prev->type == CT_STRING) || (prev->type == CT_WORD) || (next->type == CT_STRING))) { set_chunk_type(pc, CT_CONCAT); } /* Check for the D template symbol '!' (word + '!' + word or '(') */ if ((pc->type == CT_NOT) && (prev->type == CT_WORD) && ((next->type == CT_PAREN_OPEN) || (next->type == CT_WORD) || (next->type == CT_TYPE))) { set_chunk_type(pc, CT_D_TEMPLATE); } /* handle "version(unittest) { }" vs "unittest { }" */ if (prev && (pc->type == CT_UNITTEST) && (prev->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_WORD); } /* handle 'static if' and merge the tokens */ if (prev && (pc->type == CT_IF) && chunk_is_str(prev, "static", 6)) { /* delete PREV and merge with IF */ pc->str.insert(0, ' '); pc->str.insert(0, prev->str); pc->orig_col = prev->orig_col; pc->orig_line = prev->orig_line; chunk_t *to_be_deleted = prev; prev = chunk_get_prev_ncnl(prev); chunk_del(to_be_deleted); } } if (cpd.lang_flags & LANG_CPP) { /* Change Word before '::' into a type */ if ((pc->type == CT_WORD) && (next->type == CT_DC_MEMBER)) { set_chunk_type(pc, CT_TYPE); } } /* Change get/set to CT_WORD if not followed by a brace open */ if ((pc->type == CT_GETSET) && (next->type != CT_BRACE_OPEN)) { if ((next->type == CT_SEMICOLON) && ((prev->type == CT_BRACE_CLOSE) || (prev->type == CT_BRACE_OPEN) || (prev->type == CT_SEMICOLON))) { set_chunk_type(pc, CT_GETSET_EMPTY); set_chunk_parent(next, CT_GETSET); } else { set_chunk_type(pc, CT_WORD); } } /* Interface is only a keyword in MS land if followed by 'class' or 'struct' * likewise, 'class' may be a member name in Java. */ if ((pc->type == CT_CLASS) && !CharTable::IsKw1(next->str[0])) { set_chunk_type(pc, CT_WORD); } /* Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL * Usually the next item is part of the operator. * In a few cases the next few tokens are part of it: * operator + - common case * operator >> - need to combine '>' and '>' * operator () * operator [] - already converted to TSQUARE * operator new [] * operator delete [] * operator const char * * operator const B& * operator std::allocator<U> * * In all cases except the last, this will put the entire operator value * in one chunk. */ if (pc->type == CT_OPERATOR) { tmp2 = chunk_get_next(next); /* Handle special case of () operator -- [] already handled */ if (next->type == CT_PAREN_OPEN) { tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->type == CT_PAREN_CLOSE)) { next->str = "()"; set_chunk_type(next, CT_OPERATOR_VAL); chunk_del(tmp); next->orig_col_end += 1; } } else if ((next->type == CT_ANGLE_CLOSE) && tmp2 && (tmp2->type == CT_ANGLE_CLOSE) && (tmp2->orig_col == next->orig_col_end)) { next->str.append('>'); next->orig_col_end++; set_chunk_type(next, CT_OPERATOR_VAL); chunk_del(tmp2); } else if (next->flags & PCF_PUNCTUATOR) { set_chunk_type(next, CT_OPERATOR_VAL); } else { set_chunk_type(next, CT_TYPE); /* Replace next with a collection of all tokens that are part of * the type. */ tmp2 = next; while ((tmp = chunk_get_next(tmp2)) != NULL) { if ((tmp->type != CT_WORD) && (tmp->type != CT_TYPE) && (tmp->type != CT_QUALIFIER) && (tmp->type != CT_STAR) && (tmp->type != CT_CARET) && (tmp->type != CT_AMP) && (tmp->type != CT_TSQUARE)) { break; } /* Change tmp into a type so that space_needed() works right */ make_type(tmp); int num_sp = space_needed(tmp2, tmp); while (num_sp-- > 0) { next->str.append(" "); } next->str.append(tmp->str); tmp2 = tmp; } while ((tmp2 = chunk_get_next(next)) != tmp) { chunk_del(tmp2); } set_chunk_type(next, CT_OPERATOR_VAL); next->orig_col_end = next->orig_col + next->len(); } set_chunk_parent(next, CT_OPERATOR); LOG_FMT(LOPERATOR, "%s: %d:%d operator '%s'\n", __func__, pc->orig_line, pc->orig_col, next->text()); } /* Change private, public, protected into either a qualifier or label */ if (pc->type == CT_PRIVATE) { /* Handle Qt slots - maybe should just check for a CT_WORD? */ if (chunk_is_str(next, "slots", 5) || chunk_is_str(next, "Q_SLOTS", 7)) { tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->type == CT_COLON)) { next = tmp; } } if (next->type == CT_COLON) { set_chunk_type(next, CT_PRIVATE_COLON); if ((tmp = chunk_get_next_ncnl(next)) != NULL) { chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); } } else { set_chunk_type(pc, (chunk_is_str(pc, "signals", 7) || chunk_is_str(pc, "Q_SIGNALS", 9)) ? CT_WORD : CT_QUALIFIER); } } /* Look for <newline> 'EXEC' 'SQL' */ if ((chunk_is_str(pc, "EXEC", 4) && chunk_is_str(next, "SQL", 3)) || ((*pc->str == '$') && (pc->type != CT_SQL_WORD))) { tmp = chunk_get_prev(pc); if (chunk_is_newline(tmp)) { if (*pc->str == '$') { set_chunk_type(pc, CT_SQL_EXEC); if (pc->len() > 1) { /* SPLIT OFF '$' */ chunk_t nc; nc = *pc; pc->str.resize(1); pc->orig_col_end = pc->orig_col + 1; nc.type = CT_SQL_WORD; nc.str.pop_front(); nc.orig_col++; nc.column++; chunk_add_after(&nc, pc); next = chunk_get_next(pc); } } tmp = chunk_get_next(next); if (chunk_is_str_case(tmp, "BEGIN", 5)) { set_chunk_type(pc, CT_SQL_BEGIN); } else if (chunk_is_str_case(tmp, "END", 3)) { set_chunk_type(pc, CT_SQL_END); } else { set_chunk_type(pc, CT_SQL_EXEC); } /* Change words into CT_SQL_WORD until CT_SEMICOLON */ while (tmp != NULL) { if (tmp->type == CT_SEMICOLON) { break; } if ((tmp->len() > 0) && (unc_isalpha(*tmp->str) || (*tmp->str == '$'))) { set_chunk_type(tmp, CT_SQL_WORD); } tmp = chunk_get_next_ncnl(tmp); } } } /* handle MS abomination 'for each' */ if ((pc->type == CT_FOR) && chunk_is_str(next, "each", 4) && (next == chunk_get_next(pc))) { /* merge the two with a space between */ pc->str.append(' '); pc->str += next->str; pc->orig_col_end = next->orig_col_end; chunk_del(next); next = chunk_get_next_ncnl(pc); /* label the 'in' */ if (next && (next->type == CT_PAREN_OPEN)) { tmp = chunk_get_next_ncnl(next); while (tmp && (tmp->type != CT_PAREN_CLOSE)) { if (chunk_is_str(tmp, "in", 2)) { set_chunk_type(tmp, CT_IN); break; } tmp = chunk_get_next_ncnl(tmp); } } } /* ObjectiveC allows keywords to be used as identifiers in some situations * This is a dirty hack to allow some of the more common situations. */ if (cpd.lang_flags & LANG_OC) { if (((pc->type == CT_IF) || (pc->type == CT_FOR) || (pc->type == CT_WHILE)) && !chunk_is_token(next, CT_PAREN_OPEN)) { set_chunk_type(pc, CT_WORD); } if ((pc->type == CT_DO) && (chunk_is_token(prev, CT_MINUS) || chunk_is_token(next, CT_SQUARE_CLOSE))) { set_chunk_type(pc, CT_WORD); } } /* Another hack to clean up more keyword abuse */ if ((pc->type == CT_CLASS) && (chunk_is_token(prev, CT_DOT) || chunk_is_token(next, CT_DOT))) { set_chunk_type(pc, CT_WORD); } /* Detect Objective C class name */ if ((pc->type == CT_OC_IMPL) || (pc->type == CT_OC_INTF) || (pc->type == CT_OC_PROTOCOL)) { if (next->type != CT_PAREN_OPEN) { set_chunk_type(next, CT_OC_CLASS); } set_chunk_parent(next, pc->type); tmp = chunk_get_next_ncnl(next); if (tmp != NULL) { chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); } tmp = chunk_get_next_type(pc, CT_OC_END, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->type); } } if (pc->type == CT_OC_INTF) { tmp = chunk_get_next_ncnl(pc, CNAV_PREPROC); while ((tmp != NULL) && (tmp->type != CT_OC_END)) { if (get_token_pattern_class(tmp->type) != PATCLS_NONE) { LOG_FMT(LOBJCWORD, "@interface %d:%d change '%s' (%s) to CT_WORD\n", pc->orig_line, pc->orig_col, tmp->text(), get_token_name(tmp->type)); set_chunk_type(tmp, CT_WORD); } tmp = chunk_get_next_ncnl(tmp, CNAV_PREPROC); } } /* Detect Objective-C categories and class extensions */ /* @interface ClassName (CategoryName) */ /* @implementation ClassName (CategoryName) */ /* @interface ClassName () */ /* @implementation ClassName () */ if (((pc->parent_type == CT_OC_IMPL) || (pc->parent_type == CT_OC_INTF) || (pc->type == CT_OC_CLASS)) && (next->type == CT_PAREN_OPEN)) { set_chunk_parent(next, pc->parent_type); tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->next != NULL)) { if (tmp->type == CT_PAREN_CLOSE) { //set_chunk_type(tmp, CT_OC_CLASS_EXT); set_chunk_parent(tmp, pc->parent_type); } else { set_chunk_type(tmp, CT_OC_CATEGORY); set_chunk_parent(tmp, pc->parent_type); } } tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->parent_type); } } /* Detect Objective C @property * @property NSString *stringProperty; * @property(nonatomic, retain) NSMutableDictionary *shareWith; */ if (pc->type == CT_OC_PROPERTY) { if (next->type != CT_PAREN_OPEN) { chunk_flags_set(next, PCF_STMT_START | PCF_EXPR_START); } else { set_chunk_parent(next, pc->type); tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->type); tmp = chunk_get_next_ncnl(tmp); if (tmp != NULL) { chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); tmp = chunk_get_next_type(tmp, CT_SEMICOLON, pc->level); if (tmp != NULL) { set_chunk_parent(tmp, pc->type); } } } } } /* Detect Objective C @selector * @selector(msgNameWithNoArg) * @selector(msgNameWith1Arg:) * @selector(msgNameWith2Args:arg2Name:) */ if ((pc->type == CT_OC_SEL) && (next->type == CT_PAREN_OPEN)) { set_chunk_parent(next, pc->type); tmp = chunk_get_next(next); if (tmp != NULL) { set_chunk_type(tmp, CT_OC_SEL_NAME); set_chunk_parent(tmp, pc->type); while ((tmp = chunk_get_next_ncnl(tmp)) != NULL) { if (tmp->type == CT_PAREN_CLOSE) { set_chunk_parent(tmp, CT_OC_SEL); break; } set_chunk_type(tmp, CT_OC_SEL_NAME); set_chunk_parent(tmp, pc->type); } } } /* Handle special preprocessor junk */ if (pc->type == CT_PREPROC) { set_chunk_parent(pc, next->type); } /* Detect "pragma region" and "pragma endregion" */ if ((pc->type == CT_PP_PRAGMA) && (next->type == CT_PREPROC_BODY)) { if ((memcmp(next->str, "region", 6) == 0) || (memcmp(next->str, "endregion", 9) == 0)) { set_chunk_type(pc, (*next->str == 'r') ? CT_PP_REGION : CT_PP_ENDREGION); set_chunk_parent(prev, pc->type); } } /* Check for C# nullable types '?' is in next */ if ((cpd.lang_flags & LANG_CS) && (next->type == CT_QUESTION) && (next->orig_col == (pc->orig_col + pc->len()))) { tmp = chunk_get_next_ncnl(next); if (tmp != NULL) { bool doit = ((tmp->type == CT_PAREN_CLOSE) || (tmp->type == CT_ANGLE_CLOSE)); if (tmp->type == CT_WORD) { tmp2 = chunk_get_next_ncnl(tmp); if ((tmp2 != NULL) && ((tmp2->type == CT_SEMICOLON) || (tmp2->type == CT_ASSIGN) || (tmp2->type == CT_COMMA) || (tmp2->type == CT_BRACE_OPEN))) { doit = true; } } if (doit) { pc->str += next->str; pc->orig_col_end = next->orig_col_end; chunk_del(next); next = tmp; } } } /* Change 'default(' into a sizeof-like statement */ if ((cpd.lang_flags & LANG_CS) && (pc->type == CT_DEFAULT) && (next->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_SIZEOF); } if ((pc->type == CT_UNSAFE) && (next->type != CT_BRACE_OPEN)) { set_chunk_type(pc, CT_QUALIFIER); } if (((pc->type == CT_USING) || ((pc->type == CT_TRY) && (cpd.lang_flags & LANG_JAVA))) && (next->type == CT_PAREN_OPEN)) { set_chunk_type(pc, CT_USING_STMT); } /* Add minimal support for C++0x rvalue references */ if ((pc->type == CT_BOOL) && chunk_is_str(pc, "&&", 2)) { if (prev->type == CT_TYPE) { set_chunk_type(pc, CT_BYREF); } } /* HACK: treat try followed by a colon as a qualifier to handle this: * A::A(int) try : B() { } catch (...) { } */ if ((pc->type == CT_TRY) && chunk_is_str(pc, "try", 3) && (next != NULL) && (next->type == CT_COLON)) { set_chunk_type(pc, CT_QUALIFIER); } /* If Java's 'synchronized' is in a method declaration, it should be * a qualifier. */ if ((cpd.lang_flags & LANG_JAVA) && (pc->type == CT_SYNCHRONIZED) && (next->type != CT_PAREN_OPEN)) { set_chunk_type(pc, CT_QUALIFIER); } // guy 2015-11-05 // change CT_DC_MEMBER + CT_FOR into CT_DC_MEMBER + CT_FUNC_CALL if ((pc->type == CT_FOR) && (pc->prev->type == CT_DC_MEMBER)) { set_chunk_type(pc, CT_FUNC_CALL); } /* TODO: determine other stuff here */ prev = pc; pc = next; next = chunk_get_next_ncnl(pc); } } // tokenize_cleanup
type_t *type_new_pointer(type_t *ref, attr_list_t *attrs) { type_t *t = make_type(pointer_default, ref); t->attrs = attrs; return t; }
Expression *expression_binary(int op, Expression *first, Expression *second) { Tac *temp; Tac *result; Symbol *temp_variable; debug("Binary Op: %d First: %s Type: %d Second: %s Type: %d", op, first->result->name, first->result->type->code, second->result->name, second->result->type->code); //Constant folding //if ((first->result->type->code == TYPE_NATURAL) && (second->result->type->code == TYPE_NATURAL) // && ((op == TAC_ADD) || (op == TAC_SUBTRACT) || (op == TAC_MULTIPLY) || (op == TAC_DIVIDE))) if ((first->result->type->code == TYPE_NATURAL) && (second->result->type->code == TYPE_NATURAL)) { //Fix 5-19-2011 //For same reasons in expression_unary //Remove both symbols from symbol table //symboltable_delete(constantTable, first->result); //symboltable_delete(constantTable, second->result); Symbol* fold_result = make_symbol(); fold_result->type = make_type(TYPE_NATURAL); fold_result->name = (char*)safe_malloc(sizeof(char) * 12); switch (op) { case TAC_ADD: fold_result->value.integer = first->result->value.integer + second->result->value.integer; break; case TAC_SUBTRACT: fold_result->value.integer = first->result->value.integer - second->result->value.integer; break; case TAC_MULTIPLY: fold_result->value.integer = first->result->value.integer * second->result->value.integer; break; case TAC_DIVIDE: fold_result->value.integer = first->result->value.integer / second->result->value.integer; break; case TAC_GT: fold_result->value.integer = first->result->value.integer > second->result->value.integer; break; case TAC_LT: fold_result->value.integer = first->result->value.integer < second->result->value.integer; break; case TAC_GTE: fold_result->value.integer = first->result->value.integer >= second->result->value.integer; break; case TAC_LTE: fold_result->value.integer = first->result->value.integer <= second->result->value.integer; break; case TAC_EQUAL: fold_result->value.integer = first->result->value.integer == second->result->value.integer; break; case TAC_NOTEQUAL: fold_result->value.integer = first->result->value.integer != second->result->value.integer; break; default: die("Unrecognized Binary Operation: %s", op); break; } //Rewire expression first->result = fold_result; //Now fix the symbol name sprintf(first->result->name, "%d", first->result->value.integer); //Insert the symbol back symboltable_insert(constantTable, first->result); //Give back some resources //free(second->result); free(second); debug("Folded constant %d", first->result->value.integer); return first; } //Create temp temp_variable = make_temp(); temp_variable->type = make_type(TYPE_VARIABLE);//Generic variable type temp = make_tac(TAC_VARIABLE, temp_variable, NULL, NULL); temp->prev = join_tac(first->tac, second->tac); //Call operator result = make_tac(op, temp->result, first->result, second->result); result->prev = temp; //Rewire the expression first->result = temp->result; first->tac = result; //Cleanup free(second); return first; }
void tokenize_cleanup(void) { chunk_t *pc = chunk_get_head(); chunk_t *prev = NULL; chunk_t *next; chunk_t *tmp; chunk_t *tmp2; bool in_type_cast = false; pc = chunk_get_head(); next = chunk_get_next_ncnl(pc); while ((pc != NULL) && (next != NULL)) { /* Change '[' + ']' into '[]' */ if ((pc->type == CT_SQUARE_OPEN) && (next->type == CT_SQUARE_CLOSE)) { pc->type = CT_TSQUARE; pc->str = "[]"; pc->len = 2; chunk_del(next); pc->orig_col_end += 1; next = chunk_get_next_ncnl(pc); } if ((pc->type == CT_DOT) && ((cpd.lang_flags & LANG_ALLC) != 0)) { pc->type = CT_MEMBER; } /* Determine the version stuff (D only) */ if (pc->type == CT_VERSION) { if (next->type == CT_PAREN_OPEN) { pc->type = CT_IF; } else { if (next->type != CT_ASSIGN) { LOG_FMT(LERR, "%s:%d %s: version: Unexpected token %s\n", cpd.filename, pc->orig_line, __func__, get_token_name(next->type)); cpd.error_count++; } pc->type = CT_WORD; } } /** * Change CT_BASE before CT_PAREN_OPEN to CT_WORD. * public myclass() : base() { * } */ if ((pc->type == CT_BASE) && (next->type == CT_PAREN_OPEN)) { pc->type = CT_WORD; } /** * Change CT_WORD after CT_ENUM, CT_UNION, or CT_STRUCT to CT_TYPE * Change CT_WORD before CT_WORD to CT_TYPE */ if (next->type == CT_WORD) { if ((pc->type == CT_ENUM) || (pc->type == CT_UNION) || (pc->type == CT_STRUCT)) { next->type = CT_TYPE; } if (pc->type == CT_WORD) { pc->type = CT_TYPE; } } /* change extern to qualifier if extern isn't followed by a string or * an open paren */ if (pc->type == CT_EXTERN) { if (next->type == CT_STRING) { /* Probably 'extern "C"' */ } else if (next->type == CT_PAREN_OPEN) { /* Probably 'extern (C)' */ } else { /* Something else followed by a open brace */ tmp = chunk_get_next_ncnl(next); if ((tmp != NULL) || (tmp->type != CT_BRACE_OPEN)) { pc->type = CT_QUALIFIER; } } } /** * Change CT_STAR to CT_PTR_TYPE if preceded by CT_TYPE, * CT_QUALIFIER, or CT_PTR_TYPE. */ if ((next->type == CT_STAR) && ((pc->type == CT_TYPE) || (pc->type == CT_QUALIFIER) || (pc->type == CT_PTR_TYPE))) { next->type = CT_PTR_TYPE; } if ((pc->type == CT_TYPE_CAST) && (next->type == CT_ANGLE_OPEN)) { next->parent_type = CT_TYPE_CAST; in_type_cast = true; } /** * Change angle open/close to CT_COMPARE, if not a template thingy */ if ((pc->type == CT_ANGLE_OPEN) && (pc->parent_type != CT_TYPE_CAST)) { check_template(pc); } if ((pc->type == CT_ANGLE_CLOSE) && (pc->parent_type != CT_TEMPLATE)) { if (in_type_cast) { in_type_cast = false; pc->parent_type = CT_TYPE_CAST; } else { next = handle_double_angle_close(pc); } } if ((cpd.lang_flags & LANG_D) != 0) { /* Check for the D string concat symbol '~' */ if ((pc->type == CT_INV) && ((prev->type == CT_STRING) || (prev->type == CT_WORD) || (next->type == CT_STRING))) { pc->type = CT_CONCAT; } /* Check for the D template symbol '!' (word + '!' + word or '(') */ if ((pc->type == CT_NOT) && (prev->type == CT_WORD) && ((next->type == CT_PAREN_OPEN) || (next->type == CT_WORD) || (next->type == CT_TYPE))) { pc->type = CT_D_TEMPLATE; } /* handle "version(unittest) { }" vs "unittest { }" */ if ((pc->type == CT_UNITTEST) && (prev->type == CT_PAREN_OPEN)) { pc->type = CT_WORD; } } if ((cpd.lang_flags & LANG_CPP) != 0) { /* Change Word before '::' into a type */ if ((pc->type == CT_WORD) && (next->type == CT_DC_MEMBER)) { pc->type = CT_TYPE; } } /* Change get/set to CT_WORD if not followed by a brace open */ if ((pc->type == CT_GETSET) && (next->type != CT_BRACE_OPEN)) { if ((next->type == CT_SEMICOLON) && ((prev->type == CT_BRACE_CLOSE) || (prev->type == CT_BRACE_OPEN) || (prev->type == CT_SEMICOLON))) { pc->type = CT_GETSET_EMPTY; next->parent_type = CT_GETSET; } else { pc->type = CT_WORD; } } /* Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL * Usually the next item is part of the operator. * In a few cases the next few tokens are part of it: * operator + - common case * operator >> - need to combine '>' and '>' * operator () * operator [] - already converted to TSQUARE * operator new [] * operator delete [] * operator const char * * operator const B& * operator std::allocator<U> * * In all cases except the last, this will put the entire operator value * in one chunk. */ if (pc->type == CT_OPERATOR) { /* Handle special case of () operator -- [] already handled */ if (next->type == CT_PAREN_OPEN) { tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->type == CT_PAREN_CLOSE)) { next->str = "()"; next->len = 2; next->type = CT_OPERATOR_VAL; chunk_del(tmp); next->orig_col_end += 1; } } else if ((next->type == CT_ANGLE_CLOSE) && (memcmp(next->str, ">>", 2) == 0)) { next->len++; next->orig_col_end++; next->type = CT_OPERATOR_VAL; chunk_del(chunk_get_next(next)); } else if (next->flags & PCF_PUNCTUATOR) { next->type = CT_OPERATOR_VAL; } else { next->type = CT_TYPE; /* Replace next with a collection of all tokens that are part of * the type. */ char opbuf[256]; int len; len = snprintf(opbuf, sizeof(opbuf), "%.*s", next->len, next->str); tmp2 = next; while ((tmp = chunk_get_next(tmp2)) != NULL) { if ((tmp->type != CT_WORD) && (tmp->type != CT_TYPE) && (tmp->type != CT_QUALIFIER) && (tmp->type != CT_STAR) && (tmp->type != CT_AMP) && (tmp->type != CT_TSQUARE)) { break; } /* Change tmp into a type so that space_needed() works right */ make_type(tmp); len += snprintf(opbuf + len, sizeof(opbuf) - len, "%s%.*s", space_needed(tmp2, tmp) ? " " : "", tmp->len, tmp->str); tmp2 = tmp; } while ((tmp2 = chunk_get_next(next)) != tmp) { chunk_del(tmp2); } next->str = strdup(opbuf); next->len = len; next->flags |= PCF_OWN_STR; next->type = CT_OPERATOR_VAL; next->orig_col_end = next->orig_col + next->len; } next->parent_type = CT_OPERATOR; LOG_FMT(LOPERATOR, "%s: %d:%d operator '%.*s'\n", __func__, pc->orig_line, pc->orig_col, next->len, next->str); } /* Change private, public, protected into either a qualifier or label */ if (pc->type == CT_PRIVATE) { /* Handle Qt slots - maybe should just check for a CT_WORD? */ if (chunk_is_str(next, "slots", 5) || chunk_is_str(next, "Q_SLOTS", 7)) { tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->type == CT_COLON)) { next = tmp; } } if (next->type == CT_COLON) { next->type = CT_PRIVATE_COLON; if ((tmp = chunk_get_next_ncnl(next)) != NULL) { tmp->flags |= PCF_STMT_START | PCF_EXPR_START; } } else { pc->type = (chunk_is_str(pc, "signals", 7) || chunk_is_str(pc, "Q_SIGNALS", 9)) ? CT_WORD : CT_QUALIFIER; } } /* Look for <newline> 'EXEC' 'SQL' */ if (chunk_is_str(pc, "EXEC", 4) && chunk_is_str(next, "SQL", 3)) { tmp = chunk_get_prev(pc); if (chunk_is_newline(tmp)) { tmp = chunk_get_next(next); if (chunk_is_str_case(tmp, "BEGIN", 5)) { pc->type = CT_SQL_BEGIN; } else if (chunk_is_str_case(tmp, "END", 3)) { pc->type = CT_SQL_END; } else { pc->type = CT_SQL_EXEC; } /* Change words into CT_SQL_WORD until CT_SEMICOLON */ while (tmp != NULL) { if (tmp->type == CT_SEMICOLON) { break; } if ((tmp->len > 0) && isalpha(*tmp->str)) { tmp->type = CT_SQL_WORD; } tmp = chunk_get_next_ncnl(tmp); } } } /* Detect Objective C class name */ if ((pc->type == CT_OC_IMPL) || (pc->type == CT_OC_INTF) || (pc->type == CT_OC_PROTOCOL)) { if (next->type != CT_PAREN_OPEN) { next->type = CT_OC_CLASS; } next->parent_type = pc->type; tmp = chunk_get_next_ncnl(next); if (tmp != NULL) { tmp->flags |= PCF_STMT_START | PCF_EXPR_START; } tmp = chunk_get_next_type(pc, CT_OC_END, pc->level); if (tmp != NULL) { tmp->parent_type = pc->type; } } /* Detect Objective-C categories and class extensions */ /* @interface ClassName (CategoryName) */ /* @implementation ClassName (CategoryName) */ /* @interface ClassName () */ /* @implementation ClassName () */ if (((pc->parent_type == CT_OC_IMPL) || (pc->parent_type == CT_OC_INTF) || (pc->type == CT_OC_CLASS)) && (next->type == CT_PAREN_OPEN)) { next->parent_type = pc->parent_type; tmp = chunk_get_next(next); if ((tmp != NULL) && (tmp->next != NULL)) { if (tmp->type == CT_PAREN_CLOSE) { //tmp->type = CT_OC_CLASS_EXT; tmp->parent_type = pc->parent_type; } else { tmp->type = CT_OC_CATEGORY; tmp->parent_type = pc->parent_type; } } tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); if (tmp != NULL) { tmp->parent_type = pc->parent_type; } } /** * Objective C @dynamic and @synthesize * @dynamic xxx, yyy; * @synthesize xxx, yyy; * Just find the semicolon and mark it. */ if (pc->type == CT_OC_DYNAMIC) { tmp = chunk_get_next_type(pc, CT_SEMICOLON, pc->level); if (tmp != NULL) { tmp->parent_type = pc->type; } } /* Detect Objective C @property * @property NSString *stringProperty; * @property(nonatomic, retain) NSMutableDictionary *shareWith; */ if (pc->type == CT_OC_PROPERTY) { if (next->type != CT_PAREN_OPEN) { next->flags |= PCF_STMT_START | PCF_EXPR_START; } else { next->parent_type = pc->type; tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); if (tmp != NULL) { tmp->parent_type = pc->type; tmp = chunk_get_next_ncnl(tmp); if (tmp != NULL) { tmp->flags |= PCF_STMT_START | PCF_EXPR_START; tmp = chunk_get_next_type(tmp, CT_SEMICOLON, pc->level); if (tmp != NULL) { tmp->parent_type = pc->type; } } } } } /* Detect Objective C @selector * @selector(msgNameWithNoArg) * @selector(msgNameWith1Arg:) * @selector(msgNameWith2Args:arg2Name:) */ if ((pc->type == CT_OC_SEL) && (next->type == CT_PAREN_OPEN)) { next->parent_type = pc->type; tmp = chunk_get_next(next); if (tmp != NULL) { tmp->type = CT_OC_SEL_NAME; tmp->parent_type = pc->type; while ((tmp = chunk_get_next_ncnl(tmp)) != NULL) { if (tmp->type == CT_PAREN_CLOSE) { tmp->parent_type = CT_OC_SEL; break; } tmp->type = CT_OC_SEL_NAME; tmp->parent_type = pc->type; } } } /* Mark Objective-C blocks (aka lambdas or closures) * The syntax and usage is exactly like C function pointers with two exceptions: * Instead of an asterisk they have a caret as pointer symbol. * In method declarations which take a block as parameter, there can be anonymous blocks, e.g.: (^) * 1. block literal: ^{ ... }; * 2. block declaration: return_t (^name) (int arg1, int arg2, ...) NB: return_t is optional and name can be optional if found as param in a method declaration. * 3. block expression: ^ return_t (int arg) { ... }; NB: return_t is optional * * See http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks for more info... */ if ((cpd.lang_flags & LANG_OC) && (pc->type == CT_ARITH) && (chunk_is_str(pc, "^", 1)) && (prev->type != CT_NUMBER) && (prev->type != CT_NUMBER_FP)) { /* mark objc blocks caret so that we can process it later*/ pc->type = CT_OC_BLOCK_CARET; if (prev->type == CT_PAREN_OPEN) { /* block declaration */ pc->parent_type = CT_OC_BLOCK_TYPE; } else if ((next->type == CT_PAREN_OPEN) || (next->type == CT_BRACE_OPEN)) { /* block expression without return type */ /* block literal */ pc->parent_type = CT_OC_BLOCK_EXPR; } else { /* block expression with return type (seldomly used) */ if (prev->type == CT_ASSIGN) { /* shortcut to spare the peeking below * the XOR operator wouldn't be used directly * after an assign all by itself */ pc->parent_type = CT_OC_BLOCK_EXPR; } else { /* this ones tricky because we don't know how many * stars the return type has - if there even is one */ tmp = pc; while ((tmp = chunk_get_next(tmp)) != NULL) { /* we just peek ahead and see if the line contains * an open brace somewhere. * FIXME: this check needs to be more thorough. */ if (tmp->type == CT_BRACE_OPEN) { pc->parent_type = CT_OC_BLOCK_EXPR; break; } } } } } /* Handle special preprocessor junk */ if (pc->type == CT_PREPROC) { pc->parent_type = next->type; } /* Detect "pragma region" and "pragma endregion" */ if ((pc->type == CT_PP_PRAGMA) && (next->type == CT_PREPROC_BODY)) { if ((memcmp(next->str, "region", 6) == 0) || (memcmp(next->str, "endregion", 9) == 0)) { pc->type = (*next->str == 'r') ? CT_PP_REGION : CT_PP_ENDREGION; prev->parent_type = pc->type; } } /* Check for C# nullable types '?' is in next */ if ((cpd.lang_flags & LANG_CS) && (next->type == CT_QUESTION) && (next->orig_col == (pc->orig_col + pc->len))) { tmp = chunk_get_next_ncnl(next); if (tmp != NULL) { bool doit = ((tmp->type == CT_PAREN_CLOSE) || (tmp->type == CT_ANGLE_CLOSE)); if (tmp->type == CT_WORD) { tmp2 = chunk_get_next_ncnl(tmp); if ((tmp2 != NULL) && ((tmp2->type == CT_SEMICOLON) || (tmp2->type == CT_ASSIGN) || (tmp2->type == CT_COMMA))) { doit = true; } } if (doit) { pc->len++; chunk_del(next); next = tmp; } } } /* Change 'default(' into a sizeof-like statement */ if ((cpd.lang_flags & LANG_CS) && (pc->type == CT_DEFAULT) && (next->type == CT_PAREN_OPEN)) { pc->type = CT_SIZEOF; } if ((pc->type == CT_UNSAFE) && (next->type != CT_BRACE_OPEN)) { pc->type = CT_QUALIFIER; } if ((pc->type == CT_USING) && (next->type == CT_PAREN_OPEN)) { pc->type = CT_USING_STMT; } /* Add minimal support for C++0x rvalue references */ if ((pc->type == CT_BOOL) && chunk_is_str(pc, "&&", 2)) { if (prev->type == CT_TYPE) { pc->type = CT_BYREF; } } /* HACK: treat try followed by a colon as a qualifier to handle this: * A::A(int) try : B() { } catch (...) { } */ if ((pc->type == CT_TRY) && chunk_is_str(pc, "try", 3) && (next != NULL) && (next->type == CT_COLON)) { pc->type = CT_QUALIFIER; } /* TODO: determine other stuff here */ prev = pc; pc = next; next = chunk_get_next_ncnl(pc); } }
void init_builtin_types(void) { make_type("nil"); make_type("unspecific"); make_type("boolean"); make_type("integer"); make_type("string"); make_type("symbol"); make_type("pair"); make_type("procedure"); make_type("code"); make_type("code-pointer"); make_type("environment"); make_type("continuation"); }
/** Makes an empty tuple */ static type make(bool variadic = false) { return make(nd::empty(0, make_type()), variadic); }
/** * If there is nothing but CT_WORD and CT_MEMBER, then it's probably a * template thingy. Otherwise, it's likely a comparison. */ static void check_template(chunk_t *start) { chunk_t *pc; chunk_t *end; chunk_t *prev; chunk_t *next; bool in_if = false; LOG_FMT(LTEMPL, "%s: Line %d, col %d:", __func__, start->orig_line, start->orig_col); prev = chunk_get_prev_ncnl(start, CNAV_PREPROC); if (prev == NULL) { return; } if (prev->type == CT_TEMPLATE) { LOG_FMT(LTEMPL, " CT_TEMPLATE:"); /* We have: "template< ... >", which is a template declaration */ int level = 1; for (pc = chunk_get_next_ncnl(start, CNAV_PREPROC); pc != NULL; pc = chunk_get_next_ncnl(pc, CNAV_PREPROC)) { LOG_FMT(LTEMPL, " [%s,%d]", get_token_name(pc->type), level); if (chunk_is_str(pc, "<", 1)) { level++; } else if (chunk_is_str(pc, ">", 1)) { level--; if (level == 0) { break; } } } end = pc; } else { /* We may have something like "a< ... >", which is a template use * '...' may consist of anything except braces {}, a semicolon, and * unbalanced parens. * if we are inside an 'if' statement and hit a CT_BOOL, then it isn't a * template. */ /* A template requires a word/type right before the open angle */ if ((prev->type != CT_WORD) && (prev->type != CT_TYPE) && (prev->type != CT_OPERATOR_VAL) && (prev->parent_type != CT_OPERATOR)) { LOG_FMT(LTEMPL, " - after %s + ( - Not a template\n", get_token_name(prev->type)); start->type = CT_COMPARE; return; } LOG_FMT(LTEMPL, " - prev %s -", get_token_name(prev->type)); /* Scan back and make sure we aren't inside square parens */ pc = start; while ((pc = chunk_get_prev_ncnl(pc, CNAV_PREPROC)) != NULL) { if ((pc->type == CT_SEMICOLON) || (pc->type == CT_BRACE_OPEN) || (pc->type == CT_BRACE_CLOSE) || (pc->type == CT_SQUARE_CLOSE) || (pc->type == CT_SEMICOLON)) { break; } if (pc->type == CT_IF) { in_if = true; break; } if (pc->type == CT_SQUARE_OPEN) { LOG_FMT(LTEMPL, " - Not a template: after a square open\n"); start->type = CT_COMPARE; return; } } /* Scan forward to the angle close * If we have a comparison in there, then it can't be a template. */ c_token_t tokens[16]; int num_tokens = 1; tokens[0] = CT_ANGLE_OPEN; for (pc = chunk_get_next_ncnl(start, CNAV_PREPROC); pc != NULL; pc = chunk_get_next_ncnl(pc, CNAV_PREPROC)) { LOG_FMT(LTEMPL, " [%s,%d]", get_token_name(pc->type), num_tokens); if (chunk_is_str(pc, "<", 1)) { tokens[num_tokens++] = CT_ANGLE_OPEN; } else if (chunk_is_str(pc, ">", 1)) { if (--num_tokens <= 0) { break; } if (tokens[num_tokens] != CT_ANGLE_OPEN) { /* unbalanced parens */ break; } } else if (in_if && ((pc->type == CT_BOOL) || (pc->type == CT_COMPARE))) { break; } else if ((pc->type == CT_BRACE_OPEN) || (pc->type == CT_BRACE_CLOSE) || (pc->type == CT_SEMICOLON)) { break; } else if (pc->type == CT_PAREN_OPEN) { if (num_tokens >= (int)(ARRAY_SIZE(tokens) - 1)) { break; } tokens[num_tokens++] = pc->type; } else if (pc->type == CT_PAREN_CLOSE) { num_tokens--; if (tokens[num_tokens] != (pc->type - 1)) { /* unbalanced parens */ break; } } } end = pc; } if ((end != NULL) && (end->type == CT_ANGLE_CLOSE)) { pc = chunk_get_next_ncnl(end, CNAV_PREPROC); if ((pc != NULL) && (pc->type != CT_NUMBER)) { LOG_FMT(LTEMPL, " - Template Detected\n"); start->parent_type = CT_TEMPLATE; pc = start; while (pc != end) { next = chunk_get_next_ncnl(pc, CNAV_PREPROC); pc->flags |= PCF_IN_TEMPLATE; if (next->type != CT_PAREN_OPEN) { make_type(pc); } pc = next; } end->parent_type = CT_TEMPLATE; end->flags |= PCF_IN_TEMPLATE; return; } } LOG_FMT(LTEMPL, " - Not a template: end = %s\n", (end != NULL) ? get_token_name(end->type) : "<null>"); start->type = CT_COMPARE; }
int main(int argc, char * argv[]) { int i; int which; if (argc != 2) exit(0); if (strcmp(argv[1], "-table") == 0) { which = gen_table; } else if (strcmp(argv[1], "-dhcptag") == 0) { which = gen_tag; } else if (strcmp(argv[1], "-dhcptype") == 0) { which = gen_type; } else if (strcmp(argv[1], "-mandoc") == 0) { which = gen_mandoc; } else exit(1); switch (which) { case gen_tag: print_copyright_header(argv[0], argv[1]); printf("#ifndef _S_DHCP_TAG\n" "#define _S_DHCP_TAG\n\n" "#include <stdint.h>\n\n" "enum {"); for (i = 0; option[i].code != END; i++) { if (option[i].code == COMMENT) printf("\n %s\n", option[i].type); else { printf(" %-35s\t= %d,\n", make_option(option[i].name), option[i].code); } } printf("\n /* undefined */\n"); for (i = 0; i <= 127; i++) { if (find_option(i) == -1) { char buf[32]; snprintf(buf, sizeof(buf), "%d", i); printf(" %-35s\t= %d,\n", make_option(buf), i); } } printf("\n /* site-specific 128..254 */\n"); for (i = 128; i <= 254; i++) { char buf[32]; snprintf(buf, sizeof(buf), "%d", i); printf(" %-35s\t= %d,\n", make_option(buf), i); } printf("};\n"); printf("\n/* defined tags */\n"); for (i = 0; option[i].code != END; i++) { if (option[i].code != COMMENT) { printf("#define %-35s\t\"%s\"\n", make_option_define(option[i].name), option[i].name); } } printf("\n/* undefined */\n"); for (i = 0; i <= 127; i++) { if (find_option(i) == -1) { char buf[32]; snprintf(buf, sizeof(buf), "%d", i); printf("#define %-35s\t\"%s\"\n", make_option_define(buf), buf); } } printf("\n/* site-specific 128..254 */\n"); for (i = 128; i <= 254; i++) { char buf[32]; snprintf(buf, sizeof(buf), "%d", i); printf("#define %-35s\t\"%s\"\n", make_option_define(buf), buf); } printf("#endif /* _S_DHCP_TAG */\n"); break; case gen_type: print_copyright_header(argv[0], argv[1]); printf("#ifndef _S_DHCP_TYPE\n" "#define _S_DHCP_TYPE\n"); printf("\nenum {\n"); for (i = 0; types[i].name; i++) { if (i == 0) { printf(" %-20s\t = %d,\n", make_type("first"), i); printf(" %-20s\t =", make_type(types[i].name)); printf(" %s,\n", make_type("first")); } else printf(" %-20s\t = %d,\n", make_type(types[i].name), i); } printf(" %-20s\t =", make_type("last")); printf(" %s,\n", make_type(types[i ? (i - 1) : 0].name)); printf("};\n\ntypedef uint32_t dhcptype_t;\n\n"); printf("typedef struct {\n" " dhcptype_t type;\n" " const char * name;\n" "} dhcptag_info_t;\n\n"); printf("typedef struct {\n" " int size; /* in bytes */\n" " int multiple_of; /* type of element */\n" " const char * name;\n" " int string_list;\n" "} dhcptype_info_t;\n\n"); printf("#endif /* _S_DHCP_TYPE */\n"); break; case gen_table: print_copyright_header(argv[0], argv[1]); printf("#ifndef _S_DHCP_PARSE_TABLE\n" "#define _S_DHCP_PARSE_TABLE\n"); printf("static const dhcptag_info_t dhcptag_info_table[] = {\n"); for (i = 0; i <= LAST_TAG; i++) { int opt; opt = find_option(i); if (opt < 0) { char buf[128]; snprintf(buf, sizeof(buf), "option_%d", i); printf(" /* %3d */ { %-20s, \"%s\" },\n", i, make_type("opaque"), buf); } else printf(" /* %3d */ { %-20s, \"%s\" },\n", i, make_type(option[opt].type), option[opt].name); } printf("};\n\n"); printf("static const dhcptype_info_t dhcptype_info_table[] = {\n"); for (i = 0; types[i].name; i++) { const char * type = types[i].multiple_of; printf(" /* %2d */ { %d, %s, \"%s\", %d },\n", i, types[i].size, make_type((type != 0) ? type : "none"), types[i].name, types[i].string_list); } printf("};\n"); printf("#endif /* _S_DHCP_PARSE_TABLE */\n"); break; case gen_mandoc: for (i = 1; i < LAST_TAG; i++) { int opt; opt = find_option(i); if (opt < 0) { continue; } printf(".It Sy dhcp_%s\n", option[opt].name); printf("Option code %d, type is %s.\n", i, option[opt].type); } break; default: break; } exit(0); return (0); }