home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / spin / part01 next >
Text File  |  1989-03-08  |  60KB  |  2,436 lines

  1. Subject:  v18i009:  Simple programmable interface kit, Part01/02
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Jim McBeath <voder!sci!gumby!jimmc>
  7. Posting-number: Volume 18, Issue 9
  8. Archive-name: spin/part01
  9.  
  10. [  This posting is hard to describe.  It's sort of like an extensible
  11.    command-language interpreter library.  --r$  ]
  12.  
  13. Spin is a simple interpreter intended for use as a program development
  14. tool and modest programmable interface.  It contains a parser and
  15. execution engine, with the ability to easily extend the basic engine with
  16. additional features such as control constructs or new operations.
  17.  
  18. The spin interpreter has been set up to be usable in a bare-bones
  19. configuration, in which there are almost no capabilities or functions
  20. available other than application-specific ones.  There are also a set of
  21. various simple extensions available which raise the
  22. application-independent capabilities of spin up to a level where it is
  23. almost usable by itself.  The intent is for the application to add
  24. whatever application-specific functions it needs and to select the level
  25. of application-independent support needed.  The spin library was designed
  26. to be modular enough that the application program could pick and choose
  27. among almost all of the aspects of the interpreter.  If there is a
  28. capability which is not needed, it does not need to be loaded.  If there
  29. is a capability which the programmer feels he can implement better, it is
  30. typically a fairly simple job for him to rewrite that capability without
  31. worrying about other parts of the system.
  32.  
  33. In addition to the generic extensions, an application program can add
  34. whatever application-specific functions are desired.  Each function
  35. requires a one-line call to one of the spin primitives, to be executed
  36. during program startup time.  Once this has been done, the function is
  37. available to the user of the application.
  38.  
  39. There are a small number of data types known to spin (e.g. int, float,
  40. string), which can be specified as the argument and return types for
  41. functions.  The spin interpreter will do type checking on all arguments
  42. passed to functions.
  43.  
  44.  
  45. #! /bin/sh
  46. # This is a shell archive.  Remove anything before this line, then unpack
  47. # it by saving it into a file and typing "sh file".  To overwrite existing
  48. # files, type "sh file -c".  You can also feed this as standard input via
  49. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  50. # will see the following message at the end:
  51. #        "End of archive 1 (of 2)."
  52. # Contents:  MANIFEST Makefile README TODO cont.sp contsubs.c exec.h
  53. #   filesubs.c goto.c goto.h initsubs.c lex.l listsubs.c main.c
  54. #   mathsubs.c parse.c spin.3 spin.h spinparse.h varsubs.c xalloc.c
  55. #   xalloc.h
  56. # Wrapped by rsalz@fig.bbn.com on Thu Mar  9 15:55:19 1989
  57. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  58. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  59.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  60. else
  61. echo shar: Extracting \"'MANIFEST'\" \(809 characters\)
  62. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  63. X   File Name        Archive #    Description
  64. X-----------------------------------------------------------
  65. X MANIFEST                   1    
  66. X Makefile                   1    
  67. X README                     1    
  68. X TODO                       1    
  69. X cont.sp                    1    
  70. X contsubs.c                 1    
  71. X exec.c                     2    
  72. X exec.h                     1    
  73. X filesubs.c                 1    
  74. X goto.c                     1    
  75. X goto.h                     1    
  76. X initsubs.c                 1    
  77. X lex.l                      1    
  78. X listsubs.c                 1    
  79. X main.c                     1    
  80. X mathsubs.c                 1    
  81. X parse.c                    1    
  82. X spin.3                     1    
  83. X spin.h                     1    
  84. X spinparse.h                1    
  85. X varsubs.c                  1    
  86. X xalloc.c                   1    
  87. X xalloc.h                   1    
  88. END_OF_FILE
  89. if test 809 -ne `wc -c <'MANIFEST'`; then
  90.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  91. fi
  92. # end of 'MANIFEST'
  93. fi
  94. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  95.   echo shar: Will not clobber existing file \"'Makefile'\"
  96. else
  97. echo shar: Extracting \"'Makefile'\" \(3439 characters\)
  98. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  99. X#Makefile for spin
  100. X# 28.Jul.87  jimmc  Initial definition
  101. X#  2.Aug.87  jimmc  Add backup tag
  102. X# 30.Nov.87  jimmc  Add LINTSRCS macro, SHAR stuff
  103. X# 11.Jan.88  jimmc  Remove main.o from object list for library
  104. X#  1.Mar.87  jimmc  Add man tag
  105. X
  106. XROOTNAME      = spin
  107. XLIBRARY          = $(ROOTNAME).a
  108. XLINTLIB          = llib-$(LIBRARY).ln
  109. XPROGRAM          = $(ROOTNAME)
  110. XDEST          = .
  111. X
  112. XMKMF          = mkmf
  113. X
  114. XCLASH         = clash
  115. X
  116. XSHAR          = shar
  117. XSHARFILE      = $(ROOTNAME).shar
  118. X
  119. XMAKE          =    make $(MFLAGS)
  120. XMAKEFILE      = Makefile
  121. X
  122. XBKPMACH = wheel
  123. XBKPDIR = src/$(ROOTNAME).bak
  124. X
  125. X# careful with this variable.  it is really set down in target "depend:"
  126. XCFLAGS    = $(CCOPTS) 
  127. X
  128. XINCLUDE    =
  129. XCCOPTS = -g
  130. X
  131. XLINKER          = cc 
  132. X
  133. XLINTFLAGS =    $(INCLUDE) $(LINTOPTS)
  134. XLINTOPTS    = -bauz
  135. X
  136. XSRCS          = contsubs.c \
  137. X        exec.c \
  138. X        filesubs.c \
  139. X        goto.c \
  140. X        initsubs.c \
  141. X        lex.l \
  142. X        listsubs.c \
  143. X        main.c \
  144. X        mathsubs.c \
  145. X        parse.c \
  146. X        varsubs.c \
  147. X        xalloc.c
  148. X
  149. XLINTSRCS = `echo $(SRCS) | sed -e 's/lex.l//' -e 's/main.c//' `
  150. X
  151. XLIBOBJS = `echo $(OBJS) | sed -e 's/main.o//' `
  152. X
  153. XOBJS          = contsubs.o \
  154. X        exec.o \
  155. X        filesubs.o \
  156. X        goto.o \
  157. X        initsubs.o \
  158. X        lex.o \
  159. X        listsubs.o \
  160. X        main.o \
  161. X        mathsubs.o \
  162. X        parse.o \
  163. X        varsubs.o \
  164. X        xalloc.o
  165. X
  166. XHDRS          = exec.h \
  167. X        goto.h \
  168. X        spin.h \
  169. X        spinparse.h \
  170. X        xalloc.h
  171. X
  172. XSHARETC = Post.note README $(ROOTNAME).3 TODO cont.sp
  173. X
  174. XSHARSRCS = $(SHARETC) $(SRCS) $(HDRS) $(MAKEFILE)
  175. X
  176. XEXTHDRS          = /usr/include/ctype.h \
  177. X        /usr/include/setjmp.h \
  178. X        /usr/include/stdio.h
  179. X
  180. XLIBS          =
  181. X
  182. XXLINTLIBS      =
  183. X
  184. Xdefault:    $(PROGRAM)
  185. X
  186. Xlib:        $(LIBRARY)
  187. X
  188. Xlibrary:    $(LIBRARY)
  189. X
  190. Xlintlib:    $(LINTLIB)
  191. X
  192. Xshar:        $(SHARFILE)
  193. X
  194. Xclash:;        $(CLASH) $(HDRS) $(LINTSRCS)
  195. X
  196. Xall:        $(PROGRAM) $(LINTLIB)
  197. X
  198. X$(PROGRAM):    main.o $(LIBRARY)
  199. X        @echo -n "Loading $(PROGRAM) ... "
  200. X        @rm -f $(PROGRAM)
  201. X        @$(LINKER) $(CFLAGS) main.o $(LIBRARY) -o $(PROGRAM).new
  202. X        @mv -f $(PROGRAM).new $(PROGRAM)
  203. X        @echo "done"
  204. X
  205. X$(LIBRARY):    $(OBJS)
  206. X        @echo -n "Loading $(LIBRARY) ... "
  207. X        @ar cru $(LIBRARY) $(LIBOBJS)
  208. X        @ranlib $(LIBRARY)
  209. X        @echo "done"
  210. X
  211. X$(LINTLIB):    $(SRCS)
  212. X        lint -C$(LIBRARY) $(LINTFLAGS) $(LINTSRCS)
  213. X
  214. Xman:        $(ROOTNAME).3
  215. X        nroff -man $(ROOTNAME).3 > $(ROOTNAME).man.new
  216. X        mv $(ROOTNAME).man.new $(ROOTNAME).man
  217. X
  218. X$(SHARFILE):    $(SHARSRCS)
  219. X        $(SHAR) $(SHARSRCS) > $(SHARFILE)
  220. X
  221. Xinstall:    $(PROGRAM)
  222. X        @echo Installing $(PROGRAM) in $(DEST)
  223. X        @install -m 770 -c $(PROGRAM) $(DEST)
  224. X
  225. Xdepend:        $(XDEP)
  226. X        @echo Updating $(MAKEFILE) ...
  227. X        @$(MKMF) -f $(MAKEFILE) \
  228. X            CFLAGS='$$(CCOPTS) $(INCLUDE)'
  229. X# PROGRAM makes mkmf use p.Makefile template
  230. X#            PROGRAM=$(PROGRAM)
  231. X
  232. Xlint:;        lint $(LINTFLAGS) $(LINTSRCS) $(LINTLIBS)
  233. X
  234. Xtidy:;        @rm -f $(OBJS)
  235. X
  236. Xclean:        tidy
  237. X        @rm -f $(PROGRAM) $(LIBRARY)
  238. X
  239. Xprint:;        @pr $(SRCS) $(HDRS)
  240. X
  241. Xtags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
  242. X
  243. Xbackup:;    tar cf - $(HDRS) $(SRCS) $(MAKEFILE) | \
  244. X            rsh $(BKPMACH) 'cd $(BKPDIR); tar xBf -'
  245. X
  246. Xlex.o: spin.h spinparse.h xalloc.h
  247. X
  248. X###
  249. Xcontsubs.o: /usr/include/stdio.h xalloc.h spin.h exec.h
  250. Xexec.o: /usr/include/stdio.h /usr/include/ctype.h goto.h \
  251. X    /usr/include/setjmp.h xalloc.h spin.h spinparse.h exec.h
  252. Xfilesubs.o: /usr/include/stdio.h goto.h /usr/include/setjmp.h spin.h \
  253. X    xalloc.h
  254. Xgoto.o: goto.h /usr/include/setjmp.h xalloc.h
  255. Xinitsubs.o: spin.h
  256. Xlistsubs.o: xalloc.h spin.h
  257. Xmain.o: /usr/include/stdio.h xalloc.h
  258. Xmathsubs.o: spin.h
  259. Xparse.o: /usr/include/stdio.h /usr/include/ctype.h goto.h \
  260. X    /usr/include/setjmp.h xalloc.h spin.h spinparse.h
  261. Xvarsubs.o: xalloc.h spin.h
  262. Xxalloc.o: /usr/include/stdio.h
  263. END_OF_FILE
  264. if test 3439 -ne `wc -c <'Makefile'`; then
  265.     echo shar: \"'Makefile'\" unpacked with wrong size!
  266. fi
  267. # end of 'Makefile'
  268. fi
  269. if test -f 'README' -a "${1}" != "-c" ; then 
  270.   echo shar: Will not clobber existing file \"'README'\"
  271. else
  272. echo shar: Extracting \"'README'\" \(1289 characters\)
  273. sed "s/^X//" >'README' <<'END_OF_FILE'
  274. XThe SPIN Library                 1.Mar.88
  275. XWritten by Jim McBeath (jimmc) at SCI
  276. X
  277. XThis is version 1.0 of SPIN, a Simple Programmable INterface.
  278. XIt is intended to make life easier when developing programs;
  279. Xit is not commercial quality, but should be modular enough that
  280. Xany competent programmer can incrementally improve those parts
  281. Xof it which suit his needs.
  282. X
  283. XFiles of interest:
  284. X    *.[ch]    The source files for spin.
  285. X    Makefile    Exactly that.
  286. X    README    What you are looking at right now.
  287. X    spin.3    Source for man page.  Describes (briefly) what
  288. X        spin is all about.
  289. X        Use "make man" to create spin man file (spin.man).
  290. X    cont.sp    A sample spin file.
  291. X
  292. XWhat to do (after unpacking):
  293. X1. Use "make man" to create spin.man from spin.3.  Read it.
  294. X2. Make the library and program by doing a simple "make".
  295. X3. Test the program (spin) by running it and issuing the following commands
  296. X   (you type in the stuff on the lines after the ">" prompt):
  297. X    >SPversion
  298. X    STRING spin v1.0 1.Mar.88
  299. X    >plus 1 2
  300. X    add 1 2
  301. X    INT 3
  302. X    >strcat foo ".bar"
  303. X    STRING foo.bar
  304. X    >quit
  305. X4. Make the lint library (for other programs) by doing "make lintlib".
  306. X   You are now ready to link other programs with spin.
  307. X5. Send me your comments, wishes, and improvements.
  308. X
  309. X        -Jim McBeath  {decwrl|oliveb|weitek|auspyr}!sci!jimmc
  310. X          1.Mar.1988
  311. X
  312. END_OF_FILE
  313. if test 1289 -ne `wc -c <'README'`; then
  314.     echo shar: \"'README'\" unpacked with wrong size!
  315. fi
  316. # end of 'README'
  317. fi
  318. if test -f 'TODO' -a "${1}" != "-c" ; then 
  319.   echo shar: Will not clobber existing file \"'TODO'\"
  320. else
  321. echo shar: Extracting \"'TODO'\" \(345 characters\)
  322. sed "s/^X//" >'TODO' <<'END_OF_FILE'
  323. X 1.Mar.88
  324. X
  325. X- Make SPescape truly varargs
  326. X- Write a routine to scan command line switches and remove recognized ones?
  327. X- Decide how lists are allocated
  328. X- reexamine arg and return code characters and meanings
  329. X- clean up memory management; there are many memory leaks.
  330. X   how about garbage collection for tokens and strings?
  331. X- improve documentation
  332. END_OF_FILE
  333. if test 345 -ne `wc -c <'TODO'`; then
  334.     echo shar: \"'TODO'\" unpacked with wrong size!
  335. fi
  336. # end of 'TODO'
  337. fi
  338. if test -f 'cont.sp' -a "${1}" != "-c" ; then 
  339.   echo shar: Will not clobber existing file \"'cont.sp'\"
  340. else
  341. echo shar: Extracting \"'cont.sp'\" \(1326 characters\)
  342. sed "s/^X//" >'cont.sp' <<'END_OF_FILE'
  343. X/* Some control structures to test spin */
  344. X
  345. Xdefine while (\
  346. X    (fset c (argquote 1))\
  347. X    (fset e (argquote 2))\
  348. X(label begin)\
  349. X    (if (eval (get c))\
  350. X        (goto ok))\
  351. X    (goto end)\
  352. X(label ok)\
  353. X    (eval (get e))\
  354. X    (goto begin)\
  355. X(label end)\
  356. X)
  357. X
  358. Xdefine until (\
  359. X    (fset c (argquote 1))\
  360. X    (fset e (argquote 2))\
  361. X(label begin)\
  362. X    (if (eval (get c))\
  363. X        (goto end))\
  364. X    (eval (get e))\
  365. X    (goto begin)\
  366. X(label end)\
  367. X)
  368. X
  369. Xdefine do (\
  370. X    (fset e (argquote 1))\
  371. X    (fset k (argquote 2))\
  372. X    (fset c (argquote 3))\
  373. X(label begin)\
  374. X    (eval (get e))\
  375. X    (if (streq "while" (get k)) (goto dowhile))\
  376. X/* dountil */\
  377. X    (if (eval (get c)) (goto done))\
  378. X    (goto begin)\
  379. X(label dowhile)\
  380. X    (if (eval (get c)) (goto begin))\
  381. X(label done)\
  382. X)
  383. X
  384. Xdefine testwhile (\
  385. X    (fset a (argeval 1))\
  386. X    (fset b (argeval 2))\
  387. X    (while (igr (get b) (get a)) (\
  388. X        (print (get a))\
  389. X        (set a (plus 1 (get a)))\
  390. X    ))\
  391. X)
  392. X
  393. Xdefine testuntil (\
  394. X    (fset a (argeval 1))\
  395. X    (fset b (argeval 2))\
  396. X    (until (igr (get a) (get b)) (\
  397. X        (print (get a))\
  398. X        (set a (plus 1 (get a)))\
  399. X    ))\
  400. X)
  401. X
  402. Xdefine testdountil (\
  403. X    (fset a (argeval 1))\
  404. X    (fset b (argeval 2))\
  405. X    (do (\
  406. X        (print (get a))\
  407. X        (set a (plus 1 (get a)))\
  408. X    ) until (igr (get a) (get b)))\
  409. X)
  410. X
  411. Xdefine testdowhile (\
  412. X    (fset a (argeval 1))\
  413. X    (fset b (argeval 2))\
  414. X    (do (\
  415. X        (print (get a))\
  416. X        (set a (plus 1 (get a)))\
  417. X    ) while (igr (get b) (get a)))\
  418. X)
  419. X
  420. X/* end */
  421. END_OF_FILE
  422. if test 1326 -ne `wc -c <'cont.sp'`; then
  423.     echo shar: \"'cont.sp'\" unpacked with wrong size!
  424. fi
  425. # end of 'cont.sp'
  426. fi
  427. if test -f 'contsubs.c' -a "${1}" != "-c" ; then 
  428.   echo shar: Will not clobber existing file \"'contsubs.c'\"
  429. else
  430. echo shar: Extracting \"'contsubs.c'\" \(3543 characters\)
  431. sed "s/^X//" >'contsubs.c' <<'END_OF_FILE'
  432. X/* contsubs.c - control structure subroutines for spin
  433. X *
  434. X * 16.Oct.87  jimmc  Initial definition
  435. X * 21.Oct.87  jimmc  Add func and args stuff
  436. X * 30.Nov.87  jimmc  Lint cleanup
  437. X */
  438. X/* LINTLIBRARY */
  439. X
  440. X#include <stdio.h>
  441. X#include "xalloc.h"
  442. X#include "spin.h"
  443. X#include "exec.h"
  444. X
  445. Xstruct funcargs {
  446. X    struct funcargs *up;
  447. X    int num;    /* number of args */
  448. X    SPtoken **val;    /* the args (pointer to array of pointers) */
  449. X    SPtoken *vallist;
  450. X};
  451. Xstruct funcargs *curargs;
  452. X
  453. Xextern SPtoken *SPexec();
  454. X
  455. XSPtoken *
  456. Xsp_if(test,truecode,falsecode)
  457. Xint test;    /* the value to test */
  458. XSPtoken *truecode;    /* execute this if true */
  459. XSPtoken *falsecode;    /* execute this is false */
  460. X{
  461. X    if (test) {
  462. X        return SPexec(truecode);
  463. X    }
  464. X    else {
  465. X        return SPexec(falsecode);
  466. X    }
  467. X}
  468. X
  469. Xvoid
  470. Xsp_exit(code)
  471. Xint code;
  472. X{
  473. X/*** should allow programs to set up exit routines which are called
  474. X * before the exit is actually done, or which may abort the exit.
  475. X */
  476. X    exit(code);
  477. X}
  478. X
  479. Xchar *
  480. Xsp_priminfo(name)
  481. Xchar *name;
  482. X{
  483. XSPfuncinfo *finfo, *SPfindfunc();
  484. X
  485. X    finfo = SPfindfunc(name);
  486. X    if (!finfo) return NIL;
  487. X    return finfo->args;
  488. X}
  489. X
  490. Xvoid
  491. Xsp_define(name,list)
  492. Xchar *name;
  493. XSPtoken *list;
  494. X{
  495. Xextern SPtoken *sp_fset();
  496. X
  497. X    (void)sp_fset(name,list);
  498. X}
  499. X
  500. Xint    /* 1 if we found and executed the function */
  501. Xsp_xexec(name,args,rval)
  502. Xchar *name;    /* name of the function to execute */
  503. XSPtoken *args;    /* the args to that function */
  504. XSPtoken *rval;    /* the token in which to return the value of the func */
  505. X{
  506. XSPtoken *fval, *sp_fget(), *rrval, *SPexec();
  507. Xstruct funcargs fargs;
  508. Xint n;
  509. XSPtoken* tk;
  510. X
  511. X    fval = sp_fget(name);    /* see if we have it */
  512. X    if (!fval) return 0;    /* not found */
  513. X    for (n=0,tk=args; tk; tk=tk->next) n++;    /* count args */
  514. X    fargs.num = n;
  515. X    if (n>0) fargs.val = XALLOC(SPtoken *,n);
  516. X    for (n=0,tk=args; tk; tk=tk->next) fargs.val[n++]=tk;
  517. X    fargs.vallist = NIL;
  518. X    fargs.up = curargs;
  519. X    curargs = &fargs;
  520. X    rrval = SPexec(fval);    /* execute the function (just a list!) */
  521. X        /*** not much argument checking here! */
  522. X    if (rrval) *rval = *rrval;
  523. X    else rval->type = SPTokNil;
  524. X    if (n>0) XFREE(fargs.val);
  525. X    curargs = fargs.up;
  526. X    return 1;        /* we got it OK */
  527. X}
  528. X
  529. XSPtoken *
  530. Xsp_argquote(argnum)
  531. Xint argnum;
  532. X{
  533. X    if (!curargs || argnum<1 || argnum>curargs->num) return NIL;
  534. X    return curargs->val[argnum-1];
  535. X}
  536. X
  537. XSPtoken *
  538. Xsp_argeval(argnum)
  539. Xint argnum;
  540. X{
  541. X    if (!curargs || argnum<1 || argnum>curargs->num) return NIL;
  542. X    return SPexec(curargs->val[argnum-1]);
  543. X}
  544. X
  545. Xstatic
  546. Xsp_makevallist()
  547. X{
  548. X    ALLOCTOKEN(curargs->vallist)
  549. X    curargs->vallist->type = SPTokList;
  550. X    curargs->vallist->value.l = curargs->val[0];
  551. X    curargs->vallist->next = NIL;
  552. X}
  553. X
  554. XSPtoken *
  555. Xsp_arglistquote()
  556. X{
  557. X    if (!curargs) return NIL;
  558. X    if (!curargs->vallist) sp_makevallist();
  559. X    return curargs->vallist;
  560. X}
  561. X
  562. XSPtoken *
  563. Xsp_arglisteval()
  564. X{
  565. XSPtoken *list, *tk, *newtk, **prevtkp, *SPnewnil();
  566. X
  567. X    if (!curargs) return NIL;
  568. X    if (!curargs->vallist) sp_makevallist();
  569. X    ALLOCTOKEN(list)
  570. X    list->type = SPTokList;
  571. X    list->next = NIL;
  572. X    prevtkp = &list->value.l;
  573. X    for (tk=curargs->vallist->value.l; tk; tk=tk->next) {
  574. X        newtk = SPexec(tk);
  575. X        if (!newtk) newtk = SPnewnil();
  576. X        *prevtkp = newtk;
  577. X        prevtkp = &newtk->next;
  578. X    }
  579. X    *prevtkp = NIL;
  580. X    return list;
  581. X}
  582. X
  583. XSPinitcont()
  584. X{
  585. X    SPdeffunc("if","lbLL",sp_if);
  586. X    SPdeffunc("exit","vI0",sp_exit);
  587. X    SPdeffunc("quit","vI0",sp_exit);    /* synonym for exit */
  588. X    SPdeffunc("define","vnL",sp_define);
  589. X    SPdeffunc("argquote","li",sp_argquote);
  590. X    SPdeffunc("argeval","Li",sp_argeval);
  591. X    SPdeffunc("arglistquote","l",sp_arglistquote);
  592. X    SPdeffunc("arglisteval","L",sp_arglisteval);
  593. X    SPdeffunc("priminfo","sn",sp_priminfo);
  594. X    SPsetxexecp(sp_xexec);
  595. X}
  596. X
  597. X/* end */
  598. END_OF_FILE
  599. if test 3543 -ne `wc -c <'contsubs.c'`; then
  600.     echo shar: \"'contsubs.c'\" unpacked with wrong size!
  601. fi
  602. # end of 'contsubs.c'
  603. fi
  604. if test -f 'exec.h' -a "${1}" != "-c" ; then 
  605.   echo shar: Will not clobber existing file \"'exec.h'\"
  606. else
  607. echo shar: Extracting \"'exec.h'\" \(256 characters\)
  608. sed "s/^X//" >'exec.h' <<'END_OF_FILE'
  609. X/* exec.h - stuff for spin execution
  610. X *
  611. X */
  612. X
  613. Xtypedef struct _SPfuncinfo {
  614. X    char *name;        /* name of the function */
  615. X    char *args;        /* return ard arg types */
  616. X    void (*funcp)();    /* pointer to the function */
  617. X    struct _SPfuncinfo *next;
  618. X} SPfuncinfo;
  619. X
  620. X/* end */
  621. END_OF_FILE
  622. if test 256 -ne `wc -c <'exec.h'`; then
  623.     echo shar: \"'exec.h'\" unpacked with wrong size!
  624. fi
  625. # end of 'exec.h'
  626. fi
  627. if test -f 'filesubs.c' -a "${1}" != "-c" ; then 
  628.   echo shar: Will not clobber existing file \"'filesubs.c'\"
  629. else
  630. echo shar: Extracting \"'filesubs.c'\" \(1271 characters\)
  631. sed "s/^X//" >'filesubs.c' <<'END_OF_FILE'
  632. X/* filesubs.c - file subroutines for spin
  633. X *
  634. X * 20.Oct.87  jimmc  Initial definition
  635. X *  4.Nov.87  jimmc  Add print
  636. X *  5.Nov.87  jimmc  Add setjmp stuff in sourcefile
  637. X * 30.Nov.87  jimmc  Lint cleanup
  638. X */
  639. X/* LINTLIBRARY */
  640. X
  641. X#include <stdio.h>
  642. X#include "goto.h"
  643. X#include "spin.h"
  644. X#include "xalloc.h"
  645. X
  646. Xint            /* 0 if no errors */
  647. Xsp_sourcefile(filename)
  648. Xchar *filename;
  649. X{
  650. XSPtoken *rval, *SPparsefile();
  651. XFILE *fp;
  652. Xjmp_buf jbuf;
  653. Xjmp_bufp oldbufp;
  654. X
  655. X    fp = fopen(filename,"r");
  656. X    if (!fp) {
  657. X        SPescape("CantOpenFile","can't open file %s",filename);
  658. X        /* NOTREACHED */
  659. X    }
  660. X    oldbufp = SPjbufp;
  661. X    SPjbufp = jmpbuf_addr(jbuf);
  662. X    if (setjmp(jbuf)) {    /* got an error while processing */
  663. X        fclose(fp);    /* close the file */
  664. X        SPjbufp = oldbufp;
  665. X        longjmp(jmpbuf_ref(SPjbufp),1);    /* continue up */
  666. X        /* NOTREACHED */
  667. X    }
  668. X    rval = SPparsefile(fp);
  669. X    fclose(fp);
  670. X    FREETOKENLIST(rval)
  671. X    SPjbufp = oldbufp;
  672. X    return 0;
  673. X}
  674. X
  675. Xint            /* 0 if no errors */
  676. Xsp_sourcestring(string)
  677. Xchar *string;
  678. X{
  679. XSPtoken *rval, *SPparsestring();
  680. X
  681. X    rval = SPparsestring(string);
  682. X    FREETOKENLIST(rval)
  683. X    return 0;
  684. X}
  685. X
  686. Xsp_print(v)
  687. XSPtoken *v;
  688. X{
  689. X    SPprintval(stdout,v,0);
  690. X}
  691. X
  692. XSPinitfile()
  693. X{
  694. X    SPdeffunc("sourcefile","is",sp_sourcefile);
  695. X    SPdeffunc("sourcestring","is",sp_sourcestring);
  696. X    SPdeffunc("print","vV",sp_print);
  697. X}
  698. X
  699. X/* end */
  700. END_OF_FILE
  701. if test 1271 -ne `wc -c <'filesubs.c'`; then
  702.     echo shar: \"'filesubs.c'\" unpacked with wrong size!
  703. fi
  704. # end of 'filesubs.c'
  705. fi
  706. if test -f 'goto.c' -a "${1}" != "-c" ; then 
  707.   echo shar: Will not clobber existing file \"'goto.c'\"
  708. else
  709. echo shar: Extracting \"'goto.c'\" \(1742 characters\)
  710. sed "s/^X//" >'goto.c' <<'END_OF_FILE'
  711. X/* goto.c - subroutines used in goto (also for error goto)
  712. X *
  713. X *  4.Nov.87  jimmc  Initial definition
  714. X * 30.Nov.87  jimmc  Lint cleanup
  715. X */
  716. X/* LINTLIBRARY */
  717. X
  718. X#include <strings.h>
  719. X#include "goto.h"
  720. X#include "xalloc.h"
  721. X
  722. Xextern char *sprintf();    /* make lint happy */
  723. X
  724. Xjmp_bufp SPjbufp;
  725. Xchar *SPgotolabel;
  726. Xchar *SPerrorstr;
  727. X
  728. XSPgoto(label)
  729. Xchar *label;
  730. X{
  731. X    if (SPgotolabel) XFREE(SPgotolabel);
  732. X    SPgotolabel = XALLOC(char,strlen(label)+1);
  733. X    strcpy(SPgotolabel,label);
  734. X    longjmp(jmpbuf_ref(SPjbufp),1);
  735. X    /* NOTREACHED */
  736. X}
  737. X
  738. X/* ARGSUSED */
  739. Xvoid
  740. XSPlabel(label)    /* labels are actually handled in SPexeclist */
  741. Xchar *label;
  742. X{
  743. X    ;    /* no value for a label statement */
  744. X}
  745. X
  746. Xchar *
  747. XSPerrorinfo(info)
  748. Xchar *info;
  749. X{
  750. Xint l;
  751. Xchar *newerrorstr;
  752. X
  753. X    if (!info) return SPerrorstr;
  754. X    if (info[0]=='+') {
  755. X        if (SPerrorstr) l = strlen(SPerrorstr)+strlen(info+1)+1;
  756. X        else l = strlen(info+1)+1;
  757. X        newerrorstr = XALLOC(char,l);
  758. X        if (SPerrorstr) strcpy(newerrorstr,SPerrorstr);
  759. X        else newerrorstr[0]=0;
  760. X        strcat(newerrorstr,info+1);
  761. X    }
  762. X    else {
  763. X        l = strlen(info)+1;
  764. X        newerrorstr = XALLOC(char,l);
  765. X        strcpy(newerrorstr,info);
  766. X    }
  767. X    if (SPerrorstr) XFREE(SPerrorstr);
  768. X    SPerrorstr = newerrorstr;
  769. X    return SPerrorstr;
  770. X}
  771. X
  772. X/* SPescape is an internal function used to deal with errors */
  773. X/* VARARGS2 */
  774. XSPescape(label,fmt,arg1,arg2)
  775. Xchar *label;        /* label to go to */
  776. Xchar *fmt;        /* printf-style format for error info */
  777. Xchar *arg1,*arg2;        /* first of printf-style args */
  778. X{
  779. Xchar buf[2000];
  780. X
  781. X/*** this needs to be fixed up to be truly variable number of args */
  782. X    sprintf(buf,fmt,arg1,arg2);
  783. X    SPerrorinfo(buf);
  784. X    SPgoto(label);
  785. X    /* NOTREACHED */
  786. X}
  787. X
  788. XSPinitgoto()
  789. X{
  790. X    SPdeffunc("goto","vs",SPgoto);
  791. X    SPdeffunc("label","vs",SPlabel);
  792. X    SPdeffunc("errorinfo","sSN",SPerrorinfo);
  793. X}
  794. X
  795. X/* end */
  796. END_OF_FILE
  797. if test 1742 -ne `wc -c <'goto.c'`; then
  798.     echo shar: \"'goto.c'\" unpacked with wrong size!
  799. fi
  800. # end of 'goto.c'
  801. fi
  802. if test -f 'goto.h' -a "${1}" != "-c" ; then 
  803.   echo shar: Will not clobber existing file \"'goto.h'\"
  804. else
  805. echo shar: Extracting \"'goto.h'\" \(481 characters\)
  806. sed "s/^X//" >'goto.h' <<'END_OF_FILE'
  807. X/* goto.h - things required to use the setjmp stuff in SP
  808. X *
  809. X *  4.Nov.87  jimmc  Initial definition
  810. X */
  811. X
  812. X#include <setjmp.h>
  813. X
  814. X/* The fact that jmp_buf is so hazily defined makes it difficult to
  815. X * deal with pointers to jmp_bufs, etc.  The following code assumes
  816. X * that a jmp_buf is an array of ints, so it may be machine dependent.
  817. X */
  818. X
  819. Xtypedef int *jmp_bufp;
  820. X
  821. Xextern jmp_bufp SPjbufp;
  822. Xextern char *SPgotolabel;
  823. X
  824. X#define jmpbuf_addr(jb) jb
  825. X#define jmpbuf_ref(jbp) jbp
  826. X
  827. X/* end */
  828. END_OF_FILE
  829. if test 481 -ne `wc -c <'goto.h'`; then
  830.     echo shar: \"'goto.h'\" unpacked with wrong size!
  831. fi
  832. # end of 'goto.h'
  833. fi
  834. if test -f 'initsubs.c' -a "${1}" != "-c" ; then 
  835.   echo shar: Will not clobber existing file \"'initsubs.c'\"
  836. else
  837. echo shar: Extracting \"'initsubs.c'\" \(759 characters\)
  838. sed "s/^X//" >'initsubs.c' <<'END_OF_FILE'
  839. X/* initsubs.c - this routine pulls in all of the standard spin subroutine
  840. X * packages which are available.
  841. X *
  842. X * 16.Oct.87  jimmc  Initial definition
  843. X *  4.Nov.87  jimmc  Add call to SPinitgoto
  844. X *  5.Nov.87  jimmc  Add call to SPinitmath
  845. X * 30.Nov.87  jimmc  Lint cleanup
  846. X *  1.Mar.88  jimmc  Add SPversion
  847. X */
  848. X/* LINTLIBRARY */
  849. X
  850. Xstatic char *SPversion_string = "spin v1.0 1.Mar.88";
  851. X
  852. X#include "spin.h"
  853. X
  854. Xchar *
  855. XSPversion()
  856. X{
  857. X    return SPversion_string;
  858. X}
  859. X
  860. XSPinitsubs()
  861. X{
  862. X    SPdeffunc("SPversion","s",SPversion);
  863. X
  864. X    SPinitgoto();    /* labels and goto */
  865. X    SPinitmath();    /* math operators */
  866. X    SPinitcont();    /* control flow */
  867. X    SPinitvars();    /* variables and function definitions */
  868. X    SPinitlist();    /* list operations */
  869. X    SPinitfile();    /* file operations */
  870. X}
  871. X
  872. X/* end */
  873. END_OF_FILE
  874. if test 759 -ne `wc -c <'initsubs.c'`; then
  875.     echo shar: \"'initsubs.c'\" unpacked with wrong size!
  876. fi
  877. # end of 'initsubs.c'
  878. fi
  879. if test -f 'lex.l' -a "${1}" != "-c" ; then 
  880.   echo shar: Will not clobber existing file \"'lex.l'\"
  881. else
  882. echo shar: Extracting \"'lex.l'\" \(4639 characters\)
  883. sed "s/^X//" >'lex.l' <<'END_OF_FILE'
  884. X    /* lex - lex routines for spin
  885. X     *
  886. X     * 16.Oct.87  jimmc  Initial definition (taken from ilet)
  887. X     * 21.Oct.87  jimmc  Add NIL token
  888. X     */
  889. X
  890. X    /* definitions */
  891. X
  892. XD    [0-9]
  893. XE       [Ee][+-]?{D}+
  894. XO    [0-7]
  895. XH    [0-9A-Fa-f]
  896. XS    [A-Za-z]
  897. Xs    [A-Za-z0-9_]
  898. XW    [ \t\n\f]
  899. Xw    [ \t\f]
  900. Xx    [Xx]
  901. X
  902. X%{
  903. X#include <ctype.h>
  904. X#include <stdio.h>
  905. X#include "spin.h"
  906. X#include "spinparse.h"
  907. X#include "xalloc.h"
  908. X
  909. X#undef input
  910. X#undef output
  911. X#undef unput
  912. X
  913. X/* a macro to aid debugging */
  914. X/* #define RETURN(c) {printf("token %s\n","c");return(c);} */
  915. X#define RETURN(c) return(c)
  916. X
  917. X#define malform()   {SPwerror("bad character formation"); \
  918. X            SPtokenpval = ""; RETURN(SPTokStr); }
  919. X#define collect()   {while(c != '\'' && c != '\n' && c != ';') c = input(); \
  920. X                     unput('\n');}
  921. X
  922. Xchar *SPtokenpval;
  923. Xint SPtokenival;
  924. Xfloat SPtokenfval;
  925. X
  926. X%}
  927. X    /* rules follow the next %% */
  928. X%%
  929. X
  930. X"/*"        { for (;;) {    /* slash-star starts comments */
  931. X                int c;
  932. X                if ((c=input())==0) break;    /* EOF */
  933. X                if (c=='*') {
  934. X                    if ((c=input())=='/') break;
  935. X                    /* end of comment */
  936. X                    else unput(c);
  937. X                    }
  938. X                /* continue eating comment */
  939. X                }
  940. X              /* now the comment has been eaten */
  941. X              yyleng = 0; yymore(); }
  942. X\"        {  /* character string */  /* taken from LISCH1 */
  943. X                register int c ;
  944. X
  945. X                for(yyleng = 0; c = input(); ++yyleng) {
  946. X                switch(c) {
  947. X                case '\\':
  948. X                    if ((c = input()) == '\n')
  949. X                    --yyleng ;
  950. X                    else {
  951. X                    unput(c) ;
  952. X                    yytext[yyleng] = backslash() ;
  953. X                    }
  954. X                    break ;
  955. X                case '\n':
  956. X                    SPwerror("bad string format");
  957. X                    unput('\n') ;
  958. X                    /* fall through */
  959. X                case '"':
  960. X                    yytext[yyleng] = '\0' ;
  961. X                    goto break2 ;
  962. X                default:
  963. X                    if (isprint(c))
  964. X                    yytext[yyleng] = c;
  965. X                    else
  966. X                    SPwerror("bad char in string (%3o)",c);
  967. X                    break ;
  968. X                }
  969. X                }
  970. X            break2:
  971. X                SPtokenpval = yytext;
  972. X                RETURN(SPTokStr);
  973. X            }
  974. X"0"{x}{H}+    { sscanf( yytext+2, "%x", &SPtokenival);  RETURN(SPTokInt);}
  975. X"0"([oO])?{O}+    { sscanf( yytext, "%o", &SPtokenival); RETURN(SPTokInt); }
  976. X"0"[oO]{D}+    { SPwerror("bad octal integer");
  977. X              SPtokenival = 0; RETURN(SPTokInt); }
  978. X{D}+        { sscanf( yytext, "%d", &SPtokenival); RETURN(SPTokInt); }
  979. X{D}+"."{D}*({E})?    |
  980. X{D}*"."{D}+({E})?    |
  981. X{D}+{E}        { sscanf( yytext, "%f", &SPtokenfval); RETURN(SPTokFloat); }
  982. X{W}+        { /* ignore white space */ }
  983. X"NIL"        { RETURN(SPTokNil); }
  984. X{S}{s}*        { SPtokenpval = yytext; RETURN(SPTokName); }
  985. X"("        { RETURN(SPTokLP); }
  986. X")"        { RETURN(SPTokRP); }
  987. X";"        { RETURN(SPTokSM); }
  988. X"."|[^.]        { illchar("in input"); }
  989. X
  990. X%%
  991. X
  992. X/* user subroutines */
  993. X/* we are supplying our own input routines */
  994. X
  995. Xchar cstack[256];    /* the unput buffer */
  996. Xint ccount;        /* number of chars in the unput buffer */
  997. Xint cindex;        /* index into input line buffer array */
  998. Xchar *cinline;        /* the input line buffer */
  999. X
  1000. XSPlexinit(info)
  1001. XSPstreaminfo *info;
  1002. X{
  1003. X    cindex=0;
  1004. X    cinline = info->SPlinebuf;
  1005. X    ccount = 0;
  1006. X}
  1007. X
  1008. Xstatic
  1009. Xinput()
  1010. X{
  1011. X    int c;
  1012. X
  1013. X    if (ccount>0) {
  1014. X        c = cstack[--ccount];
  1015. X            /* these are chars pushed back with unput */
  1016. X    }
  1017. X    else {        /* no lookahead, get a new char */
  1018. X        c = cinline[cindex++];
  1019. X        if (c==0) cindex--;
  1020. X    }
  1021. X    return c;
  1022. X}
  1023. X
  1024. X/*..........*/
  1025. X
  1026. Xunput(c)
  1027. Xchar c;
  1028. X{
  1029. X
  1030. X    if ((cindex>0)&&(c==cinline[cindex-1])) {
  1031. X        /* see if he is putting back the most recent char */
  1032. X        cindex--;    /* just back up the pointer and counter */
  1033. X    }
  1034. X    else    /*** should check for overflow */
  1035. X        cstack[ccount++] = c;        /* stack up the char */
  1036. X}
  1037. X
  1038. X/*..........*/
  1039. X
  1040. Xoutput(c)
  1041. X{
  1042. X    /* this should never be called */
  1043. X    SPwerror("compiler error: 'output' called with arg %3o",c);
  1044. X}
  1045. X
  1046. X/*..........*/
  1047. X
  1048. Xillchar(s)
  1049. Xchar *s;
  1050. X{
  1051. X    char c;
  1052. X
  1053. X    c = yytext[yyleng-1];
  1054. X    if (isprint(c)) SPwerror("illegal char '%c' %s", c, s);
  1055. X        /* printable chars */
  1056. X    else SPwerror("illegal char %03o %s", c, s);
  1057. X        /* non-printing chars */
  1058. X}
  1059. X
  1060. Xyywrap() { 
  1061. X    return 1; 
  1062. X}
  1063. X
  1064. Xbackslash()    /* taken from LISCH1 */
  1065. X{
  1066. X    register int c ;
  1067. X
  1068. X    switch(c = input()) {
  1069. X    case '\\':  
  1070. X        return('\\') ;
  1071. X    case 'b':   
  1072. X        return('\b') ;
  1073. X    case 'e':   
  1074. X        return('\033') ;        /* escape */
  1075. X    case 'f':   
  1076. X        return('\f') ;
  1077. X    case 'n':   
  1078. X        return('\n') ;
  1079. X    case 'r':   
  1080. X        return('\r') ;
  1081. X    case 't':   
  1082. X        return('\t') ;
  1083. X    case 'v':   
  1084. X        return('\013') ;        /* vertical tab */
  1085. X    case '"':   
  1086. X        return('"') ;
  1087. X    case '\'':  
  1088. X        return('\'') ;
  1089. X    case '^':
  1090. X        c = input() ;
  1091. X        if (isprint(c))
  1092. X            return(c & ~0140) ;
  1093. X                /* convert to control char range */
  1094. X        else {
  1095. X            unput(c) ;
  1096. X            return('^') ;
  1097. X        }
  1098. X    default:
  1099. X        if (! isdigit(c))
  1100. X            return(c) ;
  1101. X        else {
  1102. X            int i, n ;
  1103. X            char buf[4] ;
  1104. X
  1105. X            buf[0] = c ;
  1106. X            for (i = 1; i < 3; i++)
  1107. X                if (! isdigit(buf[i] = input())) {
  1108. X                    unput(buf[i]) ;
  1109. X                    break ;
  1110. X                }
  1111. X            buf[i] = '\0' ;
  1112. X            sscanf(buf, "%o", &n) ;
  1113. X            return(n) ;
  1114. X        }
  1115. X    }
  1116. X}
  1117. X
  1118. X/* end */
  1119. END_OF_FILE
  1120. if test 4639 -ne `wc -c <'lex.l'`; then
  1121.     echo shar: \"'lex.l'\" unpacked with wrong size!
  1122. fi
  1123. # end of 'lex.l'
  1124. fi
  1125. if test -f 'listsubs.c' -a "${1}" != "-c" ; then 
  1126.   echo shar: Will not clobber existing file \"'listsubs.c'\"
  1127. else
  1128. echo shar: Extracting \"'listsubs.c'\" \(1600 characters\)
  1129. sed "s/^X//" >'listsubs.c' <<'END_OF_FILE'
  1130. X/* listsubs.c - routines which deal with lists for spin
  1131. X *
  1132. X * 16.Oct.87  jimmc  Initial definition
  1133. X * 21.Oct.87  jimmc  Add eval function
  1134. X * 30.Nov.87  jimmc  Lint cleanup
  1135. X */
  1136. X/* LINTLIBRARY */
  1137. X
  1138. X#include "xalloc.h"
  1139. X#include "spin.h"
  1140. X
  1141. Xextern SPtoken *SPcopytoken(), *SPexec();
  1142. X
  1143. XSPtoken *
  1144. Xsp_quote(list)
  1145. XSPtoken *list;
  1146. X{
  1147. X    return SPcopytoken(list);
  1148. X}
  1149. X
  1150. XSPtoken *
  1151. Xsp_eval(list)
  1152. XSPtoken *list;
  1153. X{
  1154. X    return SPexec(list);
  1155. X}
  1156. X
  1157. XSPinitlist()
  1158. X{
  1159. X    SPdeffunc("quote","LL",sp_quote);
  1160. X    SPdeffunc("eval","LV",sp_eval);
  1161. X}
  1162. X
  1163. X
  1164. X/* convert an integer array into a list
  1165. X */
  1166. XSPtoken *
  1167. XSPiarrtolist(ac,av)
  1168. Xint ac;        /* size of integer array */
  1169. Xint *av;    /* array of integers to convert to a list */
  1170. X{
  1171. X    SPtoken *ap, *next, **app;
  1172. X    int i;
  1173. X
  1174. X    ALLOCTOKEN(ap)
  1175. X    ap->type = SPTokList;
  1176. X    ap->next = NIL;
  1177. X    app = &(ap->value.l);
  1178. X    for (i=0; i<ac; i++) {
  1179. X        ALLOCTOKEN(next)
  1180. X        next->type = SPTokInt;
  1181. X        next->value.n = av[i];
  1182. X        *app = next;
  1183. X        app = &(next->next);
  1184. X    }
  1185. X    *app = NIL;
  1186. X    return ap;
  1187. X}
  1188. X
  1189. X/* converts a list to an array of ints; mallocs the array and returns
  1190. X * a pointer to it.  The list must contain only ints.
  1191. X * On error, returns -1.
  1192. X */
  1193. Xint        /* returns size of array as value */
  1194. XSPlisttoiarr(ap,ipp)
  1195. XSPtoken *ap;
  1196. Xint **ipp;        /* pointer to array pointer for return value */
  1197. X{
  1198. X    int i,n;
  1199. X    int *ip;
  1200. X    SPtoken *np;
  1201. X
  1202. X    if (ap->type != SPTokList) return -1;
  1203. X    n = 0;        /* count the number of ints */
  1204. X    for (np=ap->value.l; np; np=np->next) {
  1205. X        if (np->type != SPTokInt) return -1;    /* must be all ints */
  1206. X        n++;
  1207. X    }
  1208. X    ip = XALLOC(int,n);
  1209. X    for (i=0, np=ap->value.l; i<n; i++, np=np->next) {
  1210. X        ip[i] = np->value.n;
  1211. X    }
  1212. X    *ipp = ip;
  1213. X    return n;
  1214. X}
  1215. X
  1216. X/* end */
  1217. END_OF_FILE
  1218. if test 1600 -ne `wc -c <'listsubs.c'`; then
  1219.     echo shar: \"'listsubs.c'\" unpacked with wrong size!
  1220. fi
  1221. # end of 'listsubs.c'
  1222. fi
  1223. if test -f 'main.c' -a "${1}" != "-c" ; then 
  1224.   echo shar: Will not clobber existing file \"'main.c'\"
  1225. else
  1226. echo shar: Extracting \"'main.c'\" \(1584 characters\)
  1227. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  1228. X/* main.c - test module and sample main program for spin
  1229. X *
  1230. X * 17.Oct.87  jimmc  Initial definition
  1231. X *  4.Nov.87  jimmc  Add ieq, igr, streq
  1232. X */
  1233. X
  1234. X#include <stdio.h>
  1235. X#include <strings.h>
  1236. X#include "xalloc.h"
  1237. X
  1238. X/* #define MINSPIN */
  1239. X/* define MINSPIN to get just the stripped down interpreter (in case
  1240. X * you are curious as to just how big it is).
  1241. X */
  1242. X
  1243. Xchar *Progname, *rindex();
  1244. X
  1245. Xmain(argc,argv)
  1246. Xint argc;
  1247. Xchar *argv[];
  1248. X{
  1249. Xint i,j;
  1250. Xchar *execval;
  1251. X
  1252. X    Progname=rindex(argv[0],'/');
  1253. X    if (Progname) Progname++; else Progname=argv[0];
  1254. X
  1255. X    m_init();
  1256. X#ifndef MINSPIN
  1257. X    SPinitsubs();
  1258. X#endif
  1259. X    for (i=1; i<argc; i++) {
  1260. X        if (argv[i][0]=='-') for (j=1; j>0&&argv[i][j]; j++) {
  1261. X            switch (argv[i][j]) {
  1262. X            case 'e':
  1263. X                execval = argv[++i];
  1264. X                j = -1;
  1265. X                break;
  1266. X            default:    break;    /* just ignore it */
  1267. X            }
  1268. X        }
  1269. X        /* ignore other stuff */
  1270. X    }
  1271. X    if (execval) { SPmainstring(execval); }
  1272. X    SPmainfile(stdin);
  1273. X    exit(0);
  1274. X}
  1275. X
  1276. Xint
  1277. Xm_plus(a,b)
  1278. Xint a,b;
  1279. X{
  1280. Xprintf("add %d %d\n", a, b);
  1281. X    return (a+b);
  1282. X}
  1283. X
  1284. Xint
  1285. Xm_strlen(s)
  1286. Xchar *s;
  1287. X{
  1288. X    if (!s) return NULL;
  1289. X    return strlen(s);
  1290. X}
  1291. X
  1292. Xchar *
  1293. Xm_strcat(a,b)
  1294. Xchar *a, *b;
  1295. X{
  1296. Xchar *r;
  1297. X
  1298. X    r = XALLOC(char,strlen(a)+strlen(b)+1);
  1299. X    strcpy(r,a);
  1300. X    strcat(r,b);
  1301. X    return r;
  1302. X}
  1303. X
  1304. Xint
  1305. Xm_streq(a,b)
  1306. Xchar *a,*b;
  1307. X{
  1308. X    return (strcmp(a,b)==0);
  1309. X}
  1310. X
  1311. Xint
  1312. Xm_ieq(a,b)
  1313. Xint a,b;
  1314. X{
  1315. X    return (a==b);
  1316. X}
  1317. X
  1318. Xint
  1319. Xm_igr(a,b)
  1320. Xint a,b;
  1321. X{
  1322. X    return (a>b);
  1323. X}
  1324. X
  1325. Xm_init()
  1326. X{
  1327. X    SPdeffunc("plus","iii;summand addend addend",m_plus);
  1328. X    SPdeffunc("strlen","iSN",m_strlen);
  1329. X    SPdeffunc("strcat","sS\"foo\"S\"bar\"",m_strcat);
  1330. X    SPdeffunc("streq","iss",m_streq);
  1331. X    SPdeffunc("ieq","iii",m_ieq);
  1332. X    SPdeffunc("igr","iii",m_igr);
  1333. X}
  1334. X
  1335. X/* end */
  1336. END_OF_FILE
  1337. if test 1584 -ne `wc -c <'main.c'`; then
  1338.     echo shar: \"'main.c'\" unpacked with wrong size!
  1339. fi
  1340. # end of 'main.c'
  1341. fi
  1342. if test -f 'mathsubs.c' -a "${1}" != "-c" ; then 
  1343.   echo shar: Will not clobber existing file \"'mathsubs.c'\"
  1344. else
  1345. echo shar: Extracting \"'mathsubs.c'\" \(919 characters\)
  1346. sed "s/^X//" >'mathsubs.c' <<'END_OF_FILE'
  1347. X/* mathsubs.c - math operators for spin
  1348. X *
  1349. X *  5.Nov.87  jimmc  Initial definition
  1350. X * 30.Nov.87  jimmc  Lint cleanup
  1351. X */
  1352. X/* LINTLIBRARY */
  1353. X
  1354. X#include "spin.h"
  1355. X
  1356. Xstatic
  1357. XSPbadbool(op)
  1358. Xchar *op;
  1359. X{
  1360. X/* this routine is to catch and error which "should never happen" */
  1361. X    SPescape("BadTokenType","non-list arg to %s",op);
  1362. X    /* NOTREACHED */
  1363. X}
  1364. X
  1365. Xint
  1366. Xsp_not(b)
  1367. Xint b;
  1368. X{
  1369. X    return (!b);
  1370. X}
  1371. X
  1372. Xint
  1373. Xsp_and(l)
  1374. XSPtoken *l;
  1375. X{
  1376. X    if (!l || l->type!=SPTokList) {
  1377. X        SPbadbool("and");
  1378. X        /* NOTREACHED */
  1379. X    }
  1380. X    for (l=l->value.l; l; l=l->next)
  1381. X        if (SPbooleval(l)==0)
  1382. X            return 0;
  1383. X    return 1;
  1384. X}
  1385. X
  1386. Xint
  1387. Xsp_or(l)
  1388. XSPtoken *l;
  1389. X{
  1390. X    if (!l || l->type!=SPTokList) {
  1391. X        SPbadbool("or");
  1392. X        /* NOTREACHED */
  1393. X    }
  1394. X    for (l=l->value.l; l; l=l->next)
  1395. X        if (SPbooleval(l)==1)
  1396. X            return 1;
  1397. X    return 0;
  1398. X}
  1399. X
  1400. XSPinitmath()
  1401. X{
  1402. Xextern int SPbool();
  1403. X    SPdeffunc("bool","iV",SPbool);
  1404. X    SPdeffunc("not","ib",sp_not);
  1405. X    SPdeffunc("and","iR",sp_and);
  1406. X    SPdeffunc("or","iR",sp_or);
  1407. X}
  1408. X
  1409. X/* end */
  1410. END_OF_FILE
  1411. if test 919 -ne `wc -c <'mathsubs.c'`; then
  1412.     echo shar: \"'mathsubs.c'\" unpacked with wrong size!
  1413. fi
  1414. # end of 'mathsubs.c'
  1415. fi
  1416. if test -f 'parse.c' -a "${1}" != "-c" ; then 
  1417.   echo shar: Will not clobber existing file \"'parse.c'\"
  1418. else
  1419. echo shar: Extracting \"'parse.c'\" \(7791 characters\)
  1420. sed "s/^X//" >'parse.c' <<'END_OF_FILE'
  1421. X/* parse.c - parsing routines
  1422. X *
  1423. X * 29.Sep.87  jimmc  Code start
  1424. X *  4.Nov.87  jimmc  Add setjmp stuff
  1425. X * 30.Nov.87  jimmc  Lint cleanup
  1426. X */
  1427. X/* LINTLIBRARY */
  1428. X
  1429. X#include <stdio.h>
  1430. X#include <ctype.h>
  1431. X#include <strings.h>
  1432. X#include "goto.h"
  1433. X#include "xalloc.h"
  1434. X#include "spin.h"
  1435. X#include "spinparse.h"
  1436. X
  1437. Xextern char *sprintf();    /* make lint happy */
  1438. X
  1439. XSPtoken *__tmptoken;
  1440. X
  1441. Xextern int SPtokenival;
  1442. Xextern float SPtokenfval;
  1443. Xextern char *SPtokenpval;
  1444. X
  1445. Xextern char *SPerrorstr;
  1446. X
  1447. Xchar *SPprompt1 = ">";
  1448. Xchar *SPprompt2 = ">>";
  1449. X
  1450. Xstatic char *parseerr="ParsingError";
  1451. X
  1452. XSPfgets(info,t)
  1453. XSPstreaminfo *info;    /* what to read from */
  1454. Xint t;            /* offset into linebuf */
  1455. X{
  1456. Xchar *dst, *src;
  1457. Xint i;
  1458. X
  1459. X    switch (info->type) {
  1460. X    case 'f':    /* file */
  1461. X        fgets(info->SPlinebuf+t,info->SPlinebufsize-t,info->stream);
  1462. X        if (feof(info->stream)) info->eofflag=1;
  1463. X        break;
  1464. X    case 's':    /* string */
  1465. X        dst = info->SPlinebuf+t;
  1466. X        src = info->stringget;
  1467. X        if (! *src) {
  1468. X            info->eofflag=1;
  1469. X            *dst = 0;
  1470. X            break;
  1471. X        }
  1472. X        for (i=0; i<info->SPlinebufsize-t; i++) {
  1473. X            *dst++ = *src++;
  1474. X            if (dst[-1]==0) {
  1475. X                info->eofflag=1;
  1476. X                break;
  1477. X            }
  1478. X            if (dst[-1]=='\n') {
  1479. X                *dst = 0;
  1480. X                break;
  1481. X            }
  1482. X        }
  1483. X        if (i>=info->SPlinebufsize-t) *dst=0;
  1484. X        info->stringget = src;
  1485. X        break;
  1486. X    default:    /* error */
  1487. X        SPescape("BadStreamType","bad type %c in SPfgets", info->type);
  1488. X        /* NOTREACHED */
  1489. X    }
  1490. X}
  1491. X
  1492. Xvoid            /* reads data info SPlinebuf in info structure */
  1493. XSPgetline(info)        /* read an arbitrarily long line from the stream */
  1494. XSPstreaminfo *info;    /* what to read from */
  1495. X{
  1496. X    int t, l;
  1497. X    static char *mmsg="SP line buffer";
  1498. X
  1499. X    if (info->SPlinebufsize==0) {
  1500. X        info->SPlinebufsize = 120;    /* a starting point */
  1501. X        info->SPlinebuf = XALLOCM(char,info->SPlinebufsize,mmsg);
  1502. X    }
  1503. X    info->SPlinebuf[info->SPlinebufsize-1]=0;
  1504. X        /* set to null so we can check it */
  1505. X    info->SPlinebuf[info->SPlinebufsize-2]=0;
  1506. X    info->SPlinebuf[0]=0;
  1507. X    t = 0;        /* first read goes into start of buffer */
  1508. X    if (info->stream==stdin) {
  1509. X        fputs(SPprompt1,stdout);
  1510. X    }
  1511. X    while (1) {    /* exit from the loop with a break statement */
  1512. X        SPfgets(info,t);
  1513. X        l = strlen(info->SPlinebuf+t)+t;    /* len of string */
  1514. X        if (l<info->SPlinebufsize-1) {    /* buffer not full */
  1515. X            /* info->SPlinebuf[l] is null char */
  1516. X            if (info->SPlinebuf[l-1]=='\n'
  1517. X                && info->SPlinebuf[l-2]=='\\') {
  1518. X                /* continuation line */
  1519. X                t = l-2;  /* new chars overwrite backslash */
  1520. X                info->SPlineno++;
  1521. X                if (info->stream==stdin) {
  1522. X                    fputs(SPprompt2,stdout);
  1523. X                }
  1524. X                goto readmore;
  1525. X            }
  1526. X            else break;    /* done reading */
  1527. X        }
  1528. X        else if (info->SPlinebuf[l-1]=='\n') break;
  1529. X            /* buffer full, but ends with newline, so we're done */
  1530. X
  1531. X        /* buffer is full; expand buffer and read more */
  1532. X        t = l;    /* this is where new piece should start */
  1533. X        info->SPlinebufsize *=2;    /* try twice the size */
  1534. X        info->SPlinebuf = XREALLOCM(char,
  1535. X            info->SPlinebuf,info->SPlinebufsize,mmsg);
  1536. Xreadmore:
  1537. X        info->SPlinebuf[t]=0;
  1538. X        info->SPlinebuf[info->SPlinebufsize-1]=0;
  1539. X        info->SPlinebuf[info->SPlinebufsize-2]=0;
  1540. X    }
  1541. X/* We now have the complete line in info->SPlinebuf,
  1542. X * no matter how long it was!
  1543. X */
  1544. X    info->SPlineno++;
  1545. X}
  1546. X
  1547. Xvoid
  1548. XSPparseline(info)    /* parse and execute the line in info->SPlinebuf */
  1549. XSPstreaminfo *info;
  1550. X{
  1551. X
  1552. X    SPtokenize(info);    /* break the line into tokens */
  1553. X    SPlistize(info);    /* convert parens into nested lists */
  1554. X}
  1555. X
  1556. Xvoid
  1557. XSPtokenize(info)
  1558. XSPstreaminfo *info;
  1559. X{
  1560. Xint t;
  1561. XSPtoken *tk, *lasttk;
  1562. X
  1563. X    SPlexinit(info);    /* init the lex parser */
  1564. X    info->tokenlist = NIL;
  1565. X    lasttk = NIL;
  1566. X    while ((t=yylex())) {
  1567. X        ALLOCTOKEN(tk)
  1568. X        if (!info->tokenlist) {
  1569. X            info->tokenlist = tk;
  1570. X        }
  1571. X        if (lasttk)
  1572. X            lasttk->next = tk;
  1573. X        tk->next = NIL;    /* put on end of token list */
  1574. X        lasttk = tk;
  1575. X        tk->type = t;
  1576. X        switch (t) {
  1577. X        case SPTokStr:
  1578. X        case SPTokName:
  1579. X            tk->value.s = XALLOCM(char,strlen(SPtokenpval)+1,
  1580. X                "token string");
  1581. X            strcpy(tk->value.s,SPtokenpval);
  1582. X            break;
  1583. X        case SPTokInt:
  1584. X            tk->value.n = SPtokenival;
  1585. X            break;
  1586. X        case SPTokFloat:
  1587. X            tk->value.f = SPtokenfval;
  1588. X            break;
  1589. X        default: break;
  1590. X        }
  1591. X    }
  1592. X}
  1593. X
  1594. XSPtoken *
  1595. XSPmklist(tklist)    /* makes a balanced list, returns excess at end */
  1596. XSPtoken *tklist;
  1597. X{
  1598. XSPtoken *prevtk, *newtk;
  1599. X
  1600. X    prevtk = NIL;
  1601. X    while (tklist) {
  1602. X        switch (tklist->type) {
  1603. X        case SPTokRP:    /* right paren */
  1604. X        case SPTokSM:    /* semicolon */
  1605. X            if (prevtk) prevtk->next = NIL;
  1606. X            return tklist;
  1607. X        case SPTokLP:    /* left paren - nested list */
  1608. X            tklist->type = SPTokList;  /* convert type to list */
  1609. X            tklist->value.l = tklist->next;
  1610. X            if (!tklist->next) {    /* error */
  1611. X                SPescape(parseerr,
  1612. X                    "open paren at end of input");
  1613. X                /* NOTREACHED */
  1614. X            }
  1615. X            newtk = SPmklist(tklist->next);
  1616. X            if (tklist->value.l == newtk) {
  1617. X                tklist->value.l = NIL;
  1618. X            }
  1619. X            if (newtk) {
  1620. X                if (newtk->type==SPTokSM) {
  1621. X                    tklist->next = newtk;
  1622. X                    newtk->type = SPTokLP;
  1623. X                }
  1624. X                else {
  1625. X                    tklist->next = newtk->next;
  1626. X                    FREETOKEN(newtk)  /* release the CP */
  1627. X                }
  1628. X            }
  1629. X            else {
  1630. X                tklist->next = NIL;
  1631. X            }
  1632. X            break;
  1633. X        default:
  1634. X            break;
  1635. X        }
  1636. X        prevtk = tklist;
  1637. X        tklist = tklist->next;
  1638. X    }
  1639. X    return NIL;
  1640. X}
  1641. X
  1642. Xvoid
  1643. XSPlistize(info)        /* convert paren and semi tokens into lists */
  1644. XSPstreaminfo *info;
  1645. X{
  1646. XSPtoken *tklist, *newtk;
  1647. X
  1648. X    tklist = info->tokenlist;
  1649. X    newtk = SPmklist(tklist);    /* make a balanced list */
  1650. X    while (newtk && newtk->type == SPTokSM) {
  1651. X        tklist->next = newtk->next;
  1652. X        tklist = tklist->next;
  1653. X        newtk = SPmklist(tklist);
  1654. X    }
  1655. X    if (newtk) {
  1656. X        SPescape(parseerr,"unbalanced close parenthesis");
  1657. X        /* NOTREACHED */
  1658. X    }
  1659. X/* make a list out of the top level */
  1660. X    ALLOCTOKEN(newtk)
  1661. X    newtk->type = SPTokList;
  1662. X    newtk->next = NIL;
  1663. X    newtk->value.l = info->tokenlist;
  1664. X    info->tokenlist = newtk;
  1665. X}
  1666. X
  1667. XSPtoken *
  1668. XSPparseinfo(info)
  1669. XSPstreaminfo *info;
  1670. X{
  1671. XSPtoken *rval, *SPexeclist();
  1672. X
  1673. X    rval = NIL;
  1674. X    info->eofflag = 0;
  1675. X    while (!info->eofflag) {
  1676. X        SPgetline(info);    /* read in a line */
  1677. X        if (!info->SPlinebuf[0]) break;    /* EOF */
  1678. X        SPparseline(info);    /* parse one line */
  1679. X        if (rval) FREETOKEN(rval)
  1680. X        rval = SPexeclist(info->tokenlist);    /* execute it */
  1681. X        if (info->stream==stdin) {
  1682. X            if (rval && rval->type!=SPTokNil)
  1683. X                SPprintval(stdout,rval,0);
  1684. X        }
  1685. X    }
  1686. X    if (info->SPlinebuf) XFREE(info->SPlinebuf);
  1687. X    XFREE(info);
  1688. X    return rval;
  1689. X}
  1690. X
  1691. XSPtoken *        /* returns a token which is the top value from
  1692. X             * the value stack for this level. */
  1693. XSPparsefile(stream)
  1694. XFILE *stream;        /* where to read input from */
  1695. X{
  1696. XSPstreaminfo *info;
  1697. X
  1698. X    info = XCALLOCM(SPstreaminfo,1,"stream info structure");
  1699. X    info->stream = stream;
  1700. X    info->type = 'f';
  1701. X    return SPparseinfo(info);    /* frees info when done */
  1702. X}
  1703. X
  1704. XSPtoken *        /* same as SPparsestream */
  1705. XSPparsestring(str)
  1706. Xchar *str;
  1707. X{
  1708. XSPstreaminfo *info;
  1709. X
  1710. X    info = XCALLOCM(SPstreaminfo,1,"stream info structure");
  1711. X    info->string = info->stringget = str;
  1712. X    info->type = 's';
  1713. X    return SPparseinfo(info);    /* frees info when done */
  1714. X}
  1715. X
  1716. Xint    /* returns 0 if no errors, 1 if error */
  1717. XSPmainfile(stream)
  1718. XFILE *stream;
  1719. X{
  1720. Xjmp_buf jbuf;
  1721. XSPtoken *rval;
  1722. X
  1723. X    SPjbufp = jmpbuf_addr(jbuf);
  1724. X    while (1) {
  1725. X        if (setjmp(jbuf)) {    /* uncaught goto */
  1726. X            fprintf(stderr,"Uncaught goto: %s\n", SPgotolabel);
  1727. X            if (SPerrorstr) fprintf(stderr,"%s\n", SPerrorstr);
  1728. X            XFREE(SPgotolabel);
  1729. X            if (feof(stream)) return 1;
  1730. X        }
  1731. X        else {    /* normal execution */
  1732. X            rval = SPparsefile(stream);
  1733. X            if (rval) FREETOKEN(rval);
  1734. X            if (feof(stream)) return 0;
  1735. X        }
  1736. X    }
  1737. X}
  1738. X
  1739. Xint    /* returns 0 if no errors, 1 if error */
  1740. XSPmainstring(str)
  1741. Xchar *str;
  1742. X{
  1743. Xjmp_buf jbuf;
  1744. XSPtoken *rval;
  1745. X
  1746. X    SPjbufp = jmpbuf_addr(jbuf);
  1747. X    if (setjmp(jbuf)) {    /* uncaught goto */
  1748. X        fprintf(stderr,"Uncaught goto: %s\n", SPgotolabel);
  1749. X        if (SPerrorstr) fprintf(stderr,"%s\n", SPerrorstr);
  1750. X        XFREE(SPgotolabel);
  1751. X        return 1;    /* error executing string */
  1752. X    }
  1753. X    rval = SPparsestring(str);
  1754. X    if (rval) FREETOKEN(rval);
  1755. X    return 0;
  1756. X}
  1757. X
  1758. X/* VARARGS1 */
  1759. XSPwerror(fmt,a0,a1,a2)
  1760. Xchar *fmt;
  1761. Xchar *a0,*a1,*a2;
  1762. X{
  1763. Xchar buf[1000];
  1764. X
  1765. X    sprintf(buf,fmt,a0,a1,a2);
  1766. X    fprintf(stderr,"Warning: %s\n",buf);
  1767. X}
  1768. X
  1769. X/* end */
  1770. END_OF_FILE
  1771. if test 7791 -ne `wc -c <'parse.c'`; then
  1772.     echo shar: \"'parse.c'\" unpacked with wrong size!
  1773. fi
  1774. # end of 'parse.c'
  1775. fi
  1776. if test -f 'spin.3' -a "${1}" != "-c" ; then 
  1777.   echo shar: Will not clobber existing file \"'spin.3'\"
  1778. else
  1779. echo shar: Extracting \"'spin.3'\" \(7690 characters\)
  1780. sed "s/^X//" >'spin.3' <<'END_OF_FILE'
  1781. X.\" spin.3
  1782. X.TH SPIN 3 " 1 March 1988"
  1783. X.SH NAME
  1784. Xspin \- simple programmable interface library
  1785. X.SH SYNOPSIS
  1786. X.br
  1787. X#include "spin.h"
  1788. X.sp 1
  1789. X% ld <your program etc.> spin.a
  1790. X.br
  1791. X.SH DESCRIPTION
  1792. X.I Spin
  1793. Xis a simple interpreter intended for use as a program development
  1794. Xtool and modest programmable interface.
  1795. XIt contains a parser and execution engine, with the ability to
  1796. Xeasily extend the basic engine with additional features such
  1797. Xas control constructs or new operations.
  1798. X.LP
  1799. XThe spin interpreter has been set up to be usable in a bare-bones
  1800. Xconfiguration, in which there are almost no capabilities or functions
  1801. Xavailable other than application-specific ones.
  1802. XThere are also a set of various simple extensions available
  1803. Xwhich raise the application-independent capabilities of spin up
  1804. Xto a level where it is almost usable by itself.
  1805. XThe intent is for the application to add whatever application-specific
  1806. Xfunctions it needs and to select the level of application-independent
  1807. Xsupport needed.
  1808. XThe spin library was designed to be modular enough that the application
  1809. Xprogram could pick and choose among almost all of the aspects of the
  1810. Xinterpreter.
  1811. XIf there is a capability which is not needed, it does not need to
  1812. Xbe loaded.
  1813. XIf there is a capability which the programmer feels he can implement
  1814. Xbetter, it is typically a fairly simple job for him to rewrite that
  1815. Xcapability without worrying about other parts of the system.
  1816. X.LP
  1817. XIn addition to the generic extensions, an application program can
  1818. Xadd whatever application-specific functions are desired.
  1819. XEach function requires a one-line call to one of the spin
  1820. Xprimitives, to be executed during program startup time.
  1821. XOnce this has been done, the function is available to the user
  1822. Xof the application.
  1823. X.LP
  1824. XThere are a small number of data types known to spin (e.g. int,
  1825. Xfloat, string), which can be specified as the argument and return
  1826. Xtypes for functions.
  1827. XThe spin interpreter will do type checking on all arguments
  1828. Xpassed to functions.
  1829. X.LP
  1830. XTo use spin, a program need only link with the spin library and
  1831. Xcall the appropriate initialization routines during startup.
  1832. X.SH BASIC FUNCTIONS
  1833. X.LP
  1834. XThe minimal program requires a call to one of two functions:
  1835. XSPmainfile or SPmainstring.
  1836. XThese routines will parse and execute a stream (FILE *) or string
  1837. X(respectively) until EOF or EOS.
  1838. XHowever, if the main program never invokes any other spin primitive,
  1839. Xthere will not be any legal functions available for the parsed code
  1840. Xto call!
  1841. XThere are two ways to initialize functions:
  1842. Xby calling the initialization routines for one of the
  1843. Xapplication-independent packages, or by adding
  1844. Xapplication-specific functions by calling SPdeffunc.
  1845. XThe complete set of application-independent packages can be loaded
  1846. Xby calling SPinitsubs.
  1847. XTypically an application will call SPdeffunc a number of times
  1848. X(once for each of its functions), and will call either SPinitsubs
  1849. Xor a subset of the functions SPinitsubs calls.
  1850. X.SH DATA TYPES
  1851. X.LP
  1852. XThe spin interpreter understands the following data types:
  1853. Xnil, integer, float, string, and list.
  1854. XBecause there are no built-in operations, there are also no
  1855. Xbuilt-in conversions (nor for that matter any built-in explicit
  1856. Xcasting mechanism!).
  1857. XNote in particular that there is no automatic conversion between
  1858. Xint and float: if a program is expecting an int, passing a float
  1859. Xto it will cause an error.
  1860. XThe one exception to this is that all types have an interpretation
  1861. Xas a boolean, so that any variable can be directly used as a boolean
  1862. Xto a function which is expecting a boolean.
  1863. X.SH ARGUMENT AND RETURN TYPES AND DEFAULTS
  1864. X.LP
  1865. XIn the SPdeffunc call, the second argument is a string which encodes
  1866. Xthe types of the return value and arguments of a function.
  1867. XThe first character specifies the return type of the function, the
  1868. Xremainder specify the types of each consecutive argument.
  1869. XThe list is terminated by a null (EOS) or by a semicolon.
  1870. X(In the future, spin will probably accept some descriptive text
  1871. Xafter a semicolon which gives names for each of the arguments.)
  1872. XTypically, the type of an argument is represented by a single
  1873. Xcharacter.
  1874. XIn some cases, a default can also be included, in which case it
  1875. Xappears immediately after the type character.
  1876. X.LP
  1877. XThe valid argument type code characters are:
  1878. X.TP
  1879. Xb - boolean
  1880. XAny type can be passed to a function expecting a boolean; the value
  1881. Xwill be cast to a boolean, and the function will receive an integer
  1882. Xzero or one.
  1883. X.TP
  1884. Xi - integer
  1885. X.TP
  1886. XI - optional integer
  1887. XThe default value immediately follows the I, such as "I0" or "I-99".
  1888. X.TP
  1889. Xf - float
  1890. X.TP
  1891. Xn - name
  1892. XA name is a subset of string; it can not contain any characters other
  1893. Xthan alphanumerics (with leading alpha) or underscore, and it may be
  1894. Xspecified within quotes or with no quotes.
  1895. X.TP
  1896. Xs - string
  1897. X.TP
  1898. XS - optional string
  1899. XThe default value immediately follows the S,
  1900. X.I "in double quotes"
  1901. X(remember to escape the quotes with backslashes).
  1902. XFor example, "S\"foo\"".
  1903. X.TP
  1904. XV - untyped variable
  1905. XA single evaluated variable of any type (passed to the application
  1906. Xfunction as a spin token).
  1907. X.TP
  1908. XL - a list variable
  1909. XA single unevaluated token.
  1910. XThis if useful for building such things as the "if" construct, in
  1911. Xwhich only one of the clauses should be executed.
  1912. X.TP
  1913. XR - remainder
  1914. XThe remainder of the arguments as a list, unevaluated.
  1915. X.LP
  1916. XThe valid return type code characters are:
  1917. X.TP
  1918. Xi - integer
  1919. X.TP
  1920. Xv - void
  1921. XThis is used when the function returns no value.
  1922. XAny value returned by the function is ignored.
  1923. X.TP
  1924. Xf - float
  1925. X.TP
  1926. Xn - name
  1927. X.TP
  1928. Xs - static string
  1929. XSpin will make an allocated copy of a static string, so functions
  1930. Xmay return pointers to internal buffers which are overwritten on
  1931. Xthe next call.
  1932. X.TP
  1933. XS - allocated string
  1934. XThis code is used when the function allocates the string using malloc
  1935. Xand returns it.
  1936. XSpin will not make a copy of the string, but will assume that it owns
  1937. Xit from then on.
  1938. X.TP
  1939. XV - allocated variable
  1940. XThe function allocates a spin token and returns it as the value of
  1941. Xthe function.
  1942. XSpin will assume that it owns the token from then on.
  1943. XA function can use this type to return a value of arbitrary type.
  1944. X.TP
  1945. Xl - static list of variables
  1946. XSpin will make a copy of the list, as with the "s" type.
  1947. X.TP
  1948. XL - allocated list of variables
  1949. XSpin assumes the entire list belongs to it from then on, as with the "S" type.
  1950. X.SH ERRORS AND GOTO
  1951. XThe spin routines handle exceptions by executing a "goto" to a label
  1952. Xwhich is different depending on what the exception is.
  1953. XIf this label is defined, execution continues at that point; if not,
  1954. Xexecution terminates, and the label is printed along with an error
  1955. Xmessage.
  1956. XNote that this mechanism involves the function execution extension
  1957. Xto the core, so any programmer implementing his own function execution
  1958. Xshould be sure to include this aspect.
  1959. X.SH BUGS
  1960. X.LP
  1961. XThe documentation is too skimpy.
  1962. X.LP
  1963. XThe data types are not one of the easily-changed aspects of spin;
  1964. Xthey are pretty firmly wired into the core interpreter.
  1965. X.LP
  1966. XThe argument and return type codes are not particularly consistent
  1967. Xor complete.
  1968. X.LP
  1969. XThe implementations of variables and functions should be considered
  1970. Xonly as an example of how this kind of extension could be added to
  1971. Xthe basic interpreter.
  1972. XThese implementations are decidedly inferior in both performance and
  1973. Xfunctionality, but they do show how such a thing could be done.
  1974. X.LP
  1975. XThere are lots of memory leaks; garbage collection is probably
  1976. Xthe way to go.
  1977. X.LP
  1978. XThe parser is line-oriented, so has problems with things like
  1979. Xmulti-line comments.  This definitely needs to be improved.
  1980. X.LP
  1981. XThe syntax should be that of some previously defined language.
  1982. X.LP
  1983. XThis whole package could be replaced by a simple Lisp package that
  1984. Xcould be linked with an application, but I don't have one handy.
  1985. END_OF_FILE
  1986. if test 7690 -ne `wc -c <'spin.3'`; then
  1987.     echo shar: \"'spin.3'\" unpacked with wrong size!
  1988. fi
  1989. # end of 'spin.3'
  1990. fi
  1991. if test -f 'spin.h' -a "${1}" != "-c" ; then 
  1992.   echo shar: Will not clobber existing file \"'spin.h'\"
  1993. else
  1994. echo shar: Extracting \"'spin.h'\" \(1086 characters\)
  1995. sed "s/^X//" >'spin.h' <<'END_OF_FILE'
  1996. X/* spin.h - application programs using spin should include this file.
  1997. X *
  1998. X * 16.Oct.87  jimmc  Initial definition
  1999. X */
  2000. X
  2001. X/* xalloc.h must also be included in order to use the ALLOC/FREE macros */
  2002. X
  2003. X#define NIL 0
  2004. X#define void int
  2005. X    /* void is broken */
  2006. X
  2007. Xtypedef struct _SPtoken {    /* one token */
  2008. X    int type;    /* token type */
  2009. X#define SPTokNil 'N'    /* the NIL type */
  2010. X#define SPTokInt 'i'
  2011. X#define SPTokFloat 'f'
  2012. X#define SPTokStr 's'
  2013. X#define SPTokName 'n'
  2014. X#define SPTokList 'l'
  2015. X#define SPTokLP '('
  2016. X#define SPTokRP ')'
  2017. X#define SPTokSM ';'
  2018. X    union {
  2019. X        int n;        /* integer values */
  2020. X        float f;    /* float values */
  2021. X        char *s;    /* string and name values */
  2022. X        struct _SPtoken *l;    /* list values */
  2023. X    } value;
  2024. X    struct _SPtoken *next;    /* for tokens in a list */
  2025. X} SPtoken;
  2026. X
  2027. Xextern SPtoken *__tmptoken;    /* for ALLOC and FREE macros */
  2028. X
  2029. X#define ALLOCTOKEN(_tk_) { \
  2030. X    _tk_ = XALLOC(SPtoken,1); \
  2031. X}
  2032. X
  2033. X#define FREETOKEN(_tk_) { \
  2034. X    XFREE(_tk_); \
  2035. X    _tk_ = NIL; \
  2036. X}
  2037. X
  2038. X#define FREETOKENLIST(_tk_) { \
  2039. X    while (_tk_) { \
  2040. X        __tmptoken = _tk_->next; \
  2041. X        XFREE(_tk_); \
  2042. X        _tk_ = __tmptoken; \
  2043. X    } \
  2044. X    _tk_ = NIL; \
  2045. X}
  2046. X
  2047. X/* end */
  2048. END_OF_FILE
  2049. if test 1086 -ne `wc -c <'spin.h'`; then
  2050.     echo shar: \"'spin.h'\" unpacked with wrong size!
  2051. fi
  2052. # end of 'spin.h'
  2053. fi
  2054. if test -f 'spinparse.h' -a "${1}" != "-c" ; then 
  2055.   echo shar: Will not clobber existing file \"'spinparse.h'\"
  2056. else
  2057. echo shar: Extracting \"'spinparse.h'\" \(558 characters\)
  2058. sed "s/^X//" >'spinparse.h' <<'END_OF_FILE'
  2059. X/* spinparse.h - internal include file for spin parser
  2060. X *
  2061. X * 20.Oct.87  jimmc  Add string stuff
  2062. X */
  2063. X
  2064. Xtypedef struct _SPstreaminfo {
  2065. X    int type;    /* 's' for string, 'f' for stream (file) */
  2066. X    int eofflag;    /* set when no more chars in input */
  2067. X    FILE *stream;
  2068. X    char *string;
  2069. X    char *stringget;    /* points into string */
  2070. X    char *SPlinebuf;
  2071. X    int SPlinebufsize;
  2072. X    int SPlineno;
  2073. X    SPtoken *tokenlist;    /* the line parsed into tokens */
  2074. X    SPtoken *execlist;    /* list of tokens being executed */
  2075. X    SPtoken *valuelist;    /* list of values in the stack */
  2076. X} SPstreaminfo;
  2077. X
  2078. X/* end */
  2079. END_OF_FILE
  2080. if test 558 -ne `wc -c <'spinparse.h'`; then
  2081.     echo shar: \"'spinparse.h'\" unpacked with wrong size!
  2082. fi
  2083. # end of 'spinparse.h'
  2084. fi
  2085. if test -f 'varsubs.c' -a "${1}" != "-c" ; then 
  2086.   echo shar: Will not clobber existing file \"'varsubs.c'\"
  2087. else
  2088. echo shar: Extracting \"'varsubs.c'\" \(2638 characters\)
  2089. sed "s/^X//" >'varsubs.c' <<'END_OF_FILE'
  2090. X/* varsubs.c - set/get variable values for spin
  2091. X *
  2092. X * 16.Oct.87  jimmc  Initial definition
  2093. X * 21.Oct.87  jimmc  Add fset, fdeclare, fget
  2094. X *  5.Nov.87  jimmc  Use SPescape instead of SPwerror
  2095. X * 30.Nov.87  jimmc  Lint cleanup
  2096. X */
  2097. X/* LINTLIBRARY */
  2098. X
  2099. X#include <strings.h>
  2100. X#include "xalloc.h"
  2101. X#include "spin.h"
  2102. X
  2103. Xextern SPtoken *SPexec();
  2104. X
  2105. Xtypedef struct _SPvarinfo {
  2106. X    char *name;    /* name of the variable */
  2107. X    SPtoken *val;    /* value as a token */
  2108. X    struct _SPvarinfo *next;
  2109. X} SPvarinfo;
  2110. X
  2111. XSPvarinfo *SPvarbase;
  2112. X
  2113. Xstatic char *badvaruse="BadVarUse";
  2114. Xstatic char *badvardecl="BadVarDecl";
  2115. Xstatic char *badvarref="BadVarRef";
  2116. X
  2117. XSPvarinfo *
  2118. Xsp_iget(name)
  2119. Xchar *name;
  2120. X{
  2121. XSPvarinfo *vinfo;
  2122. X
  2123. X    for (vinfo=SPvarbase;vinfo;vinfo=vinfo->next)
  2124. X        if (strcmp(vinfo->name,name)==0) return vinfo;
  2125. X    return NIL;
  2126. X}
  2127. X
  2128. Xstatic
  2129. Xsp_dodeclare(name)
  2130. Xchar *name;
  2131. X{
  2132. XSPvarinfo *vinfo;
  2133. X
  2134. X    vinfo = XALLOCM(SPvarinfo,1,"sp_declare");
  2135. X    vinfo->next = SPvarbase;
  2136. X    SPvarbase = vinfo;
  2137. X    vinfo->name = XALLOCM(char,strlen(name)+1,"declare name");
  2138. X    strcpy(vinfo->name,name);
  2139. X    vinfo->val = NIL;
  2140. X}
  2141. X
  2142. Xint
  2143. Xsp_declare(name)
  2144. Xchar *name;
  2145. X{
  2146. XSPvarinfo *vinfo;
  2147. X
  2148. X    vinfo = sp_iget(name);
  2149. X    if (vinfo) {
  2150. X        SPescape(badvardecl,"%s already declared",name);
  2151. X        /* NOTREACHED */
  2152. X    }
  2153. X    sp_dodeclare(name);
  2154. X    return 1;
  2155. X}
  2156. X
  2157. Xint
  2158. Xsp_fdeclare(name)
  2159. Xchar *name;
  2160. X{
  2161. X
  2162. X    if (!sp_iget(name)) sp_dodeclare(name);
  2163. X    return 1;
  2164. X}
  2165. X
  2166. XSPtoken *
  2167. Xsp_set(name,value)
  2168. Xchar *name;
  2169. XSPtoken *value;
  2170. X{
  2171. XSPvarinfo *vinfo;
  2172. X
  2173. X    vinfo = sp_iget(name);
  2174. X    if (!vinfo) {
  2175. X/* for auto-declaration, simply call sp_declare(name) here instead
  2176. X * of delivering the error message */
  2177. X        SPescape(badvaruse,"variable %s set but not declared",name);
  2178. X        /* NOTREACHED */
  2179. X    }
  2180. X    FREETOKEN(vinfo->val)
  2181. X    vinfo->val = value;
  2182. X    return value;
  2183. X}
  2184. X
  2185. XSPtoken *
  2186. Xsp_fset(name,value)
  2187. Xchar *name;
  2188. XSPtoken *value;
  2189. X{
  2190. XSPvarinfo *vinfo;
  2191. X
  2192. X    (void)sp_fdeclare(name);
  2193. X    vinfo = sp_iget(name);
  2194. X    if (!vinfo) {
  2195. X/* should never happen, since we called sp_fdeclare first */
  2196. X        SPescape(badvaruse,"variable %s set but not declared",name);
  2197. X        /* NOTREACHED */
  2198. X    }
  2199. X    FREETOKEN(vinfo->val)
  2200. X    vinfo->val = value;
  2201. X    return value;
  2202. X}
  2203. X
  2204. XSPtoken *
  2205. Xsp_get(name)
  2206. Xchar *name;
  2207. X{
  2208. XSPvarinfo *vinfo;
  2209. X
  2210. X    vinfo = sp_iget(name);
  2211. X    if (!vinfo) {
  2212. X        SPescape(badvarref,
  2213. X            "variable %s referenced but not declared",name);
  2214. X        /* NOTREACHED */
  2215. X    }
  2216. X    return vinfo->val;
  2217. X}
  2218. X
  2219. XSPtoken *
  2220. Xsp_fget(name)
  2221. Xchar *name;
  2222. X{
  2223. XSPvarinfo *vinfo;
  2224. X
  2225. X    vinfo = sp_iget(name);
  2226. X    if (!vinfo) return NIL;
  2227. X    return vinfo->val;
  2228. X}
  2229. X
  2230. XSPinitvars()
  2231. X{
  2232. X    SPdeffunc("declare","in",sp_declare);
  2233. X    SPdeffunc("fdeclare","in",sp_fdeclare);
  2234. X    SPdeffunc("set","lnV",sp_set);
  2235. X    SPdeffunc("fset","lnV",sp_fset);
  2236. X    SPdeffunc("get","ln",sp_get);
  2237. X    SPdeffunc("fget","ln",sp_fget);
  2238. X}
  2239. X
  2240. X/* end */
  2241. END_OF_FILE
  2242. if test 2638 -ne `wc -c <'varsubs.c'`; then
  2243.     echo shar: \"'varsubs.c'\" unpacked with wrong size!
  2244. fi
  2245. # end of 'varsubs.c'
  2246. fi
  2247. if test -f 'xalloc.c' -a "${1}" != "-c" ; then 
  2248.   echo shar: Will not clobber existing file \"'xalloc.c'\"
  2249. else
  2250. echo shar: Extracting \"'xalloc.c'\" \(2363 characters\)
  2251. sed "s/^X//" >'xalloc.c' <<'END_OF_FILE'
  2252. X/* xalloc - allocate memory, give error message and die if no more
  2253. X * Written by Jim McBeath (jimmc) at SCI
  2254. X *
  2255. X *  3.Jun.86  jimmc
  2256. X * 18.Sep.87  jimmc  Add xcalloc
  2257. X * 22.Sep.87  jimmc  Allow null msg strings
  2258. X *  5.Nov.87  jimmc  Change xalloc to xallocm etc.;
  2259. X *            add new xalloc, xcalloc, xrealloc
  2260. X * 30.Nov.87  jimmc  Lint cleanup
  2261. X */
  2262. X/* LINTLIBRARY */
  2263. X
  2264. X#include <stdio.h>
  2265. X
  2266. X#define ERROR_EXIT 1
  2267. X#define NULLCP (char *)NULL
  2268. X
  2269. Xextern char *malloc(), *calloc(), *realloc();
  2270. X
  2271. Xextern char *Progname;
  2272. X
  2273. Xstatic int totalused=0;        /* only true if no frees performed */
  2274. X
  2275. Xchar *
  2276. Xxalloc( size )
  2277. Xint size;        /* number of bytes to allocate */
  2278. X{
  2279. Xchar *x;
  2280. X
  2281. X    x = malloc( (unsigned)size );
  2282. X    if (x==0) xnomem(NULLCP,size);
  2283. X    totalused += size;
  2284. X    return x;
  2285. X}
  2286. X
  2287. Xchar *
  2288. Xxallocm( size, msg )
  2289. Xint size;        /* number of bytes to allocate */
  2290. Xchar *msg;        /* error string */
  2291. X{
  2292. Xchar *x;
  2293. X
  2294. X    x = malloc( (unsigned)size );
  2295. X    if (x==0) xnomem(msg,size);
  2296. X    totalused += size;
  2297. X    return x;
  2298. X}
  2299. X
  2300. Xchar *
  2301. Xxcalloc( size )        /* NOTE ARGS NOT SAME AS calloc()! */
  2302. Xint size;        /* number of bytes to allocate */
  2303. X{
  2304. Xchar *x;
  2305. X
  2306. X    x = calloc( (unsigned)size, 1 );
  2307. X    if (x==0) xnomem(NULLCP,size);
  2308. X    totalused += size;
  2309. X    return x;
  2310. X}
  2311. X
  2312. Xchar *
  2313. Xxcallocm( size, msg )    /* NOTE ARGS NOT SAME AS calloc()! */
  2314. Xint size;        /* number of bytes to allocate */
  2315. Xchar *msg;        /* error string */
  2316. X{
  2317. Xchar *x;
  2318. X
  2319. X    x = calloc( (unsigned)size, 1 );
  2320. X    if (x==0) xnomem(msg,size);
  2321. X    totalused += size;
  2322. X    return x;
  2323. X}
  2324. X
  2325. Xchar *
  2326. Xxrealloc( ptr, size )
  2327. Xchar *ptr;        /* old pointer */
  2328. Xint size;        /* number of bytes to allocate */
  2329. X{
  2330. Xchar *x;
  2331. X
  2332. X    x = realloc( ptr, (unsigned)size );
  2333. X    if (x==0) xnomem(NULLCP,size);
  2334. X    totalused += size;    /*** not quite accurate! */
  2335. X    return x;
  2336. X}
  2337. X
  2338. Xchar *
  2339. Xxreallocm( ptr, size, msg )
  2340. Xchar *ptr;        /* old pointer */
  2341. Xint size;        /* number of bytes to allocate */
  2342. Xchar *msg;        /* error string */
  2343. X{
  2344. Xchar *x;
  2345. X
  2346. X    x = realloc( ptr, (unsigned)size );
  2347. X    if (x==0) xnomem(msg,size);
  2348. X    totalused += size;    /*** not quite accurate! */
  2349. X    return x;
  2350. X}
  2351. X
  2352. Xstatic
  2353. Xxnomem(msg,size)
  2354. Xchar *msg;
  2355. Xint size;
  2356. X{
  2357. Xchar *nomemmsg="No more memory";
  2358. X
  2359. X    if (msg)
  2360. X        fprintf(stderr,"\n%s: %s (%s)\n", Progname, nomemmsg, msg);
  2361. X    else
  2362. X        fprintf(stderr,"\n%s: %s\n", Progname, nomemmsg);
  2363. X
  2364. X#if 0    /* not accurate! */
  2365. X    fprintf(stderr,"Previously used: %d; this request: %d\n",
  2366. X            totalused, size);
  2367. X#else
  2368. X    fprintf(stderr,"Requested memory size: %d\n", size);
  2369. X#endif
  2370. X    exit(ERROR_EXIT);
  2371. X}
  2372. X
  2373. X/* end */
  2374. END_OF_FILE
  2375. if test 2363 -ne `wc -c <'xalloc.c'`; then
  2376.     echo shar: \"'xalloc.c'\" unpacked with wrong size!
  2377. fi
  2378. # end of 'xalloc.c'
  2379. fi
  2380. if test -f 'xalloc.h' -a "${1}" != "-c" ; then 
  2381.   echo shar: Will not clobber existing file \"'xalloc.h'\"
  2382. else
  2383. echo shar: Extracting \"'xalloc.h'\" \(959 characters\)
  2384. sed "s/^X//" >'xalloc.h' <<'END_OF_FILE'
  2385. X/* xalloc.h - defines for use with xalloc.c
  2386. X *
  2387. X * 18.Sep.87  jimmc  Collected into xalloc.h
  2388. X * 22.Sep.87  jimmc  Add XFREE, XALLOCD etc.
  2389. X * 21.Oct.87  jimmc  Change XALLOC to XALLOCM, XALLOCD to XALLOC etc.
  2390. X *  6.Nov.87  jimmc  call xallocm instead of xalloc, etc.
  2391. X */
  2392. X
  2393. X#ifndef XALLOCINCLUDED
  2394. X#define XALLOCINCLUDED
  2395. X
  2396. Xextern char *xalloc(), *xcalloc(), *xrealloc();
  2397. Xextern char *xallocm(), *xcallocm(), *xreallocm();
  2398. X
  2399. X#define XALLOC(item, count ) (item *)xalloc(sizeof(item)*(count))
  2400. X#define XCALLOC(item, count ) (item *)xcalloc(sizeof(item)*(count))
  2401. X#define XREALLOC(item, old, count ) \
  2402. X    (item *)xrealloc((char *)(old),sizeof(item)*(count))
  2403. X
  2404. X#define XFREE(old) free((char *)(old));
  2405. X
  2406. X#define XALLOCM(item, count, msg) (item *)xallocm(sizeof(item)*(count),msg)
  2407. X#define XCALLOCM(item, count, msg) (item *)xcallocm(sizeof(item)*(count),msg)
  2408. X#define XREALLOCM(item, old, count, msg) \
  2409. X    (item *)xreallocm((char *)(old),sizeof(item)*(count),msg)
  2410. X#endif
  2411. X
  2412. X/* end */
  2413. END_OF_FILE
  2414. if test 959 -ne `wc -c <'xalloc.h'`; then
  2415.     echo shar: \"'xalloc.h'\" unpacked with wrong size!
  2416. fi
  2417. # end of 'xalloc.h'
  2418. fi
  2419. echo shar: End of archive 1 \(of 2\).
  2420. cp /dev/null ark1isdone
  2421. MISSING=""
  2422. for I in 1 2 ; do
  2423.     if test ! -f ark${I}isdone ; then
  2424.     MISSING="${MISSING} ${I}"
  2425.     fi
  2426. done
  2427. if test "${MISSING}" = "" ; then
  2428.     echo You have unpacked both archives.
  2429.     rm -f ark[1-9]isdone
  2430. else
  2431.     echo You still need to unpack the following archives:
  2432.     echo "        " ${MISSING}
  2433. fi
  2434. ##  End of shell archive.
  2435. exit 0
  2436.