home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / testi / corsoasm / sorgenti_darkcoder / vari / codfiscale.s < prev    next >
Encoding:
Text File  |  1995-12-06  |  11.4 KB  |  604 lines

  1. ;
  2. ; CODICE FISCALE (C)1993 Daniele Paccaloni (DDT / HALF-BRAINS TEAM) !
  3. ; Questa e' la piu' veloce routine per calcolare il codice fiscale di
  4. ; una persona. La tabella dei comuni puo' essere ampliata a piacere.
  5. ; Ovviamente la velocita' non e' indispensabile per calcolare il
  6. ; codice fiscale di una sola persona (come avviene adesso in prompt mode)
  7. ; ma, aggiustando il tutto per un lavoro batch, sarebbe molto utile a
  8. ; qualche ufficio di stato, data la vergognosa lentezza con cui vengono
  9. ; svolte molte pratiche :) Se tutti i programmi fossero scritti in
  10. ; assembly non ci sarebbe piu' bisogno dei pentium... se non per giocare
  11. ; a DOOM !!!
  12. ; Divertitevi a scovare il codice fiscale dei vostri amici, li stupirete
  13. ; indovinando tutte le cifre.. e anche l'ultima, la piu' difficile !!! :)
  14. ; Questo programma puo' dare assuefazione .. !@#?! Tenere lontano dalla
  15. ; portata dei bambini piu' piccoli.
  16. ;                    Daniele
  17.  
  18. S:
  19.  
  20. Input:    move.l    $4.w,a6            ;Take the execbase address,
  21.     lea    DosName,a1        ;open the GFXlibrary {
  22.     jsr    -408(a6)        ;}.
  23.     tst.l    d0
  24.     beq.w    Error
  25.     move.l    d0,DosBase        ;Save the GFXbase pointer,
  26.     move.l    d0,a6
  27.  
  28.  
  29. ; COGNOME
  30.  
  31.     bsr.w    ClrBuf
  32.  
  33. InputSurn:
  34.     jsr    -60(a6)        ; _LVOOutput
  35.     tst.l    d0
  36.     beq.w    Error
  37.     move.l    d0,OutHandler
  38.     move.l    d0,d1
  39.     move.l    #OutText1,d2
  40.     move.l    #EndOutText1-OutText1,d3
  41.     jsr    -48(a6)        ; _LVOWrite
  42.  
  43.     jsr    -54(a6)        ; _LVOInput
  44.     tst.l    d0
  45.     beq.w    Error
  46.     move.l    d0,InHandler    ; d0=string lenght
  47.     move.l    d0,d1
  48.     move.l    #InputBuffer,d2
  49.     moveq    #80,d3
  50.     jsr    -42(a6)        ; _LVORead
  51.     tst.l    d0
  52.     beq.s    InputSurn
  53.     move.l    d0,d1            ;Copy string lenght
  54.  
  55.     bsr.w    Maiuscolo
  56.     bsr.w    EliminaSpazii
  57.  
  58.     move.w    d1,d0            ;Cerca le prime 3 consonanti
  59.     subq.w    #1,d0
  60.     moveq    #3,d4
  61.     lea    InputBuffer(pc),a0
  62.     lea    CODICE(pc),a4
  63. ChkNxtC:
  64.     move.b    (a0)+,d3
  65.     lea    VocalsTab(pc),a2
  66.     moveq    #4,d2
  67. ChkVocC:
  68.     cmp.b    (a2)+,d3
  69.     beq.s    IsVoc
  70.     dbra    d2,ChkVocC
  71.     cmp.b    #10,d3            ;Check if EOL
  72.     beq.s    GetVocs
  73.     move.b    d3,(a4)+
  74.     subq.w    #1,d4
  75.     beq.s    NOME
  76. IsVoc:
  77.     dbra    d0,ChkNxtC
  78.  
  79. GetVocs:
  80.     move.w    d1,d0            ;Completa con le vocali
  81.     subq.w    #1,d0
  82.     lea    InputBuffer(pc),a0
  83. ChkNxtV:
  84.     move.b    (a0)+,d3
  85.     lea    VocalsTab(pc),a2
  86.     moveq    #4,d2
  87. ChkVocV:
  88.     cmp.b    (a2)+,d3
  89.     beq.s    YeVoc
  90.     dbra    d2,ChkVocV
  91.     dbra    d0,ChkNxtV
  92.     bra.s    VDone
  93.  
  94. YeVoc:
  95.     move.b    d3,(a4)+
  96.     subq.w    #1,d4
  97.     beq.s    NOME
  98.     dbra    d0,ChkNxtV
  99. VDone:
  100. PatchX:
  101.     move.b    #"X",(a4)+    ;Inserisce le X se necessario
  102.     subq.w    #1,d4
  103.     bne.s    PatchX
  104.  
  105. ;--------------------------------NOME
  106.  
  107. NOME:
  108.     bsr.w    ClrBuf
  109. InputName:
  110.     jsr    -60(a6)        ; _LVOOutput
  111.     tst.l    d0
  112.     beq.w    Error
  113.     move.l    d0,OutHandler
  114.     move.l    d0,d1
  115.     move.l    #OutText2,d2
  116.     move.l    #EndOutText2-OutText2,d3
  117.     jsr    -48(a6)        ; _LVOWrite
  118.  
  119.     jsr    -54(a6)        ; _LVOInput
  120.     tst.l    d0
  121.     beq.w    Error
  122.     move.l    d0,InHandler
  123.     move.l    d0,d1
  124.     move.l    #InputBuffer,d2
  125.     moveq    #80,d3
  126.     jsr    -42(a6)        ; _LVORead
  127.     tst.l    d0        ; d0 = lunghezza stringa
  128.     beq.s    InputName
  129.     move.l    d0,d1            ;Copia lunghezza stringa
  130.  
  131.     bsr.w    Maiuscolo
  132.     bsr.w    EliminaSpazii
  133.  
  134. ; Copia le prime 4 consonanti del nome in ConsNome:
  135.  
  136.     move.l    d1,d0
  137.     subq.w    #1,d0
  138.     moveq    #4,d4            ;Verifica 4 consonanti
  139.     lea    InputBuffer(pc),a0
  140.     lea    ConsNome(pc),a5        ;Copia qui le prime 4 conson
  141. NxtLet:
  142.     move.b    (a0)+,d3
  143.     lea    VocalsTab(pc),a2
  144.     moveq    #4,d2
  145. ChkCons:
  146.     cmp.b    (a2)+,d3
  147.     beq.s    NoCon
  148.     dbra    d2,ChkCons
  149.     cmp.b    #10,d3            ;Check if EOL
  150.     beq.s    NoCon
  151.     move.b    d3,(a5)+
  152.     subq.w    #1,d4
  153.     beq.s    FourCon
  154. NoCon:
  155.     dbra    d0,NxtLet
  156.     lea    ConsNome(pc),a5        ;Indirizzo prime 4 consonanti
  157.     moveq    #3,d0
  158.     sub.w    d4,d0            ;d0=numero di consonanti nome
  159.     bpl.s    CPyCon
  160.     subq.w    #1,d4
  161.     bra.s    NoCons
  162. CpyCon:
  163.     move.b    (a5)+,(a4)+
  164.     dbra    d0,CpyCon
  165.     subq.w    #1,d4        ;Testa se ci sono 3 consonanti,
  166.     beq.s    DATA        ; se si` vai a codificare la data...
  167. NoCons:
  168.     move.w    d1,d0        ;Altrimenti completa con vocali:
  169.     subq.w    #1,d0
  170.     lea    InputBuffer(pc),a0
  171. ChkNxtN:
  172.     move.b    (a0)+,d3
  173.     lea    VocalsTab(pc),a2
  174.     moveq    #4,d2
  175. ChkVocN:
  176.     cmp.b    (a2)+,d3
  177.     beq.s    YeVoc2
  178.     dbra    d2,ChkVocN
  179.     dbra    d0,ChkNxtN
  180.     bra.s    VDoneN
  181.  
  182. YeVoc2:
  183.     move.b    d3,(a4)+
  184.     subq.w    #1,d4
  185.     beq.w    DATA
  186.     dbra    d0,ChkNxtN
  187. VDoneN:
  188. PatchXN:
  189.     move.b    #"X",(a4)+    ;Inserisce le X se necessario
  190.     subq.w    #1,d4
  191.     bne.s    PatchXN
  192.     bra.s    SkipHere
  193.  
  194. ; Copia la 1',3',4' consonante nel CODICE
  195.  
  196. FourCon:
  197.     lea    ConsNome(pc),a5        ; Indirizzo prime 4 consonanti
  198.     move.b    (a5),(a4)+        ; Copia la prima nel codice
  199.     move.b    2(a5),(a4)+        ; Copia la terza nel codica
  200.     move.b    3(a5),(a4)+        ; Copia la quarta nel codice
  201. SkipHere:
  202. ;------------------------------------DATA DI NASCITA
  203. DATA:
  204.     bsr.w    ClrBuf
  205. InputData:
  206.     jsr    -60(a6)        ; _LVOOutput
  207.     tst.l    d0
  208.     beq.w    Error
  209.     move.l    d0,OutHandler
  210.     move.l    d0,d1
  211.     move.l    #OutText3,d2
  212.     move.l    #EndOutText3-OutText3,d3
  213.     jsr    -48(a6)        ; _LVOWrite
  214.  
  215.     jsr    -54(a6)        ; _LVOInput
  216.     tst.l    d0
  217.     beq.w    Error
  218.     move.l    d0,InHandler
  219.     move.l    d0,d1
  220.     move.l    #InputBuffer,d2
  221.     moveq    #80,d3
  222.     jsr    -42(a6)        ; _LVORead
  223.     tst.l    d0        ; d0 = lunghezza stringa
  224.     beq.s    InputData
  225.     cmp.l    #9,d0
  226.     bne.s    InputData
  227.     lea    InputBuffer(pc),a0
  228.     cmp.b    #"/",2(a0)
  229.     bne.s    InputData
  230.     cmp.b    #"/",5(a0)
  231.     bne.s    InputData
  232.     move.b    (a0),d7
  233.     bsr.w    VerifNum
  234.     bne.s    InputData
  235.     move.b    1(a0),d7
  236.     bsr.w    VerifNum
  237.     bne.s    InputData
  238.     move.b    3(a0),d7
  239.     bsr.w    VerifNum
  240.     bne.s    InputData
  241.     move.b    4(a0),d7
  242.     bsr.w    VerifNum
  243.     bne.w    InputData
  244.     move.b    6(a0),d7
  245.     bsr.w    VerifNum
  246.     bne.w    InputData
  247.     move.b    7(a0),d7
  248.     bsr.w    VerifNum
  249.     bne.w    InputData
  250.     move.l    d0,d1            ;Copia lunghezza stringa
  251.  
  252.     cmp.b    #"2",(a0)        ;Testa se il giorno e' > 29
  253.     bls.s    OkGg
  254.     cmp.b    #"1",1(a0)        ;Se giorno > 31 allora
  255.     bhi.w    InputData        ;   reinput...
  256.  
  257. OkGg:
  258.     move.b    3(a0),d0
  259.     sub.b    #$30,d0
  260.     mulu.w    #10,d0            ;moltiplicazione non ottimizz
  261.     add.b    4(a0),d0
  262.     sub.b    #$30,d0
  263.     cmp.b    #12,d0
  264.     bhi.w    InputData
  265.  
  266.     move.b    6(a0),(a4)+        ;Copia le ultime due cifre dell'
  267.     move.b    7(a0),(a4)+        ; anno nel codice.
  268.  
  269.     subq.w    #1,d0            ;Sottrae 1 per scostam in tab
  270.     and.w    #$00ff,d0        ;Pulisce parte alta di d0
  271.     lea    MonthTab(pc),a2        ;a2 punta alla tabella
  272.     move.b    (a2,d0.w),d0        ;prende lettera del mese in d0
  273.  
  274.     move.b    d0,(a4)+        ;mette lettera del mese nel cod
  275.  
  276.     move.b    (a0),d6            ;d6.b = cifra decine del giorno
  277.     move.b    1(a0),d7        ;d7.b = cifra unita` del giorno
  278. ;------------------------------------SESSO
  279.     bsr.w    ClrBuf
  280. InputSesso:
  281.     jsr    -60(a6)        ; _LVOOutput
  282.     tst.l    d0
  283.     beq.w    Error
  284.     move.l    d0,OutHandler
  285.     move.l    d0,d1
  286.     move.l    #OutText4,d2
  287.     move.l    #EndOutText4-OutText4,d3
  288.     jsr    -48(a6)        ; _LVOWrite
  289.  
  290.     jsr    -54(a6)        ; _LVOInput
  291.     tst.l    d0
  292.     beq.w    Error
  293.     move.l    d0,InHandler
  294.     move.l    d0,d1
  295.     move.l    #InputBuffer,d2
  296.     moveq    #80,d3
  297.     jsr    -42(a6)        ; _LVORead
  298.     tst.l    d0        ;d0 = lunghezza stringa
  299.     beq.s    InputSesso
  300.     move.l    d0,d1            ;Copia lunghezza stringa
  301.  
  302.     bsr.w    Maiuscolo
  303.  
  304.     lea    InputBuffer(pc),a2
  305.     cmp.b    #"M",(a2)
  306.     beq.s    Maschio
  307.     cmp.b    #"F",(a2)
  308.     bne.s    InputSesso
  309.  
  310.     addq.b    #4,d6            ;Se e' una femmina aggiungi 4
  311.                     ; alla cifra delle decine !
  312.  
  313. Maschio:move.b    d6,(a4)+        ;Mette cifra decine del giorno
  314.                     ;  nel codice,
  315.     move.b    d7,(a4)+        ;Mette cifra unita` del giorno
  316.                     ;  nel codice.
  317.  
  318. ;------------------------------------COMUNE
  319.     bsr.w    ClrBuf
  320. InputComune:
  321.     jsr    -60(a6)        ; _LVOOutput
  322.     tst.l    d0
  323.     beq.w    Error
  324.     move.l    d0,OutHandler
  325.     move.l    d0,d1
  326.     move.l    #OutText5,d2
  327.     move.l    #EndOutText5-OutText5,d3
  328.     jsr    -48(a6)        ; _LVOWrite
  329.  
  330.     jsr    -54(a6)        ; _LVOInput
  331.     tst.l    d0
  332.     beq.w    Error
  333.     move.l    d0,InHandler
  334.     move.l    d0,d1
  335.     move.l    #InputBuffer,d2
  336.     moveq    #80,d3
  337.     jsr    -42(a6)        ; _LVORead
  338.     tst.l    d0        ; d0 = lunghezza stringa
  339.     beq.s    InputComune
  340.     move.l    d0,d1            ;Copia lunghezza stringa
  341.  
  342.     bsr.w    Maiuscolo
  343.  
  344.     lea    ComuniTab(pc),a3
  345. SrchNxt:
  346.     lea    InputBuffer(pc),a2
  347.     move.l    d0,d1
  348.     subq.w    #1,d1
  349. CmpCom:
  350.     move.b    (a2)+,d2
  351.     cmp.b    (a3)+,d2
  352.     bne.s    NoThiz
  353.     dbra    d1,CmpCom
  354.     bra.s    ComFound
  355.  
  356. NoThiz:
  357.     cmp.b    #10,(a3)+
  358.     bne.s    NoThiz
  359.     addq.w    #4,a3
  360.     cmp.l    #ComuniTabEnd,a3
  361.     bne.s    SrchNxt
  362.  
  363. ;Non trovato; inserire il codice fiscale
  364.  
  365. InputCodiceCom:
  366.     jsr    -60(a6)        ; _LVOOutput
  367.     tst.l    d0
  368.     beq.w    Error
  369.     move.l    d0,OutHandler
  370.     move.l    d0,d1
  371.     move.l    #OutText6,d2
  372.     move.l    #EndOutText6-OutText6,d3
  373.     jsr    -48(a6)        ; _LVOWrite
  374.     jsr    -54(a6)        ; _LVOInput
  375.     tst.l    d0
  376.     beq.w    Error
  377.     move.l    d0,InHandler
  378.     move.l    d0,d1
  379.     move.l    #InputBuffer,d2
  380.     moveq    #80,d3
  381.     jsr    -42(a6)            ;d0 = lunghezza stringa
  382.     tst.l    d0
  383.     beq.s    InputCodiceCom
  384.     cmp.b    #5,d0            ;Lunghezza codice = 4 cifre
  385.     bne.s    InputCodiceCom
  386.     lea    InputBuffer(pc),a3
  387.     bclr.b    #5,(a3)            ;Lettera codice maiuscola
  388. ComFound:
  389.     move.b    (a3)+,(a4)+        ;Copia codice comune
  390.     move.b    (a3)+,(a4)+        ;   nel codice fiscale
  391.     move.b    (a3)+,(a4)+
  392.     move.b    (a3)+,(a4)+
  393.  
  394. ;------------------------------COMPUTA CARATTERE DI CONTROLLO
  395.  
  396.     lea    CODICE+1(pc),a0
  397.     moveq    #6,d5
  398.     moveq    #0,d7
  399. ParLop:
  400.     move.b    (a0),d6
  401.     cmp.b    #"9",d6
  402.     bls.s    PNum
  403.     sub.b    #"A"-"0",d6
  404. PNum:
  405.     sub.b    #"0",d6
  406.     ext.w    d6
  407.     add.w    d6,d7
  408.     addq.w    #2,a0
  409.     dbra    d5,ParLop
  410.  
  411.     lea    CODICE(pc),a0
  412.     lea    CtrlTab(pc),a2
  413.     moveq    #7,d5
  414. DisLop:
  415.     moveq    #0,d6
  416.     move.b    (a0),d6
  417.     cmp.b    #"9",d6
  418.     bls.s    DNum
  419.     sub.b    #"A"-"0",d6
  420. DNum:
  421.     sub.b    #"0",d6
  422.     lsl.w    #1,d6
  423.     add.w    (a2,d6.w),d7
  424.     addq    #2,a0
  425.     dbra    d5,DisLop
  426.  
  427.     divu.w    #26,d7
  428.     swap    d7
  429.     add.b    #"A",d7
  430.     move.b    d7,(a4)
  431.  
  432. ;------------------------------STAMPA CODICE
  433.  
  434.     move.l    DosBase(pc),a6
  435.     jsr    -60(a6)        ; _LVOOutput - Stampa il codice fiscale
  436.     tst.l    d0
  437.     beq.s    Error
  438.     move.l    d0,OutHandler
  439.     move.l    d0,d1
  440.     move.l    #CODICE,d2
  441.     moveq    #17,d3
  442.     jsr    -48(a6)        ; _LVOWrite
  443.  
  444. Error:
  445.     move.l    $4.w,a6            ;Indirizzo Execbase,
  446.     move.l    DosBase(pc),a1
  447.     jsr    -414(a6)        ;Chiude la libreria DOS
  448.     rts
  449.  
  450.  
  451.  
  452. ;---- SOUBROUTINE MAIUSCOLO --------
  453. ; Parametri:    d0.w = numero caratteri
  454.  
  455. Maiuscolo:
  456.     movem.l    d0/a0,-(sp)
  457.     subq.w    #1,d0
  458.     lea    InputBuffer(pc),a0
  459. Caps:
  460.     cmp.b    #" ",(a0)
  461.     bne.s    OkM
  462.     addq.w    #1,a0
  463.     bra.s    After
  464.  
  465. OkM:
  466.     bclr.b    #5,(a0)+
  467. After:
  468.     dbra    d0,Caps
  469.     movem.l    (sp)+,d0/a0
  470.     rts
  471.  
  472.  
  473. ;---- SOUBROUTINE ELIMINASPAZII --------
  474. ; Parametri:    [nessuno]
  475.  
  476. EliminaSpazii:
  477.     movem.l    d0/a0/a1/a2,-(sp)
  478.     lea    InputBuffer(pc),a0
  479. HuntS:
  480.     move.b    (a0),d6
  481.     cmp.b    #10,d6
  482.     beq.s    EDone
  483.     cmp.b    #" ",d6
  484.     beq.s    Argh
  485.     addq.w    #1,a0
  486.     bra.s    HuntS
  487.  
  488. Argh:
  489.     move.l    a0,a1
  490.     move.l    a0,a2
  491. Yop:
  492.     addq.w    #1,a2
  493.     move.b    (a2),(a1)+
  494.     cmp.b    #10,(a2)
  495.     beq.s    SEOL
  496.     bra.s    Yop
  497.  
  498. SEOL:
  499.     addq.w    #1,a0
  500.     bra.s    HuntS
  501. EDone:
  502.     movem.l    (sp)+,d0/a0/a1/a2
  503.     rts
  504.  
  505.  
  506. ;---- SOUBROUTINE CLEAR BUFFER --------
  507. ; Parametri:    nessuno
  508.  
  509. ClrBuf:
  510.     lea    InputBuffer(pc),a0
  511.     moveq    #(80/4)-1,d0
  512. ClrB:
  513.     clr.l    (a0)+
  514.     dbra    d0,ClrB
  515.     rts
  516.  
  517. ;---- SOUBROUTINE VERIFICA NUMERO --------
  518. ; Parametri:    d7.b = carattere da verificare
  519. ; Risultato:    Zflag settato se uguale
  520.  
  521. VerifNum:
  522.     cmp.b    #$30,d7
  523.     bhi.s    OKBnd1
  524.     rts
  525.  
  526. OkBnd1:
  527.     cmp.b    #$39,d7
  528.     bhi.s    ExitVM
  529.     moveq    #0,d7
  530. ExitVM:
  531.     rts
  532.  
  533. ;---------------------------------------------------
  534. DosName:    dc.b    "dos.library",0
  535. DosBase:    dc.l    0
  536.  
  537. OutHandler:    dc.l    0
  538. InHandler:    dc.l    0
  539.  
  540. OutText1:    dc.b    10,$9b,'33',$6d,"  CODICE FISCALE ",$9b,'31',$6d,"di D.Paccaloni & T.Labruzzo"
  541.         dc.b    10,10,"COGNOME > "
  542. EndOutText1:
  543. OutText2:    dc.b    10,"NOME > "
  544. EndOutText2:
  545. OutText3:    dc.b    10,"DATA DI NASCITA (gg/mm/aa) > "
  546. EndOutText3:
  547. OutText4:    dc.b    10,"SESSO > "
  548. EndOutText4:
  549. OutText5:    dc.b    10,"COMUNE DI NASCITA > "
  550. EndOutText5:
  551. OutText6:    dc.b    10,"Codice comune non trovato, inserirlo (4 cifre) > "
  552. EndOutText6:
  553.  
  554.     even
  555.  
  556. InputBuffer:    dcb.b    80,0
  557.  
  558. VocalsTab:    dc.b    "AEIOU"
  559.  
  560. MonthTab:    dc.b    "ABCDEHLMPRST"
  561.  
  562.         ; Tabella dei comuni, da ampliare se necessario !
  563. ComuniTab:    dc.b    "AREZZO",10,"A390"
  564.         dc.b    "ASCOLI PICENO",10,"A462"
  565.         dc.b    "ASTI",10,"A479"
  566.         dc.b    "BARI",10,"A662"
  567.         dc.b    "BERGAMO",10,"A794"
  568.         dc.b    "BOLOGNA",10,"A944"
  569.         dc.b    "BRESCIA",10,"B157"
  570.         dc.b    "CATANIA",10,"C351"
  571.         dc.b    "CATANZARO",10,"C352"
  572.         dc.b    "COMO",10,"C933"
  573.         dc.b    "FERRARA",10,"D548"
  574.         dc.b    "IMPERIA",10,"E290"
  575.         dc.b    "LA SPEZIA",10,"E463"
  576.         dc.b    "LECCE",10,"E506"
  577.         dc.b    "MILANO",10,"F205"
  578.         dc.b    "NAPOLI",10,"F839"
  579.         dc.b    "PALERMO",10,"G273"
  580.         dc.b    "PISA",10,"G702"
  581.         dc.b    "ROMA",10,"H501"
  582.         dc.b    "SIRACUSA",10,"I754"
  583.         dc.b    "TORINO",10,"L219"
  584.         dc.b    "TRIESTE",10,"L424"
  585.         dc.b    "TRENTO",10,"L378"
  586.         dc.b    "UDINE",10,"L483"
  587.         dc.b    "VENEZIA",10,"L736"
  588.         dc.b    "VERONA",10,"L781"
  589. ComuniTabEnd:
  590.  
  591.         even
  592. CtrlTab:    dc.w    1,0,5,7,9,13,15,17,19,21,2,4,18,20,11,3,6,8
  593.         dc.w    12,14,16,10,22,25,24,23
  594.  
  595.         even
  596. ConsNome:    dcb.b    4,0
  597.  
  598. CODICE:        dcb.b    16,0    ;16 caratteri
  599.         dc.b    10    ;EOL
  600.  
  601.  
  602.     end
  603.  
  604.