home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG030.ARK / BASIC.PLM < prev    next >
Text File  |  1984-04-29  |  39KB  |  997 lines

  1. BASCOM:
  2. DO;
  3.  
  4.          /* BASIC - E COMPILER MODIFIED FOR RESIDENT OPERATION
  5.          BY GARY A. KILDALL, DIGITAL RESEARCH, PACIFIC GROVE, CA.
  6.          VERSION 1.4  - ORIGINAL DISTRIBUTION BY EUBANKS, NPS,
  7.          VERSION 1.5  - FIXES UNINITIALIZED STORAGE PROBLEMS
  8.                            WFCB(32) = 0,  RFCB(12) = 0, CONT = 0
  9.                            HASHTABLE = 0...0
  10.                         ALLOWS $ PARAMETERS IN CALL, RATHER THAN PROGRAM
  11.           */
  12.  
  13.     DECLARE JMPTOMAIN (3) BYTE DATA(0C3H,0,0); /* FILLED WITH DDT */
  14.  
  15.  
  16.         /*
  17.          *********************************************************
  18.          *                                                       *
  19.          *                   BASIC-E COMPILER                    *
  20.          *                                                       *
  21.          *             U. S. NAVY POSTGRADUATE SCHOOL            *
  22.          *                  MONTEREY, CALIFORNIA                 *
  23.          *                                                       *
  24.          *             WRITTEN BY GORDON EUBANKS, JR.            *
  25.          *                                                       *
  26.          *                    CPM VERSION 1.4                    *
  27.          *                                                       *
  28.          *                     DECEMBER 1976                     *
  29.          *                                                       *
  30.          *********************************************************
  31.         */
  32.  
  33.         /*
  34.          *********************************************************
  35.          *                                                       *
  36.          *    THE BASIC-E COMPILER IS DIVIDED INTO THE FOLLOW-   *
  37.          *     ING MAJOR SECTIONS:                               *
  38.          *            (1) GLOBAL DECLERATIONS AND LITERAL        *
  39.          *                DEFINITIONS                            *
  40.          *            (2) SYSTEM INPUT OUTPUT ROUTINES AND       *
  41.          *                ASSOCIATED VARIABLE DECLERATIONS       *
  42.          *            (3) SCANNER                                *
  43.          *            (4) SYMBOL TABLE ROUTINES                  *
  44.          *            (5) PARSER AND CODE GENERATION             *
  45.          *                                                       *
  46.          *    BASIC-E REQUIRES A SOURCE PROGRAM AVAILABLE ON     *
  47.          *     AN INPUT DEVICE AND WILL WRITE A BINARY OUTPUT    *
  48.          *     FILE WHICH MAY BE EXECUTED BY THE RUN TIME        *
  49.          *     MONITOR.  THE SOURCE MUST BE READ TWICE.          *
  50.          *     THE NORMAL OUTPUT DEVICE IS THE CONSOLE.          *
  51.          *                                                       *
  52.          *     MODIFICATION OF THE COMPILER FOR OTHER OPERATING  *
  53.          *     SYSTEMS WILL REQUIRE MODIFICATIONS TO SECTION     *
  54.          *     (2) AND IN SECTION 1 REDEFINITION OF LITERALS IN  *
  55.          *     SECTIONS "SYSTEM PARAMETERS WHICH MAY REQUIRE     *
  56.          *     MODIFICATION BY USERS" AND "EXTERNAL ENTRY        *
  57.          *     POINTS".  OTHER CHANGES SHOULD NOT BE REQUIRED    *
  58.          *                                                       *
  59.          *********************************************************
  60.         */
  61.  
  62.  
  63.         /*
  64.          **********************************************************
  65.          *                                                        *
  66.          *          ****     SECTION   1     ****                 *
  67.          *                                                        *
  68.          **********************************************************
  69.         */
  70.         /*
  71.          *********************************************************
  72.          *                                                       *
  73.          *                   GLOBAL LITERALS                     *
  74.          *                                                       *
  75.          *********************************************************
  76.         */
  77.  
  78. $INCLUDE(:F1:BASCOM.LIT)
  79.  
  80.         /*
  81.          *********************************************************
  82.          *                                                       *
  83.          *                EXTERNAL ENTRY POINTS                  *
  84.          *    THESE ENTRY POINTS ALLOW INTERFACING WITH CP/M     *
  85.          *                                                       *
  86.          *********************************************************
  87.         */
  88.  
  89. DECLARE
  90.         BDOS    LIT            '05H',  /* ENTRY POINT TO CP/M */
  91.         PARMS   LIT            '6DH',  /* $ PARAMETERS */
  92.         BOOT    LIT            '0H';   /* RETURN TO SYSTEM */
  93.  
  94.  
  95. MON1: PROCEDURE(F,A);
  96.     DECLARE F BYTE, A ADDRESS;
  97.     /* PATCHED WITH JMP 0005 */
  98.     L: GO TO L;
  99.     END MON1;
  100.  
  101. MON2: PROCEDURE(F,A) BYTE;
  102.     DECLARE F BYTE, A ADDRESS;
  103.     /* PATCHED WITH JMP 0005 */
  104.     L: GO TO L;
  105.     RETURN 0;
  106.     END MON2;
  107.  
  108. MON3: PROCEDURE PUBLIC;
  109.     /* USED TO RETURN TO CP/M */
  110.     DECLARE A ADDRESS; A = BOOT;
  111.     CALL A;
  112.     END MON3;
  113.  
  114.  
  115.         /*
  116.          *********************************************************
  117.          *                                                       *
  118.          *                  GLOBAL VARIABLES                     *
  119.          *                                                       *
  120.          *********************************************************
  121.         */
  122. DECLARE
  123.         PASS1  BYTE PUBLIC INITIAL(TRUE),     /* PASS1 FLAG */
  124.         PASS2  BYTE PUBLIC INITIAL(FALSE),      /* PASS2 FLAG */
  125.                /*
  126.                   COMPILER TOGGLES
  127.                */
  128.         LISTPROD     BYTE PUBLIC INITIAL(FALSE),
  129.         LISTSOURCE   BYTE PUBLIC INITIAL(FALSE),
  130.         DEBUGLN      BYTE PUBLIC INITIAL(FALSE),
  131.         LOWERTOUPPER BYTE INITIAL(TRUE),
  132.         NOINTFILE    BYTE INITIAL(FALSE),
  133.         LSTFLAG      BYTE INITIAL(FALSE),  /* LST DEVICE IF 'F' */
  134.         ERRSET       BYTE INITIAL(FALSE),
  135.         ERRORCOUNT   ADDRESS PUBLIC INITIAL(0),
  136.         COMPILING    BYTE PUBLIC,
  137.         DATACT       ADDRESS PUBLIC, /* COUNTS SIZE OF DATA AREA */
  138.  
  139.  
  140.   /*   FLAGS USED DURING CODE GENERATION */
  141.         FORSTMT      BYTE PUBLIC,
  142.         RANDOMFILE   BYTE PUBLIC,
  143.         FILEIO       BYTE PUBLIC,
  144.         INPUTSTMT    BYTE PUBLIC,
  145.         GOSUBSTMT    BYTE PUBLIC,
  146.  
  147.   /*   THE FOLLOWING GLOBAL VARIABLES ARE USED BY THE SCANNER      */
  148.  
  149.         TOKEN     BYTE PUBLIC,  /* TYPE OF TOKEN JUST SCANNED */
  150.         SUBTYPE   BYTE PUBLIC,  /* SUBTYPE OF CURRENT TOKEN */
  151.         FUNCOP    BYTE PUBLIC,  /* IF TOKEN FUNC THEN THIS IS FUNC NUMBER */
  152.         HASHCODE  BYTE PUBLIC,  /* HASH VALUE OF CURRENT TOKEN */
  153.         NEXTCHAR  BYTE PUBLIC,  /* CURRENT CHARACTER FROM GETCHAR */
  154.         ACCUM(IDENTSIZE)     BYTE PUBLIC,  /* HOLDS CURRENT TOKEN */
  155.         ACCLEN BYTE PUBLIC AT(.ACCUM(0)),   /* ACCUM 0 IS LENGTH */
  156.         CONT    BYTE PUBLIC,  /* INDICATES ACCUM WAS FULL, STILL MORE */
  157.         COLUMN  BYTE INITIAL(0),  /* CURRENT COLUMN */
  158.  
  159.             /*
  160.              **************************************************
  161.              *                                                *
  162.              *  THE FOLLOWING LITERAL DEFINITIONS ESTABLISH   *
  163.              *  MNEMONIC NAMES FOR THE TOKENS WHICH ARE THE   *
  164.              *  OUTPUT OF THE LALR PARSER PROGRAM.            *
  165.              *                                                *
  166.              **************************************************
  167.             */
  168.         POUND LIT '12', LPARN LIT '02', RPARN  LIT '05',
  169.         ASTRK LIT '04', TPLUS LIT '03', TMINUS LIT '07',
  170.         LESST LIT '01', TCOLIN LIT '11', SCOLN  LIT '06',
  171.         EXPON LIT '14', EQUAL LIT '13', GTRT   LIT '10',
  172.         TDATA LIT '99', TAND  LIT '24', TCR    LIT '23',
  173.         TELSE LIT '34', TDEF  LIT '25', TDIM   LIT '26',
  174.         TFOR  LIT '28', TEND  LIT '27', TFILE  LIT '35',
  175.         TIF   LIT '17', TGOSB LIT '43', TGOTO  LIT '36',
  176.         TNEXT LIT '37', TINPT LIT '44', TLET   LIT '29',
  177.         SLASH LIT '08', TNOT  LIT '30', TON    LIT '20',
  178.         TOR   LIT '21', TPRNT LIT '45', TREAD  LIT '38',
  179.         TREST LIT '48', TRETN LIT '46', TSTEP  LIT '39',
  180.         TSTOP LIT '40', TTHEN LIT '41', TTO    LIT '22',
  181.         FUNCT LIT '53', TGEQ  LIT '15', TSUB   LIT '32',
  182.         TLEQ  LIT '18', COMMA LIT '09', TGO    LIT '16',
  183.         TNE   LIT '19', TCLOS LIT '42', TXOR   LIT '33',
  184.         TOUT  LIT '31', TIRN LIT '51',  STRING LIT '50',
  185.         IDENTIFIER LIT '52',            FLOATPT LIT '49',
  186.         UDFUNCT LIT '54',               TREM LIT '0';
  187.  
  188.         /*
  189.          *********************************************************
  190.          *                                                       *
  191.          *       ****       SECTION    2       ****              *
  192.          *                                                       *
  193.          *      SYSTEM DEPENDENT ROUTINES AND VARIABLES          *
  194.          *                                                       *
  195.          *            THE FOLLOWING ROUTINES ARE USED            *
  196.          *            BY THE COMPILER TO ACCESS DISK             *
  197.          *            FILES AND THE CONSOLE.  THESE              *
  198.          *            ROUTINES ASSUME THE USE OF THE             *
  199.          *            CP/M DISK OPERATING SYSTEM.                *
  200.          *                                                       *
  201.          *      THE FCB'S ARE USED BY THE SYSTEM TO MAINTAIN     *
  202.          *      INFORMATION ON OPEN FILES.  THEY ARE ONLY USED   *
  203.          *      BY PROCEDURES IN THIS SECTION.  THE BUFFERS      *
  204.          *      AND POINTERS TO THE BUFFERS ARE USED BY THE      *
  205.          *      REMAINDER OF THE PROGRAM BUT THEIR SIZE MAY      *
  206.          *      BE VARIED TO SUIT THE DISK SYSTEM BEING USED     *
  207.          *                                                       *
  208.          *********************************************************
  209.         */
  210.  
  211. DECLARE
  212.         PARMLIST(9) BYTE INITIAL('         '),  /* $ PARAMS SAVED HERE */
  213.         RFCBADDR    ADDRESS INITIAL(5CH),
  214.             /* NOTE: CP/M PROVIES 5CH AS FCB AREA AND 80H AS A
  215.                      BUFFER FOR PROGRAM USE */
  216.         RFCB BASED RFCBADDR(33)    BYTE,  /* SOURCE FCB */
  217.         WFCB(33)                   BYTE  /* INTERMEDIATE FILE FCB */
  218.                                    INITIAL(0,'        ','INT',0,0,0,0),
  219.         SBLOC                      ADDRESS INITIAL(80H),
  220.         SOURCEBUFF BASED SBLOC(SOURCERECSIZE)BYTE,  /* SOURCE BUFFER */
  221.         SOURCEPTR       BYTE INITIAL(SOURCERECSIZE), /* BUFFER INDEX */
  222.         CURSOURCERECSIZE BYTE INITIAL(SOURCERECSIZE),
  223.         DISKOUTBUFF(INTRECSIZE)      BYTE,
  224.         BUFFPTR            BYTE INITIAL(255), /* BUFFER INDEX */
  225.         LINEBUFF(CONBUFFSIZE)        BYTE,  /* CONSOLE OUT BUFFER */
  226.         LINEPTR            BYTE INITIAL(0), /* BUFFER INDEX */
  227.         LINENO ADDRESS PUBLIC,    /* CURRENT LINE NUMBER */
  228.         SEPARATOR BYTE   PUBLIC INITIAL(COLIN);
  229.  
  230.           DECLARE
  231.                   PCHAR    LIT    '2',  /* CHAR TO CONSOLE */
  232.                   PBUFF    LIT    '9',  /* BUFFER TO CONSOLE */
  233.                   RCHAR    LIT    '1',  /* CHAR FROM CONSOLE */
  234.                   RBUFF    LIT   '10',  /* BUFFER FROM CONSOLE */
  235.                   OFILE    LIT   '15',  /* OPEN FILE */
  236.                   CFILE    LIT   '16',   /* CLOSE FILE */
  237.                   DFILE    LIT   '19',  /* DELETE FILE */
  238.                   RFILE    LIT   '20',  /* READ FILE */
  239.                   WFILE    LIT   '21',  /* WRITE FILE */
  240.                   MFILE    LIT   '22',  /* MAKE FILE */
  241.                   SDMA     LIT   '26',  /* SET DMA */
  242.                   FILEERR  LIT  '255',  /* ERROR RTN CODE */
  243.                   FILEEOF  LIT    '1';  /* EOF RTN CODE */
  244.  
  245. MOVE: PROCEDURE (SOURCE,DEST,COUNT) PUBLIC;
  246.     DECLARE
  247.             SOURCE ADDRESS,
  248.             DEST   ADDRESS,
  249.             COUNT     BYTE,
  250.             SCHAR BASED SOURCE BYTE,
  251.             DCHAR BASED DEST   BYTE;
  252.  
  253.     DO WHILE(COUNT := COUNT -1) <> 255;
  254.          DCHAR = SCHAR;
  255.          SOURCE = SOURCE + 1;
  256.          DEST = DEST + 1;
  257.          END;
  258.     RETURN;
  259. END MOVE;
  260.  
  261. FILL: PROCEDURE (DEST,CHAR,COUNT) PUBLIC;
  262.       /* MOVE CHAR TO A N TIMES */
  263.     DECLARE
  264.             DEST        ADDRESS,
  265.             CHAR        BYTE,
  266.             COUNT       BYTE,
  267.             DCHAR       BASED     DEST     BYTE;
  268.      DO WHILE (COUNT := COUNT -1) <> 255;
  269.           DCHAR = CHAR;
  270.           DEST = DEST + 1;
  271.           END;
  272.     RETURN;
  273. END FILL;
  274.  
  275.  
  276. CHAROUT: PROCEDURE(CHAR);
  277.     DECLARE CHAR BYTE;
  278.     IF LSTFLAG THEN /* GO TO THE LIST DEVICE */
  279.         CALL MON1(5,CHAR); ELSE CALL MON1(2,CHAR);
  280.     END CHAROUT;
  281.  
  282. PRINTCHAR: PROCEDURE(CHAR);
  283.     DECLARE CHAR BYTE;
  284.     /* CHECK FOR TABS AND END OF LINE */
  285.     IF CHAR = TAB THEN /* EXPAND TO NEXT COLUMN */
  286.         DO WHILE ((COLUMN := COLUMN + 1) AND 7) <> 0;
  287.         CALL CHAROUT(' ');
  288.         END; ELSE
  289.         DO; COLUMN = COLUMN + 1; CALL CHAROUT(CHAR);
  290.         IF CHAR = LF THEN COLUMN = 0;
  291.         END;
  292. END PRINTCHAR;
  293.  
  294. PRINT: PROCEDURE(A) PUBLIC;
  295.     DECLARE A ADDRESS;
  296.     DECLARE MSG BASED A BYTE;
  297.         DO WHILE MSG <> '$';
  298.         CALL PRINTCHAR(MSG);
  299.         A = A + 1;
  300.         END;
  301. END PRINT;
  302.  
  303.  
  304. DISKERR: PROCEDURE;
  305.     CALL PRINT(.('DE    $'));
  306.     CALL MON3;  /* RETURN TO SYSTEM */
  307.     RETURN;
  308. END DISKERR;
  309.  
  310. OPEN$SOURCEFILE: PROCEDURE;
  311.     /*  SETS UP THE FCB FOR THE SOURCE PROGRAM
  312.         WHICH MUST BE OF TYPE 'BAS' AND THEN OPENS
  313.         THE FILE.  CP/M PUTS THE NAME USED AS A
  314.         PARAMETER WHEN THE COMPILER IS EXECUTED, AT
  315.         5CH.
  316.     */
  317.  
  318.     CALL MOVE(.('BAS'),RFCBADDR+9,3);
  319.     RFCB(32),RFCB(12) = 0;
  320.     IF MON2(OFILE,RFCBADDR) = FILEERR THEN
  321.          DO;
  322.               CALL PRINT(.('NS $'));
  323.               CALL MON3;  /* RETURN TO SYSTEM */
  324.          END;
  325. END OPEN$SOURCEFILE;
  326.  
  327.  
  328. REWIND$SOURCE$FILE: PROCEDURE PUBLIC;
  329.     /* CP/M DOES NOT REQUIRE ANY ACTION PRIOR TO REOPENING */
  330.     RETURN;
  331. END REWIND$SOURCE$FILE;
  332.  
  333.  
  334. CLOSE$INT$FILE: PROCEDURE PUBLIC;
  335.     IF MON2(CFILE,.WFCB) = FILEERR THEN
  336.          CALL DISKERR;
  337. END CLOSE$INT$FILE;
  338.  
  339. SETUP$INT$FILE: PROCEDURE PUBLIC;
  340.      /*  MAKES A NEW FILE */
  341.     IF NOINTFILE THEN  /* ONLY MAKE FILE IF THIS TOGGLE IS OFF */
  342.          RETURN;
  343.     CALL MOVE(.RFCB,.WFCB,9);
  344.     CALL MON1(DFILE,.WFCB);
  345.     IF MON2(MFILE,.WFCB) = FILEERR THEN
  346.          CALL DISKERR;
  347.     WFCB(32) = 0; /* ZERO NEXT RECORD */
  348.  END SETUP$INT$FILE;
  349.  
  350. READ$SOURCE$FILE: PROCEDURE BYTE;
  351.     DECLARE DCNT BYTE;
  352.     IF(DCNT := MON2(RFILE,RFCBADDR)) > FILEEOF THEN
  353.          CALL DISKERR;
  354.     RETURN DCNT; /* ZERO IF READ ELSE 1 IF EOF - ERRORS > 1 */
  355. END READ$SOURCE$FILE;
  356.  
  357.  
  358. WRITE$INT$FILE: PROCEDURE PUBLIC;
  359.     IF NOINTFILE THEN
  360.          RETURN;
  361.     CALL MON1(SDMA,.DISKOUTBUFF);
  362.     IF MON2(WFILE,.WFCB) <> 0 THEN
  363.          CALL DISKERR;
  364.     CALL MON1(SDMA,80H); /* RESET DMA ADDRESS */
  365. END WRITE$INT$FILE;
  366.  
  367.  
  368. CRLF: PROCEDURE PUBLIC;
  369.      CALL PRINTCHAR(EOLCHAR);
  370.      CALL PRINTCHAR(LF);
  371.     RETURN;
  372. END CRLF;
  373.  
  374.  
  375. PRINT$DEC: PROCEDURE(VALUE) PUBLIC;
  376.     /*
  377.         CONVERTS VALUE TO A DECIMAL NUMBER WHICH IS PRINTED
  378.         ON THE CONSOLE.  USED FOR LINENUMBERING STATEMENTS
  379.         AND TO PRINT PRODUCTIONS.
  380.     */
  381.     DECLARE
  382.             VALUE ADDRESS,
  383.             I     BYTE,
  384.             FLAG  BYTE,
  385.             COUNT BYTE;
  386.     DECLARE DECIMAL(4) ADDRESS DATA(1000,100,10,1);
  387.     FLAG = FALSE;
  388.     DO I = 0 TO 3;
  389.          COUNT = 30H;
  390.          DO WHILE VALUE >= DECIMAL(I);
  391.               VALUE = VALUE - DECIMAL(I);
  392.               FLAG = TRUE;
  393.               COUNT = COUNT + 1;
  394.          END;
  395.          IF FLAG OR (I >= 3) THEN
  396.               CALL PRINTCHAR(COUNT);
  397.          ELSE
  398.               CALL PRINTCHAR(' ');
  399.     END;
  400.     RETURN;
  401. END PRINTDEC;
  402.  
  403.  
  404. SETFLAGS: PROCEDURE PUBLIC;
  405.     /*
  406.        RESET COMPILER FLAGS USED DURING PARSING
  407.     */
  408.       RANDOMFILE,FILEIO,
  409.       INPUTSTMT, FORSTMT, GOSUBSTMT = FALSE;
  410. END SETFLAGS;
  411.  
  412.  
  413.         /*
  414.          *********************************************************
  415.          *                                                       *
  416.          *     THE FOLLOWING ROUTINE GENERATES THE INTERMEDIATE  *
  417.          *     LANGUAGE FILE. EMIT IS THE ONLY ROUTINE TO        *
  418.          *     ACTUALLY WRITE TO THE DISK.  GENERATE, EMITDAT,   *
  419.          *     AND EMITCON CALL EMIT.                            *
  420.          *                                                       *
  421.          *********************************************************
  422.         */
  423.  
  424.  
  425.  
  426. EMIT: PROCEDURE(OBJCODE) PUBLIC;
  427.     DECLARE OBJCODE BYTE;
  428.     IF (BUFFPTR:=BUFFPTR + 1) >= INTRECSIZE THEN /* WRITE TO DISK */
  429.          DO;
  430.               CALL WRITE$INT$FILE;
  431.               BUFFPTR = 0;
  432.          END;
  433.     DISKOUTBUFF(BUFFPTR) = OBJCODE;
  434.     RETURN;
  435. END EMIT;
  436.  
  437.  
  438.         /*
  439.          *********************************************************
  440.          *                                                       *
  441.          *           ***     SCANNER SECTION     ***             *
  442.          *                                                       *
  443.          *********************************************************
  444.         */
  445.  
  446. CLEAR$LINE$BUFF: PROCEDURE;
  447.     CALL FILL(.LINEBUFF,' ',CONBUFFSIZE);
  448. END CLEAR$LINE$BUFF;
  449.  
  450.  
  451. LIST$LINE: PROCEDURE(LENGTH);
  452.     DECLARE
  453.             LENGTH BYTE,
  454.             I      BYTE;
  455.     CALL PRINT$DEC(LINENO);
  456.     CALL PRINT$CHAR(SEPARATOR);
  457.     CALL PRINT$CHAR(' ');
  458.     DO I = 0 TO LENGTH;
  459.          CALL PRINT$CHAR(LINEBUFF(I));
  460.          END;
  461.     CALL CRLF;
  462.     CALL CLEAR$LINE$BUFF;
  463.     SEPARATOR = COLIN;
  464. END LIST$LINE;
  465.  
  466.         /*
  467.          **********************************************************
  468.          *                                                        *
  469.          *    GETCHAR SETS THE GLOBAL VARIABLE NEXTCHAR TO THE    *
  470.          *    NEXT SOURCEFILE CHARACTER AND RETURNS NEXTCHAR TO   *
  471.          *    THE CALLING ROUTINE.                                *
  472.          *                                                        *
  473.          *    TABS ARE REPLACED WITH A BLANK AND IF EITHER        *
  474.          *    LISTSOURCE IS TRUE OR AN ERROR HAS OCCURED LINES    *
  475.          *    ARE OUTPUT TO THE CONSOLE.                          *
  476.          *                                                        *
  477.          **********************************************************
  478.         */
  479.  
  480. GETCHAR: PROCEDURE BYTE PUBLIC;
  481.     DECLARE ADDEND(*) BYTE
  482.          DATA ('END',EOLCHAR,LF); /*TO ADD END IF LEFT OFF */
  483.     NEXT$SOURCE$CHAR: PROCEDURE BYTE;
  484.          RETURN SOURCEBUFF(SOURCEPTR);
  485.     END NEXT$SOURCE$CHAR;
  486.  
  487.     CHECKFILE: PROCEDURE BYTE;
  488.          /*
  489.               CHECKFILE MAINTAINS THE SOURCE BUFFER FULL AND
  490.               CHECKS FOR END OF FILE ON THE SOURCE FILE.
  491.               IF A LINE FEED IS FOUND IT IS SKIPPED.
  492.               IF END OF FILE IS DETECTED THEN TRUE IS RETURNED
  493.               ELSE FALSE IS RETURNED.
  494.          */
  495.          DO FOREVER;  /* ALLOW US TO SKIP LINE FEEDS */
  496.               IF (SOURCEPTR := SOURCEPTR + 1) >= CURSOURCERECSIZE THEN
  497.                    DO;
  498.                         SOURCEPTR = 0;
  499.                         IF READ$SOURCE$FILE = FILEEOF THEN
  500.                              RETURN TRUE;
  501.                    END;
  502.               IF (NEXTCHAR := NEXT$SOURCE$CHAR) <> LF THEN
  503.                    RETURN FALSE;
  504.          END;  /* OF DO FOREVER */
  505.     END CHECKFILE;
  506.  
  507.     IF CHECKFILE OR (NEXTCHAR = EOFFILLER)  THEN
  508.                    DO; /* EOF REACHED */
  509.                         CALL MOVE(.ADDEND,SBLOC,5);
  510.                         SOURCEPTR = 0;
  511.                         NEXTCHAR = NEXT$SOURCE$CHAR;
  512.                    END;
  513.        IF LINEPTR < CONBUFFSIZE THEN
  514.               LINEBUFF(LINEPTR := LINEPTR + 1) = NEXTCHAR;  /* OUTPUT LINE */
  515.          IF NEXTCHAR = EOLCHAR THEN
  516.               DO;
  517.                    LINENO = LINENO + 1;
  518.                    IF LISTSOURCE OR ERRSET THEN
  519.                         CALL LISTLINE(LINEPTR - 1);  /* NOT EOLCHAR */
  520.                    LINEPTR = 0;
  521.               END;
  522.     IF NEXTCHAR = TAB THEN
  523.          NEXTCHAR = ' ';  /* ONLY NEED REPLACE WITH 1 BLANK  */
  524.     RETURN NEXTCHAR;
  525. END GETCHAR;
  526.  
  527.  
  528. GETNOBLANK: PROCEDURE;
  529.     DO WHILE((GETCHAR = ' ') OR (NEXTCHAR = EOFFILLER));
  530.          END;
  531.     RETURN;
  532. END GETNOBLANK;
  533.  
  534.  
  535.  
  536.  
  537. CHECK$CONTINUATION: PROCEDURE;
  538.     /*
  539.         CHECK FOR CONTINUATION CHAR. IF FOUND SET NEXTCHAR
  540.         TO FIRST CHARACTER ON NEXT LINE.  IT THEN LOOKS TO
  541.         THE PARSER AS IF IT WAS ALL ONE LINE.
  542.     */
  543.     IF NEXTCHAR = CONTCHAR THEN
  544.          DO;
  545.               DO WHILE GETCHAR <> EOLCHAR;
  546.                    END;
  547.               CALL GETNOBLANK;
  548.          END;
  549.     RETURN;
  550. END CHECK$CONTINUATION;
  551.  
  552.  
  553.         /*
  554.          **********************************************************
  555.          *                                                        *
  556.          *    ERROR IS THE COMPILER ERROR HANDLING ROUTINE        *
  557.          *    IF AN ERROR IS DETECTED WHILE PARSING A STATEMENT   *
  558.          *    THE REMAINDER OF THE STATEMENT IS SKIPPED AND THE   *
  559.          *    STATEMENT IS WRITTEN ON THE CONSOLE FOLLOWED BY A   *
  560.          *    TWO LETTER DISCRIPTION OF THE ERROR. AN UP ARROR    *
  561.          *    INDICATES WHERE IN THE LINE THE ERROR WAS DETECTED  *
  562.          *    THE PARSER IS RESET AND COMPILATION CONTINUES WITH  *
  563.          *    THE NEXT STATEMENT.                                 *
  564.          *                                                        *
  565.          **********************************************************
  566.         */
  567.  
  568. ERROR: PROCEDURE(ERRCODE) PUBLIC;
  569.        DECLARE
  570.                ERRCODE ADDRESS,
  571.                POINTER BYTE;
  572.     POINTER = LINEPTR + 2;
  573.     IF PASS2 THEN
  574.          ERRSET = TRUE;  /* SO SOURCE LINE WILL BE LISTED */
  575.     IF TOKEN <> TCR THEN
  576.          DO;  /* SKIP REMAINDER OF LINE */
  577.               DO WHILE NEXTCHAR <> EOLCHAR;
  578.                    CALL CHECK$CONTINUATION;
  579.                    NEXTCHAR = GETCHAR;
  580.                    END;
  581.               CALL GET$NO$BLANK;
  582.          END;
  583.     IF PASS2 THEN
  584.          DO;       /* PRINT ERROR MESSAGE */
  585.               ERRORCOUNT = ERRORCOUNT + 1;
  586.               CALL PRINTCHAR(HIGH(ERRCODE));
  587.               CALL PRINTCHAR(LOW(ERRCODE));
  588.               CALL PRINTCHAR(QUESTIONMARK);
  589.               DO WHILE(POINTER:=POINTER - 1) >= 1;
  590.                    CALL PRINTCHAR(' ');
  591.                    END;
  592.               CALL PRINTCHAR(UPARROW);
  593.               CALL CRLF;
  594.          END;
  595.     ERRSET, COMPILING = FALSE;
  596.     CALL SETFLAGS;
  597.     RETURN;
  598.   END ERROR;
  599.  
  600.         /*
  601.          *********************************************************
  602.          *                                                       *
  603.          *    INITIALIZE$SCANNER SETS NEXTCHAR TO THE FIRST      *
  604.          *    NON-BLANK CHARACTER ON THE INPUT FILE AND          *
  605.          *    INITIALIZES THE OUTPUTLINE COUNTER AND POINTER     *
  606.          *                                                       *
  607.          *    INITIALIZE$SCANNER IS CALLED AT THE BEGINNING OF   *
  608.          *    PASS ONE AND PASS TWO.                             *
  609.          *                                                       *
  610.          *********************************************************
  611.         */
  612. IN$SCANNER: PROCEDURE PUBLIC;
  613.     DECLARE COUNT BYTE;
  614.     DECLARE I BYTE;
  615.     IF PASS1 THEN /* GET PARAMETER LIST */
  616.         CALL MOVE(PARMS,.PARMLIST,8); /* LAST BLANK IS LEFT UNFILLED */
  617.     CALL OPEN$SOURCEFILE;
  618.     CONT,COLUMN,LINENO,LINEPTR = 0;
  619.     CALL CLEAR$LINE$BUFF;
  620.     SOURCEPTR = SOURCERECSIZE;
  621.     SEPARATOR = COLIN;
  622.     CALL GETNOBLANK;
  623.     IF PARMLIST(0) = '$' THEN
  624.          DO; I = 0;
  625.               DO WHILE (COUNT := PARMLIST(I:=I+1)) <> ' ';
  626.                    IF(COUNT := COUNT - 'A') <= 5 THEN
  627.                         DO CASE COUNT;
  628.                              LISTPROD = TRUE;
  629.                              LISTSOURCE = FALSE;
  630.                              NOINTFILE = TRUE;
  631.                              LOWERTOUPPER = FALSE;
  632.                              DEBUGLN = TRUE;
  633.                              LSTFLAG = TRUE;
  634.                         END; /* OF CASE */
  635.               END;
  636.          END;
  637. END IN$SCANNER;
  638.  
  639.  
  640.         /*
  641.          *********************************************************
  642.          *                                                       *
  643.          *    THE SCANNER ACCEPTS INPUT CHARACTERS FROM THE      *
  644.          *    SOURCE FILE RETURNING TOKENS TO THE PARSER.        *
  645.          *    CONVERSION TO UPPERCASE IS PERFORMED WHEN SCAN-    *
  646.          *    NING IDENTIFIERS UNLESS LOWERTOUPPER IS FALSE.     *
  647.          *    BLANKS ARE IGNORED.  EACH TOKEN IS PLACED IN       *
  648.          *    ACCUM.  ACCLEN   IS THE LENGTH OF THE TOKEN.       *
  649.          *    THE TOKEN IS HASHCODED BY SUMMING EACH ASCII       *
  650.          *    CHARACTER MODULO HASHTBLSIZE AND THE RESULT IS     *
  651.          *    RETURNED IN HASHCODE.  SUBTYPE AND FUNCOP ARE      *
  652.          *    SET IF THE TOKEN IS A PREDEFINED FUNCTION.         *
  653.          *    REM AND DATA STATEMENTS ARE HANDLED COMPLETELY     *
  654.          *    BY THE SCANNER. IF THE RESERVED WORD REM OR        *
  655.          *    REMARK IS DETECTED THE INPUT IS SCANNED UNTIL      *
  656.          *    THE END OF THE CURRENT INPUT LINE IS LOCATED.      *
  657.          *    THE NEXT TOKEN (A CARRIAGE RETURN) IS THEN         *
  658.          *    SCANNED AND RTURNED. DATA STATEMENTS ARE SIMILAR   *
  659.          *    EXCEPT THE DATA IS WRITTEN OUT USEING EMITDAT      *
  660.          *                                                       *
  661.          *********************************************************
  662.         */
  663. SCANNER: PROCEDURE PUBLIC;
  664.  
  665.         /*
  666.          **********************************************************
  667.          *                                                        *
  668.          *    THE FOLLOWING UTILITY PROCEDURES ARE USED BY THE    *
  669.          *    SCANNER.                                            *
  670.          *                                                        *
  671.          **********************************************************
  672.         */
  673.  
  674.     PUTINACCUM: PROCEDURE;
  675.          IF NOT CONT THEN
  676.               DO;
  677.                    ACCUM(ACCLEN := ACCLEN + 1) = NEXTCHAR;
  678.                    HASHCODE = (HASHCODE + NEXTCHAR) AND HASHMASK;
  679.                    IF ACCLEN >= (IDENTSIZE - 1) THEN
  680.                         CONT = TRUE;
  681.               END;
  682.          RETURN;
  683.     END PUTINACCUM;
  684.  
  685.  
  686.     PUTANDGET: PROCEDURE;
  687.          CALL PUTINACCUM;
  688.          CALL GETNOBLANK;
  689.          RETURN;
  690.     END PUTANDGET;
  691.  
  692.  
  693.     PUTANDCHAR: PROCEDURE;
  694.          CALL PUTINACCUM;
  695.          NEXTCHAR = GETCHAR;
  696.          RETURN;
  697.     END PUTANDCHAR;
  698.  
  699.  
  700.     NUMERIC: PROCEDURE BYTE;
  701.          RETURN(NEXTCHAR - '0') <= 9;
  702.     END NUMERIC;
  703.  
  704.     LOWERCASE: PROCEDURE BYTE;
  705.          RETURN (NEXTCHAR >= 61H) AND (NEXTCHAR <= 7AH);
  706.     END LOWER$CASE;
  707.  
  708.  
  709.     DECIMALPT: PROCEDURE BYTE;
  710.          RETURN NEXTCHAR = '.';
  711.     END DECIMALPT;
  712.  
  713.  
  714.     CONV$TO$UPPER: PROCEDURE;
  715.          IF LOWERCASE AND LOWERTOUPPER THEN
  716.               NEXTCHAR = NEXTCHAR AND 5FH;
  717.          RETURN;
  718.     END CONV$TO$UPPER;
  719.  
  720.  
  721.     LETTER: PROCEDURE BYTE;
  722.         CALL CONV$TO$UPPER;
  723.          RETURN ((NEXTCHAR - 'A') <= 25) OR LOWERCASE;
  724.     END LETTER;
  725.  
  726.  
  727.     ALPHANUM: PROCEDURE BYTE;
  728.          RETURN NUMERIC OR LETTER OR DECIMALPT;
  729.     END ALPHANUM;
  730.  
  731.  
  732.     SPOOLNUMERIC: PROCEDURE;
  733.          DO WHILE NUMERIC;
  734.               CALL PUTANDCHAR;
  735.               END;
  736.          RETURN;
  737.     END SPOOLNUMERIC;
  738.  
  739.  
  740.     SETUP$NEXT$CALL: PROCEDURE;
  741.          IF NEXTCHAR = ' ' THEN
  742.               CALL GETNOBLANK;
  743.          CONT = FALSE;
  744.          RETURN;
  745.     END SETUP$NEXT$CALL;
  746.  
  747. EMITDAT: PROCEDURE(OBJCODE);
  748.      /*
  749.        WRITES DATA STATEMENTS DURING PASS2 AND
  750.        COUNTS SIZE OF DATA AREA.
  751.      */
  752.     DECLARE OBJCODE BYTE;
  753.     DATACT = DATACT + 1;
  754.     IF PASS2 THEN
  755.          CALL EMIT(OBJCODE);
  756.     RETURN;
  757. END EMITDAT;
  758.  
  759.         /*
  760.          *********************************************************
  761.          *                                                       *
  762.          *      LOOKUP IS CALLED BY THE SCANNER WITH THE         *
  763.          *       PRINTNAME OF THE CURRENT TOKEN IN               *
  764.          *      THE ACCUMULATOR.  LOOKUP DETERMINES IF THIS      *
  765.          *      TOKEN IS A RESERVED WORD AND  SETS THE           *
  766.          *      VALUE OF TOKEN.  IF THE TOKEN IS A PREDEFINED    *
  767.          *      FUNCTION THEN THE SUBTYPE AND FUNCOP ARE ALSO    *
  768.          *      SET.                                             *
  769.          *      THE RESERVED WORD TABLE IS DIVIDED INTO 7        *
  770.          *      TABLES FOR RESERVED WORDS OF LENGTH 1 TO 7.      *
  771.          *      THE FOLLOWING VECTORS ARE ALSO USED:             *
  772.          *          TK - TOKEN ASSOCIATED WITH RESERVED WORD     *
  773.          *          OFFSET - INDEX INTO LNG VECTOR FOR A GIVEN   *
  774.          *                   R/W LENGTH                          *
  775.          *          COUNT - NUMBER OF R/W OF A GIVEN LENGTH      *
  776.          *          TKOS - INDEX INTO TK FOR A GIVEN R/W LENGTH  *
  777.          *          ST - SPECIAL DATA FOR PREDEFINED FUNCTIONS   *
  778.          *                                                       *
  779.          *      PREDEFINED FUNCTIONS HAVE TOKEN VALUES >64.      *
  780.          *      THIS NUMBER BECOMES THE FUNCOP AND THE TOKEN     *
  781.          *      IS FUNCT.  FUNCOP IS THE MACHINE CODE FOR THE    *
  782.          *      PARTICULAR PREDEFINED FUNCTION.                  *
  783.          *                                                       *
  784.          *********************************************************
  785.         */
  786.  
  787.     LOOKUP: PROCEDURE BYTE;
  788.  
  789.          DECLARE MAXRWLNG LIT '9';  /* MAX LENGTH OF A RESERVED WORD */
  790.  
  791.          DECLARE LNG1(*) BYTE
  792.              DATA(EOLCHAR,'<','(','+','*',')','-',',','=','/',
  793.                            ';','>',':',POUNDSIGN,UPARROW),  /*  15  */
  794.                  LNG2(*) BYTE
  795.                       DATA('IF','TO','GO','ON','OR','EQ','LT','GT',
  796.                            'LE','GE','NE'),       /*  11  */
  797.                  LNG3(*) BYTE
  798.                        DATA('FOR','LET','REM','DIM','DEF','NOT','AND',
  799.                            'TAN','SIN','COS','SQR','TAB','LOG','LEN',
  800.                            'FRE','ATN','ABS','EXP','INT','END','POS',
  801.                            'RND','SGN','INP','ASC','VAL','XOR','SUB',
  802.                             'OUT'),
  803.                                       /*  29  */
  804.                  LNG4(*) BYTE DATA('THEN','READ','GOTO','ELSE','NEXT',
  805.                            'STOP','DATA','FILE','CHR$','MID$',
  806.                            'STEP','STR$','COSH','SINH'),  /*  14  */
  807.                  LNG5(*) BYTE DATA('PRINT','INPUT','GOSUB','CLOSE',
  808.                                      'LEFT$'),           /*  5  */
  809.                  LNG6(*) BYTE DATA('RETURN','RIGHT$','REMARK'),  /* 3 */
  810.                  LNG7(*) BYTE DATA('RESTORE'),  /*  1  */
  811.                  LNG9(*) BYTE DATA('RANDOMIZE'),
  812.                  TK(*) BYTE  DATA(0,TCR,LESST,LPARN,TPLUS,ASTRK,RPARN,TMINUS,
  813.                            COMMA,EQUAL,SLASH,SCOLN,GTRT,TCOLIN,POUND,
  814.                            EXPON,        /* LNG 1 */
  815.                            TIF,TTO,TGO,TON,TOR,EQUAL,LESST,GTRT,TLEQ,
  816.                            TGEQ,TNE,   /* LNG2 */
  817.                            TFOR,TLET,TREM,TDIM,TDEF,TNOT,TAND,
  818.                            72,69,70,73,74,78,84,76,71,65,75,
  819.                            66,TEND,79,67,68,80,81,88,TXOR,TSUB,TOUT,
  820.                                        /* LNG 3 */
  821.                            TTHEN,TREAD,TGOTO,TELSE,TNEXT,TSTOP,TDATA,
  822.                            TFILE,82,85,TSTEP,87,89,90,  /* LNG 4 */
  823.                            TPRNT,TINPT,TGOSB,TCLOS,83,       /* LNG 5 */
  824.                            TRETN,86,TREM,  /* LNG 6 */
  825.                            TREST,TIRN),
  826.                OFFSET(*) BYTE DATA(0,0,15,37,124,180,205,223,230,230),
  827.                COUNT(*) BYTE DATA(0,15,11,29,14,5,3,1,0,1),
  828.                TKOS(*) BYTE DATA(0,0,15,26,55,69,74,77,78,78),
  829.                ST(*) BYTE DATA(1,1,0,1,1,1,1,1,1,1,1,0,0,1,0,1,
  830.                            5,65,70,5,71,70,65,5,1,1);
  831.  
  832.          DECLARE
  833.                  PTR              ADDRESS,
  834.                  FIELD BASED PTR (1) BYTE,
  835.                  I                BYTE;
  836.  
  837.          COMPARE: PROCEDURE BYTE;
  838.               DECLARE I BYTE;
  839.               I = 0;
  840.               DO WHILE (FIELD(I) = ACCUM(I := I + 1)) AND I <= ACCLEN;
  841.                    END;
  842.               RETURN I > ACCLEN;
  843.          END COMPARE;
  844.  
  845.          IF ACCLEN > MAXRWLNG THEN
  846.               RETURN FALSE;
  847.          PTR = OFFSET(ACCLEN) + .LNG1;
  848.          DO I = 1 TO COUNT(ACCLEN);
  849.               IF COMPARE THEN
  850.                    DO;
  851.  
  852.                         IF((TOKEN := TK(TKOS(ACCLEN) + I)) > 64) AND
  853.                            (TOKEN <> TDATA) THEN
  854.                              DO;
  855.                                   SUBTYPE = ST(TOKEN - 65);
  856.                                   FUNCOP = TOKEN;
  857.                                   TOKEN = FUNCT;
  858.                              END;
  859.                         RETURN TRUE;
  860.                    END;
  861.               PTR = PTR + ACCLEN;
  862.               END;
  863.          RETURN FALSE;
  864.     END LOOKUP;
  865.  
  866.  
  867.     DO FOREVER;  /* TO HANDLE REM, DAT AND CONTINUATION */
  868.     ACCLEN, HASHCODE, TOKEN, SUBTYPE = 0;
  869.         /* FIRST CASE - IS THIS A STRING OR THE CONTINUATION
  870.            OF A STRING?  (ONLY STRINGS MAY BE CONTINUED)
  871.         */
  872.     IF(NEXTCHAR = STRINGDELIM) OR CONT THEN
  873.          DO; /* FOUND STRING */
  874.               TOKEN = STRING;
  875.               CONT = FALSE;
  876.               DO FOREVER;  /* ALLOWS "" IN STRING TO BE " */
  877.                    DO WHILE GETCHAR <> STRINGDELIM;
  878.                    IF NEXTCHAR = EOLCHAR THEN CALL ERROR('US');
  879.                         CALL PUTINACCUM;
  880.                         IF CONT THEN RETURN;
  881.                         END;
  882.                    CALL GETNOBLANK;
  883.                    IF NEXTCHAR <> STRINGDELIM THEN
  884.                         RETURN;
  885.                    CALL PUT$IN$ACCUM;
  886.               END; /* OF DO FOREVER */
  887.          END; /* OF RECOGNIZING A STRING */
  888.        /*
  889.            NEXT CASE IS A NUMERIC WHICH MUST START WITH A
  890.            NUMBER OR WITH A PERIOD
  891.            ONLY FIRST IDENTSIZE CHARACTERS ARE RETAINED
  892.        */
  893.   ELSE IF NUMERIC OR DECIMALPT THEN
  894.          DO; /* HAVE DIGIT */
  895.               TOKEN = FLOATPT;
  896.                DO WHILE NEXTCHAR = '0'; /* ELIM LEADING ZEROS */
  897.                     NEXTCHAR = GETCHAR;
  898.                     END;
  899.               CALL SPOOLNUMERIC;  /* GET ALL THE NUMBERS */
  900.               IF DECIMALPT THEN
  901.                    DO;
  902.                         CALL PUTANDCHAR;
  903.                         CALL SPOOLNUMERIC;
  904.                    END;
  905.               CALL CONV$TO$UPPER;
  906.               IF NEXTCHAR = 'E' THEN
  907.                    DO;  /* A FLOATING POINT NUMBER */
  908.                         CALL PUTANDGET;
  909.                         IF (NEXTCHAR = '+') OR (NEXTCHAR='-') THEN
  910.                              CALL PUTANDGET;
  911.                         IF NOT NUMERIC THEN
  912.                              CALL ERROR('IF');
  913.                         CALL SPOOL$NUMERIC;
  914.                    END;
  915.                IF ACCLEN = 0 THEN
  916.                     HASHCODE, ACCUM(ACCLEN := 1) = '0';
  917.               CALL SETUP$NEXT$CALL;
  918.               RETURN;
  919.          END; /* OF RECOGNIZING NUMERIC CONSTANT */
  920.  
  921.        /*
  922.            NEXT CASE IS IDENTIFIER. MAY BE RESERVED WORD
  923.            IN WHICH CASE MAY BE REM, OR DATA. THESE STATEMENTS
  924.            ARE HANDLED BY THE SCANNER VICE THE PARSER AND THEN
  925.            ANOTHER LOOP THROUGH THE SCANNER IS MADE.
  926.            ONLY IDENTSIZE-1 CHARACTERS ARE RETAINED
  927.        */
  928.     ELSE IF LETTER THEN
  929.          DO; /* HAVE A LETTER */
  930.               DO WHILE ALPHANUM;
  931.                    CALL PUTANDCHAR;
  932.                    END;
  933.               IF NEXTCHAR = '$' THEN
  934.                    DO;
  935.                         SUBTYPE = STRING;
  936.                         CALL PUTANDCHAR;
  937.                    END;
  938.               ELSE
  939.                    SUBTYPE = FLOATPT;
  940.               IF NOT LOOKUP THEN
  941.                    DO;
  942.                         IF ACCUM(1) = 'F' AND ACCUM(2) = 'N'
  943.                                 AND ACCLEN <> 1 THEN
  944.                              TOKEN = UDFUNCT;
  945.                         ELSE
  946.                              TOKEN = IDENTIFIER;
  947.                         CALL SETUP$NEXT$CALL;
  948.                         RETURN;
  949.                    END;
  950.               ELSE /* IS A RW */
  951.                    IF TOKEN = TREM THEN
  952.                         DO WHILE NEXTCHAR <> EOLCHAR;
  953.                              NEXTCHAR = GETCHAR;
  954.                              CALL CHECK$CONTINUATION;
  955.                              END;
  956.                    ELSE
  957.                         IF TOKEN = TDATA THEN
  958.                              DO;
  959.                                    DECLARE DAT LIT '51';
  960.                                   CALL EMITDAT(DAT);
  961.                                   CALL EMITDAT(NEXTCHAR);
  962.                                   DO WHILE GETCHAR <> EOLCHAR;
  963.                                        CALL CHECK$CONTINUATION;
  964.                                        CALL EMITDAT(NEXTCHAR);
  965.                                        END;
  966.                                   CALL EMITDAT(',');
  967.                                   CALL EMITDAT(0);
  968.                                   DATACT = DATACT - 1;
  969.                              END;
  970.                         ELSE
  971.                              DO;
  972.                                   CALL SETUP$NEXT$CALL;
  973.                                   RETURN;
  974.                              END;
  975.          END; /* OF RECOGNIZING RW OR IDENT */
  976.         /*
  977.             LAST CASE IS A SPECIAL CHARACTER - IT MAY BE
  978.             THE CONTINUATION CHARACTER IN WHICH CASE JUST
  979.             GO TO NEXT LINE AND SCAN SOMEMORE.
  980.         */
  981.     ELSE
  982.          DO; /* SPECIAL CHARACTER */
  983.               IF NEXTCHAR = CONTCHAR THEN
  984.                    CALL CHECK$CONTINUATION;
  985.               ELSE
  986.                    DO;
  987.                         CALL PUTANDGET;
  988.                         IF NOT LOOKUP THEN
  989.                              CALL ERROR('IC');
  990.                         RETURN;
  991.                    END;
  992.          END; /* OF RECOGNIZING SPECIAL CHAR */
  993.     END;  /* OF DO FOREVER */
  994.  
  995. END SCANNER;
  996. END;
  997.