home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / perl / 5603 < prev    next >
Encoding:
Text File  |  1992-08-30  |  20.1 KB  |  738 lines

  1. Newsgroups: comp.lang.perl
  2. Path: sparky!uunet!s5!is1.is.morgan.com!is0.is.morgan.com!robt
  3. From: robt@is.morgan.com (Rob Torop)
  4. Subject: usersub: HOW TO
  5. Message-ID: <ROBT.92Aug29232737@idt101.is.morgan.com>
  6. Sender: news@is.morgan.com
  7. Nntp-Posting-Host: idt101
  8. Organization: Morgan Stanley & Company
  9. Distribution: comp.lang.perl
  10. Date: Sun, 30 Aug 1992 04:27:37 GMT
  11. Lines: 725
  12.  
  13. #--------------------------------CUT HERE-------------------------------------
  14. #! /bin/sh
  15. #
  16. # This is a shell archive.  Save this into a file, edit it
  17. # and delete all lines above this comment.  Then give this
  18. # file to sh by executing the command "sh file".  The files
  19. # will be extracted into the current directory owned by
  20. # you with default permissions.
  21. #
  22. # The files contained herein are:
  23. #
  24. # -r--r--r--  1 robt         7077 Aug 29 15:58 usub.doc
  25. # -r--r--r--  1 robt         1686 Aug 29 15:49 ex1.mus
  26. # -r--r--r--  1 robt         1714 Aug 29 15:49 ex2.mus
  27. # -r--r--r--  1 robt         2287 Aug 29 15:49 ex3.mus
  28. # -r--r--r--  1 robt          480 Aug 29 15:56 exfns.c
  29. # -r--r--r--  1 robt          266 Aug 29 15:36 exfns.h
  30. # -r--r--r--  1 robt          892 Aug 29 23:20 makefile
  31. # -r--r--r--  1 robt         1370 Aug 29 16:09 extest.pl
  32. #
  33. echo 'x - usub.doc'
  34. if test -f usub.doc; then echo 'shar: not overwriting usub.doc'; else
  35. sed 's/^X//' << '________This_Is_The_END________' > usub.doc
  36. X/*
  37. X *   Last edited by:  $Author: robt $
  38. X *               on:  $Date: 1992/08/29 19:58:19 $
  39. X *         Filename:  $RCSfile: usub.doc,v $
  40. X *         Revision:  $Revision: 1.3 $
  41. X */
  42. X
  43. X                 usub: Hooking C functions in to perl
  44. X                 ------------------------------------
  45. X
  46. XRobert Torop (robt@is.morgan.com)                        
  47. X
  48. XThese notes do not represent the views of Morgan Stanley & Co. in any
  49. Xway.  I am solely responsible for the contents.
  50. X
  51. XThese notes describe in detail how to hook functions into perl using
  52. Xthe "usersub" mechanism.  Assuming people are interested, I will post
  53. Xnew versions when (and if!) I figure out more, particularly about
  54. Xassociative arrays.  You might want to skip reading this all together
  55. Xand just look at the sample programs (see the makefile).
  56. X
  57. XIntroduction
  58. X------------
  59. X
  60. XYou should have the following files:
  61. X
  62. X    makefile            Makes the examples
  63. X    usub.doc            These notes
  64. X    ex1.mus             Glue to hook "opie" from exfns.c into perl
  65. X    ex2.mus             Glue to hook more of exfns.c into perl
  66. X    ex3.mus             Same as ex3.mus, with an example of
  67. X                        returning an array.
  68. X    exfns.c             Functions to be hooked in to perl in examples
  69. X    exfns.h             Header file for exfns.c
  70. X    extest.pl           Small program to test that the new functions
  71. X                        are there.
  72. X    
  73. XYou will also need uperl.o (should have been created when perl was
  74. Xbuilt), the .h files from perl, and the program mus, all of which
  75. Xshould be in your perl source directory.  You should also take a look
  76. Xat README in the usub directory under the perl source.  
  77. X
  78. XDANGER WILL ROBINSON!
  79. X---------------------
  80. X
  81. XIf you are using perl with patchlevel < 20, you may have memory
  82. Xleakage problems.  I did, with functions that return arrays.  This is
  83. Xapparently due to a problem which has been fixed.  When I compile
  84. Xusing patchlevel 35, I have no such problems.  This may not be a big
  85. Xdeal - I had to run around 100K calls before perl barfed.
  86. X
  87. XBasic Structure
  88. X---------------
  89. X
  90. Xperl hooks in functions and variables using two enumerated variables,
  91. Xand four functions.
  92. X
  93. X    1) An enum variable called usersubs, the elements of which look like
  94. X       US_functionName.  For example:
  95. X
  96. X            static enum usersubs { US_aGreatFunction };
  97. X
  98. X       These values will be passed to usersub (see below) so it can
  99. X       tell what function has been called.
  100. X
  101. X    2) An enum variable called uservars, the elements of which look like
  102. X       UV_variableName.  For example:
  103. X
  104. X            static enum uservars { UV_anImportantVariable };
  105. X
  106. X       These values will be passed to userset and userval (see below) so 
  107. X       tell what variable is being set/retrieved.
  108. X    
  109. X    3) Four functions, userinit, usersub, userset, and userval, the
  110. X       latter two two of which are required only if one is using uservars.
  111. X        
  112. Xuserinit performs any initializations needed.  This can be
  113. X
  114. X    1) Any initialization needed by the code you're hooking in.  
  115. X    2) Registering the functions enumerated in usersubs using make_usub.
  116. X    3) Setting the uf_set and uf_get fields of a global struct ufuncs
  117. X       for use by MAGICVAR.
  118. X    4) Registering the variables enumerated in uservals using the
  119. X       MAGICVAR macro.
  120. X
  121. Xusersub gets passed the enumerated value of the function being called
  122. X(eg US_myFunction), the number of parameters, and a pointer to the perl
  123. Xstack.  It is just a switch on the US_ value, each case of which must
  124. Xpull parameters off the stack and put them back on appropriately.  The
  125. Xmus program helps in this - if a function is simple enough, it will fill
  126. Xin the code for you.  Our examples use mus to do this.
  127. X
  128. Xuserval is called when the perl program tries to get the value of a
  129. Xvariable defined in your struct uservals.  It gets passed a (STR *)
  130. Xwhich it must fill in, usually using the functions str_numset or
  131. Xstr_set.
  132. X
  133. Xuserset is called when the perl program tries to set the value of a
  134. Xvariable defined in your struct uservals.  It gets passed a (STR *)
  135. Xfrom which it must extract and set the variable, usually using
  136. Xstr_gnum or str_get.  (These could be either functions or macros,
  137. Xdepending on the value of the symbol CRIPPLED_CC - don't worry about
  138. Xit.).
  139. X
  140. Xmus
  141. X---
  142. X
  143. Xmus is a program which makes using usub easier.  The input to mus is
  144. Xan "extended" C source.  The output of mus is a C program which
  145. Xcontains code to check the number of arguments, extract the arguments
  146. Xfrom the perl stack, calls your function and then puts the result back
  147. Xon the stack.  It only handles scalar values, but see example 3 for
  148. Xthe way to return an array.  You should run mus on the examples and
  149. Xlook at the resulting C programs.  In particular, doing this will show
  150. Xyou how to use str_set, str_setnum, str_get, and str_gnum.
  151. X
  152. XA Handy Hint
  153. X------------
  154. X
  155. XIf you compile with debugging on, you can dbx (or whatever) your copy
  156. Xof perl and stop in usersub to see what's going on like this:
  157. X
  158. X       $ dbx myperl
  159. X       (dbx) stop in usersub
  160. X       (dbx) run -de 0
  161. X       <DB>1 $x = &myFunction('hello');  # now you're in the perl debugger
  162. X       stopped at usersub at line ....   # now you're in dbx
  163. X       (dbx)
  164. X            
  165. X            
  166. XIf you trace in far enough, st[1] will be the first argument you passed
  167. Xto the function.  Have fun...
  168. X
  169. XExample 1
  170. X---------
  171. X
  172. XIn this example, we have a function already written, with prototype
  173. X
  174. X    double opie(double);
  175. X
  176. Xin the file exfns.c, and we want to call it from perl like this
  177. X
  178. X    $x = 12.3;
  179. X    print &opie($x), "\n";
  180. X
  181. XThe file ex1.mus contains all that is needed.  In this simple
  182. Xcase, that's not much.  The makefile runs ex1.mus through the mus
  183. Xpreprocessor, creating ex1.c.  Since all we want opie to do is
  184. Xreturn a scalar, we don't have to worry about the perl stack and the
  185. XCASE/END construction does the trick.
  186. X
  187. XExample 2
  188. X---------
  189. X
  190. XIn this example, we add two functions from exfns.c
  191. X
  192. X    int    andy(int);
  193. X    char * helen(int, char *);
  194. X
  195. Xand our own "magic" variable
  196. X    
  197. X    int Mayberry;
  198. X
  199. XThey will be used in perl like this
  200. X
  201. X    $n = &andy(0);
  202. X    $x = &helen($n, "crump"); # This could change the value of $Mayberry
  203. X    print $Mayberry, "\n";
  204. X    $Mayberry = 12;
  205. X
  206. XAgain, we can use mus directly for this, and the code is in
  207. Xex2.mus.  The main difference, other than using different function
  208. Xtypes is that we have two additional functions, userset and userval,
  209. Xwhich are used when we set or retrieve the value of a user variable,
  210. Xin this case $Mayberry.  Note the way in which these functions are
  211. Xregistered in userinit.
  212. X    
  213. XExample 3 (Harder Stuff - returning arrays)
  214. X-------------------------------------------
  215. X
  216. Xex3.mus is the same as ex2.mus, except that a new function,
  217. Xcalled otis has been added.  &otis($n) returns an array of the squares
  218. Xof the integers between 1 and $n.  This involves some messing around
  219. Xwith the perl stack, and using the function astore to enlarge the
  220. Xstack, the function str_nmake to create new numeric elements, and the
  221. Xfunction str_2mortal to let perl know that it can reclaim the memory
  222. Xused for the return value.
  223. X
  224. X
  225. X
  226. X
  227. ________This_Is_The_END________
  228. if test `wc -c < usub.doc` -ne     7077; then
  229.     echo 'shar: usub.doc was damaged during transit (should have been     7077 bytes)'
  230. fi
  231. fi        ; : end of overwriting check
  232. echo 'x - ex1.mus'
  233. if test -f ex1.mus; then echo 'shar: not overwriting ex1.mus'; else
  234. sed 's/^X//' << '________This_Is_The_END________' > ex1.mus
  235. X/*
  236. X *   Last edited by:  $Author: robt $
  237. X *               on:  $Date: 1992/08/29 19:49:20 $
  238. X *         Filename:  $RCSfile: ex1.mus,v $
  239. X *         Revision:  $Revision: 1.2 $
  240. X */
  241. X
  242. X#include "EXTERN.h"
  243. X#include "perl.h"
  244. X#include "exfns.h"
  245. X
  246. X/*
  247. X * Try dbxing your customized perl and stop in usersub to 
  248. X * see what's going on. Do this:
  249. X *
  250. X *          dbx myperl
  251. X *          (dbx) stop in usersub
  252. X *          (dbx) run -de 0
  253. X *
  254. X *          <DB>1 $x = &myFunction('hello');  # now you're in perl
  255. X *
  256. X * and you'll find yourself in usersub.
  257. X */ 
  258. X
  259. X
  260. X/*
  261. X * We'll be hooking in only one function, opie from exfns.c,
  262. X * and no variables.
  263. X */
  264. X
  265. Xstatic enum usersubs {
  266. X    US_opie
  267. X};
  268. X
  269. Xstatic int usersub();
  270. Xint userinit();
  271. X
  272. Xint 
  273. Xuserinit()
  274. X{
  275. X    char * filename = "ex1.mus";
  276. X    
  277. X    /* Register opie with perl */
  278. X    make_usub("opie", US_opie,    usersub, filename);
  279. X}
  280. X
  281. X
  282. X
  283. Xstatic int
  284. Xusersub(ix, sp, items)
  285. X    int ix;               /* the US_ value of the function being called */
  286. X    register int sp;      /* perl stack pointer                         */
  287. X    register int items;   /* # of args passed                           */
  288. X{
  289. X    STR **st = stack->ary_array + sp; /* used in code generated by mus */
  290. X    register STR *Str;        /* used in str_get and str_gnum macros */
  291. X
  292. X    switch (ix) {
  293. X
  294. X/* 
  295. X * Running mus ex1.mus > ex1.c will cause this to be expanded
  296. X * into code that will 1) check that exactly one item has been passed
  297. X * in, 2) extract the argument x from the stack, 3) call opie, and
  298. X * 4) return the value to perl.  Take a look at the output of mus.
  299. X */
  300. XCASE double opie
  301. XI   double x
  302. XEND
  303. X            
  304. X    default:
  305. X    fatal("Unimplemented user-defined subroutine");
  306. X    }
  307. X
  308. X    return sp;
  309. X}
  310. X
  311. X
  312. X
  313. ________This_Is_The_END________
  314. if test `wc -c < ex1.mus` -ne     1686; then
  315.     echo 'shar: ex1.mus was damaged during transit (should have been     1686 bytes)'
  316. fi
  317. fi        ; : end of overwriting check
  318. echo 'x - ex2.mus'
  319. if test -f ex2.mus; then echo 'shar: not overwriting ex2.mus'; else
  320. sed 's/^X//' << '________This_Is_The_END________' > ex2.mus
  321. X/*
  322. X *   Last edited by:  $Author: robt $
  323. X *               on:  $Date: 1992/08/29 19:49:20 $
  324. X *         Filename:  $RCSfile: ex2.mus,v $
  325. X *         Revision:  $Revision: 1.2 $
  326. X */
  327. X
  328. X#include "EXTERN.h"
  329. X#include "perl.h"
  330. X#include "exfns.h"
  331. X
  332. X/* 
  333. X *  We'll hook in three functions: opie, andy, and helen.
  334. X */
  335. Xstatic enum usersubs {
  336. X    US_opie,
  337. X    US_andy,
  338. X    US_helen
  339. X};
  340. X
  341. X/*
  342. X * We'll hook on one variable, Mayberry
  343. X */
  344. Xstatic enum uservars {
  345. X    UV_Mayberry
  346. X};
  347. X
  348. Xstatic int usersub();
  349. Xint userinit();
  350. Xstatic int userset();
  351. Xstatic int userval();
  352. X
  353. Xint 
  354. Xuserinit()
  355. X{
  356. X#define MAGICVAR(name, ix) uf.uf_index = ix, magicname(name, &uf, sizeof uf)
  357. X    char * filename = "ex2.mus";
  358. X    static struct ufuncs uf;
  359. X
  360. X    uf.uf_set = userset;
  361. X    uf.uf_val = userval;
  362. X
  363. X    make_usub("opie",  US_opie,  usersub, filename);
  364. X    make_usub("andy",  US_andy,     usersub, filename);
  365. X    make_usub("helen", US_helen, usersub, filename);
  366. X    MAGICVAR("Mayberry", UV_Mayberry);
  367. X}
  368. X
  369. X
  370. Xstatic int
  371. Xusersub(ix, sp, items)
  372. X    int ix;
  373. X    register int sp;
  374. X    register int items;
  375. X{
  376. X    STR **st = stack->ary_array + sp;
  377. X    register STR *Str;        /* used in str_get and str_gnum macros */
  378. X
  379. X    switch (ix) {
  380. X
  381. XCASE double opie
  382. XI   double x
  383. XEND
  384. X
  385. XCASE int andy
  386. XI   int x
  387. XEND
  388. X
  389. XCASE char * helen
  390. XI   int x
  391. XI   char * y
  392. XEND
  393. X            
  394. X    default:
  395. X    fatal("Unimplemented user-defined subroutine");
  396. X    }
  397. X
  398. X    return sp;
  399. X}
  400. X
  401. X
  402. Xstatic int
  403. Xuserval(ix, str)
  404. X    int ix;
  405. X    STR *str;
  406. X{
  407. X    switch (ix) {
  408. X    case UV_Mayberry:
  409. X    str_numset(str, (double)Mayberry);
  410. X    break;
  411. X    }
  412. X    return 0;
  413. X}
  414. X
  415. X
  416. Xstatic int
  417. Xuserset(ix, str)
  418. X    int ix;
  419. X    STR *str;
  420. X{
  421. X    switch (ix) {
  422. X    case UV_Mayberry:
  423. X        Mayberry = (double)str_gnum(str);
  424. X    break;
  425. X    }
  426. X    return 0;
  427. X}
  428. X
  429. ________This_Is_The_END________
  430. if test `wc -c < ex2.mus` -ne     1714; then
  431.     echo 'shar: ex2.mus was damaged during transit (should have been     1714 bytes)'
  432. fi
  433. fi        ; : end of overwriting check
  434. echo 'x - ex3.mus'
  435. if test -f ex3.mus; then echo 'shar: not overwriting ex3.mus'; else
  436. sed 's/^X//' << '________This_Is_The_END________' > ex3.mus
  437. X/*
  438. X *   Last edited by:  $Author: robt $
  439. X *               on:  $Date: 1992/08/29 19:49:20 $
  440. X *         Filename:  $RCSfile: ex3.mus,v $
  441. X *         Revision:  $Revision: 1.2 $
  442. X */
  443. X
  444. X#include "EXTERN.h"
  445. X#include "perl.h"
  446. X#include "exfns.h"
  447. X
  448. Xstatic enum usersubs {
  449. X    US_opie,
  450. X    US_andy,
  451. X    US_helen,
  452. X    US_otis
  453. X};
  454. X
  455. Xstatic enum uservars {
  456. X    UV_Mayberry
  457. X};
  458. X
  459. Xint userinit();
  460. Xstatic int usersub();
  461. Xstatic int userset();
  462. Xstatic int userval();
  463. X
  464. Xint 
  465. Xuserinit()
  466. X{
  467. X#define MAGICVAR(name, ix) uf.uf_index = ix, magicname(name, &uf, sizeof uf)
  468. X    char * filename = "ex2.mus";
  469. X    static struct ufuncs uf;
  470. X
  471. X    uf.uf_set = userset;
  472. X    uf.uf_val = userval;
  473. X
  474. X    make_usub("opie",  US_opie,  usersub, filename);
  475. X    make_usub("andy",  US_andy,     usersub, filename);
  476. X    make_usub("helen", US_helen, usersub, filename);
  477. X    make_usub("otis",   US_otis, usersub, filename);
  478. X    MAGICVAR("Mayberry", UV_Mayberry);
  479. X}
  480. X
  481. X
  482. Xstatic int
  483. Xusersub(ix, sp, items)
  484. X    int ix;
  485. X    register int sp;
  486. X    register int items;
  487. X{
  488. X    STR **st = stack->ary_array + sp; /* for stack access */
  489. X    register STR *Str;        /* used in str_get and str_gnum macros */
  490. X
  491. X    switch (ix) {
  492. X
  493. XCASE double opie
  494. XI   double x
  495. XEND
  496. X
  497. XCASE int andy
  498. XI   int x
  499. XEND
  500. X
  501. XCASE char * helen
  502. XI   int x
  503. XI   char * y
  504. XEND
  505. X    
  506. X      case US_otis:
  507. X      if (items != 1)
  508. X        fatal("Usage: &otis($x)");
  509. X      else {
  510. X        int n = (int) str_gnum(st[1]); /* argument passed from perl */
  511. X        int i;
  512. X
  513. X        if (n <= 0)
  514. X            fatal("Argument to &otis must be positive!");
  515. X
  516. X        astore(stack, sp + n, NULL); /* force stack to grow */
  517. X        st = stack->ary_array + sp;  /* stack may have changed */
  518. X        for (i = 1; i <= n; i++) {
  519. X            /* important: pass a double to str_nmake, not an int! */
  520. X            st[i-1] = str_2mortal(str_nmake( (double)(i*i) ));
  521. X        }
  522. X        return sp + n - 1;
  523. X    }
  524. X
  525. X            
  526. X    default:
  527. X    fatal("Unimplemented user-defined subroutine");
  528. X    }
  529. X
  530. X    return sp;
  531. X}
  532. X
  533. X
  534. Xstatic int
  535. Xuserval(ix, str)
  536. X    int ix;
  537. X    STR *str;
  538. X{
  539. X    switch (ix) {
  540. X    case UV_Mayberry:
  541. X    str_numset(str, (double)Mayberry);
  542. X    break;
  543. X    }
  544. X    return 0;
  545. X}
  546. X
  547. X
  548. Xstatic int
  549. Xuserset(ix, str)
  550. X    int ix;
  551. X    STR *str;
  552. X{
  553. X    switch (ix) {
  554. X    case UV_Mayberry:
  555. X        Mayberry = (int)str_gnum(str);
  556. X    break;
  557. X    }
  558. X    return 0;
  559. X}
  560. X
  561. X
  562. X
  563. ________This_Is_The_END________
  564. if test `wc -c < ex3.mus` -ne     2287; then
  565.     echo 'shar: ex3.mus was damaged during transit (should have been     2287 bytes)'
  566. fi
  567. fi        ; : end of overwriting check
  568. echo 'x - exfns.c'
  569. if test -f exfns.c; then echo 'shar: not overwriting exfns.c'; else
  570. sed 's/^X//' << '________This_Is_The_END________' > exfns.c
  571. X/*
  572. X *   Last edited by:  $Author: robt $
  573. X *               on:  $Date: 1992/08/29 19:56:24 $
  574. X *         Filename:  $RCSfile: exfns.c,v $
  575. X *         Revision:  $Revision: 1.2 $
  576. X */
  577. X
  578. X#include <stdio.h>
  579. X
  580. Xint Mayberry = 0;
  581. X
  582. Xdouble opie(x)
  583. X     double x;
  584. X{
  585. X    return x*x + 1.2;
  586. X}
  587. X
  588. Xint andy(x)
  589. X     int x;
  590. X{
  591. X    return x + Mayberry;
  592. X}
  593. X
  594. Xchar * helen(x, y)
  595. X     int x;
  596. X     char * y;
  597. X{
  598. X    static char buf[100];
  599. X
  600. X    sprintf(buf, "%d: %s", x, y);
  601. X
  602. X    Mayberry++;
  603. X
  604. X    return buf;
  605. X}
  606. X    
  607. ________This_Is_The_END________
  608. if test `wc -c < exfns.c` -ne      480; then
  609.     echo 'shar: exfns.c was damaged during transit (should have been      480 bytes)'
  610. fi
  611. fi        ; : end of overwriting check
  612. echo 'x - exfns.h'
  613. if test -f exfns.h; then echo 'shar: not overwriting exfns.h'; else
  614. sed 's/^X//' << '________This_Is_The_END________' > exfns.h
  615. X/*
  616. X *   Last edited by:  $Author: robt $
  617. X *               on:  $Date: 1992/08/29 19:31:21 $
  618. X *         Filename:  $RCSfile: exfns.h,v $
  619. X *         Revision:  $Revision: 1.1 $
  620. X */
  621. X
  622. Xextern int Mayberry;
  623. Xextern double opie();
  624. Xextern int andy();
  625. Xextern char * helen();
  626. X
  627. ________This_Is_The_END________
  628. if test `wc -c < exfns.h` -ne      266; then
  629.     echo 'shar: exfns.h was damaged during transit (should have been      266 bytes)'
  630. fi
  631. fi        ; : end of overwriting check
  632. echo 'x - makefile'
  633. if test -f makefile; then echo 'shar: not overwriting makefile'; else
  634. sed 's/^X//' << '________This_Is_The_END________' > makefile
  635. X# Makefile for perl usersub examples
  636. X# Last edited by:  $Author: robt $
  637. X#             on:  $Date: 1992/08/30 03:20:00 $
  638. X#       Filename:  $RCSfile: makefile,v $
  639. X#       Revision:  $Revision: 1.7 $
  640. X
  641. XCC=cc
  642. X
  643. X.SUFFIXES: .mus $(SUFFIXES)
  644. X.mus.c:
  645. X    mus $*.mus > $*.c
  646. X
  647. X# Path of your perl source goes here.  uperl.o must also be there.
  648. XPERLSRC = /u/robt/src/perl435
  649. XCFLAGS = -I$(PERLSRC)
  650. XLIBS = 
  651. X
  652. X
  653. Xall: ex1perl ex2perl ex3perl
  654. X
  655. Xex1perl: $(PERLSRC)/uperl.o exfns.o ex1.o
  656. X    $(CC) $(PERLSRC)/uperl.o exfns.o ex1.o $(LIBS) -o ex1perl
  657. X
  658. Xex2perl: $(PERLSRC)/uperl.o exfns.o ex2.o
  659. X    $(CC) $(PERLSRC)/uperl.o exfns.o ex2.o $(LIBS) -o ex2perl
  660. X
  661. Xex3perl: $(PERLSRC)/uperl.o exfns.o ex3.o
  662. X    $(CC) $(PERLSRC)/uperl.o exfns.o ex3.o $(LIBS) -o ex3perl
  663. X
  664. Xshar:  usub.doc ex[1-3].mus exfns.[ch] makefile extest.pl
  665. X    shar -h usub.shar usub.doc ex[1-3].mus exfns.[ch] makefile extest.pl
  666. X
  667. Xclean:
  668. X    rm -f *.o ex*perl ex[0-9].c
  669. ________This_Is_The_END________
  670. if test `wc -c < makefile` -ne      892; then
  671.     echo 'shar: makefile was damaged during transit (should have been      892 bytes)'
  672. fi
  673. fi        ; : end of overwriting check
  674. echo 'x - extest.pl'
  675. if test -f extest.pl; then echo 'shar: not overwriting extest.pl'; else
  676. sed 's/^X//' << '________This_Is_The_END________' > extest.pl
  677. X#  Last edited by:  $Author: robt $
  678. X#              on:  $Date: 1992/08/29 20:09:02 $
  679. X#        Filename:  $RCSfile: extest.pl,v $
  680. X#        Revision:  $Revision: 1.3 $
  681. X#  Run this using the sample perls ex[1-3]perl to see that 
  682. X#  things got hooked in correctly.
  683. X
  684. X#print "&opie is defined\n"      if ( defined(&opie) );
  685. X#print "&andy is defined\n"      if ( defined(&andy) );
  686. X#print "&helen is defined\n"     if ( defined(&helen) );
  687. X#print "&otis is defined\n"      if ( defined(&otis) );
  688. X#print "\$Mayberry is defined\n" if ( defined($Mayberry) );
  689. X
  690. Xif ( defined(&opie) ) {
  691. X    print "&opie is defined\n";
  692. X    print "\t&opie(10) = ", &opie(10), "\n";
  693. X} else {
  694. X    print "&opie is not defined\n";
  695. X}
  696. X
  697. X
  698. Xif ( defined(&andy) && defined($Mayberry) ) {
  699. X    print "&andy is defined\n";
  700. X    print "\t&andy(5) = ", &andy(5), "\n";
  701. X    $Mayberry = 7;
  702. X    print "\tAfter changing \$Mayberry to $Mayberry, &andy(5) = ", &andy(5), "\n";
  703. X} else {
  704. X    print "Either &andy or \$Mayberry is not defined\n";
  705. X}
  706. X
  707. X
  708. Xif ( defined(&helen) ) {
  709. X    print "&helen is defined\n";
  710. X    print "\t&helen(3, \"floyd\") = ", &helen(3, "floyd"), "\n";
  711. X    print "\t\$Mayberry = ", $Mayberry, "\n";
  712. X} else {
  713. X    print "&helen is not defined\n";
  714. X}
  715. X
  716. Xif ( defined(&otis) ) {
  717. X    print "&otis is defined\n";
  718. X    print "\t&otis(5) = ", join(' ', &otis(5)), "\n";
  719. X} else {
  720. X    print "&otis is not defined\n";
  721. X}
  722. X
  723. X
  724. X
  725. X
  726. ________This_Is_The_END________
  727. if test `wc -c < extest.pl` -ne     1370; then
  728.     echo 'shar: extest.pl was damaged during transit (should have been     1370 bytes)'
  729. fi
  730. fi        ; : end of overwriting check
  731. exit 0
  732. --
  733. -- Rob Torop
  734.  
  735. +---------------------------------------------------------------------+
  736. | The views expressed here are neither mine nor those of my employer. |
  737. +---------------------------------------------------------------------+
  738.