home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / veos-2.0 / part09 < prev    next >
Encoding:
Text File  |  1993-04-25  |  83.8 KB  |  3,648 lines

  1. Newsgroups: comp.sources.unix
  2. From: voodoo@hitl.washington.edu (Geoffery Coco)
  3. Subject: v26i192: veos-2.0 - The Virtual Environment Operating Shell, V2.0, Part09/16
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: voodoo@hitl.washington.edu (Geoffery Coco)
  8. Posting-Number: Volume 26, Issue 192
  9. Archive-Name: veos-2.0/part09
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 9 (of 16)."
  18. # Contents:  src/utils/xform_prims.c src/xlisp/xcore/c/xlbfun.c
  19. #   src/xlisp/xcore/c/xllist.c src/xlisp/xcore/c/xlread.c
  20. # Wrapped by vixie@efficacy.home.vix.com on Sun Apr 25 23:10:41 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'src/utils/xform_prims.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'src/utils/xform_prims.c'\"
  24. else
  25. echo shar: Extracting \"'src/utils/xform_prims.c'\" \(19222 characters\)
  26. sed "s/^X//" >'src/utils/xform_prims.c' <<'END_OF_FILE'
  27. X/* xform_prims.c
  28. X
  29. X   by dav lion, at the HITLab, Seattle
  30. X
  31. X   Copyright (C) 1992  Human Interface Technology Lab, Seattle
  32. X
  33. X   xlisp wrappers for C based matrix geometrical transformation routines
  34. X
  35. X   this code is part of VEOS.
  36. X*/
  37. X
  38. X
  39. X/* xform10_MakeQuaternion() and
  40. X   xform11_NormalizeQuaternion()
  41. X   by Andrew MacDonald,
  42. X   9 Mar 1992
  43. X
  44. X   xform04_PosQuat2Mat and xform08_multQuats() fixed to normalize correctly
  45. X   9 Mar 1992
  46. X
  47. X   xform12_PointTimesQuat()
  48. X   8 Apr 1992
  49. X*/
  50. X
  51. X/****************************************************************************/
  52. X/*                          preliminaries                   */
  53. X
  54. X#include <stdio.h>
  55. X#include <math.h>
  56. X#include <world.h>
  57. X#include "xform_prims.h"
  58. X/* . . . . . . . . . . . . . . F O R W A R D S . . . . . . . . . . . .  */
  59. XLVAL xform01_identmatrix();
  60. XLVAL xform02_multmatrix();
  61. XLVAL xform03_translateMat();
  62. XLVAL xform04_PosQuat2Mat();
  63. XLVAL xform05_scaleMat();
  64. XLVAL xform06_shearMat();
  65. XLVAL xform07_copyMat();
  66. XLVAL xform08_multQuats();
  67. XLVAL xform09_Mat2PosQuat();
  68. XLVAL xform10_MakeQuaternion();
  69. XLVAL xform11_NormalizeQuaternion();
  70. XLVAL xform12_PointTimesQuat();
  71. X
  72. Xvoid Xform_LoadPrims();
  73. X
  74. X
  75. X
  76. X
  77. X/* . . . . . .. .... . . . . . G L O B A L S . . . . . . . . . . . . . .*/
  78. X
  79. X
  80. X
  81. X/* . . . . . . . . . . . . . . E X T E R N S  . . . .  . . . . . . . . .*/
  82. X
  83. X
  84. Xextern LVAL    true;    
  85. Xextern int matrixp();    
  86. X    
  87. X/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  88. X
  89. X/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
  90. X
  91. X
  92. Xvoid
  93. XXform_LoadPrims()
  94. X{
  95. X    
  96. X    xldefine_prim("IDENTITYMATRIX",     SUBR, xform01_identMat);
  97. X    xldefine_prim("MULTMATRIX",     SUBR, xform02_multMat);
  98. X    xldefine_prim("TRANSLATEMATRIX",     SUBR, xform03_translateMat);
  99. X    xldefine_prim("POSQUAT2MAT",     SUBR, xform04_PosQuat2Mat);
  100. X    xldefine_prim("SCALEMATRIX",     SUBR, xform05_scaleMat);
  101. X    xldefine_prim("SHEARMATRIX",     SUBR, xform06_shearMat);
  102. X    xldefine_prim("COPYMATRIX",     SUBR, xform07_copyMat);
  103. X    xldefine_prim("MULTQUATS",        SUBR, xform08_multQuats);
  104. X    xldefine_prim("MAT2POSQUAT",    SUBR, xform09_Mat2PosQuat);
  105. X    xldefine_prim("MAKEQUAT",        SUBR, xform10_MakeQuaternion);
  106. X    xldefine_prim("NORMQUAT",        SUBR, xform11_NormalizeQuaternion);
  107. X    xldefine_prim("POINTXQUAT",        SUBR, xform12_PointTimesQuat);
  108. X    
  109. X    }/*XForm_LoadPrims*/
  110. X
  111. X
  112. X
  113. X
  114. X
  115. Xvoid
  116. Xxform_normalizeVec(target, pMagnitude)
  117. Xfloat    target[3];
  118. Xfloat    *pMagnitude;
  119. X{
  120. X    float    magnitude;
  121. X    
  122. X#ifdef SGI
  123. X    magnitude = fsqrt(target[0] * target[0] +
  124. X              target[1] * target[1] +
  125. X              target[2] * target[2] );
  126. X#else
  127. X    magnitude = (float)sqrt((double)(target[0] * target[0] +
  128. X                target[1] * target[1] +
  129. X                target[2] * target[2] ));
  130. X#endif
  131. X    
  132. X    
  133. X    if (magnitude > EPSILON) {
  134. X    
  135. X    target[0] /= magnitude;
  136. X    target[1] /= magnitude;
  137. X    target[2] /= magnitude;
  138. X    }/*endif sane */
  139. X    else
  140. X    magnitude = 0.0;
  141. X    
  142. X    *pMagnitude = magnitude;
  143. X    }/*vecNormalizeVec*/
  144. X
  145. X
  146. Xfloat
  147. Xxform_magnitude( v)
  148. X    Vector    v;
  149. X{
  150. X    return( sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
  151. X}
  152. X
  153. X
  154. XLVAL
  155. Xxform01_identMat()
  156. X{
  157. X    LVAL    lMat;
  158. X    int        iCounter;
  159. X
  160. X    lMat = xlgetarg();
  161. X
  162. X    if (matrixp(lMat)) {
  163. X    xllastarg();
  164. X
  165. X    stuff_flonum(lMat, 0, 1.0);
  166. X    stuff_flonum(lMat, 1, 0.0);
  167. X    stuff_flonum(lMat, 2, 0.0);
  168. X    stuff_flonum(lMat, 3, 0.0);
  169. X
  170. X    stuff_flonum(lMat, 4, 0.0);
  171. X    stuff_flonum(lMat, 5, 1.0);
  172. X    stuff_flonum(lMat, 6, 0.0);
  173. X    stuff_flonum(lMat, 7, 0.0);
  174. X
  175. X    stuff_flonum(lMat, 8, 0.0);
  176. X    stuff_flonum(lMat, 9, 0.0);
  177. X    stuff_flonum(lMat, 10, 1.0);
  178. X    stuff_flonum(lMat, 11, 0.0);
  179. X
  180. X    stuff_flonum(lMat, 12, 0.0);
  181. X    stuff_flonum(lMat, 13, 0.0);
  182. X    stuff_flonum(lMat, 14, 0.0);
  183. X    stuff_flonum(lMat, 15, 1.0);
  184. X
  185. X    }/*endif happy */
  186. X    else
  187. X    xlerror("Not a Matrix");
  188. X
  189. X    return (true);
  190. X
  191. X    }/*xform01_identMat*/
  192. X
  193. X
  194. X
  195. X
  196. XLVAL
  197. Xxform02_multMat()
  198. X{
  199. X    LVAL    lM1;
  200. X    LVAL    lM2;
  201. X    LVAL    lM3;
  202. X
  203. X    static    Matrix    temp;
  204. X
  205. X    int        y;
  206. X    int        x;
  207. X
  208. X    lM1 = xlgetarg();
  209. X    if (matrixp(lM1)) {
  210. X
  211. X    lM2 = xlgetarg();
  212. X    if (matrixp(lM2)) {
  213. X        lM3 = xlgetarg();
  214. X        if (matrixp(lM3)) {
  215. X        xllastarg();
  216. X        
  217. X        for(y=0; y<4 ; y++) 
  218. X            for(x=0 ; x<4 ; x++) {
  219. X            temp[y][x] = ( m_float(lM2, y, 0) * m_float(lM1, 0, x)
  220. X                      + m_float(lM2, y, 1) * m_float(lM1, 1, x)
  221. X                      + m_float(lM2, y, 2) * m_float(lM1, 2, x)
  222. X                      + m_float(lM2, y, 3) * m_float(lM1, 3, x));
  223. X            }/*for x*/
  224. X        
  225. X        Mat2LispMat(temp,lM3);
  226. X        
  227. X        }/*endif happy*/
  228. X        else
  229. X        xlerror("arg 3 not a matrix");
  230. X        }/*endif arg2 a matrix*/
  231. X    else
  232. X        xlerror("arg2 not a matrix");
  233. X    }/*endif arg1 a matrix*/
  234. X    else
  235. X    xlerror("arg 1 not a matrix");
  236. X
  237. X    return (true);
  238. X
  239. X    }/*xform02_multMat*/
  240. X
  241. X
  242. X
  243. XLVAL
  244. Xxform03_translateMat()
  245. X{
  246. X    LVAL    lMat;
  247. X    LVAL    lTri;
  248. X
  249. X    lMat = xlgetarg();
  250. X    if (matrixp(lMat)) {
  251. X    lTri = xlgetarg();
  252. X    if (triplep(lTri)) {
  253. X        xllastarg();
  254. X        
  255. X        stuff_flonum(lMat, 0, 1.0);
  256. X        stuff_flonum(lMat, 1, 0.0);
  257. X        stuff_flonum(lMat, 2, 0.0);
  258. X        stuff_flonum(lMat, 3, 0.0);
  259. X        
  260. X        stuff_flonum(lMat, 4, 0.0);
  261. X        stuff_flonum(lMat, 5, 1.0);
  262. X        stuff_flonum(lMat, 6, 0.0);
  263. X        stuff_flonum(lMat, 7, 0.0);
  264. X        
  265. X        stuff_flonum(lMat, 8, 0.0);
  266. X        stuff_flonum(lMat, 9, 0.0);
  267. X        stuff_flonum(lMat, 10, 1.0);
  268. X        stuff_flonum(lMat, 11, 0.0);
  269. X        
  270. X        stuff_flonum(lMat, 12, v_float(lTri, 0));
  271. X        stuff_flonum(lMat, 13, v_float(lTri, 1));
  272. X        stuff_flonum(lMat, 14, v_float(lTri, 2));
  273. X        stuff_flonum(lMat, 15, 1.0);
  274. X        
  275. X        }/*endif happy*/
  276. X    else 
  277. X        xlerror("arg 2 not a triple ");
  278. X    }/*endif found matrix */
  279. X    else
  280. X    xlerror("arg 1 not a matrix");
  281. X
  282. X    return (true);
  283. X
  284. X    }/*xform03_translateMat*/
  285. X
  286. X
  287. X
  288. X
  289. XLVAL
  290. Xxform05_scaleMat()
  291. X{
  292. X    LVAL    lMat;
  293. X    LVAL    lTri;
  294. X
  295. X    lMat = xlgetarg();
  296. X    if (matrixp(lMat)) {
  297. X
  298. X    lTri = xlgetarg();
  299. X    if (triplep(lTri)) {
  300. X        xllastarg();
  301. X        
  302. X        stuff_flonum(lMat, 0, v_float(lTri,0));
  303. X        stuff_flonum(lMat, 1, 0.0);
  304. X        stuff_flonum(lMat, 2, 0.0);
  305. X        stuff_flonum(lMat, 3, 0.0);
  306. X        
  307. X        stuff_flonum(lMat, 4, 1.0);
  308. X        stuff_flonum(lMat, 5, v_float(lTri,1));
  309. X        stuff_flonum(lMat, 6, 0.0);
  310. X        stuff_flonum(lMat, 7, 0.0);
  311. X        
  312. X        stuff_flonum(lMat, 8, 1.0);
  313. X        stuff_flonum(lMat, 9, 0.0);
  314. X        stuff_flonum(lMat, 10, v_float(lTri,2));
  315. X        stuff_flonum(lMat, 11, 0.0);
  316. X        
  317. X        stuff_flonum(lMat, 12, 0.0);
  318. X        stuff_flonum(lMat, 13, 0.0);
  319. X        stuff_flonum(lMat, 14, 0.0);
  320. X        stuff_flonum(lMat, 15, 1.0);
  321. X        
  322. X        }/*endif happy*/
  323. X    else 
  324. X        xlerror("arg 2 not a triple");
  325. X    }/*endif found matrix*/
  326. X    else
  327. X    xlerror("arg 1 not a matrix");
  328. X
  329. X    return (true);
  330. X    }/*xform05_scaleMat*/
  331. X
  332. X
  333. XLVAL
  334. Xxform06_shearMat()
  335. X{
  336. X    LVAL    lMat;
  337. X    LVAL    lX;
  338. X    LVAL    lY;
  339. X
  340. X    lMat = xlgetarg();
  341. X    if (matrixp(lMat)) {
  342. X    
  343. X    lX = xlgaflonum();
  344. X    lY = xlgaflonum();
  345. X    xllastarg();
  346. X    
  347. X    stuff_flonum(lMat, 0, 1.0);
  348. X    stuff_flonum(lMat, 1, 0.0);
  349. X    stuff_flonum(lMat, 2, 0.0);
  350. X    stuff_flonum(lMat, 3, 0.0);
  351. X    
  352. X    stuff_flonum(lMat, 4, getflonum(lX));
  353. X    stuff_flonum(lMat, 5, getflonum(lY));
  354. X    stuff_flonum(lMat, 6, 0.0);
  355. X    stuff_flonum(lMat, 7, 0.0);
  356. X    
  357. X    stuff_flonum(lMat, 8, 0.0);
  358. X    stuff_flonum(lMat, 9, 0.0);
  359. X    stuff_flonum(lMat, 10, 1.0);
  360. X    stuff_flonum(lMat, 11, 0.0);
  361. X    
  362. X    stuff_flonum(lMat, 12, 0.0);
  363. X    stuff_flonum(lMat, 13, 0.0);
  364. X    stuff_flonum(lMat, 14, 0.0);
  365. X    stuff_flonum(lMat, 15, 1.0);
  366. X    
  367. X    }/*endif found matrix*/
  368. X    else
  369. X    xlerror("arg 1 not a matrix");
  370. X    
  371. X    return (true);
  372. X    }/*xform06_shearMat*/
  373. X
  374. X
  375. X
  376. XLVAL
  377. Xxform07_copyMat()
  378. X{
  379. X    LVAL    lSrc;
  380. X    LVAL    lDest;
  381. X
  382. X    lSrc = xlgetarg();
  383. X    if (matrixp(lSrc)) {
  384. X    lDest = xlgetarg();
  385. X    if (matrixp(lDest)){
  386. X        
  387. X        lDest->n_vdata[0]->n_flonum = lSrc->n_vdata[0]->n_flonum;
  388. X        lDest->n_vdata[1]->n_flonum = lSrc->n_vdata[1]->n_flonum;
  389. X        lDest->n_vdata[2]->n_flonum = lSrc->n_vdata[2]->n_flonum;
  390. X        lDest->n_vdata[3]->n_flonum = lSrc->n_vdata[3]->n_flonum;
  391. X
  392. X
  393. X        lDest->n_vdata[4]->n_flonum = lSrc->n_vdata[4]->n_flonum;
  394. X        lDest->n_vdata[5]->n_flonum = lSrc->n_vdata[5]->n_flonum;
  395. X        lDest->n_vdata[6]->n_flonum = lSrc->n_vdata[6]->n_flonum;
  396. X        lDest->n_vdata[7]->n_flonum = lSrc->n_vdata[7]->n_flonum;
  397. X
  398. X        lDest->n_vdata[8]->n_flonum = lSrc->n_vdata[8]->n_flonum;
  399. X        lDest->n_vdata[9]->n_flonum = lSrc->n_vdata[9]->n_flonum;
  400. X        lDest->n_vdata[10]->n_flonum = lSrc->n_vdata[10]->n_flonum;
  401. X        lDest->n_vdata[11]->n_flonum = lSrc->n_vdata[11]->n_flonum;
  402. X
  403. X        lDest->n_vdata[12]->n_flonum = lSrc->n_vdata[12]->n_flonum;
  404. X        lDest->n_vdata[13]->n_flonum = lSrc->n_vdata[13]->n_flonum;
  405. X        lDest->n_vdata[14]->n_flonum = lSrc->n_vdata[14]->n_flonum;
  406. X        lDest->n_vdata[15]->n_flonum = lSrc->n_vdata[15]->n_flonum;
  407. X
  408. X        }/*endif happy*/
  409. X    else
  410. X        xlerror("arg 2 not a matrix");
  411. X    }/*endif found src matrix*/
  412. X    else
  413. X    xlerror("arg 1 not a matrix");
  414. X
  415. X    return (true);
  416. X
  417. X    }/*xform07_copyMat*/
  418. X
  419. X
  420. X
  421. XLVAL
  422. Xxform04_PosQuat2Mat()
  423. X{
  424. X    LVAL    lPos;
  425. X    LVAL    lQuat;
  426. X    LVAL    lMat;
  427. X
  428. X     float x2, y2, z2, xx2, yy2, zz2, xy2, xz2, xw2, yw2, yz2, zw2;
  429. X     float    fMagnitude;
  430. X     Quaternion q;
  431. X    
  432. X    lPos = xlgetarg();
  433. X    if (triplep(lPos)){
  434. X    lQuat = xlgetarg();
  435. X    if (quaternionp(lQuat)) {
  436. X        lMat = xlgetarg();
  437. X        if (matrixp(lMat)) {
  438. X        
  439. X        
  440. X        q[0] = getflonum(getelement(lQuat, 0));
  441. X        q[1] = getflonum(getelement(getelement(lQuat,1),0));
  442. X        q[2] = getflonum(getelement(getelement(lQuat,1),1));
  443. X        q[3] = getflonum(getelement(getelement(lQuat,1),2));
  444. X        
  445. X/*        fMagnitude = xform_magnitude(&(q[1]));
  446. X        if (fMagnitude == 0.0)
  447. X            xlerror("rotate: zero length vector");
  448. X*/
  449. X#ifdef DEBUG
  450. X        fprintf(stderr, "quat after is <%f,%f,%f,%f>\n",
  451. X            q[0], q[1], q[2], q[3]);
  452. X#endif        
  453. X        x2 = q[1] + q[1];
  454. X        y2 = q[2] + q[2];
  455. X        z2 = q[3] + q[3];
  456. X        
  457. X        xx2 = q[1] * x2;
  458. X        yy2 = q[2] * y2;
  459. X        zz2 = q[3] * z2;
  460. X        xy2 = q[1] * y2;
  461. X        xz2 = q[1] * z2;
  462. X        yz2 = q[2] * z2;
  463. X        xw2 = q[0] * x2;
  464. X        yw2 = q[0] * y2;
  465. X        zw2 = q[0] * z2;
  466. X        
  467. X        stuff_flonum(lMat, 0, 1.0 - yy2 - zz2);
  468. X        stuff_flonum(lMat, 1, xy2 + zw2);
  469. X        stuff_flonum(lMat, 2,  xz2 - yw2);
  470. X        stuff_flonum(lMat, 4, xy2 - zw2);
  471. X        stuff_flonum(lMat, 5, 1.0 - xx2 - zz2);
  472. X        stuff_flonum(lMat, 6, yz2 + xw2);
  473. X        stuff_flonum(lMat, 8, xz2 + yw2);
  474. X        stuff_flonum(lMat, 9, yz2 - xw2);
  475. X        stuff_flonum(lMat, 10, 1.0 - xx2 - yy2);
  476. X
  477. X        stuff_flonum(lMat, 12, v_float(lPos,0));
  478. X        stuff_flonum(lMat, 13, v_float(lPos,1));
  479. X        stuff_flonum(lMat, 14, v_float(lPos,2));
  480. X
  481. X        stuff_flonum(lMat, 3, 0.0);
  482. X        stuff_flonum(lMat, 7, 0.0);
  483. X        stuff_flonum(lMat, 11, 0.0);
  484. X        stuff_flonum(lMat, 15, 1.0);
  485. X        
  486. X        
  487. X        }/*endif sane*/
  488. X        else
  489. X        xlerror("PosQuat2Mat: arg 3 not a matrix");
  490. X        }/*endif found matrix*/
  491. X    else
  492. X        xlerror("PosQuat2Mat: arg 2 not a quaternion");
  493. X    }/*endif found triple */
  494. X    else
  495. X    xlerror("PosQuat2Mat: arg 1 not a triple");
  496. X
  497. X    return (true);
  498. X
  499. X     }/*xform04_PosQuat2Mat*/
  500. X     
  501. X
  502. X
  503. XLVAL
  504. Xxform08_multQuats()
  505. X{
  506. X    Quaternion    q1;
  507. X    Quaternion     q2;
  508. X    Quaternion    q3;
  509. X    
  510. X    LVAL    lQ1;
  511. X    LVAL    lQ2;
  512. X    LVAL    lQ3;
  513. X    LVAL    lQ3elt;                  /* element of lQ3          */
  514. X
  515. X    float    fMagnitude;
  516. X    Vector    vCrossProduct;
  517. X
  518. X    lQ1 = xlgetarg();
  519. X    if (quaternionp(lQ1)) {
  520. X    lQ2 = xlgetarg();
  521. X    if (quaternionp(lQ2)){
  522. X        lQ3 = xlgetarg();
  523. X        if (quaternionp(lQ3)) {
  524. X
  525. X        lQ3elt = getelement(lQ3,1);      /* will need this for stuffing */
  526. X
  527. X        q1[0] = getflonum(getelement(lQ1, 0));
  528. X        q1[1] = getflonum(getelement(getelement(lQ1,1),0));
  529. X        q1[2] = getflonum(getelement(getelement(lQ1,1),1));
  530. X        q1[3] = getflonum(getelement(getelement(lQ1,1),2));
  531. X        
  532. X        
  533. X        q2[0] = getflonum(getelement(lQ2, 0));
  534. X        q2[1] = getflonum(getelement(getelement(lQ2,1),0));
  535. X        q2[2] = getflonum(getelement(getelement(lQ2,1),1));
  536. X        q2[3] = getflonum(getelement(getelement(lQ2,1),2));
  537. X
  538. X        if (FEPS(q1[0],0.0)) {
  539. X            if (!FEPS(q2[0],0.0)) {
  540. X            stuff_flonum(lQ3, 0, q2[0]);
  541. X            stuff_flonum(lQ3elt, 0, q2[1]);
  542. X            stuff_flonum(lQ3elt, 1, q2[2]);
  543. X            stuff_flonum(lQ3elt, 2, q2[3]);
  544. X            }/*endif q1 bad, q2 good*/
  545. X/*            else {
  546. X            xlerror("multquats: q1 and q2 have no rotation");
  547. X            }/*else both bad*/
  548. X            }/*endif q1 bad*/
  549. X        else
  550. X            { /* q1 must be ok, so check q2 */
  551. X            if (FEPS(q2[0],0.0)) {
  552. X            stuff_flonum(lQ3, 0, q1[0]);
  553. X            stuff_flonum(lQ3elt, 0, q1[1]);
  554. X            stuff_flonum(lQ3elt, 1, q1[2]);
  555. X            stuff_flonum(lQ3elt, 2, q1[3]);
  556. X            }/*endif q1 ok, q2 bad*/
  557. X            else 
  558. X            { /* else both ok*/
  559. X/*            fMagnitude = xform_magnitude(&(q1[1]));
  560. X            if (fMagnitude == 0.0)
  561. X                xlerror("multquats: arg 1 zero length vector");
  562. X            
  563. X            fMagnitude = xform_magnitude(&(q1[1]));
  564. X            if (fMagnitude == 0.0)
  565. X                xlerror("mulquats: arg 2 zero length vector");
  566. X*/            
  567. X            
  568. X            vCrossProduct[0] = q1[2] * q2[3] - q1[3] * q2[2];
  569. X            vCrossProduct[1] = q1[3] * q2[1] - q1[1] * q2[3];
  570. X            vCrossProduct[2] = q1[1] * q2[2] - q1[2] * q2[1];
  571. X
  572. X            
  573. X            q3[0] = (q1[0] * q2[0]) - 
  574. X                ((q1)[1]*(q2)[1] + (q1)[2]*(q2)[2] + (q1)[3]*(q2)[3]);
  575. X                          /* line above is dot product */
  576. X
  577. X            q3[1] = (q1[0] * q2[1]) + (q2[0] * q1[1]) + vCrossProduct[0];
  578. X            q3[2] = (q1[0] * q2[2]) + (q2[0] * q1[2]) + vCrossProduct[1];
  579. X            q3[3] = (q1[0] * q2[3]) + (q2[0] * q1[3]) + vCrossProduct[2];
  580. X            
  581. X/*            fMagnitude = xform_magnitude(&(q3[1]));
  582. X            if (fMagnitude == 0.0)
  583. X                xlerror("multquats: result zero length vector");
  584. X*/            
  585. X            stuff_flonum(lQ3, 0, q3[0]);
  586. X            stuff_flonum(lQ3elt, 0, q3[1]);
  587. X            stuff_flonum(lQ3elt, 1, q3[2]);
  588. X            stuff_flonum(lQ3elt, 2, q3[3]);
  589. X            
  590. X            
  591. X            }/*else both are ok*/
  592. X            }/*else*/
  593. X        }/*endif happy*/
  594. X        else
  595. X        xlerror("multquats: arg3 not quaternion");
  596. X        }/*endif got quat2*/
  597. X    else
  598. X        xlerror("multquats, arg2 not quaternion");
  599. X    }/*endif arg1 quat*/
  600. X    else
  601. X    xlerror("multquats: arg1 not quaternion");
  602. X    
  603. X    
  604. X
  605. X    return (true);
  606. X
  607. X    }/*xform08_multiplyQuats*/
  608. X
  609. X
  610. X
  611. XLVAL
  612. Xxform09_Mat2PosQuat()
  613. X{
  614. X    LVAL    lPos;
  615. X    LVAL    lQuat;
  616. X    LVAL    lMat;
  617. X
  618. X    float w2, w4, x2, y2;
  619. X    Quaternion q;
  620. X    Matrix    m;
  621. X    
  622. X    lMat = xlgetarg();
  623. X    if (matrixp(lMat)) {
  624. X    lPos = xlgetarg();
  625. X    if (triplep(lPos)){
  626. X        lQuat = xlgetarg();
  627. X        if (quaternionp(lQuat)) {
  628. X        
  629. X        w2 = 0.25 * (m_float(lMat, 0, 0) + m_float(lMat, 1, 1) 
  630. X                 + m_float(lMat, 2, 2) + m_float(lMat, 3, 3));
  631. X        if (w2 > EPSILON)
  632. X            {
  633. X            q[0] = sqrt(w2);
  634. X            w4 = 4.0 * q[0];
  635. X            q[1] = (m_float(lMat, 1, 2) - m_float(lMat, 2, 1)) / w4;
  636. X            q[2] = (m_float(lMat, 2, 0) - m_float(lMat, 0, 2)) / w4;
  637. X            q[3] = (m_float(lMat, 0, 1) - m_float(lMat, 1, 0)) / w4;
  638. X            }
  639. X        else
  640. X            {
  641. X            q[0] = 0.0;
  642. X            x2 = -0.5 * (m_float(lMat, 1, 1) + m_float(lMat, 2, 2));
  643. X            if (x2 > EPSILON)
  644. X            {
  645. X            q[1] = sqrt(x2);
  646. X            x2 = 2.0 * q[1];
  647. X            q[2] = m_float(lMat, 0, 1) / x2;
  648. X            q[3] = m_float(lMat, 0, 2) / x2;
  649. X            }
  650. X            else
  651. X            {
  652. X            q[1] = 0.0;
  653. X            y2 = 0.5 * (1.0 - m_float(lMat, 2, 2));
  654. X            if (y2 > EPSILON)
  655. X                {
  656. X                q[2] = sqrt(y2);
  657. X                q[3] = m_float(lMat, 1, 2) / (2.0 * q[2]);
  658. X                }
  659. X            else
  660. X                {
  661. X                q[2] = 0.0;
  662. X                q[3] = 1.0;
  663. X                }
  664. X            }
  665. X            }
  666. X        
  667. X        stuff_flonum(lQuat, 0, q[0]);
  668. X        stuff_flonum(lQuat, 1, q[1]);
  669. X        stuff_flonum(lQuat, 2, q[2]);
  670. X        stuff_flonum(lQuat, 3, q[3]);
  671. X
  672. X        stuff_flonum(lPos, 0, m_float(lMat, 3, 0));
  673. X        stuff_flonum(lPos, 1, m_float(lMat, 3, 1));
  674. X        stuff_flonum(lPos, 2, m_float(lMat, 3, 2));
  675. X        
  676. X        
  677. X        }/*endif sane*/
  678. X        else
  679. X        xlerror("Mat2Quat: arg 3 not a quaternion");
  680. X        }/*endif found matrix*/
  681. X    else
  682. X        xlerror("Mat2Quat: arg 2 not a triple");
  683. X    }/*endif found triple */
  684. X    else
  685. X    xlerror("Mat2Quat: arg 1 not a matrix");
  686. X
  687. X    return (true);
  688. X    }/*xform09_Mat2PosQuat*/
  689. X
  690. X
  691. X/* make a normalized quaternion from an angle (in radians) and a non-zero vector
  692. X   (indicating axis of rotation).  Third argument is quaternion to return result
  693. X   in. */
  694. XLVAL
  695. Xxform10_MakeQuaternion()
  696. X{
  697. X    LVAL    lRot;
  698. X    LVAL    lVec;
  699. X    LVAL    lQuat;
  700. X
  701. X    LVAL    lQuatElt;
  702. X    register float    norm, mag, w, x, y, z;
  703. X    
  704. X    lRot = xlgaflonum();
  705. X    lVec = xlgetarg();
  706. X    if( triplep( lVec))
  707. X    {
  708. X    lQuat = xlgetarg();
  709. X    if( quaternionp( lQuat))
  710. X    {
  711. X        w = cos( getflonum(lRot) / 2.0) * (getflonum(lRot) < 0.0 ? -1.0 : 1.0);
  712. X        x = getflonum( getelement( lVec, 0));
  713. X        y = getflonum( getelement( lVec, 1));
  714. X        z = getflonum( getelement( lVec, 2));
  715. X        
  716. X           /* actually magnitude squared */
  717. X        mag = x * x + y * y + z * z;
  718. X
  719. X        if( mag == 0.0)
  720. X        xlerror("MakeQuaternion: vector has zero length");
  721. X        else
  722. X        {
  723. X           /* normalizing factor to apply to the vector.
  724. X              the angle element is already the RIGHT THING, so we have
  725. X              to make magnitude 1.0 while keeping w constant */
  726. X        norm = sqrt( (1.0 - w * w) / mag);
  727. X        
  728. X        lQuatElt = getelement( lQuat, 1);
  729. X        stuff_flonum( lQuat, 0, w);
  730. X        stuff_flonum( lQuatElt, 0, x * norm);
  731. X        stuff_flonum( lQuatElt, 1, y * norm);
  732. X        stuff_flonum( lQuatElt, 2, z * norm);
  733. X        }
  734. X    }
  735. X    else
  736. X        xlerror("MakeQuaternion: arg3 not quaternion");
  737. X    }
  738. X    else
  739. X    xlerror("MakeQuaternion: arg2 not vector");
  740. X    
  741. X    return( true);
  742. X}
  743. X
  744. X        
  745. X        
  746. X/* normalize a quaternion (the argument).  Assumes the first component, the
  747. X   angle, is already in standard form -- cos( angle / 2).  Only fusses with
  748. X   the vector component */
  749. XLVAL
  750. Xxform11_NormalizeQuaternion()
  751. X{
  752. X    LVAL    lQuat;
  753. X    
  754. X    LVAL    lQuatElt;
  755. X    register float    norm, mag, w, x, y, z;
  756. X    
  757. X    lQuat = xlgetarg();
  758. X    if( quaternionp( lQuat))
  759. X    {
  760. X    w = getflonum( getelement( lQuat, 0));
  761. X    lQuatElt = getelement( lQuat, 1);
  762. X    x = getflonum( getelement( lQuatElt, 0));
  763. X    y = getflonum( getelement( lQuatElt, 1));
  764. X    z = getflonum( getelement( lQuatElt, 2));
  765. X
  766. X        /* actually magnitude squared */
  767. X    mag = x * x + y * y + z * z;
  768. X
  769. X    if( mag == 0.0)
  770. X        xlerror("NormalizeQuaternion: vector part has zero length");
  771. X    else
  772. X    {
  773. X            /* normalizing factor to apply to the vector.
  774. X           the angle element is already the RIGHT THING, so we have
  775. X           to make magnitude 1.0 while keeping w constant */
  776. X        norm = sqrt( (1.0 - w * w) / mag);
  777. X        
  778. X        stuff_flonum( lQuat, 0, w);
  779. X        stuff_flonum( lQuatElt, 0, x * norm);
  780. X        stuff_flonum( lQuatElt, 1, y * norm);
  781. X        stuff_flonum( lQuatElt, 2, z * norm);
  782. X    }
  783. X    }
  784. X    else
  785. X    xlerror("NormalizeQuaternion: arg1 not quaternion");
  786. X
  787. X    return( true);
  788. X}
  789. X
  790. XLVAL
  791. Xxform12_PointTimesQuat()
  792. X{
  793. X    LVAL    lPoint;
  794. X    LVAL    lQuat;
  795. X    LVAL    lResult;
  796. X
  797. X    float x2, y2, z2, xx2, yy2, zz2, xy2, xz2, xw2, yw2, yz2, zw2;
  798. X    float a, b, c;
  799. X    Quaternion q;
  800. X    
  801. X    lPoint = xlgetarg();
  802. X    if (triplep(lPoint)){
  803. X    lQuat = xlgetarg();
  804. X    if (quaternionp(lQuat)) {
  805. X        lResult = xlgetarg();
  806. X        if (triplep(lResult)) {
  807. X        
  808. X        q[0] = getflonum(getelement(lQuat, 0));
  809. X        q[1] = getflonum(getelement(getelement(lQuat,1),0));
  810. X        q[2] = getflonum(getelement(getelement(lQuat,1),1));
  811. X        q[3] = getflonum(getelement(getelement(lQuat,1),2));
  812. X        
  813. X        x2 = q[1] + q[1];
  814. X        y2 = q[2] + q[2];
  815. X        z2 = q[3] + q[3];
  816. X        
  817. X        xx2 = q[1] * x2;
  818. X        yy2 = q[2] * y2;
  819. X        zz2 = q[3] * z2;
  820. X        xy2 = q[1] * y2;
  821. X        xz2 = q[1] * z2;
  822. X        yz2 = q[2] * z2;
  823. X        xw2 = q[0] * x2;
  824. X        yw2 = q[0] * y2;
  825. X        zw2 = q[0] * z2;
  826. X        
  827. X        a = getflonum(getelement(lPoint, 0));
  828. X        b = getflonum(getelement(lPoint, 1));
  829. X        c = getflonum(getelement(lPoint, 2));
  830. X
  831. X        stuff_flonum(lResult, 0, 
  832. X                 a * (1.0 - yy2 - zz2) +
  833. X                 b * (xy2 - zw2) +
  834. X                 c * (xz2 + yw2));
  835. X
  836. X        stuff_flonum(lResult, 1,
  837. X                 a * (xy2 + zw2) +
  838. X                 b * (1 - xx2 - zz2) +
  839. X                 c * (yz2 - xw2));
  840. X
  841. X        stuff_flonum(lResult, 2,
  842. X                 a * (xz2 - yw2) +
  843. X                 b * (yz2 + xw2) +
  844. X                 c * (1 - xx2 - yy2));
  845. X        }/*endif sane*/
  846. X        else
  847. X        xlerror("PointTimesQuat: arg 3 not a triple");
  848. X        }/*endif found matrix*/
  849. X    else
  850. X        xlerror("PointTimesQuat: arg 2 not a quaternion");
  851. X    }/*endif found triple */
  852. X    else
  853. X    xlerror("PointTimesQuat: arg 1 not a triple");
  854. X
  855. X    return (true);
  856. X
  857. X     }/* xform12_PointTimesQuat */
  858. X     
  859. END_OF_FILE
  860. if test 19222 -ne `wc -c <'src/utils/xform_prims.c'`; then
  861.     echo shar: \"'src/utils/xform_prims.c'\" unpacked with wrong size!
  862. fi
  863. # end of 'src/utils/xform_prims.c'
  864. fi
  865. if test -f 'src/xlisp/xcore/c/xlbfun.c' -a "${1}" != "-c" ; then 
  866.   echo shar: Will not clobber existing file \"'src/xlisp/xcore/c/xlbfun.c'\"
  867. else
  868. echo shar: Extracting \"'src/xlisp/xcore/c/xlbfun.c'\" \(19033 characters\)
  869. sed "s/^X//" >'src/xlisp/xcore/c/xlbfun.c' <<'END_OF_FILE'
  870. X/* -*-C-*-
  871. X********************************************************************************
  872. X*
  873. X* File:         xlbfun.c
  874. X* RCS:          $Header: xlbfun.c,v 1.2 89/11/25 05:13:34 mayer Exp $
  875. X* Description:  xlisp basic built-in functions
  876. X* Author:       David Michael Betz
  877. X* Created:      
  878. X* Modified:     Sat Nov 25 05:13:11 1989 (Niels Mayer) mayer@hplnpm
  879. X* Language:     C
  880. X* Package:      N/A
  881. X* Status:       X11r4 contrib tape release
  882. X*
  883. X* WINTERP 1.0 Copyright 1989 Hewlett-Packard Company (by Niels Mayer).
  884. X* XLISP version 2.1, Copyright (c) 1989, by David Betz.
  885. X*
  886. X* Permission to use, copy, modify, distribute, and sell this software and its
  887. X* documentation for any purpose is hereby granted without fee, provided that
  888. X* the above copyright notice appear in all copies and that both that
  889. X* copyright notice and this permission notice appear in supporting
  890. X* documentation, and that the name of Hewlett-Packard and David Betz not be
  891. X* used in advertising or publicity pertaining to distribution of the software
  892. X* without specific, written prior permission.  Hewlett-Packard and David Betz
  893. X* make no representations about the suitability of this software for any
  894. X* purpose. It is provided "as is" without express or implied warranty.
  895. X*
  896. X* HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  897. X* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  898. X* IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  899. X* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  900. X* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  901. X* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  902. X* PERFORMANCE OF THIS SOFTWARE.
  903. X*
  904. X* See ./winterp/COPYRIGHT for information on contacting the authors.
  905. X* 
  906. X* Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  907. X* Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  908. X*
  909. X********************************************************************************
  910. X*/
  911. Xstatic char rcs_identity[] = "@(#)$Header: xlbfun.c,v 1.2 89/11/25 05:13:34 mayer Exp $";
  912. X
  913. X#include "xlisp.h"
  914. X
  915. X/* external variables */
  916. Xextern LVAL xlenv,xlfenv,xldenv,true;
  917. Xextern LVAL s_evalhook,s_applyhook;
  918. Xextern LVAL s_car,s_cdr,s_nth,s_get,s_svalue,s_splist,s_aref;
  919. Xextern LVAL s_lambda,s_macro;
  920. Xextern LVAL s_comma,s_comat;
  921. Xextern LVAL s_unbound;
  922. Xextern char gsprefix[];
  923. Xextern int gsnumber;
  924. X
  925. X/* external routines */
  926. Xextern LVAL xlxeval();
  927. X
  928. X/* forward declarations */
  929. XFORWARD LVAL bquote1();
  930. XFORWARD LVAL defun();
  931. XFORWARD LVAL makesymbol();
  932. X
  933. X/* xeval - the built-in function 'eval' */
  934. XLVAL xeval()
  935. X{
  936. X    LVAL expr;
  937. X
  938. X    /* get the expression to evaluate */
  939. X    expr = xlgetarg();
  940. X    xllastarg();
  941. X
  942. X    /* evaluate the expression */
  943. X    return (xleval(expr));
  944. X}
  945. X
  946. X/* xapply - the built-in function 'apply' */
  947. XLVAL xapply()
  948. X{
  949. X    LVAL fun,arglist;
  950. X
  951. X    /* get the function and argument list */
  952. X    fun = xlgetarg();
  953. X    arglist = xlgalist();
  954. X    xllastarg();
  955. X
  956. X    /* apply the function to the arguments */
  957. X    return (xlapply(pushargs(fun,arglist)));
  958. X}
  959. X
  960. X/* xfuncall - the built-in function 'funcall' */
  961. XLVAL xfuncall()
  962. X{
  963. X    LVAL *newfp;
  964. X    int argc;
  965. X    
  966. X    /* build a new argument stack frame */
  967. X    newfp = xlsp;
  968. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  969. X    pusharg(xlgetarg());
  970. X    pusharg(NIL); /* will be argc */
  971. X
  972. X    /* push each argument */
  973. X    for (argc = 0; moreargs(); ++argc)
  974. X    pusharg(nextarg());
  975. X
  976. X    /* establish the new stack frame */
  977. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  978. X    xlfp = newfp;
  979. X
  980. X    /* apply the function to the arguments */
  981. X    return (xlapply(argc));
  982. X}
  983. X
  984. X/* xmacroexpand - expand a macro call repeatedly */
  985. XLVAL xmacroexpand()
  986. X{
  987. X    LVAL form;
  988. X    form = xlgetarg();
  989. X    xllastarg();
  990. X    return (xlexpandmacros(form));
  991. X}
  992. X
  993. X/* x1macroexpand - expand a macro call */
  994. XLVAL x1macroexpand()
  995. X{
  996. X    LVAL form,fun,args;
  997. X
  998. X    /* protect some pointers */
  999. X    xlstkcheck(2);
  1000. X    xlsave(fun);
  1001. X    xlsave(args);
  1002. X
  1003. X    /* get the form */
  1004. X    form = xlgetarg();
  1005. X    xllastarg();
  1006. X
  1007. X    /* expand until the form isn't a macro call */
  1008. X    if (consp(form)) {
  1009. X    fun = car(form);        /* get the macro name */
  1010. X    args = cdr(form);        /* get the arguments */
  1011. X    if (symbolp(fun) && fboundp(fun)) {
  1012. X        fun = xlgetfunction(fun);    /* get the expansion function */
  1013. X        macroexpand(fun,args,&form);
  1014. X    }
  1015. X    }
  1016. X
  1017. X    /* restore the stack and return the expansion */
  1018. X    xlpopn(2);
  1019. X    return (form);
  1020. X}
  1021. X
  1022. X/* xatom - is this an atom? */
  1023. XLVAL xatom()
  1024. X{
  1025. X    LVAL arg;
  1026. X    arg = xlgetarg();
  1027. X    xllastarg();
  1028. X    return (atom(arg) ? true : NIL);
  1029. X}
  1030. X
  1031. X/* xsymbolp - is this an symbol? */
  1032. XLVAL xsymbolp()
  1033. X{
  1034. X    LVAL arg;
  1035. X    arg = xlgetarg();
  1036. X    xllastarg();
  1037. X    return (arg == NIL || symbolp(arg) ? true : NIL);
  1038. X}
  1039. X
  1040. X/* xnumberp - is this a number? */
  1041. XLVAL xnumberp()
  1042. X{
  1043. X    LVAL arg;
  1044. X    arg = xlgetarg();
  1045. X    xllastarg();
  1046. X    return (fixp(arg) || floatp(arg) ? true : NIL);
  1047. X}
  1048. X
  1049. X/* xintegerp - is this an integer? */
  1050. XLVAL xintegerp()
  1051. X{
  1052. X    LVAL arg;
  1053. X    arg = xlgetarg();
  1054. X    xllastarg();
  1055. X    return (fixp(arg) ? true : NIL);
  1056. X}
  1057. X
  1058. X/* xfloatp - is this a float? */
  1059. XLVAL xfloatp()
  1060. X{
  1061. X    LVAL arg;
  1062. X    arg = xlgetarg();
  1063. X    xllastarg();
  1064. X    return (floatp(arg) ? true : NIL);
  1065. X}
  1066. X
  1067. X/* xcharp - is this a character? */
  1068. XLVAL xcharp()
  1069. X{
  1070. X    LVAL arg;
  1071. X    arg = xlgetarg();
  1072. X    xllastarg();
  1073. X    return (charp(arg) ? true : NIL);
  1074. X}
  1075. X
  1076. X/* xstringp - is this a string? */
  1077. XLVAL xstringp()
  1078. X{
  1079. X    LVAL arg;
  1080. X    arg = xlgetarg();
  1081. X    xllastarg();
  1082. X    return (stringp(arg) ? true : NIL);
  1083. X}
  1084. X
  1085. X/* xarrayp - is this an array? */
  1086. XLVAL xarrayp()
  1087. X{
  1088. X    LVAL arg;
  1089. X    arg = xlgetarg();
  1090. X    xllastarg();
  1091. X    return (vectorp(arg) ? true : NIL);
  1092. X}
  1093. X
  1094. X/* xstreamp - is this a stream? */
  1095. XLVAL xstreamp()
  1096. X{
  1097. X    LVAL arg;
  1098. X    arg = xlgetarg();
  1099. X    xllastarg();
  1100. X    return (streamp(arg) || ustreamp(arg) ? true : NIL);
  1101. X}
  1102. X
  1103. X/* xobjectp - is this an object? */
  1104. XLVAL xobjectp()
  1105. X{
  1106. X    LVAL arg;
  1107. X    arg = xlgetarg();
  1108. X    xllastarg();
  1109. X    return (objectp(arg) ? true : NIL);
  1110. X}
  1111. X
  1112. X/* xboundp - is there a value bound to this symbol? */
  1113. XLVAL xboundp()
  1114. X{
  1115. X    LVAL sym;
  1116. X    sym = xlgasymbol();
  1117. X    xllastarg();
  1118. X    return (boundp(sym) ? true : NIL);
  1119. X}
  1120. X
  1121. X/* xfboundp - is there a functional value bound to this symbol? */
  1122. XLVAL xfboundp()
  1123. X{
  1124. X    LVAL sym;
  1125. X    sym = xlgasymbol();
  1126. X    xllastarg();
  1127. X    return (fboundp(sym) ? true : NIL);
  1128. X}
  1129. X
  1130. X/* xnull - is this null? */
  1131. XLVAL xnull()
  1132. X{
  1133. X    LVAL arg;
  1134. X    arg = xlgetarg();
  1135. X    xllastarg();
  1136. X    return (null(arg) ? true : NIL);
  1137. X}
  1138. X
  1139. X/* xlistp - is this a list? */
  1140. XLVAL xlistp()
  1141. X{
  1142. X    LVAL arg;
  1143. X    arg = xlgetarg();
  1144. X    xllastarg();
  1145. X    return (listp(arg) ? true : NIL);
  1146. X}
  1147. X
  1148. X/* xendp - is this the end of a list? */
  1149. XLVAL xendp()
  1150. X{
  1151. X    LVAL arg;
  1152. X    arg = xlgalist();
  1153. X    xllastarg();
  1154. X    return (null(arg) ? true : NIL);
  1155. X}
  1156. X
  1157. X/* xconsp - is this a cons? */
  1158. XLVAL xconsp()
  1159. X{
  1160. X    LVAL arg;
  1161. X    arg = xlgetarg();
  1162. X    xllastarg();
  1163. X    return (consp(arg) ? true : NIL);
  1164. X}
  1165. X
  1166. X/* xeq - are these equal? */
  1167. XLVAL xeq()
  1168. X{
  1169. X    LVAL arg1,arg2;
  1170. X
  1171. X    /* get the two arguments */
  1172. X    arg1 = xlgetarg();
  1173. X    arg2 = xlgetarg();
  1174. X    xllastarg();
  1175. X
  1176. X    /* compare the arguments */
  1177. X    return (arg1 == arg2 ? true : NIL);
  1178. X}
  1179. X
  1180. X/* xeql - are these equal? */
  1181. XLVAL xeql()
  1182. X{
  1183. X    LVAL arg1,arg2;
  1184. X
  1185. X    /* get the two arguments */
  1186. X    arg1 = xlgetarg();
  1187. X    arg2 = xlgetarg();
  1188. X    xllastarg();
  1189. X
  1190. X    /* compare the arguments */
  1191. X    return (eql(arg1,arg2) ? true : NIL);
  1192. X}
  1193. X
  1194. X/* xequal - are these equal? (recursive) */
  1195. XLVAL xequal()
  1196. X{
  1197. X    LVAL arg1,arg2;
  1198. X
  1199. X    /* get the two arguments */
  1200. X    arg1 = xlgetarg();
  1201. X    arg2 = xlgetarg();
  1202. X    xllastarg();
  1203. X
  1204. X    /* compare the arguments */
  1205. X    return (equal(arg1,arg2) ? true : NIL);
  1206. X}
  1207. X
  1208. X/* xset - built-in function set */
  1209. XLVAL xset()
  1210. X{
  1211. X    LVAL sym,val;
  1212. X
  1213. X    /* get the symbol and new value */
  1214. X    sym = xlgasymbol();
  1215. X    val = xlgetarg();
  1216. X    xllastarg();
  1217. X
  1218. X    /* assign the symbol the value of argument 2 */
  1219. X    setvalue(sym,val);
  1220. X
  1221. X    /* return the result value */
  1222. X    return (val);
  1223. X}
  1224. X
  1225. X/* xgensym - generate a symbol */
  1226. XLVAL xgensym()
  1227. X{
  1228. X    char sym[STRMAX+11]; /* enough space for prefix and number */
  1229. X    LVAL x;
  1230. X
  1231. X    /* get the prefix or number */
  1232. X    if (moreargs()) {
  1233. X    x = xlgetarg();
  1234. X    switch (null(x) ? CONS : ntype(x)) {
  1235. X    case SYMBOL:
  1236. X        x = getpname(x);
  1237. X                /*** FALL INTO STRING ***/
  1238. X    case STRING:
  1239. X        strncpy(gsprefix,getstring(x),STRMAX);
  1240. X        gsprefix[STRMAX] = '\0';
  1241. X        break;
  1242. X    case FIXNUM:
  1243. X        gsnumber = getfixnum(x);
  1244. X        break;
  1245. X    default:
  1246. X        xlerror("bad argument type",x);
  1247. X    }
  1248. X    }
  1249. X    xllastarg();
  1250. X
  1251. X    /* create the pname of the new symbol */
  1252. X    sprintf(sym,"%s%d",gsprefix,gsnumber++);
  1253. X
  1254. X    /* make a symbol with this print name */
  1255. X    return (xlmakesym(sym));
  1256. X}
  1257. X
  1258. X/* xmakesymbol - make a new uninterned symbol */
  1259. XLVAL xmakesymbol()
  1260. X{
  1261. X    LVAL pname;
  1262. X
  1263. X    /* get the print name of the symbol */
  1264. X    pname = xlgastring();
  1265. X    xllastarg();
  1266. X
  1267. X    /* make the symbol */
  1268. X    return xlmakesym(getstring(pname));
  1269. X}
  1270. X
  1271. X/* xintern - make a new interned symbol */
  1272. XLVAL xintern()
  1273. X{
  1274. X    LVAL pname;
  1275. X
  1276. X    /* get the print name of the symbol to intern */
  1277. X    pname = xlgastring();
  1278. X    xllastarg();
  1279. X
  1280. X    /* make the symbol */
  1281. X    return xlenter(getstring(pname));
  1282. X}
  1283. X
  1284. X/* xsymname - get the print name of a symbol */
  1285. XLVAL xsymname()
  1286. X{
  1287. X    LVAL sym;
  1288. X
  1289. X    /* get the symbol */
  1290. X    sym = xlgasymbol();
  1291. X    xllastarg();
  1292. X
  1293. X    /* return the print name */
  1294. X    return (getpname(sym));
  1295. X}
  1296. X
  1297. X/* xsymvalue - get the value of a symbol */
  1298. XLVAL xsymvalue()
  1299. X{
  1300. X    LVAL sym,val;
  1301. X
  1302. X    /* get the symbol */
  1303. X    sym = xlgasymbol();
  1304. X    xllastarg();
  1305. X
  1306. X    /* get the global value */
  1307. X    while ((val = getvalue(sym)) == s_unbound)
  1308. X    xlunbound(sym);
  1309. X
  1310. X    /* return its value */
  1311. X    return (val);
  1312. X}
  1313. X
  1314. X/* xsymfunction - get the functional value of a symbol */
  1315. XLVAL xsymfunction()
  1316. X{
  1317. X    LVAL sym,val;
  1318. X
  1319. X    /* get the symbol */
  1320. X    sym = xlgasymbol();
  1321. X    xllastarg();
  1322. X
  1323. X    /* get the global value */
  1324. X    while ((val = getfunction(sym)) == s_unbound)
  1325. X    xlfunbound(sym);
  1326. X
  1327. X    /* return its value */
  1328. X    return (val);
  1329. X}
  1330. X
  1331. X/* xsymplist - get the property list of a symbol */
  1332. XLVAL xsymplist()
  1333. X{
  1334. X    LVAL sym;
  1335. X
  1336. X    /* get the symbol */
  1337. X    sym = xlgasymbol();
  1338. X    xllastarg();
  1339. X
  1340. X    /* return the property list */
  1341. X    return (getplist(sym));
  1342. X}
  1343. X
  1344. X/* xget - get the value of a property */
  1345. XLVAL xget()
  1346. X{
  1347. X    LVAL sym,prp;
  1348. X
  1349. X    /* get the symbol and property */
  1350. X    sym = xlgasymbol();
  1351. X    prp = xlgasymbol();
  1352. X    xllastarg();
  1353. X
  1354. X    /* retrieve the property value */
  1355. X    return (xlgetprop(sym,prp));
  1356. X}
  1357. X
  1358. X/* xputprop - set the value of a property */
  1359. XLVAL xputprop()
  1360. X{
  1361. X    LVAL sym,val,prp;
  1362. X
  1363. X    /* get the symbol and property */
  1364. X    sym = xlgasymbol();
  1365. X    val = xlgetarg();
  1366. X    prp = xlgasymbol();
  1367. X    xllastarg();
  1368. X
  1369. X    /* set the property value */
  1370. X    xlputprop(sym,val,prp);
  1371. X
  1372. X    /* return the value */
  1373. X    return (val);
  1374. X}
  1375. X
  1376. X/* xremprop - remove a property value from a property list */
  1377. XLVAL xremprop()
  1378. X{
  1379. X    LVAL sym,prp;
  1380. X
  1381. X    /* get the symbol and property */
  1382. X    sym = xlgasymbol();
  1383. X    prp = xlgasymbol();
  1384. X    xllastarg();
  1385. X
  1386. X    /* remove the property */
  1387. X    xlremprop(sym,prp);
  1388. X
  1389. X    /* return nil */
  1390. X    return (NIL);
  1391. X}
  1392. X
  1393. X/* xhash - compute the hash value of a string or symbol */
  1394. XLVAL xhash()
  1395. X{
  1396. X    unsigned char *str;
  1397. X    LVAL len,val;
  1398. X    int n;
  1399. X
  1400. X    /* get the string and the table length */
  1401. X    val = xlgetarg();
  1402. X    len = xlgafixnum(); n = (int)getfixnum(len);
  1403. X    xllastarg();
  1404. X
  1405. X    /* get the string */
  1406. X    if (symbolp(val))
  1407. X    str = getstring(getpname(val));
  1408. X    else if (stringp(val))
  1409. X    str = getstring(val);
  1410. X    else
  1411. X    xlerror("bad argument type",val);
  1412. X
  1413. X    /* return the hash index */
  1414. X    return (cvfixnum((FIXTYPE)hash(str,n)));
  1415. X}
  1416. X
  1417. X/* xaref - array reference function */
  1418. XLVAL xaref()
  1419. X{
  1420. X    LVAL array,index;
  1421. X    int i;
  1422. X
  1423. X    /* get the array and the index */
  1424. X    array = xlgavector();
  1425. X    index = xlgafixnum(); i = (int)getfixnum(index);
  1426. X    xllastarg();
  1427. X
  1428. X    /* range check the index */
  1429. X    if (i < 0 || i >= getsz(array))
  1430. X    xlerror("array index out of bounds",index);
  1431. X
  1432. X    /* return the array element */
  1433. X    return (getelement(array,i));
  1434. X}
  1435. X
  1436. X/* xmkarray - make a new array */
  1437. XLVAL xmkarray()
  1438. X{
  1439. X    LVAL size;
  1440. X    int n;
  1441. X
  1442. X    /* get the size of the array */
  1443. X    size = xlgafixnum() ; n = (int)getfixnum(size);
  1444. X    xllastarg();
  1445. X
  1446. X    /* create the array */
  1447. X    return (newvector(n));
  1448. X}
  1449. X
  1450. X/* xvector - make a vector */
  1451. XLVAL xvector()
  1452. X{
  1453. X    LVAL val;
  1454. X    int i;
  1455. X
  1456. X    /* make the vector */
  1457. X    val = newvector(xlargc);
  1458. X
  1459. X    /* store each argument */
  1460. X    for (i = 0; moreargs(); ++i)
  1461. X    setelement(val,i,nextarg());
  1462. X    xllastarg();
  1463. X
  1464. X    /* return the vector */
  1465. X    return (val);
  1466. X}
  1467. X
  1468. X/******************************************************************************
  1469. X * (copy-array <src> <dest> [<pos>]) --> returns <dest>
  1470. X * This function copies from array <src> into the preallocated array <dest>
  1471. X * (allocate with 'make-array'). If the optional arg <pos> is given, then
  1472. X * elements from <src> will be written into <dest> at index <pos>, otherwise
  1473. X * <pos> defaults to 0. 
  1474. X *
  1475. X * This function was added to xlisp by Niels Mayer.
  1476. X ******************************************************************************/
  1477. XLVAL Prim_COPY_ARRAY()
  1478. X{
  1479. X  register int size;
  1480. X  register LVAL *src, *dest;
  1481. X  LVAL src_array, dest_array, lval_pos;
  1482. X
  1483. X  src_array = xlgavector();    /* get <src> */
  1484. X  dest_array = xlgavector();    /* get <dest> */
  1485. X  if moreargs()
  1486. X    lval_pos = xlgafixnum();    /* get optional <pos> */
  1487. X  else
  1488. X    lval_pos = NIL;
  1489. X  xllastarg();
  1490. X
  1491. X  src = src_array->n_vdata;
  1492. X  dest = dest_array->n_vdata;
  1493. X
  1494. X  if (getsz(src_array) < getsz(dest_array))    /* which is shortest? */
  1495. X    size = getsz(src_array);
  1496. X  else
  1497. X    size = getsz(dest_array);
  1498. X
  1499. X  if (lval_pos) {
  1500. X    int pos = getfixnum(lval_pos);
  1501. X    int len = getsz(dest_array) - pos;
  1502. X    if ((len <= 0) || (pos < 0))
  1503. X      xlerror("Array position out of bounds.", lval_pos);    
  1504. X    if (len < size)
  1505. X      size = len;
  1506. X    dest = dest + pos;
  1507. X  }
  1508. X
  1509. X  while (size--)
  1510. X    *dest++ = *src++;
  1511. X
  1512. X  return (dest_array);
  1513. X}
  1514. X
  1515. X/******************************************************************************
  1516. X * (array-insert-pos <array> <pos> <elt>) --> returns the new <array>
  1517. X * inserts <elt> at index <pos> in <array>. if <pos> < 0, then <elt> is
  1518. X * appended to the end of <array>.
  1519. X *
  1520. X * This function was added to xlisp by Niels Mayer.
  1521. X ******************************************************************************/
  1522. XLVAL Prim_ARRAY_INSERT_POS()
  1523. X{
  1524. X  register int i;
  1525. X  register LVAL *src, *dest;
  1526. X  LVAL src_array, dest_array, elt, lval_position;
  1527. X  int src_size, position;
  1528. X
  1529. X  src_array = xlgavector();    /* get <array> */
  1530. X  lval_position = xlgafixnum();    /* get <pos>, a fixnum */
  1531. X  elt = nextarg();        /* get <elt>, which can be any lisp type */
  1532. X  xllastarg();
  1533. X
  1534. X  src_size = getsz(src_array);
  1535. X  position = getfixnum(lval_position);
  1536. X  if (position >= src_size)
  1537. X    xlerror("Array insertion position out of bounds.", lval_position);
  1538. X  dest_array = newvector(src_size + 1);
  1539. X
  1540. X  src = src_array->n_vdata;
  1541. X  dest = dest_array->n_vdata;
  1542. X
  1543. X  if (position < 0) {        /* append <elt> to end of array */
  1544. X    i = src_size;
  1545. X    while (i--)
  1546. X      *dest++ = *src++;
  1547. X    *dest = elt;
  1548. X  }
  1549. X  else {            /* insert <elt> at <position> */
  1550. X    i = position;
  1551. X    while (i--)
  1552. X      *dest++ = *src++;
  1553. X    *dest++ = elt;
  1554. X    i = src_size - position;
  1555. X    while (i--)
  1556. X      *dest++ = *src++;
  1557. X  }
  1558. X  return (dest_array);
  1559. X}
  1560. X
  1561. X/******************************************************************************
  1562. X * (array-delete-pos <array> <pos>) --> returns the new <array>
  1563. X * deletes the element at index <pos> in <array>. If <pos>==-1, then it
  1564. X * will delete the last element in the array. 
  1565. X * Note that this function is destructive. It reuses the old <array>'s
  1566. X * elements.
  1567. X *
  1568. X * This function was added to xlisp by Niels Mayer.
  1569. X ******************************************************************************/
  1570. XLVAL Prim_ARRAY_DELETE_POS()
  1571. X{
  1572. X  register int i;
  1573. X  register LVAL *src, *dest;
  1574. X  LVAL src_array, dest_array, lval_position;
  1575. X  int src_size, position;
  1576. X
  1577. X  src_array = xlgavector();    /* get <array> */
  1578. X  lval_position = xlgafixnum();    /* get <pos>, a fixnum */
  1579. X  xllastarg();
  1580. X
  1581. X  src_size = getsz(src_array);
  1582. X  position = getfixnum(lval_position);
  1583. X  if (position >= src_size)
  1584. X    xlerror("Array insertion position out of bounds.", lval_position);
  1585. X  if ((src_size - 1) > 0)
  1586. X    dest_array = newvector(src_size - 1);
  1587. X  else
  1588. X    return (NIL);
  1589. X
  1590. X  src = src_array->n_vdata;
  1591. X  dest = dest_array->n_vdata;
  1592. X
  1593. X  if (position < 0) {        /* remove last element of array */
  1594. X    i = src_size - 1;
  1595. X    while (i--)
  1596. X      *dest++ = *src++;
  1597. X  }
  1598. X  else {            /* remove <elt> at <position> */
  1599. X    i = position;
  1600. X    while (i--)
  1601. X      *dest++ = *src++;
  1602. X    src++;            /* don't copy the deleted elt */
  1603. X    i = src_size - (position + 1);
  1604. X    while (i--)
  1605. X      *dest++ = *src++;
  1606. X  }
  1607. X  return (dest_array);
  1608. X}
  1609. X
  1610. X/* xerror - special form 'error' */
  1611. XLVAL xerror()
  1612. X{
  1613. X    LVAL emsg,arg;
  1614. X
  1615. X    /* get the error message and the argument */
  1616. X    emsg = xlgastring();
  1617. X    arg = (moreargs() ? xlgetarg() : s_unbound);
  1618. X    xllastarg();
  1619. X
  1620. X    /* signal the error */
  1621. X    xlerror(getstring(emsg),arg);
  1622. X}
  1623. X
  1624. X/* xcerror - special form 'cerror' */
  1625. XLVAL xcerror()
  1626. X{
  1627. X    LVAL cmsg,emsg,arg;
  1628. X
  1629. X    /* get the correction message, the error message, and the argument */
  1630. X    cmsg = xlgastring();
  1631. X    emsg = xlgastring();
  1632. X    arg = (moreargs() ? xlgetarg() : s_unbound);
  1633. X    xllastarg();
  1634. X
  1635. X    /* signal the error */
  1636. X    xlcerror(getstring(cmsg),getstring(emsg),arg);
  1637. X
  1638. X    /* return nil */
  1639. X    return (NIL);
  1640. X}
  1641. X
  1642. X/* xbreak - special form 'break' */
  1643. XLVAL xbreak()
  1644. X{
  1645. X    LVAL emsg,arg;
  1646. X
  1647. X    /* get the error message */
  1648. X    emsg = (moreargs() ? xlgastring() : NIL);
  1649. X    arg = (moreargs() ? xlgetarg() : s_unbound);
  1650. X    xllastarg();
  1651. X
  1652. X    /* enter the break loop */
  1653. X    xlbreak((emsg ? getstring(emsg) : (unsigned char *)"**BREAK**"),arg);
  1654. X
  1655. X    /* return nil */
  1656. X    return (NIL);
  1657. X}
  1658. X
  1659. X/* xcleanup - special form 'clean-up' */
  1660. XLVAL xcleanup()
  1661. X{
  1662. X    xllastarg();
  1663. X    xlcleanup();
  1664. X}
  1665. X
  1666. X/* xtoplevel - special form 'top-level' */
  1667. XLVAL xtoplevel()
  1668. X{
  1669. X    xllastarg();
  1670. X    xltoplevel();
  1671. X}
  1672. X
  1673. X/* xcontinue - special form 'continue' */
  1674. XLVAL xcontinue()
  1675. X{
  1676. X    xllastarg();
  1677. X    xlcontinue();
  1678. X}
  1679. X
  1680. X/* xevalhook - eval hook function */
  1681. XLVAL xevalhook()
  1682. X{
  1683. X    LVAL expr,newehook,newahook,newenv,oldenv,oldfenv,olddenv,val;
  1684. X
  1685. X    /* protect some pointers */
  1686. X    xlstkcheck(3);
  1687. X    xlsave(oldenv);
  1688. X    xlsave(oldfenv);
  1689. X    xlsave(newenv);
  1690. X
  1691. X    /* get the expression, the new hook functions and the environment */
  1692. X    expr = xlgetarg();
  1693. X    newehook = xlgetarg();
  1694. X    newahook = xlgetarg();
  1695. X    newenv = (moreargs() ? xlgalist() : NIL);
  1696. X    xllastarg();
  1697. X
  1698. X    /* bind *evalhook* and *applyhook* to the hook functions */
  1699. X    olddenv = xldenv;
  1700. X    xldbind(s_evalhook,newehook);
  1701. X    xldbind(s_applyhook,newahook);
  1702. X
  1703. X    /* establish the environment for the hook function */
  1704. X    if (newenv) {
  1705. X    oldenv = xlenv;
  1706. X    oldfenv = xlfenv;
  1707. X    xlenv = car(newenv);
  1708. X    xlfenv = cdr(newenv);
  1709. X    }
  1710. X
  1711. X    /* evaluate the expression (bypassing *evalhook*) */
  1712. X    val = xlxeval(expr);
  1713. X
  1714. X    /* restore the old environment */
  1715. X    xlunbind(olddenv);
  1716. X    if (newenv) {
  1717. X    xlenv = oldenv;
  1718. X    xlfenv = oldfenv;
  1719. X    }
  1720. X
  1721. X    /* restore the stack */
  1722. X    xlpopn(3);
  1723. X
  1724. X    /* return the result */
  1725. X    return (val);
  1726. X}
  1727. X
  1728. END_OF_FILE
  1729. if test 19033 -ne `wc -c <'src/xlisp/xcore/c/xlbfun.c'`; then
  1730.     echo shar: \"'src/xlisp/xcore/c/xlbfun.c'\" unpacked with wrong size!
  1731. fi
  1732. # end of 'src/xlisp/xcore/c/xlbfun.c'
  1733. fi
  1734. if test -f 'src/xlisp/xcore/c/xllist.c' -a "${1}" != "-c" ; then 
  1735.   echo shar: Will not clobber existing file \"'src/xlisp/xcore/c/xllist.c'\"
  1736. else
  1737. echo shar: Extracting \"'src/xlisp/xcore/c/xllist.c'\" \(20721 characters\)
  1738. sed "s/^X//" >'src/xlisp/xcore/c/xllist.c' <<'END_OF_FILE'
  1739. X/* -*-C-*-
  1740. X********************************************************************************
  1741. X*
  1742. X* File:         xllist.c
  1743. X* RCS:          $Header: xllist.c,v 1.2 89/11/25 05:39:25 mayer Exp $
  1744. X* Description:  xlisp built-in list functions
  1745. X* Author:       David Michael Betz
  1746. X* Created:      
  1747. X* Modified:     Sat Nov 25 05:39:18 1989 (Niels Mayer) mayer@hplnpm
  1748. X* Language:     C
  1749. X* Package:      N/A
  1750. X* Status:       X11r4 contrib tape release
  1751. X*
  1752. X* WINTERP 1.0 Copyright 1989 Hewlett-Packard Company (by Niels Mayer).
  1753. X* XLISP version 2.1, Copyright (c) 1989, by David Betz.
  1754. X*
  1755. X* Permission to use, copy, modify, distribute, and sell this software and its
  1756. X* documentation for any purpose is hereby granted without fee, provided that
  1757. X* the above copyright notice appear in all copies and that both that
  1758. X* copyright notice and this permission notice appear in supporting
  1759. X* documentation, and that the name of Hewlett-Packard and David Betz not be
  1760. X* used in advertising or publicity pertaining to distribution of the software
  1761. X* without specific, written prior permission.  Hewlett-Packard and David Betz
  1762. X* make no representations about the suitability of this software for any
  1763. X* purpose. It is provided "as is" without express or implied warranty.
  1764. X*
  1765. X* HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  1766. X* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  1767. X* IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  1768. X* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  1769. X* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1770. X* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  1771. X* PERFORMANCE OF THIS SOFTWARE.
  1772. X*
  1773. X* See ./winterp/COPYRIGHT for information on contacting the authors.
  1774. X* 
  1775. X* Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  1776. X* Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  1777. X*
  1778. X********************************************************************************
  1779. X*/
  1780. Xstatic char rcs_identity[] = "@(#)$Header: xllist.c,v 1.2 89/11/25 05:39:25 mayer Exp $";
  1781. X
  1782. X
  1783. X#include "xlisp.h"
  1784. X
  1785. X/* forward declarations */
  1786. XFORWARD LVAL cxr();
  1787. XFORWARD LVAL nth(),assoc();
  1788. XFORWARD LVAL subst(),sublis(),map();
  1789. X
  1790. X/* xcar - take the car of a cons cell */
  1791. XLVAL xcar()
  1792. X{
  1793. X    LVAL list;
  1794. X    list = xlgalist();
  1795. X    xllastarg();
  1796. X    return (list ? car(list) : NIL);
  1797. X}
  1798. X
  1799. X/* xcdr - take the cdr of a cons cell */
  1800. XLVAL xcdr()
  1801. X{
  1802. X    LVAL list;
  1803. X    list = xlgalist();
  1804. X    xllastarg();
  1805. X    return (list ? cdr(list) : NIL);
  1806. X}
  1807. X
  1808. X/* cxxr functions */
  1809. XLVAL xcaar() { return (cxr("aa")); }
  1810. XLVAL xcadr() { return (cxr("da")); }
  1811. XLVAL xcdar() { return (cxr("ad")); }
  1812. XLVAL xcddr() { return (cxr("dd")); }
  1813. X
  1814. X/* cxxxr functions */
  1815. XLVAL xcaaar() { return (cxr("aaa")); }
  1816. XLVAL xcaadr() { return (cxr("daa")); }
  1817. XLVAL xcadar() { return (cxr("ada")); }
  1818. XLVAL xcaddr() { return (cxr("dda")); }
  1819. XLVAL xcdaar() { return (cxr("aad")); }
  1820. XLVAL xcdadr() { return (cxr("dad")); }
  1821. XLVAL xcddar() { return (cxr("add")); }
  1822. XLVAL xcdddr() { return (cxr("ddd")); }
  1823. X
  1824. X/* cxxxxr functions */
  1825. XLVAL xcaaaar() { return (cxr("aaaa")); }
  1826. XLVAL xcaaadr() { return (cxr("daaa")); }
  1827. XLVAL xcaadar() { return (cxr("adaa")); }
  1828. XLVAL xcaaddr() { return (cxr("ddaa")); }
  1829. XLVAL xcadaar() { return (cxr("aada")); }
  1830. XLVAL xcadadr() { return (cxr("dada")); }
  1831. XLVAL xcaddar() { return (cxr("adda")); }
  1832. XLVAL xcadddr() { return (cxr("ddda")); }
  1833. XLVAL xcdaaar() { return (cxr("aaad")); }
  1834. XLVAL xcdaadr() { return (cxr("daad")); }
  1835. XLVAL xcdadar() { return (cxr("adad")); }
  1836. XLVAL xcdaddr() { return (cxr("ddad")); }
  1837. XLVAL xcddaar() { return (cxr("aadd")); }
  1838. XLVAL xcddadr() { return (cxr("dadd")); }
  1839. XLVAL xcdddar() { return (cxr("addd")); }
  1840. XLVAL xcddddr() { return (cxr("dddd")); }
  1841. X
  1842. X/* cxr - common car/cdr routine */
  1843. XLOCAL LVAL cxr(adstr)
  1844. X  char *adstr;
  1845. X{
  1846. X    LVAL list;
  1847. X
  1848. X    /* get the list */
  1849. X    list = xlgalist();
  1850. X    xllastarg();
  1851. X
  1852. X    /* perform the car/cdr operations */
  1853. X    while (*adstr && consp(list))
  1854. X    list = (*adstr++ == 'a' ? car(list) : cdr(list));
  1855. X
  1856. X    /* make sure the operation succeeded */
  1857. X    if (*adstr && list)
  1858. X    xlfail("bad argument");
  1859. X
  1860. X    /* return the result */
  1861. X    return (list);
  1862. X}
  1863. X
  1864. X/* xcons - construct a new list cell */
  1865. XLVAL xcons()
  1866. X{
  1867. X    LVAL arg1,arg2;
  1868. X
  1869. X    /* get the two arguments */
  1870. X    arg1 = xlgetarg();
  1871. X    arg2 = xlgetarg();
  1872. X    xllastarg();
  1873. X
  1874. X    /* construct a new list element */
  1875. X    return (cons(arg1,arg2));
  1876. X}
  1877. X
  1878. X/* xlist - built a list of the arguments */
  1879. XLVAL xlist()
  1880. X{
  1881. X    LVAL last,next,val;
  1882. X
  1883. X    /* protect some pointers */
  1884. X    xlsave1(val);
  1885. X
  1886. X    /* add each argument to the list */
  1887. X    for (val = NIL; moreargs(); ) {
  1888. X
  1889. X    /* append this argument to the end of the list */
  1890. X    next = consa(nextarg());
  1891. X    if (val) rplacd(last,next);
  1892. X    else val = next;
  1893. X    last = next;
  1894. X    }
  1895. X
  1896. X    /* restore the stack */
  1897. X    xlpop();
  1898. X
  1899. X    /* return the list */
  1900. X    return (val);
  1901. X}
  1902. X
  1903. X/* xappend - built-in function append */
  1904. XLVAL xappend()
  1905. X{
  1906. X    LVAL list,last,next,val;
  1907. X
  1908. X    /* protect some pointers */
  1909. X    xlsave1(val);
  1910. X
  1911. X    /* initialize */
  1912. X    val = NIL;
  1913. X    
  1914. X    /* append each argument */
  1915. X    if (moreargs()) {
  1916. X    while (xlargc > 1) {
  1917. X
  1918. X        /* append each element of this list to the result list */
  1919. X        for (list = nextarg(); consp(list); list = cdr(list)) {
  1920. X        next = consa(car(list));
  1921. X        if (val) rplacd(last,next);
  1922. X        else val = next;
  1923. X        last = next;
  1924. X        }
  1925. X    }
  1926. X
  1927. X    /* handle the last argument */
  1928. X    if (val) rplacd(last,nextarg());
  1929. X    else val = nextarg();
  1930. X    }
  1931. X
  1932. X    /* restore the stack */
  1933. X    xlpop();
  1934. X
  1935. X    /* return the list */
  1936. X    return (val);
  1937. X}
  1938. X
  1939. X/* xreverse - built-in function reverse */
  1940. XLVAL xreverse()
  1941. X{
  1942. X    LVAL list,val;
  1943. X
  1944. X    /* protect some pointers */
  1945. X    xlsave1(val);
  1946. X
  1947. X    /* get the list to reverse */
  1948. X    list = xlgalist();
  1949. X    xllastarg();
  1950. X
  1951. X    /* append each element to the head of the result list */
  1952. X    for (val = NIL; consp(list); list = cdr(list))
  1953. X    val = cons(car(list),val);
  1954. X
  1955. X    /* restore the stack */
  1956. X    xlpop();
  1957. X
  1958. X    /* return the list */
  1959. X    return (val);
  1960. X}
  1961. X
  1962. X/* xlast - return the last cons of a list */
  1963. XLVAL xlast()
  1964. X{
  1965. X    LVAL list;
  1966. X
  1967. X    /* get the list */
  1968. X    list = xlgalist();
  1969. X    xllastarg();
  1970. X
  1971. X    /* find the last cons */
  1972. X    while (consp(list) && cdr(list))
  1973. X    list = cdr(list);
  1974. X
  1975. X    /* return the last element */
  1976. X    return (list);
  1977. X}
  1978. X
  1979. X/* xmember - built-in function 'member' */
  1980. XLVAL xmember()
  1981. X{
  1982. X    LVAL x,list,fcn,val;
  1983. X    int tresult;
  1984. X
  1985. X    /* protect some pointers */
  1986. X    xlsave1(fcn);
  1987. X
  1988. X    /* get the expression to look for and the list */
  1989. X    x = xlgetarg();
  1990. X    list = xlgalist();
  1991. X    xltest(&fcn,&tresult);
  1992. X
  1993. X    /* look for the expression */
  1994. X    for (val = NIL; consp(list); list = cdr(list))
  1995. X    if (dotest2(x,car(list),fcn) == tresult) {
  1996. X        val = list;
  1997. X        break;
  1998. X    }
  1999. X
  2000. X    /* restore the stack */
  2001. X    xlpop();
  2002. X
  2003. X    /* return the result */
  2004. X    return (val);
  2005. X}
  2006. X
  2007. X/* xassoc - built-in function 'assoc' */
  2008. XLVAL xassoc()
  2009. X{
  2010. X    LVAL x,alist,fcn,pair,val;
  2011. X    int tresult;
  2012. X
  2013. X    /* protect some pointers */
  2014. X    xlsave1(fcn);
  2015. X
  2016. X    /* get the expression to look for and the association list */
  2017. X    x = xlgetarg();
  2018. X    alist = xlgalist();
  2019. X    xltest(&fcn,&tresult);
  2020. X
  2021. X    /* look for the expression */
  2022. X    for (val = NIL; consp(alist); alist = cdr(alist))
  2023. X    if ((pair = car(alist)) && consp(pair))
  2024. X        if (dotest2(x,car(pair),fcn) == tresult) {
  2025. X        val = pair;
  2026. X        break;
  2027. X        }
  2028. X
  2029. X    /* restore the stack */
  2030. X    xlpop();
  2031. X
  2032. X    /* return result */
  2033. X    return (val);
  2034. X}
  2035. X
  2036. X/* xsubst - substitute one expression for another */
  2037. XLVAL xsubst()
  2038. X{
  2039. X    LVAL to,from,expr,fcn,val;
  2040. X    int tresult;
  2041. X
  2042. X    /* protect some pointers */
  2043. X    xlsave1(fcn);
  2044. X
  2045. X    /* get the to value, the from value and the expression */
  2046. X    to = xlgetarg();
  2047. X    from = xlgetarg();
  2048. X    expr = xlgetarg();
  2049. X    xltest(&fcn,&tresult);
  2050. X
  2051. X    /* do the substitution */
  2052. X    val = subst(to,from,expr,fcn,tresult);
  2053. X
  2054. X    /* restore the stack */
  2055. X    xlpop();
  2056. X
  2057. X    /* return the result */
  2058. X    return (val);
  2059. X}
  2060. X
  2061. X/* subst - substitute one expression for another */
  2062. XLOCAL LVAL subst(to,from,expr,fcn,tresult)
  2063. X  LVAL to,from,expr,fcn; int tresult;
  2064. X{
  2065. X    LVAL carval,cdrval;
  2066. X
  2067. X    if (dotest2(expr,from,fcn) == tresult)
  2068. X    return (to);
  2069. X    else if (consp(expr)) {
  2070. X    xlsave1(carval);
  2071. X    carval = subst(to,from,car(expr),fcn,tresult);
  2072. X    cdrval = subst(to,from,cdr(expr),fcn,tresult);
  2073. X    xlpop();
  2074. X    return (cons(carval,cdrval));
  2075. X    }
  2076. X    else
  2077. X    return (expr);
  2078. X}
  2079. X
  2080. X/* xsublis - substitute using an association list */
  2081. XLVAL xsublis()
  2082. X{
  2083. X    LVAL alist,expr,fcn,val;
  2084. X    int tresult;
  2085. X
  2086. X    /* protect some pointers */
  2087. X    xlsave1(fcn);
  2088. X
  2089. X    /* get the assocation list and the expression */
  2090. X    alist = xlgalist();
  2091. X    expr = xlgetarg();
  2092. X    xltest(&fcn,&tresult);
  2093. X
  2094. X    /* do the substitution */
  2095. X    val = sublis(alist,expr,fcn,tresult);
  2096. X
  2097. X    /* restore the stack */
  2098. X    xlpop();
  2099. X
  2100. X    /* return the result */
  2101. X    return (val);
  2102. X}
  2103. X
  2104. X/* sublis - substitute using an association list */
  2105. XLOCAL LVAL sublis(alist,expr,fcn,tresult)
  2106. X  LVAL alist,expr,fcn; int tresult;
  2107. X{
  2108. X    LVAL carval,cdrval,pair;
  2109. X
  2110. X    if (pair = assoc(expr,alist,fcn,tresult))
  2111. X    return (cdr(pair));
  2112. X    else if (consp(expr)) {
  2113. X    xlsave1(carval);
  2114. X    carval = sublis(alist,car(expr),fcn,tresult);
  2115. X    cdrval = sublis(alist,cdr(expr),fcn,tresult);
  2116. X    xlpop();
  2117. X    return (cons(carval,cdrval));
  2118. X    }
  2119. X    else
  2120. X    return (expr);
  2121. X}
  2122. X
  2123. X/* assoc - find a pair in an association list */
  2124. XLOCAL LVAL assoc(expr,alist,fcn,tresult)
  2125. X  LVAL expr,alist,fcn; int tresult;
  2126. X{
  2127. X    LVAL pair;
  2128. X
  2129. X    for (; consp(alist); alist = cdr(alist))
  2130. X    if ((pair = car(alist)) && consp(pair))
  2131. X        if (dotest2(expr,car(pair),fcn) == tresult)
  2132. X        return (pair);
  2133. X    return (NIL);
  2134. X}
  2135. X
  2136. X/* xremove - built-in function 'remove' */
  2137. XLVAL xremove()
  2138. X{
  2139. X    LVAL x,list,fcn,val,last,next;
  2140. X    int tresult;
  2141. X
  2142. X    /* protect some pointers */
  2143. X    xlstkcheck(2);
  2144. X    xlsave(fcn);
  2145. X    xlsave(val);
  2146. X
  2147. X    /* get the expression to remove and the list */
  2148. X    x = xlgetarg();
  2149. X    list = xlgalist();
  2150. X    xltest(&fcn,&tresult);
  2151. X
  2152. X    /* remove matches */
  2153. X    for (; consp(list); list = cdr(list))
  2154. X
  2155. X    /* check to see if this element should be deleted */
  2156. X    if (dotest2(x,car(list),fcn) != tresult) {
  2157. X        next = consa(car(list));
  2158. X        if (val) rplacd(last,next);
  2159. X        else val = next;
  2160. X        last = next;
  2161. X    }
  2162. X
  2163. X    /* restore the stack */
  2164. X    xlpopn(2);
  2165. X
  2166. X    /* return the updated list */
  2167. X    return (val);
  2168. X}
  2169. X
  2170. X/* xremif - built-in function 'remove-if' */
  2171. XLVAL xremif()
  2172. X{
  2173. X    LVAL remif();
  2174. X    return (remif(TRUE));
  2175. X}
  2176. X
  2177. X/* xremifnot - built-in function 'remove-if-not' */
  2178. XLVAL xremifnot()
  2179. X{
  2180. X    LVAL remif();
  2181. X    return (remif(FALSE));
  2182. X}
  2183. X
  2184. X/* remif - common code for 'remove-if' and 'remove-if-not' */
  2185. XLOCAL LVAL remif(tresult)
  2186. X  int tresult;
  2187. X{
  2188. X    LVAL list,fcn,val,last,next;
  2189. X
  2190. X    /* protect some pointers */
  2191. X    xlstkcheck(2);
  2192. X    xlsave(fcn);
  2193. X    xlsave(val);
  2194. X
  2195. X    /* get the expression to remove and the list */
  2196. X    fcn = xlgetarg();
  2197. X    list = xlgalist();
  2198. X    xllastarg();
  2199. X
  2200. X    /* remove matches */
  2201. X    for (; consp(list); list = cdr(list))
  2202. X
  2203. X    /* check to see if this element should be deleted */
  2204. X    if (dotest1(car(list),fcn) != tresult) {
  2205. X        next = consa(car(list));
  2206. X        if (val) rplacd(last,next);
  2207. X        else val = next;
  2208. X        last = next;
  2209. X    }
  2210. X
  2211. X    /* restore the stack */
  2212. X    xlpopn(2);
  2213. X
  2214. X    /* return the updated list */
  2215. X    return (val);
  2216. X}
  2217. X
  2218. X/* dotest1 - call a test function with one argument */
  2219. Xint dotest1(arg,fun)
  2220. X  LVAL arg,fun;
  2221. X{
  2222. X    LVAL *newfp;
  2223. X
  2224. X    /* create the new call frame */
  2225. X    newfp = xlsp;
  2226. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  2227. X    pusharg(fun);
  2228. X    pusharg(cvfixnum((FIXTYPE)1));
  2229. X    pusharg(arg);
  2230. X    xlfp = newfp;
  2231. X
  2232. X    /* return the result of applying the test function */
  2233. X    return (xlapply(1) != NIL);
  2234. X
  2235. X}
  2236. X
  2237. X/* dotest2 - call a test function with two arguments */
  2238. Xint dotest2(arg1,arg2,fun)
  2239. X  LVAL arg1,arg2,fun;
  2240. X{
  2241. X    LVAL *newfp;
  2242. X
  2243. X    /* create the new call frame */
  2244. X    newfp = xlsp;
  2245. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  2246. X    pusharg(fun);
  2247. X    pusharg(cvfixnum((FIXTYPE)2));
  2248. X    pusharg(arg1);
  2249. X    pusharg(arg2);
  2250. X    xlfp = newfp;
  2251. X
  2252. X    /* return the result of applying the test function */
  2253. X    return (xlapply(2) != NIL);
  2254. X
  2255. X}
  2256. X
  2257. X/* xnth - return the nth element of a list */
  2258. XLVAL xnth()
  2259. X{
  2260. X    return (nth(TRUE));
  2261. X}
  2262. X
  2263. X/* xnthcdr - return the nth cdr of a list */
  2264. XLVAL xnthcdr()
  2265. X{
  2266. X    return (nth(FALSE));
  2267. X}
  2268. X
  2269. X/* nth - internal nth function */
  2270. XLOCAL LVAL nth(carflag)
  2271. X  int carflag;
  2272. X{
  2273. X    LVAL list,num;
  2274. X    FIXTYPE n;
  2275. X
  2276. X    /* get n and the list */
  2277. X    num = xlgafixnum();
  2278. X    list = xlgacons();
  2279. X    xllastarg();
  2280. X
  2281. X    /* make sure the number isn't negative */
  2282. X    if ((n = getfixnum(num)) < 0)
  2283. X    xlfail("bad argument");
  2284. X
  2285. X    /* find the nth element */
  2286. X    while (consp(list) && --n >= 0)
  2287. X    list = cdr(list);
  2288. X
  2289. X    /* return the list beginning at the nth element */
  2290. X    return (carflag && consp(list) ? car(list) : list);
  2291. X}
  2292. X
  2293. X/* xlength - return the length of a list or string */
  2294. XLVAL xlength()
  2295. X{
  2296. X    FIXTYPE n;
  2297. X    LVAL arg;
  2298. X
  2299. X    /* get the list or string */
  2300. X    arg = xlgetarg();
  2301. X    xllastarg();
  2302. X
  2303. X    /* find the length of a list */
  2304. X    if (listp(arg))
  2305. X    for (n = 0; consp(arg); n++)
  2306. X        arg = cdr(arg);
  2307. X
  2308. X    /* find the length of a string */
  2309. X    else if (stringp(arg))
  2310. X    n = (FIXTYPE)getslength(arg)-1;
  2311. X
  2312. X    /* find the length of a vector */
  2313. X    else if (vectorp(arg))
  2314. X    n = (FIXTYPE)getsz(arg);
  2315. X
  2316. X    /* otherwise, bad argument type */
  2317. X    else
  2318. X    xlerror("bad argument type",arg);
  2319. X
  2320. X    /* return the length */
  2321. X    return (cvfixnum(n));
  2322. X}
  2323. X
  2324. X/* xmapc - built-in function 'mapc' */
  2325. XLVAL xmapc()
  2326. X{
  2327. X    return (map(TRUE,FALSE));
  2328. X}
  2329. X
  2330. X/* xmapcar - built-in function 'mapcar' */
  2331. XLVAL xmapcar()
  2332. X{
  2333. X    return (map(TRUE,TRUE));
  2334. X}
  2335. X
  2336. X/* xmapl - built-in function 'mapl' */
  2337. XLVAL xmapl()
  2338. X{
  2339. X    return (map(FALSE,FALSE));
  2340. X}
  2341. X
  2342. X/* xmaplist - built-in function 'maplist' */
  2343. XLVAL xmaplist()
  2344. X{
  2345. X    return (map(FALSE,TRUE));
  2346. X}
  2347. X
  2348. X/* map - internal mapping function */
  2349. XLOCAL LVAL map(carflag,valflag)
  2350. X  int carflag,valflag;
  2351. X{
  2352. X    LVAL *newfp,fun,lists,val,last,p,x,y;
  2353. X    int argc;
  2354. X
  2355. X    /* protect some pointers */
  2356. X    xlstkcheck(3);
  2357. X    xlsave(fun);
  2358. X    xlsave(lists);
  2359. X    xlsave(val);
  2360. X
  2361. X    /* get the function to apply and the first list */
  2362. X    fun = xlgetarg();
  2363. X    lists = xlgalist();
  2364. X
  2365. X    /* initialize the result list */
  2366. X    val = (valflag ? NIL : lists);
  2367. X
  2368. X    /* build a list of argument lists */
  2369. X    for (lists = last = consa(lists); moreargs(); last = cdr(last))
  2370. X    rplacd(last,cons(xlgalist(),NIL));
  2371. X
  2372. X    /* loop through each of the argument lists */
  2373. X    for (;;) {
  2374. X
  2375. X    /* build an argument list from the sublists */
  2376. X    newfp = xlsp;
  2377. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  2378. X    pusharg(fun);
  2379. X    pusharg(NIL);
  2380. X    argc = 0;
  2381. X    for (x = lists; x && (y = car(x)) && consp(y); x = cdr(x)) {
  2382. X        pusharg(carflag ? car(y) : y);
  2383. X        rplaca(x,cdr(y));
  2384. X        ++argc;
  2385. X    }
  2386. X
  2387. X    /* quit if any of the lists were empty */
  2388. X    if (x) {
  2389. X        xlsp = newfp;
  2390. X        break;
  2391. X    }
  2392. X
  2393. X    /* apply the function to the arguments */
  2394. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  2395. X    xlfp = newfp;
  2396. X    if (valflag) {
  2397. X        p = consa(xlapply(argc));
  2398. X        if (val) rplacd(last,p);
  2399. X        else val = p;
  2400. X        last = p;
  2401. X    }
  2402. X    else
  2403. X        xlapply(argc);
  2404. X    }
  2405. X
  2406. X    /* restore the stack */
  2407. X    xlpopn(3);
  2408. X
  2409. X    /* return the last test expression value */
  2410. X    return (val);
  2411. X}
  2412. X
  2413. X/* xrplca - replace the car of a list node */
  2414. XLVAL xrplca()
  2415. X{
  2416. X    LVAL list,newcar;
  2417. X
  2418. X    /* get the list and the new car */
  2419. X    list = xlgacons();
  2420. X    newcar = xlgetarg();
  2421. X    xllastarg();
  2422. X
  2423. X    /* replace the car */
  2424. X    rplaca(list,newcar);
  2425. X
  2426. X    /* return the list node that was modified */
  2427. X    return (list);
  2428. X}
  2429. X
  2430. X/* xrplcd - replace the cdr of a list node */
  2431. XLVAL xrplcd()
  2432. X{
  2433. X    LVAL list,newcdr;
  2434. X
  2435. X    /* get the list and the new cdr */
  2436. X    list = xlgacons();
  2437. X    newcdr = xlgetarg();
  2438. X    xllastarg();
  2439. X
  2440. X    /* replace the cdr */
  2441. X    rplacd(list,newcdr);
  2442. X
  2443. X    /* return the list node that was modified */
  2444. X    return (list);
  2445. X}
  2446. X
  2447. X/* xnconc - destructively append lists */
  2448. XLVAL xnconc()
  2449. X{
  2450. X    LVAL next,last,val;
  2451. X
  2452. X    /* initialize */
  2453. X    val = NIL;
  2454. X    
  2455. X    /* concatenate each argument */
  2456. X    if (moreargs()) {
  2457. X    while (xlargc > 1) {
  2458. X
  2459. X        /* ignore everything except lists */
  2460. X        if ((next = nextarg()) && consp(next)) {
  2461. X
  2462. X        /* concatenate this list to the result list */
  2463. X        if (val) rplacd(last,next);
  2464. X        else val = next;
  2465. X
  2466. X        /* find the end of the list */
  2467. X        while (consp(cdr(next)))
  2468. X            next = cdr(next);
  2469. X        last = next;
  2470. X        }
  2471. X    }
  2472. X
  2473. X    /* handle the last argument */
  2474. X    if (val) rplacd(last,nextarg());
  2475. X    else val = nextarg();
  2476. X    }
  2477. X
  2478. X    /* return the list */
  2479. X    return (val);
  2480. X}
  2481. X
  2482. X/* xdelete - built-in function 'delete' */
  2483. XLVAL xdelete()
  2484. X{
  2485. X    LVAL x,list,fcn,last,val;
  2486. X    int tresult;
  2487. X
  2488. X    /* protect some pointers */
  2489. X    xlsave1(fcn);
  2490. X
  2491. X    /* get the expression to delete and the list */
  2492. X    x = xlgetarg();
  2493. X    list = xlgalist();
  2494. X    xltest(&fcn,&tresult);
  2495. X
  2496. X    /* delete leading matches */
  2497. X    while (consp(list)) {
  2498. X    if (dotest2(x,car(list),fcn) != tresult)
  2499. X        break;
  2500. X    list = cdr(list);
  2501. X    }
  2502. X    val = last = list;
  2503. X
  2504. X    /* delete embedded matches */
  2505. X    if (consp(list)) {
  2506. X
  2507. X    /* skip the first non-matching element */
  2508. X    list = cdr(list);
  2509. X
  2510. X    /* look for embedded matches */
  2511. X    while (consp(list)) {
  2512. X
  2513. X        /* check to see if this element should be deleted */
  2514. X        if (dotest2(x,car(list),fcn) == tresult)
  2515. X        rplacd(last,cdr(list));
  2516. X        else
  2517. X        last = list;
  2518. X
  2519. X        /* move to the next element */
  2520. X        list = cdr(list);
  2521. X     }
  2522. X    }
  2523. X
  2524. X    /* restore the stack */
  2525. X    xlpop();
  2526. X
  2527. X    /* return the updated list */
  2528. X    return (val);
  2529. X}
  2530. X
  2531. X/* xdelif - built-in function 'delete-if' */
  2532. XLVAL xdelif()
  2533. X{
  2534. X    LVAL delif();
  2535. X    return (delif(TRUE));
  2536. X}
  2537. X
  2538. X/* xdelifnot - built-in function 'delete-if-not' */
  2539. XLVAL xdelifnot()
  2540. X{
  2541. X    LVAL delif();
  2542. X    return (delif(FALSE));
  2543. X}
  2544. X
  2545. X/* delif - common routine for 'delete-if' and 'delete-if-not' */
  2546. XLOCAL LVAL delif(tresult)
  2547. X  int tresult;
  2548. X{
  2549. X    LVAL list,fcn,last,val;
  2550. X
  2551. X    /* protect some pointers */
  2552. X    xlsave1(fcn);
  2553. X
  2554. X    /* get the expression to delete and the list */
  2555. X    fcn = xlgetarg();
  2556. X    list = xlgalist();
  2557. X    xllastarg();
  2558. X
  2559. X    /* delete leading matches */
  2560. X    while (consp(list)) {
  2561. X    if (dotest1(car(list),fcn) != tresult)
  2562. X        break;
  2563. X    list = cdr(list);
  2564. X    }
  2565. X    val = last = list;
  2566. X
  2567. X    /* delete embedded matches */
  2568. X    if (consp(list)) {
  2569. X
  2570. X    /* skip the first non-matching element */
  2571. X    list = cdr(list);
  2572. X
  2573. X    /* look for embedded matches */
  2574. X    while (consp(list)) {
  2575. X
  2576. X        /* check to see if this element should be deleted */
  2577. X        if (dotest1(car(list),fcn) == tresult)
  2578. X        rplacd(last,cdr(list));
  2579. X        else
  2580. X        last = list;
  2581. X
  2582. X        /* move to the next element */
  2583. X        list = cdr(list);
  2584. X     }
  2585. X    }
  2586. X
  2587. X    /* restore the stack */
  2588. X    xlpop();
  2589. X
  2590. X    /* return the updated list */
  2591. X    return (val);
  2592. X}
  2593. X
  2594. X/* xsort - built-in function 'sort' */
  2595. XLVAL xsort()
  2596. X{
  2597. X    LVAL sortlist();
  2598. X    LVAL list,fcn;
  2599. X
  2600. X    /* protect some pointers */
  2601. X    xlstkcheck(2);
  2602. X    xlsave(list);
  2603. X    xlsave(fcn);
  2604. X
  2605. X    /* get the list to sort and the comparison function */
  2606. X    list = xlgalist();
  2607. X    fcn = xlgetarg();
  2608. X    xllastarg();
  2609. X
  2610. X    /* sort the list */
  2611. X    list = sortlist(list,fcn);
  2612. X
  2613. X    /* restore the stack and return the sorted list */
  2614. X    xlpopn(2);
  2615. X    return (list);
  2616. X}
  2617. X
  2618. X/*
  2619. X    This sorting algorithm is based on a Modula-2 sort written by
  2620. X    Richie Bielak and published in the February 1988 issue of
  2621. X    "Computer Language" magazine in a letter to the editor.
  2622. X*/
  2623. X
  2624. X/* sortlist - sort a list using quicksort */
  2625. XLOCAL LVAL sortlist(list,fcn)
  2626. X  LVAL list,fcn;
  2627. X{
  2628. X    LVAL gluelists();
  2629. X    LVAL smaller,pivot,larger;
  2630. X    
  2631. X    /* protect some pointers */
  2632. X    xlstkcheck(3);
  2633. X    xlsave(smaller);
  2634. X    xlsave(pivot);
  2635. X    xlsave(larger);
  2636. X    
  2637. X    /* lists with zero or one element are already sorted */
  2638. X    if (consp(list) && consp(cdr(list))) {
  2639. X    pivot = list; list = cdr(list);
  2640. X    splitlist(pivot,list,&smaller,&larger,fcn);
  2641. X    smaller = sortlist(smaller,fcn);
  2642. X    larger = sortlist(larger,fcn);
  2643. X    list = gluelists(smaller,pivot,larger);
  2644. X    }
  2645. X
  2646. X    /* cleanup the stack and return the sorted list */
  2647. X    xlpopn(3);
  2648. X    return (list);
  2649. X}
  2650. X
  2651. X/* splitlist - split the list around the pivot */
  2652. XLOCAL splitlist(pivot,list,psmaller,plarger,fcn)
  2653. X  LVAL pivot,list,*psmaller,*plarger,fcn;
  2654. X{
  2655. X    LVAL next;
  2656. X    
  2657. X    /* initialize the result lists */
  2658. X    *psmaller = *plarger = NIL;
  2659. X    
  2660. X    /* split the list */
  2661. X    for (; consp(list); list = next) {
  2662. X    next = cdr(list);
  2663. X    if (dotest2(car(list),car(pivot),fcn)) {
  2664. X        rplacd(list,*psmaller);
  2665. X        *psmaller = list;
  2666. X    }
  2667. X    else {
  2668. X        rplacd(list,*plarger);
  2669. X        *plarger = list;
  2670. X    }
  2671. X    }
  2672. X}
  2673. X
  2674. X/* gluelists - glue the smaller and larger lists with the pivot */
  2675. XLOCAL LVAL gluelists(smaller,pivot,larger)
  2676. X  LVAL smaller,pivot,larger;
  2677. X{
  2678. X    LVAL last;
  2679. X    
  2680. X    /* larger always goes after the pivot */
  2681. X    rplacd(pivot,larger);
  2682. X
  2683. X    /* if the smaller list is empty, we're done */
  2684. X    if (null(smaller))
  2685. X    return (pivot);
  2686. X
  2687. X    /* append the smaller to the front of the resulting list */
  2688. X    for (last = smaller; consp(cdr(last)); last = cdr(last))
  2689. X    ;
  2690. X    rplacd(last,pivot);
  2691. X    return (smaller);
  2692. X}
  2693. END_OF_FILE
  2694. if test 20721 -ne `wc -c <'src/xlisp/xcore/c/xllist.c'`; then
  2695.     echo shar: \"'src/xlisp/xcore/c/xllist.c'\" unpacked with wrong size!
  2696. fi
  2697. # end of 'src/xlisp/xcore/c/xllist.c'
  2698. fi
  2699. if test -f 'src/xlisp/xcore/c/xlread.c' -a "${1}" != "-c" ; then 
  2700.   echo shar: Will not clobber existing file \"'src/xlisp/xcore/c/xlread.c'\"
  2701. else
  2702. echo shar: Extracting \"'src/xlisp/xcore/c/xlread.c'\" \(19982 characters\)
  2703. sed "s/^X//" >'src/xlisp/xcore/c/xlread.c' <<'END_OF_FILE'
  2704. X/* -*-C-*-
  2705. X********************************************************************************
  2706. X*
  2707. X* File:         xlread.c
  2708. X* RCS:          $Header: xlread.c,v 1.3 89/11/25 05:43:32 mayer Exp $
  2709. X* Description:  xlisp expression input routine
  2710. X* Author:       David Michael Betz
  2711. X* Created:      
  2712. X* Modified:     Sat Nov 25 05:43:19 1989 (Niels Mayer) mayer@hplnpm
  2713. X* Language:     C
  2714. X* Package:      N/A
  2715. X* Status:       X11r4 contrib tape release
  2716. X*
  2717. X* WINTERP 1.0 Copyright 1989 Hewlett-Packard Company (by Niels Mayer).
  2718. X* XLISP version 2.1, Copyright (c) 1989, by David Betz.
  2719. X*
  2720. X* Permission to use, copy, modify, distribute, and sell this software and its
  2721. X* documentation for any purpose is hereby granted without fee, provided that
  2722. X* the above copyright notice appear in all copies and that both that
  2723. X* copyright notice and this permission notice appear in supporting
  2724. X* documentation, and that the name of Hewlett-Packard and David Betz not be
  2725. X* used in advertising or publicity pertaining to distribution of the software
  2726. X* without specific, written prior permission.  Hewlett-Packard and David Betz
  2727. X* make no representations about the suitability of this software for any
  2728. X* purpose. It is provided "as is" without express or implied warranty.
  2729. X*
  2730. X* HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  2731. X* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  2732. X* IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  2733. X* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  2734. X* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  2735. X* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  2736. X* PERFORMANCE OF THIS SOFTWARE.
  2737. X*
  2738. X* See ./winterp/COPYRIGHT for information on contacting the authors.
  2739. X* 
  2740. X* Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  2741. X* Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  2742. X*
  2743. X********************************************************************************
  2744. X*/
  2745. X static char *rcs_identity = "@(#)$Header: xlread.c,v 1.3 89/11/25 05:43:32 mayer Exp $";
  2746. X
  2747. X
  2748. X#include "xlisp.h"
  2749. X
  2750. X/* symbol parser modes */
  2751. X#define DONE    0
  2752. X#define NORMAL    1
  2753. X#define ESCAPE    2
  2754. X
  2755. X/* external variables */
  2756. Xextern LVAL s_stdout,true,s_dot;
  2757. Xextern LVAL s_quote,s_function,s_bquote,s_comma,s_comat;
  2758. Xextern LVAL s_rtable,k_wspace,k_const,k_nmacro,k_tmacro;
  2759. Xextern LVAL k_sescape,k_mescape;
  2760. Xextern char buf[];
  2761. X
  2762. X/* external routines */
  2763. Xextern FILE *osaopen();
  2764. Xextern double atof();
  2765. Xextern ITYPE;
  2766. Xextern LVAL s_unbound;
  2767. X
  2768. X#define WSPACE "\t \f\r\n"
  2769. X#define CONST1 "!$%&*+-./0123456789:<=>?@[]^_{}~"
  2770. X#define CONST2 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  2771. X
  2772. X/* forward declarations */
  2773. XFORWARD LVAL callmacro();
  2774. XFORWARD LVAL psymbol(),punintern();
  2775. XFORWARD LVAL pnumber(),pquote(),plist(),pvector(),pstruct();
  2776. XFORWARD LVAL readlist(),tentry();
  2777. X
  2778. X/* xlload - load a file of xlisp expressions */
  2779. Xint xlload(fname,vflag,pflag)
  2780. X  char *fname; int vflag,pflag;
  2781. X{
  2782. X    char fullname[STRMAX+1];
  2783. X    LVAL fptr,expr,path;
  2784. X    CONTEXT cntxt;
  2785. X    FILE *fp;
  2786. X    int sts;
  2787. X
  2788. X    /* protect some pointers */
  2789. X    xlstkcheck(3);
  2790. X    xlsave(fptr);
  2791. X    xlsave(expr);
  2792. X    xlsave(path);
  2793. X
  2794. X
  2795. X    /** let user choose path name **/   /* Voodoo */
  2796. X
  2797. X    fullname[0] = '\0';                               
  2798. X
  2799. X    /* find user path from load-path variable */
  2800. X    if ((path = xlxgetvalue(xlenter("LOAD-PATH"))) != s_unbound && 
  2801. X    stringp(path)) {                         
  2802. X    strcpy(fullname,getstring(path));                
  2803. X    if (fullname[strlen(fullname) - 1] != '/')            
  2804. X        strcat(fullname, "/");                    
  2805. X    }
  2806. X
  2807. X    /* incorporate filename */
  2808. X    strcat(fullname,fname);
  2809. X
  2810. X    /* default the extension */
  2811. X    if (needsextension(fname))
  2812. X    strcat(fullname,".lsp");
  2813. X
  2814. X    fname = fullname;
  2815. X
  2816. X
  2817. X    /* allocate a file node */
  2818. X    fptr = cvfile(NULL);
  2819. X
  2820. X    /* open the file */
  2821. X    if ((fp = osaopen(fname,"r")) == NULL) {
  2822. X    xlpopn(3);
  2823. X    return (FALSE);
  2824. X    }
  2825. X    setfile(fptr,fp);
  2826. X
  2827. X    /* print the information line */
  2828. X    if (vflag)
  2829. X    { sprintf(buf,"; loading \"%s\"\n",fname); stdputstr(buf); }
  2830. X
  2831. X    /* read, evaluate and possibly print each expression in the file */
  2832. X    xlbegin(&cntxt,CF_ERROR,true);
  2833. X    if (xlsetjmp(cntxt.c_jmpbuf))
  2834. X    sts = FALSE;
  2835. X    else {
  2836. X    while (xlread(fptr,&expr,FALSE)) {
  2837. X        expr = xleval(expr);
  2838. X        if (pflag)
  2839. X        stdprint(expr);
  2840. X    }
  2841. X    sts = TRUE;
  2842. X    }
  2843. X    xlend(&cntxt);
  2844. X
  2845. X    /* close the file */
  2846. X    osclose(getfile(fptr));
  2847. X    setfile(fptr,NULL);
  2848. X
  2849. X    /* restore the stack */
  2850. X    xlpopn(3);
  2851. X
  2852. X    /* return status */
  2853. X    return (sts);
  2854. X}
  2855. X
  2856. X/* xlread - read an xlisp expression */
  2857. Xint xlread(fptr,pval,rflag)
  2858. X  LVAL fptr,*pval; int rflag;
  2859. X{
  2860. X    int sts;
  2861. X
  2862. X    /* read an expression */
  2863. X    while ((sts = readone(fptr,pval)) == FALSE)
  2864. X    ;
  2865. X
  2866. X    /* return status */
  2867. X    return (sts == EOF ? FALSE : TRUE);
  2868. X}
  2869. X
  2870. X/* readone - attempt to read a single expression */
  2871. Xint readone(fptr,pval)
  2872. X  LVAL fptr,*pval;
  2873. X{
  2874. X    LVAL val,type;
  2875. X    int ch;
  2876. X
  2877. X    /* get a character and check for EOF */
  2878. X    if ((ch = xlgetc(fptr)) == EOF)
  2879. X    return (EOF);
  2880. X
  2881. X    /* handle white space */
  2882. X    if ((type = tentry(ch)) == k_wspace)
  2883. X    return (FALSE);
  2884. X
  2885. X    /* handle symbol constituents */
  2886. X    else if (type == k_const) {
  2887. X    xlungetc(fptr,ch);
  2888. X    *pval = psymbol(fptr);
  2889. X    return (TRUE);        
  2890. X    }
  2891. X
  2892. X    /* handle single and multiple escapes */
  2893. X    else if (type == k_sescape || type == k_mescape) {
  2894. X    xlungetc(fptr,ch);
  2895. X    *pval = psymbol(fptr);
  2896. X    return (TRUE);
  2897. X    }
  2898. X    
  2899. X    /* handle read macros */
  2900. X    else if (consp(type)) {
  2901. X    if ((val = callmacro(fptr,ch)) && consp(val)) {
  2902. X        *pval = car(val);
  2903. X        return (TRUE);
  2904. X    }
  2905. X    else
  2906. X        return (FALSE);
  2907. X    }
  2908. X
  2909. X    /* handle illegal characters */
  2910. X    else
  2911. X    xlerror("illegal character",cvfixnum((FIXTYPE)ch));
  2912. X}
  2913. X
  2914. X/* rmhash - read macro for '#' */
  2915. XLVAL rmhash()
  2916. X{
  2917. X    LVAL fptr,mch,val;
  2918. X    int escflag,ch;
  2919. X
  2920. X    /* protect some pointers */
  2921. X    xlsave1(val);
  2922. X
  2923. X    /* get the file and macro character */
  2924. X    fptr = xlgetfile();
  2925. X    mch = xlgachar();
  2926. X    xllastarg();
  2927. X
  2928. X    /* make the return value */
  2929. X    val = consa(NIL);
  2930. X
  2931. X    /* check the next character */
  2932. X    switch (ch = xlgetc(fptr)) {
  2933. X    case '\'':
  2934. X        rplaca(val,pquote(fptr,s_function));
  2935. X        break;
  2936. X    case '(':
  2937. X        xlungetc(fptr,ch);
  2938. X        rplaca(val,pvector(fptr));
  2939. X        break;
  2940. X    case 'b':
  2941. X    case 'B':
  2942. X        rplaca(val,pnumber(fptr,2));
  2943. X        break;
  2944. X    case 'o':
  2945. X    case 'O':
  2946. X        rplaca(val,pnumber(fptr,8));
  2947. X        break;
  2948. X    case 'x':
  2949. X    case 'X':
  2950. X            rplaca(val,pnumber(fptr,16));
  2951. X        break;
  2952. X    case 's':
  2953. X    case 'S':
  2954. X        rplaca(val,pstruct(fptr));
  2955. X        break;
  2956. X    case '\\':
  2957. X        xlungetc(fptr,ch);
  2958. X        pname(fptr,&escflag);
  2959. X        ch = buf[0];
  2960. X        if (strlen(buf) > 1) {
  2961. X            upcase(buf);
  2962. X            if (strcmp(buf,"NEWLINE") == 0)
  2963. X            ch = '\n';
  2964. X            else if (strcmp(buf,"SPACE") == 0)
  2965. X            ch = ' ';
  2966. X            else
  2967. X            xlerror("unknown character name",cvstring(buf));
  2968. X        }
  2969. X        rplaca(val,cvchar(ch));
  2970. X        break;
  2971. X    case ':':
  2972. X            rplaca(val,punintern(fptr));
  2973. X        break;
  2974. X    case '|':
  2975. X            pcomment(fptr);
  2976. X        val = NIL;
  2977. X        break;
  2978. X    default:
  2979. X        xlerror("illegal character after #",cvfixnum((FIXTYPE)ch));
  2980. X    }
  2981. X
  2982. X    /* restore the stack */
  2983. X    xlpop();
  2984. X
  2985. X    /* return the value */
  2986. X    return (val);
  2987. X}
  2988. X
  2989. X/* rmquote - read macro for '\'' */
  2990. XLVAL rmquote()
  2991. X{
  2992. X    LVAL fptr,mch;
  2993. X
  2994. X    /* get the file and macro character */
  2995. X    fptr = xlgetfile();
  2996. X    mch = xlgachar();
  2997. X    xllastarg();
  2998. X
  2999. X    /* parse the quoted expression */
  3000. X    return (consa(pquote(fptr,s_quote)));
  3001. X}
  3002. X
  3003. X/* rmdquote - read macro for '"' */
  3004. XLVAL rmdquote()
  3005. X{
  3006. X    unsigned char buf[STRMAX+1],*p,*sptr;
  3007. X    LVAL fptr,str,newstr,mch;
  3008. X    int len,blen,ch,d2,d3;
  3009. X
  3010. X    /* protect some pointers */
  3011. X    xlsave1(str);
  3012. X
  3013. X    /* get the file and macro character */
  3014. X    fptr = xlgetfile();
  3015. X    mch = xlgachar();
  3016. X    xllastarg();
  3017. X
  3018. X    /* loop looking for a closing quote */
  3019. X    len = blen = 0; p = buf;
  3020. X    while ((ch = checkeof(fptr)) != '"') {
  3021. X
  3022. X    /* handle escaped characters */
  3023. X    switch (ch) {
  3024. X    case '\\':
  3025. X        switch (ch = checkeof(fptr)) {
  3026. X        case 't':
  3027. X            ch = '\011';
  3028. X            break;
  3029. X        case 'n':
  3030. X            ch = '\012';
  3031. X            break;
  3032. X        case 'f':
  3033. X            ch = '\014';
  3034. X            break;
  3035. X        case 'r':
  3036. X            ch = '\015';
  3037. X            break;
  3038. X        default:
  3039. X            if (ch >= '0' && ch <= '7') {
  3040. X                d2 = checkeof(fptr);
  3041. X                d3 = checkeof(fptr);
  3042. X                if (d2 < '0' || d2 > '7'
  3043. X                 || d3 < '0' || d3 > '7')
  3044. X                xlfail("invalid octal digit");
  3045. X                ch -= '0'; d2 -= '0'; d3 -= '0';
  3046. X                ch = (ch << 6) | (d2 << 3) | d3;
  3047. X            }
  3048. X            break;
  3049. X        }
  3050. X    }
  3051. X
  3052. X    /* check for buffer overflow */
  3053. X    if (blen >= STRMAX) {
  3054. X         newstr = newstring(len + STRMAX + 1);
  3055. X        sptr = getstring(newstr); *sptr = '\0';
  3056. X        if (str) strcat(sptr,getstring(str));
  3057. X        *p = '\0'; strcat(sptr,buf);
  3058. X        p = buf; blen = 0;
  3059. X        len += STRMAX;
  3060. X        str = newstr;
  3061. X    }
  3062. X
  3063. X    /* store the character */
  3064. X    *p++ = ch; ++blen;
  3065. X    }
  3066. X
  3067. X    /* append the last substring */
  3068. X    if (str == NIL || blen) {
  3069. X    newstr = newstring(len + blen + 1);
  3070. X    sptr = getstring(newstr); *sptr = '\0';
  3071. X    if (str) strcat(sptr,getstring(str));
  3072. X    *p = '\0'; strcat(sptr,buf);
  3073. X    str = newstr;
  3074. X    }
  3075. X
  3076. X    /* restore the stack */
  3077. X    xlpop();
  3078. X
  3079. X    /* return the new string */
  3080. X    return (consa(str));
  3081. X}
  3082. X
  3083. X/* rmbquote - read macro for '`' */
  3084. XLVAL rmbquote()
  3085. X{
  3086. X    LVAL fptr,mch;
  3087. X
  3088. X    /* get the file and macro character */
  3089. X    fptr = xlgetfile();
  3090. X    mch = xlgachar();
  3091. X    xllastarg();
  3092. X
  3093. X    /* parse the quoted expression */
  3094. X    return (consa(pquote(fptr,s_bquote)));
  3095. X}
  3096. X
  3097. X/* rmcomma - read macro for ',' */
  3098. XLVAL rmcomma()
  3099. X{
  3100. X    LVAL fptr,mch,sym;
  3101. X    int ch;
  3102. X
  3103. X    /* get the file and macro character */
  3104. X    fptr = xlgetfile();
  3105. X    mch = xlgachar();
  3106. X    xllastarg();
  3107. X
  3108. X    /* check the next character */
  3109. X    if ((ch = xlgetc(fptr)) == '@')
  3110. X    sym = s_comat;
  3111. X    else {
  3112. X    xlungetc(fptr,ch);
  3113. X    sym = s_comma;
  3114. X    }
  3115. X
  3116. X    /* make the return value */
  3117. X    return (consa(pquote(fptr,sym)));
  3118. X}
  3119. X
  3120. X/* rmlpar - read macro for '(' */
  3121. XLVAL rmlpar()
  3122. X{
  3123. X    LVAL fptr,mch;
  3124. X
  3125. X    /* get the file and macro character */
  3126. X    fptr = xlgetfile();
  3127. X    mch = xlgachar();
  3128. X    xllastarg();
  3129. X
  3130. X    /* make the return value */
  3131. X    return (consa(plist(fptr)));
  3132. X}
  3133. X
  3134. X/* rmrpar - read macro for ')' */
  3135. XLVAL rmrpar()
  3136. X{
  3137. X    xlfail("misplaced right paren");
  3138. X}
  3139. X
  3140. X/* rmsemi - read macro for ';' */
  3141. XLVAL rmsemi()
  3142. X{
  3143. X    LVAL fptr,mch;
  3144. X    int ch;
  3145. X
  3146. X    /* get the file and macro character */
  3147. X    fptr = xlgetfile();
  3148. X    mch = xlgachar();
  3149. X    xllastarg();
  3150. X
  3151. X    /* skip to end of line */
  3152. X    while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
  3153. X    ;
  3154. X
  3155. X    /* return nil (nothing read) */
  3156. X    return (NIL);
  3157. X}
  3158. X
  3159. X/* pcomment - parse a comment delimited by #| and |# */
  3160. XLOCAL pcomment(fptr)
  3161. X  LVAL fptr;
  3162. X{
  3163. X    int lastch,ch,n;
  3164. X
  3165. X    /* look for the matching delimiter (and handle nesting) */
  3166. X    for (n = 1, lastch = -1; n > 0 && (ch = xlgetc(fptr)) != EOF; ) {
  3167. X    if (lastch == '|' && ch == '#')
  3168. X        { --n; ch = -1; }
  3169. X    else if (lastch == '#' && ch == '|')
  3170. X        { ++n; ch = -1; }
  3171. X    lastch = ch;
  3172. X    }
  3173. X}
  3174. X
  3175. X/* pnumber - parse a number */
  3176. XLOCAL LVAL pnumber(fptr,radix)
  3177. X  LVAL fptr; int radix;
  3178. X{
  3179. X    int digit,ch;
  3180. X    long num;
  3181. X    
  3182. X    for (num = 0L; (ch = xlgetc(fptr)) != EOF; ) {
  3183. X    if (islower(ch)) ch = toupper(ch);
  3184. X    if (!('0' <= ch && ch <= '9') && !('A' <= ch && ch <= 'F'))
  3185. X        break;
  3186. X    if ((digit = (ch <= '9' ? ch - '0' : ch - 'A' + 10)) >= radix)
  3187. X        break;
  3188. X    num = num * (long)radix + (long)digit;
  3189. X    }
  3190. X    xlungetc(fptr,ch);
  3191. X    return (cvfixnum((FIXTYPE)num));
  3192. X}
  3193. X
  3194. X/* plist - parse a list */
  3195. XLOCAL LVAL plist(fptr)
  3196. X  LVAL fptr;
  3197. X{
  3198. X    LVAL val,expr,lastnptr,nptr;
  3199. X
  3200. X    /* protect some pointers */
  3201. X    xlstkcheck(2);
  3202. X    xlsave(val);
  3203. X    xlsave(expr);
  3204. X
  3205. X    /* keep appending nodes until a closing paren is found */
  3206. X    for (lastnptr = NIL; nextch(fptr) != ')'; )
  3207. X
  3208. X    /* get the next expression */
  3209. X    switch (readone(fptr,&expr)) {
  3210. X    case EOF:
  3211. X        badeof(fptr);
  3212. X    case TRUE:
  3213. X
  3214. X        /* check for a dotted tail */
  3215. X        if (expr == s_dot) {
  3216. X
  3217. X        /* make sure there's a node */
  3218. X        if (lastnptr == NIL)
  3219. X            xlfail("invalid dotted pair");
  3220. X
  3221. X        /* parse the expression after the dot */
  3222. X        if (!xlread(fptr,&expr,TRUE))
  3223. X            badeof(fptr);
  3224. X        rplacd(lastnptr,expr);
  3225. X
  3226. X        /* make sure its followed by a close paren */
  3227. X        if (nextch(fptr) != ')')
  3228. X            xlfail("invalid dotted pair");
  3229. X        }
  3230. X
  3231. X        /* otherwise, handle a normal list element */
  3232. X        else {
  3233. X        nptr = consa(expr);
  3234. X        if (lastnptr == NIL)
  3235. X            val = nptr;
  3236. X        else
  3237. X            rplacd(lastnptr,nptr);
  3238. X        lastnptr = nptr;
  3239. X        }
  3240. X        break;
  3241. X    }
  3242. X
  3243. X    /* skip the closing paren */
  3244. X    xlgetc(fptr);
  3245. X
  3246. X    /* restore the stack */
  3247. X    xlpopn(2);
  3248. X
  3249. X    /* return successfully */
  3250. X    return (val);
  3251. X}
  3252. X
  3253. X/* pvector - parse a vector */
  3254. XLOCAL LVAL pvector(fptr)
  3255. X  LVAL fptr;
  3256. X{
  3257. X    LVAL list,val;
  3258. X    int len,i;
  3259. X
  3260. X    /* protect some pointers */
  3261. X    xlsave1(list);
  3262. X
  3263. X    /* read the list */
  3264. X    list = readlist(fptr,&len);
  3265. X
  3266. X    /* make a vector of the appropriate length */
  3267. X    val = newvector(len);
  3268. X
  3269. X    /* copy the list into the vector */
  3270. X    for (i = 0; i < len; ++i, list = cdr(list))
  3271. X    setelement(val,i,car(list));
  3272. X
  3273. X    /* restore the stack */
  3274. X    xlpop();
  3275. X
  3276. X    /* return successfully */
  3277. X    return (val);
  3278. X}
  3279. X
  3280. X/* pstruct - parse a structure */
  3281. XLOCAL LVAL pstruct(fptr)
  3282. X  LVAL fptr;
  3283. X{
  3284. X    extern LVAL xlrdstruct();
  3285. X    LVAL list,val;
  3286. X    int len;
  3287. X
  3288. X    /* protect some pointers */
  3289. X    xlsave1(list);
  3290. X
  3291. X    /* read the list */
  3292. X    list = readlist(fptr,&len);
  3293. X
  3294. X    /* make the structure */
  3295. X    val = xlrdstruct(list);
  3296. X
  3297. X    /* restore the stack */
  3298. X    xlpop();
  3299. X
  3300. X    /* return successfully */
  3301. X    return (val);
  3302. X}
  3303. X
  3304. X/* pquote - parse a quoted expression */
  3305. XLOCAL LVAL pquote(fptr,sym)
  3306. X  LVAL fptr,sym;
  3307. X{
  3308. X    LVAL val,p;
  3309. X
  3310. X    /* protect some pointers */
  3311. X    xlsave1(val);
  3312. X
  3313. X    /* allocate two nodes */
  3314. X    val = consa(sym);
  3315. X    rplacd(val,consa(NIL));
  3316. X
  3317. X    /* initialize the second to point to the quoted expression */
  3318. X    if (!xlread(fptr,&p,TRUE))
  3319. X    badeof(fptr);
  3320. X    rplaca(cdr(val),p);
  3321. X
  3322. X    /* restore the stack */
  3323. X    xlpop();
  3324. X
  3325. X    /* return the quoted expression */
  3326. X    return (val);
  3327. X}
  3328. X
  3329. X/* psymbol - parse a symbol name */
  3330. XLOCAL LVAL psymbol(fptr)
  3331. X  LVAL fptr;
  3332. X{
  3333. X    int escflag;
  3334. X    LVAL val;
  3335. X    pname(fptr,&escflag);
  3336. X    return (escflag || !isnumber(buf,&val) ? xlenter(buf) : val);
  3337. X}
  3338. X
  3339. X/* punintern - parse an uninterned symbol */
  3340. XLOCAL LVAL punintern(fptr)
  3341. X  LVAL fptr;
  3342. X{
  3343. X    int escflag;
  3344. X    pname(fptr,&escflag);
  3345. X    return (xlmakesym(buf));
  3346. X}
  3347. X
  3348. X/* pname - parse a symbol/package name */
  3349. XLOCAL int pname(fptr,pescflag)
  3350. X  LVAL fptr; int *pescflag;
  3351. X{
  3352. X    int mode,ch,i;
  3353. X    LVAL type;
  3354. X
  3355. X    /* initialize */
  3356. X    *pescflag = FALSE;
  3357. X    mode = NORMAL;
  3358. X    i = 0;
  3359. X
  3360. X    /* accumulate the symbol name */
  3361. X    while (mode != DONE) {
  3362. X
  3363. X    /* handle normal mode */
  3364. X    while (mode == NORMAL)
  3365. X        if ((ch = xlgetc(fptr)) == EOF)
  3366. X        mode = DONE;
  3367. X        else if ((type = tentry(ch)) == k_sescape) {
  3368. X        i = storech(buf,i,checkeof(fptr));
  3369. X        *pescflag = TRUE;
  3370. X        }
  3371. X        else if (type == k_mescape) {
  3372. X        *pescflag = TRUE;
  3373. X        mode = ESCAPE;
  3374. X        }
  3375. X        else if (type == k_const
  3376. X         ||  (consp(type) && car(type) == k_nmacro))
  3377. X        i = storech(buf,i,islower(ch) ? toupper(ch) : ch);
  3378. X        else
  3379. X        mode = DONE;
  3380. X
  3381. X    /* handle multiple escape mode */
  3382. X    while (mode == ESCAPE)
  3383. X        if ((ch = xlgetc(fptr)) == EOF)
  3384. X        badeof(fptr);
  3385. X        else if ((type = tentry(ch)) == k_sescape)
  3386. X        i = storech(buf,i,checkeof(fptr));
  3387. X        else if (type == k_mescape)
  3388. X        mode = NORMAL;
  3389. X        else
  3390. X        i = storech(buf,i,ch);
  3391. X    }
  3392. X    buf[i] = 0;
  3393. X
  3394. X    /* check for a zero length name */
  3395. X    if (i == 0)
  3396. X    xlfail("zero length name");
  3397. X
  3398. X    /* unget the last character and return it */
  3399. X    xlungetc(fptr,ch);
  3400. X    return (ch);
  3401. X}
  3402. X
  3403. X/* readlist - read a list terminated by a ')' */
  3404. XLOCAL LVAL readlist(fptr,plen)
  3405. X  LVAL fptr; int *plen;
  3406. X{
  3407. X    LVAL list,expr,lastnptr,nptr;
  3408. X    int ch;
  3409. X
  3410. X    /* protect some pointers */
  3411. X    xlstkcheck(2);
  3412. X    xlsave(list);
  3413. X    xlsave(expr);
  3414. X
  3415. X    /* get the open paren */
  3416. X    if ((ch = nextch(fptr)) != '(')
  3417. X    xlfail("expecting an open paren");
  3418. X    xlgetc(fptr);
  3419. X
  3420. X    /* keep appending nodes until a closing paren is found */
  3421. X    for (lastnptr = NIL, *plen = 0; (ch = nextch(fptr)) != ')'; ) {
  3422. X
  3423. X    /* check for end of file */
  3424. X    if (ch == EOF)
  3425. X        badeof(fptr);
  3426. X
  3427. X    /* get the next expression */
  3428. X    switch (readone(fptr,&expr)) {
  3429. X    case EOF:
  3430. X        badeof(fptr);
  3431. X    case TRUE:
  3432. X        nptr = consa(expr);
  3433. X        if (lastnptr == NIL)
  3434. X        list = nptr;
  3435. X        else
  3436. X        rplacd(lastnptr,nptr);
  3437. X        lastnptr = nptr;
  3438. X        ++(*plen);
  3439. X        break;
  3440. X    }
  3441. X    }
  3442. X
  3443. X    /* skip the closing paren */
  3444. X    xlgetc(fptr);
  3445. X
  3446. X    /* restore the stack */
  3447. X    xlpopn(2);
  3448. X
  3449. X    /* return the list */
  3450. X    return (list);
  3451. X}
  3452. X
  3453. X/* storech - store a character in the print name buffer */
  3454. XLOCAL int storech(buf,i,ch)
  3455. X  char *buf; int i,ch;
  3456. X{
  3457. X    if (i < STRMAX)
  3458. X    buf[i++] = ch;
  3459. X    return (i);
  3460. X}
  3461. X
  3462. X/* tentry - get a readtable entry */
  3463. XLVAL tentry(ch)
  3464. X  int ch;
  3465. X{
  3466. X    LVAL rtable;
  3467. X    rtable = getvalue(s_rtable);
  3468. X    if (!vectorp(rtable) || ch < 0 || ch >= getsz(rtable))
  3469. X    return (NIL);
  3470. X    return (getelement(rtable,ch));
  3471. X}
  3472. X
  3473. X/* nextch - look at the next non-blank character */
  3474. XLOCAL int nextch(fptr)
  3475. X  LVAL fptr;
  3476. X{
  3477. X    int ch;
  3478. X
  3479. X    /* return and save the next non-blank character */
  3480. X    while ((ch = xlgetc(fptr)) != EOF && isspace(ch))
  3481. X    ;
  3482. X    xlungetc(fptr,ch);
  3483. X    return (ch);
  3484. X}
  3485. X
  3486. X/* checkeof - get a character and check for end of file */
  3487. XLOCAL int checkeof(fptr)
  3488. X  LVAL fptr;
  3489. X{
  3490. X    int ch;
  3491. X
  3492. X    if ((ch = xlgetc(fptr)) == EOF)
  3493. X    badeof(fptr);
  3494. X    return (ch);
  3495. X}
  3496. X
  3497. X/* badeof - unexpected eof */
  3498. XLOCAL badeof(fptr)
  3499. X  LVAL fptr;
  3500. X{
  3501. X    xlgetc(fptr);
  3502. X    xlfail("unexpected EOF");
  3503. X}
  3504. X
  3505. X/* isnumber - check if this string is a number */
  3506. Xint isnumber(str,pval)
  3507. X  char *str; LVAL *pval;
  3508. X{
  3509. X    int dl,dr;
  3510. X    char *p;
  3511. X
  3512. X    /* initialize */
  3513. X    p = str; dl = dr = 0;
  3514. X
  3515. X    /* check for a sign */
  3516. X    if (*p == '+' || *p == '-')
  3517. X    p++;
  3518. X
  3519. X    /* check for a string of digits */
  3520. X    while (isdigit(*p))
  3521. X    p++, dl++;
  3522. X
  3523. X    /* check for a decimal point */
  3524. X    if (*p == '.') {
  3525. X    p++;
  3526. X    while (isdigit(*p))
  3527. X        p++, dr++;
  3528. X    }
  3529. X
  3530. X    /* check for an exponent */
  3531. X    if ((dl || dr) && *p == 'E') {
  3532. X    p++;
  3533. X
  3534. X    /* check for a sign */
  3535. X    if (*p == '+' || *p == '-')
  3536. X        p++;
  3537. X
  3538. X    /* check for a string of digits */
  3539. X    while (isdigit(*p))
  3540. X        p++, dr++;
  3541. X    }
  3542. X
  3543. X    /* make sure there was at least one digit and this is the end */
  3544. X    if ((dl == 0 && dr == 0) || *p)
  3545. X    return (FALSE);
  3546. X
  3547. X    /* convert the string to an integer and return successfully */
  3548. X    if (pval) {
  3549. X    if (*str == '+') ++str;
  3550. X    if (str[strlen(str)-1] == '.') str[strlen(str)-1] = 0;
  3551. X    *pval = (dr ? cvflonum(atof(str)) : cvfixnum(ICNV(str)));
  3552. X    }
  3553. X    return (TRUE);
  3554. X}
  3555. X
  3556. X/* defmacro - define a read macro */
  3557. Xdefmacro(ch,type,offset)
  3558. X  int ch; LVAL type; int offset;
  3559. X{
  3560. X    extern FUNDEF *funtab;
  3561. X    LVAL subr;
  3562. X    subr = cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset);
  3563. X    setelement(getvalue(s_rtable),ch,cons(type,subr));
  3564. X}
  3565. X
  3566. X/* callmacro - call a read macro */
  3567. XLVAL callmacro(fptr,ch)
  3568. X  LVAL fptr; int ch;
  3569. X{
  3570. X    LVAL *newfp;
  3571. X
  3572. X    /* create the new call frame */
  3573. X    newfp = xlsp;
  3574. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  3575. X    pusharg(cdr(getelement(getvalue(s_rtable),ch)));
  3576. X    pusharg(cvfixnum((FIXTYPE)2));
  3577. X    pusharg(fptr);
  3578. X    pusharg(cvchar(ch));
  3579. X    xlfp = newfp;
  3580. X    return (xlapply(2));
  3581. X}
  3582. X
  3583. X/* upcase - translate a string to upper case */
  3584. XLOCAL upcase(str)
  3585. X  unsigned char *str;
  3586. X{
  3587. X    for (; *str != '\0'; ++str)
  3588. X    if (islower(*str))
  3589. X        *str = toupper(*str);
  3590. X}
  3591. X
  3592. X/* xlrinit - initialize the reader */
  3593. Xxlrinit()
  3594. X{
  3595. X    LVAL rtable;
  3596. X    char *p;
  3597. X    int ch;
  3598. X
  3599. X    /* create the read table */
  3600. X    rtable = newvector(256);
  3601. X    setvalue(s_rtable,rtable);
  3602. X
  3603. X    /* initialize the readtable */
  3604. X    for (p = WSPACE; ch = *p++; )
  3605. X    setelement(rtable,ch,k_wspace);
  3606. X    for (p = CONST1; ch = *p++; )
  3607. X    setelement(rtable,ch,k_const);
  3608. X    for (p = CONST2; ch = *p++; )
  3609. X    setelement(rtable,ch,k_const);
  3610. X
  3611. X    /* setup the escape characters */
  3612. X    setelement(rtable,'\\',k_sescape);
  3613. X    setelement(rtable,'|', k_mescape);
  3614. X
  3615. X    /* install the read macros */
  3616. X    defmacro('#', k_nmacro,FT_RMHASH);
  3617. X    defmacro('\'',k_tmacro,FT_RMQUOTE);
  3618. X    defmacro('"', k_tmacro,FT_RMDQUOTE);
  3619. X    defmacro('`', k_tmacro,FT_RMBQUOTE);
  3620. X    defmacro(',', k_tmacro,FT_RMCOMMA);
  3621. X    defmacro('(', k_tmacro,FT_RMLPAR);
  3622. X    defmacro(')', k_tmacro,FT_RMRPAR);
  3623. X    defmacro(';', k_tmacro,FT_RMSEMI);
  3624. X}
  3625. END_OF_FILE
  3626. if test 19982 -ne `wc -c <'src/xlisp/xcore/c/xlread.c'`; then
  3627.     echo shar: \"'src/xlisp/xcore/c/xlread.c'\" unpacked with wrong size!
  3628. fi
  3629. # end of 'src/xlisp/xcore/c/xlread.c'
  3630. fi
  3631. echo shar: End of archive 9 \(of 16\).
  3632. cp /dev/null ark9isdone
  3633. MISSING=""
  3634. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  3635.     if test ! -f ark${I}isdone ; then
  3636.     MISSING="${MISSING} ${I}"
  3637.     fi
  3638. done
  3639. if test "${MISSING}" = "" ; then
  3640.     echo You have unpacked all 16 archives.
  3641.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3642. else
  3643.     echo You still need to unpack the following archives:
  3644.     echo "        " ${MISSING}
  3645. fi
  3646. ##  End of shell archive.
  3647. exit 0
  3648.