; Copyright 1996 Acorn Computers Ltd ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. ; You may obtain a copy of the License at ; ; http://www.apache.org/licenses/LICENSE-2.0 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ; Kernel.Messages ; ; This file deals with translating text and errors in an international ; kernel. ; ; ; TranslateError ; Entry: ; R0 = Pointer to error block (Error number followed by token:default). ; Exit ; R0 = pointer to error block to use. ; If the error semaphore is set a pointer to the original block is ; returned. ; V Set. ; ; EXPORT Write0_Translated GBLL countmsgusage countmsgusage SETL {FALSE} [ countmsgusage ! 0, "*** WARNING: Cacheing *ALL* messages - even those with substitutions" ] TranslateError_VClear ROUT Push "r4,LR" MOV r4,#0 BL TranslateError_UseR4 CLRV Pull "r4,PC" TranslateError ROUT Push "r4,LR" MOV r4,#0 BL TranslateError_UseR4 Pull "r4,PC" TranslateError_UseR4 Push "R8,R9,LR" MRS R8,CPSR ORR R8,R8,#V_bit ; V set ready :) LDR LR, =ZeroPage LDRB R9, [LR, #ErrorSemaphore] TEQ R9,#0 BNE %FT90 BIC R9, R8, #&0F ORR R9, R9, #SVC_mode ; SVC mode, preserve IRQ state MSR CPSR_c, R9 Push "R0-R7" MOV R5,#0 MOV R6,#0 MOV R7,#0 MOV R1,#-1 ; We are looking up an error, don't bother STRB R1, [LR, #ErrorSemaphore] ; translating other errors. [ CacheCommonErrors BL CheckCommonErrorCache ; sets R9 to memory address for cached result [ ZeroPage = 0 MOVNE R1,#0 ] STRNE R9,[SP] BNE %FT80 MOV R2,R9 ; 0 - or our cached area! MOV R3,#256 | MOV R2,#0 ] LDR R1,=ZeroPage+KernelMessagesBlock+4 SWI XMessageTrans_ErrorLookup LDR R14,[R0] LDR R1,[SP] LDR R1,[R1] CMP R14,R1 STREQ R0,[SP] [ (ZeroPage = 0) :LOR: CacheCommonErrors MOV R1,#0 ; To clear the semaphore ] [ CacheCommonErrors TEQNE R9,#0 ; Did we try to cache this message? STRNE R1,[R9] ; blat out the error number 80 ] [ ZeroPage <> 0 ASSERT (ZeroPage :AND: 255) = 0 LDR R1, =ZeroPage ] STRB R1, [R1 ,#ErrorSemaphore] ; Clear error semaphore Pull "R0-R7" 90 MSR CPSR_cf, R8 ; Back to original mode, V set Pull "R8,R9,PC" [ CacheCommonErrors ; This block MUST not be empty CommonErrorAddresses [ countmsgusage & ErrorBlock_RMNot32bit & ErrorBlock_RCExc & ErrorBlock_RCNegative & ErrorBlock_BadString & ErrorBlock_VarCantFind & ErrorBlock_BadVarType & ErrorBlock_BadVarNam & ErrorBlock_VarTooLong & ErrorBlock_BadMacVal & ErrorBlock_VarNoRoom & ErrorBlock_BadBra & ErrorBlock_StkOFlo & ErrorBlock_MissOpn & ErrorBlock_MissOpr & ErrorBlock_BadInt & ErrorBlock_StrOFlo & ErrorBlock_NaffItm & ErrorBlock_DivZero & ErrorBlock_BadBase & ErrorBlock_NumbTooBig & ErrorBlock_BadClaimNum & ErrorBlock_SysHeapFull & ErrorBlock_BadDynamicArea & ErrorBlock_AreaAlreadyExists & ErrorBlock_AreaNotOnPageBdy & ErrorBlock_OverlappingAreas & ErrorBlock_CantAllocateArea & ErrorBlock_CantAllocateLevel2 & ErrorBlock_UnknownAreaHandler & ErrorBlock_CantGetPhysMem & ErrorBlock_AplWSpaceInUse & ErrorBlock_ChDynamCAO & ErrorBlock_RAMFsUnchangeable & ErrorBlock_HeapBadReason & ErrorBlock_HeapFail_Init & ErrorBlock_HeapFail_BadDesc & ErrorBlock_HeapFail_BadLink & ErrorBlock_HeapFail_Alloc & ErrorBlock_HeapFail_NotABlock & ErrorBlock_HeapFail_BadExtend & ErrorBlock_HeapFail_ExcessiveShrink & ErrorBlock_NoSuchSWI1 & ErrorBlock_NoSuchSWI & ErrorBlock_UndefinedInstruction & ErrorBlock_InstructionAbort & ErrorBlock_DataAbort & ErrorBlock_AddressException & ErrorBlock_BranchThrough0 & ErrorBlock_BadEnvNumber & ErrorBlock_BadReadSysInfo & ErrorBlock_BadModuleReason & ErrorBlock_NoMoreModules & ErrorBlock_NoMoreIncarnations & ErrorBlock_PostfixNeeded & ErrorBlock_IncarnationExists & ErrorBlock_ChunkNotRM & ErrorBlock_MHNoRoom & ErrorBlock_ModulePostfix & ErrorBlock_NotMod & ErrorBlock_BadRMHeaderField & ErrorBlock_CantKill & ErrorBlock_RMNotFound & ErrorBlock_IncarnationNotFound & ErrorBlock_RMNotFoundInROM & ErrorBlock_ModuleTooOld & ErrorBlock_BadParameters & ErrorBlock_ArgRepeated & ErrorBlock_NaffDevNo & ErrorBlock_BadDevVecRel & ErrorBlock_RedirectFail & ErrorBlock_StackFull & ErrorBlock_OscliLongLine & ErrorBlock_NoOscliSpecials & ErrorBlock_OscliTooHard & ErrorBlock_BadParmString & ErrorBlock_CoreNotWriteable & ErrorBlock_CoreNotReadable & ErrorBlock_BadCommand & ErrorBlock_NoSuchSWI2 & ErrorBlock_TooManyParms & ErrorBlock_BadKey & ErrorBlock_BadAddress & ErrorBlock_OutsideFile & ErrorBlock_Escape & ErrorBlock_BadTime & ErrorBlock_BadMODE & ErrorBlock_ModeNotAvailable & ErrorBlock_BadPixelDepth & ErrorBlock_Sprite_BadDPI & ErrorBlock_BadMSFlags & SpriteErr_NoWorkSpace & SpriteErr_NoRoom & SpriteErr_DoesntExist & SpriteErr_NoSprites & SpriteErr_NotGraphics & SpriteErr_NotEnoughRoom & SpriteErr_BadSpriteFile & SpriteErr_NoRoomToMerge & SpriteErr_Bad2ndPtr & SpriteErr_InvalidRowOrCol & SpriteErr_InvalidHeight & SpriteErr_InvalidWidth & SpriteErr_NoRoomToInsert & SpriteErr_SpriteAlreadyExists & SpriteErr_InvalidSpriteMode & SpriteErr_BadReasonCode & SpriteErr_CantInTeletext & SpriteErr_InvalidSaveArea & SpriteErr_SpriteIsCurrentDest & SpriteErr_NoMaskOrPaletteAllowedInThisDepth ] & ErrorBlock_ChDynamNotAllMoved & ErrorBlock_NaffRelease & ErrorBlock_BuffOverflow & ErrorBlock_BadNumb EndCommonErrorAddresses GBLA ECEACount ECEACount SETA (EndCommonErrorAddresses-CommonErrorAddresses)/4 ASSERT (EndCommonErrorAddresses <> CommonErrorAddresses) ! 0, "Requiring ":CC:(:STR:(ECEACount*256)):CC:" bytes for error cache" ! 0, "Cached error block pointer at ":CC::STR:CachedErrorBlocks ! 0, "Cacheing ":CC:(:STR:ECEACount):CC:" error messages" ; This routine exits with Z clear if it can supply a cached translation; else must set Z ; so that the TranslateError_UseR4 routine continues to function and set R9 to the cache ; block to use for the result (or set R9 to zero to indicate no cacheing for this error) CheckCommonErrorCache ROUT Entry "r1-r3" [ countmsgusage MOV r4, #0 ; prevents substitutions | CMP r4, #1 ; is R4 = 0? If so, clear C for next instruction SBCS r9, r4, r4 ; R9=0,Z set - if R4 was >0, else R9=-1, Z clear EXIT EQ ] [ ZeroPage = 0 LDR r9, [r4, #KernelMessagesBlock] ; R4 guaranteed zero from above | LDR r1, =ZeroPage LDR r9, [r1, #KernelMessagesBlock] ] TEQ r9, #0 EXIT EQ ; not initialised messages yet! Exit R9=0, Z set [ ZeroPage = 0 LDR r9, [r4, #CachedErrorBlocks] | LDR r9, [r1, #CachedErrorBlocks] ] TEQ r9, #0 ; in: R9=cached error blocks memory pointer BLEQ CommonErrorCacheInit ; out: R9=0 and EQ on error; else NE and R9 valid (also case if routine wasn't called) EXIT EQ ; not initialised cache yet ADR lr, CommonErrorAddresses MOV r2, #ECEACount - 1 10 LDR r1, [lr, r2, LSL #2] TEQ r1, r0 BEQ %FT20 SUBS r2, r2, #1 BPL %BT10 ; Set Z if message not found, set R9 zero to mark we don't want to cache this MOVS r9, #0 EXIT 20 [ countmsgusage ADD r3, r9, #ECEACount*256 LDR r1, [r3, r2, LSL #2] ADD r1, r1, #1 STR r1, [r3, r2, LSL #2] ] ; Read the cached error number (0 = we don't have this cached or we have uncached it) ; Update R9 to point to the actual error buffer at the same time. LDR r1, [r9, r2, LSL #8]! ; Set Z if we don't have that error cached yet, clear it and copy the cached ; block to R0 if we do already have this message. TEQ r1, #0 MOVNE r0, r9 EXIT ; On entry, R9 points to the error cache memory, or 0 to indicate we don't have it yet. ; If this routine exits Z clear (NE), it MUST have pointed R9 at the sys heap memory CommonErrorCacheInit ROUT Entry "r0-r8" MOVS r2, r9 ; copy R9 to R2 - only claim memory if it was 0 BNE %FT10 [ countmsgusage LDR r3, =ECEACount*260 ; size of block required | LDR r3, =ECEACount*256 ; size of block required ] BL ClaimSysHeapNode MOVS r9, #0 ; set Z for STREQ below and for return EXIT VS 10 MOV r3, #0 [ ZeroPage = 0 STREQ r2, [R3, #CachedErrorBlocks] | LDREQ r4, =ZeroPage STREQ r2, [r4, #CachedErrorBlocks] ] GBLA CECLoop CECLoop SETA 0 [ countmsgusage LDR r4, =ECEACount*260 90 SUBS r4, r4, #4 STR r3, [r2, r4] BNE %BT90 | WHILE CECLoop < ECEACount STR r3, [r2, #CECLoop * 256] CECLoop SETA CECLoop+1 WEND ] MOVS r9, r2 ; set up R9; clear Z EXIT ; Invoked by the service call handler in the UtilityModule to clear out our cache ; whenever the territory changes or messagetrans says that a messages file was changed. CacheCommonErrorsReinit Entry "r9" LDR r9, =ZeroPage LDR r9, [r9, #CachedErrorBlocks] TEQ r9, #0 BLNE CommonErrorCacheInit EXIT ] ;---------------------------------------------------------------------------------------- ; ;WriteS_Translated ;Entry: ; R14 -> Token. ;*NOTE* ; MUST BE TOKEN:DEFAULT ; ;Exit: ; Message printed ; Returns to word after end of token. ; WriteS_Translated ROUT Push "r0-r8,LR" MOV r4,#0 B Int_WriteS_Translated_UseR4 WriteS_Translated_UseR4 Push "r0-r8,LR" Int_WriteS_Translated_UseR4 MRS r8,CPSR MOV r1,LR LDR r2,=ZeroPage LDR r0,[r2,#KernelMessagesBlock] CMP r0,#0 ; If no messages file, try the global one. ADDNE r0,r2,#KernelMessagesBlock+4 MOV r2,#0 ; Use message in place. MOV r3,#0 MOV r5,#0 MOV r6,#0 MOV r7,#0 ; No arguments. SWI XMessageTrans_Lookup BVC %FT01 MOV R2,R1 ; MessageTrans not present or token not found. 00 LDRB r0,[r2],#1 ; Skip to after ":" CMP r0,#":" BNE %BT00 ; Now ; r1 -> terminator ; r2 -> message ; Print the message. 01 LDRB r0,[r2],#1 ; Print all characters of message CMP r0,#" " BLT %FT02 CMP r0,#"%" SWINE XOS_WriteC BNE %BT01 LDRB r0,[r2],#1 ; Found a % CMP r0,#" " BLT %FT02 ; Trailing % sign! CMP r0,#"0" SWINE XOS_WriteI+"%" SWINE XOS_WriteC BNE %BT01 ; Just in case it isn't %0 CMP r4,#0 ; r4 = original parameter BEQ %BT01 11 LDRB R0,[R4],#1 CMP R0,#" " SWIGE XOS_WriteC BGE %BT11 B %BT01 ; Now skip to end of token. 02 LDR r1,[sp,#9*4] ; Get original token pointer 03 LDRB r0,[r1],#1 CMP r0,#32 BGE %BT03 ; Skip to control character. 04 CMP r0,#0 ; Print all control characters to terminating 0. SWINE XOS_WriteC LDRNEB r0,[r1],#1 BNE %BT04 ; r1 now points at byte after end of token. ADD r1,r1,#3 ; Round up to next word. BIC r1,r1,#3 STR r1,[sp,#9*4] ; Store back as return address on stack ORRVS r8,r8,#V_bit MSR CPSR_f,r8 Pull "r0-r8,PC" ;Return. ;---------------------------------------------------------------------------------------- ; ;GSWriteS_Translated ;Entry: ; R14 -> Token. ;*NOTE* ; MUST BE TOKEN:DEFAULT ; ;Exit: ; Message printed ; Returns to word after end of token. ; GSWriteS_Translated ROUT Push "r0-r8,LR" MOV r4,#0 B Int_GSWriteS_Translated_UseR4 GSWriteS_Translated_UseR4 Push "r0-r8,LR" Int_GSWriteS_Translated_UseR4 MRS r8,CPSR MOV r1,LR LDR r2,=ZeroPage LDR r0,[r2,#KernelMessagesBlock] CMP r0,#0 ; If no messages file, try the global one. ADDNE r0,r2,#KernelMessagesBlock+4 LDR r2,=GeneralMOSBuffer MOV r3,#256 MOV r5,#0 MOV r6,#0 MOV r7,#0 ; No arguments. SWI XMessageTrans_GSLookup BVC %FT01 MOV R2,R1 ; MessageTrans not present or token not found. 00 LDRB r0,[r2],#1 ; Skip to after ":" CMP r0,#":" BNE %BT00 ; Now ; r1 -> terminator ; r2 -> message ; Print the message using OS_PrettyPrint. 01 LDR r0, =GeneralMOSBuffer MOV r1, #0 SWI XOS_PrettyPrint ; Now skip to end of token. 02 LDR r1,[sp,#9*4] ; Get original token pointer 03 LDRB r0,[r1],#1 CMP r0,#0 BNE %BT03 ; Skip to 0. ; r1 now points at byte after end of token. ADD r1,r1,#3 ; Round up to next word. BIC r1,r1,#3 STR r1,[sp,#9*4] ; Store back as return address on stack ORRVS r8,r8,#V_bit MSR CPSR_f,r8 Pull "r0-r8,PC" ;Return. ;---------------------------------------------------------------------------------------- ;FindToken ; ;Entry: ; R0 -> Token. ;*NOTE* ; MUST BE TOKEN:DEFAULT ; ;Exit: ; r0 -> Message, or after the : if MessageTrans is dead. ; ; FindToken ROUT Push "r0-r8,LR" MRS r8,CPSR MOV r1,r0 LDR r2,=ZeroPage LDR r0,[r2,#KernelMessagesBlock] CMP r0,#0 ; If no messages file, try the global one. ADDNE r0,r2,#KernelMessagesBlock+4 MOV r2,#0 MOV r3,#0 MOV r4,#0 MOV r5,#0 MOV r6,#0 MOV r7,#0 ; No arguments. SWI XMessageTrans_Lookup BVC %FT01 MOV R2,R1 ; MessageTrans not present or token not found. 00 LDRB r0,[r2],#1 ; Skip to after ":" CMP r0,#":" BNE %BT00 01 STR r2,[sp] MSR CPSR_f,r8 Pull "r0-r8,PC" ;---------------------------------------------------------------------------------------- ;Write0_Translated ; ;Entry: ; R0 -> Token. ;*NOTE* ; MUST BE TOKEN:DEFAULT ; ;Exit: ; Message printed, r0->Message. ; Write0_Translated ROUT EntryS "r0,r1" BL FindToken MOV R1,R0 01 LDRB R0,[R1],#1 CMP R0,#31 SWIGT XOS_WriteC STRVS r0,[SP] EXIT VS BGT %BT01 EXITS END