00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <config.h>
00037
00038 #include <ctype.h>
00039 #include <limits.h>
00040 #include "file.h"
00041 #include "match.h"
00042 #include "nat.h"
00043 #include "optlist.h"
00044 #include "player.h"
00045 #include "prototypes.h"
00046
00047 static char *nstr_parse_val(char *, struct valstr *);
00048 static int nstr_match_ca(struct valstr *, struct castr *);
00049 static int nstr_match_val(struct valstr *, struct castr *, int);
00050 static int nstr_string_ok(struct castr *ca, int idx);
00051 static struct valstr *nstr_resolve_sel(struct valstr *, struct castr *);
00052 static struct valstr *nstr_mkselval(struct valstr *, int, struct castr *);
00053 static struct valstr *nstr_resolve_id(struct valstr *, struct castr *, int, int);
00054 static int nstr_promote(int);
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 int
00066 nstr_comp(struct nscstr *np, int len, int type, char *str)
00067 {
00068 struct castr *ca = ef_cadef(type);
00069 char *cond;
00070 char *tail;
00071 int i;
00072 struct nscstr dummy;
00073 int lft_caidx, rgt_caidx;
00074 int lft_val, rgt_val;
00075 int lft_type, rgt_type;
00076
00077 cond = str;
00078 for (i = 0; ; ++i, ++np) {
00079 if (i >= len)
00080 np = &dummy;
00081
00082
00083 tail = nstr_parse_val(cond, &np->lft);
00084 lft_caidx = nstr_match_ca(&np->lft, ca);
00085
00086
00087 if (*tail != '<' && *tail != '=' && *tail != '>' && *tail != '#') {
00088 if (*tail)
00089 pr("%s -- expected condition operator\n", cond);
00090 else
00091 pr("%s -- missing condition operator\n", cond);
00092 return -1;
00093 }
00094 np->operator = *tail;
00095 ++tail;
00096
00097
00098 tail = nstr_parse_val(tail, &np->rgt);
00099 rgt_caidx = nstr_match_ca(&np->rgt, ca);
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 lft_val = nstr_match_val(&np->lft, ca, rgt_caidx);
00111 rgt_val = nstr_match_val(&np->rgt, ca, lft_caidx);
00112
00113
00114
00115
00116 if (lft_val >= 0 && rgt_val >= 0) {
00117 pr("%.*s -- condition ambiguous\n", (int)(tail-cond), cond);
00118 return -1;
00119 } else if (rgt_val >= 0) {
00120
00121 if (!nstr_resolve_sel(&np->lft, &ca[lft_caidx]))
00122 return -1;
00123 nstr_mkselval(&np->rgt, rgt_val, &ca[lft_caidx]);
00124 } else if (lft_val >= 0) {
00125
00126 nstr_mkselval(&np->lft, lft_val, &ca[rgt_caidx]);
00127 if (!nstr_resolve_sel(&np->rgt, &ca[rgt_caidx]))
00128 return -1;
00129 } else {
00130
00131
00132
00133
00134 if (!nstr_resolve_id(&np->lft, ca, lft_caidx,
00135 nstr_string_ok(ca, rgt_caidx)))
00136 return -1;
00137 if (!nstr_resolve_id(&np->rgt, ca, rgt_caidx,
00138 nstr_string_ok(ca, lft_caidx)))
00139 return -1;
00140 }
00141
00142
00143 lft_type = nstr_promote(np->lft.val_type);
00144 rgt_type = nstr_promote(np->rgt.val_type);
00145 np->optype = NSC_NOTYPE;
00146 if (lft_type == NSC_STRING) {
00147 if (!nstr_coerce_val(&np->rgt, NSC_STRING, str))
00148 np->optype = NSC_STRING;
00149 } else if (rgt_type == NSC_STRING) {
00150 if (!nstr_coerce_val(&np->lft, NSC_STRING, str))
00151 np->optype = NSC_STRING;
00152 } else if (lft_type == NSC_DOUBLE) {
00153 if (!nstr_coerce_val(&np->rgt, NSC_DOUBLE, str))
00154 np->optype = NSC_DOUBLE;
00155 } else if (rgt_type == NSC_DOUBLE) {
00156 if (!nstr_coerce_val(&np->lft, NSC_DOUBLE, str))
00157 np->optype = NSC_DOUBLE;
00158 } else {
00159 if (!nstr_coerce_val(&np->lft, NSC_LONG, str)
00160 && !nstr_coerce_val(&np->rgt, NSC_LONG, str))
00161 np->optype = NSC_LONG;
00162 }
00163 if (np->optype == NSC_NOTYPE)
00164 return -1;
00165
00166
00167 if (*tail == 0)
00168 break;
00169 if (*tail != '&') {
00170 pr("%s -- expected `&'\n", cond);
00171 return -1;
00172 }
00173 cond = tail + 1;
00174 }
00175
00176 if (i >= len) {
00177
00178 pr("%s -- too many conditions\n", str);
00179 return -1;
00180 }
00181
00182 return i + 1;
00183 }
00184
00185
00186 static int
00187 strnncmp(char *s1, size_t sz1, char *s2, size_t sz2)
00188 {
00189 int res;
00190 if (sz1 == sz2) return strncmp(s1, s2, sz2);
00191 if (sz1 < sz2) return -strnncmp(s2, sz2, s1, sz1);
00192 res = strncmp(s1, s2, sz2);
00193 return res ? res : s1[sz2];
00194 }
00195
00196 #define EVAL(op, lft, rgt) \
00197 ((op) == '<' ? (lft) < (rgt) \
00198 : (op) == '=' ? (lft) == (rgt) \
00199 : (op) == '>' ? (lft) > (rgt) \
00200 : (op) == '#' ? (lft) != (rgt) \
00201 : 0)
00202
00203
00204
00205
00206
00207
00208
00209 int
00210 nstr_exec(struct nscstr *np, int ncond, void *ptr)
00211 {
00212 int i, op, optype, cmp;
00213 struct valstr lft, rgt;
00214
00215 for (i = 0; i < ncond; ++i) {
00216 op = np[i].operator;
00217 optype = np[i].optype;
00218 if (np[i].lft.val_cat == NSC_NOCAT || np[i].rgt.val_cat == NSC_NOCAT)
00219 return 0;
00220 lft = np[i].lft;
00221 nstr_exec_val(&lft, player->cnum, ptr, optype);
00222 rgt = np[i].rgt;
00223 nstr_exec_val(&rgt, player->cnum, ptr, optype);
00224 switch (optype) {
00225 case NSC_LONG:
00226 if (!EVAL(op, lft.val_as.lng, rgt.val_as.lng))
00227 return 0;
00228 break;
00229 case NSC_DOUBLE:
00230 if (!EVAL(op, lft.val_as.dbl, rgt.val_as.dbl))
00231 return 0;
00232 break;
00233 case NSC_STRING:
00234 cmp = strnncmp(lft.val_as.str.base, lft.val_as.str.maxsz,
00235 rgt.val_as.str.base, rgt.val_as.str.maxsz);
00236 if (!EVAL(op, cmp, 0))
00237 return 0;
00238 break;
00239 default:
00240 CANT_REACH();
00241 return 0;
00242 }
00243 }
00244
00245 return 1;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 static char *
00255 nstr_parse_val(char *str, struct valstr *val)
00256 {
00257 long l;
00258 double d;
00259 char *tail, *tail2;
00260
00261
00262 if (str[0] == '\'') {
00263 for (tail = str + 1; *tail && *tail != '\''; ++tail) ;
00264
00265 val->val_type = NSC_STRING;
00266 val->val_cat = NSC_VAL;
00267 val->val_as.str.base = str + 1;
00268 val->val_as.str.maxsz = tail - (str + 1);
00269 if (*tail) ++tail;
00270
00271 return tail;
00272 }
00273
00274
00275 if (isalpha(str[0])) {
00276 for (tail = str+1; isalnum(*tail) || *tail == '_'; ++tail) ;
00277 val->val_type = NSC_NOTYPE;
00278 val->val_cat = NSC_ID;
00279 val->val_as.str.base = str;
00280 val->val_as.str.maxsz = tail - str;
00281 return tail;
00282 }
00283
00284
00285 l = strtol(str, &tail, 0);
00286 d = strtod(str, &tail2);
00287 if (tail2 > tail) {
00288 val->val_type = NSC_DOUBLE;
00289 val->val_cat = NSC_VAL;
00290 val->val_as.dbl = d;
00291 return tail2;
00292 }
00293 if (tail != str) {
00294 val->val_type = NSC_LONG;
00295 val->val_cat = NSC_VAL;
00296 val->val_as.lng = l;
00297 return tail;
00298 }
00299
00300
00301 tail = str+1;
00302 val->val_type = NSC_NOTYPE;
00303 val->val_cat = NSC_ID;
00304 val->val_as.str.base = str;
00305 val->val_as.str.maxsz = tail - str;
00306 return tail;
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316 static int
00317 nstr_match_ca(struct valstr *val, struct castr *ca)
00318 {
00319 char id[32];
00320
00321 if (val->val_cat != NSC_ID || val->val_as.str.maxsz >= sizeof(id))
00322 return M_NOTFOUND;
00323
00324 if (!ca)
00325 return M_NOTFOUND;
00326
00327 memcpy(id, val->val_as.str.base, val->val_as.str.maxsz);
00328 id[val->val_as.str.maxsz] = 0;
00329
00330 return stmtch(id, ca, offsetof(struct castr, ca_name),
00331 sizeof(struct castr));
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341 static int
00342 nstr_match_val(struct valstr *val, struct castr *ca, int idx)
00343 {
00344 char id[32];
00345
00346 if (val->val_cat != NSC_ID || val->val_as.str.maxsz >= sizeof(id))
00347 return M_NOTFOUND;
00348
00349 if (idx < 0 || ca[idx].ca_table == EF_BAD)
00350 return M_NOTFOUND;
00351 if (CANT_HAPPEN(nstr_promote(ca[idx].ca_type) != NSC_LONG))
00352 return M_NOTFOUND;
00353
00354 memcpy(id, val->val_as.str.base, val->val_as.str.maxsz);
00355 id[val->val_as.str.maxsz] = 0;
00356
00357 return ef_elt_byname(ca[idx].ca_table, id);
00358 }
00359
00360
00361
00362
00363
00364 static int
00365 nstr_string_ok(struct castr *ca, int idx)
00366 {
00367 return idx >= 0 && nstr_promote(ca[idx].ca_type) == NSC_STRING;
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 static struct valstr *
00380 nstr_resolve_id(struct valstr *val, struct castr *ca, int idx, int string_ok)
00381 {
00382 if (val->val_cat != NSC_ID)
00383 return val;
00384
00385 if (idx == M_NOTUNIQUE && !string_ok) {
00386 pr("%.*s -- ambiguous name\n",
00387 (int)val->val_as.str.maxsz, val->val_as.str.base);
00388 val->val_cat = NSC_NOCAT;
00389 return NULL;
00390 }
00391
00392 if (idx == M_NOTFOUND && !string_ok) {
00393 pr("%.*s -- unknown name\n",
00394 (int)val->val_as.str.maxsz, val->val_as.str.base);
00395 val->val_cat = NSC_NOCAT;
00396 return NULL;
00397 }
00398
00399 if (idx < 0) {
00400 CANT_HAPPEN(!string_ok);
00401
00402 val->val_type = NSC_STRING;
00403 val->val_cat = NSC_VAL;
00404
00405 if (val->val_as.str.maxsz == 1 && val->val_as.str.base[0] == '~')
00406 val->val_as.str.maxsz = 0;
00407 return val;
00408 }
00409
00410 return nstr_resolve_sel(val, &ca[idx]);
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 static struct valstr *
00420 nstr_resolve_sel(struct valstr *val, struct castr *ca)
00421 {
00422 if (CANT_HAPPEN(val->val_cat != NSC_ID)) {
00423 val->val_cat = NSC_NOCAT;
00424 return val;
00425 }
00426
00427 if ((ca->ca_flags & NSC_DEITY) && !player->god) {
00428 pr("%.*s -- not accessible to mortals\n",
00429 (int)val->val_as.str.maxsz, val->val_as.str.base);
00430 val->val_cat = NSC_NOCAT;
00431 return NULL;
00432 }
00433
00434 val->val_type = ca->ca_type;
00435 val->val_cat = NSC_OFF;
00436 val->val_as.sym.off = ca->ca_off;
00437 val->val_as.sym.len = ca->ca_len;
00438 val->val_as.sym.idx = 0;
00439 return val;
00440 }
00441
00442
00443
00444
00445 static struct valstr *
00446 nstr_mkselval(struct valstr *val, int selval, struct castr *ca)
00447 {
00448 if (CANT_HAPPEN(nstr_promote(ca->ca_type) != NSC_LONG
00449 || ca->ca_table == EF_BAD)) {
00450 val->val_type = NSC_NOTYPE;
00451 val->val_cat = NSC_NOCAT;
00452 return val;
00453 }
00454
00455 val->val_type = ca->ca_type;
00456 val->val_cat = NSC_VAL;
00457 val->val_as.lng = selval;
00458 return val;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 char *
00470 nstr_comp_val(char *str, struct valstr *val, int type)
00471 {
00472 struct castr *ca = ef_cadef(type);
00473 char *tail = nstr_parse_val(str, val);
00474 if (!nstr_resolve_id(val, ca, nstr_match_ca(val, ca), 0))
00475 return NULL;
00476 return tail;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486 static int
00487 nstr_promote(int valtype)
00488 {
00489 switch (valtype) {
00490 case NSC_LONG:
00491 case NSC_DOUBLE:
00492 case NSC_STRING:
00493 break;
00494 case NSC_CHAR:
00495 case NSC_UCHAR:
00496 case NSC_SHORT:
00497 case NSC_USHORT:
00498 case NSC_INT:
00499 case NSC_XCOORD:
00500 case NSC_YCOORD:
00501 case NSC_HIDDEN:
00502 case NSC_TIME:
00503 valtype = NSC_LONG;
00504 break;
00505 case NSC_FLOAT:
00506 valtype = NSC_DOUBLE;
00507 break;
00508 case NSC_STRINGY:
00509 valtype = NSC_STRING;
00510 break;
00511 default:
00512 CANT_REACH();
00513 valtype = NSC_NOTYPE;
00514 }
00515 return valtype;
00516 }
00517
00518 static int
00519 cond_type_mismatch(char *str)
00520 {
00521 if (str)
00522 pr("%s -- condition operand type mismatch\n", str);
00523 return -1;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533 int
00534 nstr_coerce_val(struct valstr *val, nsc_type to, char *str)
00535 {
00536
00537 nsc_type from = nstr_promote(val->val_type);
00538
00539 if (from == NSC_NOTYPE)
00540 return 0;
00541
00542 if (from != to) {
00543 switch (to) {
00544 case NSC_STRING:
00545 return cond_type_mismatch(str);
00546 case NSC_DOUBLE:
00547 if (from == NSC_LONG) {
00548 if (val->val_cat == NSC_VAL)
00549 val->val_as.dbl = val->val_as.lng;
00550 } else
00551 return cond_type_mismatch(str);
00552 break;
00553 case NSC_LONG:
00554 return cond_type_mismatch(str);
00555 default:
00556 CANT_REACH();
00557 to = from;
00558 }
00559 }
00560
00561 if (val->val_cat == NSC_VAL) {
00562
00563 CANT_HAPPEN(val->val_type == NSC_XCOORD
00564 || val->val_type == NSC_YCOORD
00565 || val->val_type == NSC_HIDDEN);
00566 val->val_type = to;
00567 }
00568
00569 return 0;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 void
00583 nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
00584 {
00585 char *memb_ptr;
00586 nsc_type valtype;
00587 int idx;
00588 struct natstr *natp;
00589
00590 switch (val->val_cat) {
00591 default:
00592 CANT_REACH();
00593
00594 case NSC_VAL:
00595 valtype = val->val_type;
00596 break;
00597 case NSC_OFF:
00598 valtype = NSC_LONG;
00599 memb_ptr = ptr;
00600 memb_ptr += val->val_as.sym.off;
00601 idx = val->val_as.sym.idx;
00602 switch (val->val_type) {
00603 case NSC_CHAR:
00604 val->val_as.lng = ((signed char *)memb_ptr)[idx];
00605 break;
00606 case NSC_UCHAR:
00607 val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
00608 break;
00609 case NSC_SHORT:
00610 val->val_as.lng = ((short *)memb_ptr)[idx];
00611 break;
00612 case NSC_USHORT:
00613 val->val_as.lng = ((unsigned short *)memb_ptr)[idx];
00614 break;
00615 case NSC_INT:
00616 val->val_as.lng = ((int *)memb_ptr)[idx];
00617 break;
00618 case NSC_LONG:
00619 val->val_as.lng = ((long *)memb_ptr)[idx];
00620 break;
00621 case NSC_XCOORD:
00622 val->val_as.lng = xrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
00623 break;
00624 case NSC_YCOORD:
00625 val->val_as.lng = yrel(getnatp(cnum), ((short *)memb_ptr)[idx]);
00626 break;
00627 case NSC_HIDDEN:
00628 val->val_as.lng = -1;
00629 if (CANT_HAPPEN(((struct natstr *)ptr)->ef_type != EF_NATION))
00630 break;
00631 natp = getnatp(cnum);
00632 if (!opt_HIDDEN
00633 || natp->nat_stat == STAT_GOD
00634 || (getcontact(natp, idx) && getcontact(ptr, idx)))
00635 val->val_as.lng = ((unsigned char *)memb_ptr)[idx];
00636 break;
00637 case NSC_FLOAT:
00638 val->val_as.dbl = ((float *)memb_ptr)[idx];
00639 valtype = NSC_DOUBLE;
00640 break;
00641 case NSC_DOUBLE:
00642 val->val_as.dbl = ((double *)memb_ptr)[idx];
00643 valtype = NSC_DOUBLE;
00644 break;
00645 case NSC_STRINGY:
00646 CANT_HAPPEN(idx);
00647 val->val_as.str.maxsz = val->val_as.sym.len;
00648 val->val_as.str.base = (char *)memb_ptr;
00649 valtype = NSC_STRING;
00650 break;
00651 case NSC_STRING:
00652 val->val_as.str.base = ((char **)memb_ptr)[idx];
00653 val->val_as.str.maxsz = INT_MAX;
00654 valtype = NSC_STRING;
00655 break;
00656 case NSC_TIME:
00657 val->val_as.lng = ((time_t *)memb_ptr)[idx];
00658 break;
00659 default:
00660 CANT_REACH();
00661 val->val_as.lng = 0;
00662 }
00663 val->val_cat = NSC_VAL;
00664 }
00665
00666 if (valtype == want)
00667 ;
00668 else if (want == NSC_DOUBLE) {
00669 if (valtype == NSC_LONG) {
00670 valtype = want;
00671 val->val_as.dbl = val->val_as.lng;
00672 }
00673 } else if (want == NSC_STRING)
00674 CANT_REACH();
00675
00676 if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
00677 valtype = want;
00678 switch (want) {
00679 case NSC_LONG: val->val_as.lng = 0; break;
00680 case NSC_DOUBLE: val->val_as.dbl = 0.0; break;
00681 case NSC_STRING: val->val_as.str.base = NULL; break;
00682 default:
00683 CANT_REACH();
00684 }
00685 }
00686
00687 val->val_type = valtype;
00688 }
00689
00690 char *
00691 symbol_by_value(int key, struct symbol *table)
00692 {
00693 int i;
00694
00695 for (i = 0; table[i].name; i++)
00696 if (key == table[i].value)
00697 return table[i].name;
00698
00699 return NULL;
00700 }