void main() { printf( "%d\n", keyword_lookup( "case" ) ); printf( "%d\n", keyword_lookup( "crigger" ) ); printf( "%d\n", keyword_lookup( "auto" ) ); }
int mail_index_sync_keywords(struct mail_index_sync_map_ctx *ctx, const struct mail_transaction_header *hdr, const struct mail_transaction_keyword_update *rec) { struct mail_index_view *view = ctx->view; const char *keyword_name; const struct mail_index_ext *ext; const uint32_t *uid, *end; uint32_t seqset_offset, ext_map_idx; unsigned int keyword_idx; int ret; i_assert(rec->name_size > 0); seqset_offset = sizeof(*rec) + rec->name_size; if ((seqset_offset % 4) != 0) seqset_offset += 4 - (seqset_offset % 4); i_assert(seqset_offset < hdr->size); uid = CONST_PTR_OFFSET(rec, seqset_offset); end = CONST_PTR_OFFSET(rec, hdr->size); keyword_name = t_strndup(rec + 1, rec->name_size); if (!keyword_lookup(ctx, keyword_name, &keyword_idx)) keywords_header_add(ctx, keyword_name, &keyword_idx); /* if the keyword wasn't found, the "keywords" extension was created. if it was found, the record size should already be correct, but in case it isn't just fix it ourself. */ if (!mail_index_map_lookup_ext(view->map, MAIL_INDEX_EXT_KEYWORDS, &ext_map_idx)) i_unreached(); ext = array_idx(&view->map->extensions, ext_map_idx); if (keyword_idx / CHAR_BIT >= ext->record_size) { if (rec->modify_type == MODIFY_REMOVE) { /* nothing to do */ return 1; } /* grow the record size */ keywords_ext_register(ctx, ext_map_idx, ext->reset_id, ext->hdr_size, array_count(&view->map->keyword_idx_map)); if (!mail_index_map_lookup_ext(view->map, MAIL_INDEX_EXT_KEYWORDS, &ext_map_idx)) i_unreached(); ext = array_idx(&view->map->extensions, ext_map_idx); } while (uid+2 <= end) { ret = keywords_update_records(ctx, ext, keyword_idx, rec->modify_type, uid[0], uid[1]); if (ret <= 0) return ret; uid += 2; } return 1; }
/* --------------------------------------------------------------------- * CMD_EVAL * This monster evaluates an if/or/and statement * There are five kinds of statement: * 1) keyword and value (no $-code) if random 30 * 2) keyword, comparison and value if people > 2 * 3) keyword and actor if isnpc $n * 4) keyword, actor and value if carries $n sword * 5) keyword, actor, comparison and value if level $n >= 10 * *---------------------------------------------------------------------- */ int cmd_eval( sh_int vnum, char *line, int check, CHAR_DATA *mob, CHAR_DATA *ch, const void *arg1, const void *arg2, CHAR_DATA *rch ) { CHAR_DATA *lval_char = mob; CHAR_DATA *vch = (CHAR_DATA *) arg2; OBJ_DATA *obj1 = (OBJ_DATA *) arg1; OBJ_DATA *obj2 = (OBJ_DATA *) arg2; OBJ_DATA *lval_obj = NULL; char *original, buf[MAX_INPUT_LENGTH], code; int lval = 0, oper = 0, rval = -1; original = line; line = one_argument( line, buf ); if ( buf[0] == '\0' || mob == NULL ) return FALSE; /* * If this mobile has no target, let's assume our victim is the one */ if ( mob->mprog_target == NULL ) mob->mprog_target = ch; switch ( check ) { /* * Case 1: keyword and value */ case CHK_RAND: return( atoi( buf ) < number_percent() ); case CHK_MOBHERE: if ( is_number( buf ) ) return( get_mob_vnum_room( mob, atoi(buf) ) ); else return( (bool) (get_char_room( mob, buf) != NULL) ); case CHK_OBJHERE: if ( is_number( buf ) ) return( get_obj_vnum_room( mob, atoi(buf) ) ); else return( (bool) (get_obj_here( mob, buf) != NULL) ); case CHK_MOBEXISTS: return( (bool) (get_char_world( mob, buf) != NULL) ); case CHK_OBJEXISTS: return( (bool) (get_obj_world( mob, buf) != NULL) ); /* * Case 2 begins here: We sneakily use rval to indicate need * for numeric eval... */ case CHK_PEOPLE: rval = count_people_room( mob, 0 ); break; case CHK_PLAYERS: rval = count_people_room( mob, 1 ); break; case CHK_MOBS: rval = count_people_room( mob, 2 ); break; case CHK_CLONES: rval = count_people_room( mob, 3 ); break; case CHK_ORDER: rval = get_order( mob ); break; case CHK_HOUR: rval = time_info.hour; break; default:; } /* * Case 2 continued: evaluate expression */ if ( rval >= 0 ) { if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval: prog %d syntax error(2) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); lval = rval; rval = atoi( buf ); return( num_eval( lval, oper, rval ) ); } /* * Case 3,4,5: Grab actors from $* codes */ if ( buf[0] != '$' || buf[1] == '\0' ) { sprintf( buf, "Cmd_eval: prog %d syntax error(3) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } else code = buf[1]; switch( code ) { case 'i': lval_char = mob; break; case 'n': lval_char = ch; break; case 't': lval_char = vch; break; case 'r': lval_char = rch == NULL ? get_random_char( mob ) : rch ; break; case 'o': lval_obj = obj1; break; case 'p': lval_obj = obj2; break; case 'q': lval_char = mob->mprog_target; break; default: sprintf( buf, "Cmd_eval: prog %d syntax error(4) '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } /* * From now on, we need an actor, so if none was found, bail out */ if ( lval_char == NULL && lval_obj == NULL ) return FALSE; /* * Case 3: Keyword, comparison and value */ switch( check ) { case CHK_ISPC: return( lval_char != NULL && !IS_NPC( lval_char ) ); case CHK_ISNPC: return( lval_char != NULL && IS_NPC( lval_char ) ); case CHK_ISGOOD: return( lval_char != NULL && IS_GOOD( lval_char ) ); case CHK_ISEVIL: return( lval_char != NULL && IS_EVIL( lval_char ) ); case CHK_ISNEUTRAL: return( lval_char != NULL && IS_NEUTRAL( lval_char ) ); case CHK_ISIMMORT: return( lval_char != NULL && IS_IMMORTAL( lval_char ) ); case CHK_ISCHARM: /* A relic from MERC 2.2 MOBprograms */ return( lval_char != NULL && IS_AFFECTED( lval_char, AFF_CHARM ) ); case CHK_ISFOLLOW: return( lval_char != NULL && lval_char->master != NULL && lval_char->master->in_room == lval_char->in_room ); case CHK_ISACTIVE: return( lval_char != NULL && lval_char->position > POS_SLEEPING ); case CHK_ISDELAY: return( lval_char != NULL && lval_char->mprog_delay > 0 ); case CHK_ISVISIBLE: switch( code ) { default : case 'i': case 'n': case 't': case 'r': case 'q': return( lval_char != NULL && can_see( mob, lval_char ) ); case 'o': case 'p': return( lval_obj != NULL && can_see_obj( mob, lval_obj ) ); } case CHK_HASTARGET: return( lval_char != NULL && lval_char->mprog_target != NULL && lval_char->in_room == lval_char->mprog_target->in_room ); case CHK_ISTARGET: return( lval_char != NULL && mob->mprog_target == lval_char ); default:; } /* * Case 4: Keyword, actor and value */ line = one_argument( line, buf ); switch( check ) { case CHK_AFFECTED: return( lval_char != NULL && IS_SET(lval_char->affected_by, flag_lookup(buf, affect_flags)) ); case CHK_ACT: return( lval_char != NULL && IS_SET(lval_char->act, flag_lookup(buf, act_flags)) ); case CHK_IMM: return( lval_char != NULL && IS_SET(lval_char->imm_flags, flag_lookup(buf, imm_flags)) ); case CHK_OFF: return( lval_char != NULL && IS_SET(lval_char->off_flags, flag_lookup(buf, off_flags)) ); case CHK_CARRIES: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, FALSE ) ); else return( lval_char != NULL && (get_obj_carry( lval_char, buf ) != NULL) ); case CHK_WEARS: if ( is_number( buf ) ) return( lval_char != NULL && has_item( lval_char, atoi(buf), -1, TRUE ) ); else return( lval_char != NULL && (get_obj_wear( lval_char, buf ) != NULL) ); case CHK_HAS: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), FALSE ) ); case CHK_USES: return( lval_char != NULL && has_item( lval_char, -1, item_lookup(buf), TRUE ) ); case CHK_NAME: switch( code ) { default : case 'i': case 'n': case 't': case 'r': case 'q': return( lval_char != NULL && is_name( buf, lval_char->name ) ); case 'o': case 'p': return( lval_obj != NULL && is_name( buf, lval_obj->name ) ); } case CHK_POS: return( lval_char != NULL && lval_char->position == position_lookup( buf ) ); case CHK_CLAN: return( lval_char != NULL && lval_char->clan == clan_lookup( buf ) ); case CHK_RACE: return( lval_char != NULL && lval_char->race == race_lookup( buf ) ); case CHK_OBJTYPE: return( lval_obj != NULL && lval_obj->item_type == item_lookup( buf ) ); default:; } /* * Case 5: Keyword, actor, comparison and value */ if ( (oper = keyword_lookup( fn_evals, buf )) < 0 ) { sprintf( buf, "Cmd_eval: prog %d syntax error(5): '%s'", vnum, original ); bug( buf, 0 ); return FALSE; } one_argument( line, buf ); rval = atoi( buf ); switch( check ) { case CHK_VNUM: switch( code ) { default : case 'i': case 'n': case 't': case 'r': case 'q': if( lval_char != NULL && IS_NPC( lval_char ) ) lval = lval_char->pIndexData->vnum; break; case 'o': case 'p': if ( lval_obj != NULL ) lval = lval_obj->pIndexData->vnum; } break; case CHK_HPCNT: if ( lval_char != NULL ) lval = (lval_char->hit * 100)/(UMAX(1,lval_char->max_hit)); break; case CHK_ROOM: if ( lval_char != NULL && lval_char->in_room != NULL ) lval = lval_char->in_room->vnum; break; case CHK_SEX: if ( lval_char != NULL ) lval = lval_char->sex; break; case CHK_LEVEL: if ( lval_char != NULL ) lval = lval_char->level; break; case CHK_ALIGN: if ( lval_char != NULL ) lval = lval_char->alignment; break; case CHK_MONEY: /* Money is converted to silver... */ if ( lval_char != NULL ) lval = lval_char->gold + (lval_char->silver * 100); break; case CHK_OBJVAL0: if ( lval_obj != NULL ) lval = lval_obj->value[0]; break; case CHK_OBJVAL1: if ( lval_obj != NULL ) lval = lval_obj->value[1]; break; case CHK_OBJVAL2: if ( lval_obj != NULL ) lval = lval_obj->value[2]; break; case CHK_OBJVAL3: if ( lval_obj != NULL ) lval = lval_obj->value[3]; break; case CHK_OBJVAL4: if ( lval_obj != NULL ) lval = lval_obj->value[4]; break; case CHK_GRPSIZE: if( lval_char != NULL ) lval = count_people_room( lval_char, 4 ); break; default: return FALSE; } return( num_eval( lval, oper, rval ) ); }
void program_flow( sh_int pvnum, /* For diagnostic purposes */ char *source, /* the actual MOBprog code */ CHAR_DATA *mob, CHAR_DATA *ch, const void *arg1, const void *arg2 ) { CHAR_DATA *rch = NULL; char *code, *line; char buf[MAX_STRING_LENGTH]; char control[MAX_INPUT_LENGTH], data[MAX_STRING_LENGTH]; static int call_level; /* Keep track of nested "mpcall"s */ int level, eval, check; int state[MAX_NESTED_LEVEL], /* Block state (BEGIN,IN,END) */ cond[MAX_NESTED_LEVEL]; /* Boolean value based on the last if-check */ sh_int mvnum = mob->pIndexData->vnum; if( ++call_level > MAX_CALL_LEVEL ) { bug( "MOBprogs: MAX_CALL_LEVEL exceeded, vnum %d", mob->pIndexData->vnum ); return; } /* * Reset "stack" */ for ( level = 0; level < MAX_NESTED_LEVEL; level++ ) { state[level] = IN_BLOCK; cond[level] = TRUE; } level = 0; code = source; /* * Parse the MOBprog code */ while ( *code ) { bool first_arg = TRUE; char *b = buf, *c = control, *d = data; /* * Get a command line. We sneakily get both the control word * (if/and/or) and the rest of the line in one pass. */ while( isspace( *code ) && *code ) code++; while ( *code ) { if ( *code == '\n' || *code == '\r' ) break; else if ( isspace(*code) ) { if ( first_arg ) first_arg = FALSE; else *d++ = *code; } else { if ( first_arg ) *c++ = *code; else *d++ = *code; } *b++ = *code++; } *b = *c = *d = '\0'; if ( buf[0] == '\0' ) break; if ( buf[0] == '*' ) /* Comment */ continue; line = data; /* * Match control words */ if ( !str_cmp( control, "if" ) ) { if ( state[level] == BEGIN_BLOCK ) { sprintf( buf, "Mobprog: misplaced if statement, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } state[level] = BEGIN_BLOCK; if ( ++level >= MAX_NESTED_LEVEL ) { sprintf( buf, "Mobprog: Max nested level exceeded, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) { cond[level] = FALSE; continue; } line = one_argument( line, control ); if ( ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { cond[level] = cmd_eval( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else { sprintf( buf, "Mobprog: invalid if_check (if), mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } state[level] = END_BLOCK; } else if ( !str_cmp( control, "or" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: or without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; line = one_argument( line, control ); if ( ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else { sprintf( buf, "Mobprog: invalid if_check (or), mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = (eval == TRUE) ? TRUE : cond[level]; } else if ( !str_cmp( control, "and" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: and without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; line = one_argument( line, control ); if ( ( check = keyword_lookup( fn_keyword, control ) ) >= 0 ) { eval = cmd_eval( pvnum, line, check, mob, ch, arg1, arg2, rch ); } else { sprintf( buf, "Mobprog: invalid if_check (and), mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = (cond[level] == TRUE) && (eval == TRUE) ? TRUE : FALSE; } else if ( !str_cmp( control, "endif" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: endif without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } cond[level] = TRUE; state[level] = IN_BLOCK; state[--level] = END_BLOCK; } else if ( !str_cmp( control, "else" ) ) { if ( !level || state[level-1] != BEGIN_BLOCK ) { sprintf( buf, "Mobprog: else without if, mob %d prog %d", mvnum, pvnum ); bug( buf, 0 ); return; } if ( level && cond[level-1] == FALSE ) continue; state[level] = IN_BLOCK; cond[level] = (cond[level] == TRUE) ? FALSE : TRUE; } else if ( cond[level] == TRUE && ( !str_cmp( control, "break" ) || !str_cmp( control, "end" ) ) ) { call_level--; return; } else if ( (!level || cond[level] == TRUE) && buf[0] != '\0' ) { state[level] = IN_BLOCK; expand_arg( data, buf, mob, ch, arg1, arg2, rch ); if ( !str_cmp( control, "mob" ) ) { /* * Found a mob restricted command, pass it to mob interpreter */ line = one_argument( data, control ); mob_interpret( mob, line ); } else { /* * Found a normal mud command, pass it to interpreter */ interpret( mob, data ); } } } call_level--; }
bool adam_keyword_lookup(const name_t& name) { return keyword_lookup(name); }