home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / utilities / zap / !Zap / 3rdParty / UtilsSrc (.txt) < prev    next >
Encoding:
RISC OS BBC BASIC V Source  |  1994-01-04  |  25.3 KB  |  840 lines

  1.  E-Template
  2.  Template program for creating Zap modes.
  3.  The module will be saved to work_directory$
  4.  You should run Zap first to ensure Zap$Dir and ZapWork$Dir
  5.  are set up.
  6.  directory to save module
  7.     "work_directory$="<ZapMod$Dir>"
  8.  name of mode
  9. mode_name$="Utils"
  10.  authors name
  11. mode_author$="Paul Moore"
  12.  version number of module
  13. ver$="0.03"
  14.  mode number you want to be
  15.  you MUST not hard wire this in as I may have allocated it
  16.  to someone else!
  17.  mode_number=15
  18.  mode to base this mode on (text)
  19.  mode_basemode=0
  20.  define a proc error to print line number even if running
  21.  under wimp.
  22. error
  23.  reserve space for code / workspace
  24.  default of 64k
  25. code_size%=&10000
  26.  code% code_size%
  27. L%=code%+code_size%
  28.  load the library defining zap's variables
  29.  "<ZapWork$Dir>.Docs.E-Library"
  30.  define zaps constants (call E-Library)
  31. define_zap_variables
  32.  define any variables in our workspace
  33. set_up_variables
  34.  assemble the code
  35. assemble_code
  36.  save the module
  37.  "OS_File",&0A,work_directory$+".Zap"+mode_name$,&FFA,0,code%,code%+length%
  38.  "Zap";mode_name$+" module created and saved"
  39.  define any variables we want to store in the module workspace
  40. set_up_variables
  41.  buflen% = length of OS command buffer
  42.  parmct% = number of argsub parameters
  43. buflen% = 255
  44.  pass=%1100 
  45.  %1110 
  46.  2:P%=0:O%=code%:[OPTpass
  47. .search_parm        EQUD 0
  48. C%.cmd_buf            
  49. res(buflen%)
  50. variable_size%=P%
  51.  assemble the main code
  52. assemble_code
  53.  define flags
  54. Iflag%=1<<27
  55. Vflag%=1<<28
  56. Cflag%=1<<29
  57.  define register numbers (for macros)
  58. U<R0=0:R1=1:R2=2:R3=3:R4=4:R5=5:R6=6:R7=7:R8=8:R9=9:R10=10
  59. V,R11=11:R12=12:R13=13:R14=14:R15=15:PC=15
  60.  pass=%1100 
  61.  %1110 
  62.  2:P%=0:O%=code%
  63. [OPTpass
  64. .Module_header
  65. \ .Start_code           EQUD 0
  66. ]..Initialisation_code  EQUD initialise_code
  67. ^,.Finalisation_code    EQUD finalise_code
  68. _ .Service_call_handler EQUD 0
  69. `+.Title_string         EQUD title_string
  70. a*.Help_string          EQUD help_string
  71. b .Command_keyword_tab  EQUD 0
  72. c .SWI_chunk_number     EQUD 0
  73. d .SWI_handler_code     EQUD 0
  74. e .SWI_decoding_table   EQUD 0
  75. f .SWI_decoding_code    EQUD 0
  76. hD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  77. iB\ TITLES 
  78.  COMMAND TABLES                                    \
  79. jD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  80. .help_string
  81. S("Zap"+mode_name$+
  82. 9+ver$+" ("+
  83. date+") 
  84.  "+mode_author$)
  85. .title_string
  86. S("Zap"+mode_name$)
  87. rD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  88. sB\ INITIALISE 
  89.  FINALISE                                      \
  90. tD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  91. .initialise_code
  92. MOV R0,#6
  93. LDR R3,var_size
  94. z;SWI "XOS_Module"              \ claim varable workspace
  95. RTSVS
  96. |CMOV R11,R2                    \ claimed block (R11 from now on)
  97. }@STR R11,[R12]                 \ save as my workspace pointer
  98. ~=STR R11,workspace_address     \ save it in the module for
  99. 7MOV R0,#18                    \ accessing commands.
  100. ADR R1,zap_title
  101. ,SWI "XOS_Module"              \ find zap
  102. RTSVS                       \ not found
  103. 1MOV R12,R4                    \ zap workspace
  104. 9ADR R0,key_command_table      \ add table of commands
  105. call(Zap_AddCommands)
  106. RTSVS
  107. MOV R1,#0
  108. MOV R2,R11
  109. LDR R3,var_size
  110. call(Zap_FillWords)         \ clear workspace to zeros
  111. .var_size
  112. EQUD variable_size%
  113. .zap_title
  114. S("Zap")
  115. .workspace_address
  116. EQUD 0
  117. \X R11=module workspace |
  118. .get_workspace
  119. LDR R11,workspace_address
  120. MOV PC,R14
  121. .finalise_code
  122. MOV R0,#7
  123. LDR R2,[R12]
  124. 2SWI "XOS_Module"              \ free workspace
  125. RTSVS
  126. MOV R0,#0
  127. 5STR R0,[R12]                  \ null private word
  128. A\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  129. A\ Command table                                             \
  130. A\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  131. .key_command_table
  132. EQUD key_command_table
  133. 5EQUD 0                        \ service call code
  134. com("FILTERSEL",filtersel)
  135. com("WINLEFT",winleft)
  136. com("WINRIGHT",winright)
  137. com("WINUP",winup)
  138. com("WINDOWN",windown)
  139. com("DELWORDLEFT",delwordleft)
  140. com("DELWORDRIGHT",delwordright)
  141. com("SEARCHWORD",searchword)
  142. com("FW",fw)
  143. com("BW",bw)
  144. 'EQUD 0                        \ end
  145. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  146. D\ Word movement commands                                       \
  147. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  148. EQUD (1<<12)
  149. STMFD R13!,{R14}
  150. LDR R0,[R10,#c_off]
  151. TEQ R1,#0
  152.     .fw01
  153. BLNE fwd_word
  154. SUBNES R1,R1,#1
  155. BNE fw01
  156. call(Zap_JumptoOffset)
  157. LDMFD R13!,{PC}
  158. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  159. EQUD (1<<12)
  160. STMFD R13!,{R14}
  161. LDR R0,[R10,#c_off]
  162. TEQ R1,#0
  163.     .bw01
  164. BLNE back_word
  165. SUBNES R1,R1,#1
  166. BNE bw01
  167. call(Zap_JumptoOffset)
  168. LDMFD R13!,{PC}
  169. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  170. D\ Word deletion commands                                       \
  171. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  172. EQUD 0
  173. .delwordleft
  174. STMFD R13!,{R14}
  175. LDR R3,[R10,#c_off]
  176. MOV R0,R3
  177. TEQ R1,#0
  178. .dwl01
  179. BLNE back_word
  180. SUBNES R1,R1,#1
  181. BNE dwl01
  182. .\\\ R0 = start of block, R3 = end of block
  183. MOV R1,R0
  184. SUB R2,R3,R0
  185. call(Zap_StartOp)
  186. BVS dwl02
  187. MOV R0,#2
  188. call(Zap_Command)
  189. BVS dwl02
  190. call(Zap_StopOp)
  191. .dwl02
  192. LDMFD R13!,{PC}
  193. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  194. EQUD (1<<12)
  195. .delwordright
  196. STMFD R13!,{R14}
  197. LDR R3,[R10,#c_off]
  198. MOV R0,R3
  199. TEQ R1,#0
  200. .dwr01
  201. BLNE fwd_word
  202. SUBNES R1,R1,#1
  203. BNE dwr01
  204. .\\\ R3 = start of block, R0 = end of block
  205. MOV R1,R3
  206. SUB R2,R0,R3
  207. call(Zap_StartOp)
  208. BVS dwr02
  209. MOV R0,#2
  210. call(Zap_Command)
  211. BVS dwr02
  212. call(Zap_StopOp)
  213. .dwr02
  214. LDMFD R13!,{PC}
  215. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  216. D\ Word search commands                                         \
  217. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  218. EQUD (2<<3)+(1<<12)
  219. .searchword
  220. STMFD R13!,{R14}
  221. BL get_workspace
  222. MOV R2,R0
  223. TEQ R1,#0
  224. BEQ sw02
  225. !    .sw01
  226. LDR R0,[R2],#4
  227. STR(R0,search_parm)
  228. BL search_rtn
  229. BVS sw02
  230. SUBS R1,R1,#1
  231. BNE sw01
  232. )    .sw02
  233. LDMFD R13!,{PC}
  234. ,D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  235. .search_rtn
  236. STMFD R13!,{R1-R7,R14}
  237. 08LDR R7,[R10,#c_off]     \ R7 = current cursor offset
  238. MOV R0,R7
  239. BL getc_off
  240. BL wordchar
  241. BCC sr_err
  242. 7    .sr01
  243. TEQ R0,#0
  244. BEQ sr02
  245. SUB R0,R0,#1
  246. BL getc_off
  247. BL wordchar
  248. BCS sr01
  249. ADD R0,R0,#1
  250. ?    .sr02
  251. A0MOV R5,R0               \ R5 = start of word
  252. C.LDR R2,[R9,#f_len]      \ R2 = file length
  253. MOV R0,R7
  254. E    .sr03
  255. CMP R0,R2
  256. MOVHS R0,R2
  257. BHS sr04
  258. ADD R0,R0,#1
  259. BL getc_off
  260. BL wordchar
  261. BCS sr03
  262. M    .sr04
  263. O2MOV R6,R0               \ R6 = end of word + 1
  264. P1SUB R4,R6,R5            \ R4 = length of word
  265. ADD R0,R4,#1
  266. call(Zap_Claim)
  267. LDMVSFD R13!,{R1-R7,PC}
  268. U-MOV R7,R0               \ R7 = heap block
  269. LDR R0,[R9,#f_splito]
  270. CMP R5,R0
  271. CMPLT R0,R6
  272. BLT sr05
  273. \ Word is in one part
  274. LDR R1,[R9,#f_ptr]
  275. ADD R1,R1,R5
  276. MOV R2,R7
  277. MOV R3,R4
  278. call(Zap_MoveBytes)
  279. BVS err_free
  280. B sr06
  281. \ Word is in two parts
  282. f    .sr05
  283. LDR R1,[R9,#f_ptr]
  284. ADD R1,R1,R5
  285. MOV R2,R7
  286. SUB R3,R0,R5
  287. STMFD R13!,{R1-R3}
  288. call(Zap_MoveBytes)
  289. BVS err_free
  290. LDMFD R13!,{R1-R3}
  291. LDR R0,[R9,#f_splits]
  292. ADD R1,R1,R0
  293. ADD R1,R1,R3
  294. ADD R2,R2,R3
  295. SUB R3,R4,R3
  296. call(Zap_MoveBytes)
  297. BVS err_free
  298. w    .sr06
  299. y,\ Word is now on heap. Zero-terminate it
  300. MOV R0,#0
  301. STRB R0,[R7,R4]
  302. }*\ Work out what type of search we want
  303. \  0 = to buffer
  304. 3\ +1 = from here, forward        ie, next match
  305. 7\ -1 = from here, backward       ie, previous match
  306. 4\ +2 = from start, forward       ie, first match
  307. 3\ -2 = from start, backward      ie, last match
  308. \ others are errors
  309. LDR(R0,search_parm)
  310. CMP R0,#0
  311. Q R1,#1               \ To buffer for type 0
  312. @MOVNE R1,#2               \ Otherwise, get file offset in R0
  313. 9MOVPL R4,#1               \ Forwards, unless type < 0
  314. .MOVMI R4,#0               \ when backwards
  315. EMOVPL R3,R6               \ For forward search, start at word end
  316. HMOVMI R3,R5               \ For backward search, start at word start
  317. BRSBMI R0,R0,#0            \ Get the absolute value of the type
  318. CMP R0,#1
  319. @MOVNE R3,#0               \ From start, unless abs(type) = 1
  320. \ Do the search
  321. MOV R0,R7
  322. MOV R5,#0
  323. call(Zap_Search)
  324. BVS err_free
  325. ,\ If we got a throwback buffer, stop now
  326. CMP R1,#1
  327. LDMEQFD R13!,{R1-R7,PC}
  328. CMP R0,#0
  329. BMI sr_notfound
  330. call(Zap_GotoOffset)
  331. BVS err_free
  332. MOV R0,R7
  333. call(Zap_Free)
  334. LDMFD R13!,{R1-R7,PC}
  335. .err_free
  336. MOV R1,R0
  337. MOV R0,R7
  338. call(Zap_Free)
  339. MOV R0,R1
  340. LDMFD R13!,{R1-R7,R14}
  341. RS PC,R14,#Vflag%
  342. .sr_notfound
  343. MOV R0,R7
  344. call(Zap_Free)
  345. ADR R0,sr_no
  346. LDMFD R13!,{R1-R7,R14}
  347. RS PC,R14,#Vflag%
  348. .sr_err
  349. ADR R0,sr_error
  350. LDMFD R13!,{R1-R7,R14}
  351. RS PC,R14,#Vflag%
  352. .sr_error
  353. EQUD 0
  354. S("Not in a word")
  355. .sr_no
  356. EQUD 0
  357. S("Not found")
  358. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  359. D\ Subroutines                                                  \
  360. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  361. #\ Move one word forward in file
  362. 7\ (In) R0 = file offset, (Out) R0 = new file offset
  363. .fwd_word
  364. STMFD R13!,{R1-R2,R14}
  365. LDR R2,[R9,#f_len]
  366. CMP R0,R2
  367. MOVHS R0,R2
  368. BHS fw_eof
  369.     .fw01
  370. BL getc_off
  371. BL wordchar
  372. BCC fw02
  373. ADD R0,R0,#1
  374. CMP R0,R2
  375. BHS fw_eof
  376. B fw01
  377.     .fw02
  378. ADD R0,R0,#1
  379. CMP R0,R2
  380. BHS fw_eof
  381. BL getc_off
  382. BL wordchar
  383. BCC fw02
  384. .fw_eof
  385. LDMFD R13!,{R1-R2,PC}^
  386. $\ Move one word backward in file
  387. 7\ (In) R0 = file offset, (Out) R0 = new file offset
  388. .back_word
  389. STMFD R13!,{R1,R14}
  390.     .bw01
  391. SUBS R0,R0,#1
  392. BMI bw_eof
  393. BL getc_off
  394. BL wordchar
  395. BCC bw01
  396.     .bw02
  397. SUBS R0,R0,#1
  398. BMI bw_eof
  399. BL getc_off
  400. BL wordchar
  401. BCS bw02
  402. .bw_eof
  403. ADD R0,R0,#1
  404. LDMFD R13!,{R1,PC}^
  405. (\ Get a character from a file buffer
  406. '\ (In) R0=file offset (Out) R1=char
  407. .getc_off
  408. STMFD R13!,{R0,R14}
  409. LDR R1,[R9,#f_splito]
  410. CMP R0,R1
  411. LDRCS R1,[R9,#f_splits]
  412. ADDCS R0,R0,R1
  413. LDR R1,[R9,#f_ptr]
  414. LDRB R1,[R1,R0]
  415. LDMFD R13!,{R0,PC}^
  416. 5\ Check whether a character is a word constituent
  417. ,\ (In) R1=char (Out) CS=Word, CC=NonWord
  418. .wordchar
  419. STMFD R13!,{R0-R2,R14}
  420. ADR R0,wordtab
  421. MOV R2,R1,LSR #5
  422. LDR R0,[R0,R2,ASL #2]
  423.  R1,R1,#&1F
  424. ADD R1,R1,#1
  425. MOVS R0,R0,LSR R1
  426. LDMFD R13!,{R0-R2,PC}
  427. %\ Word characters (A-Z,a-z,0-9,_)
  428. .wordtab
  429. #EQUD &00000000        \ &00-&1F
  430. )EQUD &03FF0000        \ &20-&3F (0-9)
  431. /EQUD &87FFFFFE        \ &40-&5F (A-Z and _)
  432. )EQUD &07FFFFFE        \ &60-&7F (a-z)
  433. #EQUD &00000000        \ &80-&9F
  434.  #EQUD &00000000        \ &A0-&BF
  435. !#EQUD &00000000        \ &C0-&DF
  436. "#EQUD &00000000        \ &E0-&FF
  437. $D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  438. %D\ Window Movement Commands                                     \
  439. &D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  440. EQUD (2<<3)+(1<<12)
  441. .winleft
  442. STMFD R13!,{R14}
  443. BL getarg
  444. LDR R0,[R8,#w_minx]
  445. SUB R0,R0,R2
  446. STR R0,[R8,#w_minx]
  447. LDR R0,[R8,#w_maxx]
  448. SUB R0,R0,R2
  449. STR R0,[R8,#w_maxx]
  450. MOV R0,#1
  451. MOV R1,R8
  452. call(Zap_OpenWindow)
  453. LDMFD R13!,{PC}
  454. <D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  455. EQUD (2<<3)+(1<<12)
  456. .winright
  457. STMFD R13!,{R14}
  458. BL getarg
  459. LDR R0,[R8,#w_minx]
  460. ADD R0,R0,R2
  461. STR R0,[R8,#w_minx]
  462. LDR R0,[R8,#w_maxx]
  463. ADD R0,R0,R2
  464. STR R0,[R8,#w_maxx]
  465. MOV R0,#1
  466. MOV R1,R8
  467. call(Zap_OpenWindow)
  468. LDMFD R13!,{PC}
  469. RD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  470. EQUD (2<<3)+(1<<12)
  471. .winup
  472. STMFD R13!,{R14}
  473. BL getarg
  474. LDR R0,[R8,#w_miny]
  475. ADD R0,R0,R2
  476. STR R0,[R8,#w_miny]
  477. LDR R0,[R8,#w_maxy]
  478. ADD R0,R0,R2
  479. STR R0,[R8,#w_maxy]
  480. MOV R0,#1
  481. MOV R1,R8
  482. call(Zap_OpenWindow)
  483. LDMFD R13!,{PC}
  484. hD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  485. EQUD (2<<3)+(1<<12)
  486. .windown
  487. STMFD R13!,{R14}
  488. BL getarg
  489. LDR R0,[R8,#w_miny]
  490. SUB R0,R0,R2
  491. STR R0,[R8,#w_miny]
  492. LDR R0,[R8,#w_maxy]
  493. SUB R0,R0,R2
  494. STR R0,[R8,#w_maxy]
  495. MOV R0,#1
  496. MOV R1,R8
  497. call(Zap_OpenWindow)
  498. LDMFD R13!,{PC}
  499. ~D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  500. /\ (In)  R0=list of words, R1=number in list
  501. .\ (Out) R2=sum of list, R0,R1,R3 corrupted
  502. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  503. .getarg
  504. MOV R2,#0
  505. SUBS R1,R1,#1
  506. LDRPL R3,[R0],#4
  507. ADDPL R2,R2,R3
  508. BPL L01
  509. MOVS PC,R14
  510. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  511. D\ Filter Selection Command                                     \
  512. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  513. EQUD 1+(3<<3)+(1<<6)
  514. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  515. -\ (Uses) R7=command string, R6=heap block
  516. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  517. .filtersel
  518. .\\ Are we being asked for a prompt string?
  519. TEQ R2,#6
  520. BEQ add_prompt
  521. 1\\ Remember the minibuffer contents for later
  522. MOV R7,R0
  523. ,\\ Get the selected area to a heap block
  524. call(Zap_ReadSel)           \ (Out) R2=len, R3=block
  525. BVS error_ret
  526. TEQ R3,#0
  527. <BEQ error_nosel               \ Error if there isn't one
  528. 1\\ Save the selected area to a temporary file
  529. ADR R1,file_in
  530. FBL save                       \ (In) R1=filename, R2=len, R3=block
  531. BVS error_ret
  532. \\ Free the heap block
  533. MOV R0,R3
  534. call(Zap_Free)              \ (In) R0=block
  535. BVS error_ret
  536. \\ Filter the file
  537. MOV R0,R7
  538. ADR R1,file_in
  539. ADR R2,file_out
  540. HBL filter_file                \ (In) R0=command, R1=input, R2=output
  541. BVS error_ret
  542. .\\ Find the length of the replacement file
  543. ADR R1,file_out
  544. =BL get_len                    \ (In) R1=file (Out) R0=len
  545. BVS error_ret
  546. AMOV R4,R0                     \ Save filesize in R4 for later
  547. ,\\ Get the necessary space on Zap's heap
  548. call(Zap_Claim)             \ (In) R0=size (Out) R0=block
  549. BVS error_ret
  550. CMOV R3,R0                     \ Save block addr in R3 for later
  551.  \\ Load the replacement file
  552. ADR R1,file_out
  553. :BL load_file                  \ (In) R0=block, R1=file
  554. BVS error_ret
  555. 6\\ Get the file offset and length of the selection
  556. call(Zap_GetSel)            \ (Out) CC, R1=offset, R2=len
  557. LBCS error_nosel               \ Error if there isn't one - cannot happen
  558. BVS error_ret
  559. 2\\ Replace the selection with the changed text
  560. call(Zap_StartOp)
  561. BVS error_ret
  562. call(Zap_ReplaceArea)       \ (In) R1=offset, R2=len, R3=block, R4=blklen
  563. BVS error_ret
  564. call(Zap_StopOp)
  565. BVS error_ret
  566. :\\ Free the heap block, and delete the temporary files
  567. MOV R0,R3
  568. call(Zap_Free)              \ (In) R0=block
  569. BVS error_ret
  570. 0ADR R1,file_in                \ (In) R1=file
  571. BL delete
  572. 0ADR R1,file_out               \ (In) R1=file
  573. BL delete
  574. \\ Finished
  575. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  576. D\ Error returns                                                \
  577. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  578. .error_nosel
  579. ADR R0,error_noselection
  580. \ Fall through!
  581. .error_ret
  582. .error_noselection
  583. EQUD 0
  584. S("No selection")
  585. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  586. D\ Input and output filenames for command                       \
  587. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  588. .file_in
  589. S("<Wimp$ScrapDir>.Zap-In")
  590. .file_out
  591. S("<Wimp$ScrapDir>.Zap-Out")
  592. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  593. D\ Add a prompt to the minibuffer (tail called from command)    \
  594. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  595. .add_prompt
  596. ADR R0,prompt_string
  597. call(Zap_MiniPrompt)
  598. .prompt_string
  599. S("Filter: ")
  600. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  601. D\ Save data to a file                                          \
  602. D\ (In) R1 = filename, R2 = len, R3 = addr                      \
  603. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  604.     .save
  605. STMFD R13!,{R1-R5,R14}
  606. #MOV R4,R3          \ start addr
  607. !ADD R5,R3,R2       \ end addr
  608. "MOV R0,#10         \ save file
  609. !LDR R2,file_txt    \ filetype
  610. SWI "XOS_File"
  611. LDMFD R13!,{R1-R5,PC}
  612. .file_txt
  613. EQUD &FFF
  614. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  615. D\ Get the length of a file                                     \
  616. D\ (In) R1 = file (Out) R0 = length                             \
  617. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  618. .get_len
  619. STMFD R13!,{R1-R6,R14}
  620. MOV R0,#17
  621. SWI "XOS_File"
  622. MOVVC R0,R4
  623. LDMFD R13!,{R1-R6,PC}
  624.  D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  625. !D\ Delete a file                                                \
  626. "D\ (In) R1 = file                                               \
  627. #D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  628. .delete
  629. STMFD R13!,{R1-R5,R14}
  630. MOV R0,#6
  631. SWI "XOS_File"
  632. LDMFD R13!,{R1-R5,PC}
  633. +D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  634. ,D\ Load a file                                                  \
  635. -D\ (In) R0 = address, R1 = file                                 \
  636. .D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  637. .load_file
  638. STMFD R13!,{R1-R7,R14}
  639. 2,MOV R2,R0           \ address to load to
  640. 3#MOV R0,#16          \ load file
  641. 4/MOV R3,#0           \ load to given address
  642. SWI "XOS_File"
  643. LDMFD R13!,{R1-R7,PC}
  644. 8D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  645. 9D\ Filter file_in to file_out                                   \
  646. :D\ (In) R0=command, R1=input, R2=output                         \
  647. ;D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  648. .filter_file
  649. STMFD R13!,{R0-R2,R14}
  650. @(\ The parameter list is on the stack
  651. MOV R3,R13
  652. C6\ Claim some space for the command buffer from Zap
  653. MOV R0,#buflen%
  654. call(Zap_Claim)
  655. FGADDVS R13,R13,#4                \ On an error, we don't restore R0!
  656. LDMVSFD R13!,{R1-R2,PC}
  657. MOV R2,#buflen%
  658. MOV R1,R0
  659. ADR R0,cmd_template
  660. BL argsub
  661. N(\ Save the address of the heap block
  662. MOV R2,R0
  663. Q8\ Drop R0 from the stack, as we intend to corrupt it
  664. ADD R13,R13,#4
  665. \ Start the child task
  666. SWI "XWimp_StartTask"
  667. BVS error_starttask
  668. TEQ R0,#0
  669. ADRNE R0,error_livetask
  670. BNE error_starttask
  671. \ Free the heap block
  672. MOV R0,R2
  673. call(Zap_Free)
  674. LDMFD R13!,{R1-R2,PC}
  675. a&\ Error in starting the child task
  676. .error_starttask
  677. c@MOV R1,R0                       \ Preserve the error pointer
  678. MOV R0,R2
  679. call(Zap_Free)                \ Free the heap block (ignore errors here)
  680. MOV R0,R1
  681. LDMFD R13!,{R1-R2,R14}
  682. RS PC,R14,#Vflag%
  683. lD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  684. .error_livetask
  685. EQUD 0
  686. S("Filter task has not completed")
  687. qD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  688. .cmd_template
  689. S("%0 < %1 > %2 2> Null:")
  690. vD\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  691. wD\ Substitute args into a string                                \
  692. xD\ (In) R0 = template, R1 = output buffer, R2 = output buffer   \
  693. yD\      length, R3 = parameter list                             \
  694. zD\ (Out) R0 = output buffer, R1 = null at end of output         \
  695. {D\                                                              \
  696. |D\ Copies the template into the output buffer, replacing %n by  \
  697. }D\ the contents of the nth parameter in the list at R3. %% is   \
  698. ~D\ replaced by a single %                                       \
  699. D\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  700. .argsub
  701. STMFD R13!,{R1-R5,R14}
  702. &\ Main loop - load and store bytes
  703. \ Buffer overflow?
  704. TEQ R2,#0
  705. BEQ Lerr_overflow
  706. LDRB R4,[R0]
  707. \ Argument substitution?
  708. TEQ R4,#
  709. BEQ Lpct
  710. '\ Basic case - add to output string
  711.     .Lbas
  712. STRB R4,[R1],#1
  713. ADD R0,R0,#1
  714. SUB R2,R2,#1
  715. \ At end?
  716. TEQ R4,#0
  717. BNE L11
  718. 9SUB R1,R1,#1                    \ Back up to the null
  719. ILDMFD R13!,{R0,R2-R5,PC}        \ Restore, but restore saved R1 to R0
  720. \ Argument substitution
  721.     .Lpct
  722. LDRB R4,[R0,#1]!
  723. +TEQ R4,#
  724. "%"                  \ %% => %
  725. BEQ Lbas
  726.  \ Check that we have %0 - %9
  727. CMP R4,#
  728. BLT Lerr_invalid
  729. CMP R4,#
  730. BGT Lerr_invalid
  731. EADD R0,R0,#1                    \ R0 -> next unread template char
  732. SUB R4,R4,#
  733. LDR R5,[R3,R4,LSL #2]
  734. \ Copy [R5] into [R1]
  735. LDRB R4,[R5],#1
  736. TEQ R4,#0
  737. ABEQ L11                         \ Done - go back to main loop
  738. TEQ R2,#0
  739. BEQ Lerr_overflow
  740. STRB R4,[R1],#1
  741. SUB R2,R2,#1
  742.     B L12
  743. .Lerr_overflow
  744. ADR R0,error_overflow
  745. LDMFD R13!,{R1-R5,R14}
  746. RS PC,R14,#Vflag%
  747. .Lerr_invalid
  748. ADR R0,error_invalid
  749. LDMFD R13!,{R1-R5,R14}
  750. RS PC,R14,#Vflag%
  751. .error_overflow
  752. EQUD 0
  753. S("Overflow")
  754. .error_invalid
  755. EQUD 0
  756. S("Invalid template")
  757. @\\\\\\\\\\ End Of Assembly \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  758.  pass
  759. length%=P%
  760. S(A$)    :[OPTpass:EQUS A$+
  761. 0:ALIGN:]:=""
  762. RES(n%)  :[OPTpass:EQUS 
  763. 0):ALIGN:]:=""
  764. SS(A$)   :[OPTpass:SWI "XOS_WriteS":EQUS A$+
  765. 0:ALIGN:]:=""
  766. JSR      :[OPTpass:STMFD   R13!,{R14}:]:=""
  767. RTV      :[OPTpass:LDMFD   R13!,{R14}:
  768. RS PC,R14,#Vflag%:]:=""
  769. RTC      :[OPTpass:LDMFD   R13!,{R14}:BICS PC,R14,#Vflag%:]:=""
  770. RTS      :[OPTpass:LDMFD   R13!,{PC} :]:=""
  771. RTSNE    :[OPTpass:LDMNEFD R13!,{PC}:]:=""
  772. RTSEQ    :[OPTpass:LDMEQFD R13!,{PC}:]:=""
  773. RTSCS    :[OPTpass:LDMCSFD R13!,{PC}:]:=""
  774. RTSCC    :[OPTpass:LDMCCFD R13!,{PC}:]:=""
  775. RTSVS    :[OPTpass:LDMVSFD R13!,{PC}:]:=""
  776. RTSVC    :[OPTpass:LDMVCFD R13!,{PC}:]:=""
  777. RTSLS    :[OPTpass:LDMLSFD R13!,{PC}:]:=""
  778. RTSHI    :[OPTpass:LDMHIFD R13!,{PC}:]:=""
  779. RTSMI    :[OPTpass:LDMMIFD R13!,{PC}:]:=""
  780. RTSLE    :[OPTpass:LDMLEFD R13!,{PC}:]:=""
  781. RTSGE    :[OPTpass:LDMGEFD R13!,{PC}:]:=""
  782. RTSLT    :[OPTpass:LDMLTFD R13!,{PC}:]:=""
  783. RTSS     :[OPTpass:LDMFD   R13!,{PC}^:]:=""
  784. RTSSNE   :[OPTpass:LDMNEFD R13!,{PC}^:]:=""
  785. RTSSEQ   :[OPTpass:LDMEQFD R13!,{PC}^:]:=""
  786. RTSSCC   :[OPTpass:LDMCCFD R13!,{PC}^:]:=""
  787. RTSSCS   :[OPTpass:LDMCSFD R13!,{PC}^:]:=""
  788. mem(x%)  :w%=O%-code%:P%=P%+x%:O%=O%+x%:[OPTpass:ALIGN:]:=w%
  789. res(x%)  :P%=P%+x%:O%=O%+x%:[OPTpass:ALIGN:]:=""
  790. newl     :[OPTpass:SWI "XOS_NewLine":]:=""
  791. date      
  792.  date% 64:?date%=3:
  793.  "OS_Word",&0E,date%
  794.  "OS_ConvertDateAndTime",date%,date%+16,32,"%DY %M3 19%YR" 
  795.  A%,B%
  796. ?B%=13:=$A%
  797.  This modules workspace is at R11!!
  798. ADR(s%,x%)  :[OPTpass:ADD   s%,R11,#x%:]:=""
  799. LDR(s%,x%)  :[OPTpass:LDR   s%,[R11,#x%]:]:=""
  800. LDREQ(s%,x%):[OPTpass:LDREQ s%,[R11,#x%]:]:=""
  801. LDRNE(s%,x%):[OPTpass:LDRNE s%,[R11,#x%]:]:=""
  802. LDRCS(s%,x%):[OPTpass:LDRCS s%,[R11,#x%]:]:=""
  803. LDRCC(s%,x%):[OPTpass:LDRCC s%,[R11,#x%]:]:=""
  804. STR(s%,x%)  :[OPTpass:STR   s%,[R11,#x%]:]:=""
  805. STREQ(s%,x%):[OPTpass:STREQ s%,[R11,#x%]:]:=""
  806. STRNE(s%,x%):[OPTpass:STRNE s%,[R11,#x%]:]:=""
  807. STRVS(s%,x%):[OPTpass:STRVS s%,[R11,#x%]:]:=""
  808. MOV(s%,x%)
  809.  perform MOV s%,#x% on second pass only (variable may not exist)
  810.  (pass 
  811.  2)<>0 
  812.  [OPTpass:MOV s%,#x%:]
  813.  [OPTpass:MOV s%,#0:]
  814. TEQ(s%,x%)
  815.  perform TEQ s%,#x% on second pass only (variable may not exist)
  816.  (pass 
  817.  2)<>0 
  818.  [OPTpass:TEQ s%,#x%:]
  819.  [OPTpass:TEQ s%,#0:]
  820. error
  821. " at line ";
  822. err(a%,T$)
  823. A[OPTpass:ADD R0,PC,#0:
  824. RS PC,R14,#Vflag%:EQUD a%:
  825. S(T$):]:=""
  826. com(T$,a%)
  827. [OPTpass:EQUS T$:EQUB 0:]
  828. %!O%=0     :
  829.  zero next four bytes
  830.   [OPTpass:ALIGN:EQUD a%:]:=""
  831.  Call zap at entry offset a% Entry R0-R11=args R12=zap workspace
  832. call(a%)
  833. [OPTpass
  834. %:LDR R14,[R12]                 \ get start of zap table
  835. &6ADD R14,R14,#a%               \ get address of sub
  836. '9STMFD R13!,{R14}              \ save address on stack
  837. (?MOV R14,PC                    \ return address (with flags)
  838. )0LDMFD R13!,{PC}               \ call the sub
  839. *    ]:=""
  840.