ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/object.c
(Generate patch)

Comparing deliantra/server/common/object.c (file contents):
Revision 1.2 by root, Tue Feb 7 23:29:55 2006 UTC vs.
Revision 1.6 by root, Sun Jun 4 19:46:55 2006 UTC

1/* 1/*
2 * static char *rcsid_object_c = 2 * static char *rcsid_object_c =
3 * "$Id: object.c,v 1.2 2006/02/07 23:29:55 root Exp $"; 3 * "$Id: object.c,v 1.6 2006/06/04 19:46:55 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
69 0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8, 69 0,1,2,3,4,5,6,7,8,1,2,2,2,3,4,4,4,5,6,6,6,7,8,8,8,
70 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8}; 70 1,2,2,2,2,2,3,4,4,4,4,4,5,6,6,6,6,6,7,8,8,8,8,8};
71 71
72 72
73/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 73/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
74static int compare_ob_value_lists_one(object * wants, object * has) { 74static int compare_ob_value_lists_one(const object * wants, const object * has) {
75 key_value * wants_field; 75 key_value * wants_field;
76 76
77 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both 77 /* n-squared behaviour (see get_ob_key_link()), but I'm hoping both
78 * objects with lists are rare, and lists stay short. If not, use a 78 * objects with lists are rare, and lists stay short. If not, use a
79 * different structure or at least keep the lists sorted... 79 * different structure or at least keep the lists sorted...
103 /* If we get here, every field in wants has a matching field in has. */ 103 /* If we get here, every field in wants has a matching field in has. */
104 return TRUE; 104 return TRUE;
105} 105}
106 106
107/* Returns TRUE if ob1 has the same key_values as ob2. */ 107/* Returns TRUE if ob1 has the same key_values as ob2. */
108static int compare_ob_value_lists(object * ob1, object * ob2) { 108static int compare_ob_value_lists(const object * ob1, const object * ob2) {
109 /* However, there may be fields in has which aren't partnered in wants, 109 /* However, there may be fields in has which aren't partnered in wants,
110 * so we need to run the comparison *twice*. :( 110 * so we need to run the comparison *twice*. :(
111 */ 111 */
112 return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1); 112 return compare_ob_value_lists_one(ob1, ob2) && compare_ob_value_lists_one(ob2, ob1);
113} 113}
198 (ob1->materialname != ob2->materialname) || 198 (ob1->materialname != ob2->materialname) ||
199 (ob1->lore != ob2->lore) || 199 (ob1->lore != ob2->lore) ||
200 (ob1->subtype != ob2->subtype) || 200 (ob1->subtype != ob2->subtype) ||
201 (ob1->move_type != ob2->move_type) || 201 (ob1->move_type != ob2->move_type) ||
202 (ob1->move_block != ob2->move_block) || 202 (ob1->move_block != ob2->move_block) ||
203 (ob1->move_allow != ob2->move_allow) ||
203 (ob1->move_on != ob2->move_on) || 204 (ob1->move_on != ob2->move_on) ||
204 (ob1->move_off != ob2->move_off) || 205 (ob1->move_off != ob2->move_off) ||
205 (ob1->move_slow != ob2->move_slow) || 206 (ob1->move_slow != ob2->move_slow) ||
206 (ob1->move_slow_penalty != ob2->move_slow_penalty) 207 (ob1->move_slow_penalty != ob2->move_slow_penalty)
207 ) 208 )
212 * some items equipped, and we don't want those to merge. 213 * some items equipped, and we don't want those to merge.
213 */ 214 */
214 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED)) 215 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
215 return 0; 216 return 0;
216 217
218 switch (ob1->type) {
219 case SCROLL:
220 if (ob1->level != ob2->level) return 0;
221 break;
222
223 }
217 if (ob1->key_values != NULL || ob2->key_values != NULL) { 224 if (ob1->key_values != NULL || ob2->key_values != NULL) {
218 /* At least one of these has key_values. */ 225 /* At least one of these has key_values. */
219 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) { 226 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
220 /* One has fields, but the other one doesn't. */ 227 /* One has fields, but the other one doesn't. */
221 return 0; 228 return 0;
222 } else {
223 return compare_ob_value_lists(ob1, ob2); 229 } else if (!compare_ob_value_lists(ob1, ob2)) {
230 return 0;
224 } 231 }
225 } 232 }
226 233
227 switch (ob1->type) {
228 case SCROLL:
229 if (ob1->level != ob2->level) return 0;
230 break;
231
232 }
233 /* Everything passes, must be OK. */ 234 /* Everything passes, must be OK. */
234 return 1; 235 return 1;
235} 236}
236 237
237/* 238/*
385 * get_nearest_part(multi-object, object 2) returns the part of the 386 * get_nearest_part(multi-object, object 2) returns the part of the
386 * multi-object 1 which is closest to the second object. 387 * multi-object 1 which is closest to the second object.
387 * If it's not a multi-object, it is returned. 388 * If it's not a multi-object, it is returned.
388 */ 389 */
389 390
390object *get_nearest_part(object *op,object *pl) { 391object *get_nearest_part(object *op, const object *pl) {
391 object *tmp,*closest; 392 object *tmp,*closest;
392 int last_dist,i; 393 int last_dist,i;
393 if(op->more==NULL) 394 if(op->more==NULL)
394 return op; 395 return op;
395 for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more) 396 for(last_dist=distance(op,pl),closest=op,tmp=op->more;tmp!=NULL;tmp=tmp->more)
414 * Returns the first object which has a name equal to the argument. 415 * Returns the first object which has a name equal to the argument.
415 * Used only by the patch command, but not all that useful. 416 * Used only by the patch command, but not all that useful.
416 * Enables features like "patch <name-of-other-player> food 999" 417 * Enables features like "patch <name-of-other-player> food 999"
417 */ 418 */
418 419
419object *find_object_name(char *str) { 420object *find_object_name(const char *str) {
420 const char *name=add_string(str); 421 const char *name=add_string(str);
421 object *op; 422 object *op;
422 for(op=objects;op!=NULL;op=op->next) 423 for(op=objects;op!=NULL;op=op->next)
423 if(op->name==name) 424 if(op->name==name)
424 break; 425 break;
1019 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE)) 1020 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE))
1020 update_now=1; 1021 update_now=1;
1021 1022
1022 if ((move_on | op->move_on) != move_on) update_now=1; 1023 if ((move_on | op->move_on) != move_on) update_now=1;
1023 if ((move_off | op->move_off) != move_off) update_now=1; 1024 if ((move_off | op->move_off) != move_off) update_now=1;
1025 /* This isn't perfect, but I don't expect a lot of objects to
1026 * to have move_allow right now.
1027 */
1024 if ((move_block | op->move_block) != move_block) update_now=1; 1028 if (((move_block | op->move_block) & ~op->move_allow) != move_block)
1029 update_now=1;
1025 if ((move_slow | op->move_slow) != move_slow) update_now=1; 1030 if ((move_slow | op->move_slow) != move_slow) update_now=1;
1026 } 1031 }
1027 /* if the object is being removed, we can't make intelligent 1032 /* if the object is being removed, we can't make intelligent
1028 * decisions, because remove_ob can't really pass the object 1033 * decisions, because remove_ob can't really pass the object
1029 * that is being removed. 1034 * that is being removed.
1511 if(op->more!=NULL) { 1516 if(op->more!=NULL) {
1512 /* The part may be on a different map. */ 1517 /* The part may be on a different map. */
1513 1518
1514 object *more = op->more; 1519 object *more = op->more;
1515 1520
1521 /* We really need the caller to normalize coordinates - if
1522 * we set the map, that doesn't work if the location is within
1523 * a map and this is straddling an edge. So only if coordinate
1524 * is clear wrong do we normalize it.
1525 */
1526 if (OUT_OF_REAL_MAP(more->map, more->x, more->y)) {
1516 /* Debugging information so you can see the last coordinates this object had */ 1527 /* Debugging information so you can see the last coordinates this object had */
1517 more->ox = more->x; 1528 more->ox = more->x;
1518 more->oy = more->y; 1529 more->oy = more->y;
1519 more->map = get_map_from_coord(m, &more->x, &more->y); 1530 more->map = get_map_from_coord(m, &more->x, &more->y);
1531 } else if (!more->map) {
1532 /* For backwards compatibility - when not dealing with tiled maps,
1533 * more->map should always point to the parent.
1534 */
1535 more->map = m;
1536 }
1520 1537
1521 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) { 1538 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) {
1522 if ( ! op->head) 1539 if ( ! op->head)
1523 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); 1540 LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n");
1524 return NULL; 1541 return NULL;
1527 CLEAR_FLAG(op,FLAG_REMOVED); 1544 CLEAR_FLAG(op,FLAG_REMOVED);
1528 1545
1529 /* Debugging information so you can see the last coordinates this object had */ 1546 /* Debugging information so you can see the last coordinates this object had */
1530 op->ox=op->x; 1547 op->ox=op->x;
1531 op->oy=op->y; 1548 op->oy=op->y;
1549
1550 /* Ideally, the caller figures this out. However, it complicates a lot
1551 * of areas of callers (eg, anything that uses find_free_spot would now
1552 * need extra work
1553 */
1554 op->map=get_map_from_coord(m, &op->x, &op->y);
1532 x = op->x; 1555 x = op->x;
1533 y = op->y; 1556 y = op->y;
1534 op->map=get_map_from_coord(m, &x, &y);
1535 1557
1536 /* this has to be done after we translate the coordinates. 1558 /* this has to be done after we translate the coordinates.
1537 */ 1559 */
1538 if(op->nrof && !(flag & INS_NO_MERGE)) { 1560 if(op->nrof && !(flag & INS_NO_MERGE)) {
1539 for(tmp=GET_MAP_OB(op->map,x,y);tmp!=NULL;tmp=tmp->above) 1561 for(tmp=GET_MAP_OB(op->map,x,y);tmp!=NULL;tmp=tmp->above)
1540 if (CAN_MERGE(op,tmp)) { 1562 if (CAN_MERGE(op,tmp)) {
1541 op->nrof+=tmp->nrof; 1563 op->nrof+=tmp->nrof;
1542 remove_ob(tmp); 1564 remove_ob(tmp);
1543 free_object(tmp); 1565 free_object(tmp);
1544 } 1566 }
1545 }
1546
1547 /* Ideally, the caller figures this out. However, it complicates a lot
1548 * of areas of callers (eg, anything that uses find_free_spot would now
1549 * need extra work
1550 */
1551 if (op->map != m) {
1552 /* coordinates should not change unless map also changes */
1553 op->x = x;
1554 op->y = y;
1555 } 1567 }
1556 1568
1557 CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */ 1569 CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1558 CLEAR_FLAG(op, FLAG_INV_LOCKED); 1570 CLEAR_FLAG(op, FLAG_INV_LOCKED);
1559 if (!QUERY_FLAG(op, FLAG_ALIVE)) 1571 if (!QUERY_FLAG(op, FLAG_ALIVE))
1706 1718
1707/* this function inserts an object in the map, but if it 1719/* this function inserts an object in the map, but if it
1708 * finds an object of its own type, it'll remove that one first. 1720 * finds an object of its own type, it'll remove that one first.
1709 * op is the object to insert it under: supplies x and the map. 1721 * op is the object to insert it under: supplies x and the map.
1710 */ 1722 */
1711void replace_insert_ob_in_map(char *arch_string, object *op) { 1723void replace_insert_ob_in_map(const char *arch_string, object *op) {
1712 object *tmp; 1724 object *tmp;
1713 object *tmp1; 1725 object *tmp1;
1714 1726
1715 /* first search for itself and remove any old instances */ 1727 /* first search for itself and remove any old instances */
1716 1728
2084 * present_arch(arch, map, x, y) searches for any objects with 2096 * present_arch(arch, map, x, y) searches for any objects with
2085 * a matching archetype at the given map and coordinates. 2097 * a matching archetype at the given map and coordinates.
2086 * The first matching object is returned, or NULL if none. 2098 * The first matching object is returned, or NULL if none.
2087 */ 2099 */
2088 2100
2089object *present_arch(archetype *at, mapstruct *m, int x, int y) { 2101object *present_arch(const archetype *at, mapstruct *m, int x, int y) {
2090 object *tmp; 2102 object *tmp;
2091 if(m==NULL || out_of_map(m,x,y)) { 2103 if(m==NULL || out_of_map(m,x,y)) {
2092 LOG(llevError,"Present_arch called outside map.\n"); 2104 LOG(llevError,"Present_arch called outside map.\n");
2093 return NULL; 2105 return NULL;
2094 } 2106 }
2120 * present_in_ob(type, object) searches for any objects with 2132 * present_in_ob(type, object) searches for any objects with
2121 * a matching type variable in the inventory of the given object. 2133 * a matching type variable in the inventory of the given object.
2122 * The first matching object is returned, or NULL if none. 2134 * The first matching object is returned, or NULL if none.
2123 */ 2135 */
2124 2136
2125object *present_in_ob(unsigned char type,object *op) { 2137object *present_in_ob(unsigned char type, const object *op) {
2126 object *tmp; 2138 object *tmp;
2127 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2139 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2128 if(tmp->type==type) 2140 if(tmp->type==type)
2129 return tmp; 2141 return tmp;
2130 return NULL; 2142 return NULL;
2143 * the object name, not the archetype name. this is so that the 2155 * the object name, not the archetype name. this is so that the
2144 * spell code can use one object type (force), but change it's name 2156 * spell code can use one object type (force), but change it's name
2145 * to be unique. 2157 * to be unique.
2146 */ 2158 */
2147 2159
2148object *present_in_ob_by_name(int type, char *str,object *op) { 2160object *present_in_ob_by_name(int type, const char *str, const object *op) {
2149 object *tmp; 2161 object *tmp;
2150 2162
2151 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 2163 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) {
2152 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) 2164 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name)))
2153 return tmp; 2165 return tmp;
2159 * present_arch_in_ob(archetype, object) searches for any objects with 2171 * present_arch_in_ob(archetype, object) searches for any objects with
2160 * a matching archetype in the inventory of the given object. 2172 * a matching archetype in the inventory of the given object.
2161 * The first matching object is returned, or NULL if none. 2173 * The first matching object is returned, or NULL if none.
2162 */ 2174 */
2163 2175
2164object *present_arch_in_ob(archetype *at, object *op) { 2176object *present_arch_in_ob(const archetype *at, const object *op) {
2165 object *tmp; 2177 object *tmp;
2166 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2178 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2167 if( tmp->arch == at) 2179 if( tmp->arch == at)
2168 return tmp; 2180 return tmp;
2169 return NULL; 2181 return NULL;
2223 * to know if the space in question will block the object. We can't use 2235 * to know if the space in question will block the object. We can't use
2224 * the archetype because that isn't correct if the monster has been 2236 * the archetype because that isn't correct if the monster has been
2225 * customized, changed states, etc. 2237 * customized, changed states, etc.
2226 */ 2238 */
2227 2239
2228int find_free_spot(object *ob, mapstruct *m,int x,int y,int start,int stop) { 2240int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) {
2229 int i,index=0, flag; 2241 int i,index=0, flag;
2230 static int altern[SIZEOFFREE]; 2242 static int altern[SIZEOFFREE];
2231 2243
2232 for(i=start;i<stop;i++) { 2244 for(i=start;i<stop;i++) {
2233 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); 2245 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]);
2254 * find_free_spot(), but it will search max number of squares. 2266 * find_free_spot(), but it will search max number of squares.
2255 * But it will return the first available spot, not a random choice. 2267 * But it will return the first available spot, not a random choice.
2256 * Changed 0.93.2: Have it return -1 if there is no free spot available. 2268 * Changed 0.93.2: Have it return -1 if there is no free spot available.
2257 */ 2269 */
2258 2270
2259int find_first_free_spot(object *ob, mapstruct *m,int x,int y) { 2271int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) {
2260 int i; 2272 int i;
2261 for(i=0;i<SIZEOFFREE;i++) { 2273 for(i=0;i<SIZEOFFREE;i++) {
2262 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) 2274 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]))
2263 return i; 2275 return i;
2264 } 2276 }
2365/* 2377/*
2366 * distance(object 1, object 2) will return the square of the 2378 * distance(object 1, object 2) will return the square of the
2367 * distance between the two given objects. 2379 * distance between the two given objects.
2368 */ 2380 */
2369 2381
2370int distance(object *ob1,object *ob2) { 2382int distance(const object *ob1, const object *ob2) {
2371 int i; 2383 int i;
2372 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ 2384 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+
2373 (ob1->y - ob2->y)*(ob1->y - ob2->y); 2385 (ob1->y - ob2->y)*(ob1->y - ob2->y);
2374 return i; 2386 return i;
2375} 2387}
2540 * core dumps if they do. 2552 * core dumps if they do.
2541 * 2553 *
2542 * Add a check so we can't pick up invisible objects (0.93.8) 2554 * Add a check so we can't pick up invisible objects (0.93.8)
2543 */ 2555 */
2544 2556
2545int can_pick(object *who,object *item) { 2557int can_pick(const object *who, const object *item) {
2546 return /*QUERY_FLAG(who,FLAG_WIZ)||*/ 2558 return /*QUERY_FLAG(who,FLAG_WIZ)||*/
2547 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& 2559 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&&
2548 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && 2560 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible &&
2549 (who->type==PLAYER||item->weight<who->weight/3)); 2561 (who->type==PLAYER||item->weight<who->weight/3));
2550} 2562}
2585 2597
2586 return dst; 2598 return dst;
2587} 2599}
2588 2600
2589/* return true if the object was destroyed, 0 otherwise */ 2601/* return true if the object was destroyed, 0 otherwise */
2590int was_destroyed (object *op, tag_t old_tag) 2602int was_destroyed (const object *op, tag_t old_tag)
2591{ 2603{
2592 /* checking for FLAG_FREED isn't necessary, but makes this function more 2604 /* checking for FLAG_FREED isn't necessary, but makes this function more
2593 * robust */ 2605 * robust */
2594 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); 2606 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED);
2595} 2607}
2599/* load_object on it. I admit it is a highly inefficient way to make things, */ 2611/* load_object on it. I admit it is a highly inefficient way to make things, */
2600/* but it was simple to make and allows reusing the load_object function. */ 2612/* but it was simple to make and allows reusing the load_object function. */
2601/* Remember not to use load_object_str in a time-critical situation. */ 2613/* Remember not to use load_object_str in a time-critical situation. */
2602/* Also remember that multiparts objects are not supported for now. */ 2614/* Also remember that multiparts objects are not supported for now. */
2603 2615
2604object* load_object_str(char *obstr) 2616object* load_object_str(const char *obstr)
2605{ 2617{
2606 object *op; 2618 object *op;
2607 FILE *tempfile; 2619 FILE *tempfile;
2608 char filename[MAX_BUF]; 2620 char filename[MAX_BUF];
2609 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); 2621 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir);
2633 2645
2634/* This returns the first object in who's inventory that 2646/* This returns the first object in who's inventory that
2635 * has the same type and subtype match. 2647 * has the same type and subtype match.
2636 * returns NULL if no match. 2648 * returns NULL if no match.
2637 */ 2649 */
2638object *find_obj_by_type_subtype(object *who, int type, int subtype) 2650object *find_obj_by_type_subtype(const object *who, int type, int subtype)
2639{ 2651{
2640 object *tmp; 2652 object *tmp;
2641 2653
2642 for (tmp=who->inv; tmp; tmp=tmp->below) 2654 for (tmp=who->inv; tmp; tmp=tmp->below)
2643 if (tmp->type == type && tmp->subtype == subtype) return tmp; 2655 if (tmp->type == type && tmp->subtype == subtype) return tmp;
2649 * otherwise return NULL. 2661 * otherwise return NULL.
2650 * 2662 *
2651 * key must be a passed in shared string - otherwise, this won't 2663 * key must be a passed in shared string - otherwise, this won't
2652 * do the desired thing. 2664 * do the desired thing.
2653 */ 2665 */
2654key_value * get_ob_key_link(object * ob, const char * key) { 2666key_value * get_ob_key_link(const object * ob, const char * key) {
2655 key_value * link; 2667 key_value * link;
2656 2668
2657 for (link = ob->key_values; link != NULL; link = link->next) { 2669 for (link = ob->key_values; link != NULL; link = link->next) {
2658 if (link->key == key) { 2670 if (link->key == key) {
2659 return link; 2671 return link;
2668 * 2680 *
2669 * The argument doesn't need to be a shared string. 2681 * The argument doesn't need to be a shared string.
2670 * 2682 *
2671 * The returned string is shared. 2683 * The returned string is shared.
2672 */ 2684 */
2673const char * get_ob_key_value(object * op, const char * const key) { 2685const char * get_ob_key_value(const object * op, const char * const key) {
2674 key_value * link; 2686 key_value * link;
2675 const char * canonical_key; 2687 const char * canonical_key;
2676 2688
2677 canonical_key = find_string(key); 2689 canonical_key = find_string(key);
2678 2690
2708 * Returns TRUE on success. 2720 * Returns TRUE on success.
2709 */ 2721 */
2710int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { 2722int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) {
2711 key_value * field = NULL, *last=NULL; 2723 key_value * field = NULL, *last=NULL;
2712 2724
2713 LOG(llevDebug, "set_ob_value_s: '%s' '%s' %d\n", canonical_key, value, add_key);
2714
2715 for (field=op->key_values; field != NULL; field=field->next) { 2725 for (field=op->key_values; field != NULL; field=field->next) {
2716 if (field->key != canonical_key) { 2726 if (field->key != canonical_key) {
2717 last = field; 2727 last = field;
2718 continue; 2728 continue;
2719 } 2729 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines