1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
   2: static char rcsid[] = "$Header: bobj.c,v 2.5 85/08/22 15:59:59 timo Exp $";
   3: 
   4: /*
   5:  * B editor -- A shrunken version of the B interpreter's run-time system.
   6:  */
   7: 
   8: #include "b.h"
   9: #include "bobj.h"
  10: #include "node.h"
  11: 
  12: #define COMPOUNDS
  13: 
  14: string malloc();
  15: string calloc();
  16: string realloc();
  17: string strcpy();
  18: 
  19: extern bool dflag;
  20: 
  21: struct head {
  22:     char type;
  23:     intlet refcnt;
  24:     intlet len;
  25: };
  26: #define Intsize (sizeof(int))
  27: #define Hsize (sizeof(struct head))
  28: #define Headsize (((Hsize-1)/Intsize + 1) * Intsize)
  29: 
  30: #define Field(v, i) (((value *)&(v)->cts)[i])
  31: 
  32: #ifndef NDEBUG
  33: 
  34: /* Statistics on allocation/sharing */
  35: 
  36: int nobjs;
  37: int nrefs;
  38: 
  39: #define Increfs ++nrefs
  40: #define Decrefs --nrefs
  41: 
  42: #else NDEBUG
  43: 
  44: #define Increfs
  45: #define Decrefs
  46: 
  47: #endif NDEBUG
  48: 
  49: 
  50: #define Copy(v) if ((v) && Refcnt(v) < Maxintlet) { ++Refcnt(v); Increfs; }
  51: #define Release(v) if (!(v) || Refcnt(v) == Maxintlet) ; else RRelease(v)
  52: #define RRelease(v) \
  53:     if (Refcnt(v) > 1) { --Refcnt(v); Decrefs; } else release(v)
  54: 
  55: 
  56: /*
  57:  * Allocate a value with nbytes of data after the usual type, len, refcnt
  58:  * fields.
  59:  */
  60: 
  61: value
  62: grabber(nbytes)
  63:     register int nbytes;
  64: {
  65:     register value v = (value) malloc((unsigned) (Headsize + nbytes));
  66: 
  67:     if (!v)
  68:         syserr("grabber: malloc");
  69: #ifndef NDEBUG
  70:     if (dflag)
  71:         newval(v);
  72: #endif
  73: #ifndef NDEBUG
  74:     ++nobjs;
  75: #endif
  76:     Increfs;
  77:     v->refcnt = 1;
  78:     return v;
  79: }
  80: 
  81: 
  82: /*
  83:  * Reallocate a value with nbytes of data after the usual type, len, refcnt
  84:  * fields.
  85:  */
  86: 
  87: value
  88: regrabber(v, nbytes)
  89:     register value v;
  90:     register int nbytes;
  91: {
  92:     Assert(v && v->refcnt == 1);
  93:     v = (value) realloc((char*)v, (unsigned) (Headsize + nbytes));
  94:     if (!v)
  95:         syserr("regrabber: realloc");
  96:     return v;
  97: }
  98: 
  99: 
 100: /*
 101:  * Set an object's refcnt to infinity, so it will never be released.
 102:  */
 103: 
 104: fix(v)
 105:     register value v;
 106: {
 107:     register int i;
 108:     register node n;
 109:     register path p;
 110: 
 111:     Assert(v->refcnt > 0);
 112: #ifndef NDEBUG
 113:     if (v->refcnt < Maxintlet)
 114:         nrefs -= v->refcnt;
 115: #endif
 116:     v->refcnt = Maxintlet;
 117: #if OBSOLETE
 118:     switch (v->type) {
 119:     case Tex:
 120:         break;
 121:     case Nod:
 122:         n = (node)v;
 123:         for (i = v->len - 1; i >= 0; --i)
 124:             if (n->n_child[i])
 125:                 fix((value)(n->n_child[i]));
 126:         break;
 127:     case Pat:
 128:         p = (path)v;
 129:         if (p->p_parent)
 130:             fix((value)(p->p_parent));
 131:         if (p->p_tree)
 132:             fix((value)(p->p_tree));
 133:         break;
 134: #ifdef COMPOUNDS
 135:     case Com:
 136:         for (i = v->len-1; i >= 0; --i)
 137:             if (Field(v, i))
 138:                 fix(Field(v, i));
 139:         break;
 140: #endif COMPOUNDS
 141: #ifdef SLOW_INTS
 142:     case Num:
 143: #endif SLOW_INTS
 144:     default:
 145:         Abort();
 146:     }
 147: #endif OBSOLETE
 148: }
 149: 
 150: 
 151: #ifdef COMPOUNDS
 152: /*
 153:  * Allocate a compound with n fields.
 154:  */
 155: 
 156: Visible value
 157: grab_com(n)
 158:     int n;
 159: {
 160:     value v = grabber(n*sizeof(value));
 161: 
 162:     v->type = Com;
 163:     v->len = n;
 164:     for (--n; n >= 0; --n)
 165:         Field(v, n) = Vnil;
 166:     return v;
 167: }
 168: #endif COMPOUNDS
 169: 
 170: 
 171: /*
 172:  * Allocate a node with nch children.
 173:  */
 174: 
 175: node
 176: grab_node(nch)
 177:     register int nch;
 178: {
 179:     register node n = (node) grabber(
 180:             sizeof(struct node) - Headsize +
 181:             sizeof(value) * (nch-1));
 182:     register int i;
 183: 
 184:     n->type = Nod;
 185:     n->len = nch;
 186:     n->n_marks = 0;
 187:     n->n_width = 0;
 188:     n->n_symbol = 0;
 189:     for (i = nch-1; i >= 0; --i)
 190:         n->n_child[i] = Nnil;
 191:     return n;
 192: }
 193: 
 194: 
 195: /*
 196:  * Allocate a path.
 197:  */
 198: 
 199: path
 200: grab_path()
 201: {
 202:     register path p = (path) grabber(
 203:             sizeof(struct path) - Headsize);
 204: 
 205:     p->type = Pat;
 206:     p->p_parent = Pnil;
 207:     p->p_tree = Nnil;
 208:     p->p_ichild = 0;
 209:     p->p_ycoord = 0;
 210:     p->p_xcoord = 0;
 211:     p->p_level = 0;
 212:     p->p_addmarks = 0;
 213:     p->p_delmarks = 0;
 214:     return p;
 215: }
 216: 
 217: 
 218: #ifdef SLOW_INTS
 219: /*
 220:  * Make an integer.
 221:  */
 222: 
 223: value
 224: mk_integer(i)
 225:     int i;
 226: {
 227:     value v;
 228:     static value tab[128];
 229: 
 230:     if (!i)
 231:         return Vnil;
 232:     if (!(i&~127) && tab[i])
 233:         return tab[i];
 234: 
 235:     v = grabber(sizeof(value));
 236:     v->type = Num;
 237:     Field(v, 0) = (value) i;
 238:     if (!(i&~127)) {
 239:         tab[i] = v;
 240:         v->refcnt = Maxintlet;
 241:     }
 242:     return v;
 243: }
 244: #endif SLOW_INTS
 245: 
 246: 
 247: /*
 248:  * Make a text object out of a C string.
 249:  */
 250: 
 251: value
 252: mk_text(str)
 253:     register string str;
 254: {
 255:     register int len = strlen(str);
 256:     register value v = grabber(len+1);
 257: 
 258:     v->type = Tex;
 259:     v->len = len;
 260:     strcpy(Str(v), str);
 261:     return v;
 262: }
 263: 
 264: 
 265: /*
 266:  * Concatenate a C string to a text object (at the end).
 267:  */
 268: 
 269: concato(pv, str)
 270:     register value *pv;
 271:     register string str;
 272: {
 273:     register value v = *pv;
 274:     register int vlen = v->len;
 275:     register int len = strlen(str);
 276: 
 277:     Assert(v && v->refcnt > 0);
 278:     if (!len)
 279:         return;
 280: 
 281:     len += vlen;
 282:     if (v->refcnt == 1)
 283:         v = regrabber(v, len+1);
 284:     else {
 285:         v = grabber(len+1);
 286:         v->type = Tex;
 287:         strcpy(Str(v), Str(*pv));
 288:         Release(*pv);
 289:     }
 290:     strcpy(Str(v) + vlen, str);
 291:     v->len = len;
 292:     *pv = v;
 293: }
 294: 
 295: 
 296: /*
 297:  * Return a substring (trim) of a text object.
 298:  */
 299: 
 300: value
 301: trim(v, behead, curtail)
 302:     register value v;
 303:     register int behead;
 304:     register int curtail;
 305: {
 306:     register value w;
 307:     register int c;
 308: 
 309:     Assert(v && v->refcnt > 0);
 310:     Assert(behead >= 0 && curtail >= 0 && behead+curtail <= v->len);
 311:     if (behead + curtail == 0) {
 312:         Copy(v);
 313:         return v;
 314:     }
 315: 
 316:     c = Str(v)[v->len - curtail];
 317:     Str(v)[v->len - curtail] = 0; /* TEMPORARILY */
 318:     w = mk_text(Str(v) + behead);
 319:     Str(v)[v->len - curtail] = c;
 320:     return w;
 321: }
 322: 
 323: 
 324: #ifdef SLOW_INTS
 325: /*
 326:  * Return the C value if an integer object.
 327:  */
 328: 
 329: int
 330: intval(v)
 331:     register value v;
 332: {
 333:     if (!v)
 334:         return 0;
 335:     return (int) Field(v, 0);
 336: }
 337: #endif SLOW_INTS
 338: 
 339: 
 340: /*
 341:  * Make sure a location (pointer variable) contains a unique object.
 342:  */
 343: 
 344: uniql(pv)
 345:     register value *pv;
 346: {
 347:     register value v = *pv;
 348:     register value w;
 349:     register path p;
 350:     register node n;
 351:     register int i;
 352: 
 353:     Assert(v && v->refcnt > 0);
 354:     if (v->refcnt == 1)
 355:         return;
 356: 
 357:     switch (v->type) {
 358: 
 359:     case Nod:
 360:         n = grab_node(v->len);
 361:         for (i = v->len - 1; i >= 0; --i) {
 362:             w = (value) (n->n_child[i] = ((node)v)->n_child[i]);
 363:             Copy(w); /* This is ugly */
 364:         }
 365:         n->n_marks = ((node)v)->n_marks;
 366:         n->n_width = ((node)v)->n_width;
 367:         n->n_symbol = ((node)v)->n_symbol;
 368:         w = (value)n;
 369:         break;
 370: 
 371:     case Pat:
 372:         p = grab_path();
 373:         p->p_parent = ((path)v)->p_parent;
 374:         Copy(p->p_parent);
 375:         p->p_tree = ((path)v)->p_tree;
 376:         Copy(p->p_tree);
 377:         p->p_ichild = ((path)v)->p_ichild;
 378:         p->p_ycoord = ((path)v)->p_ycoord;
 379:         p->p_xcoord = ((path)v)->p_xcoord;
 380:         p->p_level = ((path)v)->p_level;
 381:         w = (value)p;
 382:         break;
 383: 
 384: #ifdef SLOW_INTS
 385:     case Num:
 386:         w = mk_integer(intval(v));
 387:         break;
 388: #endif SLOW_INTS
 389: 
 390: #ifdef COMPOUNDS
 391:     case Com:
 392:         w = grab_com(v->len);
 393:         for (i = v->len - 1; i >= 0; --i) {
 394:             n = (node) (Field(w, i) = Field(v, i));
 395:             Copy(n); /* This is uglier */
 396:         }
 397:         break;
 398: #endif COMPOUNDS
 399: 
 400:     case Tex:
 401:         w = mk_text(Str(v));
 402:         break;
 403: 
 404:     default:
 405:         Abort();
 406: 
 407:     }
 408:     Release(v);
 409:     *pv = w;
 410: }
 411: 
 412: 
 413: /*
 414:  * Increase the reference count of an object, unless it is infinite.
 415:  */
 416: 
 417: value
 418: copy(v)
 419:     value v;
 420: {
 421:     if (!v)
 422:         return v;
 423: 
 424:     Assert(v->refcnt > 0);
 425:     if (v->refcnt < Maxintlet) {
 426:         ++v->refcnt;
 427:         Increfs;
 428:     }
 429:     return v;
 430: }
 431: 
 432: 
 433: /*
 434:  * Decrease the reference count of an object, unless it is infinite.
 435:  * If it reaches zero, free the storage occupied by the object.
 436:  */
 437: 
 438: release(v)
 439:     register value v;
 440: {
 441:     register int i;
 442:     register value w;
 443: 
 444:     if (!v)
 445:         return;
 446:     Assert(v->refcnt > 0);
 447:     if (v->refcnt == Maxintlet)
 448:         return;
 449: 
 450:     Decrefs;
 451:     --v->refcnt;
 452:     if (v->refcnt == 0) {
 453:         switch (v->type) {
 454: #ifdef SLOW_INTS
 455:         case Num:
 456: #endif SLOW_INTS
 457:         case Tex:
 458:             break;
 459: #ifdef COMPOUNDS
 460:         case Com:
 461:             for (i = v->len - 1; i >= 0; --i) {
 462:                 w = Field(v, i);
 463:                 Release(w);
 464:             }
 465:             break;
 466: #endif COMPOUNDS
 467:         case Nod:
 468:             for (i = v->len - 1; i >= 0; --i) {
 469:                 w = (value)(((node)v)->n_child[i]);
 470:                 Release(w);
 471:             }
 472:             break;
 473:         case Pat:
 474:             w = (value)(((path)v)->p_parent);
 475:             Release(w);
 476:             w = (value)(((path)v)->p_tree);
 477:             Release(w);
 478:             break;
 479:         default:
 480:             Abort();
 481:         }
 482: #ifndef NDEBUG
 483:         if (dflag)
 484:             delval(v);
 485:         --nobjs;
 486: #endif NDEBUG
 487:         free((string)v);
 488:     }
 489: }
 490: 
 491: objstats()
 492: {
 493: #ifndef NDEBUG
 494:     fprintf(stderr, "*** Object statistics: %d objects, %d references\n",
 495:         nobjs, nrefs);
 496: #ifdef MSTATS
 497:     mstats("(at end)"); /* A routine which some malloc versions have to print
 498: 	             memory statistics. Remove if your malloc hasn't. */
 499: #endif MSTATS
 500: #endif NDEBUG
 501: }
 502: 
 503: #ifndef NDEBUG
 504: valdump(v)
 505:     value v;
 506: {
 507:     if (!v)
 508:         fputs("(nil)", stderr);
 509:     else {
 510:         fprintf(stderr, "v=0x%x, type='%c', len=%d, refcnt=",
 511:             v, v->type, v->len);
 512:         if (v->refcnt == Maxintlet)
 513:             putc('*', stderr);
 514:         else
 515:             fprintf(stderr, "%d", v->refcnt);
 516:         fputs(": ", stderr);
 517:         wrval(v);
 518: 
 519:     }
 520:     putc('\n', stderr);
 521: }
 522: 
 523: #define QUOTE '\''
 524: 
 525: wrval(v)
 526:     value v;
 527: {
 528:     register string cp;
 529:     register int c;
 530: 
 531:     if (!v) {
 532:         fputs("nil", stderr);
 533:         return;
 534:     }
 535: 
 536:     switch (v->type) {
 537: 
 538: #ifdef SLOW_INTS
 539:     case Num:
 540:         fprintf(stderr, "%d", intval(v));
 541:         break;
 542: #endif SLOW_INTS
 543: 
 544:     case Tex:
 545:         putc(QUOTE, stderr);
 546:         for (cp = Str(v); c = *cp; ++cp) {
 547:             if (' ' <= c && c < 0177) {
 548:                 putc(c, stderr);
 549:                 if (c == QUOTE)
 550:                     putc(c, stderr);
 551:             }
 552:             else if (0 <= c && c < ' ')
 553:                 putc('^', stderr), putc(c + '@', stderr);
 554:             else
 555:                 fprintf(stderr, "\\%03o", c);
 556:         }
 557:         putc(QUOTE, stderr);
 558:         break;
 559: 
 560: #ifdef COMPOUNDS
 561:     case Com:
 562:       {
 563:         int i;
 564:         value f;
 565:         putc('(', stderr);
 566:         for (i = 0; i < v->len; ++i) {
 567:             if (i)
 568:                 putc(',', stderr), putc(' ', stderr);
 569:             f = Field(v, i);
 570:             if (!f || f->refcnt == 1 || f->type != Com) {
 571:                 if (f && f->type == Com)
 572:                     fprintf(stderr, "0x%x=", f);
 573:                 wrval(f);
 574:             }
 575:             else
 576:                 fprintf(stderr, "0x%x", f);
 577:         }
 578:         putc(')', stderr);
 579:         break;
 580:       }
 581: #endif COMPOUNDS
 582: 
 583:     default:
 584:         fprintf(stderr, "0x%x", v);
 585: 
 586:     }
 587: }
 588: 
 589: static struct list {
 590:     struct list *link;
 591:     value val;
 592: } head;
 593: #endif NDEBUG
 594: 
 595: objdump()
 596: {
 597: #ifndef NDEBUG
 598:     struct list *l;
 599: 
 600:     for (l = head.link; l; l = l->link)
 601:         valdump(l->val);
 602: #endif NDEBUG
 603: }
 604: 
 605: objcheck()
 606: {
 607: #ifndef NDEBUG
 608:     struct list *l;
 609: 
 610:     for (l = head.link; l; l = l->link)
 611:         if (l->val->refcnt != Maxintlet)
 612:             valdump(l->val);
 613: #endif NDEBUG
 614: }
 615: 
 616: #ifndef NDEBUG
 617: newval(v)
 618:     register value v;
 619: {
 620:     register struct list *l =
 621:             (struct list *) malloc((unsigned) sizeof(struct list));
 622: 
 623:     if (!l)
 624:         syserr("newval: malloc");
 625:     l->link = head.link;
 626:     l->val = v;
 627:     head.link = l;
 628: }
 629: 
 630: delval(v)
 631:     register value v;
 632: {
 633:     register struct list *l;
 634:     register struct list *p;
 635: 
 636:     for (p = &head, l = head.link; l; p = l, l = l->link) {
 637:         if (l->val == v) {
 638:             p->link = l->link;
 639:             free((string)l);
 640:             return;
 641:         }
 642:     }
 643:     Abort();
 644: }
 645: #endif NDEBUG

Defined functions

delval defined in line 630; used 1 times
fix defined in line 104; used 7 times
grab_com defined in line 156; used 4 times
grab_node defined in line 175; used 3 times
grab_path defined in line 199; used 3 times
grabber defined in line 61; used 6 times
intval defined in line 329; used 2 times
mk_integer defined in line 223; used 1 times
newval defined in line 617; used 1 times
  • in line 71
objcheck defined in line 605; used 1 times
objdump defined in line 595; used 1 times
objstats defined in line 491; used 1 times
regrabber defined in line 87; used 1 times
valdump defined in line 504; used 2 times
wrval defined in line 525; used 2 times

Defined variables

head defined in line 592; used 6 times
nobjs defined in line 36; used 3 times
nrefs defined in line 37; used 4 times
rcsid defined in line 2; never used
value defined in line 223; used 46 times

Defined struct's

head defined in line 21; never used
list defined in line 589; used 16 times

Defined macros

COMPOUNDS defined in line 12; used 5 times
Copy defined in line 50; used 5 times
Decrefs defined in line 45; used 2 times
Field defined in line 30; used 9 times
Headsize defined in line 28; used 4 times
Hsize defined in line 27; used 1 times
  • in line 28
Increfs defined in line 44; used 3 times
Intsize defined in line 26; used 2 times
  • in line 28(2)
QUOTE defined in line 523; used 3 times
RRelease defined in line 52; used 1 times
  • in line 51
Release defined in line 51; used 6 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4477
Valid CSS Valid XHTML 1.0 Strict