home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / alt / sources / 2873 < prev    next >
Encoding:
Text File  |  1992-12-23  |  38.6 KB  |  1,619 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!spool.mu.edu!news.cs.indiana.edu!umn.edu!csus.edu!netcom.com!thinman
  3. From: thinman@netcom.com (Technically Sweet)
  4. Subject: COOL: C Object-Oriented Library: part 2 of 4
  5. Message-ID: <1992Dec23.191529.10437@netcom.com>
  6. Organization: International Foundation for Internal Freedom
  7. Date: Wed, 23 Dec 1992 19:15:29 GMT
  8. Lines: 1609
  9.  
  10. #!/bin/sh
  11. # This is part 02 of a multipart archive
  12. # ============= class.c ==============
  13. if test -f 'class.c' -a X"$1" != X"-c"; then
  14.     echo 'x - skipping class.c (File already exists)'
  15. else
  16. echo 'x - extracting class.c (Text)'
  17. sed 's/^X//' << 'SHAR_EOF' > 'class.c' &&
  18. X/*
  19. X *    COOL: C Object-Oriented Library
  20. X *
  21. X *    COOL Class object implementation.
  22. X *    COOL initialization routine.
  23. X *
  24. X *     Copyright 1991 by Lance Norskog
  25. X *
  26. X *    First cut: lots of private tables, no good.
  27. X *    Second cut: fixed-size method tables for classes, 
  28. X *        pointers for derived objects.
  29. X *    ... minor fixes: 2-level inheritance didn't work!
  30. X *    March 1992: add components for 5D project.
  31. X *    June  1992: add type list options for Scheme interface
  32. X *    ???   1992: integrate with Scheme memory management
  33. X *
  34. X * Permission to use, copy, modify, and distribute this software and its
  35. X * documentation for any purpose and without fee is hereby granted, provided
  36. X * that the above copyright notice appear in all copies and that both that
  37. X * copyright notice and this permission notice appear in supporting
  38. X * documentation.  This software is provided "as is" without express or
  39. X * implied warranty.
  40. X */
  41. X
  42. X#include <stdio.h>
  43. X#include <setjmp.h>
  44. X#include <varargs.h>
  45. X#include "cool.h"
  46. X#include "coolint.h"
  47. X
  48. X/* Class object internal data structure */
  49. Xstruct cool_class {
  50. X/*    cool_priv_t    cl_private;        /* starts all private data */
  51. X    sint        cl_size;        /* Size of private data */
  52. X    sint        cl_gap;            /* future use */
  53. X    object_t    cl_parents[MAXPARENTS]; /* Table of parents */
  54. X    methtab_t    cl_methtab[MAXMETHODS]; /* Table of methods */
  55. X    char *        cl_compnames[MAXCOMP];    /* Names of components */
  56. X};
  57. Xtypedef struct cool_class *class_t;
  58. X
  59. Xstruct {
  60. X    cool_priv_t        private;
  61. X    struct cool_class    Class;
  62. X} uberclass;
  63. X
  64. Xstatic sint generation = 1;            /* finds use of old objects */
  65. X
  66. X/* 
  67. X * Add an object to table.  
  68. X */
  69. Xstatic object_t
  70. Xaddobject(name)
  71. Xchar *name;
  72. X{
  73. X    int newob, gen;
  74. X    char *str = cool_strdup(name);
  75. X
  76. X    newob = cool_freelist;
  77. X    if (newob == 0)
  78. X        cool_raise("OutOfObjects", CODEMARK);
  79. X    cool_freelist = cool_objtab[OBJECTOF(newob)].ob_next;
  80. X
  81. X    /* Build object */
  82. X    bzero(&cool_objtab[OBJECTOF(newob)], sizeof(cool_objtab[0]));
  83. X    cool_objtab[OBJECTOF(newob)].ob_name = str;
  84. X    gen = cool_objtab[OBJECTOF(newob)].ob_generation;
  85. X    /* wrap around */
  86. X    if (generation == MAXIMUMGEN)
  87. X        generation = 1;
  88. X    
  89. X    return (object_t) MKOBJECT(newob, gen);
  90. X}
  91. X
  92. X/* 
  93. X * Delete an object from table.  
  94. X */
  95. Xstatic 
  96. Xdelobject(obj)
  97. Xobjtab_t *obj;
  98. X{
  99. X    /* Find an object */
  100. X    cool_strfree(obj->ob_name);
  101. X    obj->ob_name = (char *) 0;
  102. X    obj->ob_next = cool_freelist;
  103. X    obj->ob_generation = BADGEN;        /* Mark object as dead */
  104. X    cool_freelist = (sint) (obj - cool_objtab);
  105. X}
  106. X
  107. X/* Native method handlers */
  108. X
  109. Xstatic ret_t
  110. Xclass_ambiguous(priv) 
  111. Xcool_priv_t *priv;
  112. X{ 
  113. X    /* look up class and method's name from private data */
  114. X    cool_raise("Ambiguous", CODEMARK);
  115. X}
  116. X
  117. X/* 
  118. X * Add/replace a method to object's method table.  
  119. X */
  120. Xstatic
  121. Xmethod_t
  122. Xaddmethod(obj, name, func, nargs)
  123. Xobjtab_t *obj;
  124. Xchar *name;
  125. Xret_t (*func)();
  126. Xint nargs;
  127. X{
  128. X    methtab_t *meth;
  129. X    int i, m, found;
  130. X    char *rt, *at;
  131. X
  132. X    if (ISMETHOD(name)) 
  133. X        cool_raise("AddMethod", "Class '%s': Method is not a string",
  134. X            obj->ob_name);
  135. X
  136. X    if ((nargs < 0) || (nargs >= MAXARGS))
  137. X        cool_raise("AddMethod", 
  138. X            "Class '%s' Method '%s': Too many arguments: %d", 
  139. X            obj->ob_name, name, nargs);
  140. X
  141. X    meth = obj->ob_methtab[MYMETHODS];
  142. X    for(m = 0; m < MAXMETHODS; m++, meth++) {
  143. X        if (! meth->m_name)
  144. X            break;
  145. X        if (cool_streq(meth->m_name, name)) {
  146. X            /* 
  147. X             * Overriding a previous method.  Probably inherited.
  148. X             * If this breaks an ambiguity, count down.
  149. X             */
  150. X            if (meth->m_func == class_ambiguous)
  151. X                obj->ob_ambiguous--;
  152. X            break;
  153. X        }
  154. X    }
  155. X    if (m == MAXMETHODS)
  156. X        cool_raise("TooManyMethods", NULL);
  157. X
  158. X    
  159. X    /* force given argument list to match given number of arguments */
  160. X    meth->m_func = func;
  161. X    meth->m_nargs = nargs;
  162. X    found = methdigest(meth, cool_strdup(name));
  163. X    if ((found != -1) && (found != nargs))
  164. X        cool_raise("MethodArgumentNumbers", NULL);
  165. X
  166. X    return MKMETHOD(MYMETHODS, m);
  167. X}
  168. X
  169. X/* Class method handlers. */
  170. X
  171. X/*
  172. X * Add a method to a class.
  173. X */
  174. Xstatic method_t
  175. Xclass_addmethod(class, name, func, nargs)
  176. Xclass_t class;
  177. Xchar *name;
  178. Xret_t (*func)();
  179. Xint nargs;
  180. X{
  181. X    method_t m;
  182. X    methtab_t *meth;
  183. X    objtab_t *obj;
  184. X    char args[1024];
  185. X
  186. X    cool_squish(name, args);
  187. X    obj = &cool_objtab[OBJECTOF(SELFOF(class))];
  188. X    /* The ambiguous thing should be handled here. */
  189. X    return addmethod(obj, name, func, nargs);
  190. X}
  191. X
  192. X/* Slow class creation and destruction methods. */
  193. X
  194. X/*
  195. X * Create an instance of a class.
  196. X */
  197. Xstatic object_t
  198. Xclass_create_obj(class, name)
  199. Xclass_t class;
  200. Xchar *name;
  201. X{
  202. X    object_t cl, ob;
  203. X    objtab_t *obj, *clobj, *pobj;
  204. X    methtab_t *mt;
  205. X    cool_priv_t *priv;
  206. X    char compname[128];
  207. X    int i, m, p, q;
  208. X
  209. X    if (SELFOF(class) != CLASSOF(class)) {
  210. X        cool_raise("CreateObject", "Must send Create to a class");
  211. X    }
  212. X    if (name == NULL)
  213. X        name = cool_makename();    
  214. X    ob = addobject(name);
  215. X    obj = &cool_objtab[OBJECTOF(ob)];
  216. X    clobj = &cool_objtab[OBJECTOF(SELFOF(class))];
  217. X
  218. X    /* Copy method table */
  219. X    bcopy(clobj->ob_methtab, obj->ob_methtab, sizeof(obj->ob_methtab));
  220. X
  221. X    /* Allocate private chunks of inherited classes */
  222. X    for(i = 0; i < MAXPARENTS; i++) {
  223. X        class_t pclass;
  224. X
  225. X        if (! (p = (cint) class->cl_parents[i]))
  226. X            continue;
  227. X        /* Get class struct of parent.  &...[1] skips cool_priv_t. */
  228. X        pclass = (class_t) 
  229. X            &cool_objtab[OBJECTOF(p)].ob_private[MYMETHODS][1];
  230. X        obj->ob_private[i] = (cool_priv_t *)
  231. X            cool_malloc(pclass->cl_size);
  232. X    }
  233. X    /* Allocate private chunk of this class. */
  234. X    obj->ob_private[MYMETHODS] = (cool_priv_t *)cool_malloc(class->cl_size);
  235. X    
  236. X    /* Fill in all privates of object, including inherited data */
  237. X    for(i = 0; i < ALLCLASSES; i++) {
  238. X        /* Now, we want the cool_priv_t at the beginning. */
  239. X        priv = obj->ob_private[i];
  240. X        if (priv) {
  241. X            priv->self = ob;
  242. X            priv->class = SELFOF(class);
  243. X        }
  244. X    }
  245. X    if (clobj->ob_ambiguous)
  246. X        cool_raise("AmbiguousMethods", "Class %s", clobj->ob_name);
  247. X
  248. X
  249. X    /* Create any component objects before init this object. */
  250. X    /* ob_components in class object are class names */
  251. X    /* ob_components in object are individual object names */
  252. X    for(i = 0; (i < MAXCOMP) && clobj->ob_components[i]; i++) {
  253. X        sprintf(compname, "%s.%s", name, class->cl_compnames[i]);
  254. X        obj->ob_components[i] = coolta(object_t, 
  255. X            clobj->ob_components[i], METHOD_CREATE, compname);
  256. X    }
  257. X
  258. X    /* Call init functions of all my method tables */
  259. X    /* Most distant ancestor first, then recent ancestors, then my own. */
  260. X    /* Should reserve methods 0 & 1 for init and exit. LATER */
  261. X    for(p = 0; p < ALLCLASSES; p++) {
  262. X        mt = clobj->ob_methtab[p];
  263. X        if (! mt)
  264. X            continue;
  265. X        (* mt[METHODOF(METHOD_INIT)].m_func)(obj->ob_private[p] + 1); 
  266. X    }
  267. X
  268. X    return ob;
  269. X}
  270. X
  271. X/*
  272. X * Destroy an instance of a class.
  273. X */
  274. Xstatic
  275. Xclass_destroy_obj(class, ob)
  276. Xclass_t class;
  277. Xobject_t ob;
  278. X{
  279. X    object_t cl, comp;
  280. X    method_t exit;
  281. X    objtab_t *obj;
  282. X    methtab_t *mt;
  283. X    int i, m, p;
  284. X
  285. X    /* Convert to index form */
  286. X    ob = (object_t) OBJECTOF(cool_object(ob));
  287. X
  288. X    if (SELFOF(class) != CLASSOF(class)) {
  289. X        coolva(cool_classof(ob), METHOD_DESTROY, ob);
  290. X        return;
  291. X    }
  292. X        
  293. X
  294. X    obj = &cool_objtab[(cint) ob];
  295. X
  296. X    if (SELFOF(class) != cool_objtab[(cint)ob].ob_private[MYMETHODS]->class)
  297. X        cool_raise("Destroy", "Class and object don\'t match");
  298. X
  299. X    /* Call Exit functions of all its method tables */
  300. X    /* My exit first, then recent ancestors, then most distant ancestor. */
  301. X    /* Inverse order of object creation. */
  302. X    /* Should reserve methods 0 & 1 for init and exit. LATER */
  303. X    for(p = ALLCLASSES - 1; p >= 0; p--) {
  304. X        mt = obj->ob_methtab[p];
  305. X        if (! mt)
  306. X            continue;
  307. X
  308. X        (* mt[METHODOF(METHOD_EXIT)].m_func)(obj->ob_private[p] + 1); 
  309. X        cool_free((char *) obj->ob_private[p]); 
  310. X    }
  311. X
  312. X    /* Destroy all component objects after main exit methods. */
  313. X    for(i = 0; (i < MAXCOMP) && (comp = obj->ob_components[i]); i++)
  314. X        coolva(cool_classof(comp), METHOD_DESTROY, comp);
  315. X
  316. X    /* new gen for object; catch dangling references */
  317. X    cool_objtab[(cint) ob].ob_generation++;
  318. X}
  319. X
  320. X/*
  321. X * Cause class to inherit a method from a parent class.
  322. X * The parent class may have inherited the method from one of its parents.
  323. X * If we allowed method changing for objects, this could be a standard
  324. X * object method.
  325. X */
  326. Xstatic
  327. Xmethod_t
  328. Xclass_inherit(class, method, parent)
  329. Xclass_t class;
  330. Xmethod_t method;
  331. Xobject_t parent;
  332. X{
  333. X    objtab_t *pobj;
  334. X    methtab_t *mt;
  335. X    int myclass, p;
  336. X
  337. X    /* Rationalize. */
  338. X    parent = cool_object(parent);
  339. X
  340. X    for(p = 0; p < MAXPARENTS; p++) {
  341. X        if (class->cl_parents[p] == parent)
  342. X            break;
  343. X    }
  344. X    if(p == MAXPARENTS)
  345. X        cool_raise("ClassIsNotAParent", CODEMARK);
  346. X
  347. X    /* Force exception if bogus. */
  348. X    method = cool_method(parent, method);
  349. X
  350. X    /* copy method from parent to my method_t */
  351. X    myclass = OBJECTOF(CLASSOF(class));
  352. X    p = OBJECTOF(parent);
  353. X    mt = &cool_objtab[p].ob_methtab[MYMETHODS][METHODOF(method)];
  354. X
  355. X    return addmethod(&cool_objtab[myclass], mt->m_name, mt->m_func, mt->m_nargs);
  356. X}
  357. X
  358. X/* Stubs, Init is the first method of every class. */
  359. Xstatic ret_t
  360. Xclass_init_obj() {;}
  361. X
  362. X/* Stubs, Exit is the second method of every class. */
  363. Xstatic ret_t
  364. Xclass_exit_obj() {;}
  365. X
  366. X/* Stubs, Copy is the third method of every class. */
  367. Xstatic void
  368. Xclass_copy_obj() {;}
  369. X
  370. X/*
  371. X * Clone is the method of every class.
  372. X * Make a "deep copy" of an object.
  373. X */
  374. Xstatic object_t
  375. Xclass_clone_obj(class, name, newname)
  376. Xclass_t class;
  377. Xchar *name, *newname;
  378. X{
  379. X    object_t cl, ob, nob, comp;
  380. X    objtab_t *obj, *clobj, *nobj;
  381. X    methtab_t *mt;
  382. X    cool_priv_t *priv;
  383. X    int i, m, p, q;
  384. X
  385. X    if (SELFOF(class) != CLASSOF(class)) {
  386. X        coolva2(cool_classof(ob), METHOD_CLONE, SELFOF(class), newname);
  387. X    }
  388. X
  389. X
  390. X    if (newname == NULL)
  391. X        newname = cool_makename();    
  392. X    else
  393. X        if (cool_getobject((object_t) newname) != OBJECTERR)
  394. X            cool_raise("Copy Object", 
  395. X                "New name is already an object");
  396. X
  397. X    ob = cool_object((object_t) name);
  398. X    obj = &cool_objtab[OBJECTOF(ob)];
  399. X    nob = addobject(newname);
  400. X    nobj = &cool_objtab[OBJECTOF(nob)];
  401. X    clobj = &cool_objtab[OBJECTOF(SELFOF(class))];
  402. X    if (SELFOF(class) != CLASSOF(obj->ob_private[MYMETHODS] + 1))
  403. X        cool_raise("Copy Object", "Object is not in class");
  404. X
  405. X    /* Copy method table from old to new object. */
  406. X    bcopy(obj->ob_methtab, nobj->ob_methtab, sizeof(obj->ob_methtab));
  407. X
  408. X    /* Allocate private chunks of inherited classes */
  409. X    for(i = 0; i < MAXPARENTS; i++) {
  410. X        class_t pclass;
  411. X
  412. X        if (! (p = (cint) class->cl_parents[i]))
  413. X            continue;
  414. X        /* Get class struct of parent.  &...[1] skips cool_priv_t. */
  415. X        pclass = (class_t) 
  416. X            &cool_objtab[OBJECTOF(p)].ob_private[MYMETHODS][1];
  417. X        nobj->ob_private[i] = (cool_priv_t *)
  418. X            cool_malloc(pclass->cl_size);
  419. X        /* Copy private area */
  420. X        bcopy(obj->ob_private[i] + 1, nobj->ob_private[i] + 1, 
  421. X            pclass->cl_size - sizeof(cool_priv_t));
  422. X    }
  423. X    /* Allocate private chunk of this class. */
  424. X    nobj->ob_private[MYMETHODS] = (cool_priv_t*)cool_malloc(class->cl_size);
  425. X
  426. X    
  427. X    /* Fill in all privates of object, including inherited data */
  428. X    for(p = 0; p < ALLCLASSES; p++) {
  429. X        /* Now, we want the cool_priv_t at the beginning. */
  430. X        priv = nobj->ob_private[p];
  431. X        if (priv) {
  432. X            /* Copy private areas */
  433. X            bcopy(obj->ob_private[p] + 1, 
  434. X                nobj->ob_private[p] + 1, 
  435. X                    class->cl_size);
  436. X            priv->self = ob;    /* replace */
  437. X        }
  438. X    }
  439. X
  440. X    /* Call copy functions of all my method tables */
  441. X    /* Most distant ancestor first, then recent ancestors, then my own. */
  442. X    for(p = 0; p < ALLCLASSES; p++) {
  443. X        mt = clobj->ob_methtab[p];
  444. X        if (! mt)
  445. X            continue;
  446. X
  447. X        /* Call copy methods */
  448. X        (* mt[METHODOF(METHOD_COPY)].m_func)(obj->ob_private[p] + 1,
  449. X             nobj->ob_private[p] + 1); 
  450. X    }
  451. X
  452. X    /* Clone all component objects */
  453. X    for(i = 0; (i < MAXCOMP) && (comp = obj->ob_components[i]); i++)
  454. X        nobj->ob_components[i] = 
  455. X            coolt(object_t, comp, METHOD_CLONE);
  456. X
  457. X    return nob;
  458. X}
  459. X
  460. X/*
  461. X * Add component to class.  
  462. X */
  463. X
  464. Xclass_component(class, compclass, compname)
  465. Xclass_t class;
  466. Xchar *compname;
  467. Xobject_t compclass;
  468. X{
  469. X    objtab_t *clobj;
  470. X    int i;
  471. X
  472. X    /* XXX check if it's really a class */
  473. X    compclass = cool_object(compclass);        /* rationalize */
  474. X    if (! compname)
  475. X        cool_raise("Component", "Must have valid string for name");
  476. X    if (SELFOF(class) != CLASSOF(class))
  477. X        cool_raise("Component", "Must send Component to a class");
  478. X    clobj = &cool_objtab[OBJECTOF(SELFOF(class))];
  479. X    for(i = 0; i < MAXCOMP; i++)
  480. X        if (! clobj->ob_components[i])
  481. X            break;
  482. X    if (i == MAXCOMP)
  483. X        cool_raise("Component", "Too many components");
  484. X    clobj->ob_components[i] = compclass;
  485. X    class->cl_compnames[i] = cool_strdup(compname);
  486. X}
  487. X
  488. X#ifdef    SELFISH
  489. X/*
  490. X * Cause object to possess a new parent class.
  491. X */
  492. Xstatic
  493. Xmethod_t
  494. Xobj_addparent(priv, method, parent)
  495. Xpriv_t   priv;
  496. Xmethod_t method;
  497. Xobject_t parent;
  498. X{
  499. X    int i, newob;
  500. X    class_t  class;
  501. X    objtab_t *obj;
  502. X    method_t meth;
  503. X    methtab_t **methpp;
  504. X    int p, q, r;
  505. X
  506. X    parent = cool_object(parent);    /* rationalize */
  507. X
  508. X    /* priv[-1] is the private area */
  509. X    obj = &cool_objtab[OBJECTOF(CLASSOF(priv))];
  510. X    for(p = 0; p < MAXPARENTS; p++)
  511. X        if (class->cl_parents[p] == 0)
  512. X            break;
  513. X    if (p == MAXPARENTS)
  514. X        cool_raise("TooManyParents", obj->ob_name);
  515. X    class->cl_parents[p] = parent;
  516. X
  517. X    /* Copy pointers to grandparents' etc. methods */
  518. X    methpp = cool_objtab[OBJECTOF(parent)].ob_methtab;
  519. X    q = 0;
  520. X    for(r = 0; (r < MAXPARENTS) && methpp[r]; r++) {
  521. X        obj->ob_methtab[q++] = methpp[r];
  522. X        if (q == MAXPARENTS)
  523. X            cool_raise("TooManyParents", obj->ob_name);
  524. X    }
  525. X
  526. X    /* Don't worry about ambigous methods for now. */
  527. X}
  528. X#endif
  529. X
  530. X/*
  531. X * Add a new class
  532. X */
  533. X
  534. Xstatic object_t
  535. Xclass_newclass(junk, name, size, va_alist)
  536. Xclass_t     junk;                /* not used */
  537. Xchar         *name;
  538. Xint        size;
  539. Xva_dcl                        /* wacky varargs syntax */
  540. X{
  541. X    int i, newob;
  542. X    class_t  class, pclass;
  543. X    objtab_t *obj;
  544. X    method_t meth;
  545. X    methtab_t **methpp;
  546. X    int p, q, r;
  547. X    va_list ap;
  548. X
  549. X    for(newob = 0; newob < cool_numobs; newob++) 
  550. X        if (cool_streq(cool_objtab[OBJECTOF(newob)].ob_name, name))
  551. X            cool_raise("ClassDoesExist", name);
  552. X    newob = (int) addobject(name);
  553. X    obj = &cool_objtab[OBJECTOF(newob)];
  554. X    obj->ob_ambiguous = 0;
  555. X    for(p = 0; p < MAXPARENTS; p++) {
  556. X        obj->ob_private[p] = (cool_priv_t *) 0;
  557. X        obj->ob_methtab[p] = (methtab_t *) 0;
  558. X    }
  559. X
  560. X    obj->ob_private[MYMETHODS] = (cool_priv_t *) 
  561. X        cool_malloc(sizeof (struct cool_class) + sizeof (cool_priv_t));
  562. X    /* Ignore function parameter */
  563. X    class = (class_t) &obj->ob_private[MYMETHODS][1];
  564. X    obj->ob_methtab[MYMETHODS] = class->cl_methtab;
  565. X
  566. X    SELFOF(class) = (object_t) newob;
  567. X    CLASSOF(class) = (object_t) newob;
  568. X    class->cl_size = size + sizeof(cool_priv_t);
  569. X
  570. X    /* Get list of parents */
  571. X    va_start(ap);
  572. X    for(p = 0; p < MAXPARENTS; p++) {
  573. X        if (class->cl_parents[p] = va_arg(ap, object_t)) {
  574. X            class->cl_parents[p] =         /* do lookup */
  575. X                cool_object(class->cl_parents[p]);
  576. X            q = OBJECTOF(class->cl_parents[p]);
  577. X            pclass = 
  578. X(class_t) &(cool_objtab[q].ob_private[MYMETHODS][1]);
  579. X            /* copy parent's list of grandparents */
  580. X            for(q = 0; pclass->cl_parents[q] && 
  581. X                    (p+1 < MAXPARENTS) && (q < MAXPARENTS); q++)
  582. X                class->cl_parents[++p] = pclass->cl_parents[q];
  583. X        } else
  584. X            break;
  585. X    }
  586. X    va_end(ap);
  587. X
  588. X    if (p > MAXPARENTS)
  589. X        cool_raise("TooManyParents", CODEMARK);
  590. X    for(; p < MAXPARENTS; p++) 
  591. X        class->cl_parents[p] = 0;
  592. X
  593. X    /*
  594. X       * Copy parent's method pointer tables to our table.
  595. X     */
  596. X    q = 0;
  597. X    for(p = 0; p < MAXPARENTS && class->cl_parents[p]; p++) {
  598. X        /* Copy pointers to grandparents' etc. methods */
  599. X        methpp = cool_objtab[OBJECTOF(class->cl_parents[p])].ob_methtab;
  600. X        /* Copy pointer to parent's own method table */
  601. X        obj->ob_methtab[q++] = methpp[MYMETHODS];
  602. X        if (q == MAXPARENTS)
  603. X            cool_raise("TooManyInherits", obj->ob_name);
  604. X    }
  605. X
  606. X/* n.b.: Object 0 is class Class.  You cannot inherit from this class. */
  607. X
  608. X    {
  609. X    /* Don't count same method second time if there are 3 or more. */
  610. X    char searched[MAXPARENTS][MAXMETHODS];
  611. X    int m;
  612. X
  613. X    for(p = 0; p < MAXPARENTS; p++) for(m = 0; m < MAXPARENTS; m++)
  614. X        searched[p][m] = 0;
  615. X
  616. X    /* First, add all well-known methods */
  617. X    addmethod(obj, "Create=integer:",    class_create_obj, 0);
  618. X    addmethod(obj, "Create=integer:string",    class_create_obj, 1);
  619. X    addmethod(obj, "Destroy",   class_destroy_obj, 1);
  620. X    addmethod(obj, "Method",    class_addmethod, MAXARGS - 1);
  621. X    addmethod(obj, "Inherit",   class_inherit, 2);
  622. X    addmethod(obj, "Component", class_component, 2);
  623. X    addmethod(obj, "Clone",     class_clone_obj, 2);
  624. X    addmethod(obj, "Init",      class_init_obj, 0);
  625. X    addmethod(obj, "Exit",      class_exit_obj, 0);
  626. X    addmethod(obj, "Copy",      class_copy_obj, 1);
  627. X
  628. X    /*
  629. X     * Hunt for conflicts among parents' unique methods 
  630. X     * Mark by adding our own method with func class_ambiguous
  631. X     */
  632. X    obj->ob_ambiguous = 0;
  633. X    for(p = 0; class->cl_parents[p] && (p < MAXPARENTS - 1); p++,methpp++) {
  634. X        methtab_t *mp;
  635. X        /* for each method after base class methods, 
  636. X            hunt remaining parents for it */
  637. X        mp = obj->ob_methtab[p];
  638. X        for (q = p + 1; q < MAXPARENTS; q++) {
  639. X            /* Don't search well-known methods */
  640. X            for(m = STDMETHODS; m < MAXMETHODS; m++) 
  641. X            if (mp[m].m_name && ! searched[p][m] &&
  642. X                ((meth = cool_getmethod((object_t) mp[m].m_name,
  643. X                obj->ob_methtab[q])) != METHODERR)) {
  644. X                    addmethod(obj, mp[m].m_name,
  645. X                        class_ambiguous, 0);
  646. X                    obj->ob_ambiguous++;
  647. X                    searched[PARENTOF(meth)][METHODOF(meth)]=1;
  648. X                }
  649. X            }
  650. X        }
  651. X    }
  652. X
  653. X    return (object_t) newob;
  654. X}
  655. X
  656. Xtestgcc() {
  657. X#ifdef    __GNUC__
  658. X    /* -fwritable-strings test */
  659. X    "abcde"[2] = 5;
  660. X    /*
  661. X     * COOL must be compiled with gcc -fwritable-strings
  662. X     * to support the string/object disambiguation trick.
  663. X     * Note the misspelling of writable.
  664. X     */
  665. X#endif
  666. X}
  667. X
  668. Xvoid
  669. Xcool_init()
  670. X{
  671. X    objtab_t *obj;
  672. X    methtab_t *meth;
  673. X    int i;
  674. X
  675. X    testgcc();
  676. X
  677. X    if (cool_freelist != 0)
  678. X        cool_raise("Coolinit", "MultipleInit");
  679. X
  680. X    /* build freelist */
  681. X    for(i = 2; i < MAXOBJECTS; i++)
  682. X        cool_objtab[i - 1].ob_next = i;
  683. X    cool_freelist = 1;
  684. X
  685. X    /* Build Class object */
  686. X    obj = cool_objtab;
  687. X    obj->ob_name = "Class";
  688. X    for(i = 0; i < MAXPARENTS; i++) {
  689. X        obj->ob_methtab[i] = (methtab_t *) 0;
  690. X        obj->ob_private[i] = (cool_priv_t *) 0;
  691. X    }
  692. X    obj->ob_private[MYMETHODS] = (cool_priv_t *) &uberclass;
  693. X    obj->ob_methtab[MYMETHODS] = uberclass.Class.cl_methtab;
  694. X
  695. X    /* Add methods */
  696. X    addmethod(obj, "Create", class_newclass, MAXPARENTS);
  697. X}
  698. X
  699. X
  700. SHAR_EOF
  701. chmod 0644 class.c ||
  702. echo 'restore of class.c failed'
  703. Wc_c="`wc -c < 'class.c'`"
  704. test 17641 -eq "$Wc_c" ||
  705.     echo 'class.c: original size 17641, current size' "$Wc_c"
  706. fi
  707. # ============= msg.c ==============
  708. if test -f 'msg.c' -a X"$1" != X"-c"; then
  709.     echo 'x - skipping msg.c (File already exists)'
  710. else
  711. echo 'x - extracting msg.c (Text)'
  712. sed 's/^X//' << 'SHAR_EOF' > 'msg.c' &&
  713. X
  714. X/*
  715. X *    COOL: C Object-Oriented Library
  716. X *
  717. X *    Message handler
  718. X *
  719. X *     Copyright 1991 by Lance Norskog
  720. X *
  721. X * Permission to use, copy, modify, and distribute this software and its
  722. X * documentation for any purpose and without fee is hereby granted, provided
  723. X * that the above copyright notice appear in all copies and that both that
  724. X * copyright notice and this permission notice appear in supporting
  725. X * documentation.  This software is provided "as is" without express or
  726. X * implied warranty.
  727. X */
  728. X
  729. X#include <stdio.h>    /* for NULL */
  730. X#include <setjmp.h>    
  731. X#include <varargs.h>
  732. X#include "cool.h"
  733. X#include "coolint.h"
  734. X
  735. X/*
  736. X * Handle a message to an object.
  737. X */
  738. Xret_t
  739. Xcool_msg(o, m, va_alist)
  740. Xobject_t o;
  741. Xmethod_t m;
  742. Xva_dcl
  743. X{
  744. X    objtab_t *obj;
  745. X    methtab_t *meth;
  746. X    cint p;
  747. X    unsigned long args[MAXARGS];
  748. X    va_list ap;
  749. X    int i;
  750. X
  751. X    /* Convert object and method to index form */
  752. X    if (ISOBJECT(o)) {
  753. X        if (! GOODGEN(o))
  754. X            cool_raise("BadGeneration", CODEMARK);
  755. X    } else
  756. X        o = (object_t) cool_object(o);
  757. X    obj = &cool_objtab[OBJECTOF(o)];
  758. X    if (! ISMETHOD(m)) {
  759. X        m = (method_t) cool_method(o, m);
  760. X    }
  761. X
  762. X    /* Dispatch handler function with correct parent and sizes */
  763. X    p = PARENTOF(m);
  764. X    /* m = METHODOF(m); debug */
  765. X    meth = &obj->ob_methtab[p][METHODOF(m)];
  766. X
  767. X    /* get args */
  768. X    va_start(ap);
  769. X    for(i = 0; i < meth->m_nargs; i++)
  770. X        args[i] = va_arg(ap, unsigned long);
  771. X    va_end(ap);
  772. X
  773. X    /* Only way to do it */
  774. X    switch(meth->m_nargs) {
  775. X        case 0:
  776. X            return (* meth->m_func)(obj->ob_private[p] + 1);
  777. X        case 1:
  778. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  779. X                args[0]);
  780. X        case 2:
  781. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  782. X                args[0], args[1]);
  783. X        case 3:
  784. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  785. X                args[0], args[1], args[2]);
  786. X        case 4:
  787. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  788. X                args[0], args[1], args[2], args[3]);
  789. X        case 5:
  790. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  791. X                args[0], args[1], args[2], args[3], args[4]);
  792. X        case 6:
  793. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  794. X                args[0], args[1], args[2], args[3], args[4], 
  795. X                args[5]);
  796. X        case 7:
  797. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  798. X                args[0], args[1], args[2], args[3], args[4], 
  799. X                args[5], args[6]);
  800. X        case 8:
  801. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  802. X                args[0], args[1], args[2], args[3], args[4], 
  803. X                args[5], args[6], args[7]);
  804. X        case 9:
  805. X        default:
  806. X            return (* meth->m_func)(obj->ob_private[p] + 1, 
  807. X                args[0], args[1], args[2], args[3], args[4], 
  808. X                args[5], args[6], args[7], args[8]);
  809. X        /* ... MAXARGS */
  810. X    }
  811. X}
  812. X
  813. X
  814. SHAR_EOF
  815. chmod 0644 msg.c ||
  816. echo 'restore of msg.c failed'
  817. Wc_c="`wc -c < 'msg.c'`"
  818. test 2528 -eq "$Wc_c" ||
  819.     echo 'msg.c: original size 2528, current size' "$Wc_c"
  820. fi
  821. # ============= lookup.c ==============
  822. if test -f 'lookup.c' -a X"$1" != X"-c"; then
  823.     echo 'x - skipping lookup.c (File already exists)'
  824. else
  825. echo 'x - extracting lookup.c (Text)'
  826. sed 's/^X//' << 'SHAR_EOF' > 'lookup.c' &&
  827. X/*
  828. X *    COOL: C Object-Oriented Library
  829. X *
  830. X *    Object and method string lookups
  831. X *
  832. X *     Copyright 1991 by Lance Norskog
  833. X *
  834. X *      June 1992: implement overloaded methods
  835. X *
  836. X * Permission to use, copy, modify, and distribute this software and its
  837. X * documentation for any purpose and without fee is hereby granted, provided
  838. X * that the above copyright notice appear in all copies and that both that
  839. X * copyright notice and this permission notice appear in supporting
  840. X * documentation.  This software is provided "as is" without express or
  841. X * implied warranty.
  842. X */
  843. X
  844. X#include <stdio.h>
  845. X#include <setjmp.h>
  846. X#ifdef    USG
  847. X#include <string.h>
  848. X#else
  849. X#include <strings.h>
  850. X#endif
  851. X#include "cool.h"
  852. X#include "coolint.h"
  853. X
  854. X/* 
  855. X * Look up an object in the object table.
  856. X * Return error if not found.
  857. X * 
  858. X * Internal use only!
  859. X */
  860. X
  861. X
  862. Xobject_t
  863. Xcool_getobject(object)
  864. Xobject_t object;
  865. X{
  866. X    cint     i;
  867. X
  868. X    if (ISOBJECT(object))
  869. X        if (GOODGEN(object))
  870. X            return object;
  871. X        else    cool_raise("BadGeneration", CODEMARK);
  872. X    else  {
  873. X
  874. X        /* yeah yeah yeah.  This should use ob_next for a live list. */
  875. X        for(i = 0; i < MAXOBJECTS; i++)
  876. X            if (cool_objtab[i].ob_name && 
  877. X                cool_streq(cool_objtab[i].ob_name, 
  878. X                        (char *) object))
  879. X                    break;
  880. X        if (i == MAXOBJECTS)
  881. X            return OBJECTERR;
  882. X        return (object_t) MKOBJECT(i, cool_objtab[i].ob_generation);
  883. X    } 
  884. X}
  885. X
  886. X/* 
  887. X * Look up an object in the object table.
  888. X * Raise exception if not found.
  889. X */
  890. X
  891. Xobject_t
  892. Xcool_object(object)
  893. Xobject_t object;
  894. X{
  895. X    object_t obj;
  896. X
  897. X    obj = cool_getobject(object);
  898. X    if (obj == OBJECTERR)
  899. X        cool_raise("ObjectDoesNotExist", object);
  900. X    return obj;
  901. X}
  902. X
  903. Xint
  904. Xcool_isobject(object)
  905. Xobject_t object;
  906. X{
  907. X    object_t obj;
  908. X
  909. X    obj = cool_getobject(object);
  910. X    return (obj != OBJECTERR);
  911. X}
  912. X
  913. X/*
  914. X * Get a text name of an object.
  915. X */
  916. X
  917. Xchar *
  918. Xcool_nameof(object)
  919. Xobject_t object;
  920. X{
  921. X    object_t obj;
  922. X
  923. X    obj = cool_getobject(object);
  924. X    if (obj == OBJECTERR)
  925. X        cool_raise("ObjectDoesNotExist", object);
  926. X    return cool_objtab[OBJECTOF(obj)].ob_name;
  927. X}
  928. X
  929. X/*
  930. X * Get a class object of an object.
  931. X */
  932. X
  933. Xobject_t
  934. Xcool_classof(object)
  935. Xobject_t object;
  936. X{
  937. X    object_t ob;
  938. X    objtab_t *obj;
  939. X    int    o, p;
  940. X
  941. X    ob = cool_getobject(object);
  942. X    if (ob == OBJECTERR)
  943. X        cool_raise("ObjectDoesNotExist", object);
  944. X    obj = &cool_objtab[OBJECTOF(ob)];
  945. X    return cool_objtab[OBJECTOF(ob)].ob_private[MYMETHODS]->class;
  946. X}
  947. X
  948. X/*
  949. X * Get a component object of an object.
  950. X */
  951. X
  952. Xobject_t
  953. Xcool_componentof(object, name)
  954. Xobject_t object;
  955. Xchar *name;
  956. X{
  957. X    char *obname, fullname[128];
  958. X    object_t compob;
  959. X
  960. X    obname = cool_nameof(object);
  961. X    sprintf(fullname, "%s.%s", obname, name);
  962. X    compob = cool_getobject((object_t) fullname);
  963. X    if (compob == OBJECTERR)
  964. X        cool_raise("ComponentDoesNotExist", fullname);
  965. X    return compob;
  966. X}
  967. X
  968. X/* 
  969. X * Look up a method in a particular method table.
  970. X * Internal use only!
  971. X */
  972. X
  973. Xmethod_t
  974. Xcool_getmethod(meth, mt)
  975. Xmethod_t    meth;
  976. Xmethtab_t    *mt;
  977. X{
  978. X    cint     i, m, match;
  979. X    sint    matches;
  980. X
  981. X    if (ISMETHOD(meth))
  982. X        return meth;
  983. X    if (mt == NULL) 
  984. X        return METHODERR;
  985. X
  986. X    for(matches = match = m = 0; m < MAXMETHODS; m++, mt++)
  987. X        if (mt->m_name && metheq(mt, (char *) meth)) {
  988. X            match = m;
  989. X            matches++;
  990. X        }
  991. X/* hack! make C keep working the old way for "Create"
  992. X    if (matches == 1)
  993. X        return (method_t) match;
  994. X*/
  995. X            
  996. X    /* return last match */
  997. X    return (matches == 0) ? METHODERR : (method_t) match;
  998. X}
  999. X
  1000. X/* walk methods - each time return next method with same name */
  1001. Xmethod_t
  1002. Xcool_walkmethods(object, name, mp, retp, nargsp, argsp)
  1003. Xobject_t    object;
  1004. Xchar        *name;
  1005. Xmethod_t    *mp;
  1006. Xchar        **retp;
  1007. Xint        *nargsp;
  1008. Xchar        ***argsp;
  1009. X{
  1010. X    object_t ob;
  1011. X    objtab_t *obj;
  1012. X    method_t meth;
  1013. X    methtab_t *mt;
  1014. X    int    m, p;
  1015. X
  1016. X    ob = cool_getobject(object);
  1017. X    if (ob == OBJECTERR)
  1018. X        cool_raise("ObjectDoesNotExist", object);
  1019. X    obj = &cool_objtab[OBJECTOF(ob)];
  1020. X
  1021. X    if (*mp == (method_t) -1) {
  1022. X        m = 0;
  1023. X        p = MYMETHODS;
  1024. X    } else {
  1025. X        /* Search starting after given parent/method */
  1026. X        m = METHODOF(*mp);
  1027. X        p = PARENTOF(*mp);
  1028. X        if (++m == MAXMETHODS) {
  1029. X            p--;
  1030. X            m = 0;
  1031. X        }
  1032. X    }
  1033. X    for(; p >= 0; p--, m = 0) {
  1034. X        if (! (mt = obj->ob_methtab[p]))
  1035. X            continue;
  1036. X        mt = &mt[m];
  1037. X
  1038. X        for(; m < MAXMETHODS; m++, mt++)
  1039. X            if (cool_streq(mt->m_name, name)) {
  1040. X                *mp = MKMETHOD(p, m);
  1041. X                *retp = mt->m_rettype;
  1042. X                *argsp = mt->m_argtypes;
  1043. X                *nargsp = mt->m_nargs;
  1044. X                return 1;
  1045. X            }
  1046. X    }
  1047. X
  1048. X    /* no more of this name */
  1049. X    return 0;
  1050. X}
  1051. X
  1052. Xmethod_t
  1053. Xcool_method(object, method)
  1054. Xobject_t    object;
  1055. Xmethod_t    method;
  1056. X{
  1057. X    object_t ob;
  1058. X    objtab_t *obj;
  1059. X    method_t meth;
  1060. X    methtab_t *mt;
  1061. X    int    p;
  1062. X
  1063. X    ob = cool_getobject(object);
  1064. X    if (ob == OBJECTERR)
  1065. X        cool_raise("ObjectDoesNotExist", object);
  1066. X    obj = &cool_objtab[OBJECTOF(ob)];
  1067. X    /* Search object's methods, then parents' methods */
  1068. X    for(p = MYMETHODS; p >= 0; p--) {
  1069. X        if (mt = obj->ob_methtab[p])
  1070. X            if ((meth = cool_getmethod(method, mt)) != METHODERR)
  1071. X            return MKMETHOD(p, meth);
  1072. X    }
  1073. X    cool_raise("MethodDoesNotExist", method);
  1074. X}
  1075. X
  1076. X
  1077. Xint
  1078. Xcool_hasmethod(object, method)
  1079. Xobject_t    object;
  1080. Xmethod_t    method;
  1081. X{
  1082. X
  1083. X    object_t ob;
  1084. X    objtab_t *obj;
  1085. X    method_t meth;
  1086. X    methtab_t *mt;
  1087. X    int    p;
  1088. X
  1089. X    ob = cool_getobject(object);
  1090. X    if (ob == OBJECTERR)
  1091. X        cool_raise("ObjectDoesNotExist", object);
  1092. X    obj = &cool_objtab[OBJECTOF(ob)];
  1093. X    /* Search object's methods, then parents' methods */
  1094. X    for(p = MYMETHODS; p >= 0; p--) {
  1095. X        if (mt = obj->ob_methtab[p])
  1096. X            if ((meth = cool_getmethod(method, mt)) != METHODERR)
  1097. X            return 1;
  1098. X    }
  1099. X    return 0;
  1100. X}
  1101. X
  1102. Xstatic unsigned long argval[9];
  1103. Xstatic char scmtype[9];
  1104. Xstatic char cooltype[9];
  1105. Xstatic char **ctype;
  1106. X
  1107. X/* table of names corresponding to argument types */
  1108. Xchar *ctypenames[] = {
  1109. X    0,
  1110. X    "",            /* end of argument list */
  1111. X    "integer",
  1112. X    "bool",
  1113. X    "char",
  1114. X    "string",
  1115. X    "object",
  1116. X    "msg",
  1117. X    "double",
  1118. X    "ivect",        /* vector of integers */
  1119. X    "dvect",        /* vector of doubles */
  1120. X    "*",            /* anything */
  1121. X/* VR add-ons */
  1122. X    "point",        /* 3 or 4 doubles */
  1123. X    "homog",        /* homogeneous doubles matrix (4x4) */
  1124. X    (char *) 0
  1125. X};
  1126. X
  1127. X/* digest an argument list.  Return number of arguments found, -1 if no list */
  1128. Xint
  1129. Xmethdigest(mt, s)
  1130. Xmethtab_t *mt;
  1131. Xchar *s;
  1132. X{
  1133. X    int i, j;
  1134. X    char *rt, *at;
  1135. X
  1136. X    mt->m_name = s;
  1137. X
  1138. X    /* add optional return type and arg type list */
  1139. X    /* chop up copy of full string into words, add to list */
  1140. X    /* syntax: method[=[return]][:[argtype[,argtype]*]]  */
  1141. X    /* XXX doesn't catch case where same arg list and different return */
  1142. X    mt->m_rettype = (char *) 0;
  1143. X    for(i = 0; i < MAXARGS; i++)
  1144. X        mt->m_argtypes[i] = (char *) 0;
  1145. X    rt = index(mt->m_name, '=');
  1146. X    at = index(mt->m_name, ':');
  1147. X    if (rt && at && (rt > at) || index(mt->m_name, ' '))
  1148. X        cool_raise("MethodTypeSyntax", NULL);
  1149. X    if (at)
  1150. X        *at++ = '\0';
  1151. X    if (rt) {
  1152. X        *rt++ = '\0';
  1153. X        mt->m_rettype = rt;
  1154. X        /* parse out argument type */
  1155. X        for(j = 1; ctypenames[j]; j++)
  1156. X            if (cool_streq(rt, ctypenames[j]))
  1157. X                mt->m_rettype = (char *) j;
  1158. X        if (mt->m_rettype == CANY)
  1159. X            cool_raise("MethodReturns*", NULL);
  1160. X    }
  1161. X    if (at) {
  1162. X        if (index(at, ':') || index(at, '='))
  1163. X            cool_raise("MethodTypeSyntax", NULL);
  1164. X        mt->m_argtypes[0] = at;
  1165. X        for(i = 1; at = index(at, ','); i++) {
  1166. X            *at++ = '\0';
  1167. X            mt->m_argtypes[i] = at;
  1168. X        }
  1169. X        for(i = 0; mt->m_argtypes[i]; i++) {
  1170. X            /* parse out argument type */
  1171. X            for(j = 1; ctypenames[j]; j++)
  1172. X                if (cool_streq(mt->m_argtypes[i],ctypenames[j]))
  1173. X                    mt->m_argtypes[i] = (char *) j;
  1174. X        }
  1175. X        /* name: no arguments.  VOID is valid return but not arg. */
  1176. X        if (mt->m_argtypes[0] == CVOID) {
  1177. X            mt->m_argtypes[0] = 0;
  1178. X            return 0;
  1179. X        } else
  1180. X            return i;
  1181. X    }
  1182. X    return -1;
  1183. X}
  1184. X
  1185. Xmetheq(mt, s)
  1186. Xmethtab_t *mt;
  1187. Xchar *s;
  1188. X{
  1189. X    int i, nargs;
  1190. X    methtab_t tmp;
  1191. X    char strbuf[256];
  1192. X
  1193. X    strcpy(strbuf, s);
  1194. X    tmp.m_nargs = methdigest(&tmp, strbuf);
  1195. X
  1196. X    if (! cool_streq(mt->m_name, tmp.m_name))
  1197. X        return 0;
  1198. X    if (mt->m_rettype && tmp.m_rettype && 
  1199. X        ! cool_streq(mt->m_rettype, tmp.m_rettype))
  1200. X        return 0;
  1201. X    /* if argument list specified, it must match given method */
  1202. X    if ((tmp.m_nargs >= 0) && (mt->m_nargs != tmp.m_nargs))
  1203. X        return 0;
  1204. X    if (mt->m_argtypes[0] && tmp.m_argtypes[0])
  1205. X        if (! cool_streq(mt->m_argtypes[0], tmp.m_argtypes[0]))
  1206. X            return 0;
  1207. X    for(i = 1; i < MAXARGS && (mt->m_argtypes[i] || tmp.m_argtypes[i]);i++)
  1208. X        if (! cool_streq(mt->m_argtypes[i], tmp.m_argtypes[i]))
  1209. X            return 0;
  1210. X    return 1;
  1211. X}
  1212. X
  1213. X/* junk */
  1214. X
  1215. X#ifdef    JUNK
  1216. Xmetheq(s1, s2)
  1217. Xchar *s1, *s2;
  1218. X{
  1219. X    for(; *s1 || *s2; s1++, s2++) {
  1220. X        if (*s1 == *s2)
  1221. X            continue;
  1222. X        /* if one ends and other doesn't */
  1223. X        if  ((*s1 == '=' || *s1 == ':' || *s1 == ',') && !*s2)
  1224. X            return 1;
  1225. X        if  ((*s2 == '=' || *s2 == ':' || *s2 == ',') && !*s1)
  1226. X            return 1;
  1227. X        /* skip optional return type if arglist */
  1228. X        if  (*s1 == '=' && *s2 == ':')
  1229. X            while(*s1 != ':' && *s1)
  1230. X                s1++;
  1231. X        if  (*s2 == '=' && *s1 == ':')
  1232. X            while(*s2 != ':' && *s2)
  1233. X                s2++;
  1234. X    }
  1235. X    return *s1 == *s2;
  1236. X}
  1237. X#endif
  1238. X
  1239. SHAR_EOF
  1240. chmod 0644 lookup.c ||
  1241. echo 'restore of lookup.c failed'
  1242. Wc_c="`wc -c < 'lookup.c'`"
  1243. test 8509 -eq "$Wc_c" ||
  1244.     echo 'lookup.c: original size 8509, current size' "$Wc_c"
  1245. fi
  1246. # ============= exception.c ==============
  1247. if test -f 'exception.c' -a X"$1" != X"-c"; then
  1248.     echo 'x - skipping exception.c (File already exists)'
  1249. else
  1250. echo 'x - extracting exception.c (Text)'
  1251. sed 's/^X//' << 'SHAR_EOF' > 'exception.c' &&
  1252. X
  1253. X/*
  1254. X *    COOL: C Object-Oriented Library
  1255. X *
  1256. X *    COOL exception system.
  1257. X *
  1258. X *     Copyright 1991 by Lance Norskog
  1259. X *
  1260. X *    No, this will not work with threads.
  1261. X *    You'll have to integrate the two.  Somehow.  Don't ask me.
  1262. X *
  1263. X * Permission to use, copy, modify, and distribute this software and its
  1264. X * documentation for any purpose and without fee is hereby granted, provided
  1265. X * that the above copyright notice appear in all copies and that both that
  1266. X * copyright notice and this permission notice appear in supporting
  1267. X * documentation.  This software is provided "as is" without express or
  1268. X * implied warranty.
  1269. X */
  1270. X
  1271. X#include <stdio.h>
  1272. X#include <setjmp.h>
  1273. X#include <varargs.h>
  1274. X#include "cool.h"
  1275. X#include "coolint.h"
  1276. X
  1277. X/* 
  1278. X * Exception stack.
  1279. X */
  1280. X
  1281. Xstruct exceptiontab {
  1282. X    char     *exception;
  1283. X    jmp_buf    jbuf;
  1284. X} exceptions[MAXEXCEPTIONS];
  1285. Xint topexception = 0;        /* Next useable slot */
  1286. X
  1287. Xint *
  1288. Xcool_pushexception(exception)
  1289. Xchar *exception;
  1290. X{
  1291. X    int e;
  1292. X    int * ret;
  1293. X    
  1294. X    if (topexception == MAXEXCEPTIONS)
  1295. X        cool_raise("TooManyExceptions", NULL);
  1296. X    e = topexception++;
  1297. X    exceptions[e].exception = exception;    /* No need to dup */
  1298. X/*
  1299. X    ret = exceptions[e].jbuf;
  1300. X    return ret;
  1301. X*/
  1302. X    return exceptions[e].jbuf;
  1303. X}
  1304. X
  1305. X/*
  1306. X * Collapse exception table down to entry containing the given jump buffer.
  1307. X */
  1308. Xvoid
  1309. Xcool_popexception(jbuf)
  1310. Xjmp_buf *jbuf;
  1311. X{
  1312. X    struct exceptiontab *ex;
  1313. X
  1314. X    ex = (struct exceptiontab *) jbuf;
  1315. X    topexception = ex - exceptions;
  1316. X}
  1317. X
  1318. Xvoid
  1319. Xcool_raise(exception, fmt, va_alist)
  1320. Xchar *exception, *fmt;
  1321. Xva_dcl
  1322. X{
  1323. X    int e;
  1324. X    va_list args;
  1325. X    
  1326. X    for(e = topexception - 1; e >= 0; e--)
  1327. X        if (cool_streq(exceptions[e].exception, exception))
  1328. X            break;
  1329. X
  1330. X    if (e == -1) {
  1331. X        fflush(stdout);
  1332. X        fprintf(stderr, "COOL Exception: '%s': ", exception);
  1333. X        va_start(args);
  1334. X        /* NULL or "" */
  1335. X        if (fmt && fmt[0])
  1336. X            vfprintf(stderr, fmt, args);
  1337. X        va_end(args);
  1338. X        fprintf(stderr, "\n", exception);
  1339. X        abort();
  1340. X    }
  1341. X
  1342. X    longjmp(exceptions[e].jbuf, 1);
  1343. X}
  1344. X
  1345. X
  1346. SHAR_EOF
  1347. chmod 0644 exception.c ||
  1348. echo 'restore of exception.c failed'
  1349. Wc_c="`wc -c < 'exception.c'`"
  1350. test 1895 -eq "$Wc_c" ||
  1351.     echo 'exception.c: original size 1895, current size' "$Wc_c"
  1352. fi
  1353. # ============= util.c ==============
  1354. if test -f 'util.c' -a X"$1" != X"-c"; then
  1355.     echo 'x - skipping util.c (File already exists)'
  1356. else
  1357. echo 'x - extracting util.c (Text)'
  1358. sed 's/^X//' << 'SHAR_EOF' > 'util.c' &&
  1359. X/*
  1360. X *    COOL: C Object-Oriented Library
  1361. X *
  1362. X *    COOL utilities.  Malloc/free/realloc, strings.
  1363. X *
  1364. X *     Copyright 1991 by Lance Norskog
  1365. X *
  1366. X * Permission to use, copy, modify, and distribute this software and its
  1367. X * documentation for any purpose and without fee is hereby granted, provided
  1368. X * that the above copyright notice appear in all copies and that both that
  1369. X * copyright notice and this permission notice appear in supporting
  1370. X * documentation.  This software is provided "as is" without express or
  1371. X * implied warranty.
  1372. X */
  1373. X
  1374. X#include <stdio.h>    /* for NULL */
  1375. X#include <setjmp.h>    /* for NULL */
  1376. X#include "cool.h"
  1377. X#include "coolint.h"
  1378. X
  1379. X/* Feb 15 92: write own static malloc to find malloc bugs */
  1380. X
  1381. X/*
  1382. Xextern char *malloc(), *realloc();
  1383. Xextern void free();
  1384. X*/
  1385. X
  1386. Xchar malloc_space[512 * 1024];
  1387. Xstatic char *newspace = malloc_space;
  1388. X
  1389. Xchar *
  1390. Xcool_malloc(size)
  1391. Xint size;
  1392. X{
  1393. X    char *newptr;
  1394. X
  1395. X/*
  1396. X    if (! space)
  1397. X        newspace = space = malloc(1024 * 1024);
  1398. X    if (space == 0)
  1399. X        cool_raise("NoMoreMemory", NULL);
  1400. X*/
  1401. X/*
  1402. X    size += size/2;
  1403. X    size += 0x3 & (~size);
  1404. X*/
  1405. X    size = (size + 3) & ~3;
  1406. X    newptr = newspace;
  1407. X    newspace += size;
  1408. X    if (newptr > &malloc_space[ 512 * 1024 ])
  1409. X        cool_raise("NoMoreMemory", NULL);
  1410. X#ifdef    DEBUG
  1411. X    /* add to list */
  1412. X#endif
  1413. X    bzero(newptr, size);
  1414. X    return newptr;
  1415. X}
  1416. X
  1417. Xvoid
  1418. Xcool_free(ptr)
  1419. Xchar *ptr;
  1420. X{
  1421. X#ifdef    DEBUG
  1422. X    /* check list and remove */
  1423. X#endif
  1424. X    /* free(ptr); */
  1425. X}
  1426. X
  1427. Xchar *
  1428. Xcool_realloc(ptr, size)
  1429. Xchar *ptr;
  1430. Xint size;
  1431. X{
  1432. X    char *newptr = cool_malloc(size);
  1433. X
  1434. X#ifdef    DEBUG
  1435. X    /* check list and update if necessary */
  1436. X#endif
  1437. X    bcopy(ptr, newptr, size);
  1438. X    return newptr;
  1439. X}
  1440. X
  1441. X/* String processing stuff */
  1442. X
  1443. X/* 
  1444. X * Duplicate an argument string for internal use.
  1445. X * Should be a string table or something.
  1446. X * Tough.
  1447. X */
  1448. Xchar *
  1449. Xcool_strdup(str)
  1450. Xchar *str;
  1451. X{
  1452. X    char *ret = cool_malloc(strlen(str) + 1);
  1453. X
  1454. X    strcpy(ret, str);
  1455. X    return ret;
  1456. X}
  1457. X
  1458. X/* 
  1459. X * Free an internal duplicate string.
  1460. X */
  1461. Xvoid
  1462. Xcool_strfree(str)
  1463. Xchar *str;
  1464. X{
  1465. X    cool_free(str);
  1466. X}
  1467. X
  1468. X/*
  1469. X * Compare two strings
  1470. X */
  1471. Xint
  1472. Xcool_streq(s1, s2)
  1473. Xchar *s1, *s2;
  1474. X{
  1475. X    return s1 && s2 && ! strcmp(s1, s2);
  1476. X}
  1477. X
  1478. X/* 
  1479. X * Squish spaces out of an argument list 
  1480. X */
  1481. Xcool_squish(from, to)
  1482. Xchar *from, *to;
  1483. X{
  1484. X    while(*from) {
  1485. X        if ((*from != ' ') && (*from != '\t'))
  1486. X            *to++ = *from++;
  1487. X        else
  1488. X            from++;
  1489. X    }
  1490. X    *to = '\0';
  1491. X}
  1492. X
  1493. X/*
  1494. X * Generate unique gibberish string
  1495. X */
  1496. Xchar *
  1497. Xcool_makename() {
  1498. X    static counter = 1234;
  1499. X    char buf[30];
  1500. X    
  1501. X    sprintf(buf, "ZZZ%d", counter++);
  1502. X    return cool_strdup(buf);
  1503. X}
  1504. X
  1505. X/* 
  1506. X * Count number of arguments in argument string
  1507. X */
  1508. X/*
  1509. X * What?
  1510. X
  1511. Xint
  1512. Xcool_countargs(args) 
  1513. Xchar *args;
  1514. X{
  1515. X}
  1516. X*/
  1517. X
  1518. X
  1519. X
  1520. X
  1521. X
  1522. X
  1523. X
  1524. X
  1525. SHAR_EOF
  1526. chmod 0644 util.c ||
  1527. echo 'restore of util.c failed'
  1528. Wc_c="`wc -c < 'util.c'`"
  1529. test 2536 -eq "$Wc_c" ||
  1530.     echo 'util.c: original size 2536, current size' "$Wc_c"
  1531. fi
  1532. # ============= cool.h ==============
  1533. if test -f 'cool.h' -a X"$1" != X"-c"; then
  1534.     echo 'x - skipping cool.h (File already exists)'
  1535. else
  1536. echo 'x - extracting cool.h (Text)'
  1537. sed 's/^X//' << 'SHAR_EOF' > 'cool.h' &&
  1538. X
  1539. X/*
  1540. X *    COOL: C Object-Oriented Library
  1541. X *
  1542. X *    Public header file
  1543. X *
  1544. X *     Copyright 1991 by Lance Norskog
  1545. X *
  1546. X * Permission to use, copy, modify, and distribute this software and its
  1547. X * documentation for any purpose and without fee is hereby granted, provided
  1548. X * that the above copyright notice appear in all copies and that both that
  1549. X * copyright notice and this permission notice appear in supporting
  1550. X * documentation.  This software is provided "as is" without express or
  1551. X * implied warranty.
  1552. X */
  1553. X
  1554. Xtypedef unsigned long    object_t, method_t, ret_t;
  1555. Xvoid        cool_init();
  1556. Xret_t        cool_msg(/* object_t, method_t, [ args ] */);
  1557. X
  1558. X        /* Handy type-caster */
  1559. X#define        cool(type, msg) ((type) cool_msg msg)
  1560. X
  1561. Xobject_t     cool_object(/* object_t ob */);
  1562. Xmethod_t    cool_method(/* object_t ob, method_t m */);
  1563. X
  1564. Xvoid        cool_raise(/* char *exception, *fmt, [ *args] */ );    
  1565. X/* Handy define for fmt/args portion */
  1566. X#define        CODEMARK    "File %s, line %d", __FILE__, __LINE__
  1567. X
  1568. X#define        cool_exception(exception, code, handler) \
  1569. X    { \
  1570. X        int * cool_jmp; \
  1571. X        cool_jmp = cool_pushexception(exception); \
  1572. X        if (setjmp(cool_jmp)) { \
  1573. X            cool_popexception(cool_jmp); \
  1574. X            handler \
  1575. X        } else { \
  1576. X            code \
  1577. X            cool_popexception(cool_jmp); \
  1578. X        } \
  1579. X    }
  1580. X
  1581. Xint         *cool_pushexception(/* char *exception */);
  1582. Xvoid        cool_popexception(/* jmp_buf * */);
  1583. Xchar *        cool_nameof(/* object_t */);
  1584. Xobject_t    cool_classof(/* object_t */);
  1585. Xobject_t    cool_componentof(/* object_t, char * */);
  1586. X/* later */
  1587. X
  1588. X/*
  1589. X * This data structure is always the first part of the secret data of
  1590. X * an object.  It is, however, before the pointer a method handler receives.
  1591. X */
  1592. Xtypedef struct cool_priv {
  1593. X    object_t    self;        /* Inheritance: This object */
  1594. X    object_t    class;        /* Inheritance: Class of this object */
  1595. X} cool_priv_t;
  1596. X
  1597. X#define    SELFOF(priv)    ((cool_priv_t *) priv)[-1].self
  1598. X#define    CLASSOF(priv)    ((cool_priv_t *) priv)[-1].class
  1599. X
  1600. X#ifdef    USG
  1601. X#define index(s, c)    (strchr(s, c))
  1602. X#define rindex(s, c)    (strrchr(s, c))
  1603. X#endif
  1604. SHAR_EOF
  1605. chmod 0644 cool.h ||
  1606. echo 'restore of cool.h failed'
  1607. Wc_c="`wc -c < 'cool.h'`"
  1608. test 1945 -eq "$Wc_c" ||
  1609.     echo 'cool.h: original size 1945, current size' "$Wc_c"
  1610. fi
  1611. true || echo 'restore of coolint.h failed'
  1612. echo End of part 2, continue with part 3
  1613. exit 0
  1614. -- 
  1615.  
  1616. Lance Norskog
  1617.  
  1618. Data is not information is not knowledge is not wisdom.
  1619.