🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.amiga.tech
Article #8406

A small ARexx example, and other useful tidbits . . .

#8406
From: Kim DeVaughn
Date: Fri, 01 Apr 1988 23:11
311 lines
14680 bytes
[ "A car is just a big purse on wheels."   --Johanna Reynolds ]

In a recent posting concerning ARexx and IPC, as an example of ARexx's
scripting/macro capabilities, I made reference to an amicron initiated,
talking alarm clock program that one of my co-workers whipped off.

I hadn't really thought about posting it, until Peter da Silva catagorized
the REXX language as being "PL/I like".  Bunk.

So, in the interest of education, and with Bob Rethemeyer's permission
(he's the author), here's "cuckoo", along with a crontab file.

Also included is a 336-byte, "bare-bones", assembly language substitute
for the "say" command.  It's valuable in it's own right as an assembly
language example of using the  translator.library  and  narrator.device.

[ Coincidentally, I just saw a posting requesting assembly language examples
for inclusion into a freely redistributable library, similar in concept to
the Fish Disks.  Feel free to include "mumble". ]

Bear in mind that the REXX language has many more features, and power than
are used in "cuckoo".  It should, however, give you a "feel" for what the
language is like.  Note too, that this example makes implicit use of IPC
to communicate to AmigaDOS (where it invokes the "say" command [line 19],
and also where it invokes whatever is equated to "speak" [lines 8, 59, 60,
and 62], which in this case is "mumble").

Hope some of you find this example useful!

/kim


# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# cuckoo.rexx timeto.rexx sample.crontab mumble.asm mumble.uue

echo x - cuckoo.rexx
cat > "cuckoo.rexx" << '//E*O*F cuckoo.rexx//'
/* CUCKOO:  ANNOUNCES THE CURRENT TIME.   R. Rethemeyer  03-88 *
* Cuckoo is useful with AmiCron to announce times for events.  *
* The "MUMBLE" program is used for the voice output.           *
* If that is not available, change 'speak' to "sys:system/say".*
*  Usage: "RX CUCKOO [ALARM]"                                  *
* The ALARM option produces an obnoxious noise and message.   */
/*--------------------------------------------------------------------*/
speak="Mumble"  /* PROGRAM FOR VOICE OUTPUT */
nice="Excuse me sir, the time iz now"  /* NORMAL MESSAGE */
nasty="All right u bum, get up. Nouw. The time iz" /* ALARM MESSAGE */
dingaling="gggggggggggggggggggggggggggg"   /* OBNOXIOUS ALARM NOISE */
/*--------------------------------------------------------------------*/
arg opt
if opt="ALARM" then intro=nasty ; else intro=nice
zhour = time('h')
xmin  = time('m')
xmin  = xmin-((xmin%60)*60)
xhour = zhour
say "Cuckoo at" zhour||":"||xmin
mnite = " "
if zhour > 12 then xhour = zhour-12
select
  when xhour=0  then do; xhour="twelve"; if xmin=0 then mnite="midnite"; end
  when xhour=11 then xhour = "elaven"
  when xhour=12 then do; xhour="twelve"; if xmin=0 then mnite="noon"; end
  otherwise nop
end
smin=" "
if xmin=0 then tmin = "o clock"
else do
  tmin=xmin%10
  if tmin=1 then do;
       select
         when xmin=10 then  tmin = "ten"
         when xmin=11 then  tmin = "elaven"
         when xmin=12 then  tmin = "twelve"
         when xmin=13 then  tmin = "thirt teen"
         when xmin=14 then  tmin = "fourt teen"
         when xmin=15 then  tmin = "fif teen"
         when xmin=16 then  tmin = "six teen"
         when xmin=17 then  tmin = "seven teen"
         when xmin=18 then  tmin = "eight teen"
         when xmin=19 then  tmin = "nine teen"
       end
  end
  else do
   smin=xmin
   if xmin>9 then smin=xmin-(tmin*10)
   if smin=0 then smin=" "
   select
     when tmin=0 then tmin = "oh"
     when tmin=2 then tmin = "twenty"
     when tmin=3 then tmin = "thirty"
     when tmin=4 then tmin = "forty"
     when tmin=5 then tmin = "fifty"
   end
  end
end
if opt="ALARM" then address COMMAND speak dingaling
address COMMAND speak intro xhour tmin smin mnite "."
if tmin="o clock" & opt="ALARM" then ,
  address COMMAND speak "I repeat," xhour tmin "."
exit
//E*O*F cuckoo.rexx//

echo x - timeto.rexx
cat > "timeto.rexx" << '//E*O*F timeto.rexx//'
/* speak a sentence prefixed by time */
parse arg sentence
cuckoo /* announce the time first */
address command "mumble Its time to " sentence "."
exit
//E*O*F timeto.rexx//

echo x - sample.crontab
cat > "sample.crontab" << '//E*O*F sample.crontab//'
0,15,30,45 * * * * rx cuckoo
0,10,20,30,40,50 7 * * 1-5 rx cuckoo alarm
30 7,18 * * * rx timeto feed the cat
//E*O*F sample.crontab//

echo x - mumble.asm
cat > "mumble.asm" << '//E*O*F mumble.asm//'
         PLEN 60
**********************************************************************
*    Program:  MUMBLE - bare-bones CLI substitute for SAY command    *
*    Author:   Robert Rethemeyer, Sunnyvale, CA  (@BBS-HT or BBS-JC) *
*    Revision: 0.1  03/30/88 initial release                         *
*    Status:   RELEASED TO THE PUBLIC DOMAIN, "AS-IS"                *
**********************************************************************
* MUMBLE is a very small CLI program which speaks the text on the    *
* command line using the Amiga's translator/narrator voice output.   *
* It is convenient for use in CLI or ARexx scripts.                  *
* Command usage:    MUMBLE <text>                                    *
**********************************************************************
* MUMBLE provides a function similar to the command line usage of    *
* the SAY command, but takes much less memory and disk space         *
* (300 bytes vs. 9K+).  It is not, however, as versatile as SAY.     *
* There are no -options; the voice parameters are fixed, and the     *
* program will not run in window mode or read from a file.           *
**********************************************************************
* Mumble return codes:
*   0= success
*   1-9,20-26= narrator IO error
*   11= could not allocate memory
*   12= could not open translator.library
*   13= could not open narrator.device
**********************************************************************
         NOLIST
  INCLUDE "exec/types.i"
  INCLUDE "exec/io.i"
  INCLUDE "exec/ports.i"
  INCLUDE "exec/memory.i"
  INCLUDE "devices/narrator.i"
         LIST
         XREF  _LVOOpenLibrary
         XREF  _LVOCloseLibrary
         XREF  _LVOAllocMem
         XREF  _LVOFreeMem
         XREF  _LVOOpenDevice
         XREF  _LVOCloseDevice
         XREF  _LVOTranslate
         XREF  _LVOFindTask
         XREF  _LVOAddPort
         XREF  _LVORemPort
         XREF  _LVODoIO
ExecBase EQU   4
execptr  EQUR  A6
**********************************************************************
* Voice parameters can be changed here, to user's liking:
VSEX     EQU   MALE           MALE/FEMALE/DEFSEX
VMODE    EQU   NATURALF0      NATURALF0/ROBOTICF0/DEFMODE
VRATE    EQU   180            40-400/DEFRATE
VFREQ    EQU   DEFFREQ        5000-28000/DEFFREQ
VPITCH   EQU   DEFPITCH       65-320/DEFPITCH
VVOL     EQU   DEFVOL         0-64/DEFVOL
**********************************************************************
Mumble:
         MOVEQ   #0,d5                       return code if parmlen=0
         MOVE.L  d0,d4              SAVE EXECUTION PARMS  parmlen
         BEQ     endprog                     do nothing if parmlen=0
         MOVE.L  a0,d3                       save parmaddr
         MOVE.L  ExecBase,execptr            a6=exec lib pointer
*                                   ALLOCATE SCRATCH MEMOR%
         MOVEQ   #11,d5                      return code if this fails
         ASL.L   #2,d0                       size of TRarea = parmlen*4
         ADD.L   #scratchlen,d0              add to size of scratch area
         MOVE.L  d0,d6                       remember for deallocate later
         MOVE.L  #MEMF_PUBLIC+MEMF_CLEAR,d1  mem flags
         JSR     _LVOAllocMem(execptr)       ask for the storage
         MOVE.L  d0,a3                       a3=scratch area ptr
         BEQ     broke1                      abort if request failed
*                                   OPEN TRANSLATOR LIBRARY
         MOVEQ   #12,d5                      return code if this fails
         LEA     tranlib(pc),a1              addr of library name
         MOVEQ   #0,d0                       any version will do
         JSR     _LVOOpenLibrary(execptr)    get library pointer
         MOVE.L  d0,a5                       a5=tran lib pointer
         BEQ     broke2                      back out if no lib
*                                   TRANSLATE COMMAND LINE PARAMETER
         MOVE.L  d3,a0                       retrieve parmaddr
         MOVE.L  d4,d0                       and parmlen
         LEA     TRarea(a3),a1               point to xlat out buff
         ASL.L   #2,d4                       figure out buff length again
         MOVE.L  d4,d1                       for func (and save for later)
         JSR     _LVOTranslate(a5)           translate to phonemes
         MOVE.L  a5,a1                       :
         JSR     _LVOCloseLibrary(execptr)   close trans lib
*                                   INIT NARRATOR DEVICE PORT
         MOVE.L  #0,a1                       :
         JSR     _LVOFindTask(execptr)       identify this task
         MOVE.L  d0,Narport+MP_SIGTASK(a3)   let narrator find it
         LEA     Narport(a3),a1              point to the port area
         JSR     _LVOAddPort(execptr)        install narrator port
*                                   INIT NARRATOR DEVICE
         MOVEQ   #13,d5                      return code if this fails
         LEA     Narname(pc),a0              point to device name
         MOVEQ   #0,d0                       unit 0
         LEA     Nardev(a3),a1               point to device structure
         MOVEQ   #0,d1                       no flags
         JSR     _LVOOpenDevice(execptr)     open narrator device
         TST.L   d0                          if device open failed
         BNE.S   broke3                      then back out
*                                   INIT DEVICE STUFF
         LEA     Nardev(a3),a1               a1=device structure
         LEA     Narport(a3),a0              a0=port address
         MOVE.L  a0,MN_REPLYPORT(a1)         give port addr to device
         LEA     audmaps(pc),a0              audio maps
         MOVE.L  a0,NDI_CHMASKS(a1)          addr of maps
         MOVE.W  #4,NDI_NUMMASKS(a1)         number of masks
         MOVE.W  #VPITCH,NDI_PITCH(a1)       init pitch
         MOVE.W  #VRATE,NDI_RATE(a1)         init rate
         MOVE.W  #VVOL,NDI_VOLUME(a1)        init volume
         MOVE.W  #VFREQ,NDI_SAMPFREQ(a1)     init sample freq
         MOVE.W  #VSEX,NDI_SEX(a1)           init sex
         MOVE.W  #VMODE,NDI_MODE(a1)         init mode
         MOVE.W  #CMD_WRITE,IO_COMMAND(a1)   init device command
         MOVE.L  d4,IO_LENGTH(a1)            length of buffer
         LEA     TRarea(a3),a0               addr of buffer
         MOVE.L  a0,IO_DATA(a1)              :
*                                   THE MOMENT OF TRUTH
         JSR     _LVODoIO(execptr)           do i/o, wait for reply
         MOVE.L  d0,d5                       save return code
         NEG.L   d5                          convert rc to positive
*                                   CLEAN UP AND RETURN
         LEA     Nardev(a3),a1               point to device structure
         JSR     _LVOCloseDevice(execptr)    release device
broke3   LEA     Narport(a3),a1              point to port
         JSR     _LVORemPort(execptr)        delete the port
broke2   MOVE.L  d6,d0                       length of scratch area
         MOVE.L  a3,a1                       addr of scratch area
         JSR     _LVOFreeMem(execptr)        free scratch mem
broke1   MOVE.L  d5,d0                       set return code
endprog  RTS                        ALL DONE!
************************************************************
         CNOP    0,2
tranlib  DC.B    'translator.library',0
         CNOP    0,2
narname  DC.B    'narrator.device',0
         CNOP    0,2
audmaps  DC.B    3,5,10,12         Audio device maps
*************************************************************
version  DC.B    'MUMBLE V0.1 RAR' Imbedded version info
*************************************************************
    STRUCTURE Scratch,0            Format of allocated scratch mem
      STRUCT   Narport,MP_SIZE     Message reply port for narrator
      STRUCT   Nardev,NDI_SIZE     Narrator IO block
      LABEL  scratchlen            Length of scratch area less TRarea
      STRUCT   TRarea,0            xlat out buff (size computed dynamically)
         END                       and there ain't no more
//E*O*F mumble.asm//

echo x - mumble.uue
cat > "mumble.uue" << '//E*O*F mumble.uue//'

begin 755 mumble
M```#\P`````````!``````````````!+```#Z0```$MZ`"@`9P``ZB8(+'@`^
M!'H+Y8`&@````&@L`"(\``$``4ZN_SHF0&<``,9Z#$/Z`,1P`$ZN_=@J0&<`)
M`*P@0R`$0^L`:.6$(@1.K?_B(DU.KOYB(GP`````3J[^VB=``!!#ZP``3J[^0
MGGH-0?H`FG``0^L`(G(`3J[^1$J`9F!#ZP`B0>L``"-(``Y!^@"*(T@`.#-\&
M``0`/#-\`&X`,C-\`+0`,#-\`$``/C-\5K@`0#-\````-C-\````-#-\``,`&
M'"-$`"1!ZP!H(T@`*$ZN_C@J`$2%0^L`(DZN_CY#ZP``3J[^F"`&(DM.KO\NW
M(`5.=71R86YS;&%T;W(N;&EB<F%R>0``;F%R<F%T;W(N9&5V:6-E``,%"@Q-'
554U"3$4@5C`N,2!205(```````/RT
``
end
size 336
//E*O*F mumble.uue//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
 63  331  2294  cuckoo.rexx
 5  28  152  timeto.rexx
 3  25  109  sample.crontab
 147  730  8084  mumble.asm
 13  15  506  mumble.uue
 231  1129  11145  total
!!!
wc  cuckoo.rexx timeto.rexx sample.crontab mumble.asm mumble.uue | sed 's=[^ ]*/==' | diff -b $temp -
exit 0

-- 
UUCP:  kim@amdahl.amdahl.com
  or:  {sun,decwrl,hplabs,pyramid,ihnp4,uunet,oliveb,cbosgd,ames}!amdahl!kim
DDD:   408-746-8462
USPS:  Amdahl Corp.  M/S 249,  1250 E. Arques Av,  Sunnyvale, CA 94086
CIS:   76535,25
Technical Details
Message-ID: <26223@amdahl.uts.amdahl.com>
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!lll-winken!lll-lcc!ames!oliveb!amdahl!kim

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!lll-winken!lll-lcc!ames!oliveb!amdahl!kim
From: kim@amdahl.uts.amdahl.com (Kim DeVaughn)
Newsgroups: comp.sys.amiga.tech,comp.sys.amiga
Subject: A small ARexx example, and other useful tidbits . . .
Message-ID: <26223@amdahl.uts.amdahl.com>
Date: 1 Apr 88 23:11:35 GMT
Organization: Amdahl Corporation,  Sunnyvale, CA 94086
Lines: 310
Keywords: Warning: also contains a small assembly language example!