home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 146_01 / ccint.txt < prev    next >
Text File  |  1985-03-10  |  24KB  |  1,328 lines

  1.  ORG 0
  2.  NAM SMALL-C INTERPRETER
  3.  OPT NOP,NOG
  4. *
  5. *   LAST UPDATE   9-SEP-82
  6. *
  7.  JMP BEGIN START THE INTERPRETER
  8.  
  9. *  AN INDIRECT CALL TABLE
  10.  NOP PUT ON A BOUNDARY OF 4
  11.  FCB 86
  12.  JMP fclose+1
  13.  FCB 86
  14.  JMP fopen+1
  15.  FCB 86
  16.  JMP getc+1
  17.  FCB 86
  18.  JMP getchar+1
  19.  FCB 86
  20.  JMP gets+1
  21.  FCB 86
  22.  JMP putc+1
  23.  FCB 86
  24.  JMP putchar+1
  25.  FCB 86
  26.  JMP puts+1
  27.  NOP
  28.  JMP RTSC
  29.  FCB 86
  30.  JMP isalpha+1
  31.  FCB 86
  32.  JMP isdigit+1
  33.  FCB 86 
  34.  JMP isalnum+1
  35.  FCB 86
  36.  JMP islower+1
  37.  FCB 86
  38.  JMP isupper+1
  39.  FCB 86
  40.  JMP isspace+1
  41.  FCB 86
  42.  JMP toupper+1
  43.  FCB 86
  44.  JMP tolower+1
  45.  FCB 86
  46.  JMP strclr+1
  47.  FCB 86
  48.  JMP strlen+1
  49.  FCB 86
  50.  JMP strcpy+1
  51.  FCB 86
  52.  JMP strcat+1
  53.  FCB 86
  54.  JMP strcmp+1
  55.  RMB 4*4 ROOM FOR 4 MORE
  56.  
  57.  LIB FLEXPTRS
  58.  
  59. NFILES EQU 4 MAX NO OF DISK FILES OPEN AT ONCE
  60. PC RMB 2 PSEUDO PROGRAM COUNTER
  61. R1A RMB 1 WORKING 16 BIT
  62. R1B RMB 1 --REGISTER
  63. DFLAG FCB NFILES-1 DIVIDE ROUTINE FLAG
  64. STEMP RMB 2 TEMP STORAGE FOR STACK POINTER
  65. X1TMP RMB 2 TEMP STORAGE FOR X REG
  66. X2TMP RMB 2 ... DITTO ...
  67. FCBPTR RMB 2 POINTER INTO FCB TABLE
  68. FCBTBL FDB FCB TABLE OF FCB POINTERS
  69.  RMB NFILES*2 ROOM FOR THE REST
  70.  
  71.  
  72.  
  73. ***************************************************
  74.  
  75. BEGIN LDX #FCBTBL+2 POINT TO FCB ADDRESSES
  76.  LDA A #NFILES-1
  77.  STA A DFLAG   INIT COUNTER
  78.  LDA A $AC2B GET TOP OF MEMORY
  79.  LDA B $AC2C
  80.  
  81. BLOOP SUB B #$40 SUBTR 320 (SIZE OF FCB)
  82.  SBC A #1
  83.  STA A 0,X SAVE FCB ADDRESS
  84.  INX
  85.  STA B 0,X
  86.  INX
  87.  DEC DFLAG DONE ???
  88.  BNE BLOOP
  89.  
  90.  CLR 0,X MARK END OF TABLE
  91.  CLR 1,X
  92.  STA A STEMP TOP OF STACK AREA
  93.  STA B STEMP+1
  94.  LDX STEMP
  95.  TXS SET STACK POINTER
  96.  
  97.  LDX #FCBTBL POINT TO TABLE OF FCB ADDRESSES
  98. Init STX FCBPTR
  99.  LDX 0,X GET FCB ADDRESS
  100.  BEQ Initend QUIT IF END OF TABLE
  101.  CLR 2,X MARK AS NOT IN USE
  102.  LDX FCBPTR
  103.  INX
  104.  INX
  105.  BRA Init
  106.  
  107. Initend LDX #$800
  108.  BRA NEXT2 START THE INTERPRETATION
  109.  
  110. **************************************************************
  111. *
  112. *  THE HEART OF THE INTERPRETER--- NEXT INSTRUCTION FETCHER.
  113. *
  114. BUMP2 LDX PC GET PROG COUNTER
  115. BUMP2A INX INCR BY 2
  116.  INX
  117.  BRA NEXT1 FETCH NEXT INSTRUCTION
  118.  
  119. NEXT LDX PC
  120. NEXT1 STA A R1A SAVE THE WORK
  121.  STA B R1B --REGISTER
  122. NEXT2 LDA B 0,X GET THE PSEUDO-INSTRUCTION
  123.   INX  (B CONTAINS A TABLE OFFSET)
  124.  STX PC SAVE NEW PC
  125.  STA B JJJ+2 SAVE AS PAGE OFFSET
  126.  LDA B R1B RESTORE
  127. JJJ LDX JTABLE POINT TO ROUTINE (SELF MODIFYING CODE)
  128.  JMP 0,X GO EXECUTE THE PSEUDO-INSTR.
  129.  
  130. **************************************************************
  131. *                  THE JUMP TABLE                            *
  132. **************************************************************
  133.  
  134.  ORG *+255/256*256  MUST START ON A PAGE BOUNDARY
  135.  
  136. JTABLE FDB LD1IM  #0
  137.  FDB LD1SOFF #1
  138.  FDB LD1 #2
  139.  FDB LDB1 #3
  140.  FDB LD1R #4
  141.  FDB LDB1R #5
  142.  FDB ST1 #6
  143.  FDB STB1 #7
  144.  FDB ST1SP #8
  145.  FDB STB1SP #9
  146.  FDB PUSHR1 #10
  147.  FDB EXG1 #11
  148.  FDB JMPL #12
  149.  FDB BRZL #13
  150.  FDB JSRL #14
  151.  FDB JSRSP #15
  152.  FDB RTSC #16
  153.  FDB MODSP #17
  154.  FDB DBL1 #18
  155.  FDB ADDS #19
  156.  FDB SUBFST #20
  157.  FDB MUL1 #21
  158.  FDB DIV1 #22
  159.  FDB MOD #23
  160.  FDB ORS #24
  161.  FDB XORS #25
  162.  FDB ANDS #26
  163.  FDB ASRS #27
  164.  FDB ASLS #28
  165.  FDB NEGR #29
  166.  FDB NOTR #30
  167.  FDB INCR #31
  168.  FDB DECR #32
  169.  FDB ZEQ #33
  170.  FDB ZNE #34
  171.  FDB ZLT #35
  172.  FDB ZLE #36
  173.  FDB ZGT #37
  174.  FDB ZGE #38
  175.  FDB ULT #39
  176.  FDB ULE #40
  177.  FDB UGT #41
  178.  FDB UGE #42
  179.  FDB ASMC #43
  180.  
  181. *************************************************************
  182. *-------------------------
  183. * #0 LOAD REG WITH IMMED. VALUE
  184. LD1IM LDX PC
  185.  LDA A 0,X HIGH BYTE
  186.  LDA B 1,X LOW BYTE
  187.  JMP BUMP2A
  188.  
  189. *-------------------------
  190. * #1 LOAD STACK ADDRESS + OFFSET INTO REG
  191. LD1SOFF STS R1A SAVE STACK VALUE
  192.  LDX PC
  193.  LDA A 0,X GET OFFSET 
  194.  LDA B 1,X -- VALUE
  195.  SEC
  196.  ADC B R1B ADD OFFSET + 1
  197.  ADC A R1A
  198.  JMP BUMP2A
  199.  
  200. *-------------------------
  201. * #2  LOAD WORD @ ADDRESS
  202. LD1 LDX PC
  203.  LDX 0,X GET ADDRESS
  204. LD1A LDA A 0,X GET WORD
  205.  LDA B 1,X
  206.  JMP BUMP2
  207.  
  208. *-------------------------
  209. * #3  LOAD BYTE @ ADDRESS
  210. LDB1 LDX PC
  211.  LDX 0,X GET ADDRESS
  212.  CLR A
  213.  LDA B 0,X GET BYTE
  214.  BPL LDB1A
  215.  COM A SIGN EXTEND
  216. LDB1A JMP BUMP2
  217.  
  218. *-------------------------
  219. * #4  LOAD WORD INDIRECT (ADDR IN REG)
  220. LD1R LDX R1A GET ADDRESS
  221.  LDA A 0,X GET WORD
  222.  LDA B 1,X
  223.  JMP NEXT
  224.  
  225. *-------------------------
  226. * #5  LOAD BYTE INDIRECT (ADDR IN REG)
  227. LDB1R LDX R1A
  228.  CLR A
  229.  LDA B 0,X GET BYTE
  230.  BPL LDB1RA
  231.  COM A
  232. LDB1RA JMP NEXT
  233.  
  234. *-------------------------
  235. * #6  STORE WORD @ ADDRESS
  236. ST1 LDX PC
  237.  LDX 0,X GET ADDRESS
  238.  STA A 0,X STORE WORD
  239.  STA B 1,X
  240.  JMP BUMP2
  241.  
  242. *-------------------------
  243. * #7  STORE BYTE @ ADDRESS
  244. STB1 LDX PC
  245.  LDX 0,X GET ADDR
  246.  STA B 0,X STORE BYTE
  247.  JMP BUMP2
  248.  
  249. *-------------------------
  250. * #8  STORE WORD @ ADDRESS ON STACK
  251. ST1SP TSX STACK TO INDEX
  252.  LDX 0,X GET ADDRESS
  253.  STA A 0,X STORE WORD
  254.  STA B 1,X
  255.  INS
  256.  INS POP STACK
  257.  JMP NEXT
  258.  
  259. *-------------------------
  260. * #9  STORE BYTE @ ADDRESS ON STACK
  261. STB1SP TSX
  262.  LDX 0,X
  263.  STA B 0,X STORE BYTE
  264.  INS POP ...
  265.  INS
  266.  JMP NEXT
  267.  
  268. *-------------------------
  269. * #10  PUSH WORD ON STACK
  270. PUSHR1 PSH B
  271.  PSH A
  272.  LDX PC
  273.  JMP NEXT2
  274.  
  275. *-------------------------
  276. * #11  SWAP REG AND TOP OF STACK
  277. EXG1 TSX
  278.  LDX 0,X GET VALUE ON STACK
  279.  STX R1A SAVE
  280.  INS
  281.  INS
  282.  PSH B
  283.  PSH A REG ON STACK
  284.  LDA A R1A NEW REG
  285.  LDA B R1B
  286.  LDX PC
  287.  JMP NEXT2
  288.  
  289. *-------------------------
  290. * #12  JUMP TO LABEL
  291. JMPL LDX PC
  292. JMP1 LDX 0,X GET ADDRESS (NEW PC)
  293.  JMP NEXT2
  294.  
  295. *-------------------------
  296. * #13  JUMP TO LABEL IF FALSE
  297. BRZL ORA A R1B SET FLAGS
  298.  BEQ JMPL IF REG=0 -- JUMP
  299.  JMP BUMP2 ELSE, PROCEED
  300.  
  301. *-------------------------
  302. * #14  CALL TO LABEL
  303. JSRL LDX PC
  304.  INX ADJUST RETURN
  305.  INX -- ADDRESS
  306.  DES
  307.  STS *+5 *** SELF MODIFYING CODE ***
  308.  DES
  309.  STX $FFFF PUSH RETURN ADDRESS
  310.  BRA JMPL
  311.  
  312. *-------------------------
  313. * #15  CALL TO TOP OF STACK
  314. JSRSP TSX POINT TO STACK
  315.  LDX 0,X GET ADDRESS (NEW PC)
  316.  INS POP
  317.  INS
  318.  LDA B PC+1 GET RETURN ADDRESS
  319.  PSH B
  320.  LDA B PC
  321.  PSH B SAVE RETURN ADDRESS
  322.  JMP NEXT2
  323.  
  324. *-------------------------
  325. * #16  RETURN TO CALLER
  326. RTSC TSX
  327.  LDX 0,X GET ADDRESS
  328.  INS POP
  329.  INS
  330.  JMP NEXT1
  331.  
  332. *-------------------------
  333. * #17  MODIFY THE STACK POINTER
  334. MODSP LDX PC
  335.  LDA A 0,X GET VALUE
  336.  LDA B 1,X
  337.  STS STEMP
  338.  ADD B STEMP+1 ADD STACK POINTER
  339.  ADC A STEMP
  340.  STA A STEMP
  341.  STA B STEMP+1
  342.  LDS STEMP NEW STACK POINTER
  343.  LDA A R1A RESTORE REGISTER
  344.  LDA B R1B
  345.  JMP BUMP2A
  346.  
  347. *---------------------------
  348. * #18  DOUBLE THE PRIMARY REGISTER
  349. DBL1 ASL B
  350.  ROL A
  351.  JMP NEXT
  352.  
  353. *---------------------------
  354. * #19  ADD REG AND TOP OF STACK (THEN POP)
  355. ADDS TSX
  356.  ADD B 1,X DO THE ADD
  357.  ADC A 0,X
  358.  JMP POPS POP & RETURN
  359.  
  360. *---------------------------
  361. * #20  SUBTRACT REG FROM TOP OF STACK
  362. SUBFST PUL A GET VALUE OFF STACK
  363.  PUL B
  364.  SUB B R1B SUBTRACT REGISTER
  365.  SBC A R1A
  366.  JMP NEXT
  367.  
  368. *---------------------------
  369. * #21  MULTIPLY TOP OF STACK BY REG (RESULT IN REG)
  370. MUL1 PSH B
  371.  PSH A REG ON STACK
  372.  LDA A #16
  373.  PSH A SET COUNTER
  374.  CLR A 
  375.  CLR B
  376.  TSX POINT TO DATA
  377.  
  378. M2 ROR 3,X SHIFT MULTIPLIER
  379.  ROR 4,X
  380.  DEC 0,X DONE ?
  381.  BMI M4
  382.  BCC M3
  383.  ADD B 2,X
  384.  ADC A 1,X
  385.  
  386. M3 ROR A
  387.  ROR B SHIFT RESULT
  388.  BRA M2 AND LOOP
  389.  
  390. M4 INS CLEAN STACK
  391.  INS
  392.  INS
  393.  PUL A GET RESULT
  394.  PUL B
  395.  JMP NEXT
  396.  
  397. *-----------------------------
  398. * #22  DIVIDE THE TOP OF STACK BY REG --- RESULT IN REG.
  399. DIV1 BSR BDIV DO THE BASIC DIVIDE
  400.  LDA A DFLAG GET SIGN FLAG
  401.  AND A #1 MASK OFF BIT ZERO
  402.  PUL A GET RESULT
  403.  PUL B
  404.  BEQ DIV1R
  405.  
  406. DIV1N BSR NEGATE NEGATE THE VALUE IN A,B
  407.  
  408. DIV1R JMP NEXT
  409.  
  410. *-----------------------------
  411. * #23  DIVIDE TOP OF STACK BY REG --- REMAINDER IN REG
  412. MOD BSR BDIV
  413.  INS CLEAN STACK
  414.  INS
  415.  PSH A TEMP SAVE
  416.  LDA A DFLAG GET SIGN FLAG
  417.  BPL MOD1
  418.  COM A
  419.  
  420. MOD1 AND A #1 MASK OFF BIT 0
  421.  PUL A
  422.  BNE DIV1N IF BIT 0 SET, NEGATE
  423.  
  424.  JMP NEXT
  425.  
  426. *****************************************************
  427. *   BASIC 16 BIT DIVIDE ROUTINE
  428. * ENTER WITH: DIVIDEND ON STACK
  429. *             DIVISOR IN A,B
  430. * EXIT WITH:  QUOTIENT ON STACK
  431. *             REMAINDER IN A,B
  432. *             SIGN FLAG IN DFLAG
  433. *
  434. BDIV CLR DFLAG
  435.  TST A CHECK DIVISOR SIGN
  436.  BPL BDIV1
  437.  
  438.  INC DFLAG ADJUST SIGN FLAG
  439.  BSR NEGATE TAKE ABSOLUTE VALUE
  440.  
  441. BDIV1 PSH B FORCE ON STACK
  442.  PSH A
  443.  LDA A #17 BIT COUNTER
  444.  PSH A
  445.  TSX POINT TO DATA
  446.  LDA A 5,X CHECK SIGN
  447.  BPL BDIV2 -- OF DIVIDEND
  448.  
  449.  COM DFLAG ADJUST FLAG
  450.  LDA B 6,X
  451.  BSR NEGATE
  452.  STA A 5,X
  453.  STA B 6,X
  454.  
  455. BDIV2 CLR A
  456.  CLR B
  457.  
  458. * MAIN DIVIDE LOOP (UNSIGNED)
  459.  
  460. UDIV1 CMP A 1,X
  461.  BHI UDIV3
  462.  BCS UDIV2
  463.  CMP B 2,X
  464.  BCC UDIV3
  465.  
  466. UDIV2 CLC
  467.  BRA UDIV4
  468.  
  469. UDIV3 SUB B 2,X
  470.  SBC A 1,X
  471.  SEC
  472.  
  473. UDIV4 ROL 6,X
  474.  ROL 5,X
  475.  DEC 0,X
  476.  BEQ UDIV5
  477.  
  478.  ROL B
  479.  ROL A
  480.  BCC UDIV1
  481.  BRA UDIV3
  482.  
  483. UDIV5 INS
  484.  INS
  485.  INS
  486.  RTS
  487.  
  488. *----------------------------------------
  489. * NEGATE THE VALUE IN A,B
  490. NEGATE COM A
  491.  COM B
  492.  ADD B #1
  493.  ADC A #0
  494.  RTS
  495.  
  496. *----------------------------------
  497. * #24  INCLUSIVE OR THE TOP OF STACK AND REG.
  498. ORS TSX
  499.  ORA A 0,X
  500.  ORA B 1,X
  501. POPS INS POP THE STACK
  502.  INS
  503.  JMP NEXT
  504.  
  505. *----------------------------------
  506. * #25  EXCLUSIVE OR ......
  507. XORS TSX
  508.  EOR A 0,X
  509.  EOR B 1,X
  510.  BRA POPS
  511.  
  512. *----------------------------------
  513. * #26  AND .........
  514. ANDS TSX
  515.  AND A 0,X
  516.  AND B 1,X
  517.  BRA POPS
  518.  
  519. *----------------------------------
  520. * #27  ARITH. SHIFT RIGHT THE TOP OF STACK
  521. ASRS TSX
  522.  AND B #$1F MAX REASONABLE SHIFT
  523.  BEQ ASRS2
  524.  
  525. ASRS1 ASR 0,X
  526.  ROR 1,X
  527.  DEC B
  528.  BNE ASRS1
  529.  
  530. ASRS2 PUL A GET THE RESULT
  531.  PUL B
  532.  JMP NEXT
  533.  
  534. *--------------------------------
  535. * #28  ARITH. SHIFT LEFT THE TOP OF STACK
  536. ASLS TSX
  537.  AND B #$1F
  538.  BEQ ASRS2
  539.  
  540. ASLS1 ASL 1,X
  541.  ROL 0,X
  542.  DEC B
  543.  BNE ASLS1
  544.  
  545.  BRA ASRS2
  546.  
  547. *--------------------------------
  548. * #29  NEGATE THE REGISTER
  549. NEGR BSR NEGATE
  550.  JMP NEXT
  551.  
  552. *--------------------------------
  553. * #30  COMPLEMENT THE REGISTER
  554. NOTR COM A
  555.  COM B
  556.  JMP NEXT
  557.  
  558. *--------------------------------
  559. * #31  ADD 1 TO REG
  560. INCR ADD B #1
  561.  ADC A #0
  562.  JMP NEXT
  563.  
  564. *--------------------------------
  565. * #32 SUBTRACT 1 FROM REG
  566. DECR SUB B #1
  567.  SBC A #0
  568.  JMP NEXT
  569.  
  570. *****************************************************
  571. *
  572. *   BASIC COMPARE INSTRUCTION SUBROUTINE
  573. *   Compare the top of Stack to Register and set Condition codes
  574. *
  575. *  Signed compare -- Carry reflects the sign of difference
  576. *         (set means: top of stack < A,B )
  577. *
  578. SCMP TSX
  579.  LDA A 2,X GET TOP OF STACK
  580.  LDA B 3,X
  581.  SUB B R1B SET CONDITION
  582.  SBC A R1A ... FLAGS
  583.  BPL STCMP1 SKIP IF PLUS
  584.  
  585.  STA B R1B TEMP SAVE
  586.  ORA A R1B SET/RESET ZERO FLAG
  587.  SEC AND SET CARRY
  588.  RTS
  589.  
  590. STCMP1 STA B R1B
  591.  ORA A R1B
  592.  CLC CLEAR THE CARRY
  593.  RTS
  594. *
  595. *  Unsigned compare, Carry set if top of stack < A,B
  596. *
  597. BCMP TSX
  598.  LDA A 2,X GET TOP OF STACK
  599.  LDA B 3,X
  600.  CMP A R1A CHECK TOP BYTE
  601.  BNE BCMP1
  602.  CMP B R1B
  603. BCMP1 RTS
  604.  
  605.  
  606. *-------------------------------
  607. * #33  TEST FOR EQUALITY
  608. ZEQ BSR BCMP
  609.  BEQ TRUE
  610.  BRA FALSE
  611.  
  612. *-------------------------------
  613. * #34  TEST FOR NOT-EQUAL
  614. ZNE BSR BCMP
  615.  BNE TRUE
  616.  BRA FALSE
  617.  
  618. *-------------------------------
  619. * #35  TEST FOR LESS THAN
  620. ZLT BSR SCMP
  621.  BCS TRUE
  622.  BRA FALSE
  623.  
  624. *-------------------------------
  625. * #36  TEST FOR LESS THAN OR EQUAL
  626. ZLE BSR SCMP
  627.  BLS TRUE
  628.  BRA FALSE
  629.  
  630. *-------------------------------
  631. * #37  TEST FOR GREATER THAN
  632. ZGT BSR SCMP
  633.  BHI TRUE
  634.  BRA FALSE
  635.  
  636. *-------------------------------
  637. * #38  TEST FOR GREATER THAN OR EQUAL
  638. ZGE BSR SCMP
  639.  BCC TRUE
  640.  BRA FALSE
  641.  
  642. *-------------------------------
  643. * #39 TEST FOR LESS THAN (UNSIGNED)
  644. ULT BSR BCMP
  645.  BCS TRUE
  646.  BRA FALSE
  647.  
  648. *-------------------------------
  649. * #40  TEST FOR LESS THAN OR EQUAL (UNSIGNED)
  650. ULE BSR BCMP
  651.  BLS TRUE
  652.  BRA FALSE
  653.  
  654. *-------------------------------
  655. * #41  TEST FOR GREATER THAN (UNSIGNED)
  656. UGT BSR BCMP
  657.  BHI TRUE
  658.  BRA FALSE
  659.  
  660. *------------------------------
  661. * #42  TEST FOR GREATER THAN OR EQUAL (UNSIGNED)
  662. UGE BSR BCMP
  663.  BCC TRUE
  664.  
  665. FALSE CLR B RETURN FALSE
  666.  BRA TRUE1
  667.  
  668. TRUE LDA B #1 RETURN TRUE
  669.  
  670. TRUE1 CLR A
  671.  JMP POPS POP STACK AND PROCEED
  672.  
  673. *-------------------------------------
  674. * #43  SWITCH TO EXECUTABLE (ASSEMBLY) CODE
  675. ASMC LDX PC POINT TO CODE
  676.  JMP 0,X GO EXECUTE IT
  677.  
  678. ***********************************************************
  679. *
  680. *        RUN-TIME SUBROUTINE LIBRARY
  681. *
  682. ***********************************************************
  683.  
  684. *   fopen(file-name, "type")
  685. *   Open a File..........
  686. fopen FCB 86 SWITCH TO INLINE CODE
  687.  LDX #FCBTBL-2 POINT TO FCB ADDRESSES TABLE
  688.  
  689. NXTFIL INX
  690.  INX
  691.  STX FCBPTR SAVE POINTER
  692.  LDX 0,X GET FCB ADDRESS
  693.  BEQ NOFILE
  694.  TST 2,X BUSY ?
  695.  BEQ GODOIT NO,
  696.  LDX FCBPTR ELSE, NEXT IN LINE
  697.  BRA NXTFIL
  698.  
  699. NOFILE LDX #FMSG POINT TO MESSAGE
  700.  JSR PSTRNG PRINT IT
  701.  JMP WARMS --AND BACK TO FLEX
  702.  
  703. GODOIT STX R1A SAVE FCB ADDRESS
  704.  TSX
  705.  LDX 4,X POINT TO FILE NAME
  706.  STX $AC14 SAVE IN LINE BUFFER POINTER
  707.  LDX R1A GET FCB POINTER
  708.  JSR GETFIL GET FILE SPEC
  709.  BCS FERROR REPORT IF ERROR
  710.  TSX
  711.  LDX 2,X POINT TO MODE
  712.  LDA A #1
  713.  LDA B #'w' OPEN FOR WRITE
  714.  CMP B 0,X  -- ????
  715.  BEQ OWRITE YES,
  716.  
  717. *  DEFAULT TO OPEN FOR READ
  718.  
  719.  LDX R1A POINT TO FCB
  720.  STA A 0,X STORE IN FCB
  721.  JSR FMS DO THE OPEN
  722.  BEQ FEXIT
  723.  
  724. FERROR JSR RPTERR REPORT THE TYPE OF ERROR
  725.  JSR FMSCLS CLOSE ALL OPEN FILES
  726.  JMP WARMS RETURN TO FLEX
  727.  
  728. * OK, OPEN FOR WRITE
  729.  
  730. OWRITE LDA A #2 CODE FOR WRITE
  731.  LDX R1A GET FCB ADDRESS
  732.  STA A 0,X
  733.  JSR FMS TRY AN OPEN
  734.  BEQ FEXIT IF SUCCESSFULL--DONE
  735.  
  736.  LDA A 1,X GET ERROR STATUS
  737.  CMP A #3 ALREADY EXISTS ?
  738.  BNE FERROR NO--SOME OTHER ERROR
  739.  
  740.  LDA A #12 DELETE THE EXISTING FILE
  741.  STA A 0,X
  742.  JSR FMS
  743.  BNE FERROR
  744.  LDA A 36,X FIX NAME
  745.  STA A 4,X
  746.  BRA OWRITE
  747.  
  748. FEXIT TSX
  749.  LDX 2,X POINT TO MODE AGAIN
  750.  LDA B 1,X GET OPTIONAL CHAR
  751.  CMP B #'u UNCOMPRESSED (BINARY) ???
  752.  BNE FEXIT1 NO, SO SKIP
  753.  
  754.  LDA B #$FF
  755.  LDX R1A
  756.  STA B 59,X SET FLAG IN FCB
  757.  
  758. FEXIT1 LDA A R1A RETURN THE FCB POINTER
  759.  LDA B R1B
  760.  
  761.  JMP RTSC RETURN TO INTERPRETER
  762.  
  763. *-------------------------------------------------
  764.  
  765. *  fclose(unit)
  766. *  CLOSE A FILE
  767. fclose FCB 86 SWITCH TO IN-LINE
  768.  TSX
  769.  LDX 2,X POINT TO FCB
  770.  LDA A #4 CLOSE CODE
  771.  STA A 0,X
  772.  JSR FMS DO THE CLOSE
  773.  BNE FERROR
  774.  CLR A
  775.  LDA B #1 OK CODE
  776.  JMP RTSC RETURN TO INTERPRETER....
  777.  
  778. *--------------------------------------------------
  779.  
  780. *  getc(unit)  read a byte from file
  781. *        return a char, else a -1 if EOF
  782.  
  783. getc FCB 86
  784.  TSX
  785.  LDX 2,X POINT TO FCB
  786.  JSR FMS GET BYTE
  787.  BEQ CHOK
  788.  
  789.  LDA A 1,X GET ERROR
  790.  CMP A #8 EOF ?
  791.  BNE FERROR
  792.  
  793.  LDA A #$FF LOAD EOF INDICATOR
  794.  
  795. CHOK TAB  COPY CHAR IN A
  796. CHOK1 CLR A
  797.  TST B
  798.  BPL GETC1
  799.  
  800.  COM A  SIGN EXTEND
  801.  
  802. GETC1 JMP RTSC
  803.  
  804. *----------------------------------------------
  805.  
  806. *  putc(c,unit)   write to file
  807.  
  808. putc FCB 86
  809.  TSX
  810.  LDA A 5,X GET CHAR
  811.  LDX 2,X GET FCB ADDR
  812.  PSH A SAVE CHAR
  813.  JSR FMS
  814.  BNE FERROR
  815.  PUL B GET CHAR
  816.  BRA CHOK1
  817.  
  818. *-----------------------------------------------
  819. FMSG FCC 'NO MORE FILES MAY BE OPENED.'
  820.  FCB $0D,$0A,4
  821. *-----------------------------------------------
  822.  
  823. *   getchar()    get a char from standard input
  824.  
  825. getchar FCB 86
  826.  JSR GETCHR
  827.  CMP A #$0D CR ???
  828.  BEQ GETCH1 SKIP IF TRUE
  829.  
  830.  CMP A #$1A COMPARE TO CNTRL-Z (EOF)
  831.  BNE CHOK NO
  832.  LDA B #$FF YES...
  833.  BRA CHOK1 RETURN -1
  834.  
  835. GETCH1 LDA A #$0A LOAD A LF
  836.  JSR PUTCHR ECHO IT
  837.  LDA B #$0D
  838.  BRA CHOK1
  839.  
  840. *-----------------------------------------------
  841.  
  842. *   putchar(c)   write a char to standard output
  843.  
  844. putchar FCB 86
  845.  TSX
  846.  LDA A 3,X GET THE CHAR
  847.  PSH A SAVE CHAR
  848.  CMP A #$0D IS IT A CR ?
  849.  BEQ PUTC2 YES, SKIP
  850.  JSR PUTCHR ELSE, OUTPUT IT
  851. PUTC1 PUL B RESTORE CHAR
  852.  BRA CHOK1
  853.  
  854. PUTC2 JSR PCRLF OUTPUT CR/LF PAIR
  855.  BRA PUTC1
  856.  
  857. *----------------------------------------------
  858.  
  859. *   gets(buffer)  get a char string into buffer
  860.  
  861. gets FCB 86
  862.  TSX
  863.  LDX 2,X GET START OF BUFFER
  864.  CLR B
  865.  
  866. GETS1 JSR GETCHR READ A CHAR
  867.  CMP A $AC00 BACKSPACE ?
  868.  BNE GETS2
  869.  
  870.  LDA A #$20
  871.  JSR PUTCHR
  872.  LDA A #$08
  873.  JSR PUTCHR
  874.  TST B  BEGINNING OF LINE ?
  875.  BEQ GETS1 YES,
  876.  
  877.  DEC B ELSE,
  878.  DEX ADJUST LINE POINTER
  879.  BRA GETS1
  880.  
  881. GETS2 CMP A $AC01 DELETE LINE CHAR ?
  882.  BNE GETS3
  883.  
  884.  LDA A #$0D CR...
  885.  JSR PUTCHR
  886.  LDA A #$0A LF...
  887.  JSR PUTCHR
  888.  BRA gets+1 GO TRY AGAIN....
  889.  
  890. GETS3 STA A 0,X GOOD CHAR--STORE IN BUFFER
  891.  INX AND BUMP POINTER
  892.  INC B AND COUNTER
  893.  
  894.  CMP A #$0D IS IT A CR ?
  895.  BNE GETS1 NO
  896.  
  897.  DEX
  898.  CLR 0,X MARK END OF STRING WITH A NULL
  899.  STX R1A SAVE POINTER VALUE
  900.  LDA A R1A GET IT INTO WORK
  901.  LDA B R1B .. REG
  902.  TSX
  903.  SUB B 3,X RETURN LENGTH
  904.  SBC A 2,X --OF BUFFER
  905. GETS4 JMP RTSC
  906.  
  907. *----------------------------------------------
  908. *  puts(string)  print a string on the terminal
  909. puts FCB 86
  910.  TSX
  911.  LDX 2,X GET STRING ADDRESS
  912. PLOOP LDA A 0,X GET THE CHAR
  913.  BEQ GETS4 IF END OF STRING--QUIT
  914.  CMP A #'\ SPECIAL CHAR ?
  915.  BNE PLOOP1 NO, SKIP
  916.  BSR SPECIAL YES, INTERPRET
  917.  CMP A #$0D IS IT A CR (NEWLINE)
  918.  BNE PLOOP1 NO--SKIP
  919.  JSR PCRLF YES PRINT CR/LF PAIR
  920.  BRA PLOOP2
  921. PLOOP1 JSR PUTCHR PRINT IT
  922. PLOOP2 INX BUMP POINTER
  923.  BRA PLOOP
  924.  
  925.  
  926. *  This subroutine interprets the backslash (\) sequence.
  927.  
  928. SPECIAL INX
  929.  LDA A 0,X GET NEXT CHAR
  930.  CMP A #'b
  931.  BNE SP1
  932.  LDA A #08 BACKSPACE
  933.  BRA SPEXIT
  934. SP1 CMP A #'f
  935.  BNE SP2
  936.  LDA A #$0C FORMFEED
  937.  BRA SPEXIT
  938. SP2 CMP A #'n
  939.  BNE SP3
  940.  LDA A #$0D NEWLINE
  941.  BRA SPEXIT
  942. SP3 CMP A #'\ BACKSLASH
  943.  BEQ SPEXIT
  944.  CMP A #'' SINGLE QUOTE
  945.  BEQ SPEXIT
  946.  CMP A #'" DOUBLE QUOTE
  947.  BEQ SPEXIT
  948.  CMP A #'x START OF HEX SEQUENCE
  949.  BEQ SPHEX
  950.  CMP A #'0 OCTAL SEQUENCE ?
  951.  BLT SPERR
  952.  CMP A #'7
  953.  BLE SPOCTAL YES
  954.  
  955. SPERR DEX BACKUP THE POINTER
  956.  LDA A 0,X RESTORE CHAR
  957. SPEXIT RTS RETURN
  958.  
  959. SPOCTAL LDA B #3
  960.  STA B DFLAG SAVE COUNTER
  961.  CLR B
  962.  
  963. SPOCT1 SUB A #'0 CONVERT TO DIGIT
  964.  ASL B SHIFT ACCUM
  965.  ASL B
  966.  ASL B
  967.  ABA ADD IN NEW DIGIT
  968.  TAB SAVE
  969.  DEC DFLAG
  970.  BEQ SPBYE IF MAX COUNT--EXIT
  971.  INX
  972.  LDA A 0,X GET NEXT CHAR
  973.  CMP A #'0 VERIFY IF OCTAL
  974.  BLT SPFINI
  975.  CMP A #'7
  976.  BLE SPOCT1 YES, CONTINUE
  977.  
  978. SPFINI DEX BACKUP
  979. SPBYE TBA GET ACCUM CHAR
  980.  RTS
  981.  
  982. SPHEX LDA B #2
  983.  STA B DFLAG
  984.  CLR B
  985.  
  986. SPHEXL INX
  987.  LDA A 0,X GET NEXT CHAR
  988.  CMP A #'0 VERIFY IF HEX
  989.  BLT SPFINI ..
  990.  CMP A #'9 ..
  991.  BLE SPHEX2 ..
  992.  CMP A #'A ..
  993.  BLT SPFINI ..
  994.  CMP A #'F ..
  995.  BLE SPHEX1 ..
  996.  CMP A #'a ..
  997.  BLT SPFINI ..
  998.  CMP A #'f ..
  999.  BGT SPFINI ..
  1000.  SUB A #$20 YES IT IS HEX
  1001. SPHEX1 SUB A #7
  1002. SPHEX2 SUB A #'0
  1003.  ASL B
  1004.  ASL B
  1005.  ASL B
  1006.  ASL B
  1007.  ABA
  1008.  TAB
  1009.  DEC DFLAG
  1010.  BEQ SPBYE MAX COUNT REACHED ???
  1011.  BRA SPHEXL NO, LOOP
  1012.  
  1013.  
  1014. *----------------------------------------------
  1015. *
  1016. *
  1017. *       Test if given char is alpha     *
  1018. * isalpha(c)
  1019. *       char c;
  1020. * {     c=c&127;
  1021. *       return(((c>='a')&(c<='z'))|
  1022. *               ((c>='A')&(c<='Z'))|
  1023. *               (c='_'));
  1024. * }
  1025. *
  1026. isalpha FCB     86      switch to assembly
  1027.         TSX
  1028.         LDA B   3,X     get char
  1029.         BSR     alPHA
  1030.         JMP     RTSC
  1031. *
  1032. *---------------------------------------------
  1033. *       Test if given char is numeric   *
  1034. *
  1035. * isdigit(c)
  1036. *       char c;
  1037. * {     c=c&127;
  1038. *       return((c>='0')&(c<='9'));
  1039. * }
  1040. *
  1041. isdigit FCB     86
  1042.         TSX
  1043.         LDA B   3,X
  1044.         BSR     nuMERIC
  1045.         JMP     RTSC
  1046. *
  1047. *----------------------------------------------
  1048. *       Test if given char is alphanumeric      *
  1049. *
  1050. * isalnum(c)
  1051. *       char c;
  1052. * {     return((alpha(c)|(numeric(c)));
  1053. * }
  1054. *
  1055. isalnum FCB     86
  1056.         TSX
  1057.         LDA B   3,X     get char
  1058.         BSR     alPHA   check if alpha
  1059.         TSX
  1060.         PSH B           save result
  1061.         LDA B   3,X     get char again
  1062.         BSR     nuMERIC check if decimal
  1063.         TSX
  1064.         ORA B   0,X     fix flag
  1065.         INS             clean stack
  1066.         JMP     RTSC
  1067. *
  1068. *
  1069. alPHA   CLR A
  1070.         AND B   #$7F
  1071.         CMP B   #'a
  1072.         BLT     alPHA1
  1073.         CMP B   #'z
  1074.         BLE     alYES
  1075. alPHA1  CMP B   #'A
  1076.         BLT     alPHA2
  1077.         CMP B   #'Z
  1078.         BLE     alYES
  1079. alPHA2  CMP B   #'_
  1080.         BEQ     alYES
  1081. *
  1082. alNO    CLR B
  1083.         RTS
  1084. *
  1085. alYES   LDA B   #1
  1086.         RTS
  1087. *
  1088. *
  1089. nuMERIC CLR A
  1090.         AND B   #$7F
  1091.         CMP B   #'0
  1092.         BLT     alNO
  1093.         CMP B   #'9
  1094.         BLE     alYES
  1095.         BRA     alNO
  1096. *
  1097. *-----------------------------------------------
  1098. *  islower(c)
  1099. *       char c;        returns TRUE if c is lower case alpha,
  1100. *                        FALSE otherwise.
  1101. *
  1102. islower FCB 86 SWITCH TO IN-LINE
  1103.  TSX
  1104.  LDA B 3,X GET CHAR
  1105.  AND B #$7F
  1106.  CLR A
  1107.  CMP B #'a
  1108.  BLT ISNO
  1109.  CMP B #'z
  1110.  BLE ISYES
  1111. *
  1112. ISNO CLR B
  1113.  JMP RTSC    RETURN FALSE
  1114. *
  1115. ISYES LDA B #1
  1116.  JMP RTSC RETURN TRUE
  1117. *
  1118. *----------------------------------------------
  1119. *  isupper(c)
  1120. *      char c;      return TRUE if c is upper case alpha.
  1121. *
  1122. isupper FCB 86
  1123.  TSX
  1124.  LDA B 3,X
  1125.  AND B #$7F
  1126.  CLR A
  1127.  CMP B #'A
  1128.  BLT ISNO
  1129.  CMP B #'Z
  1130.  BLE ISYES
  1131.  BRA ISNO
  1132. *
  1133. *-----------------------------------------------
  1134. *  isspace(c)
  1135. *      char c;       return TRUE if a "white space" char
  1136. *
  1137. isspace FCB 86
  1138.  TSX
  1139.  LDA B 3,X GET CHAR
  1140.  AND B #$7F
  1141.  CLR A
  1142.  CMP B #'   SPACE ?
  1143.  BEQ ISYES
  1144.  CMP B #$0D  CR ???
  1145.  BEQ ISYES
  1146.  CMP B #$0A  LF ???
  1147.  BEQ ISYES
  1148.  CMP B #$09  HOR TAB ???
  1149.  BEQ ISYES
  1150.  BRA ISNO
  1151. *
  1152. *----------------------------------------------
  1153. *  toupper(c)
  1154. *      char c;   make c an upper case char if lower
  1155. *                          case alpha
  1156. *
  1157. toupper FCB 86
  1158.  TSX
  1159.  LDA B 3,X
  1160.  LDA A 2,X
  1161.  BNE TOUPP1  SKIP IF MSB'S NOT ZERO
  1162.  CMP B #'a
  1163.  BLT TOUPP1
  1164.  CMP B #'z
  1165.  BGT TOUPP1
  1166.  SUB B #$20  CONVERT TO UPPER CASE
  1167. TOUPP1 JMP RTSC
  1168. *
  1169. *---------------------------------------------
  1170. *  tolower(c)
  1171. *      char c;   convert to lower case if upper case alpha.
  1172. *
  1173. tolower FCB 86
  1174.  TSX
  1175.  LDA B 3,X
  1176.  LDA A 2,X
  1177.  BNE TOLOW1
  1178.  CMP B #'A
  1179.  BLT TOLOW1
  1180.  CMP B #'Z
  1181.  BGT TOLOW1
  1182.  ADD B #$20 CONVERT TO LOWER CASE
  1183. TOLOW1 JMP RTSC
  1184. *
  1185. *---------------------------------------------
  1186. *  strclr(s,n)
  1187. *      char *s;  int n;  clear a string of n bytes.
  1188. *
  1189. strclr FCB 86
  1190.  TSX
  1191.  LDA A 2,X GET LENGTH OF STRING
  1192.  LDA B 3,X
  1193.  LDX  4,X POINT TO STRING
  1194.  TST B
  1195.  BEQ SCLR2
  1196.  
  1197. SCLR1 CLR 0,X
  1198.  INX
  1199.  DEC B
  1200.  BNE SCLR1
  1201. SCLR2 TST A
  1202.  BEQ SCLR3
  1203.  DEC A
  1204.  BRA SCLR1
  1205.  
  1206. SCLR3 JMP RTSC
  1207. *
  1208. *-----------------------------------------------
  1209. *  return the length of a string
  1210. *
  1211. * strlen(s)
  1212. *       char *s;
  1213. * {     char *t;
  1214. *       t=s;
  1215. *       while (*s) s++;
  1216. *       return (s-t);
  1217. * }
  1218. *
  1219. strlen  FCB     86
  1220.         TSX
  1221.         LDX     2,X     point to string
  1222.         CLR A           preset counter
  1223.         CLR B
  1224. *
  1225. strlLP  TST     0,X     look for NULL
  1226.         BEQ     strlRT  found !!
  1227.         INX
  1228.         ADD B   #1      bump counter
  1229.         ADC A   #0
  1230.         BRA     strlLP
  1231. *
  1232. strlRT  JMP     RTSC
  1233. *
  1234. *------------------------------------------------
  1235. *  strcpy(s1,s2)
  1236. *      char *s1, *s2;    copy s2 into s1.
  1237. *
  1238. strcpy FCB 86
  1239.  TSX
  1240.  LDX 4,X POINT TO S1
  1241.  STX X1TMP SAVE POINTER
  1242.  TSX
  1243.  LDX 2,X POINT TO S2
  1244.  
  1245. SCPY1 LDA B 0,X
  1246.  INX
  1247.  STX X2TMP
  1248.  LDX X1TMP
  1249.  STA B 0,X
  1250.  BEQ SCLR3  END OF STRING ???
  1251.  INX
  1252.  STX X1TMP
  1253.  LDX X2TMP
  1254.  BRA SCPY1
  1255. *
  1256. *------------------------------------------------
  1257. *  strcat(s1,s2)
  1258. *      char *s1, *s2;   s2 is concatenated onto s1.
  1259. *
  1260. strcat FCB 86
  1261.  TSX
  1262.  LDX 2,X
  1263.  STX X2TMP SAVE POINTER TO S2
  1264.  TSX
  1265.  LDX 4,X POINT TO S1
  1266.  
  1267. SCAT1 TST 0,X LOOK FOR END OF STRING
  1268.  BEQ SCAT2
  1269.  INX
  1270.  BRA SCAT1
  1271.  
  1272. SCAT2 STX X1TMP SAVE POINTER
  1273.  LDX X2TMP
  1274.  LDA B 0,X
  1275.  INX
  1276.  STX X2TMP
  1277.  LDX X1TMP
  1278.  STA B 0,X
  1279.  BEQ SCAT3
  1280.  INX
  1281.  BRA SCAT2
  1282.  
  1283. SCAT3 JMP RTSC
  1284. *
  1285. *--------------------------------------------
  1286. *  strcmp(s1,s2)
  1287. *        char *s1, *s2;       returns:   0  if s1 = s2
  1288. *                                       <0  if s1 < s2
  1289. *                                       >0  if s1 > s2
  1290. *
  1291. strcmp FCB 86
  1292.  TSX
  1293.  LDX 2,X POINT TO S2
  1294.  STX X2TMP
  1295.  TSX
  1296.  LDX 4,X POINT TO S1
  1297.  
  1298. SCMP1 LDA A 0,X GET S1 CHAR
  1299.  BEQ SCMP3
  1300.  INX
  1301.  STX X1TMP
  1302.  LDX X2TMP
  1303.  LDA B 0,X
  1304.  BEQ SCMP2
  1305.  SBA COMPARE BY SUBTRACTING
  1306.  BNE SCMP3
  1307.  INX
  1308.  STX X2TMP
  1309.  LDX X1TMP
  1310.  BRA SCMP1
  1311.  
  1312. SCMP2 CLR A
  1313.  
  1314. SCMP3 TAB
  1315.  BMI SCMP4
  1316.  CLR A
  1317.  JMP RTSC
  1318.  
  1319. SCMP4 LDA A #$FF SIGN EXTEND
  1320.  JMP RTSC
  1321. *
  1322. *
  1323. *****************************************************
  1324. *
  1325. HERE EQU *   END OF INTERPRETER
  1326.  END
  1327.