* Database example machine code program.
* Example 3: Demonstrate SELECT (INCLUDE) by means of a job.
* Uses file MCTEST_DBS which is created by TEST_MC1_BIN.
         INCLUDE  flp2_QDOS_TRAP_IN
         INCLUDE  flp2_QDOS_VECT_IN
         DATA     1024
SD.CURE  EQU      $E
SD.CURS  EQU      $F
SD.TAB   EQU      $11
*
         INCLUDE  flp2_QDOS_DATA_IN
         INCLUDE  flp2_DATA_IN
* Organise layout of dataspace.
         OFFSET   0
WIND     DS.L     1                 Screen window channel ID
DSBRT    DS.L     1                 Database manager vector
DCHAN    DS.L     1                 Database channel ID
DBASE    DS.L     1                 Database ID
WORK
*
         SECTION  MAIN
* Job header:
         BRA.L    START
         DC.W     0,$4AFB,6,'SELECT'
* Various pieces of data
FILENAME DC.W     15,'FLP2_MCTEST_DBS'  File name
* Selection 1:
SEL1     DC.W     1                 1 Parameter
         DC.W     1                 EXCLUDE FETCH(1) < 0
         DC.B     SPBC.LT
         DC.L     SEL1_VAL-SEL1
         DC.W     SPBO..NO          No next parameter

SEL1_VAL DC.W     0
* Selection 2:
SEL2     DC.W     2                 2 Parameters
         DC.W     2                 EXCLUDE FETCH(2) <= -7
         DC.B     SPBC.LT+SPBC.EQ,0
         DC.L     SEL2_VA-SEL2
         DC.W     SPBO..OR          OR

         DC.W     2                 EXCLUDE FETCH(2) >= 4
         DC.B     SPBC.GT+SPBC.EQ,0
         DC.L     SEL2_VB-SEL2
         DC.W     SPBO..NO

SEL2_VA  DC.W     -7
SEL2_VB  DC.W     4
* For selection 3: see routine SEL3 (user-supplied routine)
*
WINDOW   DC.B     7,1,0,4               Window definition
         DC.W     224,186,288,26

*                        123456789 123456789 123456789 12345
MESSE    DC.W        22,'Press any key to exit '
MESS1    DC.B     00,22,'SELECT demonstration.',$0A
         DS.W     0
MESS2    DC.B     00,12,' Record(s).',$0A
         DS.W     0
MESS3    DC.B     00,12,'Selection 1',$0A
         DS.W     0
MESS4    DC.B     00,15,'Selections 1&2',$0A
         DS.W     0
MESS5    DC.B     00,13,$0A,'Selection 3',$0A
         DS.W     0
* Start by clearing my dataspace
START
         LEA      0(A6,A5.L),SP     Set SP to top of dataspace
         LEA      0(A6,A4.L),A6     Set A6 to bottom
         MOVE.L   A6,A4
CLR_LOOP CLR.B    (A4)+             Clear it out
         CMPA.L   A4,SP
         BNE.S    CLR_LOOP
* Open a window to use for user IO
         LEA      WINDOW(PC),A1
         MOVE.W   UT.CON,A2         Open window
         JSR      (A2)
         BEQ.S    PRT_MES1
         BRA.S    SUICIDE

* Print error message and wait for keypress
SUI_PRT
         MOVE.L   WIND(A6),A0
         MOVE.W   UT.ERR,A2         Print the error message
         JSR      (A2)
* Exit point to quit
SUI_QUIT
         MOVE.L   WIND(A6),A0
         MOVE.L   D0,-(SP)          Save error code
         LEA      MESSE(PC),A1      Print error quit message
         MOVE.W   UT.MTEXT,A2
         JSR      (A2)              (Returns D3=-1)
         BNE.S    SUI_CONT

         MOVEQ    #SD.CURE,D0       Enable cursor
         TRAP     #3

         MOVEQ    #IO.FBYTE,D0      Wait for keypress
         TRAP     #3
SUI_CONT
         MOVE.L   (SP)+,D0
* Quit program
SUICIDE
         MOVE.L   D0,D3             Return error message to activator job
         MOVEQ    #-1,D1            Remove myself
         MOVEQ    #MT.FRJOB,D0
         TRAP     #1
* Send message 1 to window
PRT_MES1
         MOVE.L   A0,WIND(A6)
         LEA      MESS1(PC),A1
         MOVE.W   UT.MTEXT,A2
         JSR      (A2)
         BNE.S    SUICIDE
* Open database channel
         LEA      FILENAME(PC),A0   Filename ptr
         MOVEQ    #-1,D1            For myself
         MOVEQ    #IO.OLD,D3        Old file for modification
         MOVEQ    #IO.OPEN,D0       Open the channel
         TRAP     #2
         TST.L    D0
         BNE.S    SUI_PRT
* Now find out database manager
         MOVE.L   A0,DCHAN(A6)      Save channel ID
         MOVEQ    #-1,D3
         MOVEQ    #FS.DBASE,D0      Get the vector
         TRAP     #3
         TST.L    D0
         BNE.S    SUI_PRT
         MOVE.L   A1,DSBRT(A6)      Save vector address
         MOVE.L   A1,A4
* Now OPEN a database
* Use internal memory routines (MT.ALCHP, MT.RECHP): set A2 to 0
         SUBA.L   A2,A2             Memory allocate/release address
         JSR      FSD.OPEN(A4)
         BNE.S    SUI_PRT
         MOVE.L   A0,DBASE(A6)      Save database address
* In a loop: set some fields, append a record.
         LEA      WORK(A6),A1       A1 points to workspace
         MOVEQ    #2,D2             Fields word length
         MOVEQ    #9,D5             Create 10 more records
APPN_LP
* Set some fields
         MOVE.W   D5,(A1)           Put 0-D5 into field 1
         NEG.W    (A1)
         MOVEQ    #1,D1
         JSR      FSD.PUT(A4)
         BNE.S    SUI_PRT

         ADDQ.W   #7,(A1)           Put 7-D5 into field 2
         MOVEQ    #2,D1
         JSR      FSD.PUT(A4)
         BNE.L    SUI_PRT
* Add a new record to database
         JSR      FSD.APPN(A4)      Append record
         BNE.L    SUI_PRT
         DBRA     D5,APPN_LP
* Do selection 1
         MOVE.L   WIND(A6),A0
         LEA      MESS3(PC),A1
         MOVE.W   UT.MTEXT,A2       Print "Selection 1",LF
         JSR      (A2)              Returns D3.W=-1
         BNE.L    SUI_PRT
*
         MOVE.L   DBASE(A6),A0
         LEA      SEL1(PC),A1
         JSR      FSD.SEL(A4)       Do selection 1
         BNE.L    SUI_PRT
         BSR.S    REC_DUMP
* Print a LF
         MOVE.L   WIND(A6),A0
         MOVEQ    #$0A,D1
         MOVEQ    #-1,D3
         MOVEQ    #IO.SBYTE,D0
         TRAP     #3
         TST.L    D0
         BNE.L    SUI_PRT
* Overlay selection 2 on 1
         LEA      MESS4(PC),A1
         MOVE.W   UT.MTEXT,A2       Print "Selections 1&2",LF
         JSR      (A2)              Returns D3.W=-1
         BNE.L    SUI_PRT
*
         MOVE.L   DBASE(A6),A0
         LEA      SEL2(PC),A1
         JSR      FSD.SEL(A4)       Do selection 2
         BNE.L    SUI_PRT
         BSR.S    REC_DUMP
* Reset selection
         MOVE.L   DBASE(A6),A0
         JSR      FSD.RES(A4)
         BNE.L    SUI_PRT
* Do selection 3
         MOVE.L   WIND(A6),A0
         LEA      MESS5(PC),A1
         MOVE.W   UT.MTEXT,A2       Print "Selections 1&2",LF
         JSR      (A2)              Returns D3.W=-1
         BNE.L    SUI_PRT
*
         MOVE.L   DBASE(A6),A0
         PEA      SEL3(PC)          Set up parameter block on stack
         MOVE.W   #$8000,-(SP)      Use user-routine, EXCLUDE
         MOVE.L   SP,A1
         JSR      FSD.SEL(A4)       Do selection 3
         BNE.L    SUI_PRT
         ADDQ.L   #6,SP             Reclaim used stack
         BSR.S    REC_DUMP
         BRA.L    SUI_QUIT
*
* Print the number of records, followed by those records:
*
REC_DUMP
         MOVEQ    #0,D1
         JSR      FSD.INFO(A4)      Get Recnum and Fieldnum
         BNE.L    SUI_PRT
         MOVE.L   D2,D6
*
         MOVE.L   D6,D7             Fieldnum in D6.W
         SWAP     D7                Recnum in D7.W
         MOVE.W   D7,D1
         BEQ.L    NO_RECS
         MOVE.L   WIND(A6),A0       Print no. fields
         MOVE.W   UT.MINT,A2
         JSR      (A2)
         BNE.L    SUI_PRT

         LEA      MESS2(PC),A1      Print "Records."&LF
         MOVE.W   UT.MTEXT,A5
         JSR      (A5)
         BNE.L    SUI_PRT

* Print each record
         MOVE.W   UT.MINT,A5        Printing routine for integers
         MOVEQ    #0,D5             Start at Record 1
REOUT_LP
         MOVE.L   DBASE(A6),A0
         MOVE.W   D5,D1
         JSR      FSD.POSA(A4)      Get record
         BNE.L    SUI_PRT
* Print each field
         MOVE.W   #1,D4             Start at field 1
RFOUT_LP
         MOVE.W   D4,D1             Field Number
         MOVEQ    #2,D2             Buffer length
         MOVE.L   DBASE(A6),A0
         LEA      WORK(A6),A1       Buffer address
         JSR      FSD.GET(A4)       Get field
         BNE.L    SUI_PRT

         MOVE.W   WORK(A6),D1       Get contents of buffer
         MOVE.L   WIND(A6),A0
         JSR      (A5)              Print contents (D3=-1 on return)
         BNE.L    SUI_PRT

         MOVE.W   D4,D1
         LSL.W    #3,D1             D1*8
         MOVEQ    #SD.TAB,D0
         TRAP     #3
         TST.L    D0
         BNE.L    SUI_PRT

         ADDQ.W   #1,D4             Do all fields
         CMP.W    D4,D6
         BCC.S    RFOUT_LP
*
         MOVEQ    #$0A,D1           Print LF
         MOVEQ    #IO.SBYTE,D0
         TRAP     #3
         TST.L    D0
         BNE.L    SUI_PRT
*
         ADDQ.W   #1,D5             Do all records
         CMP.W    D5,D7
         BHI.S    REOUT_LP
         MOVE.L   WIND(A6),A0
         MOVEQ    #SD.CURE,D0       Enable cursor
         TRAP     #3
         MOVEQ    #IO.FBYTE,D0      Pause for keypress
         TRAP     #3
         MOVEQ    #SD.CURS,D0       Disable cursor
         TRAP     #3
NO_RECS
         RTS
*
* User select routine
* Deselect records in which FETCH(2) is even.
*
SEL3
         MOVE.W   2(A1),D0          Do FETCH(2)
         BPL.S    SEL3_POS
         NEG.W    D0
SEL3_POS
         BTST     #0,3(A1)          Set Z if (word) Even
         MOVE     SR,D5             Set bit 2 D5 from Z flag
         MOVEQ    #0,D0             No error
         RTS
         END
