home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PSION CD 2
/
PsionCDVol2.iso
/
Programs
/
1156
/
Cryptanalysis.sis
(
.txt
)
next >
Wrap
EPOC Installation Package
|
2001-10-18
|
48KB
|
1,436 lines
E:\Psioncd2work\Psioncd2\Sistemp\crack.opl!:\PsionCD\Cryptanalysis\crack.oplE:\Psioncd2work\Psioncd2\Sistemp\Bis.txt!:\PsionCD\Cryptanalysis\Bis.txtCryptanalysis 45.7 kB7
REM This program was written by James L. Dean on February 1, 2000.
REM It implements the algorithm given by George W. Hart in the September
REM 1994 edition of the Communications of the ACM (Volume 37, Number 9).
REM Edgar Allan Poe used this method to crack simple substitution ciphers
REM around 1839; consider the following from pages 784-785 of David Kahn's The
REM Codebreakers:
REM The closest he ever came to doing so was when he
REM demonstrated how he deduced that a challenge sent him by
REM G. W. Kulp, of Lewiston, Pennsylvania, was a false
REM cryptogram. He picked out three words in the
REM cryptogram--MW, LAAM, and MLW. Since "all English words
REM of but two letters consist of a vowel and a consonant," he
REM wrote, MW must be one of 30 words, which he listed. He
REM then inserted every letter of the alphabet in the middle
REM of all 30 words in an exhaustive trial process to see
REM which letters would make a sensible word out of MLW. Here
REM he found 18, including ash and tho'. Turning to LAAM, he
REM observed, that "if MLW be ash, then LAAM will be a word of
REM this form, s..a, in which the dots represent two unknown
REM letters of the same kind." He ran through his 18 words in
REM this way, and found that the only one that gave a possible
REM meaning for LAAM was h..t, or hoot. "LAAM is then hoot or
REM nothing. But the hypothesis of the word hoot is founded
REM upon that of the word tho'.... We now arrive at a definite
REM conclusion. Either Mr. Kulp's puzzle is not genuine, or MW
REM stands for to, MLW for tho', and LAAM for hoot. But it is
REM evident that this latter cannot be--for in that case both
REM W and A represent the letter 0. What follows?--why that
REM Mr. Kulp's puzzle is no puzzle at all. This demonstration
REM is as absolutely conclusive as any mathematical one could
REM be. The process of reasoning here employed is that
REM employed also in the solution of the cyphers."
DECLARE EXTERNAL
INCLUDE "DATE.OXH"
EXTERNAL AddEncipheredWord&:(EncipheredWord$)
EXTERNAL AddPlaintext:(PatternHead&,Pattern&,Plaintext$)
EXTERNAL AddWordNotInWordList:(PatternPtr&)
EXTERNAL FreePattern:(PatternPtr&)
EXTERNAL GetCiphertext:
EXTERNAL GetCiphertextPatterns:
EXTERNAL GetEncipheredChar%:
EXTERNAL GetMaxDistinctLettersPerWord:(EncipheredHead&)
EXTERNAL GetPatternForPlaintextWord:(Pattern&)
EXTERNAL GetWordListChar%:
EXTERNAL GetWordListWord:(PreviousWord$)
EXTERNAL GetWordsMatchingPatterns:
EXTERNAL GoBackward:
EXTERNAL GoForward:(KeepOnlyTheBest%,EncipheredHead&,CiphertextHead&)
EXTERNAL IsLower%:(CurrentChar%)
EXTERNAL IsUpper%:(CurrentChar%)
EXTERNAL Main:
EXTERNAL Malloc&:(NumBytes%)
EXTERNAL OutputSolution:(EncipheredHead&,CiphertextHead&)
EXTERNAL PatternForEncipheredWord&:(EncipheredWord&,EncipheredWordLen%)
EXTERNAL PatternForWord&:(Word&,WordLen%)
EXTERNAL Solve:(NumDistinctWords&,EncipheredHead&,SortedHead&,KeepOnlyTheBest%,CiphertextHead&)
EXTERNAL Sort:
EXTERNAL StrCmp%:(Str1&,Str2&)
EXTERNAL StrICmp%:(Str1&,Str2&)
EXTERNAL ToLower%:(CurrentChar%)
EXTERNAL ToUpper%:(CurrentChar%)
CONST AlphabetSize%=27
CONST Apostrophe%=39
CONST Asterisk%=42
CONST EOF%=-1
CONST False%=0
CONST LowercaseA%=97
CONST LowercaseZ%=122
CONST Slash%=47
CONST True%=-1
CONST UppercaseA%=65
CONST UppercaseZ%=90
PROC Main:
GLOBAL Alphabetic%
GLOBAL CiphertextCharPtr&
GLOBAL CiphertextHead&
GLOBAL CiphertextPtr&
GLOBAL CiphertextTail&
GLOBAL EncipheredHead&
GLOBAL EncipheredPtrForMax&
GLOBAL EncipheredTail&
GLOBAL FatalError%
GLOBAL MaxDistinctLettersPerWord
GLOBAL NumDistinctWords&
GLOBAL PatternHead&
GLOBAL SortedHead&
GLOBAL Word$(255)
LOCAL ElapsedTime&
LOCAL EncipheredPtr1&
LOCAL KeepOnlyTheBest%
LOCAL NumChars%
LOCAL SortedPtr&
LOCAL StartTime&
LOCAL StopTime&
FatalError%=False%
ElapsedTime&=0
PRINT " Cryptanalysis of Simple Substitution Ciphers with Word Divisions"
PRINT
KeepOnlyTheBest%=False%
GetCiphertext:
IF NOT FatalError%
IF CiphertextHead& = 0
FatalError%=True%
PRINT "Fatal error: no ciphertext was entered."
ENDIF
ENDIF
IF NOT FatalError%
StartTime&=DTNow&:
GetCiphertextPatterns:
IF NOT FatalError%
IF PatternHead& = 0
FatalError%=True%
PRINT "Fatal error: the cipher text contains no words."
ENDIF
ENDIF
IF NOT FatalError%
GetWordsMatchingPatterns:
IF NOT FatalError%
GetMaxDistinctLettersPerWord:(EncipheredHead&)
IF MaxDistinctLettersPerWord <= 0.0
FatalError%=True%
PRINT "Fatal error: no word in the cipher text matched any pattern in the word list."
ENDIF
IF NOT FatalError%
SortedHead&=Malloc&:(20)
IF SortedHead& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
Sort:
IF NOT FatalError%
PRINT "Possible solutions (press a key to exit):"
Solve:(NumDistinctWords&,EncipheredHead&,SortedHead&,KeepOnlyTheBest%,CiphertextHead&)
StopTime&=DTNow&:
ElapsedTime&=DTSecsDiff&:(StartTime&,StopTime&)
ENDIF
WHILE SortedHead& <> 0
SortedPtr&=PEEKL(SortedHead&+16)
FREEALLOC SortedHead&
SortedHead&=SortedPtr&
ENDWH
ENDIF
ENDIF
ENDIF
ENDIF
FreePattern:(PatternHead&)
WHILE EncipheredHead& <> 0
EncipheredPtr1&=PEEKL(EncipheredHead&+12)
FREEALLOC PEEKL(EncipheredHead&)
FREEALLOC EncipheredHead&
EncipheredHead&=EncipheredPtr1&
ENDWH
ENDIF
WHILE CiphertextHead& <> 0
CiphertextPtr&=PEEKL(CiphertextHead&+4)
FREEALLOC PEEKL(CiphertextHead&)
FREEALLOC CiphertextHead&
CiphertextHead&=CiphertextPtr&
ENDWH
PRINT
IF ElapsedTime& > 0
PRINT "Elapsed time: ";
PRINT ElapsedTime&;
IF ElapsedTime& = 1
PRINT " second"
ELSE
PRINT " seconds"
ENDIF
ENDIF
PRINT "Press Enter to exit."
INPUT Word$
PROC GetCiphertext:
EXTERNAL CiphertextCharPtr&
EXTERNAL CiphertextHead&
EXTERNAL CiphertextPtr&
EXTERNAL CiphertextTail&
EXTERNAL FatalError%
LOCAL BytePtr&
LOCAL CiphertextCharNum%
LOCAL EncipheredText$(255)
LOCAL NumCiphertextChars%
PRINT "Enter enciphered text followed by a blank line."
PRINT
CiphertextHead&=0
CiphertextTail&=0
INPUT EncipheredText$
IF EncipheredText$ <> ""
CiphertextPtr&=Malloc&:(8)
IF CiphertextPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
CiphertextCharPtr&=Malloc&:(2+LEN(EncipheredText$))
IF CiphertextCharPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
FREEALLOC CiphertextPtr&
ELSE
BytePtr&=CiphertextCharPtr&
CiphertextCharNum%=1
NumCiphertextChars%=LEN(EncipheredText$)
WHILE CiphertextCharNum% <= NumCiphertextChars%
POKEB BytePtr&,ASC(MID$(EncipheredText$,CiphertextCharNum%,1))
BytePtr&=BytePtr&+1
CiphertextCharNum%=CiphertextCharNum%+1
ENDWH
POKEB BytePtr&,10
BytePtr&=BytePtr&+1
POKEB BytePtr&,0
POKEL CiphertextPtr&,CiphertextCharPtr&
POKEL CiphertextPtr&+4,0
IF CiphertextTail& = 0
CiphertextHead&=CiphertextPtr&
ELSE
POKEL CiphertextTail&+4,CiphertextPtr&
ENDIF
CiphertextTail&=CiphertextPtr&
ENDIF
ENDIF
ENDIF
UNTIL FatalError% OR (EncipheredText$ = "")
RETURN
PROC GetCiphertextPatterns:
EXTERNAL Alphabetic%
EXTERNAL CiphertextCharPtr&
EXTERNAL CiphertextHead&
EXTERNAL CiphertextPtr&
EXTERNAL CiphertextTail&
EXTERNAL EncipheredHead&
EXTERNAL EncipheredTail&
EXTERNAL FatalError%
EXTERNAL NumDistinctWords&
EXTERNAL PatternHead&
EXTERNAL Word$
LOCAL CurrentChar%
LOCAL EndOfFile%
LOCAL PatternPtr&
LOCAL WordLength%
PRINT "Getting patterns in enciphered text..."
NumDistinctWords&=0
EncipheredHead&=0
EncipheredTail&=0
PatternHead&=0
CiphertextPtr&=CiphertextHead&
CiphertextCharPtr&=PEEKL(CiphertextHead&)
EndOfFile%=False%
Alphabetic%=False%
WHILE (EndOfFile% = 0) AND (NOT Alphabetic%)
CurrentChar%=GetEncipheredChar%:
IF CurrentChar% = EOF%
EndOfFile%=True%
ELSE
IF CurrentChar% = Apostrophe%
Alphabetic%=True%
ELSE
CurrentChar%=ToLower%:(CurrentChar%)
IF IsLower%:(CurrentChar%)
Alphabetic%=True%
ENDIF
ENDIF
ENDIF
ENDWH
IF NOT EndOfFile%
Word$=""
WordLength%=0
DO
Word$=Word$+Chr$(CurrentChar%)
WordLength%=WordLength%+1
CurrentChar%=ToLower%:(GetEncipheredChar%:)
UNTIL (CurrentChar% = EOF%) OR (WordLength% >= 255) OR ((CurrentChar% <> Apostrophe%) AND (NOT IsLower%:(CurrentChar%)))
PatternPtr&=AddEncipheredWord&:(Word$)
IF (NOT FatalError%) AND (PEEKL(PatternPtr&+12) = 0)
AddWordNotInWordList:(PatternPtr&)
ENDIF
ENDIF
UNTIL FatalError% OR (CurrentChar% = EOF%)
RETURN
PROC GetWordsMatchingPatterns:
EXTERNAL Alphabetic%
EXTERNAL FatalError%
EXTERNAL PatternHead&
EXTERNAL Word$
GLOBAL CharNum%
GLOBAL LineNum&
GLOBAL WordList$(81,60)
LOCAL Pattern&
LOCAL PreviousWord$(255)
PRINT "Getting words matching the patterns..."
WordList$(1)="AA/BBLE/COUT/DVE/BCCORDING/EUNT/CROSS/CT/DION/EVITIES/HY/DUA"
WordList$(2)="LLY/BDDED/DITION/CMINISTRATION/BFTER/BGAIN/FST/CE/CO/BHEAD/B"
WordList$(3)="ID/CR/BLL/CMOST/CONE/EG/CREADY/CSO/CTHOUGH/CWAYS/BM/CERICA/H"
WordList$(4)="N/CONG/DUNT/BN/CALYSIS/CD/COTHER/CSWER/CTI/CY/DONE/DTHING/BP"
WordList$(5)="PARENTLY/DEAR/GED/DROACH/BRE/DA/ES/CMY/COUND/CT/BS/CK/DED/CS"
WordList$(6)="OCIATION/BT/CTACK/DENTION/BUDIENCE/BVAILABLE/CERAGE/BWAY/AB/"
WordList$(7)="BACK/CD/CLL/CSED/DIC/ES/BE/CAUTIFUL/CCAME/EUSE/DOME/CD/CEN/C"
WordList$(8)="FORE/CGAN/DINNING/CHIND/CING/CLIEVE/DOW/CST/CTTER/DWEEN/CYON"
WordList$(9)="D/BIG/CLL/BLACK/COOD/CUE/BOARD/CDY/COK/CRN/CTH/CY/DS/BRING/C"
WordList$(10)="OUGHT/DWN/BUILDING/ET/CSINESS/CT/BY/AC/BALL/EED/CME/CN/DNOT/"
WordList$(11)="CR/DE/DRIED/DS/CSE/ES/CUSE/BENT/EER/ERAL/EURY/CRTAIN/HLY/BHA"
WordList$(12)="NGE/DRACTER/CIEF/DLD/FREN/COICE/CRISTIAN/CURCH/BITY/BLASS/CE"
WordList$(13)="AR/FLY/COSE/FD/CUB/BO/CLD/DLEGE/DOR/CME/ES/DING/DMITTEE/EON/"
WordList$(14)="EUNIST/HTY/DPANY/ELETE/ILY/CNCERNED/DDITIONS/DGRESS/DSIDER/I"
WordList$(15)="ED/DTINUED/EROL/CRNER/DPS/CST/ES/CULD/FN[T/DNTRIES/GY/FY/DPL"
WordList$(16)="E/DRSE/ET/CVERED/BUT/AD/BAILY/CRK/CTA/CY/DS/BE/CAD/DL/DTH/CC"
WordList$(17)="IDED/ESION/CEP/CFENSE/CGREE/CMOCRATIC/CPARTMENT/CSCRIBED/DIG"
WordList$(18)="N/GED/CTERMINED/CVELOPED/HMENT/BID/DN[T/CFFERENCE/IT/EICULT/"
WordList$(19)="CRECT/GION/GLY/CSTANCE/ERICT/BO/CES/CING/CNE/D[T/COR/CUBT/CW"
WordList$(20)="N/BR/CIVE/BUE/CRING/AE/BACH/CRLIER/EY/DTH/CST/BCONOMIC/BDUCA"
WordList$(21)="TION/BFFECT/GIVE/GS/DORT/GS/BIGHT/CTHER/BLEMENTS/CSE/BND/CGL"
WordList$(22)="AND/EISH/COUGH/CTIRE/BQUIPMENT/BSPECIALLY/CTABLISHED/BUROPE/"
WordList$(23)="BVEN/EING/DR/EY/FTHING/CIDENCE/BXAMPLE/CCEPT/CISTENCE/CPECT/"
WordList$(24)="GED/ERIENCE/CTENT/BYE/DS/AF/BACE/DT/CITH/CLL/CMILY/CR/DM/CTH"
WordList$(25)="ER/BEAR/CDERAL/CED/DL/EING/DT/CLT/CW/BIELD/CGURE/GS/CLLED/CN"
WordList$(26)="AL/FLY/DD/DE/CRE/DM/DST/CSCAL/CVE/BLOOR/BOLLOWED/GING/COD/DT"
WordList$(27)="/CR/DCE/FS/DEIGN/DM/EER/ES/DWARD/CUND/DR/BREE/EDOM/DNCH/CIEN"
WordList$(28)="D/GS/COM/DNT/BULL/CNCTION/CRTHER/CTURE/AG/BAME/CVE/BENERAL/H"
WordList$(29)="LY/CORGE/CT/DTING/BIRL/ES/CVE/EN/ES/BLASS/BO/CD/CING/CNE/COD"
WordList$(30)="/CT/CVERNMENT/BREAT/FER/DEN/COUND/EP/FS/DWING/ETH/BUN/AH/BAD"
WordList$(31)="/CIR/CLF/DL/CND/ES/CPPENED/CRD/CS/CVE/DING/BE/CAD/DR/ED/ET/D"
WordList$(32)="VY/CLD/DL/DP/CR/DE/DSELF/C[S/BIGH/EER/CM/DSELF/CS/DTORY/CT/B"
WordList$(33)="OLD/CME/CPE/CRSE/CSPITAL/CT/DEL/CUR/ES/DSE/CW/DEVER/BUMAN/CN"
WordList$(34)="DRED/CSBAND/AI/BDEA/ES/BF/B[LL/CM/BMAGE/CMEDIATELY/CPORTANT/"
WordList$(35)="BN/CCLUDE/GING/DOME/DREASE/ID/CDEED/DIVIDUAL/DUSTRIAL/HY/CFL"
WordList$(36)="UENCE/DORMATION/CSIDE/DTEAD/CTEREST/FNATIONAL/DO/CVOLVED/BS/"
WordList$(37)="CLAND/CSUE/BT/CS/C[S/CSELF/B[VE/AJ/BOB/CHN/BUST/EICE/AKEEP/C"
WordList$(38)="NNEDY/CPT/BIND/BNEW/COW/ELEDGE/EN/AL/BABOR/CCK/CND/DGUAGE/CR"
WordList$(39)="GE/FR/CST/CTE/ER/DTER/CW/CY/BEAD/EERS/DRNED/DST/DVE/CD/CFT/C"
WordList$(40)="NGTH/CSS/CT/DTER/GS/CVEL/BIFE/CGHT/CKE/CNE/ES/CST/CTERATURE/"
WordList$(41)="DTLE/CVE/ED/DING/BOCAL/CNG/EER/COK/EED/EING/CST/CT/CVE/CW/DE"
WordList$(42)="R/AM/BADE/CIN/CJOR/CKE/ES/DING/CN/DNER/DS/DY/CRCH/DKET/DRIED"
WordList$(43)="/CSS/CTERIAL/DTER/CY/DBE/BE/CAN/EING/ES/CDICAL/CET/EING/CMBE"
WordList$(44)="R/GS/CN/CRELY/CT/DHOD/GS/BIDDLE/CGHT/CLES/DITARY/DLION/CND/D"
WordList$(45)="UTES/CSS/BODERN/CMENT/CNEY/DTH/FS/CRAL/DE/DNING/CST/CTHER/CV"
WordList$(46)="E/ED/EMENT/DING/BR/CS/BUCH/CSIC/DT/BY/CSELF/AN/BAME/CTION/GA"
WordList$(47)="L/GS/DURAL/FE/BEAR/ELY/CCESSARY/CED/EED/ES/CGRO/CITHER/CVER/"
WordList$(48)="CW/CXT/BIGHT/BO/CN/CR/DMAL/DTH/CT/DE/DHING/CW/BUCLEAR/CMBER/"
WordList$(49)="GS/AOBTAINED/CVIOUSLY/BF/CF/DICE/CTEN/BH/BLD/BN/CCE/CE/DS/D["
WordList$(50)="S/CLY/BPEN/EED/DRATION/CPORTUNITY/BR/CDER/CGANIZATION/BTHER/"
WordList$(51)="FS/BUR/CT/DSIDE/BVER/BWN/AP/BAID/CPER/CRT/EICULAR/KLY/ES/EY/"
WordList$(52)="CSSED/DT/CTTERN/CY/BEACE/COPLE/CR/DFORMANCE/DHAPS/DIOD/DSON/"
WordList$(53)="GAL/GS/BHYSICAL/BICTURE/CECE/BLACE/DN/EE/ENING/ES/ET/DY/BOIN"
WordList$(54)="T/FS/CLICE/FY/ETICAL/COL/DR/CPULATION/CSITION/DSIBLE/DT/CWER"
WordList$(55)="/BRESENT/EIDENT/ES/FURE/CICE/DNCIPLE/DVATE/COBABLY/ELEM/HS/D"
WordList$(56)="CESS/DDUCTION/HS/DGRAM/HS/FESS/DPERTY/DVIDE/HD/BUBLIC/CRPOSE"
WordList$(57)="/CT/AQUALITY/CESTION/IS/CITE/AR/BACE/CDIO/CN/DGE/CTE/DHER/BE"
WordList$(58)="ACHED/ETION/DD/EING/EY/DL/ELY/DSON/CCEIVED/ENT/GLY/DORD/CD/C"
WordList$(59)="LIGION/HUS/CMEMBER/CPORT/GED/CQUIRED/CSEARCH/DPECT/EONSIBILI"
WordList$(60)="TY/DT/DULT/GS/CTURN/GED/BIGHT/CVER/BOAD/COM/BUN/DNING/AS/BAI"
WordList$(61)="D/CLES/CME/CT/CW/CY/DING/DS/BCHOOL/GS/CIENCE/BEASON/CCOND/DR"
WordList$(62)="ETARY/DTION/CE/DM/EED/ES/DN/CLF/CNSE/DT/CRIES/EOUS/DVED/EICE"
WordList$(63)="/HS/CT/CVEN/ERAL/BHALL/CE/CORT/DT/DULD/DW/EED/EN/BIDE/CMILAR"
WordList$(64)="/DPLE/FY/CNCE/DGLE/CTUATION/CX/CZE/BLOWLY/BMALL/BO/CCIAL/EET"
WordList$(65)="Y/CME/ETHING/FIMES/EWHAT/CN/CON/CRT/CUND/DTH/FERN/CVIET/BPAC"
WordList$(66)="E/CEAK/DCIAL/FFIC/CIRIT/CRING/BQUARE/BT/CAFF/DGE/DND/FARD/DR"
WordList$(67)="T/FED/DTE/FMENTS/FS/DY/CEP/ES/CILL/COCK/DOD/DP/EPED/DRY/CRAI"
WordList$(68)="GHT/DEET/ENGTH/DONG/CUDENT/HS/EY/BUBJECT/CCH/CDDENLY/CMMER/C"
WordList$(69)="N/CPPORT/CRE/DFACE/BYSTEM/AT/BABLE/CKE/EN/DING/CLK/CX/BECHNI"
WordList$(70)="CAL/CLL/CMPERATURE/CN/CRM/ES/CST/BH/CAN/DT/ES/CE/DIR/DM/ESEL"
WordList$(71)="VES/DN/DORY/DRE/FFORE/F[S/DSE/DY/CING/FS/EK/FING/DRD/ETY/DS/"
WordList$(72)="COSE/DUGHT/CREE/DOUGH/HOUT/CUS/BIME/ES/BO/CDAY/CGETHER/CLD/C"
WordList$(73)="O/DK/CP/CTAL/CWARD/DN/BRADE/DINING/CIAL/DED/COUBLE/CUE/DTH/C"
WordList$(74)="Y/DING/BURN/EED/BWENTY/CO/BYPE/ES/AU/BNLIKELY/CDER/FSTAND/CI"
WordList$(75)="ON/DTED/DVERSITY/CTIL/BP/CON/BS/CE/DD/CING/CUALLY/AVALUE/FS/"
WordList$(76)="CRIOUS/BERY/BIEW/BOICE/CLUME/AWAITING/CLKED/DL/CNT/EED/CR/CS"
WordList$(77)="/DHINGTON/DN[T/CTER/CY/DS/BE/CEK/ES/CLL/CNT/CRE/CST/EERN/BHA"
WordList$(78)="T/EEVER/CEN/DRE/DTHER/CICH/DLE/DTE/CO/DLE/DM/DSE/CY/BIDE/CFE"
WordList$(79)="/CLL/EIAM/CNDOW/CSH/CTH/EIN/EOUT/BOMAN/DEN/CRD/ES/DK/EED/EIN"
WordList$(80)="G/ES/DLD/CULD/FN[T/BRITTEN/CONG/DTE/AYEAR/ES/CS/CT/BORK/CU/D"
WordList$(81)="NG/DR/D[RE/!"
LineNum&=1
CharNum%=1
PreviousWord$=""
Pattern&=Malloc&:(256)
IF Pattern& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
DO
GetWordListWord:(PreviousWord$)
IF (NOT FatalError%) AND (Word$ <> "")
PreviousWord$=Word$
GetPatternForPlaintextWord:(Pattern&)
IF (Alphabetic%)
AddPlaintext:(PatternHead&,Pattern&,Word$)
ENDIF
ENDIF
UNTIL FatalError% OR (Word$ = "")
FREEALLOC Pattern&
ENDIF
RETURN
PROC GetMaxDistinctLettersPerWord:(EncipheredHead&)
EXTERNAL EncipheredPtrForMax&
EXTERNAL MaxDistinctLettersPerWord
EXTERNAL NumDistinctWords&
LOCAL EncipheredPtr1&
LOCAL NumDistinctLettersPerWord
LOCAL PatternPtr&
LOCAL PlaintextCount&
MaxDistinctLettersPerWord=0.0
EncipheredPtr1&=EncipheredHead&
WHILE EncipheredPtr1& <> 0
PatternPtr&=PEEKL(EncipheredPtr1&+4)
PlaintextCount&=PEEKL(PatternPtr&+8)
IF PlaintextCount& <> 0
NumDistinctLettersPerWord=FLT(PEEKL(PatternPtr&))/FLT(PlaintextCount&)
IF NumDistinctLettersPerWord > MaxDistinctLettersPerWord
MaxDistinctLettersPerWord=NumDistinctLettersPerWord
EncipheredPtrForMax&=EncipheredPtr1&
ENDIF
ENDIF
EncipheredPtr1&=PEEKL(EncipheredPtr1&+12)
ENDWH
RETURN
PROC Sort:
EXTERNAL CiphertextCharPtr&
EXTERNAL EncipheredHead&
EXTERNAL EncipheredPtrForMax&
EXTERNAL FatalError%
EXTERNAL NumDistinctWords&
EXTERNAL SortedHead&
LOCAL CipherTextChar%
LOCAL DuplicateWord%
LOCAL EncipheredPtr1&
LOCAL EncipheredPtr2&
LOCAL LetterNum%
LOCAL LetterUsed%(27)
LOCAL MaxMatchingLetters%
LOCAL NumMatchingLetters%
LOCAL PatternPtr&
LOCAL SortedPtr&
LOCAL SortedTail&
POKEL EncipheredPtrForMax&+8,SortedHead&
POKEL SortedHead&,PEEKL(EncipheredPtrForMax&)
PatternPtr&=PEEKL(EncipheredPtrForMax&+4)
POKEL SortedHead&+4,PatternPtr&
POKEL SortedHead&+8,PEEKL(PatternPtr&+12)
POKEL SortedHead&+12,0
POKEL SortedHead&+16,0
SortedTail&=SortedHead&
LetterNum%=1
WHILE LetterNum% <= AlphabetSize%
LetterUsed%(LetterNum%)=False%
LetterNum%=LetterNum%+1
ENDWH
CiphertextCharPtr&=PEEKL(EncipheredPtrForMax&)
CiphertextChar%=PEEKB(CiphertextCharPtr&)
WHILE CiphertextChar% <> 0
IF CiphertextChar% <> Apostrophe%
LetterUsed%((ToLower%:(CiphertextChar%)-LowercaseA%)+1)=True%
ENDIF
CiphertextCharPtr&=CiphertextCharPtr&+1
CiphertextChar%=PEEKB(CiphertextCharPtr&)
ENDWH
EncipheredPtr1&=PEEKL(EncipheredHead&+12)
WHILE (NOT FatalError%) AND (EncipheredPtr1& <> 0)
MaxMatchingLetters%=0
EncipheredPtrForMax&=0
EncipheredPtr2&=EncipheredHead&
WHILE EncipheredPtr2& <> 0
IF PEEKL(EncipheredPtr2&+8) = 0
NumMatchingLetters%=0
CiphertextCharPtr&=PEEKL(EncipheredPtr2&)
WHILE PEEKB(CiphertextCharPtr&) <> 0
IF PEEKB(CiphertextCharPtr&) <> Apostrophe%
IF LetterUsed%((ToLower%:(PEEKB(CiphertextCharPtr&))-LowercaseA%)+1)
NumMatchingLetters%=NumMatchingLetters%+1
ENDIF
ENDIF
CiphertextCharPtr&=CiphertextCharPtr&+1
ENDWH
IF NumMatchingLetters% >= MaxMatchingLetters%
MaxMatchingLetters%=NumMatchingLetters%
EncipheredPtrForMax&=EncipheredPtr2&
ENDIF
ENDIF
EncipheredPtr2&=PEEKL(EncipheredPtr2&+12)
ENDWH
DuplicateWord%=False%
EncipheredPtr2&=EncipheredHead&
WHILE (NOT DuplicateWord%) AND (EncipheredPtr2& <> 0)
IF PEEKL(EncipheredPtr2&+8)
IF StrICmp%:(PEEKL(EncipheredPtr2&),PEEKL(EncipheredPtrForMax&)) <> 0
EncipheredPtr2&=PEEKL(EncipheredPtr2&+12)
ELSE
DuplicateWord%=True%
ENDIF
ELSE
EncipheredPtr2&=PEEKL(EncipheredPtr2&+12)
ENDIF
ENDWH
IF DuplicateWord%
POKEL EncipheredPtrForMax&+8,PEEKL(EncipheredPtr2&+8)
ELSE
SortedPtr&=Malloc&:(20)
IF SortedPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
NumDistinctWords&=NumDistinctWords&+1
POKEL EncipheredPtrForMax&+8,SortedPtr&
POKEL SortedPtr&,PEEKL(EncipheredPtrForMax&)
PatternPtr&=PEEKL(EncipheredPtrForMax&+4)
POKEL SortedPtr&+4,PatternPtr&
POKEL SortedPtr&+8,PEEKL(PatternPtr&+12)
POKEL SortedTail&+16,SortedPtr&
POKEL SortedPtr&+12,SortedTail&
POKEL SortedPtr&+16,0
SortedTail&=SortedPtr&
CiphertextCharPtr&=PEEKL(EncipheredPtrForMax&)
CiphertextChar%=PEEKB(CiphertextCharPtr&)
WHILE CiphertextChar% <> 0
IF CiphertextChar% <> Apostrophe%
LetterUsed%((ToLower%:(CiphertextChar%)-LowercaseA%)+1)=True%
ENDIF
CiphertextCharPtr&=CiphertextCharPtr&+1
CiphertextChar%=PEEKB(CiphertextCharPtr&)
ENDWH
ENDIF
ENDIF
EncipheredPtr1&=PEEKL(EncipheredPtr1&+12)
ENDWH
RETURN
PROC GetEncipheredChar%:
EXTERNAL CiphertextCharPtr&
EXTERNAL CiphertextPtr&
LOCAL EncipheredChar%
IF CiphertextPtr& = 0
EncipheredChar%=EOF%
ELSE
EncipheredChar%=PEEKB(CiphertextCharPtr&)
CiphertextCharPtr&=CiphertextCharPtr&+1
IF PEEKB(CiphertextCharPtr&) = 0
CiphertextPtr&=PEEKL(CiphertextPtr&+4)
IF CiphertextPtr& <> 0
CiphertextCharPtr&=PEEKL(CiphertextPtr&)
ENDIF
ENDIF
ENDIF
RETURN EncipheredChar%
PROC StrICmp%:(Str1&,Str2&)
LOCAL CharPtr1&
LOCAL CharPtr2&
LOCAL Char1%
LOCAL Char2%
LOCAL Result%
Result%=0
CharPtr1&=Str1&
CharPtr2&=Str2&
Char1%=PEEKB(CharPtr1&)
Char2%=PEEKB(CharPtr2&)
WHILE (Result% = 0) AND (Char1% <> 0)
Result%=Char1%-Char2%
IF Result% = 0
CharPtr1&=CharPtr1&+1
Char1%=PEEKB(CharPtr1&)
CharPtr2&=CharPtr2&+1
Char2%=PEEKB(CharPtr2&)
ENDIF
ENDWH
RETURN Result%
PROC Solve:(NumDistinctWords&,EncipheredHead&,SortedHead&,KeepOnlyTheBest%,CiphertextHead&)
EXTERNAL CiphertextCharPtr&
EXTERNAL CiphertextPtr&
EXTERNAL FatalError%
GLOBAL Contradiction%
GLOBAL Decipherment$(27,1)
GLOBAL DeciphermentCount&(27)
GLOBAL Encipherment$(27,1)
GLOBAL EnciphermentCount&(27)
GLOBAL KeyPressed%
GLOBAL MaxScore&
GLOBAL NumPossibleSolutions&
GLOBAL Score&
GLOBAL SortedPtr&
GLOBAL WordNum&
LOCAL Borrow%
LOCAL CharPtr1&
LOCAL CharPtr2&
LOCAL CurrentChar%
LOCAL DecipheredChar$(1)
LOCAL DecipheredIndex%
LOCAL EncipheredChar%
LOCAL EncipheredIndex%
NumPossibleSolutions&=0
CurrentChar%=1
WHILE CurrentChar% <= AlphabetSize%
Decipherment$(CurrentChar%)=""
DeciphermentCount&(CurrentChar%)=0
Encipherment$(CurrentChar%)=""
EnciphermentCount&(CurrentChar%)=0
CurrentChar%=CurrentChar%+1
ENDWH
Score&=0
MaxScore&=0
SortedPtr&=SortedHead&
WordNum&=0
KeyPressed%=False%
WHILE (SortedPtr& <> 0) AND (NOT KeyPressed%)
CharPtr1&=PEEKL(PEEKL(SortedPtr&+8))
IF PEEKB(CharPtr1&) <> 0
Score&=Score&+1
ENDIF
WordNum&=WordNum&+1
Contradiction%=False%
IF PEEKB(CharPtr1&) <> 0
REM Word in dictionary
CharPtr2&=PEEKL(SortedPtr&)
WHILE (NOT Contradiction%) AND (PEEKB(CharPtr2&) <> 0)
IF PEEKB(CharPtr1&) <> Apostrophe%
DecipheredChar$=CHR$(ToLower%:(PEEKB(CharPtr1&)))
EncipheredChar%=ToLower%:(PEEKB(CharPtr2&))
EncipheredIndex%=(EncipheredChar%-LowercaseA%)+1
IF DeciphermentCount&(EncipheredIndex%) <> 0
IF Decipherment$(EncipheredIndex%) = DecipheredChar$
DeciphermentCount&(EncipheredIndex%)=DeciphermentCount&(EncipheredIndex%)+1
ELSE
Contradiction%=True%
ENDIF
ELSE
Decipherment$(EncipheredIndex%)=DecipheredChar$
DeciphermentCount&(EncipheredIndex%)=1
ENDIF
DecipheredIndex%=(ASC(DecipheredChar$)-LowercaseA%)+1
IF EnciphermentCount&(DecipheredIndex%) <> 0
IF ASC(Encipherment$(DecipheredIndex%)) = EncipheredChar%
EnciphermentCount&(DecipheredIndex%)=EnciphermentCount&(DecipheredIndex%)+1
ELSE
Contradiction%=True%
ENDIF
ELSE
Encipherment$(DecipheredIndex%)=CHR$(EncipheredChar%)
EnciphermentCount&(DecipheredIndex%)=1
ENDIF
ENDIF
CharPtr1&=CharPtr1&+1
CharPtr2&=CharPtr2&+1
ENDWH
ELSE
REM Word not in dictionary
IF Score&+NumDistinctWords&-WordNum& < MaxScore&
Contradiction%=True%
ENDIF
ENDIF
IF Contradiction%
GoBackward:
ELSE
GoForward:(KeepOnlyTheBest%,EncipheredHead&,CiphertextHead&)
ENDIF
IF NOT KeyPressed%
IF KEY
KeyPressed%=True%
ENDIF
ENDIF
ENDWH
IF NOT FatalError%
IF NumPossibleSolutions& = 0
PRINT "No solutions were found."
ENDIF
ENDIF
RETURN
PROC GoForward:(KeepOnlyTheBest%,EncipheredHead&,CiphertextHead&)
EXTERNAL CiphertextCharPtr&
EXTERNAL CiphertextPtr&
EXTERNAL Contradiction%
EXTERNAL Decipherment$()
EXTERNAL DeciphermentCount&()
EXTERNAL Encipherment$()
EXTERNAL EnciphermentCount&()
EXTERNAL KeyPressed%
EXTERNAL MaxScore&
EXTERNAL NumPossibleSolutions&
EXTERNAL Score&
EXTERNAL SortedPtr&
EXTERNAL WordNum&
LOCAL Borrow%
LOCAL CharPtr1&
LOCAL CharPtr2&
LOCAL Count&
LOCAL DecipheredChar$(1)
LOCAL DecipheredIndex%
LOCAL EncipheredChar%
LOCAL EncipheredIndex%
IF PEEKL(SortedPtr&+16) <> 0
SortedPtr&=PEEKL(SortedPtr&+16)
ELSE
IF Score& > MaxScore&
MaxScore&=Score&
IF KeepOnlyTheBest%
REM Delete previous solutions from display.
NumPossibleSolutions&=0
ENDIF
ENDIF
OutputSolution:(EncipheredHead&,CiphertextHead&)
IF PEEKB(PEEKL(PEEKL(SortedPtr&+8))) <> 0
Score&=Score&-1
ENDIF
WordNum&=WordNum&-1
Borrow%=True%
WHILE Borrow% AND (SortedPtr& <> 0) AND (NOT KeyPressed%)
CharPtr1&=PEEKL(PEEKL(SortedPtr&+8))
IF PEEKB(CharPtr1&) <> 0
Contradiction%=False%
CharPtr2&=PEEKL(SortedPtr&)
WHILE (NOT Contradiction%) AND (PEEKB(CharPtr2&) <> 0)
IF PEEKB(CharPtr1&) <> Apostrophe%
DecipheredChar$=CHR$(ToLower%:(PEEKB(CharPtr1&)))
EncipheredChar%=ToLower%:(PEEKB(CharPtr2&))
EncipheredIndex%=(EncipheredChar%-LowercaseA%)+1
IF Decipherment$(EncipheredIndex%) = DecipheredChar$
Count&=DeciphermentCount&(EncipheredIndex%)-1
DeciphermentCount&(EncipheredIndex%)=Count&
IF Count& = 0
Decipherment$(EncipheredIndex%)=""
ENDIF
ELSE
Contradiction%=True%
ENDIF
DecipheredIndex%=(ASC(DecipheredChar$)-LowercaseA%)+1
IF ASC(Encipherment$(DecipheredIndex%)) = EncipheredChar%
Count&=EnciphermentCount&(DecipheredIndex%)-1
EnciphermentCount&(DecipheredIndex%)=Count&
IF Count& = 0
Encipherment$(DecipheredIndex%)=""
ENDIF
ELSE
Contradiction%=True%
ENDIF
ENDIF
CharPtr1&=CharPtr1&+1
CharPtr2&=CharPtr2&+1
ENDWH
ENDIF
POKEL SortedPtr&+8,PEEKL(PEEKL(SortedPtr&+8)+4)
IF PEEKL(SortedPtr&+8) <> 0
Borrow%=False%
ELSE
POKEL SortedPtr&+8,PEEKL(PEEKL(SortedPtr&+4)+12)
SortedPtr&=PEEKL(SortedPtr&+12)
IF SortedPtr& <> 0
IF PEEKB(PEEKL(PEEKL(SortedPtr&+8))) <> 0
Score&=Score&-1
ENDIF
ENDIF
WordNum&=WordNum&-1
ENDIF
IF KEY
KeyPressed%=True%
ENDIF
ENDWH
ENDIF
RETURN
PROC GoBackward:
EXTERNAL Contradiction%
EXTERNAL Decipherment$()
EXTERNAL DeciphermentCount&()
EXTERNAL Encipherment$()
EXTERNAL EnciphermentCount&()
EXTERNAL KeyPressed%
EXTERNAL Score&
EXTERNAL SortedPtr&
EXTERNAL WordNum&
LOCAL Borrow%
LOCAL CharPtr1&
LOCAL CharPtr2&
LOCAL Count&
LOCAL DecipheredChar$(1)
LOCAL DecipheredIndex%
LOCAL EncipheredChar%
LOCAL EncipheredIndex%
IF PEEKB(PEEKL(PEEKL(SortedPtr&+8))) <> 0
Score&=Score&-1
ENDIF
WordNum&=WordNum&-1
Borrow%=True%
WHILE Borrow% AND (SortedPtr& <> 0) AND (NOT KeyPressed%)
CharPtr1&=PEEKL(PEEKL(SortedPtr&+8))
IF PEEKB(CharPtr1&) <> 0
Contradiction%=False%
CharPtr2&=PEEKL(SortedPtr&)
WHILE (NOT Contradiction%) AND (PEEKB(CharPtr2&) <> 0)
IF PEEKB(CharPtr1&) <> Apostrophe%
DecipheredChar$=CHR$(Tolower%:(PEEKB(CharPtr1&)))
EncipheredChar%=ToLower%:(PEEKB(CharPtr2&))
EncipheredIndex%=(EncipheredChar%-LowercaseA%)+1
IF Decipherment$(EncipheredIndex%) = DecipheredChar$
Count&=DeciphermentCount&(EncipheredIndex%)-1
DeciphermentCount&(EncipheredIndex%)=Count&
IF Count& = 0
Decipherment$(EncipheredIndex%)=""
ENDIF
ELSE
Contradiction%=True%
ENDIF
DecipheredIndex%=(ASC(DecipheredChar$)-LowercaseA%)+1
IF ASC(Encipherment$(DecipheredIndex%)) = EncipheredChar%
Count&=EnciphermentCount&(DecipheredIndex%)-1
EnciphermentCount&(DecipheredIndex%)=Count&
IF Count& = 0
Encipherment$(DecipheredIndex%)=""
ENDIF
ELSE
Contradiction%=True%
ENDIF
ENDIF
CharPtr1&=CharPtr1&+1
CharPtr2&=CharPtr2&+1
ENDWH
ENDIF
POKEL SortedPtr&+8,PEEKL(PEEKL(SortedPtr&+8)+4)
IF PEEKL(SortedPtr&+8) <> 0
Borrow%=False%
ELSE
POKEL SortedPtr&+8,PEEKL(PEEKL(SortedPtr&+4)+12)
SortedPtr&=PEEKL(SortedPtr&+12)
IF SortedPtr& <> 0
IF PEEKB(PEEKL(PEEKL(SortedPtr&+8))) <> 0
Score&=Score&-1
ENDIF
ENDIF
WordNum&=WordNum&-1
ENDIF
IF KEY
KeyPressed%=True%
ENDIF
ENDWH
RETURN
PROC OutputSolution:(EncipheredHead&,CiphertextHead&)
EXTERNAL CiphertextCharPtr&
EXTERNAL CiphertextPtr&
EXTERNAL Decipherment$()
EXTERNAL DeciphermentCount&()
EXTERNAL NumPossibleSolutions&
LOCAL CurrentChar%
LOCAL EncipheredIndex%
LOCAL EncipheredPtr&
LOCAL EndOfFile%
LOCAL Letter%
LOCAL PlaintextChar%
LOCAL PlaintextCharPtr&
CiphertextPtr&=CiphertextHead&
CiphertextCharPtr&=PEEKL(CiphertextHead&)
NumPossibleSolutions&=NumPossibleSolutions&+1
EncipheredPtr&=EncipheredHead&
PRINT
EndOfFile%=False%
Letter%=False%
WHILE (NOT EndOfFile%) AND (NOT Letter%)
CurrentChar%=GetEncipheredChar%:
IF CurrentChar% = EOF%
EndOfFile%=True%
ELSE
IF CurrentChar% = Apostrophe%
Letter%=True%
ELSE
IF IsLower%:(CurrentChar%)
Letter%=True%
ELSE
IF IsUpper%:(CurrentChar%)
Letter%=True%
ELSE
IF CurrentChar% = 10
PRINT
ELSE
PRINT CHR$(CurrentChar%);
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDWH
IF CurrentChar% <> EOF%
PlaintextCharPtr&=PEEKL(PEEKL(PEEKL(EncipheredPtr&+8)+8))
PlaintextChar%=PEEKB(PlaintextCharPtr&)
IF PlaintextChar% <> 0
DO
IF CurrentChar% = Apostrophe%
PRINT "'";
ELSE
IF IsLower%:(CurrentChar%)
CurrentChar%=ToLower%:(PlaintextChar%)
ELSE
CurrentChar%=ToUpper%:(PlaintextChar%)
ENDIF
PRINT CHR$(CurrentChar%);
ENDIF
PlaintextCharPtr&=PlaintextCharPtr&+1
PlaintextChar%=PEEKB(PlaintextCharPtr&)
CurrentChar%=GetEncipheredChar%:
UNTIL (CurrentChar% = EOF%) OR ((CurrentChar% <> Apostrophe%) AND (NOT IsLower%:(ToLower%:(CurrentChar%))))
ELSE
DO
IF CurrentChar% = Apostrophe%
PRINT CHR$(CurrentChar%);
ELSE
IF IsLower%:(CurrentChar%)
EncipheredIndex%=(CurrentChar%-LowercaseA%)+1
IF DeciphermentCount&(EncipheredIndex%) <> 0
CurrentChar%=ToLower%:(ASC(Decipherment$(EncipheredIndex%)))
ELSE
CurrentChar%=Asterisk%
ENDIF
PRINT CHR$(CurrentChar%);
ELSE
IF IsUpper%:(CurrentChar%)
EncipheredIndex%=(CurrentChar%-UppercaseA%)+1
IF DeciphermentCount&(EncipheredIndex%) <> 0
CurrentChar%=ToUpper%:(ASC(Decipherment$(EncipheredIndex%)))
ELSE
CurrentChar%=Asterisk%
ENDIF
PRINT CHR$(CurrentChar%);
ELSE
CurrentChar%=ToUpper%:(PEEKB(PlaintextCharPtr&))
PRINT CHR$(CurrentChar%);
ENDIF
ENDIF
ENDIF
CurrentChar%=GetEncipheredChar%:
UNTIL (CurrentChar% = EOF%) OR ((CurrentChar% <> Apostrophe%) AND (NOT IsLower%:(ToLower%:(CurrentChar%))))
ENDIF
IF CurrentChar% <> EOF%
IF CurrentChar% = 10
PRINT
ELSE
PRINT CHR$(CurrentChar%);
ENDIF
ENDIF
EncipheredPtr&=PEEKL(EncipheredPtr&+12)
ENDIF
UNTIL CurrentChar% = EOF%
RETURN
PROC AddWordNotInWordList:(PatternPtr&)
EXTERNAL FatalError%
LOCAL Plaintext&
LOCAL PlaintextPtr&
PlaintextPtr&=Malloc&:(8)
IF PlaintextPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
Plaintext&=Malloc&:(1)
IF Plaintext& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
POKEB Plaintext&,0
POKEL PlaintextPtr&,Plaintext&
POKEL PlaintextPtr&+4,0
POKEL PatternPtr&+12,PlaintextPtr&
ENDIF
ENDIF
RETURN
PROC AddPlaintext:(PatternHead&,Pattern&,Plaintext$)
EXTERNAL FatalError%
LOCAL BytePtr&
LOCAL Finished%
LOCAL GreaterPtr&
LOCAL InternalPtr&
LOCAL LesserPtr&
LOCAL NumPlaintextChars%
LOCAL Plaintext2&
LOCAL PlaintextCharNum%
LOCAL PlaintextPtr&
LOCAL Relation%
InternalPtr&=PatternHead&
Finished%=False%
WHILE NOT Finished%
Relation%=StrCmp%:(Pattern&,PEEKL(InternalPtr&+4))
IF Relation% < 0
LesserPtr&=PEEKL(InternalPtr&+16)
IF LesserPtr& <> 0
InternalPtr&=LesserPtr&
ELSE
Finished%=True%
ENDIF
ELSE
IF Relation% > 0
GreaterPtr&=PEEKL(InternalPtr&+20)
IF GreaterPtr& <> 0
InternalPtr&=GreaterPtr&
ELSE
Finished%=True%
ENDIF
ELSE
PlaintextPtr&=Malloc&:(8)
IF PlaintextPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
NumPlaintextChars%=LEN(Plaintext$)
Plaintext2&=Malloc&:(1+NumPlaintextChars%)
IF Plaintext2& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
FREEALLOC PlaintextPtr&
ELSE
BytePtr&=Plaintext2&
PlaintextCharNum%=1
WHILE PlaintextCharNum% <= NumPlaintextChars%
POKEB BytePtr&,ASC(MID$(Plaintext$,PlaintextCharNum%,1))
BytePtr&=BytePtr&+1
PlaintextCharNum%=PlaintextCharNum%+1
ENDWH
POKEB BytePtr&,0
POKEL PlaintextPtr&,Plaintext2&
POKEL InternalPtr&+8,PEEKL(InternalPtr&+8)+1
POKEL PlaintextPtr&+4,PEEKL(InternalPtr&+12)
POKEL InternalPtr&+12,PlaintextPtr&
ENDIF
ENDIF
Finished%=True%
ENDIF
ENDIF
ENDWH
RETURN
PROC GetPatternForPlaintextWord:(PatternPtr&)
EXTERNAL Word$
EXTERNAL Alphabetic%
LOCAL CharNum1%
LOCAL CharPtr2&
LOCAL CharNum3%
LOCAL CharPtr4&
LOCAL CharValue%
LOCAL CurrentChar$(1)
LOCAL LowercaseWord$(255)
LOCAL NumChars%
LOCAL NumDistinctChars%
Alphabetic%=True%
CharNum1%=1
NumChars%=LEN(Word$)
CharPtr2&=PatternPtr&
LowercaseWord$=""
WHILE Alphabetic% AND (CharNum1% <= NumChars%)
CurrentChar$=MID$(Word$,CharNum1%,1)
IF CurrentChar$ = "'"
LowercaseWord$=LowercaseWord$+"'"
ELSE
CharValue%=ToLower%:(ASC(CurrentChar$))
LowercaseWord$=LowercaseWord$+CHR$(CharValue%)
Alphabetic%=IsLower%:(CharValue%)
ENDIF
POKEB CharPtr2&,0
CharPtr2&=CharPtr2&+1
CharNum1%=CharNum1%+1
ENDWH
IF Alphabetic%
POKEB CharPtr2&,0
NumDistinctChars%=0
CharNum1%=1
CharPtr2&=PatternPtr&
WHILE CharNum1% <= NumChars%
IF PEEKB(CharPtr2&) = 0
CurrentChar$=MID$(Word$,CharNum1%,1)
IF CurrentChar$ = "'"
POKEB CharPtr2&,AlphabetSize%
ELSE
NumDistinctChars%=NumDistinctChars%+1
POKEB CharPtr2&,NumDistinctChars%
CharNum3%=CharNum1%+1
CharPtr4&=CharPtr2&+1
WHILE CharNum3% <= NumChars%
IF MID$(Word$,CharNum3%,1) = CurrentChar$
POKEB CharPtr4&,NumDistinctChars%
ENDIF
CharPtr4&=CharPtr4&+1
CharNum3%=CharNum3%+1
ENDWH
ENDIF
ENDIF
CharPtr2&=CharPtr2&+1
CharNum1%=CharNum1%+1
ENDWH
ENDIF
RETURN
PROC FreePattern:(PatternPtr&)
LOCAL PlaintextHead&
LOCAL PlaintextPtr&
IF PatternPtr& <> 0
FreePattern:(PEEKL(PatternPtr&+16))
FreePattern:(PEEKL(PatternPtr&+20))
FREEALLOC PEEKL(PatternPtr&+4)
PlaintextHead&=PEEKL(PatternPtr&+12)
WHILE PlaintextHead& <> 0
PlaintextPtr&=PEEKL(PlaintextHead&+4)
FREEALLOC PEEKL(PlaintextHead&)
FREEALLOC PlaintextHead&
PlaintextHead&=PlaintextPtr&
ENDWH
FREEALLOC PatternPtr&
ENDIF
RETURN
PROC PatternForWord&:(Word&,WordLen%)
EXTERNAL FatalError%
EXTERNAL NumDistinctLetters&
LOCAL CharPtr1&
LOCAL CharPtr2&
LOCAL CharPtr3&
LOCAL CharPtr4&
LOCAL Char1%
LOCAL Char3%
LOCAL NumDistinctChars&
LOCAL Pattern&
Pattern&=Malloc&:(1+WordLen%)
IF Pattern& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
NumDistinctLetters&=0
ELSE
CharPtr1&=Word&
CharPtr2&=Pattern&
WHILE PEEKB(CharPtr1&) <> 0
POKEB CharPtr2&,0
CharPtr2&=CharPtr2&+1
CharPtr1&=CharPtr1&+1
ENDWH
POKEB CharPtr2&,0
NumDistinctChars&=0
CharPtr1&=Word&
CharPtr2&=Pattern&
Char1%=PEEKB(CharPtr1&)
WHILE Char1% <> 0
IF PEEKB(CharPtr2&) = 0
IF Char1% = Apostrophe%
POKEB CharPtr2&,AlphabetSize%
ELSE
NumDistinctChars&=NumDistinctChars&+1
POKEB CharPtr2&,NumDistinctChars&
CharPtr3&=CharPtr1&+1
Char3%=PEEKB(CharPtr3&)
CharPtr4&=CharPtr2&+1
WHILE Char3% <> 0
IF Char3% = Char1%
POKEB CharPtr4&,NumDistinctChars&
ENDIF
CharPtr4&=CharPtr4&+1
CharPtr3&=CharPtr3&+1
Char3%=PEEKB(CharPtr3&)
ENDWH
ENDIF
ENDIF
CharPtr2&=CharPtr2&+1
CharPtr1&=CharPtr1&+1
Char1%=PEEKB(CharPtr1&)
ENDWH
NumDistinctLetters&=NumDistinctChars&
ENDIF
RETURN Pattern&
PROC StrCmp%:(Str1&,Str2&)
LOCAL CharPtr1&
LOCAL CharPtr2&
LOCAL Char1%
LOCAL Char2%
LOCAL Result%
Result%=0
CharPtr1&=Str1&
CharPtr2&=Str2&
Char1%=PEEKB(CharPtr1&)
Char2%=PEEKB(CharPtr2&)
WHILE (Result% = 0) AND (Char1% <> 0) AND (Char2% <> 0)
Result%=Char1%-Char2%
CharPtr1&=CharPtr1&+1
Char1%=PEEKB(CharPtr1&)
CharPtr2&=CharPtr2&+1
Char2%=PEEKB(CharPtr2&)
ENDWH
IF Result% = 0
Result%=Char1%-Char2%
ENDIF
RETURN Result%
PROC PatternForEncipheredWord&:(EncipheredWord&,EncipheredWordLen%)
EXTERNAL FatalError%
EXTERNAL PatternHead&
GLOBAL NumDistinctLetters&
LOCAL ExternalPtr&
LOCAL Finished%
LOCAL GreaterPtr&
LOCAL InternalPtr&
LOCAL LesserPtr&
LOCAL Relation%
LOCAL Pattern&
InternalPtr&=0
Pattern&=PatternForWord&:(EncipheredWord&,EncipheredWordLen%)
IF (NOT FatalError%)
IF (PatternHead&)
InternalPtr&=PatternHead&
Finished%=False%
DO
Relation%=StrCmp%:(Pattern&,PEEKL(InternalPtr&+4))
IF Relation% < 0
LesserPtr&=PEEKL(InternalPtr&+16)
IF LesserPtr& <> 0
InternalPtr&=LesserPtr&
ELSE
ExternalPtr&=Malloc&:(24)
IF ExternalPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
POKEL ExternalPtr&+4,Pattern&
POKEL ExternalPtr&,NumDistinctLetters&
POKEL ExternalPtr&+8,0
POKEL ExternalPtr&+12,0
POKEL ExternalPtr&+16,0
POKEL ExternalPtr&+20,0
POKEL InternalPtr&+16,ExternalPtr&
ENDIF
InternalPtr&=ExternalPtr&
Finished%=True%
ENDIF
ELSE
IF Relation% > 0
GreaterPtr&=PEEKL(InternalPtr&+20)
IF GreaterPtr& <> 0
InternalPtr&=GreaterPtr&
ELSE
ExternalPtr&=Malloc&:(24)
IF ExternalPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
POKEL ExternalPtr&+4,Pattern&
POKEL ExternalPtr&,NumDistinctLetters&
POKEL ExternalPtr&+8,0
POKEL ExternalPtr&+12,0
POKEL ExternalPtr&+16,0
POKEL ExternalPtr&+20,0
POKEL InternalPtr&+20,ExternalPtr&
ENDIF
InternalPtr&=ExternalPtr&
Finished%=True%
ENDIF
ELSE
FREEALLOC Pattern&
Finished%=True%
ENDIF
ENDIF
UNTIL Finished%
ELSE
InternalPtr&=Malloc&:(24)
IF InternalPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
POKEL InternalPtr&+4,Pattern&
POKEL InternalPtr&,NumDistinctLetters&
POKEL InternalPtr&+8,0
POKEL InternalPtr&+12,0
POKEL InternalPtr&+16,0
POKEL InternalPtr&+20,0
PatternHead&=InternalPtr&
ENDIF
ENDIF
ENDIF
RETURN InternalPtr&
PROC AddEncipheredWord&:(EncipheredWord$)
EXTERNAL EncipheredHead&
EXTERNAL EncipheredTail&
EXTERNAL FatalError%
EXTERNAL PatternHead&
LOCAL Ciphertext&
LOCAL BytePtr&
LOCAL EncipheredWordIndex%
LOCAL EncipheredWordLen%
LOCAL ExternalPtr&
LOCAL PatternPtr&
PatternPtr&=0
ExternalPtr&=Malloc&:(16)
IF ExternalPtr& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
Ciphertext&=Malloc&:(1+LEN(EncipheredWord$))
IF Ciphertext& = 0
FatalError%=True%
PRINT "Fatal error: out of memory."
ELSE
BytePtr&=Ciphertext&
EncipheredWordLen%=LEN(EncipheredWord$)
EncipheredWordIndex%=1
WHILE EncipheredWordIndex% <= EncipheredWordLen%
POKEB BytePtr&,ASC(MID$(EncipheredWord$,EncipheredWordIndex%,1))
BytePtr&=BytePtr&+1
EncipheredWordIndex%=EncipheredWordIndex%+1
ENDWH
POKEB BytePtr&,0
POKEL ExternalPtr&,Ciphertext&
POKEL ExternalPtr&+8,0
PatternPtr&=PatternForEncipheredWord&:(Ciphertext&,EncipheredWordLen%)
POKEL ExternalPtr&+4,PatternPtr&
POKEL ExternalPtr&+12,0
IF EncipheredTail& <> 0
POKEL EncipheredTail&+12,ExternalPtr&
ELSE
EncipheredHead&=ExternalPtr&
ENDIF
EncipheredTail&=ExternalPtr&
ENDIF
ENDIF
RETURN PatternPtr&
PROC GetWordListWord:(PreviousWord$)
EXTERNAL CharNum%
EXTERNAL FatalError%
EXTERNAL LineNum&
EXTERNAL Word$
EXTERNAL WordList$()
LOCAL CurrentChar%
LOCAL DupCount%
Word$=""
DupCount%=GetWordListChar%:
IF DupCount% <> EOF%
IF (DupCount% >= UppercaseA%) AND (DupCount% <= UppercaseZ%)
DupCount%=DupCount%-UppercaseA%
IF DupCount% > 0
Word$=LEFT$(PreviousWord$,DupCount%)
ENDIF
DO
CurrentChar%=GetWordListChar%:
IF CurrentChar% = EOF%
FatalError%=True%
PRINT "Fatal error: premature end of word list."
ELSE
IF (CurrentChar% >= UppercaseA%) AND (CurrentChar% <= UppercaseZ%)
Word$=Word$+CHR$(ToLower%:(CurrentChar%))
ELSE
IF CurrentChar% = UppercaseZ%+1
Word$=Word$+"'"
ELSE
IF CurrentChar% <> Slash%
FatalError%=True%
PRINT "Fatal error: unexpected character in word list."
ENDIF
ENDIF
ENDIF
ENDIF
UNTIL FatalError% OR (CurrentChar% = Slash%)
ELSE
FatalError%=True%
PRINT "Fatal error: invalid dup count in word list."
ENDIF
ENDIF
RETURN
PROC GetWordListChar%:
EXTERNAL CharNum%
EXTERNAL LineNum&
EXTERNAL WordList$()
LOCAL CurrentChar$(1)
LOCAL Result%
CurrentChar$=MID$(WordList$(LineNum&),CharNum%,1)
IF CurrentChar$ = "!"
Result%=EOF%
ELSE
Result%=ASC(CurrentChar$)
CharNum%=CharNum%+1
IF CharNum% > LEN(WordList$(LineNum&))
LineNum&=LineNum&+1
CharNum%=1
ENDIF
ENDIF
RETURN Result%
PROC Malloc&:(NumBytes%)
LOCAL Result&
ONERR AllocFailed
Result&=ALLOC(NumBytes%)
ONERR OFF
RETURN Result&
AllocFailed::
RETURN 0
PROC ToLower%:(CurrentChar%)
LOCAL Result%
IF CurrentChar% < UppercaseA%
Result%=CurrentChar%
ELSE
IF CurrentChar% > UppercaseZ%
Result%=CurrentChar%
ELSE
Result%=(CurrentChar%-UppercaseA%)+LowercaseA%
ENDIF
ENDIF
RETURN Result%
PROC ToUpper%:(CurrentChar%)
LOCAL Result%
IF CurrentChar% < LowercaseA%
Result%=CurrentChar%
ELSE
IF CurrentChar% > LowercaseZ%
Result%=CurrentChar%
ELSE
Result%=(CurrentChar%-LowercaseA%)+UppercaseA%
ENDIF
ENDIF
RETURN Result%
PROC IsLower%:(CurrentChar%)
LOCAL Result%
IF CurrentChar% < LowercaseA%
Result%=False%
ELSE
IF CurrentChar% > LowercaseZ%
Result%=False%
ELSE
Result%=True%
ENDIF
ENDIF
RETURN Result%
PROC IsUpper%:(CurrentChar%)
LOCAL Result%
IF CurrentChar% < UppercaseA%
Result%=False%
ELSE
IF CurrentChar% > UppercaseZ%
Result%=False%
ELSE
Result%=True%
ENDIF
ENDIF
RETURN Result%
*Texted.app
This SIS-file is designed by BISON Software.
Bison Software doesn't accept any liability for the
function of the programme to be installed.
Please pay attention to the comment in the README file
of the author.
Before installing this software please make a
B A C K U P of your Psion Series 5.
Have a lot of fun!
Diese SIS-Datei wurde von Bison Software erstellt.
Bison Software
bernimmt keinerlei Garantie f
r die
Funktion des zu installierenden Programmes.
Bitte beachten Sie die Hinweise in der README Datei des
Autors.
Bevor Sie das Programm installieren machen Sie ein
B A C K U P Ihres Psion Serie 5.
Viel Spa