chiark / gitweb /
Create readable text `.bas' for each tokenized BASIC `,ffb' file.
[ssr] / StraySrc / SapphToys / !SWIlist / bs / swiList.bas
1 REM
2 REM swiList.bs
3 REM
4 REM Build SWI name include files
5 REM
6 REM © 1995 Straylight
7 REM
8
9 REM -- Standard header ------------------------------------------------------
10
11 ON ERROR ERROR 0,"*** ERROR: "+REPORT$+" ["+STR$(ERL)+"]"
12
13 LIBRARY "libs:BAS"
14 PROCbas_init
15
16 PROCbas_aofInit(&8000)
17
18 V_flag=1<<28
19 C_flag=1<<29
20
21 FOR o=4 TO 6 STEP 2
22
23 [               opt     o
24                 FNpass
25
26 ;----- Revision history -----------------------------------------------------
27 ;
28 ; Version       By      Change
29 ;
30 ; 1.xx          MDW     Old version written in C using STEEL.
31 ;
32 ; 2.00          MDW     Rewrite from scratch in assembler using Sapphire.
33 ;                       Keep SWI names in flex block, allow user format
34 ;                       files, and add SWIs from modules dropped onto icon.
35 ;
36 ; 2.01          MDW     Replaced format file loading with a chunk file, to
37 ;                       support multiple programming languages.  Added
38 ;                       submenu to `Save list' for selecting which language
39 ;                       to use.
40 ;
41 ; 2.02          MDW     Added %d format specifier to output generation time/
42 ;                       date in given style.  Also added revision history ;-)
43 ;
44 ; 2.03          MDW     Added confirm on quit option, and prevented saving
45 ;                       a dump from SWIList back into itself.
46 ;
47 ; 2.04          MDW     Tidied up initialisation a little, and made it
48 ;                       register the heap routines as allocators for smaller
49 ;                       WimpSlot.
50 ;
51 ; 2.05          MDW     Fiddled help message generation a little to (a)
52 ;                       do message translation of the format names and (b)
53 ;                       use %0 rather than the less pretty %9 in the help
54 ;                       skeleton.
55 ;
56 ; 2.06          MDW     Added full pathname for dump save, so you don't have
57 ;                       to dig up the application to save the dump each time.
58 ;
59 ; 2.07          MDW     Used SEH for error handling, instead of raw except-
60 ;                       level stuff.
61
62 ;----- External dependencies ------------------------------------------------
63
64                 ; --- Sapphire library ---
65
66                 FNget   ("sapphire:alloc")
67                 FNget   ("sapphire:buttons")
68                 FNget   ("sapphire:chunk")
69                 FNget   ("sapphire:defHandler")
70                 FNget   ("sapphire:errorBox")
71                 FNget   ("sapphire:event")
72                 FNget   ("sapphire:fastMove")
73                 FNget   ("sapphire:flex")
74                 FNget   ("sapphire:heap")
75                 FNget   ("sapphire:help")
76                 FNget   ("sapphire:hour")
77                 FNget   ("sapphire:ibicon")
78                 FNget   ("sapphire:libOpts")
79                 FNget   ("sapphire:menu")
80                 FNget   ("sapphire:menuDefs")
81                 FNget   ("sapphire:msgs")
82                 FNget   ("sapphire:note")
83                 FNget   ("sapphire:progInfo")
84                 FNget   ("sapphire:ptr")
85                 FNget   ("sapphire:report")
86                 FNget   ("sapphire:res")
87                 FNget   ("sapphire:resources")
88                 FNget   ("sapphire:sapphire")
89                 FNget   ("sapphire:seh")
90                 FNget   ("sapphire:string")
91                 FNget   ("sapphire:warning")
92
93                 FNget   ("sapphire:choices.choices")
94
95                 FNget   ("sapphire:xfer.load")
96                 FNget   ("sapphire:xfer.saveAs")
97                 FNget   ("sapphire:xfer.save")
98                 FNget   ("sapphire:xfer.xsave")
99
100                 ; --- Link-time generated strings ---
101
102                 FNimport("cright")
103                 FNimport("version")
104
105 ;----- Initialisation -------------------------------------------------------
106
107                 FNarea  ("Client$$Code","CODE,READONLY")
108
109 ; --- main ---
110 ;
111 ; On entry;     --
112 ;
113 ; On exit;      Via OS_Exit
114 ;
115 ; Use;          Allows saving of header files containing SWI name-number
116 ;               mappings.
117
118 .main           FNentry
119
120                 adr     r0,FNlitsz("SWIList")   ;Point to application name
121                 mov     r1,#sl__wSize           ;Get my workspace size
122                 mov     r2,#0                   ;Default stack size
123                 bl      sapphire_init           ;Start up the library
124                 bl      sl__preInit             ;Do pre-initialisation stuff
125                 bl      sapphire_libInit        ;Initialise rest of library
126                 bl      sl__init                ;Initialise me
127
128                 bl      seh_throwErrors         ;Make errors throw exceptions
129                 bl      report_catchAll         ;And catch exceptions
130
131 .sl__pollLoop   mov     r0,#1                   ;Don't have idle events
132                 add     r1,r12,#sl__pollBlock   ;Point to the poll block
133                 bl      event_poll              ;Handle an event
134                 blcc    sl__unknowns            ;Handle unknown events
135                 blcc    defHandler              ;Pass it on if unrecognised
136                 b       sl__pollLoop            ;And carry on round forever
137
138                 FNltorg
139
140 ; --- sl__preInit ---
141 ;
142 ; On entry;     --
143 ;
144 ; On exit;      R0-R10 corrupted
145 ;
146 ; Use;          Does initialisation of things before the main Sapphire
147 ;               library awakes.
148
149 .sl__preInit    stmfd   r13!,{r14}              ;Save a register away
150                 bl      resources_init          ;Use shared resource DLL
151                 bl      hour_init               ;Wake up the hourglass system
152                 bl      hour_on                 ;And turn it on
153                 ldr     r0,[r11,#sapph_appName] ;Find the application name
154                 bl      heap_init               ;Initialise the resizing heap
155                 bl      heap_useHeap            ;Register it as an allocator
156                 adr     r0,sl__sapphOpts        ;Point to options block
157                 bl      libOpts_register        ;Register the options
158                 ldmfd   r13!,{pc}^              ;Return to caller when done
159
160 .sl__sapphOpts  FNlibOpt("MENU")
161                 dcd     8192
162                 FNlibOpts_end
163
164                 FNltorg
165
166 ; --- sl__init ---
167 ;
168 ; On entry;     --
169 ;
170 ; On exit;      --
171 ;
172 ; Use;          Initialises SWIList's workspace.
173
174 .sl__init       stmfd   r13!,{r14}              ;Save some registers
175                 bl      sl__initWS              ;Set up my workspace
176                 bl      sl__loadFormat          ;Load the user's format file
177                 bl      sl__initList            ;Create the SWI list
178                 bl      sl__iconBar             ;Create my icon
179                 bl      sl__setFlags            ;Finally set the flags up
180                 ldmfd   r13!,{pc}^              ;And return to caller
181
182                 FNltorg
183
184 ; --- sl__initWS ---
185 ;
186 ; On entry;     --
187 ;
188 ; On exit;      R0-R10 corrupted
189 ;
190 ; Use;          Initialises the application's workspace.
191
192 .sl__initWS     stmfd   r13!,{r14}              ;Save the link register
193                 mov     r14,#0                  ;Zero the anchor pointer
194                 str     r14,[r12,#sl__flags]    ;Clear the flags initially
195                 str     r14,[r12,#sl__anchor]   ;Say we have no block yet
196                 str     r14,[r12,#sl__modNames] ;No module name table
197                 str     r14,[r12,#sl__format]   ;No format loaded yet
198                 ldmfd   r13!,{pc}^              ;And return to caller
199
200                 FNltorg
201
202 ; --- sl__loadFormat ---
203 ;
204 ; On entry;     --
205 ;
206 ; On exit;      R0-R10 corrupted
207 ;
208 ; Use;          Loads SWIList's format file.
209
210 .sl__loadFormat stmfd   r13!,{r14}              ;Save the link register
211
212                 ; --- Enable the Choices support ---
213
214                 mov     r0,#1                   ;Enable `Choices' support
215                 bl      choices_useChoices      ;Allow read-only use nicely
216
217                 ; --- Create the format chunk file ---
218
219                 bl      chunk_create            ;Create a chunk file
220                 swivs   "OS_GenerateError"      ;Be unhappy if it fails
221                 str     r0,[r12,#sl__format]    ;Save this away
222
223                 ; --- Now do the actual load operation ---
224
225                 adr     r0,FNlitsz("Format")    ;Point to the leafname
226                 mov     r1,r11                  ;Build name in scratchpad
227                 mov     r2,#0                   ;I want to read the file
228                 bl      choices_find            ;Translate the name
229                 mov     r1,r0                   ;Point to the name
230                 sub     r13,r13,#4              ;Make a flex anchor
231                 mov     r2,r13                  ;Point to this anchor
232                 bl      load_file               ;Load the file into it
233                 ldrvc   r0,[r12,#sl__format]    ;Find the format handle
234                 movvc   r1,r13                  ;And point to the anchor
235                 blvc    chunk_read              ;Add that to the chunks
236                 mov     r0,r13                  ;Point to that anchor again
237                 bl      flex_free               ;Get rid of the block
238                 add     r13,r13,#4              ;And restore the stack
239
240                 ; --- Set flag if any format chunks found ---
241
242                 ldr     r0,[r12,#sl__format]    ;Find the format handle
243                 mov     r1,#0                   ;Start enumerating
244                 bl      chunk_enum              ;Are there any chunks?
245                 ldrcc   r14,[r12,#sl__flags]    ;Yes -- get the flags
246                 orrcc   r14,r14,#slFlag__format ;Set the format flag
247                 strcc   r14,[r12,#sl__flags]    ;And save them back again
248                 ldmfd   r13!,{pc}^              ;Return to caller when done
249
250                 FNltorg
251
252 ; --- sl__initList ---
253 ;
254 ; On entry;     --
255 ;
256 ; On exit;      R0-R10 corrupted
257 ;
258 ; Use;          Initialises the SWI table, either by loading a saved dump
259 ;               or by scanning the modules in memory.
260
261 .sl__initList   stmfd   r13!,{r14}              ;Save the link register
262                 adr     r0,FNlitsz("SWIDump")   ;Point to the leafname
263                 mov     r1,r11                  ;Build name in scratchpad
264                 mov     r2,#0                   ;I want to read the file
265                 bl      choices_find            ;Translate the name
266                 mov     r1,r0                   ;Point to the name
267                 bl      sl__loadDmp             ;Load the default dump
268                 blvc    sl__doneDmp             ;If OK, set the rest up
269                 blvs    sl__initBlock           ;Otherwise, scan the modules
270                 ldmfd   r13!,{pc}^              ;Return to caller when done
271
272                 FNltorg
273
274 ; --- sl__iconBar ---
275 ;
276 ; On entry;     --
277 ;
278 ; On exit;      --
279 ;
280 ; Use;          Sets up the icon bar icon.
281
282 .sl__iconBar    stmfd   r13!,{r0-r6,r14}        ;Save some registers
283                 adr     r0,FNlitsz("!swilist")  ;Point to sprite to use
284                 mov     r1,#0                   ;No text buffer here
285                 mvn     r2,#NOT(-1)             ;Put icon on the left
286                 mov     r3,#0                   ;Normal priority please
287                 adr     r4,sl__ibEvents         ;Point to event handler
288                 mov     r5,#0                   ;Pass no document handle
289                 mov     r6,r12                  ;Pass workspace pointer
290                 bl      ibicon_create           ;Create the icon nicely
291                 swivs   "OS_GenerateError"      ;If it failed, halt program
292                 ldmfd   r13!,{r0-r6,pc}^        ;And return to caller
293
294                 FNltorg
295
296 ; --- sl__ibEvents ---
297 ;
298 ; On entry;     R0 == event code
299 ;
300 ; On exit;      --
301 ;
302 ; Use;          Handles events for the icon bar icon.
303
304 .sl__ibEvents   cmp     r0,#(sl__ibe10-sl__ibe00)/4
305                 addcc   pc,pc,r0,lsl #2         ;Dispatch through branch tbl
306                 movs    pc,r14                  ;Ignore unknown events
307
308 .sl__ibe00      movs    pc,r14                  ;Ignore Select clicks
309                 b       sl__ibMenu              ;Handle a menu click
310                 movs    pc,r14                  ;Ignore Adjust clicks
311                 b       sl__ibLoad              ;Handle a load/save request
312                 b       sl__ibLoad              ;We treat them all the same
313                 b       sl__ibHelp              ;Handle a help request
314 .sl__ibe10
315                 ; --- Handle a menu click ---
316
317 .sl__ibMenu     stmfd   r13!,{r0-r3,r14}        ;Save some registers
318                 adr     r0,sl__imDef            ;Point to the menu definition
319                 adr     r1,sl__imEvents         ;Point to menu handler code
320                 mov     r2,r10                  ;Pass it the doc handle
321                 mov     r3,r12                  ;And my workspace address
322                 bl      menu_create             ;Display the menu nicely
323                 ldmfd   r13!,{r0-r3,pc}^        ;And return to caller
324
325 .sl__imDef      FNmenu("SWIList")
326                 FNmenu_item("slINF")
327                   FNmenu_subWarn
328                   FNmenu_ruleOff
329                 FNmenu_item("slSVL")
330                   FNmenu_r12Data
331                   FNmenu_iShade(sl__flags,slFlag__savable)
332                   FNmenu_subWarn
333                   FNmenu_noWarn
334                 FNmenu_item("slSVD")
335                   FNmenu_r12Data
336                   FNmenu_iShade(sl__flags,slFlag__block)
337                   FNmenu_subWarn
338                   FNmenu_noWarn
339                 FNmenu_item("slSCN")
340                 FNmenu_item("slRFM")
341                   FNmenu_subWarn
342                   FNmenu_ruleOff
343                 FNmenu_item("slQUT")
344                 FNmenu_end
345
346                 ; --- Handle a help request ---
347
348 .sl__ibHelp     stmfd   r13!,{r0,r14}           ;Save some registers
349                 adr     r0,FNlitsz("slhIB")     ;Point to a message tag
350                 bl      msgs_lookup             ;Translate the tag
351                 bl      help_add                ;And add it to the help
352                 ldmfd   r13!,{r0,pc}^           ;Return to caller
353
354                 ; --- Handle a load event ---
355
356 .sl__ibLoad     stmfd   r13!,{r0-r2,r14}        ;Save some registers
357                 bl      event_last              ;Find the last event
358                 ldr     r0,[r1,#40]             ;Load the filetype
359                 ldr     r14,FNlitw(&FFA)        ;Get the module filetype
360                 cmp     r0,r14                  ;Do these match
361                 beq     sl__ibLdMod             ;Yes -- handle that then
362                 ldr     r14,FNlitw(&FFD)        ;Get the data filetype
363                 cmp     r0,r14                  ;Do these match
364                 beq     sl__ibLdDump            ;Yes -- handle that then
365                 ldmfd   r13!,{r0-r2,pc}^        ;Return to caller
366
367                 ; --- Handle loading a module ---
368
369 .sl__ibLdMod    adr     r0,sl__lMod             ;Point to load block
370                 mov     r1,r10                  ;Get document handle
371                 mov     r2,r12                  ;And workspace address
372                 bl      load                    ;Do the load operation
373                 ldmfd   r13!,{r0-r2,pc}^        ;And return when done
374
375 .sl__lMod       b       sl__ibMod
376                 b       load_killBuf
377                 b       load_extendBuf
378                 b       load_doneBuf
379                 b       sl__loadMod
380                 b       sl__doneMod
381                 b       sl__lfMod
382
383                 ; --- Handle loading a dump ---
384
385 .sl__ibLdDump   ldr     r14,[r12,#sl__flags]    ;Load the flags word
386                 tst     r14,#slFlag__saving     ;Are we saving currently?
387                 bne     sl__ild50               ;Yes -- moan at user then
388
389                 adr     r0,sl__lDmp             ;Point to load block
390                 mov     r1,r10                  ;Get document handle
391                 mov     r2,r12                  ;And workspace address
392                 bl      load                    ;Yes -- start a load op
393                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
394
395 .sl__ild50      adr     r0,FNliterr(1,"slCSII") ;Point to error block
396                 bl      msgs_error              ;Translate the message
397                 mov     r1,#1                   ;Only display OK button
398                 bl      errorBox                ;Display the error
399                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
400
401 .sl__lDmp       b       sl__ibDmp
402                 b       load_killBuf
403                 b       load_extendBuf
404                 b       load_doneBuf
405                 b       sl__loadDmp
406                 b       sl__doneDmp
407                 b       sl__lfDmp
408
409                 FNltorg
410
411 ; --- sl__imEvents ---
412 ;
413 ; On entry;     R0 == event code
414 ;               R1 == item number
415 ;
416 ; On exit;      --
417 ;
418 ; Use;          Handles events from the icon bar menu.
419
420 .sl__imEvents   cmp     r0,#mEvent_help         ;A help request, perchance?
421                 beq     sl__imHelp              ;Yes -- deliver help on it
422                 cmp     r0,#mEvent_select       ;Is this a select event?
423                 cmpne   r0,#mEvent_subMenu      ;Or a submenu opening?
424                 movnes  pc,r14                  ;No -- ignore the event
425
426                 cmp     r1,#(sl__ime10-sl__ime00)/4
427                 addcc   pc,pc,r1,lsl #2         ;Dispatch by item number
428                 movs    pc,r14                  ;Ignore unknown item numbers
429
430 .sl__ime00      b       sl__imInfo              ;Display the info box
431                 b       sl__imSave              ;Save the SWI list
432                 b       sl__imDump              ;Save a SWI dump
433                 b       sl__initBlock           ;Reset the block
434                 b       sl__imRefresh           ;Refresh a particular module
435                 b       sl__imQuit              ;Close down the program
436 .sl__ime10
437
438                 ; --- Send a help message ---
439
440 .sl__imHelp     stmfd   r13!,{r0,r14}           ;Save some registers
441                 adr     r0,FNlitsz("slhIM")     ;Find the message base tag
442                 bl      menu_help               ;Give help on the item
443                 ldmfd   r13!,{r0,pc}^           ;And return to caller
444
445                 ; --- Display the info window ---
446
447 .sl__imInfo     stmfd   r13!,{r0-r2,r14}        ;Save some registers
448                 adr     r0,FNlitsz("slPUR")     ;Point to purpose message
449                 bl      msgs_lookup             ;Translate message tag
450                 ldr     r1,FNlitw(cright)       ;Find the copyright string
451                 ldr     r2,FNlitw(version)      ;And the version string
452                 bl      progInfo                ;Display the box
453                 movvs   r1,#1                   ;If it failed, display error
454                 blvs    errorBox                ;In a pretty error box
455                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
456
457                 FNltorg
458
459                 ; --- Dislplay the menu of formats ---
460
461 .sl__imSave     cmp     r0,#mEvent_subMenu      ;Make sure this is a submenu
462                 movnes  pc,r14                  ;No -- not interested
463
464                 stmfd   r13!,{r0-r5,r14}        ;Save some registers
465                 adr     r0,sl__fmtTitle         ;Point to the title
466                 mov     r1,#0                   ;No handler for that
467                 bl      menu_create             ;Set that up to display
468
469                 ldr     r4,[r12,#sl__format]    ;Load the format chunk file
470                 mov     r1,#0                   ;Read first chunk name
471 .loop           mov     r0,r4                   ;Pop it in R0 for a bit
472                 bl      chunk_enum              ;Get the next chunk
473                 ldmcsfd r13!,{r0-r5,pc}^        ;Return when finished
474                 str     r2,[r1,#4]              ;Save pointer to name
475                 mov     r2,r1                   ;Point to the anchor
476                 mov     r5,r1                   ;Look after continuation
477                 adr     r0,sl__fmtMenu          ;Point to menu skeleton
478                 adr     r1,sl__fmtHandler       ;Point to handler routine
479                 mov     r3,r12                  ;Pass workspace in R12
480                 bl      menu_create             ;Add that to the list
481                 mov     r1,r5                   ;Get the continuation value
482                 b       loop                    ;And go back to the loop
483
484 .sl__fmtTitle   FNmenu("slSVFT")
485                 FNmenu_end
486
487 .sl__fmtMenu    FNmenu_itemInd(4)
488                 FNmenu_subWarn
489                 FNmenu_end
490
491                 FNltorg
492
493                 ; --- Dislplay the dump box ---
494
495 .sl__imDump     stmfd   r13!,{r0-r5,r14}        ;Save some registers
496                 ldr     r0,[r12,#sl__used]      ;Load the actual block size
497                 ldr     r1,FNlitw(&ffd)         ;Output as a data file
498                 add     r2,r12,#sl__dumpFile    ;Point to the dump file name
499                 adr     r3,sl__dumpDef          ;Point to handler block
500                 mov     r4,r10                  ;Pass document handle
501                 mov     r5,r12                  ;And pass the workspace addr
502                 bl      saveAs                  ;Try to do the save op
503                 bvs     sl__imd90               ;Tidy up if it failed
504                 ldr     r14,[r12,#sl__flags]    ;Load the current flags
505                 orr     r14,r14,#slFlag__saving ;Say we're now saving
506                 str     r14,[r12,#sl__flags]    ;Save the flags back again
507                 ldmfd   r13!,{r0-r5,pc}^        ;And return to caller
508
509 .sl__imd90      mov     r1,#1                   ;If it failed, report error
510                 bl      errorBox                ;In a nice error box
511                 ldmfd   r13!,{r0-r5,pc}^        ;And return to caller
512
513 .sl__dumpDef    FNs     ("slSDT")               ;Title for the save box
514                 b       sl__svdDone             ;Handle box closing
515                 b       sl__saveDump            ;Save to a disk file
516                 b       sl__sendDump            ;Send to another application
517                 movs    pc,r14                  ;Ignore completion
518                 b       sl__svdFail             ;Tidy up after a failure
519
520                 FNltorg
521
522                 ; --- Display a menu of modules to refresh ---
523
524 .sl__imRefresh  cmp     r0,#mEvent_subMenu      ;Is this a submenu?
525                 movnes  pc,r14                  ;No -- go away then
526                 stmfd   r13!,{r0-r7,r14}        ;Save some registers
527
528                 ; --- Free the old title block ---
529
530                 ldr     r0,[r12,#sl__modNames]  ;Load the pointer
531                 cmp     r0,#0                   ;Is the block allocated?
532                 blne    free                    ;Yes -- deallocate it them
533                 movne   r14,#0                  ;And clear the pointer out
534                 strne   r14,[r12,#sl__modNames] ;Done that
535
536                 ; --- Enumerate interesting modules ---
537
538                 mov     r6,#0                   ;Size of block required
539                 mov     r1,#0                   ;Start at the beginning
540
541                 ; --- Read the next module ---
542
543 .loop           mov     r0,#12                  ;Enumerate module names
544                 mov     r2,#0                   ;Not interested in instances
545                 swi     "XOS_Module"            ;Read the next module
546                 bvs     sl__imRefAlloc          ;No more -- go to next phase
547
548                 ; --- Update the arguments for next call ---
549
550                 cmp     r2,#0                   ;Is there another instance?
551                 addne   r1,r1,#1                ;No -- update manually
552
553                 ; --- See whether this module was interesting ---
554
555                 ldr     r14,[r3,#&20]           ;Load the SWI handler offset
556                 cmp     r14,#0                  ;Does this look sensible?
557                 addne   r6,r6,#8                ;Yes -- add another word
558                 b       loop                    ;Get more modules
559
560                 ; --- Allocate the block ---
561
562 .sl__imRefAlloc mov     r0,r6                   ;Get the required size
563                 bl      alloc                   ;Allocate the block
564                 blcs    alloc_error             ;If it failed, point to error
565                 bcs     sl__imRefError          ;And handle that
566                 str     r0,[r12,#sl__modNames]  ;Store pointer for later
567                 mov     r7,r0                   ;Point to the block start
568
569                 ; --- Set up the title block ---
570
571                 adr     r0,sl__rfmTitle         ;Point to the title block
572                 adr     r1,sl__rfmKernel        ;Point to event handler
573                 mov     r2,r10                  ;Pass my R10 value
574                 mov     r3,r12                  ;And my R12 value
575                 bl      menu_create             ;Create the title
576
577                 ; --- Initialise for module scanning ---
578
579                 mov     r6,#0                   ;Current module number
580
581                 ; --- Read the next module ---
582
583 .loop           mov     r0,#12                  ;Enumerate module names
584                 mov     r1,r6                   ;Get next module number
585                 mov     r2,#0                   ;And next module name
586                 swi     "XOS_Module"            ;Read the next module
587                 ldmvsfd r13!,{r0-r7,pc}^        ;Return when done
588
589                 ; --- Update the arguments for next call ---
590
591                 cmp     r2,#0                   ;Is there another instance?
592                 moveq   r6,r1                   ;Yes -- store it normally
593                 addne   r6,r1,#1                ;No -- update manually
594
595                 ; --- See whether this module was interesting ---
596
597                 ldr     r14,[r3,#&20]           ;Load the SWI handler offset
598                 cmp     r14,#0                  ;Does this look sensible?
599                 beq     loop                    ;No -- loop round for more
600
601                 ; --- Add the menu item for this module ---
602
603                 ldr     r14,[r3,#&10]           ;Load the module name offset
604                 add     r14,r3,r14              ;Add this on to the base
605                 stmia   r7!,{r3,r14}            ;Store base and name string
606                 adr     r0,sl__rfmItem          ;Point to the menu block
607                 adr     r1,sl__rfmModule        ;Point to the handler
608                 sub     r2,r7,#8                ;Point to name pointer
609                 mov     r3,r12                  ;And get my workspace addr
610                 bl      menu_create             ;Add to the current menu
611                 b       loop                    ;Keep on looping
612
613                 ; --- Report an error ---
614
615 .sl__imRefError add     r2,r0,#4                ;Point to error message
616                 adr     r0,FNliterr(1,"slMLE")  ;Point to skeleton
617                 bl      str_error               ;Mangle the message
618                 mov     r1,#1                   ;Just an OK button
619                 bl      errorBox                ;Report the message
620                 ldmfd   r13!,{r0-r7,pc}^        ;And return to caller
621
622                 ; --- Refresh module title ---
623
624 .sl__rfmTitle   FNmenu("slMDS")
625                 ;FNmenu_item("slKNL")           ;Not implemented
626                 FNmenu_end
627
628                 ; --- Refresh module items ---
629
630 .sl__rfmItem    FNmenu_itemInd(4)
631                 FNmenu_end
632
633                 FNltorg
634
635                 ; --- Quit the application ---
636
637 .sl__imQuit     stmfd   r13!,{r14}              ;Save return address away
638                 bl      sl__okToQuit            ;Make sure it's all right
639                 swics   "OS_Exit"               ;Yes -- just kill everything
640                 ldmfd   r13!,{pc}^              ;Otherwise ignore the request
641
642                 FNltorg
643
644 ; --- sl__rfmKernel ---
645 ;
646 ; On entry;     --
647 ;
648 ; On exit;      --
649 ;
650 ; Use;          Refreshes the kernel SWIs table.
651
652 .sl__rfmKernel  movs    pc,r14                  ;Not implemented
653
654                 FNltorg
655
656 ; --- sl__rfmModule ---
657 ;
658 ; On entry;     --
659 ;
660 ; On exit;      --
661 ;
662 ; Use;          Refreshes a particular module.
663
664 .sl__rfmModule  stmfd   r13!,{r0,r1,r14}        ;Save link
665                 ldr     r0,[r10,#0]             ;Load module base
666                 bl      sl__scanMod             ;Scan the module
667                 movvs   r1,#1                   ;If it failed
668                 blvs    errorBox                ;Report the error
669                 ldmfd   r13!,{r0,r1,pc}^        ;And return to caller
670
671                 FNltorg
672
673 ; --- sl__setFlags ---
674 ;
675 ; On entry;     --
676 ;
677 ; On exit;      --
678 ;
679 ; Use;          Sets up the flags from the flex anchors we have.
680
681 .sl__setFlags   stmfd   r13!,{r0,r14}           ;Save some registers
682                 ldr     r0,[r12,#sl__flags]     ;Load the flags word
683                 ldr     r14,[r12,#sl__anchor]   ;Load the block anchor
684                 cmp     r14,#0                  ;Is that defined?
685                 orrne   r0,r0,#slFlag__block    ;Yes -- set the flag
686                 biceq   r0,r0,#slFlag__block    ;No -- clear it
687                 tstne   r0,#slFlag__format      ;Is there a format chunk?
688                 orrne   r0,r0,#slFlag__savable  ;Yes -- set savable flag
689                 biceq   r0,r0,#slFlag__savable  ;No -- clear it then
690                 str     r0,[r12,#sl__flags]     ;Save modified flags
691                 ldmfd   r13!,{r0,pc}^           ;And return to caller
692
693                 FNltorg
694
695 ; --- sl__unknowns ---
696 ;
697 ; On entry;     R0 == event code
698 ;               R1 == pointer to event data
699 ;
700 ; On exit;      CS if event interesting, else CC
701 ;               R2-R10 corrupted
702 ;
703 ; Use;          Handles interesting messages (e.g. PreQuit)
704
705 .sl__unknowns   cmp     r0,#17                  ;Is this a User_Message?
706                 cmpne   r0,#18                  ;Or a User_Message_Recorded?
707                 movnes  pc,r14                  ;No -- ignore it then
708
709                 ldr     r2,[r1,#16]             ;Load the event code
710                 cmp     r2,#8                   ;Is this a pre-quit message?
711                 movnes  pc,r14                  ;No -- not interested then
712
713                 ; --- Handle a PreQuit message ---
714
715                 orrs    r14,r14,#C_flag         ;We claim this event now
716                 stmfd   r13!,{r14}              ;Save return address
717                 bl      sl__okToQuit            ;Ask user if required
718                 ldmcsfd r13!,{pc}^              ;If OK then continue normally
719
720                 stmfd   r13!,{r0-r2}            ;Save some more registers
721                 mov     r0,r11                  ;Point to scratchpad
722                 ldr     r2,[r1,#0]              ;Load the message size
723                 bl      fastMove                ;Copy the message data over
724                 ldr     r14,[r0,#8]             ;Load his reference number
725                 str     r14,[r0,#12]            ;Set this as a reply to it
726                 mov     r1,r0                   ;Point to my copy
727                 mov     r0,#19                  ;Send this as an acknowledge
728                 ldr     r2,[r1,#4]              ;Load his task handle out
729                 swi     "Wimp_SendMessage"      ;Send the message back
730                 ldmfd   r13!,{r0-r2,pc}^        ;Now return to caller
731
732                 FNltorg
733
734 ; --- sl__okToQuit ---
735 ;
736 ; On entry;     --
737 ;
738 ; On exit;      CS if we're allowed to quit, else CC
739 ;
740 ; Use;          Works out if we're allowed to quit the application.  If it
741 ;               isn't sure, it pops up a warning box and asks.
742
743 .sl__okToQuit   stmfd   r13!,{r0,r1,r14}        ;Save some registers
744                 ldr     r14,[r12,#sl__flags]    ;Load the flags word out
745                 tst     r14,#slFlag__modified   ;Has the block been changed?
746                 beq     sl__otq90               ;No -- then skip onwards
747
748                 adr     r0,FNlitsz("slOTQ")     ;Point to warning messae
749                 bl      msgs_lookup             ;Translate the tag
750                 adr     r1,sl__quitButts        ;Point to buttons block
751                 bl      warning                 ;Pop up the warning box
752                 ldmfd   r13!,{r0,r1,r14}        ;Unstack the registers
753                 orrcss  pc,r14,#C_flag          ;If OK, set the C flag
754                 bicccs  pc,r14,#C_flag          ;Otherwise clear it
755
756 .sl__otq90      ldmfd   r13!,{r0,r1,r14}        ;Unstack the registers
757                 orrs    pc,r14,#C_flag          ;Set C -- we're OK
758
759 .sl__quitButts  FNbutton("slQUTB")
760                 FNbuttons_cancel
761                 FNbuttons_end
762
763                 FNltorg
764
765 ;----- Save a SWI file ------------------------------------------------------
766
767 ; --- sl__fmtHandler ---
768 ;
769 ; On entry;     R0 == menu event
770 ;               R1 == menu item
771 ;               R10 == pointer to chunk name
772 ;
773 ; On exit;      --
774 ;
775 ; Use;          Handles events on the save menu.
776
777 .sl__fmtHandler cmp     r0,#mEvent_help         ;Is this a help request?
778                 beq     sl__fmtHelp             ;Yes -- give help then
779                 cmp     r0,#mEvent_subMenu      ;Is this a submenu?
780                 cmpne   r0,#mEvent_select       ;Or a click?
781                 movnes  pc,r14                  ;No -- ignore this
782
783                 stmfd   r13!,{r0-r5,r14}        ;Save some registers
784                 ldr     r0,[r12,#sl__used]      ;Load the actual block size
785                 ldr     r1,FNlitw(&fff)         ;Output as a data file
786                 adr     r2,FNlitsz("swis")      ;Point to the dummy name
787                 adr     r3,sl__saveDef          ;Point to handler block
788                 mov     r4,r10                  ;Pass document handle
789                 mov     r5,r12                  ;And pass the workspace addr
790                 bl      saveAs                  ;Try to do the save op
791                 movvs   r1,#1                   ;If it failed, report error
792                 blvs    errorBox                ;In a nice error box
793                 ldmfd   r13!,{r0-r5,pc}^        ;And return to caller
794
795 .sl__saveDef    FNs     ("slSVT")               ;Title for the save box
796                 movs    pc,r14                  ;Don't care when it closes
797                 b       sl__saveFile            ;Save to a disk file
798                 b       sl__send                ;Send to another application
799                 b       xsave_done              ;Tell xsave it's all done
800                 b       sl__failed              ;Tidy up after a failure
801
802 .sl__fmtHelp    stmfd   r13!,{r0-r2,r14}        ;Save some registers
803                 ldr     r0,[r10,#4]             ;Find the format chunk name
804                 bl      msgs_lookup             ;Translate in case of tag
805                 mov     r1,r0                   ;Point to the result
806                 mov     r0,r11                  ;Point to scratchpad
807                 bl      str_cpy                 ;Copy the string over
808 .loop           ldrb    r14,[r0,#-1]!           ;Load last byte of string
809                 subs    r14,r14,#ASC(".")       ;Is it part of an ellipsis?
810                 streqb  r14,[r0,#0]             ;Yes -- nobble that byte
811                 beq     loop                    ;And try again
812                 adr     r0,FNlitsz("slhSVF")    ;Point to help message tag
813                 bl      msgs_lookup             ;Translate the message
814                 bl      str_buffer              ;Find an output buffer
815                 mov     r2,r11                  ;Point to scratchpad string
816                 bl      str_subst               ;And build the help string
817                 bl      help_add                ;Add this to help message
818                 ldmfd   r13!,{r0-r2,pc}^        ;Return to caller
819
820                 FNltorg
821
822 ; --- sl__saveFile ---
823 ;
824 ; On entry;     R0 == pointer to file name
825 ;               R1 == safe flag
826 ;
827 ; On exit;      --
828 ;
829 ; Use;          Saves the SWI block to a file.
830
831 .sl__saveFile   stmfd   r13!,{r0-r5,r14}        ;Save some registers
832                 mov     r2,#0                   ;No current name for this
833                 bl      sl__replace             ;Do we replace the file?
834                 movcc   r0,#0                   ;No -- return null error
835                 bcc     sl__sf20                ;But cancel the save op
836
837                 ; --- Get on with saving the file ---
838
839 .sl__sf10       mov     r3,r0                   ;Look after the file name
840                 adr     r0,sl__writeList        ;Point to saver routine
841                 mov     r1,r10                  ;Pass it the document handle
842                 mov     r2,r12                  ;And my workspace pointer
843                 ldr     r4,FNlitw(&FFF)         ;Pass the filetype over
844                 bl      xsave_save              ;Try to save the file
845                 bvs     sl__sf20                ;If failed, abort now
846
847                 ; --- Now retrostamp the file ---
848
849                 mov     r0,#17                  ;Read info on the file
850                 mov     r1,r3                   ;Point to the filename
851                 swi     "XOS_File"              ;Read info on the file
852                 movvc   r0,#1                   ;Now we set the info
853                 bicvc   r2,r2,#&FF              ;Leave filetype alone
854                 orrvc   r2,r2,#&3A              ;Put in our dummy datestamp
855                 ldrvc   r3,FNlitw(&BD896000)    ;Set up rest of datestamp
856                 swivc   "XOS_File"              ;Now retrostamp it nicely
857                 ldmvcfd r13!,{r0-r5,pc}^        ;If it worked OK, return
858
859                 ; --- It failed ---
860
861 .sl__sf20       add     r13,r13,#4              ;Don't restore R0 on exit
862                 ldmfd   r13!,{r1-r5,r14}        ;Unstack saved registers
863                 orrs    pc,r14,#V_flag          ;And return to caller
864
865                 FNltorg
866
867 ; --- sl__send ---
868 ;
869 ; On entry;     R2 == accumulator value (initially 0)
870 ;
871 ; On exit;      R0 == pointer to block to send
872 ;               R1 == size of block to send
873 ;               CS if this is the last block, else CC
874 ;
875 ; Use;          Sends a block of data to another application.
876
877 .sl__send       adr     r0,sl__writeList        ;Point to my saver routine
878                 mov     r1,r10                  ;Pass the document handle
879                 mov     r2,r12                  ;Pass my workspace too
880                 b       xsave_send              ;And get another block
881
882                 FNltorg
883
884 ; --- sl__failed ---
885 ;
886 ; On entry;     R0 == pointer to error, or 0
887 ;               R1 == 1
888 ;
889 ; On exit;      --
890 ;
891 ; Use;          Terminates a save job, and reports an error.
892
893 .sl__failed     stmfd   r13!,{r0-r2,r14}        ;Save some registers
894                 bl      xsave_failed            ;Tell xsave it's finished
895                 cmp     r0,#0                   ;Is there an actual error?
896                 addne   r2,r0,#4                ;Point to error text
897                 adrne   r0,FNliterr(1,"slSFE")
898                 blne    msgs_error              ;Translate and substitute
899                 movne   r1,#1                   ;Display just an OK button
900                 blne    errorBox                ;Yes -- report it then
901                 ldmfd   r13!,{r0-r2,pc}^        ;Return to caller
902
903                 FNltorg
904
905 ; --- sl__replace ---
906 ;
907 ; On entry;     R0 == filename
908 ;               R1 == safeness flag
909 ;               R2 == pointer to current name, or 0
910 ;
911 ; On exit;      --
912 ;
913 ; Use;          CS to save, CC to cancel
914
915 .sl__replace    stmfd   r13!,{r0-r2,r14}        ;Save some registers
916                 cmp     r1,#0                   ;Is the file marked as safe?
917                 beq     sl__replace10           ;No -- then don't ask
918
919                 movs    r1,r2                   ;Is there a current name?
920                 beq     sl__replace05           ;No -- can't do this check
921                 bl      str_icmp                ;Compare the file names
922                 beq     sl__replace10           ;The same name -- don't ask
923
924 .sl__replace05  bl      res_exists              ;Does the file exist?
925                 bcc     sl__replace10           ;No -- then don't ask
926
927                 ; --- Ask the user if this is right ---
928
929                 mov     r2,r0                   ;Get the filename pointer
930                 adr     r0,FNlitsz("slRPP")     ;Point to the prompt message
931                 bl      msgs_lookup             ;Translate the message
932                 bl      str_buffer              ;Find a handy string buffer
933                 bl      str_subst               ;Build the prompt string
934                 adr     r1,sl__exWarn           ;Point to the buttons def
935                 bl      warning                 ;Display the warning box
936                 ldmccfd r13!,{r0-r2,r14}        ;If no, abort the job
937                 bicccs  pc,r14,#C_flag          ;Tell caller it's all off
938
939 .sl__replace10  ldmfd   r13!,{r0-r2,r14}        ;Restore registers
940                 orrs    pc,r14,#C_flag          ;And let it all go ahead
941
942 .sl__exWarn     FNbutton("slRPL")
943                 FNbuttons_cancel
944                 FNbuttons_end
945
946                 FNltorg
947
948 ;----- Write out a dump file ------------------------------------------------
949
950 ; --- sl__svdDone ---
951 ;
952 ; On entry;     --
953 ;
954 ; On exit;      --
955 ;
956 ; Use;          Handles the save box closing.  We allow loads of dump files
957 ;               again.
958
959 .sl__svdDone    stmfd   r13!,{r14}              ;Save some registers
960                 ldr     r14,[r12,#sl__flags]    ;Load the flags word
961                 bic     r14,r14,#slFlag__saving ;Turn off the saving flag
962                 str     r14,[r12,#sl__flags]    ;Save the flags back
963                 ldmfd   r13!,{pc}^              ;And return to caller
964
965                 FNltorg
966
967 ; --- sl__saveDump ---
968 ;
969 ; On entry;     R0 == pointer to file name
970 ;               R1 == safeness flag
971 ;
972 ; On exit;      --
973 ;
974 ; Use;          Saves a dump of the current SWI names
975
976 .sl__saveDump   stmfd   r13!,{r0-r5,r14}        ;Save some registers
977                 add     r2,r12,#sl__dumpFile    ;Point to current name
978                 bl      sl__replace             ;Do we actually do this?
979                 movcc   r0,#0                   ;If not, return null error
980                 bcc     sl__saved90             ;To cancel the save op
981
982                 mov     r1,r0                   ;Point to the filename
983                 mov     r0,#10                  ;Save memory as a file
984                 ldr     r2,FNlitw(&FFD)         ;Save as a data file
985                 add     r14,r12,#sl__anchor     ;Point to dump anchor
986                 ldmia   r14,{r4,r5}             ;Load base and size
987                 add     r5,r4,r5                ;Turn size into limit
988                 swi     "XOS_File"              ;Try to save the file
989                 bvs     sl__saved90             ;If it failed, abort
990
991                 ldr     r14,[r13,#4]            ;Load the safeness flag
992                 cmp     r14,#0                  ;Is the flag safe?
993                 beq     sl__saved50             ;No -- skip onwards then
994
995                 ; --- Do special things when file saved properly ---
996
997                 ldr     r14,[r12,#sl__flags]    ;Yes -- load flags then
998                 bic     r14,r14,#slFlag__modified ;Clear the modified bit
999                 str     r14,[r12,#sl__flags]    ;And store the flags back
1000
1001                 bl      sl__setDumpName         ;Go and set the name
1002
1003 .sl__saved50    ldmfd   r13!,{r0-r5,pc}^        ;Return to caller
1004
1005 .sl__saved90    add     r13,r13,#4              ;Don't restore R0 on exit
1006                 ldmfd   r13!,{r1-r5,r14}        ;Restore registers
1007                 orrs    pc,r14,#V_flag          ;And return with V set
1008
1009                 FNltorg
1010
1011 ; --- sl__sendDump ---
1012 ;
1013 ; On entry;     --
1014 ;
1015 ; On exit;      R0 == pointer to block to send
1016 ;               R1 == size of block
1017 ;               CS for last block, CC otherwise
1018 ;
1019 ; Use;          Sends the SWI dump block to another application
1020
1021 .sl__sendDump   add     r0,r12,#sl__anchor      ;Find the anchor block
1022                 ldmia   r0,{r0,r1}              ;Load the values out
1023                 orrs    pc,r14,#C_flag          ;And return the only block
1024
1025                 FNltorg
1026
1027 ; --- sl__svdFail ---
1028 ;
1029 ; On entry;     R0 == pointer to error, or 0
1030 ;               R1 == 1
1031 ;
1032 ; On exit;      --
1033 ;
1034 ; Use;          Terminates a save job, and reports an error.
1035
1036 .sl__svdFail    stmfd   r13!,{r0-r2,r14}        ;Save some registers
1037                 cmp     r0,#0                   ;Is there an actual error?
1038                 addne   r2,r0,#4                ;Point to error text
1039                 adrne   r0,FNliterr(1,"slSDE")
1040                 blne    msgs_error              ;Translate and substitute
1041                 movne   r1,#1                   ;Display just an OK button
1042                 blne    errorBox                ;Yes -- report it then
1043                 ldmfd   r13!,{r0-r2,pc}^        ;Return to caller
1044
1045                 FNltorg
1046
1047 ;----- Writing out a list of SWIs -------------------------------------------
1048
1049 ; --- sl__writeList ---
1050 ;
1051 ; On entry;     --
1052 ;
1053 ; On exit;      --
1054 ;
1055 ; Use;          Writes the list of SWIs to the current xsave output.
1056
1057 .sl__writeList  stmfd   r13!,{r0-r10,r14}       ;Save some registers
1058
1059                 ; --- Make sure we can do this ---
1060
1061                 ldr     r14,[r12,#sl__anchor]   ;Load the block anchor
1062                 cmp     r14,#0                  ;Is it created currently?
1063                 adreq   r0,FNliterr(1,"slNSS")
1064                 bleq    msgs_error              ;Translate the error
1065                 beq     sl__wl90                ;And return the error
1066                 ldr     r14,[r12,#sl__format]   ;Load the format anchor
1067                 cmp     r14,#0                  ;Is it created currently?
1068                 adreq   r0,FNliterr(1,"slNFD")
1069                 bleq    msgs_error              ;Translate the error
1070                 beq     sl__wl90                ;And return the error
1071
1072                 ; --- Get on with saving then ---
1073
1074                 swi     "Hourglass_On"          ;Start an hourglass going
1075
1076                 ; --- Set up initial registers ---
1077
1078                 ldr     r9,[r10,#0]             ;Load the block base
1079                 mov     r0,r10                  ;Point to the anchor
1080                 bl      flex_size               ;Get the block size
1081                 add     r10,r9,r0               ;Find the format limit
1082                 adr     r8,FNlitsz("*UNDEFINED*") ;No module name defined yet
1083                 mov     r7,r8                   ;No prefix string yet either
1084                 mov     r6,r8                   ;And no actual SWI name
1085                 mvn     r5,#NOT(-1)             ;No SWI number defined either
1086
1087                 ; --- Write out the preamble ---
1088
1089                 bl      sl__doString            ;Write out this format
1090                 bvs     sl__wl90                ;If it failed, bail out
1091
1092                 ; --- We've found the module header ---
1093                 ;
1094                 ; Now we set up for the main loop, by remembering the index
1095                 ; into the format string; we then embark on the first item
1096                 ; in the SWI list.
1097
1098                 mov     r4,r9                   ;Remember this position
1099                 ldr     r3,[r12,#sl__anchor]    ;Load the anchor base address
1100                 mov     r2,#0                   ;Start at the beginning
1101
1102                 ; --- The main output loop ---
1103
1104 .sl__wl15       add     r1,r3,r2                ;Work out address of block
1105                 ldr     r5,[r1,#4]              ;Load the SWI chunk number
1106                 bic     r5,r5,#&ff000000        ;Clear the flags bits
1107                 add     r8,r1,#8                ;Point to the module name
1108                 mov     r9,r4                   ;Start from preamble position
1109                 bl      sl__doString            ;Write out this format string
1110                 bvs     sl__wl90                ;If it failed, bail out
1111
1112                 ; --- Written the header -- now do the SWIs ---
1113
1114                 mov     r2,r9                   ;Remeber format index
1115                 mov     r7,r8                   ;Work out prefix string pos
1116 .sl__wl20       ldrb    r14,[r7],#1             ;Load next byte
1117                 cmp     r14,#0                  ;Is this end of module name?
1118                 bne     sl__wl20                ;No -- keep going round
1119
1120                 mov     r6,r7                   ;Work out SWI name position
1121 .sl__wl25       ldrb    r14,[r6],#1             ;Load next byte from string
1122                 cmp     r14,#0                  ;Is this the end yet?
1123                 bne     sl__wl25                ;No -- keep going
1124 .sl__wl26       ldrb    r14,[r6,#0]             ;Load the first byte
1125                 cmp     r14,#0                  ;Is it a null string?
1126                 beq     sl__wl30                ;Yes -- move on to next mod
1127                 cmp     r14,#1                  ;Is this a dummy SWI?
1128                 addeq   r6,r6,#1                ;Yes -- move pointer on
1129                 addeq   r5,r5,#1                ;And move on the SWI counter
1130                 beq     sl__wl26                ;And start again
1131
1132                 mov     r9,r2                   ;Point to format string
1133                 bl      sl__doString            ;Write this string out
1134                 bvs     sl__wl90                ;If it failed, bail out
1135                 add     r5,r5,#1                ;Bump up the SWI number
1136                 b       sl__wl25                ;And go round for more
1137
1138                 ; --- Finished a module ---
1139
1140 .sl__wl30       ldr     r2,[r1,#0]              ;Load the size word
1141                 sub     r14,r1,r3               ;Work out old offset
1142                 add     r2,r14,r2               ;Add it onto previous offset
1143                 ldr     r14,[r12,#sl__used]     ;Load current size of block
1144                 cmp     r2,r14                  ;Is this the last one?
1145                 bcc     sl__wl15                ;No -- do this module too
1146
1147                 ; --- Do the end bit of the file ---
1148
1149                 bl      sl__doString            ;Write out the postamble
1150                 bvs     sl__wl90                ;If it failed, bail out
1151
1152                 swi     "Hourglass_Off"         ;Turn off the hourglass
1153                 ldmfd   r13!,{r0-r10,pc}^       ;Return to caller
1154
1155                 ; --- It failed -- return an error
1156
1157 .sl__wl90       swi     "Hourglass_Off"         ;Turn off the hourglass
1158                 add     r13,r13,#4              ;Don't restore R0
1159                 ldmfd   r13!,{r1-r10,r14}       ;Restore registers
1160                 orrs    pc,r14,#V_flag          ;And return the error
1161
1162                 FNltorg
1163
1164 ; --- sl__doString ---
1165 ;
1166 ; On entry;     R5 == current SWI number
1167 ;               R6 == pointer to current SWI postfix
1168 ;               R7 == pointer to current SWI prefix
1169 ;               R8 == pointer to current module name
1170 ;               R9 == pointer to format string input
1171 ;               R10 == pointer to end of format string
1172 ;
1173 ; On exit;      R1, R2, R4 and R6-R10 may be flex relocated
1174 ;               R0 corrupted
1175 ;               R9 == pointer to format string when processing stopped
1176 ;               May return an error
1177 ;
1178 ; Use;          Outputs a string, based on a format with the following
1179 ;               syntax:
1180 ;
1181 ;               All characters are echoed directly except `%' which is
1182 ;               an escape for the following character.  Escape codes defined
1183 ;               are:
1184 ;
1185 ;               %s == current SWI name
1186 ;               %m == current module name
1187 ;               %n == current SWI number
1188 ;               %x == current X SWI number (i.e. SWI number OR &20000)
1189 ;               %% == end of formatting section
1190
1191 .sl__doString   stmfd   r13!,{r3,r14}           ;Save some registers
1192                 FNflex_save("r1,r2,r4")         ;Save caller's registers
1193                 sub     r13,r13,#128            ;Make a small buffer
1194                 orr     r3,r5,#&20000           ;Get the X version number
1195
1196 .sl__dostr10    cmp     r9,r10                  ;Are we at the end yet?
1197                 bcs     sl__dostr50             ;Yes -- return then
1198                 ldrb    r0,[r9],#1              ;Load next byte from string
1199                 cmp     r0,#ASC("%")            ;Is this a magic `%' sign?
1200                 beq     sl__dostr20             ;Yes -- do clever things
1201
1202                 bl      sl__byte                ;Write this byte out
1203                 b       sl__dostr10             ;And continue formatting
1204
1205                 ; --- Handle an escape character ---
1206
1207 .sl__dostr20    ldrb    r0,[r9],#1              ;Load next byte from string
1208                 orr     r0,r0,#&20              ;Make sure char is lowercase
1209                 cmp     r0,#ASC("s")            ;Is this a SWI name?
1210                 adreq   r0,FNlitsz("%5_%4")     ;Yes -- point to skeleton
1211                 cmp     r0,#ASC("m")            ;Or the module name?
1212                 adreq   r0,FNlitsz("%6")        ;Yes -- point to skeleton
1213                 cmp     r0,#ASC("n")            ;Or the SWI number?
1214                 adreq   r0,FNlitsz("%x3")       ;Yes -- point to skeleton
1215                 cmp     r0,#ASC("x")            ;Or the SWI X number?
1216                 adreq   r0,FNlitsz("%x1")       ;Yes -- point to skeleton
1217                 cmp     r0,#ASC("d")            ;Or a date string?
1218                 beq     sl__dostr40             ;Yes -- process specially
1219                 cmp     r0,#ASC("p")            ;Or a literal percent?
1220                 adreq   r0,FNlitsz("%%")        ;Yes -- point to skeleton
1221                 cmp     r0,#ASC("%")            ;Or a percent sign?
1222                 addeq   r9,r9,#1                ;Yes -- skip a newline char
1223                 beq     sl__dostr50             ;Yes -- handle that
1224
1225                 cmp     r0,#256                 ;Do we have an address?
1226                 bcc     sl__dostr10             ;No -- go round for more then
1227
1228                 mov     r1,r13                  ;Build string in it
1229                 bl      str_subst               ;Build output string
1230                 mov     r2,r0                   ;Point to the string
1231 .sl__dostr30    ldrb    r0,[r2],#1              ;Load next byte
1232                 cmp     r0,#32                  ;Is it the terminator?
1233                 blcs    sl__byte                ;No -- output it then
1234                 bcs     sl__dostr30             ;And loop back round again
1235                 b       sl__dostr10             ;Carry on with the string
1236
1237                 FNltorg
1238
1239                 ; --- Handle a date format string ---
1240
1241 .sl__dostr40    stmfd   r13!,{r3}               ;I need this register
1242                 sub     r13,r13,#8              ;Make time buffer on stack
1243                 mov     r14,#3                  ;Get the subreason code
1244                 strb    r14,[r13,#0]            ;Save that in the block
1245                 mov     r1,r13                  ;Point to the buffer
1246                 mov     r0,#14                  ;Get the main reason code
1247                 swi     "OS_Word"               ;Read the current time
1248
1249                 ldrb    r0,[r9,#0]              ;Load the next byte ready
1250                 cmp     r0,#ASC("[")            ;Is this an argument?
1251                 adrne   r0,FNlitsz("slDFMT")    ;No -- point to default
1252                 blne    msgs_lookup             ;Translate nicely
1253                 movne   r3,r0                   ;And put it in the right reg
1254                 bne     sl__dostr45             ;And skip onwards a bit
1255
1256                 ; --- Read the format string argument ---
1257
1258                 mov     r1,r11                  ;Point to a spare buffer
1259                 add     r9,r9,#1                ;Skip past the `[' char
1260 .a              ldrb    r14,[r9],#1             ;Load the next byte
1261                 cmp     r14,#ASC("]")           ;Is that the end yet?
1262                 cmpne   r14,#&0D                ;Check return for safety
1263                 moveq   r14,#0                  ;Yes -- terminate string
1264                 strb    r14,[r1],#1             ;Store the byte away
1265                 bne     a                       ;Loop until all done
1266                 mov     r3,r11                  ;Point to the format string
1267
1268                 ; --- Now read the actual string ---
1269
1270 .sl__dostr45    mov     r0,r13                  ;Point to the time block
1271                 add     r1,r13,#12              ;Point to output buffer
1272                 mov     r2,#128                 ;Get the buffer size
1273                 swi     "OS_ConvertDateAndTime" ;Translate the string
1274                 add     r13,r13,#8              ;Don't need the time any more
1275                 ldmfd   r13!,{r3}               ;Restore register I saved
1276                 mov     r2,r13                  ;Point to buffer start
1277                 b       sl__dostr30             ;Now output this string
1278
1279                 ; --- Finished reading the input ---
1280
1281 .sl__dostr50    add     r13,r13,#128            ;Reclaim my little buffer
1282                 FNflex_load("r1,r2,r4")         ;Restore caller's pointers
1283                 ldmfd   r13!,{r3,r14}           ;Restore other registers
1284                 bics    pc,r14,#V_flag          ;Return without an error
1285
1286                 ; --- Write byte in R0 to output ---
1287
1288 .sl__byte       mov     r1,r14                  ;Look after return address
1289                 FNflex_save("r6-r10")           ;Save lots of values
1290                 bl      xsave_byte              ;Write this byte out
1291                 FNflex_load("r6-r10")           ;Restore our registers
1292                 movvcs  pc,r1                   ;If OK, return to caller
1293
1294                 add     r13,r13,#128            ;Reclaim my little buffer
1295                 FNflex_load("r1,r2,r4")         ;Restore caller's pointers
1296                 ldmfd   r13!,{r3,r14}           ;Restore other registers
1297                 orrs    pc,r14,#V_flag          ;And return the error
1298
1299                 FNltorg
1300
1301 ;----- Loading modules ------------------------------------------------------
1302
1303 ; --- sl__loadMod ---
1304 ;
1305 ; On entry;     R1 == pointer to filename
1306 ;
1307 ; On exit;      May return an error
1308 ;
1309 ; Use;          Loads a module and adds its SWIs to the current list.
1310
1311 .sl__loadMod    stmfd   r13!,{r0-r2,r14}        ;Save some registers
1312                 add     r2,r12,#sl__module      ;Point to anchor for this
1313                 bl      load_file               ;Try to load the file
1314                 strvs   r0,[r13,#0]             ;If failed, return error
1315                 ldmfd   r13!,{r0-r2,pc}         ;Return to caller
1316
1317                 FNltorg
1318
1319 ; --- sl__ibMod ---
1320 ;
1321 ; On entry;     R1 == estimated file size
1322 ;
1323 ; On exit;      May return an error
1324 ;
1325 ; Use;          Sets up a buffer for RAM loading.
1326
1327 .sl__ibMod      add     r2,r12,#sl__module      ;Point to anchor
1328                 b       load_initBuf            ;Start the load op
1329
1330                 FNltorg
1331
1332 ; --- sl__doneMod ---
1333 ;
1334 ; On entry;     --
1335 ;
1336 ; On exit;      --
1337 ;
1338 ; Use;          Adds a module to the SWI list.
1339
1340 .sl__doneMod    stmfd   r13!,{r0-r2,r14}        ;Save some registers
1341                 ldr     r0,[r12,#sl__module]    ;Load the flex anchor
1342                 bl      sl__scanMod             ;Scan the module
1343                 bvs     sl__doneMod50           ;If it failed, quit now
1344                 add     r0,r12,#sl__module      ;Point to the anchor
1345                 bl      flex_free               ;Free the block
1346                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
1347
1348 .sl__doneMod50  add     r2,r0,#4                ;Look after the error
1349                 add     r0,r12,#sl__module      ;Point to the anchor
1350                 bl      flex_free               ;Free the block
1351                 adr     r0,FNliterr(1,"slMAA")
1352                 bl      msgs_error              ;Translate and substitute
1353                 mov     r1,#1                   ;Only have one button
1354                 bl      errorBox                ;Report the error
1355                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
1356
1357                 FNltorg
1358
1359 ; --- sl__lfMod ---
1360 ;
1361 ; On entry;     R0 == pointer to error
1362 ;               R1 == 1
1363 ;
1364 ; On exit;      --
1365 ;
1366 ; Use;          Reports an error when an attemt to load a module failed.
1367
1368 .sl__lfMod      stmfd   r13!,{r0-r2,r14}        ;Save some registers
1369                 cmp     r0,#0                   ;Is there a real error?
1370                 addne   r2,r0,#4                ;Point to error text
1371                 adrne   r0,FNliterr(1,"slLFM")
1372                 blne    msgs_error              ;Translate and substitute
1373                 movne   r1,#1                   ;Only use one button
1374                 blne    errorBox                ;Report the error
1375                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
1376
1377                 FNltorg
1378
1379 ;----- Loading dump files ---------------------------------------------------
1380
1381 ; --- sl__loadDmp ---
1382 ;
1383 ; On entry;     R1 == pointer to filename
1384 ;
1385 ; On exit;      May return an error
1386 ;
1387 ; Use;          Loads a module and adds its SWIs to the current list.
1388
1389 .sl__loadDmp    stmfd   r13!,{r0-r2,r14}        ;Save some registers
1390                 add     r0,r12,#sl__anchor      ;Point to the anchor
1391                 ldr     r14,[r12,#sl__anchor]   ;Load the current anchor
1392                 cmp     r14,#0                  ;Is it defined currently?
1393                 blne    flex_free               ;Yes -- free the block
1394                 add     r2,r12,#sl__anchor      ;Point to anchor for this
1395                 bl      load_file               ;Try to load the file
1396                 strvs   r0,[r13,#0]             ;On error, return pointer
1397                 ldmfd   r13!,{r0-r2,pc}         ;And return to caller
1398
1399                 FNltorg
1400
1401 ; --- sl__ibDmp ---
1402 ;
1403 ; On entry;     R1 == estimated file size
1404 ;
1405 ; On exit;      May return an error
1406 ;
1407 ; Use;          Sets up a buffer for RAM loading.
1408
1409 .sl__ibDmp      stmfd   r13!,{r0,r14}           ;Save some registers
1410                 add     r0,r12,#sl__anchor      ;Point to the anchor
1411                 ldr     r14,[r12,#sl__anchor]   ;Load the current anchor
1412                 cmp     r14,#0                  ;Is it defined currently?
1413                 blne    flex_free               ;Yes -- free the block
1414                 ldmfd   r13!,{r0,r14}           ;Unstack the registers
1415                 add     r2,r12,#sl__anchor      ;Point to anchor
1416                 b       load_initBuf            ;Start the load op
1417
1418                 FNltorg
1419
1420 ; --- sl__doneDmp ---
1421 ;
1422 ; On entry;     R0 == pointer to `filename'
1423 ;
1424 ; On exit;      --
1425 ;
1426 ; Use;          Handles a completed load of a dump file.
1427
1428 .sl__doneDmp    stmfd   r13!,{r0,r1,r14}        ;Save some registers
1429                 mov     r1,r0                   ;Point to the file's name
1430                 bl      sl__setDumpName         ;Set the name up correctly
1431                 add     r0,r12,#sl__anchor      ;Point to the anchor block
1432                 bl      flex_size               ;Read the block's size
1433                 str     r0,[r12,#sl__used]      ;Save the size as used value
1434                 str     r0,[r12,#sl__size]      ;And as the size value
1435                 ldr     r14,[r12,#sl__flags]    ;Load the flags word
1436                 bic     r14,r14,#slFlag__modified ;Got it from someone else
1437                 str     r14,[r12,#sl__flags]    ;Store the flags back
1438                 bl      sl__setFlags            ;Reset the flags nicely
1439                 ldmfd   r13!,{r0,r1,pc}^        ;Return to caller
1440
1441                 FNltorg
1442
1443 ; --- sl__lfDmp ---
1444 ;
1445 ; On entry;     R0 == pointer to error
1446 ;               R1 == 1
1447 ;
1448 ; On exit;      --
1449 ;
1450 ; Use;          Reports an error when an attemt to load a module failed.
1451
1452 .sl__lfDmp      stmfd   r13!,{r0-r2,r14}        ;Save some registers
1453                 bl      sl__setFlags            ;Update the flags
1454                 cmp     r0,#0                   ;Is there a real error?
1455                 addne   r2,r0,#4                ;Point to error text
1456                 adrne   r0,FNliterr(1,"slLFM")
1457                 blne    msgs_error              ;Translate and substitute
1458                 movne   r1,#1                   ;Only use one button
1459                 blne    errorBox                ;Report the error
1460                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
1461
1462                 FNltorg
1463
1464 ;----- Format of the SWI table ----------------------------------------------
1465 ;
1466 ; In order to speed things up, we maintain a table of SWI names in memory,
1467 ; and write this out to a file when the user wants us to.  This also means
1468 ; that we can build up a list of SWIs over a period of time, by the user
1469 ; dropping module files onto our icon or window -- this saves having to load
1470 ; large numbers of modules into the RMA.
1471 ;
1472 ; The format is fairly simple.  We keep a linked list of module blocks in
1473 ; a flex block.  The blocks are sorted by ascending order of SWI chunk base
1474 ; numbers.  Each module block looks like this;
1475 ;
1476 ;   word;       size of this link block
1477 ;   word;       SWI chunk base number for module and flags in top 8 bits
1478 ;   string;     name of module which provides these SWIs (null-terminated)
1479 ;   string;     SWI prefix for following SWI names (null-terminated)
1480 ;   string;     name of first SWI provided by module (null-terminated)
1481 ;   string;     name of second SWI provided by module (null-terminated)
1482 ;   ...         ...
1483 ;   string;     name of last SWI provided by module (null-terminated)
1484 ;   byte;       0 (list terminator)
1485 ;   align;      to word boundary
1486
1487 ; --- sl__setDumpName ---
1488 ;
1489 ; On entry;     R1 == 0 for default `SWIDump' or pointer to name
1490 ;
1491 ; On exit;      --
1492 ;
1493 ; Use;          Sets the name of the current dump file.
1494
1495 .sl__setDumpName stmfd r13!,{r0-r2,r14}         ;Save some registers
1496                 movs    r0,r1                   ;Point to the source string
1497                 adreq   r0,FNlitsz("SWIDump")   ;No string -- use default
1498                 add     r1,r12,#sl__dumpFile    ;Point to the name buffer
1499                 mov     r2,#256                 ;The buffer size
1500                 orr     r2,r2,#&C0000000        ;Don't do `|'s or `""'s
1501                 swi     "OS_GSTrans"            ;Expand system variables
1502                 ldmfd   r13!,{r0-r2,pc}^        ;And return to caller
1503
1504                 FNltorg
1505
1506 ; --- sl__initBlock ---
1507 ;
1508 ; On entry;     --
1509 ;
1510 ; On exit;      May return an error
1511 ;
1512 ; Use;          Initialises the SWI list block with the currently recognised
1513 ;               OS SWIs.
1514
1515 .sl__initBlock  stmfd   r13!,{r0-r3,r14}        ;Save some registers
1516
1517                 add     r0,r12,#sl__anchor      ;Point to the anchor
1518                 ldr     r14,[r12,#sl__anchor]   ;Load the current anchor
1519                 cmp     r14,#0                  ;Is it defined currently?
1520                 blne    flex_free               ;Yes -- free the block
1521
1522                 ; --- Reset the dump file name ---
1523
1524                 mov     r1,#0                   ;Use the default name
1525                 bl      sl__setDumpName         ;Go and do that please
1526
1527                 ; --- Create the flex block ---
1528
1529                 mov     r1,#1024                ;Initially make it 1K
1530                 bl      flex_alloc              ;Allocate the block
1531                 blcs    alloc_error             ;If it failed, get an error
1532                 bcs     sl__initBlk90           ;And abort now
1533
1534                 mov     r14,r1                  ;Get the size created
1535                 mov     r1,#0                   ;Start output at beginning
1536                 stmib   r0,{r1,r14}             ;Store sizes after anchor
1537
1538                 ; --- Now build the kernel SWIs ---
1539                 ;
1540                 ; First do OS_WriteI.  Then we do the kernel SWIs lower than
1541                 ; &100.
1542
1543                 adr     r0,FNlitsz("Kernel")    ;Point to string `Kernel'
1544                 adr     r1,FNlitsz("OS")        ;Point to string `OS'
1545                 mov     r2,#&100                ;Get SWI chunk number
1546                 bl      sl__newLink             ;Add in a new link block
1547                 bvs     sl__initBlk89           ;If it failed, stop going
1548                 bcs     sl__initBlk05           ;If already done, skip
1549                 add     r0,r12,#sl__anchor      ;Point to the anchor
1550                 adr     r1,FNlitsz("WriteI")    ;Point to string `WriteI'
1551                 bl      sl__string              ;Add it to the block
1552                 blvc    sl__endLink             ;Terminate this link
1553                 bvs     sl__initBlk89           ;If it failed, stop going
1554
1555                 ; --- Now do the kernel SWIs ---
1556
1557 .sl__initBlk05  adr     r0,FNlitsz("Kernel")    ;Point to string `Kernel'
1558                 adr     r1,FNlitsz("OS")        ;Point to string `OS'
1559                 mov     r2,#&0                  ;Get SWI chunk number
1560                 bl      sl__newLink             ;Add in a new link block
1561                 bvs     sl__initBlk89           ;If it failed, stop going
1562                 bcs     sl__initBlk17           ;Already there -- skip on
1563                 mov     r3,#0                   ;Start at SWI number 0
1564
1565 .sl__initBlk10  mov     r0,r3                   ;Get the SWI number
1566                 mov     r1,r11                  ;Build string in scratchpad
1567                 mov     r2,#256                 ;And give the block size
1568                 swi     "OS_SWINumberToString"  ;Read the SWI name
1569                 swi     "XOS_SWINumberFromString" ;Try to convert back
1570                 cmp     r0,r3                   ;Is this what we expected?
1571                 bne     sl__initBlk13           ;No -- skip to end of loop
1572
1573                 add     r0,r12,#sl__anchor      ;Point to the anchor
1574                 add     r1,r11,#3               ;Skip past `OS_' prefix
1575                 bl      sl__string              ;Add it to the list
1576                 bvs     sl__initBlk89           ;If it failed, stop going
1577                 b       sl__initBlk15           ;Skip past the next bit
1578
1579 .sl__initBlk13  add     r0,r12,#sl__anchor      ;Point to the anchor
1580                 mov     r1,#1                   ;Want one extra byte
1581                 bl      sl__ensure              ;Make sure I've got it
1582                 bvs     sl__initBlk89           ;If it failed, stop going
1583                 mov     r14,#1                  ;Mark this as nonexistant
1584                 strb    r14,[r0],#1             ;Store it in the block
1585
1586 .sl__initBlk15  add     r3,r3,#1                ;Bump the SWI number
1587                 cmp     r3,#&100                ;Reached the end yet?
1588                 blt     sl__initBlk10           ;No -- go back round then
1589
1590                 ; --- Finished that; end the link block ---
1591
1592                 bl      sl__endLink             ;Terminate the link block
1593                 bvs     sl__initBlk89           ;If it failed, stop going
1594
1595                 ; --- Now go through the module list ---
1596
1597 .sl__initBlk17  mov     r1,#0                   ;Start on first module
1598 .sl__initBlk20  mov     r2,#0                   ;Start on first instance
1599                 mov     r0,#12                  ;Enumerate module addresses
1600                 swi     "XOS_Module"            ;Read next module number
1601                 bvs     sl__initBlk30           ;If error must have finished
1602                 mov     r0,r3                   ;Point to module base address
1603                 bl      sl__scanMod             ;Scan module for SWIs
1604                 bvs     sl__initBlk90           ;If it failed, stop going
1605                 cmp     r2,#0                   ;Are there more instances?
1606                 addne   r1,r1,#1                ;Yes -- move to next module
1607                 b       sl__initBlk20           ;Go handle the next module
1608
1609                 ; --- Finished the module list ---
1610
1611 .sl__initBlk30  bl      sl__setFlags            ;Reset the flags
1612                 ldmfd   r13!,{r0-r3,r14}        ;Unstack the registers
1613                 bics    pc,r14,#V_flag          ;And return without error
1614
1615                 ; --- Something went wrong ---
1616
1617 .sl__initBlk89  mov     r3,r0                   ;Look after error pointer
1618                 add     r0,r12,#sl__anchor      ;Point to the anchor
1619                 bl      flex_free               ;Free the block
1620                 mov     r1,#0                   ;Clear the anchor pointer
1621                 str     r1,[r12,#sl__anchor]    ;Save it in the block
1622                 bl      sl__setFlags            ;Reset the flags nicely
1623                 mov     r0,r3                   ;And restore error pointer
1624
1625 .sl__initBlk90  add     r13,r13,#4              ;Don't restore R0 on exit
1626                 ldmfd   r13!,{r1-r3,r14}        ;Restore registers
1627                 orrs    pc,r14,#V_flag          ;And return the error
1628
1629                 FNltorg
1630
1631 ; --- sl__scanMod ---
1632 ;
1633 ; On entry;     R0 == pointer to module
1634 ;
1635 ; On exit;      May return an error
1636 ;
1637 ; Use;          Scans a module, and adds its SWIs to the list.
1638
1639 .sl__scanMod    stmfd   r13!,{r0-r4,r14}        ;Save some registers
1640                 mov     r3,r0                   ;Look after module base
1641
1642                 ; --- Make sure this module's OK ---
1643
1644                 ldr     r0,[r3,#16]             ;Load the name offset
1645                 ldr     r1,[r3,#36]             ;Load the SWI name table
1646                 ldr     r2,[r3,#28]             ;And the SWI chunk number
1647                 cmp     r0,#256*1024            ;Make sure these are valid
1648                 cmpcc   r1,#256*1024            ;Both offsets please
1649                 bcs     sl__scanMod80           ;If not, ignore this module
1650
1651                 tst     r2,#&FF000000           ;Make sure SWI chunk's OK
1652                 tsteq   r2,#&0000003f
1653                 tsteq   r2,#&00020000
1654                 bne     sl__scanMod80           ;If not, ignore this module
1655                 cmp     r2,#&200                ;Is chunk in user range?
1656                 bcc     sl__scanMod80           ;No -- ignore this module
1657
1658                 ; --- Set the file modified flag ---
1659
1660                 ldr     r14,[r12,#sl__flags]    ;Load the flags word
1661                 orr     r14,r14,#slFlag__modified ;Set the flag
1662                 str     r14,[r12,#sl__flags]    ;Save the flags back again
1663
1664                 ; --- We now have a module to add ---
1665                 ;
1666                 ; For error recovery, we read the current block sizes, so
1667                 ; we can reset them if all goes wrong.
1668
1669                 add     r0,r3,r0                ;Translate offset to address
1670                 add     r1,r3,r1                ;For both offsets
1671                 add     r14,r12,#sl__used       ;Point to block size info
1672                 ldmia   r14,{r3,r4}             ;Load the size counts
1673                 FNflex_save("r1")               ;Look after this pointer
1674                 bl      sl__newLink             ;Add a new link in
1675                 FNflex_load("r1")               ;Restore pointer afterwards
1676                 bvs     sl__scanMod90           ;If it failed, return error
1677
1678                 ; --- Now just add the SWI names in ---
1679
1680 .sl__scanMod10  ldrb    r14,[r1],#1             ;Load a SWI prefix byte
1681                 cmp     r14,#0                  ;Is this the end yet?
1682                 bne     sl__scanMod10           ;No -- keep on going
1683
1684                 ldrb    r14,[r1],#0             ;Load the next byte out
1685                 cmp     r14,#0                  ;Is this the double-0?
1686                 beq     sl__scanMod15           ;Yes -- end right now
1687                 add     r0,r12,#sl__anchor      ;Point to anchor block
1688                 FNflex_save("r1")               ;Save this pointer away
1689                 bl      sl__string              ;Add string to the list
1690                 FNflex_load("r1")               ;Restore this pointer
1691                 bvs     sl__scanMod89           ;If it failed, report error
1692                 b       sl__scanMod10           ;Keep on adding names
1693
1694                 ; --- Finished that -- wrap everything up ---
1695
1696 .sl__scanMod15  bl      sl__endLink             ;Terminate this block
1697                 bvs     sl__scanMod89           ;If it failed, tidy up
1698 .sl__scanMod80  ldmfd   r13!,{r0-r4,r14}        ;Restore registers
1699                 bics    pc,r14,#V_flag          ;And return with V clear
1700
1701                 ; --- Failed to do the job ---
1702
1703 .sl__scanMod89  mov     r2,r0                   ;Save the error pointer
1704                 add     r0,r12,#sl__anchor      ;Point to the flex anchor
1705                 mov     r1,r4                   ;Get the old size value
1706                 bl      flex_extend             ;Reset the size
1707                 stmib   r0,{r3,r4}              ;Save old index values
1708                 mov     r0,r2                   ;Restore the error pointer
1709
1710 .sl__scanMod90  add     r13,r13,#4              ;Don't restore R0 on exit
1711                 ldmfd   r13!,{r1-r4,r14}        ;Restore the other registers
1712                 orrs    pc,r14,#V_flag          ;And return to caller
1713
1714                 FNltorg
1715
1716 ; --- sl__newLink ---
1717 ;
1718 ; On entry;     R0 == pointer to module name
1719 ;               R1 == pointer to SWI prefix
1720 ;               R2 == SWI chunk number
1721 ;
1722 ; On exit;      May return an error
1723 ;
1724 ; Use;          Ensures that a link block for the given module exists.  If
1725 ;               it doesn't exist already, it is created at the end of the
1726 ;               flex block.  The index of the last link is returned, so it
1727 ;               can be cleared if the actual SWI names can't be added.
1728
1729 .sl__newLink    stmfd   r13!,{r0-r7,r14}        ;Save some registers
1730
1731                 ; --- Set up for checking loop ---
1732
1733                 mov     r3,r0                   ;Look after module name
1734                 mov     r4,r1                   ;And the SWI prefix string
1735                 FNflex_save("r1,r3")            ;Save these for relocation
1736                 add     r14,r12,#sl__anchor     ;Point to the anchor
1737                 ldmia   r14,{r5,r6}             ;Load base and size
1738
1739                 ; --- Wade on through the block ---
1740
1741                 mov     r7,#0                   ;Start at offset 0
1742 .sl__newl10     cmp     r7,r6                   ;Reached the end yet?
1743                 bcs     sl__newl30              ;Yes -- better stop then
1744
1745                 ; --- See if this is a match ---
1746
1747                 add     r14,r5,r7               ;Find current address
1748                 ldr     r0,[r14,#4]             ;Load the SWI chunk number
1749                 bic     r0,r0,#&ff000000        ;Clear the flags byte
1750                 cmp     r0,r2                   ;Does this match our one?
1751                 bne     sl__newl15              ;No -- move along then
1752
1753                 add     r0,r14,#8               ;Point to the module name
1754                 mov     r1,r3                   ;Point to our module name
1755                 bl      str_cmp                 ;Compare the strings
1756                 bne     sl__newl15              ;No match -- move along then
1757
1758 .sl__newl13     ldrb    r14,[r0],#1             ;Load module name byte
1759                 cmp     r14,#32                 ;Is this the end?
1760                 bcs     sl__newl13              ;No -- keep going
1761
1762                 mov     r1,r4                   ;Point to the SWI prefix
1763                 bl      str_cmp                 ;Do these match?
1764                 beq     sl__newl20              ;Yes -- remove this chunk
1765
1766 .sl__newl15     ldr     r14,[r5,r7]             ;Load the length of this one
1767                 add     r7,r7,r14               ;Move on to the next block
1768                 b       sl__newl10              ;And keep on going
1769
1770                 ; --- Found a match -- remove a chunk ---
1771
1772 .sl__newl20     add     r0,r12,#sl__anchor      ;Point to the anchor
1773                 ldr     r2,[r5,r7]              ;Get the block's size
1774                 add     r1,r7,r2                ;Start at the end of it
1775                 rsb     r2,r2,#0                ;And reduce block by this
1776                 bl      flex_midExtend          ;Remove this chunk of data
1777                 add     r6,r6,r2                ;Modify the block size
1778                 str     r6,[r12,#sl__used]      ;Save this size back
1779                 ldr     r14,[r12,#sl__size]     ;Load the total block size
1780                 add     r14,r14,r2              ;Adjust that value too
1781                 str     r14,[r12,#sl__size]     ;Store my modified value back
1782                 ldr     r2,[r13,#8]             ;Restore caller's SWI base
1783
1784                 ; --- Add a new chunk onto the block ---
1785
1786 .sl__newl30     str     r6,[r12,#sl__last]      ;Save the base of this block
1787                 ldr     r7,[r12,#sl__size]      ;Get the block total size
1788
1789                 add     r0,r12,#sl__anchor      ;Point to anchor and info
1790                 mov     r1,#8                   ;Add in fixed size info
1791                 bl      sl__ensure              ;Make sure there's enough
1792                 strvc   r2,[r0,#4]              ;Save the SWI chunk number
1793
1794                 addvc   r0,r12,#sl__anchor      ;Point to anchor and info
1795                 FNflex_load("r1")               ;Unstack module name pointer
1796                 blvc    sl__string              ;Add the string in
1797                 FNflex_load("r1")               ;Unstack SWI prefix string
1798                 blvc    sl__string              ;Add the string in
1799
1800                 ldmvcfd r13!,{r0-r7,r14}        ;Unstack registers
1801                 bicvcs  pc,r14,#V_flag          ;And return to caller
1802
1803                 ; --- It failed -- better tidy up ---
1804
1805                 mov     r2,r0                   ;Look after error number
1806                 add     r0,r12,#sl__anchor      ;Point to the anchor
1807                 mov     r1,r7                   ;Get the old size back
1808                 bl      flex_extend             ;Reset the block size
1809                 stmib   r0,{r6,r7}              ;Save the old values back
1810                 mov     r0,r2                   ;Get the error pointer
1811                 add     r13,r13,#4              ;Don't restore R0 on exit
1812                 ldmfd   r13!,{r1-r7,r14}        ;Restore registers
1813                 orrs    pc,r14,#V_flag          ;Return the error
1814
1815                 FNltorg
1816
1817 ; --- sl__endLink ---
1818 ;
1819 ; On entry;     --
1820 ;
1821 ; On exit;      May return an error
1822 ;
1823 ; Use;          Terminates a link block.
1824
1825 .sl__endLink    stmfd   r13!,{r0,r1,r14}        ;Save some registers
1826                 add     r0,r12,#sl__anchor      ;Find the flex block
1827                 mov     r1,#1                   ;Want to add a single byte
1828                 bl      sl__ensure              ;Make sure we've got enough
1829                 bvs     sl__endl90              ;If it failed, return
1830
1831                 mov     r14,#0                  ;Get the NULL byte ready
1832                 strb    r14,[r0,#0]             ;Save it at the end nicely
1833                 add     r0,r12,#sl__anchor      ;Find the flex block again
1834                 bl      sl__align               ;Word align output pointer
1835
1836                 ldmia   r0,{r0,r14}             ;Load block base and size
1837                 ldr     r1,[r12,#sl__last]      ;Load the offset of the block
1838                 sub     r14,r14,r1              ;Get the last chunk size?
1839                 str     r14,[r0,r1]             ;Save the length word
1840
1841                 ldmfd   r13!,{r0,r1,r14}        ;And return to caller
1842                 bics    pc,r14,#V_flag          ;Return without error
1843
1844 .sl__endl90     add     r13,r13,#4              ;Don't return R0 on exit
1845                 ldmfd   r13!,{r1,r14}           ;Restore registers
1846                 orrs    pc,r14,#V_flag          ;And return the error
1847
1848                 FNltorg
1849
1850 ;----- Block management routines --------------------------------------------
1851
1852 ; --- sl__ensure ---
1853 ;
1854 ; On entry;     R0 == pointer to anchor/size block
1855 ;               R1 == number of bytes to add
1856 ;
1857 ; On exit;      R0 == pointer to allocated area
1858 ;               May return an error
1859 ;
1860 ; Use;          Ensures that there are R1 bytes free at the end of the given
1861 ;               flex block.
1862
1863 .sl__ensure     stmfd   r13!,{r1,r2,r14}        ;Save some registers
1864                 ldmib   r0,{r2,r14}             ;Load the base and sizes
1865                 add     r1,r1,r2                ;Find new total size
1866                 str     r1,[r0,#4]              ;Save this back
1867                 add     r1,r1,#255              ;Align up to next 256
1868                 bic     r1,r1,#255              ;For niceness's sake
1869                 cmp     r1,r14                  ;Do we already have enough
1870                 bhi     sl__ensure50            ;No -- allocate some more
1871 .sl__ensure10   str     r1,[r0,#8]              ;Save new total size
1872                 ldr     r0,[r0,#0]              ;Load address of block
1873                 add     r0,r0,r2                ;Point to first free byte
1874                 ldmfd   r13!,{r1,r2,r14}        ;Unstack registers
1875                 bics    pc,r14,#V_flag          ;And return without error
1876
1877 .sl__ensure50   bl      flex_extend             ;Extend the block nicely
1878                 bcc     sl__ensure10            ;Rejoin program if OK
1879                 bl      alloc_error             ;Get the error message
1880                 ldmfd   r13!,{r1,r2,pc}         ;Return error to caller
1881
1882                 FNltorg
1883
1884 ; --- sl__string ---
1885 ;
1886 ; On entry;     R0 == pointer to flex block and size information
1887 ;               R1 == pointer to string
1888 ;
1889 ; On exit;      May return an error
1890 ;
1891 ; Use;          Adds a string to a flex block.
1892
1893 .sl__string     stmfd   r13!,{r0-r3,r14}        ;Save some registers
1894                 mov     r2,r0                   ;Look after anchor address
1895                 FNflex_save("r1")               ;Save the string address
1896                 mov     r0,r1                   ;Point to the string
1897                 bl      str_len                 ;Work out the length
1898                 add     r1,r0,#1                ;Get the required size
1899                 mov     r0,r2                   ;Point to anchor and sizes
1900                 bl      sl__ensure              ;Make sure the space is OK
1901                 FNflex_load("r1")               ;Restore R1 from stack
1902                 blvc    str_cpy                 ;And copy it into the block
1903                 strvs   r0,[r13,#0]             ;Otherwise store the error
1904                 ldmfd   r13!,{r0-r3,pc}         ;And return to caller
1905
1906                 FNltorg
1907
1908 ; --- sl__align ---
1909 ;
1910 ; On entry;     R0 == pointer to flex anchor and size info
1911 ;
1912 ; On exit;      --
1913 ;
1914 ; Use;          Word aligns the output pointer of a flex block.
1915
1916 .sl__align      stmfd   r13!,{r14}              ;Save a register
1917                 ldr     r14,[r0,#4]             ;Load the output offset
1918                 add     r14,r14,#3              ;Word align this offset
1919                 bic     r14,r14,#3              ;Mask off bottom bits
1920                 str     r14,[r0,#4]             ;Store new offset back
1921                 ldmfd   r13!,{pc}^              ;And return to caller
1922
1923                 FNltorg
1924
1925 ;----- Workspace ------------------------------------------------------------
1926 ]
1927                 PROCws_start
1928
1929 sl__flags       =FNws_word              :REM    ;Various flags bits
1930 sl__anchor      =FNws_word              :REM    ;Flex anchor for SWI table
1931 sl__used        =FNws_word              :REM    ;Size used in flex block
1932 sl__size        =FNws_word              :REM    ;Actual size of flex block
1933 sl__last        =FNws_word              :REM    ;Offset of last block
1934 sl__modNames    =FNws_word              :REM    ;Block for module names
1935 sl__format      =FNws_word              :REM    ;Format chunk handle
1936 sl__module      =FNws_word              :REM    ;Anchor for loading modules
1937 sl__pollBlock   =FNws   (256)           :REM    ;Wimp_Poll data block
1938 sl__dumpFile    =FNws   (256)           :REM    ;Full pathname of dump file
1939
1940 sl__wSize       =FNws   (0)
1941
1942 slFlag__block   =       (1<<0)          :REM    ;We have a SWI block
1943 slFlag__format  =       (1<<1)          :REM    ;There is a format
1944 slFlag__savable =       (1<<2)          :REM    ;We can save a SWI list
1945 slFlag__modified=       (1<<3)          :REM    ;SWI block is unsaved
1946 slFlag__saving  =       (1<<4)          :REM    ;We're saving a dump
1947
1948 [               opt     o
1949
1950 ]
1951 NEXT
1952
1953 PROCbas_aofSave
1954 END
1955
1956 REM -- Macros ---------------------------------------------------------------
1957
1958 DEF FNs(s$)
1959 [ opt 4
1960   equs s$
1961   dcb 0
1962 ]
1963 =0
1964 DEFFNP(i%):PRINT~i%:=0