Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

op.c

Go to the documentation of this file.
00001  /*
00002   * plint/data/op.c : operations, convertions, comparison, functions (source)
00003   * 
00004   * Time-stamp: <2002-12-21 14:31:04 gseba>
00005   * 
00006   * Copyright (C) Sebastian Glita, email: gseba@users.sourceforge.net
00007   * 
00008   * This file is part of plint.
00009   * 
00010   * plint is free software; you can  redistribute it and/or modify it under the
00011   * terms of the  GNU General Public License as published  by the Free Software
00012   * Foundation; either version 2, or (at your option) any later version.
00013   *
00014   * plint  is distributed  in the  hope  that it  will be  useful, but  WITHOUT
00015   * ANY  WARRANTY; without  even  the implied  warranty  of MERCHANTABILITY  or
00016   * FITNESS FOR A  PARTICULAR PURPOSE.  See the GNU  General Public License for
00017   * more details.
00018   * 
00019   * You should  have received a  copy of the  GNU General Public  License along
00020   * with  plint; see  the file  COPYING.  If  not, write  to the  Free Software
00021   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA USA.
00022   *
00023   */
00024 
00025 #pragma GCC dependency "Makefile" maybe some command line defines have changed
00026 
00038 #include "plint.h"
00039 #include "error.h"
00040 
00041 #include "op.h"
00042 
00043 #define PLINT_SGN(__x__) ((__x__) < 0 ? -1 : +1)
00044 #define PLINT_MIN(__a__, __b__) (((__a__) < (__b__)) ? (__a__) : (__b__))
00045 #define PLINT_MAX(__a__, __b__) (((__a__) > (__b__)) ? (__a__) : (__b__))
00046 
00060 int plint_num_nat(plint_num_t n)
00061 {
00062   int ret = plint_num_n2i(n);
00063   return (ret < 0) ? -ret : ret;
00064 }
00065 
00071 plint_num_t plint_num_rnd(plint_num_t n)
00072 {
00073   n.val.num_int = 1 + (int)(((double)plint_num_nat(n))*rand()/(RAND_MAX+1.0));
00074   return n;
00075 }
00076 
00080 #define PLINT_OP_MINX(__fnc__,__op__)                                   \
00081 plint_num_t plint_num_##__fnc__(plint_num_t l, plint_num_t r)           \
00082 {                                                                       \
00083   plint_num_t x;                                                        \
00084   if (0);                                                               \
00085   else if (l.typ == PLINT_num_int && r.typ == PLINT_num_int)            \
00086     x = (l.val.num_int __op__ r.val.num_int) ? l : r;                   \
00087   else if (l.typ == PLINT_num_int && r.typ == PLINT_num_dbl)            \
00088     {                                                                   \
00089       x.typ = PLINT_num_dbl;                                            \
00090       x.val.num_dbl = (((double)l.val.num_int) __op__ r.val.num_dbl) ?  \
00091                         (double)l.val.num_int : r.val.num_dbl;          \
00092     }                                                                   \
00093   else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_int)            \
00094     {                                                                   \
00095       x.typ = PLINT_num_dbl;                                            \
00096       x.val.num_dbl = (l.val.num_dbl __op__ ((double)r.val.num_int)) ?  \
00097                         l.val.num_dbl : (double)r.val.num_int;          \
00098     }                                                                   \
00099   else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_dbl)            \
00100     x = (l.val.num_dbl __op__ r.val.num_dbl) ? l : r;                   \
00101   else                                                                  \
00102     PLINT_ERROR(PLINT_ERR_EVEXPR);                                      \
00103   return x;                                                             \
00104 }
00105 
00106 PLINT_OP_MINX(min, <)
00107 PLINT_OP_MINX(max, >)
00108 
00130 #define PLINT_OP_ARITM(__fnc__,__op__)                                  \
00131 void plint_num_##__fnc__(plint_num_t * l, plint_num_t r)                \
00132 {                                                                       \
00133   if (0);                                                               \
00134   else if (l->typ == PLINT_num_int && r.typ == PLINT_num_int)           \
00135     {                                                                   \
00136       l->typ = PLINT_num_int;                                           \
00137       l->val.num_int __op__##= r.val.num_int;                           \
00138     }                                                                   \
00139   else if (l->typ == PLINT_num_int && r.typ == PLINT_num_dbl)           \
00140     {                                                                   \
00141       l->typ = PLINT_num_dbl;                                           \
00142       l->val.num_dbl = ((double)l->val.num_int) __op__ r.val.num_dbl;   \
00143     }                                                                   \
00144   else if (l->typ == PLINT_num_dbl && r.typ == PLINT_num_int)           \
00145     {                                                                   \
00146       l->typ = PLINT_num_dbl;                                           \
00147       l->val.num_dbl = l->val.num_dbl __op__ ((double)r.val.num_int);   \
00148     }                                                                   \
00149   else if (l->typ == PLINT_num_dbl && r.typ == PLINT_num_dbl)           \
00150     {                                                                   \
00151       l->typ = PLINT_num_dbl;                                           \
00152       l->val.num_dbl __op__##= r.val.num_dbl;                           \
00153     }                                                                   \
00154   else                                                                  \
00155     PLINT_ERROR(PLINT_ERR_EVEXPR);                                      \
00156 }
00157 
00158 
00159 PLINT_OP_ARITM(add, +)
00160 PLINT_OP_ARITM(sub, -)
00161 PLINT_OP_ARITM(mul, *)
00162 PLINT_OP_ARITM(div, /)
00163 
00164 #undef PLINT_OP_ARITM
00165 
00166 void plint_num_rem(plint_num_t * l, plint_num_t r)
00167 {
00168   if (0);
00169   else if (l->typ == PLINT_num_int && r.typ == PLINT_num_int)
00170     {
00171       l->typ = PLINT_num_int;
00172       l->val.num_int = l->val.num_int % r.val.num_int;
00173     }
00174   else
00175     PLINT_ERROR(PLINT_ERR_EVEXPR);
00176 }
00177 
00178 
00179 /* TODO
00180   if (r.typ == PLINT_num_int && r.val.num_int == 0 || r.typ == PLINT_num_dbl && r.val.num_dbl == 0)
00181     PLINT_ERROR(PLINT_ERR_DIV0);
00182 */
00183 
00184 void plint_num_umin(plint_num_t * n)
00185 {
00186   switch (n->typ)
00187     {
00188     case PLINT_num_int:
00189       n->val.num_int = -n->val.num_int;
00190       break;
00191 
00192     case PLINT_num_dbl:
00193       n->val.num_dbl = -n->val.num_dbl;
00194       break;
00195 
00196     default:
00197       PLINT_ERROR(PLINT_ERR_EVEXPR);
00198     }
00199 }
00200 
00201 void plint_num_upls(plint_num_t * n)
00202 {
00203   switch (n->typ)
00204     {
00205     case PLINT_num_int:
00206       break;
00207 
00208     case PLINT_num_dbl:
00209       break;
00210 
00211     default:
00212       PLINT_ERROR(PLINT_ERR_EVEXPR);
00213     }
00214 }
00215 
00216 void plint_num_udiv(plint_num_t * n)
00217 {
00218   switch (n->typ)
00219     {
00220     case PLINT_num_int:
00221       n->typ = PLINT_num_dbl;
00222       n->val.num_dbl = 1./(double)n->val.num_int;
00223       break;
00224 
00225     case PLINT_num_dbl:
00226       n->val.num_dbl = 1./n->val.num_dbl;
00227       break;
00228 
00229     default:
00230       PLINT_ERROR(PLINT_ERR_EVEXPR);
00231     }
00232 }
00233 
00241 #define PLINT_OP_LOGIC(__fnc__,__op__)                          \
00242 void plint_num_##__fnc__(plint_num_t * l, plint_num_t r)        \
00243 {                                                               \
00244   if (l->typ == PLINT_num_int && r.typ == PLINT_num_int)        \
00245     l->val.num_int __op__##= r.val.num_int;                     \
00246   else                                                          \
00247     PLINT_ERROR(PLINT_ERR_EVEXPR);                              \
00248 }
00249 
00250 
00251 PLINT_OP_LOGIC(and, &)
00252 PLINT_OP_LOGIC(or , |)
00253 PLINT_OP_LOGIC(xor, ^)
00254 
00255 #undef PLINT_OP_LOGIC
00256 
00257 
00258 void plint_num_unot(plint_num_t * n)
00259 {
00260   if (n->typ == PLINT_num_int)
00261     n->val.num_int = ~n->val.num_int;
00262   else
00263     PLINT_ERROR(PLINT_ERR_EVEXPR);
00264 }
00265 
00273 #define PLINT_OP_COMPARE(__fnc__, __op__)                               \
00274 int plint_num_##__fnc__(plint_num_t l, plint_num_t r)                   \
00275 {                                                                       \
00276   if (0)                                                                \
00277     return 0;                                                           \
00278   else if (l.typ == PLINT_num_int && r.typ == PLINT_num_int)            \
00279     return l.val.num_int __op__ r.val.num_int;                          \
00280   else if (l.typ == PLINT_num_int && r.typ == PLINT_num_dbl)            \
00281     return ((double)l.val.num_int) __op__ r.val.num_dbl;                \
00282   else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_int)            \
00283     return l.val.num_dbl __op__ ((double)r.val.num_int);                \
00284   else if (l.typ == PLINT_num_dbl && r.typ == PLINT_num_dbl)            \
00285     return l.val.num_dbl __op__ r.val.num_dbl;                          \
00286   else                                                                  \
00287     PLINT_ERROR(PLINT_ERR_EVEXPR);                                      \
00288 }
00289 
00290 
00291 PLINT_OP_COMPARE(lt , < )
00292 PLINT_OP_COMPARE(gt , > )
00293 PLINT_OP_COMPARE(lte, <=)
00294 PLINT_OP_COMPARE(gte, >=)
00295 PLINT_OP_COMPARE(equ, ==)
00296 PLINT_OP_COMPARE(neq, !=)
00297 
00298 
00299 #undef PLINT_OP_COMPARE
00300 
00315 inline void plint_pnt_ucnj(plint_pnt_t * p)
00316 {
00317   p->y = -p->y;
00318 }
00319 
00320 #define PLINT_OP_ARITM(__fun__, __op__)                         \
00321 inline void plint_pnt_##__fun__(plint_pnt_t * l, plint_pnt_t r) \
00322 {                                                               \
00323   l->x __op__##= r.x;                                           \
00324   l->y __op__##= r.y;                                           \
00325 }
00326 
00327 PLINT_OP_ARITM(add, +)
00328 PLINT_OP_ARITM(sub, -)
00329 
00330 #undef PLINT_OP_ARITM
00331 
00332 void plint_pnt_mul(plint_pnt_t * l, plint_pnt_t r)
00333 {
00334   plint_pnt_t ll = *l;
00335   l->x = ll.x * r.x - ll.y * r.y;
00336   l->y = ll.x * r.y + ll.y * r.x;
00337 }
00338 
00339 void plint_pnt_div(plint_pnt_t * l, plint_pnt_t r)
00340 {
00341   PLINT_ERROR(PLINT_ERR_EVEXPR);
00342 }
00343 
00344 inline void plint_pnt_umin(plint_pnt_t * p)
00345 {
00346   p->x = -p->x;
00347   p->y = -p->y;
00348 }
00349 
00357 #define PLINT_PNT_CMP(__fnc__, __op__)                          \
00358 inline int plint_pnt_##__fnc__(plint_pnt_t l, plint_pnt_t r)    \
00359 {                                                               \
00360   return (l.x __op__ r.x) && (r.y __op__ r.y);                  \
00361 }
00362 
00363 PLINT_PNT_CMP(equ, ==)
00364 PLINT_PNT_CMP(neq, !=)
00365 PLINT_PNT_CMP(lte, <=)
00366 PLINT_PNT_CMP(gte, >=)
00367 PLINT_PNT_CMP(lt , < )
00368 PLINT_PNT_CMP(gt , > )
00369 
00370 #undef PLINT_PNT_CMP
00371 
00379 #define PLINT_OP_ARITM(__fnc__, __op__)                                 \
00380 void plint_pnt_num_##__fnc__(plint_pnt_t * l, plint_num_t r)            \
00381 {                                                                       \
00382   double d = plint_num_n2d(r);                                          \
00383   l->x __op__##= d;                                                     \
00384   l->y __op__##= d;                                                     \
00385 }
00386 
00387 PLINT_OP_ARITM(add, +)
00388 PLINT_OP_ARITM(sub, -)
00389 PLINT_OP_ARITM(mul, *)
00390 PLINT_OP_ARITM(div, /)
00391 
00392 void plint_pnt_num_rem(plint_pnt_t * l, plint_num_t r)
00393 {
00394   int i = plint_num_n2i(r);
00395   l->x %= i;
00396   l->y %= i;
00397 }
00398 
00399 #undef PLINT_OP_ARITM
00400 
00412 /*
00413  * arithmetic operations
00414  */
00415 
00416 #define PLINT_OP_ARITM(__fun__)                                 \
00417 inline void plint_2pt_##__fun__(plint_2pt_t * l, plint_2pt_t r) \
00418 {                                                               \
00419   plint_pnt_##__fun__(0+l->PP, r.P.I);                          \
00420   plint_pnt_##__fun__(1+l->PP, r.P.Z);                          \
00421 }
00422 
00423 PLINT_OP_ARITM(add)
00424 PLINT_OP_ARITM(sub)
00425 PLINT_OP_ARITM(mul)
00426 
00427 inline void plint_2pt_invX(plint_2pt_t * p)
00428 {
00429   p->P.I.x = -p->P.I.x; p->P.Z.x = -p->P.Z.x;
00430 }
00431 
00432 inline void plint_2pt_invY(plint_2pt_t * p)
00433 {
00434   p->P.I.y = -p->P.I.y; p->P.Z.y = -p->P.Z.y;
00435 }
00436 
00437 inline void plint_2pt_invO(plint_2pt_t * p)
00438 {
00439   plint_2pt_invX(p); plint_2pt_invY(p);
00440 }
00441 
00442 #undef PLINT_OP_ARITM
00443 
00444 
00445 /*
00446  * geometrical operations
00447  */
00448 
00449 inline void plint_2pt_int(plint_2pt_t * l, plint_2pt_t r)
00450 {
00451   plint_2pt_t *lr[2] = { l, &r };
00452   int f[2] = { 0, 0 }, fk;
00453   int i, j, k;
00454 
00455   for (k = 0; k < 2; ++k)
00456     for (i = 0; i < 2; ++i, *lr[k] = plint_2pt_cross(*lr[k]))
00457       for (j = 0; j < 2; ++i, *lr[k] = plint_2pt_switch(*lr[k]))
00458         if (plint_pnt_ine_2pt(lr[k]->P.I, *lr[1-k]))
00459           {
00460             f[k] = !0;
00461             i = j = 1;
00462           }
00463   
00464   for(fk = !0; ;fk = !fk)
00465     {
00466       for (k = 0; k < 2; ++k)
00467         if (f[k] == fk)
00468           break;
00469 
00470       if (fk)
00471         {
00472           if (k == 2)
00473             {
00474               plint_2pt_t ret = PLINT_2pt_INIT_NUL;
00475               *l = ret;
00476               return;
00477             }
00478         }
00479       else
00480         {
00481           switch (k)
00482             {
00483             case 0: *l = r; break;
00484             case 1: break;
00485             case 2: l->P.Z = r.P.I; break;
00486             }
00487           return;
00488         }
00489     }
00490 }
00491 
00492 inline void plint_2pt_reu(plint_2pt_t * l, plint_2pt_t r)
00493 {
00494   plint_2pt_t ll = plint_2pt_canonic(*l), rr = plint_2pt_canonic(r);
00495   plint_2pt_t lr = PLINT_2pt_INIT(ll.rect.TopLeft, rr.rect.TopLeft), LR = PLINT_2pt_INIT(ll.rect.BotRight, rr.rect.BotRight);
00496   lr = plint_2pt_canonic(lr); LR = plint_2pt_canonic(LR); 
00497   l->rect.TopLeft = lr.rect.TopLeft; l->rect.BotRight = LR.rect.BotRight;
00498 }
00499 
00500 
00501 /*
00502  * comparison operators
00503  */
00504 
00505 #define PLINT_2PT_CMP(__fnc__)                                          \
00506 inline int plint_2pt_##__fnc__(plint_2pt_t l, plint_2pt_t r)            \
00507 {                                                                       \
00508   plint_2pt_t ll = plint_2pt_canonic(l), rr = plint_2pt_canonic(r);     \
00509   return plint_pnt_##__fnc__(ll.rect.TopLeft, rr.rect.TopLeft) &&       \
00510          plint_pnt_##__fnc__(ll.rect.BotRight, rr.rect.BotRight);       \
00511 }
00512 
00513 PLINT_2PT_CMP(equ)
00514 PLINT_2PT_CMP(lt )
00515 PLINT_2PT_CMP(gt )
00516 
00517 inline int plint_2pt_neq(plint_2pt_t l, plint_2pt_t r)
00518 {
00519   return !plint_2pt_equ(l, r);
00520 }
00521 
00522 inline int plint_2pt_lte(plint_2pt_t l, plint_2pt_t r)
00523 {
00524   return !plint_2pt_gt (l, r);
00525 }
00526 
00527 inline int plint_2pt_gte(plint_2pt_t l, plint_2pt_t r)
00528 {
00529   return !plint_2pt_lt (l, r);
00530 }
00531 
00532 #undef PLINT_2PT_CMP
00533 
00534 
00535 /*
00536  * mixt arithmetic with numbers
00537  */
00538 
00539 #define PLINT_OP_ARITM(__fnc__)                                 \
00540 void plint_2pt_num_##__fnc__(plint_2pt_t * l, plint_num_t r)    \
00541 {                                                               \
00542   plint_pnt_num_##__fnc__(&l->P.I, r);                          \
00543   plint_pnt_num_##__fnc__(&l->P.Z, r);                          \
00544 }
00545 
00546 PLINT_OP_ARITM(add)
00547 PLINT_OP_ARITM(sub)
00548 PLINT_OP_ARITM(mul)
00549 PLINT_OP_ARITM(div)
00550 PLINT_OP_ARITM(rem)
00551 
00552 #undef PLINT_OP_ARITM
00553 
00554 
00555 /*
00556  * mixt arithmetic with points
00557  */
00558 
00559 #define PLINT_OP_ARITM(__fnc__)                                 \
00560 void plint_2pt_pnt_##__fnc__(plint_2pt_t * l, plint_pnt_t r)    \
00561 {                                                               \
00562   plint_pnt_##__fnc__(&l->P.I, r);                              \
00563   plint_pnt_##__fnc__(&l->P.Z, r);                              \
00564 }
00565 
00566 PLINT_OP_ARITM(add)
00567 PLINT_OP_ARITM(sub)
00568 PLINT_OP_ARITM(mul)
00569 
00570 #undef PLINT_OP_ARITM
00571 
00572 
00573 /*
00574  * mixt comparison with points
00575  */
00576 
00577 inline int plint_pnt_in_2pt(plint_pnt_t l, plint_2pt_t r)
00578 {
00579   return
00580     PLINT_SGN(l.x-r.P.I.x) + PLINT_SGN(l.x-r.P.Z.x) == 0 &&
00581     PLINT_SGN(l.y-r.P.I.y) + PLINT_SGN(l.y-r.P.Z.y) == 0 ;;
00582 }
00583 inline int plint_pnt_ine_2pt(plint_pnt_t l, plint_2pt_t r)
00584 {
00585   return
00586     plint_pnt_in_2pt(l, r) ||
00587     l.x == r.P.I.x || l.x == r.P.Z.x ||
00588     l.y == r.P.I.y || l.y == r.P.Z.y ;;
00589 }
00590 inline int plint_pnt_out_2pt(plint_pnt_t l, plint_2pt_t r)
00591 {
00592   return !plint_pnt_ine_2pt(l, r);
00593 }
00594 inline int plint_pnt_oute_2pt(plint_pnt_t l, plint_2pt_t r)
00595 {
00596   return !plint_pnt_in_2pt(l, r);
00597 }
00598 
00607 #include <regex.h>
00608 
00609 
00610 #define PLINT_str_ACUM(__r__, __n__, __s__)             \
00611 ({                                                      \
00612   plint_str_t __x = PLINT_str_INIT(__s__, __n__);       \
00613   char __y = __x.s[__x.n];                              \
00614   __x.s[__x.n] = '\0';                                  \
00615   plint_str_add(&__r__, __x);                           \
00616   __x.s[__x.n] = __y;                                   \
00617 })
00618 
00619 
00620 /*
00621  * operators
00622  */
00623 
00624 void plint_str_mul(plint_str_t * s, size_t i)
00625 {
00626   plint_str_t r;
00627   PLINT_str_NEW(r, s->n * i);
00628   if (r.n)
00629     for (; i; strncpy(r.s + (--i * s->n), s->s, s->n));
00630   r.s[r.n] = '\0';
00631   plint_str_fre(*s);
00632   *s = r;
00633 }
00634 
00635 /*
00636  * removing heading & trailing characters from the second string
00637  */
00638 
00639 void plint_str_sub(plint_str_t * x, plint_str_t y)
00640 {
00641   plint_str_t ret;
00642   size_t l, r;
00643   l = strspn(x->s, y.s);
00644   if (l < x->n)
00645     {
00646       plint_str_t s = plint_str_str(*x, -1, 0);
00647       r = strspn(s.s, y.s);
00648       plint_str_fre(s);
00649       ret = plint_str_new(x->s + l, x->n - l - r);
00650     }
00651   else
00652     PLINT_str_EMPTY(ret);
00653 
00654   plint_str_fre(*x);
00655   *x = ret;
00656 }
00657 
00658 /*
00659  * removing all characters from the second string existent in the first
00660  */
00661 
00662 void plint_str_rem(plint_str_t * l, plint_str_t t)
00663 {
00664   size_t i = -1, n;
00665   plint_str_t r;
00666   PLINT_str_EMPTY(r);
00667   while (++i < l->n)
00668     if ((n = strcspn(l->s + i, t.s)) > 0)
00669       {
00670         PLINT_str_ACUM(r, n, l->s + i);
00671         i += n;
00672       }
00673   plint_str_fre(*l);
00674   *l = r;
00675 }
00676 
00677 void plint_str_sed(plint_str_t * replace, plint_str_t regex, plint_str_t with)
00678 {
00679   plint_str_t ret;
00680   regex_t reg;
00681   regmatch_t rem[10];
00682   regoff_t off;
00683   int n_sub = 0, (*a_sub)[2];
00684 
00685   if (regex.n == 0)
00686     PLINT_str_EMPTY(ret);
00687   else
00688     {
00689       if (regcomp(&reg, regex.s, PLINT_REX_FLAGS))
00690         {
00691           plint_str_fre(*replace); plint_str_fre(regex); plint_str_fre(with);
00692           PLINT_ERROR(PLINT_ERR_REX);
00693         }
00694       
00695       {
00696         char * w = with.s;
00697         a_sub = malloc(sizeof(int[2]));
00698         a_sub[n_sub++][0] = -2;
00699         while ((w = strchr(w, '\\')) && *++w)
00700           if (isdigit(*w))
00701             {
00702               a_sub = realloc(a_sub, ++n_sub*sizeof(int[2]));
00703               a_sub[n_sub-1][0] = w-with.s-1;
00704               a_sub[n_sub-1][1] = *w-'0';
00705             }
00706       }
00707       
00708       PLINT_str_EMPTY(ret);
00709 
00710       rem->rm_eo = off = 0;
00711 
00712       while (!regexec(&reg, replace->s + (off += rem->rm_eo), 10, rem, 0))
00713         {
00714           int m, n;
00715     
00716           if (rem->rm_so > 0)
00717             PLINT_str_ACUM(ret, rem->rm_so, replace->s + off);
00718 
00719           for (m = 1; m < n_sub; ++m)
00720             {
00721               n = a_sub[m][0]-a_sub[m-1][0];
00722               if (n > 2)
00723                 PLINT_str_ACUM(ret, n-2, with.s+a_sub[m-1][0]+2);
00724               n = a_sub[m][1];
00725               if (rem[n].rm_so < rem[n].rm_eo)
00726                 PLINT_str_ACUM(ret, rem[n].rm_eo-rem[n].rm_so, replace->s+off+rem[n].rm_so);
00727             }
00728           n = with.n-a_sub[m-1][0];
00729           if (n > 2)
00730             PLINT_str_ACUM(ret, n-2, with.s+a_sub[m-1][0]+2);
00731         }
00732 
00733       if (off < replace->n)
00734         PLINT_str_ACUM(ret, replace->n-off, replace->s+off);
00735 
00736       free(a_sub);
00737       regfree(&reg);
00738     }
00739 
00740   plint_str_fre(*replace);
00741   *replace = ret;
00742 }
00743 
00744 plint_tab_t plint_str_rex(plint_str_t l, plint_str_t t)
00745 {
00746   plint_tab_t ret;
00747 
00748   regex_t reg;
00749   regmatch_t rem;
00750   regoff_t off;
00751 
00752   plint_ptr_t ptr = PLINT_PTR_NEW(tab, PLINT_tab_INIT_NUL);
00753 
00754   if (l.n > 0)
00755     {
00756       if (regcomp(&reg, l.s, PLINT_REX_FLAGS))
00757         {
00758           plint_str_fre(l); plint_str_fre(t); plint_ptr_fre(ptr);
00759           PLINT_ERROR(PLINT_ERR_REX);
00760         }
00761 
00762       rem.rm_eo = off = 0;
00763 
00764       while (!regexec(&reg, t.s + (off += rem.rm_eo), 1, &rem, 0))
00765         {
00766           plint_str_t x = plint_str_new(t.s + off + rem.rm_so, rem.rm_eo - rem.rm_so);
00767           PLINT_tab_GROW(ptr->val.tab, +=1);
00768           ptr->val.tab.a[ptr->val.tab.n-1] = plint_bar_new(PLINT_PTR_NEW(tab, PLINT_tab_INIT(2)));
00769           0[plint_var_tab(ptr->val.tab.a[ptr->val.tab.n-1]) .a] = plint_bar_new(PLINT_PTR_NEW(num_int, off + rem.rm_so));
00770           1[plint_var_tab(ptr->val.tab.a[ptr->val.tab.n-1]) .a] = plint_bar_new(plint_str_ptr(x));
00771         }
00772 
00773       regfree(&reg);
00774     }
00775 
00776   ret = plint_tab_dup(ptr->val.tab);
00777   plint_ptr_fre(ptr);
00778 
00779   return ret;
00780 }
00781 
00782 void plint_str_loc(plint_str_t * x)
00783 {
00784   for (x->n = 0; x->s[x->n]; ++x->n)
00785     x->s[x->n] = tolower(x->s[x->n]);
00786 }
00787 
00788 void plint_str_upc(plint_str_t * x)
00789 {
00790   for (x->n = 0; x->s[x->n]; ++x->n)
00791     x->s[x->n] = tolower(x->s[x->n]);
00792 }
00793 
00794 /*
00795  * comparison operators
00796  */
00797 
00798 int plint_str_inc(plint_str_t needle, plint_str_t haystack, int d)
00799 {
00800   if (!needle.n)
00801     return !0;
00802   if (!haystack.n)
00803     return 0;
00804   return !! ((d > 0 ) ? strstr(haystack.s, needle.s) : strstr(needle.s, haystack.s));
00805 }
00806 
00807 #undef PLINT_str_ACUM
00808 
00818 /*
00819  * arithmetic operators
00820  */
00821 
00822 void plint_tab_mul(plint_tab_t * t, size_t m)
00823 {
00824   if (!m) {
00825     plint_tab_fre(*t);
00826     PLINT_tab_EMPTY(*t);
00827   } else {
00828     size_t n = t->n, k, l = n * m;
00829     PLINT_tab_GROW(*t, *=m);
00830     while (--m)
00831       for (k = n; k--; )
00832         t->a[--l] = plint_var_dup(t->a[k]);
00833   }
00834 }
00835 
00836 /*
00837  * comparison operators
00838  */
00839 
00840 int plint_tab_equ(plint_tab_t l, plint_tab_t r)
00841 {
00842   if (l.n == r.n)
00843     {
00844       size_t i, n = l.n;
00845       for (i = 0; i < n && plint_val_equ(plint_var_val(l.a[i]), plint_var_val(r.a[i])); ++i);
00846       return i == n;
00847     }
00848   return 0;
00849 }
00850 
00851 inline int plint_tab_neq(plint_tab_t l, plint_tab_t r)
00852 {
00853   return !plint_tab_equ(l, r);
00854 }
00855 
00856 
00857 /*
00858  * has and includes operator
00859  */
00860 
00861 #define PLINT_TAB_CMP(__fnc__, __lt__, __rt__)                                          \
00862 int plint_tab_##__fnc__(plint_##__lt__##_t * __lt__, plint_##__rt__##_t * __rt__)       \
00863 {                                                                                       \
00864   size_t i, n = tab->n;                                                                 \
00865   for (i = 0; i < n && !plint_val_equ(plint_var_val(i[tab->a]), *ptr); ++i);            \
00866   return i < n;                                                                         \
00867 }
00868 
00869 
00870 PLINT_TAB_CMP(lt, ptr, tab)
00871 PLINT_TAB_CMP(gt, tab, ptr)
00872 
00873 #undef PLINT_TAB_CMP
00874 
00875 
00876 #define PLINT_TAB_CMP(__fnc__, __lt__, __rt__)                                          \
00877 int plint_tab_##__fnc__(plint_##__lt__##_t * __lt__, plint_##__rt__##_t * __rt__)       \
00878 {                                                                                       \
00879   return plint_tab_##__fnc__(__lt__, __rt__) ||                                         \
00880          ( ((*ptr)->typ == PLINT_tab) ? plint_tab_equ(*tab, (*ptr)->val.tab) : 0);      \
00881 }
00882 
00883 
00884 PLINT_TAB_CMP(lte, ptr, tab)
00885 PLINT_TAB_CMP(gte, tab, ptr)
00886 
00887 #undef PLINT_TAB_CMP
00888 
00889 /*
00890  * applying a function for each element with an external value
00891  */
00892 
00893 
00894 /*
00895  * external value is a number
00896  */
00897 
00898 static plint_ptr_t tab_ptr;
00899 static plint_num_t tab_num;
00900 
00901 #define PLINT_OP_ARITM(__fun__)                         \
00902 static void tab_num_##__fun__(plint_tab_t * t)          \
00903 {                                                       \
00904   size_t i;                                             \
00905   static plint_num_t m;                                 \
00906   static plint_pnt_t p;                                 \
00907   for (i = t->n; i; )                                   \
00908     switch ((tab_ptr = t->a[--i]->ptr)->typ)            \
00909     {                                                   \
00910       case PLINT_tab:                                   \
00911         tab_num_##__fun__(&tab_ptr->val.tab);           \
00912         break;                                          \
00913       case PLINT_num_int: case PLINT_num: case PLINT_num_dbl:   \
00914         m = plint_ptr_num(tab_ptr);                     \
00915         plint_num_##__fun__(&m, tab_num);               \
00916         plint_num_set(tab_ptr, m);                      \
00917         break;                                          \
00918       case PLINT_pnt:                                   \
00919         p = plint_ptr_pnt(tab_ptr);                     \
00920         plint_pnt_num_##__fun__(&p, tab_num);           \
00921         plint_pnt_set(tab_ptr, p);                      \
00922         break;                                          \
00923       default:                                          \
00924        PLINT_ERROR(PLINT_ERR_VAR_TYP);                  \
00925     }                                                   \
00926 }                                                       \
00927 void plint_tab_num_##__fun__(plint_tab_t * t, plint_num_t n)\
00928 {                                                       \
00929   tab_num = n;                                          \
00930   tab_num_##__fun__(t);                                 \
00931 }
00932 
00933 PLINT_OP_ARITM(add)
00934 PLINT_OP_ARITM(mul)
00935 
00936 #define PLINT_OP_LOGIC(__fun__)                         \
00937 static void tab_num_##__fun__(plint_tab_t * t)          \
00938 {                                                       \
00939   size_t i;                                             \
00940   static plint_num_t m;                                 \
00941   for (i = t->n; i; )                                   \
00942     switch ((tab_ptr = t->a[--i]->ptr)->typ)            \
00943     {                                                   \
00944       case PLINT_tab:                                   \
00945         tab_num_##__fun__(&tab_ptr->val.tab);           \
00946         break;                                          \
00947       case PLINT_num_int: case PLINT_num: case PLINT_num_dbl:   \
00948         m = plint_ptr_num(tab_ptr);                     \
00949         plint_num_##__fun__(&m, tab_num);               \
00950         plint_num_set(tab_ptr, m);                      \
00951         break;                                          \
00952       default:                                          \
00953        PLINT_ERROR(PLINT_ERR_VAR_TYP);                  \
00954     }                                                   \
00955 }                                                       \
00956 void plint_tab_num_##__fun__(plint_tab_t * t, plint_num_t n)\
00957 {                                                       \
00958   tab_num = n;                                          \
00959   tab_num_##__fun__(t);                                 \
00960 }
00961 
00962 PLINT_OP_LOGIC(and)
00963 PLINT_OP_LOGIC(or )
00964 PLINT_OP_LOGIC(xor)
00965 
00966 #undef PLINT_OP_ARITM
00967 #undef PLINT_OP_LOGIC
00968 
00969 #define PLINT_OP_ARITM(__fun__)                                 \
00970 static plint_num_t tab_num_l, tab_num_r, * tab_num_p;           \
00971 static void tab_num_##__fun__(plint_tab_t * t)                  \
00972 {                                                               \
00973   size_t i;                                                     \
00974   for (i = t->n; i; )                                           \
00975     switch ((tab_ptr = t->a[--i]->ptr)->typ)                    \
00976     {                                                           \
00977       case PLINT_tab:                                           \
00978         tab_num_##__fun__(&tab_ptr->val.tab);                   \
00979         break;                                                  \
00980       case PLINT_num_int:                                       \
00981       case PLINT_num_dbl:                                       \
00982         tab_num_l = tab_num_r = tab_num;                        \
00983         *tab_num_p = plint_ptr_num(tab_ptr);                    \
00984         plint_num_##__fun__(&tab_num_l, tab_num_r);             \
00985         plint_num_set(tab_ptr, tab_num_l);                      \
00986         break;                                                  \
00987       default:                                                  \
00988        PLINT_ERROR(PLINT_ERR_VAR_TYP);                          \
00989     }                                                           \
00990 }                                                               \
00991 void plint_tab_num_##__fun__(plint_tab_t * t, plint_num_t n, int d)\
00992 {                                                               \
00993   tab_num = n;                                                  \
00994   tab_num_p = (d < 0) ? &tab_num_l : &tab_num_r;                \
00995   tab_num_##__fun__(t);                                         \
00996 }
00997 
00998 
00999 PLINT_OP_ARITM(sub)
01000 PLINT_OP_ARITM(div)
01001 PLINT_OP_ARITM(rem)
01002 
01003 #undef PLINT_OP_ARITM
01004 
01005 
01006 /*
01007  * external value is a point, string
01008  */
01009 
01010 static plint_pnt_t tab_pnt;
01011 static plint_str_t tab_str;
01012 #define PLINT_OP_ARITM(__typ__, __fun__)                                        \
01013 static void tab_##__typ__##_##__fun__(plint_tab_t * t)                          \
01014 {                                                                               \
01015   size_t i;                                                                     \
01016   for (i = t->n; i; )                                                           \
01017    switch ((tab_ptr = t->a[--i]->ptr)->typ)                                     \
01018     {                                                                           \
01019       case PLINT_tab:                                                           \
01020         tab_##__typ__##_##__fun__(&tab_ptr->val.tab);                           \
01021         break;                                                                  \
01022       case PLINT_##__typ__:                                                     \
01023         plint_##__typ__##_##__fun__(&tab_ptr->val.__typ__,                      \
01024                                      tab_##__typ__);                            \
01025         break;                                                                  \
01026       default:                                                                  \
01027        PLINT_ERROR(PLINT_ERR_VAR_TYP);                                          \
01028     }                                                                           \
01029 }                                                                               \
01030 void plint_tab_##__typ__##_##__fun__(plint_tab_t * t, plint_##__typ__##_t a)    \
01031 {                                                                               \
01032   tab_##__typ__ = a;                                                            \
01033   tab_##__typ__##_##__fun__(t);                                                 \
01034 }
01035 
01036 PLINT_OP_ARITM(pnt, add)
01037 PLINT_OP_ARITM(pnt, mul)
01038 
01039 #undef PLINT_OP_ARITM
01040 
01041 #define PLINT_OP_ARITM(__typ__, __fun__)                                                \
01042 static plint_##__typ__##_t                                                              \
01043   tab_##__typ__##_l,                                                                    \
01044   tab_##__typ__##_r,                                                                    \
01045   * tab_##__typ__##_p;                                                                  \
01046 static void tab_##__typ__##_##__fun__(plint_tab_t * t)                                  \
01047 {                                                                                       \
01048   size_t i;                                                                             \
01049   for (i = t->n; i; )                                                                   \
01050    switch ((tab_ptr = t->a[--i]->ptr)->typ)                                             \
01051     {                                                                                   \
01052       case PLINT_tab:                                                                   \
01053         tab_##__typ__##_##__fun__(&tab_ptr->val.tab);                                   \
01054         break;                                                                          \
01055       case PLINT_##__typ__:                                                             \
01056         tab_##__typ__##_l =                                                             \
01057         tab_##__typ__##_r = plint_##__typ__##_cpy(tab_##__typ__);                       \
01058         *tab_##__typ__##_p = tab_ptr->val.__typ__;                                      \
01059         plint_##__typ__##_##__fun__(&tab_##__typ__##_l, tab_##__typ__##_r);             \
01060         tab_ptr->val.__typ__ = plint_##__typ__##_cpy(tab_##__typ__##_l);                \
01061         plint_##__typ__##_fre(tab_##__typ__##_l);                                       \
01062         plint_##__typ__##_fre(tab_##__typ__##_r);                                       \
01063         break;                                                                          \
01064       default:                                                                          \
01065        PLINT_ERROR(PLINT_ERR_VAR_TYP);                                                  \
01066     }                                                                                   \
01067 }                                                                                       \
01068 void plint_tab_##__typ__##_##__fun__(plint_tab_t * t, plint_##__typ__##_t a, int d)     \
01069 {                                                                                       \
01070   tab_##__typ__ = plint_##__typ__##_cpy(a);                                             \
01071   tab_##__typ__##_p = (d < 0)                                                           \
01072                               ? &tab_##__typ__##_l                                      \
01073                               : &tab_##__typ__##_r;                                     \
01074   tab_##__typ__##_##__fun__(t);                                                         \
01075   plint_##__typ__##_fre(tab_##__typ__);                                                 \
01076 }
01077 
01078 
01079 PLINT_OP_ARITM(pnt, sub)
01080 PLINT_OP_ARITM(pnt, div)
01081 
01082 PLINT_OP_ARITM(str, add)
01083 PLINT_OP_ARITM(str, sub)
01084 PLINT_OP_ARITM(str, rem)
01085 
01086 #undef PLINT_OP_ARITM
01087 
01088 
01089 /*
01090  * external value is a boolean
01091  */
01092 
01093 static plint_bol_t tab_bol;
01094 
01095 #define PLINT_OP_LOGIC(__fun__, __op__)                         \
01096 static void tab_bol_##__fun__(plint_tab_t * t)                  \
01097 {                                                               \
01098   size_t i;                                                     \
01099   for (i = t->n; i; )                                           \
01100    switch ((tab_ptr = t->a[--i]->ptr)->typ)                     \
01101     {                                                           \
01102       case PLINT_tab:                                           \
01103         tab_bol_##__fun__(&tab_ptr->val.tab);                   \
01104         break;                                                  \
01105       case PLINT_num_int:                                       \
01106         tab_ptr->typ = PLINT_bol;                               \
01107         tab_ptr->val.bol = !!tab_ptr->val.num_int;              \
01108       case PLINT_bol:                                           \
01109         tab_ptr->val.bol __op__##= tab_bol;                     \
01110         break;                                                  \
01111       default:                                                  \
01112        PLINT_ERROR(PLINT_ERR_VAR_TYP);                          \
01113     }                                                           \
01114 }                                                               \
01115 void plint_tab_bol_##__fun__(plint_tab_t * t, plint_bol_t b)    \
01116 {                                                               \
01117   tab_bol = b;                                                  \
01118   tab_bol_##__fun__(&tab_ptr->val.tab);                         \
01119 }
01120 
01121 
01122 PLINT_OP_LOGIC(and, &)
01123 PLINT_OP_LOGIC(or , |)
01124 PLINT_OP_LOGIC(xor, ^)
01125 
01126 #undef PLINT_OP_LOGIC
01127 
01136 inline void plint_hsh_add(plint_hsh_t * l, plint_hsh_t r)
01137 {
01138   plint_hsh_cat(*l, r);
01139 }
01140 
01141 static int hsh_sub(hashindex_t hi, ns_key_t ns, plint_ref_t ref, plint_hsh_t hsh)
01142 {
01143   plint_str_t str;
01144   plint_hash_str(ns_hash(ns), hi, str);
01145   hi = plint_hsh_get(hsh, str, &ref);
01146   plint_str_fre(str);
01147 
01148   if (!HASH_INDEX_ISBAD(hi))
01149     plint_var_fre((plint_var_t)hash_remstr(hsh, hi));
01150 
01151   return !0;
01152 }
01153 
01154 inline void plint_hsh_sub(plint_hsh_t * l, plint_hsh_t r)
01155 {
01156   hash_iterdata_all(r, (hash_iterfunc_t)hsh_sub, * l);
01157 }
01158 
01159 /* A |~| B = AUB / ( A/B U B/A )*/
01160 void plint_hsh_mul(plint_hsh_t * l, plint_hsh_t r)
01161 {
01162   plint_hsh_t l_r = plint_hsh_dup(*l), r_l = plint_hsh_dup(r);
01163 
01164   plint_hsh_sub(&l_r, r);
01165   plint_hsh_sub(&r_l, *l);
01166 
01167   plint_hsh_add(l, r);
01168   plint_hsh_add(&l_r, r_l);
01169   plint_hsh_sub(l, l_r);
01170 
01171 
01172   plint_hsh_fre(l_r);
01173   plint_hsh_fre(r_l);
01174 }
01175 
01176 /*
01177  * comparison operators
01178  */
01179 
01180 int plint_hsh_equ(plint_hsh_t l, plint_hsh_t r)
01181 {
01182   return plint_hsh_lt(l, r) && plint_hsh_lt(r, l);
01183 }
01184 
01185 int plint_hsh_neq(plint_hsh_t l, plint_hsh_t r)
01186 {
01187   return !plint_hsh_lt(l, r) || !plint_hsh_lt(r, l);
01188 }
01189 
01190 
01191 /*
01192  * has and includes operator
01193  */
01194 
01195 typedef struct
01196 {
01197   plint_hsh_t in;
01198   int out;
01199 } hsh_lt_t;
01200 
01201 static int hsh_lt(hashindex_t hi, ns_key_t ns, plint_ref_t ref, hsh_lt_t * p)
01202 {
01203   plint_ptr_t val = plint_var_val(plint_ref_var(ref));
01204   plint_str_t str;
01205   plint_hash_str(ns_hash(ns), hi, str);
01206   hi = plint_hsh_get(p->in, str, &ref);
01207   p->out = (HASH_INDEX_ISBAD(hi)) ? 0 : plint_val_equ(val, plint_var_val(plint_ref_var(ref)));
01208   plint_str_fre(str);
01209 
01210   return p->out;
01211 }
01212 
01213 inline int plint_hsh_lt(plint_hsh_t l, plint_hsh_t r)
01214 {
01215   hsh_lt_t x = { in: r, out: !0 };
01216   hash_iterdata_all(l, (hash_iterfunc_t)hsh_lt, &x);
01217   return x.out;
01218 }
01219 inline int plint_hsh_gt(plint_hsh_t l, plint_hsh_t r)
01220 {
01221   return plint_hsh_lt(r, l);
01222 }
01223 inline int plint_hsh_lte(plint_hsh_t l, plint_hsh_t r)
01224 {
01225   return plint_hsh_lt(l, r);
01226 }
01227 inline int plint_hsh_gte(plint_hsh_t l, plint_hsh_t r)
01228 {
01229   return plint_hsh_gt(r, l);
01230 }
01231 
01240 /*
01241  * comparison operators
01242  */
01243 
01244 int plint_val_equ(plint_ptr_t l, plint_ptr_t r)
01245 {
01246   if (l->typ == r->typ)
01247     switch (l->typ)
01248       {
01249       case PLINT_bol:return l->val.bol == r->val.bol;
01250       case PLINT_num_int:return l->val.num_int == r->val.num_int;
01251       case PLINT_num_dbl:return l->val.num_dbl == r->val.num_dbl;
01252       case PLINT_pnt:return plint_pnt_equ(l->val.pnt, r->val.pnt);
01253       case PLINT_tab:return plint_tab_equ(l->val.tab, r->val.tab);
01254       case PLINT_str:return plint_str_equ(l->val.str, r->val.str);
01255 
01256       default:
01257         return !0;
01258       }
01259 
01260   return 0;
01261 }
01262 
01263 int plint_val_neq(plint_ptr_t l, plint_ptr_t r)
01264 {
01265   return (l != r);
01266 }
01267 
01268 #define PLINT_VAL_CMP(__fnc__, __op__)                                                          \
01269 int plint_val_##__fnc__(plint_ptr_t l, plint_ptr_t r)                                           \
01270 {                                                                                               \
01271   if (l->typ == r->typ)                                                                         \
01272     switch (l->typ)                                                                             \
01273       {                                                                                         \
01274       case PLINT_str:return 0;                                                                  \
01275       case PLINT_bol:return l->val.bol __op__ r->val.bol;                                       \
01276       case PLINT_num_int:return l->val.num_int __op__ r->val.num_int;                           \
01277       case PLINT_num_dbl:return l->val.num_dbl __op__ r->val.num_dbl;                           \
01278       case PLINT_pnt:return plint_pnt_##__fnc__(l->val.pnt, r->val.pnt);                        \
01279       case PLINT_tab:return (*#__op__ == '>') ? plint_tab_##__fnc__(&l->val.tab, &r):           \
01280                                                plint_tab_##__fnc__(&l, &r->val.tab);            \
01281                                                                                                 \
01282       default:                                                                                  \
01283         return 0;                                                                               \
01284                                                                                                 \
01285       }                                                                                         \
01286   else if (l->typ == PLINT_tab)                                                                 \
01287     return (*#__op__ == '>') ? plint_tab_##__fnc__(&l->val.tab, &r) : 0;                        \
01288   else if (r->typ == PLINT_tab)                                                                 \
01289     return (*#__op__ == '<') ? plint_tab_##__fnc__(&l, &r->val.tab) : 0;                        \
01290   return 0;                                                                                     \
01291 }
01292 
01293 
01294 PLINT_VAL_CMP(lt  , < )
01295 PLINT_VAL_CMP(gt  , > )
01296 PLINT_VAL_CMP(lte , <=)
01297 PLINT_VAL_CMP(gte , >=)
01298 
01299 #undef PLINT_VAL_CMP
01300 
01305 #undef PLINT_SGN
01306 #undef PLINT_MIN
01307 #undef PLINT_MAX
01308 

Generated on Thu Jan 9 19:02:38 2003 for plint by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002