Urbane 1.060202 RC0 - Tandy Color Computer 3 Disk Extended Color Basic Preprocessor.
 MEM =  8218
 1 #               LIST_ON                                 : REM CHANGE TO COMMENT LINE IF NOT WANTED
 2 #               XREF_ON                                 : REM CHANGE TO COMMENT LINE IF NOT WANTED
 3 #               CONSTANT UBNVERSION$      = "1.060202 RC0"
 4 #               CONSTANT UBN_TITLE$        = "Urbane XUBNVERSION$  - Tandy Color Computer 3 Disk Extended Color Basic Preprocessor."
 5 '               Original Left Hello A. Nani Mouse Inx.
 6 
 7 #               CONSTANT IN_FILE$          = "UBN_IN.TXT"
 8 #               CONSTANT OUT_FILE$         = "UBN_OUT.TXT"
 9 #               CONSTANT LST_FILE$         = "UBN_LST.TXT"
 10 #               CONSTANT XRF_FILE$         = "UBN_XRF.TXT"
 11 
 12 #               CONSTANT NUM_M1            = -1
 13 #               CONSTANT NUM_0             = 0
 14 #               CONSTANT NUM_1             = 1
 15 #               CONSTANT NUM_2             = 2
 16 #               CONSTANT NUM_3             = 3
 17 #               CONSTANT NUM_4             = 4
 18 #               CONSTANT TRUE              = 1
 19 #               CONSTANT FALSE             = 0
 20 
 21 #               CONSTANT UBN_XREF_LIST_INITIAL = 0  : REM ON = 1, OFF = 0
 22 #               CONSTANT UBN_LIST_LIST_INITIAL = 0  : REM ON = 1, OFF = 0
 23 
 24 #               CONSTANT UBN_MEM_PCLEAR        = 1
 25 #               CONSTANT UBN_MEM_FILES_COUNT   = 4
 26 #               CONSTANT UBN_MEM_FILES_SPACE   = 100
 27 #               CONSTANT UBN_MEM_CLEAR         = 8500
 28 
 29 #               CONSTANT UBN_MEM_LINE_LABEL_MAX_COUNT                 = 100
 30 #               CONSTANT UBN_MEM_VARIABLE_NAMES_MAX_COUNT             = 150
 31 #               CONSTANT UBN_MEM_KEYWORD_TABLE_MAX_COUNT              = 200
 32 #               CONSTANT UBN_MEM_ILLEGAL_2CH_VARIABLE_TABLE_MAX_COUNT = 10
 33 
 34 #               CONSTANT ASC_TAB           = 09  : REM     TAB
 35 
 36 #               CONSTANT ASC_BLANK         = 32  : REM ASC(" ")
 37 
 38 #               CONSTANT ASC_DOUBLE_QUOTE  = 34  : REM ASC(""")
 39 '               CONSTANT ASC_DOUBLE_QUOTE$ is Defined as a program value, not a constant!
 40 #               CONSTANT ASC_POUND         = 35  : REM ASC("#")
 41 #               CONSTANT ASC_DOLLAR        = 36  : REM ASC("$")
 42 #               CONSTANT ASC_PERCENT       = 37  : REM ASC("%")
 43 #               CONSTANT ASC_AMPERSAND     = 38  : REM ASC("&")
 44 #               CONSTANT ASC_SINGLE_QUOTE  = 39  : REM ASC("'")
 45 
 46 #               CONSTANT ASC_PLUS          = 43  : REM ASC("+")
 47 #               CONSTANT ASC_MINUS         = 45  : REM ASC("-")
 48 #               CONSTANT ASC_PERIOD        = 46  : REM ASC(".")
 49 
 50 #               CONSTANT ASC_0             = 48 : REM ASC("0")
 51 #               CONSTANT ASC_7             = 55 : REM ASC("7")
 52 #               CONSTANT ASC_8             = 56 : REM ASC("8")
 53 #               CONSTANT ASC_9             = 57 : REM ASC("9")
 54 
 55 #               CONSTANT ASC_COLON         = 58  : REM ASC(":")
 56 #               CONSTANT ASC_EQUALS        = 61  : REM ASC("=")
 57 #               CONSTANT ASC_TILDE         = 64  : REM ASC("")
 58 
 59 #               CONSTANT ASC_A_U           = 65  : REM ASC("A")
 60 #               CONSTANT ASC_E_U           = 69  : REM ASC("E")
 61 #               CONSTANT ASC_F_U           = 70  : REM ASC("F")
 62 #               CONSTANT ASC_H_U           = 72  : REM ASC("H")
 63 #               CONSTANT ASC_O_U           = 79  : REM ASC("O")
 64 #               CONSTANT ASC_X_U           = 88  : REM ASC("X")
 65 #               CONSTANT ASC_Z_U           = 90  : REM ASC("Z")
 66 
 67 #               CONSTANT ASC_UNDERSCORE    = 95  : REM ASC("_")
 68 
 69 #               CONSTANT ASC_a_L           = 97  : REM ASC("a")
 70 #               CONSTANT ASC_e_L           = 101 : REM ASC("e")
 71 #               CONSTANT ASC_f_L           = 102 : REM ASC("f")
 72 #               CONSTANT ASC_h_L           = 104 : REM ASC("h")
 73 #               CONSTANT ASC_o_L           = 111 : REM ASC("o")
 74 #               CONSTANT ASC_x_L           = 120 : REM ASC("x")
 75 #               CONSTANT ASC_z_L           = 122 : REM ASC("z")
 76 
 77 #               CONSTANT UBN_XRF_TITLE              = 1
 78 #               CONSTANT UBN_XRF_LINE_LABEL         = 2
 79 #               CONSTANT UBN_XRF_LINE_REFERENCE     = 3
 80 #               CONSTANT UBN_XRF_VARIABLE           = 4
 81 #               CONSTANT UBN_XRF_VARIABLE_REFERENCE = 5
 82 '               CONSTANT UBN_XRF_CONSTANT           = 6
 83 '               CONSTANT UBN_XRF_CONSTANT_REFERENCE = 7
 84 #               CONSTANT UBN_XRF_KEYWORD_REFERENCE  = 8
 85 
 86 '               Start of Executation
 87                 GOTO UBN_START
 88 
 89 GET_IN_LINE_CHAR IN_LINE_CHAR_COUNTER = IN_LINE_CHAR_COUNTER + NUM_1
 90                 IF  IN_LINE_CHAR_COUNTER > I_LINE_LENGTH GOTO END_IN_LINE
 91 
 92                 LAST_CH     = IN_LINE_CH
 93                 IN_LINE_CH$ = MID$(IN_LINE$, IN_LINE_CHAR_COUNTER, NUM_1)
 94                 IN_LINE_CH  = ASC(IN_LINE_CH$)
 95                 IF IN_LINE_CH  >= ASC_BLANK THEN RETURN
 96                 IF IN_LINE_CH   = ASC_TAB GOTO SUBSTUTE_SPACE_FOR_TAB
 97 
 98                 PRINT #FILE_L, LINE_NUMBER; " " ; IN_LINE$
 99                 PRINT #FILE_L, LINE_NUMBER; " Control Character "; IN_LINE_CH; " Found in Input Line at "; IN_LINE_CHAR_COUNTER
 100                 RETURN
 101 
 102 SUBSTUTE_SPACE_FOR_TAB IN_LINE_CH$ = CHR$(ASC_BLANK)
 103                 IN_LINE_CH  = ASC_BLANK
 104                 RETURN
 105 
 106 END_IN_LINE     IN_LINE_CH  = NUM_M1
 107                 IN_LINE_CH$ =  CHR$(ASC_TILDE)
 108                 RETURN
 109 
 110 '''
 111 '               On Entry, first character of label or variable is in "IN_LINE_CH$" and "IN_LINE_CH"
 112 '               On Exit, "IN_LINE_CH$" and "IN_LINE_CH" have terminating character (next character not part of VLString).
 113 
 114 GET_VLSTRING    VLSTRING$ = IN_LINE_CH$
 115 NEXT_VLSTRING_CH GOSUB GET_IN_LINE_CHAR
 116                 IF IN_LINE_CH  <  NUM_0   THEN RETURN
 117                 IF IN_LINE_CH  >= ASC_A_U AND IN_LINE_CH  <= ASC_Z_U GOTO VLSTRING_ADD_UPPER_ALPHA
 118                 IF IN_LINE_CH  >= ASC_a_L AND IN_LINE_CH  <= ASC_z_L GOTO VLSTRING_ADD_LOWER_ALPHA
 119                 IF IN_LINE_CH  >= ASC_0   AND IN_LINE_CH  <= ASC_9   GOTO VLSTRING_ADD_NUMBER
 120                 IF IN_LINE_CH   = ASC_UNDERSCORE                     GOTO VLSTRING_ADD_SPECIAL
 121                 IF IN_LINE_CH   = ASC_TILDE                          GOTO VLSTRING_ADD_SPECIAL
 122                 IF IN_LINE_CH   = ASC_DOLLAR                         GOTO VLSTRING_ADD_DOLLAR
 123 '               REM Character Found that cannot be in Variable or line Label
 124                 RETURN
 125 
 126 VLSTRING_ADD_LOWER_ALPHA IN_LINE_CH   = IN_LINE_CH  - ( ASC_a_L - ASC_A_U )
 127                 IN_LINE_CH$ = CHR$(IN_LINE_CH)
 128 VLSTRING_ADD_UPPER_ALPHA  REM
 129 VLSTRING_ADD_NUMBER       REM
 130 VLSTRING_ADD_SPECIAL      REM
 131 VLSTRING_ADD_DOLLAR       REM
 132                 VLSTRING$ = VLSTRING$ + IN_LINE_CH$
 133 '               If an "ASC_DOLLAR" is found, declare label or variable end found
 134                 IF IN_LINE_CH  =  ASC_DOLLAR THEN LAST_CH = IN_LINE_CH : GOSUB GET_IN_LINE_CHAR : RETURN
 135                 GOTO NEXT_VLSTRING_CH
 136 
 137 '''
 138 '               On Entry, "ASC_DOUBLE_QUOTE" is in "IN_LINE_CH$" and "IN_LINE_CH"
 139 '               On Exit, "IN_LINE_CH$" and "IN_LINE_CH" have terminating character or next character.
 140 
 141 GET_QSTRING     QSTRING$ = IN_LINE_CH$
 142                 QSTRING_SKIP_VARIABLE = FALSE
 143 MORE_QSTRING    GOSUB GET_IN_LINE_CHAR
 144 
 145                 IF IN_LINE_CH <= NUM_0 GOTO BAD_QSTRING
 146                 QSTRING$      =  QSTRING$ + IN_LINE_CH$
 147                 IF IN_LINE_CH =  ASC_BLANK        THEN QSTRING_SKIP_VARIABLE = FALSE
 148                 IF QSTRING_SKIP_VARIABLE = TRUE   GOTO SKIP_VARIABLE
 149                 IF IN_LINE_CH =  ASC_X_U OR IN_LINE_CH  = ASC_x_L GOTO GET_QSTRING_VARIABLE
 150 SKIP_VARIABLE   IF IN_LINE_CH <> ASC_DOUBLE_QUOTE GOTO MORE_QSTRING
 151 
 152                 GOSUB GET_IN_LINE_CHAR
 153                 RETURN
 154 
 155 GET_QSTRING_VARIABLE GOSUB GET_IN_LINE_CHAR
 156                 IF IN_LINE_CH <= NUM_0                              GOTO BAD_QSTRING
 157                 IF IN_LINE_CH  = ASC_DOUBLE_QUOTE                   GOTO NO_QSVARIABLE
 158                 IF IN_LINE_CH >= ASC_A_U AND IN_LINE_CH  <= ASC_Z_U GOTO GET_QSTRING_VAR
 159                 IF IN_LINE_CH >= ASC_a_L AND IN_LINE_CH  <= ASC_z_L GOTO GET_QSTRING_VAR
 160                 IF IN_LINE_CH  = ASC_UNDERSCORE                     GOTO GET_QSTRING_VAR
 161                 GOTO MORE_QSTRING
 162 NO_QSVARIABLE   QSTRING$   = QSTRING$ + IN_LINE_CH$
 163                 GOSUB GET_IN_LINE_CHAR
 164                 RETURN
 165 
 166 GET_QSTRING_VAR QSTRING_CHAR_COUNTER_SAVE = IN_LINE_CHAR_COUNTER
 167                 QSTRING_LAST_CHAR_SAVE$    = IN_LINE_CH$
 168                 GOSUB GET_VLSTRING
 169 
 170                 IF LAST_CH  <>  ASC_DOLLAR GOTO NOT_QSTRING_VAR
 171                 FOR  VARIABLE_NAMES_COUNTER = VARIABLE_NAMES_START TO VARIABLE_NAMES_COUNT
 172                      IF   VLSTRING$ = VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_NAME) GOTO HAVE_QSTRING_VARIABLE
 173                 NEXT VARIABLE_NAMES_COUNTER
 174 
 175 '               Have New Variable
 176 
 177                 VARIABLE_NAMES_COUNT = VARIABLE_NAMES_COUNT + NUM_1
 178                 IF  VARIABLE_NAMES_COUNT > VARIABLE_NAMES_MAX_COUNT THEN PRINT #FILE_L, " VARIABLE_NAMES_MAX_COUNT Exceeded" : STOP
 179 
 180                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_NAME) = VLSTRING$
 181                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_2CH)  = "Pending"
 182 
 183                 GOSUB GET_NEW_2CH_VARIABLE
 184 
 185                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_2CH) = NEW_2CH_VARIABLE$ + "$"
 186                 VARIABLE_NAMES_COUNTER = VARIABLE_NAMES_COUNT
 187 
 188 HAVE_QSTRING_VARIABLE IF ASC(VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_2CH)) = ASC_DOUBLE_QUOTE GOTO ADD_QSTRING_CONSTANT
 189 
 190 '               Add existing 2ch variable to QUOTE string
 191 
 192                 QSTRING$ = QSTRING$ + VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_2CH)
 193                 GOTO MORE_QSTRING
 194 
 195 '               Do Not Include the 'X'
 196 '               Add Constant Without Leading and Trailing Quotes
 197 
 198 ADD_QSTRING_CONSTANT QSTRING_LENGTH = LEN(QSTRING$) - NUM_1
 199                 QSTRING$ = LEFT$(QSTRING$,QSTRING_LENGTH)
 200                 QSTRING_CONSTANT_LENGTH = LEN(VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_2CH)) - NUM_2
 201                 QSTRING$ = QSTRING$ + MID$(VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_2CH),NUM_2,QSTRING_CONSTANT_LENGTH)
 202                 GOTO MORE_QSTRING
 203 
 204 NOT_QSTRING_VAR IN_LINE_CHAR_COUNTER    = QSTRING_CHAR_COUNTER_SAVE
 205                 IN_LINE_CH$               = QSTRING_LAST_CHAR_SAVE$
 206                 QSTRING_SKIP_VARIABLE   = TRUE
 207                 QSTRING$ = QSTRING$ + IN_LINE_CH$
 208 '               PRINT #FILE_L, LINE_NUMBER ; " QSTRING$ = "; QSTRING$; ", IN_LINE_CH = "; IN_LINE_CH
 209 '               PRINT #FILE_L, LINE_NUMBER ; " VLSTRING$ = "; VLSTRING$
 210                 GOTO MORE_QSTRING
 211 
 212                 GOSUB GET_IN_LINE_CHAR
 213                 RETURN
 214 
 215 BAD_QSTRING     PRINT #FILE_L, LINE_NUMBER ; " ERROR - Missing end of Quoted String "  ; QSTRING$
 216                 ERRORS = ERRORS + NUM_1
 217                 RETURN
 218 GET_NEW_2CH_VARIABLE NEW_2CH_VARIABLE$ = CHR$(HIGH_2CH_VARIABLE) + CHR$(LOW_2CH_VARIABLE)
 219 
 220                 LOW_2CH_VARIABLE = LOW_2CH_VARIABLE + NUM_1
 221                 IF  LOW_2CH_VARIABLE <= ASC_Z_U GOTO  CHECK_NEW_2CH_VARIABLE
 222                 LOW_2CH_VARIABLE = ASC_A_U
 223 
 224                 HIGH_2CH_VARIABLE = HIGH_2CH_VARIABLE + NUM_1
 225                 IF HIGH_2CH_VARIABLE <= ASC_Z_U GOTO  CHECK_NEW_2CH_VARIABLE
 226                 HIGH_2CH_VARIABLE = ASC_A_U : REM Ignore Possibility of 'ZZ' being exceeded FOR NOW (676 Variables)
 227 
 228 CHECK_NEW_2CH_VARIABLE FOR  ILLEGAL_2CH_VARIABLE_TABLE_COUNTER = ILLEGAL_2CH_VARIABLE_TABLE_START TO ILLEGAL_2CH_VARIABLE_TABLE_COUNT
 229                      IF   NEW_2CH_VARIABLE$ = ILLEGAL_2CH_VARIABLE_TABLE$(ILLEGAL_2CH_VARIABLE_TABLE_COUNTER) GOTO GET_NEW_2CH_VARIABLE
 230                 NEXT ILLEGAL_2CH_VARIABLE_TABLE_COUNTER
 231 
 232                 RETURN
 233 
 234 '               This is checking if only allowable characters are present
 235 '               It does NOT check for valid number syntax
 236 CHECK_IF_NUMBER IS_NUMBER = FALSE
 237                 NUMBER_LENGTH = LEN(VLSTRING$)
 238                 FOR NUMBER_COUNTER = NUM_1 TO NUMBER_LENGTH
 239 
 240                     NUMBER_CH$  = MID$(VLSTRING$, NUMBER_COUNTER, NUM_1)
 241                     NUMBER_CH   = ASC(NUMBER_CH$)
 242 
 243                     IF NUMBER_CH  >= ASC_0   AND NUMBER_CH  <= ASC_9    GOTO MORE_NUMBERS
 244                     IF NUMBER_CH  = ASC_PERIOD OR NUMBER_CH  = ASC_PLUS OR  NUMBER_CH = ASC_MINUS  GOTO MORE_NUMBERS
 245                     IF NUMBER_CH  = ASC_E_U OR NUMBER_CH  = ASC_e_L     GOTO MORE_NUMBERS
 246 
 247                     RETURN   : REM Not a number
 248 
 249 MORE_NUMBERS    NEXT  NUMBER_COUNTER
 250                 IS_NUMBER = TRUE
 251                 RETURN
 252 
 253 '               Prepare line number for output, no leading space, No trailing space
 254 PREPARE_LINE_NUMBER LNR_$  = STR$(LINE_NUMBER)
 255 '               IF LEN(LNR_$)  < 2 THEN PRINT #FILE_L, "LINE NUMBER LENGTH LESS THAN 2 >>" ; LEN(LNR_$)
 256                 LN_LENGTH  = LEN(LNR_$) - NUM_1
 257                 LN_$       = MID$(LNR_$, NUM_2, LN_LENGTH)
 258                 RETURN
 259 
 260 NEXT_LINE       LINE INPUT #FILE_I, IN_LINE$
 261 
 262                 IN_LINE_CHAR_COUNTER = NUM_0
 263                 LAST_CH              = ASC_TILDE
 264                 DEF_CONSTANT         = FALSE
 265                 DATA_LINE            = FALSE
 266                 VLSTRING_COUNT       = NUM_0
 267 '               Let User Know we are still processing
 268                 IF  PASS = NUM_2 THEN PRINT LINE_NUMBER ;
 269                 I_EOF                = EOF(FILE_I)
 270 
 271                 IF I_EOF  = NUM_M1 GOTO I_FILE_END
 272                 I_LINE_LENGTH = LEN(IN_LINE$)
 273                 IF  I_LINE_LENGTH = NUM_0 GOTO BLANK_LINE
 274 
 275 '''             CHARACTERS IN COLUMN ONE
 276 '               "A-Za-z", "_", "0-9"   =    LINE LABLE
 277 '               "#"                    =    Urbane COMMAND
 278 '               " "                    =    NO LINE LABLE
 279 '               "'"                    =    COMMENT
 280 '               any other character    =    COMMENT
 281 
 282 COLUMN_ONE      GOSUB GET_IN_LINE_CHAR
 283                 IF IN_LINE_CH  =  ASC_POUND        GOTO URBANE_COMMAND
 284                 IF IN_LINE_CH  =  ASC_BLANK        GOTO NO_LINE_LABLE
 285                 IF IN_LINE_CH  =  ASC_SINGLE_QUOTE GOTO COMMENT
 286 
 287                 IF IN_LINE_CH  >= ASC_A_U AND IN_LINE_CH  <= ASC_Z_U GOTO LINE_LABEL
 288                 IF IN_LINE_CH  >= ASC_a_L AND IN_LINE_CH  <= ASC_z_L GOTO LINE_LABEL
 289                 IF IN_LINE_CH  >= ASC_0   AND IN_LINE_CH  <= ASC_9   GOTO LINE_LABEL
 290                 IF IN_LINE_CH   = ASC_UNDERSCORE                     GOTO LINE_LABEL
 291 
 292 COMMENT         ON PASS GOTO OUTPUT_LINE, PASS2_CONTINUE
 293 
 294 URBANE_COMMAND  IF INSTR(NUM_2, IN_LINE$, "LIST_ON")  <> NUM_0 THEN OUTPUT_LISTING = TRUE
 295                 IF INSTR(NUM_2, IN_LINE$, "LIST_OFF") <> NUM_0 THEN OUTPUT_LISTING = FALSE
 296 
 297                 IF INSTR(NUM_2, IN_LINE$, "XREF_ON")  <> NUM_0 THEN OUTPUT_XREF    = TRUE
 298                 IF INSTR(NUM_2, IN_LINE$, "XREF_OFF") <> NUM_0 THEN OUTPUT_XREF    = FALSE
 299 
 300                 IF INSTR(NUM_2, IN_LINE$, "CONSTANT") <> NUM_0 THEN DEF_CONSTANT = TRUE  : GOTO NO_LINE_LABLE
 301 
 302 '               ON PASS GOTO OUTPUT_LINE, PASS2_CONTINUE
 303 
 304 BLANK_LINE      ON PASS GOTO OUTPUT_LINE, PASS2_CONTINUE
 305 
 306 NO_LINE_LABLE   ON PASS GOTO OUTPUT_LINE, PARSE_LINE
 307 
 308 LINE_LABEL      GOSUB GET_VLSTRING
 309                 VLSTRING_COUNT = NUM_1
 310 
 311                 IF LAST_CH  <>  ASC_DOLLAR GOTO LINE_LABEL_GOOD
 312                 PRINT #FILE_L, "WARNING - '$' SHOULD NOT BE USED IN LABELS "  ; VLSTRING$
 313                 PRINT          "WARNING - '$' SHOULD NOT BE USED IN LABELS "  ; VLSTRING$
 314                 WARNINGS = WARNINGS + NUM_1
 315 
 316 LINE_LABEL_GOOD IF PASS = NUM_2 GOTO PARSE_LINE
 317 
 318                 FOR  LINE_LABEL_COUNTER = LINE_LABEL_START TO LINE_LABEL_COUNT
 319                      IF   VLSTRING$ = LINE_LABELS$(LINE_LABEL_COUNTER,LINE_LABELS_NAME) GOTO DUP_LINE_LABEL
 320                 NEXT LINE_LABEL_COUNTER
 321 
 322                  LINE_LABEL_COUNT = LINE_LABEL_COUNT + NUM_1
 323                 IF   LINE_LABEL_COUNT > LINE_LABEL_MAX_COUNT THEN PRINT #FILE_L, " LINE_LABEL_MAX_COUNT Exceeded" : STOP
 324 
 325                 LINE_LABELS$(LINE_LABEL_COUNT,LINE_LABELS_NAME) = VLSTRING$
 326                 GOSUB PREPARE_LINE_NUMBER
 327                 LINE_LABELS$(LINE_LABEL_COUNT,LINE_LABELS_NUMBER) = LN_$
 328                 IF OUTPUT_XREF = TRUE THEN PRINT #FILE_X, " "; UBN_XRF_LINE_LABEL; " "; LN_$; " "; VLSTRING$
 329                 GOTO  OUTPUT_LINE
 330 
 331 DUP_LINE_LABEL  PRINT #FILE_L, LINE_NUMBER ; " ERROR - DUPLICATE LINE LABEL  = " ; VLSTRING$
 332                 ERRORS = ERRORS + NUM_1
 333                 GOTO OUTPUT_LINE
 334 
 335 PARSE_LINE      GOSUB PREPARE_LINE_NUMBER
 336                 OUTPUT_STRING$ = LN_$
 337                 CONSTANT_NAME$ = ""
 338                 CONSTANT_INDEX = NUM_0
 339                 EQUALS_FOUND   = FALSE
 340 
 341 PARSE_CONTINUE  IF IN_LINE_CH <  NUM_0                              GOTO OUTPUT_LINE
 342                 IF IN_LINE_CH >= ASC_A_U AND IN_LINE_CH  <= ASC_Z_U GOTO LABEL_OR_VARIABLE
 343                 IF IN_LINE_CH >= ASC_a_L AND IN_LINE_CH  <= ASC_z_L GOTO LABEL_OR_VARIABLE
 344                 IF IN_LINE_CH >= ASC_0   AND IN_LINE_CH  <= ASC_9   GOTO LABEL_OR_VARIABLE
 345                 IF IN_LINE_CH  = ASC_UNDERSCORE                     GOTO LABEL_OR_VARIABLE
 346                 IF IN_LINE_CH  = ASC_DOUBLE_QUOTE                   GOTO HAVE_QUOTED_STRING
 347                 IF IN_LINE_CH  = ASC_AMPERSAND                      GOTO HEX_OR_OCTAL
 348 
 349                 IF IN_LINE_CH  = ASC_EQUALS                         THEN EQUALS_FOUND = TRUE
 350 
 351 '               Skip blanks
 352                 IF IN_LINE_CH = ASC_BLANK AND LAST_CH = ASC_BLANK GOTO PARSE_GET_NEXT_CH
 353 
 354                 OUTPUT_STRING$ = OUTPUT_STRING$ + IN_LINE_CH$
 355 
 356 PARSE_GET_NEXT_CH GOSUB GET_IN_LINE_CHAR
 357                 GOTO PARSE_CONTINUE
 358 
 359 LABEL_OR_VARIABLE VLSTRING_COUNT = VLSTRING_COUNT + NUM_1
 360                 GOSUB GET_VLSTRING
 361 
 362                 GOSUB CHECK_IF_NUMBER
 363                 IF IS_NUMBER = TRUE  GOTO HAVE_NUMBER
 364 
 365                 FOR KEYWORD_TABLE_COUNTER = KEYWORD_TABLE_START TO KEYWORD_TABLE_COUNT
 366                     IF  VLSTRING$ = KEYWORD_TABLE$(KEYWORD_TABLE_COUNTER) GOTO HAVE_KEYWORD
 367                 NEXT KEYWORD_TABLE_COUNTER
 368 
 369                 FOR  LINE_LABEL_COUNTER = LINE_LABEL_START TO LINE_LABEL_COUNT
 370                      IF   VLSTRING$ = LINE_LABELS$(LINE_LABEL_COUNTER,VARIABLE_NAMES_NAME) GOTO HAVE_LINE_LABEL
 371                 NEXT LINE_LABEL_COUNTER
 372 
 373                 FOR  VARIABLE_NAMES_COUNTER = VARIABLE_NAMES_START TO VARIABLE_NAMES_COUNT
 374                      IF   VLSTRING$ = VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_NAME) GOTO HAVE_VARIABLE
 375                 NEXT VARIABLE_NAMES_COUNTER
 376 
 377 '               NEW_VARIABLE FOUND
 378                 VARIABLE_NAMES_COUNT = VARIABLE_NAMES_COUNT + NUM_1
 379                 IF  VARIABLE_NAMES_COUNT > VARIABLE_NAMES_MAX_COUNT THEN PRINT #FILE_L, " VARIABLE_NAMES_MAX_COUNT Exceeded" : STOP
 380 
 381                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_NAME) = VLSTRING$
 382                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_2CH)  = "Pending"
 383                 IF DEF_CONSTANT <> TRUE GOTO GET_NEW_2CH
 384                 CONSTANT_NAME$ = VLSTRING$
 385                 CONSTANT_INDEX = VARIABLE_NAMES_COUNT
 386                 IF OUTPUT_XREF = TRUE THEN PRINT #FILE_X, " "; UBN_XRF_VARIABLE; " "; LN_$; " "; VLSTRING$
 387                 GOTO PARSE_CONTINUE
 388 
 389 '               Generate new 2 character variable name and put it into variable name table
 390 GET_NEW_2CH     GOSUB GET_NEW_2CH_VARIABLE
 391 
 392                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_2CH) = NEW_2CH_VARIABLE$
 393                 VARIABLE_NAMES_COUNTER = VARIABLE_NAMES_COUNT
 394                 IF OUTPUT_XREF = TRUE THEN PRINT #FILE_X, " "; UBN_XRF_VARIABLE; " "; LN_$; " "; VLSTRING$
 395                 IF LAST_CH  <>  ASC_DOLLAR  GOTO HAVE_VARIABLE
 396                 VARIABLE_NAMES$(VARIABLE_NAMES_COUNT,VARIABLE_NAMES_2CH) = NEW_2CH_VARIABLE$ + "$"
 397                 GOTO HAVE_VARIABLE
 398 
 399 HAVE_KEYWORD    IF OUTPUT_XREF = TRUE AND DATA_LINE = FALSE THEN PRINT #FILE_X, " "; UBN_XRF_KEYWORD_REFERENCE; " "; LN_$; " "; VLSTRING$
 400 '               Add keyword to output string
 401                 IF  DATA_LINE = TRUE       GOTO HAVE_DATA_LINE
 402                 IF  VLSTRING$ = "REM"      GOTO HAVE_REM
 403                 IF  VLSTRING$ = "LET"      GOTO HAVE_LET
 404                 IF  VLSTRING$ = "DATA"     THEN DATA_LINE = TRUE
 405                 IF  VLSTRING$ = "CONSTANT" GOTO PARSE_CONTINUE
 406 HAVE_DATA_LINE  OUTPUT_STRING$ = OUTPUT_STRING$ + VLSTRING$
 407 
 408                 GOTO PARSE_CONTINUE
 409 
 410 '               Line with no Line Label and first Keyword "REM" can be removed
 411 '               DECB requires the "REM keyword if there is a label on the line
 412 
 413 HAVE_REM        IF VLSTRING_COUNT = NUM_1 GOTO PASS2_CONTINUE
 414                 OUTPUT_STRING$ = OUTPUT_STRING$ + "REM"
 415                 GOTO OUTPUT_LINE
 416 
 417 '               Remove unnecessary "LET" and next Blank
 418 HAVE_LET        IF IN_LINE_CH = ASC_BLANK GOTO PARSE_GET_NEXT_CH
 419                 GOTO PARSE_CONTINUE
 420 
 421 HAVE_LINE_LABEL IF OUTPUT_XREF = TRUE THEN PRINT #FILE_X, " "; UBN_XRF_LINE_REFERENCE; " "; LN_$; " "; LINE_LABELS$(LINE_LABEL_COUNTER,LINE_LABELS_NUMBER)
 422 '               Add line number to output string
 423                 OUTPUT_STRING$ = OUTPUT_STRING$ + LINE_LABELS$(LINE_LABEL_COUNTER,LINE_LABELS_NUMBER)
 424                 GOTO PARSE_CONTINUE
 425 
 426 HAVE_NUMBER     IF   DEF_CONSTANT   <> TRUE  GOTO ADD_NUMBER
 427                 IF   CONSTANT_INDEX  = NUM_0 GOTO ADD_NUMBER
 428                 IF   EQUALS_FOUND   <> TRUE  GOTO ADD_NUMBER
 429 
 430                 NUM_PREFIX$ = ""
 431                 IF   LAST_CH = ASC_MINUS THEN NUM_PREFIX$ = "-"
 432                 IF   LAST_CH = ASC_PLUS  THEN NUM_PREFIX$ = "+"
 433 
 434                  VARIABLE_NAMES$(CONSTANT_INDEX,VARIABLE_NAMES_2CH)  = NUM_PREFIX$ + VLSTRING$
 435                 GOTO PARSE_CONTINUE
 436 
 437 '               Add number to output string
 438 ADD_NUMBER      OUTPUT_STRING$ = OUTPUT_STRING$ + VLSTRING$
 439                 GOTO PARSE_CONTINUE
 440 
 441 HAVE_VARIABLE   IF DEF_CONSTANT = TRUE GOTO PARSE_CONTINUE
 442                 IF OUTPUT_XREF = TRUE THEN PRINT #FILE_X, " "; UBN_XRF_VARIABLE_REFERENCE; " "; LN_$; " "; VLSTRING$
 443 '               Add existing 2ch variable to output string
 444                 OUTPUT_STRING$ = OUTPUT_STRING$ + VARIABLE_NAMES$(VARIABLE_NAMES_COUNTER,VARIABLE_NAMES_2CH)
 445                 GOTO PARSE_CONTINUE
 446 
 447 HAVE_QUOTED_STRING GOSUB GET_QSTRING
 448                 IF    DEF_CONSTANT  <> TRUE  GOTO ADD_QUOTED
 449                 IF    CONSTANT_INDEX = NUM_0 GOTO ADD_QUOTED
 450                 IF    EQUALS_FOUND  <> TRUE  GOTO ADD_QUOTED
 451 
 452                 VARIABLE_NAMES$(CONSTANT_INDEX,VARIABLE_NAMES_2CH)  = QSTRING$
 453                 GOTO  PARSE_CONTINUE
 454 
 455 '               Copy Quoted string to output, with double quotes
 456 
 457 ADD_QUOTED      OUTPUT_STRING$ = OUTPUT_STRING$ + QSTRING$
 458                 GOTO PARSE_CONTINUE
 459 
 460 '               On Entry, "ASC_AMPERSAND" is in "IN_LINE_CH$" and "IN_LINE_CH"
 461 '               On Exit, "IN_LINE_CH$" and "IN_LINE_CH" have next character.
 462 HEX_OR_OCTAL    HO_STRING$ = IN_LINE_CH$
 463 
 464                 GOSUB GET_IN_LINE_CHAR
 465                 HO_STRING$ = HO_STRING$ + IN_LINE_CH$
 466 
 467                 HEX   = FALSE
 468                 OCTAL = FALSE
 469                 IF IN_LINE_CH   = ASC_H_U OR  IN_LINE_CH   = ASC_h_L THEN HEX   = TRUE
 470                 IF IN_LINE_CH   = ASC_O_U OR  IN_LINE_CH   = ASC_o_L THEN OCTAL = TRUE
 471                 IF HEX = FALSE AND OCTAL = FALSE GOTO BAD_HEX_OR_OCTAL
 472 
 473 MORE_HEX_OR_OCTAL GOSUB GET_IN_LINE_CHAR
 474 
 475                 IF IN_LINE_CH  >= ASC_A_U AND IN_LINE_CH  <= ASC_F_U GOTO HOSTRING_ADD_UPPER_HEX
 476                 IF IN_LINE_CH  >= ASC_a_L AND IN_LINE_CH  <= ASC_f_L GOTO HOSTRING_ADD_LOWER_HEX
 477                 IF IN_LINE_CH  >= ASC_0   AND IN_LINE_CH  <= ASC_7   GOTO HOSTRING_ADD_OCTAL
 478                 IF IN_LINE_CH  >= ASC_8   AND IN_LINE_CH  <= ASC_9   GOTO HOSTRING_ADD_UPPER_HEX
 479 
 480 '               End of Hex or Octal Number
 481                 OUTPUT_STRING$ = OUTPUT_STRING$ + HO_STRING$
 482                 GOTO PARSE_CONTINUE
 483 
 484 HOSTRING_ADD_LOWER_HEX IN_LINE_CH   = IN_LINE_CH  - ( ASC_a_L - ASC_A_U )
 485                 IN_LINE_CH$  = CHR$(IN_LINE_CH)
 486 
 487 HOSTRING_ADD_UPPER_HEX HO_STRING$ = HO_STRING$ + IN_LINE_CH$
 488                 IF HEX = TRUE  GOTO MORE_HEX_OR_OCTAL
 489 
 490                 PRINT #FILE_L, "WARNING - Invalid Octal Number "  ; HO_STRING$
 491                 PRINT          "WARNING - Invalid Octal Number "  ; HO_STRING$
 492                 WARNINGS = WARNINGS + NUM_1
 493                 GOTO OUTPUT_LINE
 494 
 495 HOSTRING_ADD_OCTAL HO_STRING$ = HO_STRING$ + IN_LINE_CH$
 496                 GOTO MORE_HEX_OR_OCTAL
 497 
 498 BAD_HEX_OR_OCTAL PRINT #FILE_L, "WARNING - '&' Not followed by 'H' or 'O' "  ; HO_STRING$
 499                 PRINT           "WARNING - '&' Not followed by 'H' or 'O' "  ; HO_STRING$
 500                 WARNINGS = WARNINGS + NUM_1
 501 '               GOTO OUTPUT_LINE
 502 
 503 OUTPUT_LINE     IF PASS = NUM_1 AND OUTPUT_LISTING = TRUE THEN PRINT #FILE_L, LINE_NUMBER ; IN_LINE$
 504 
 505                 IF DEF_CONSTANT = TRUE GOTO PASS2_CONTINUE
 506 
 507                 IF PASS = NUM_2 THEN PRINT #FILE_O, OUTPUT_STRING$
 508 
 509 PASS2_CONTINUE  LINE_NUMBER = LINE_NUMBER + NUM_1
 510                 GOTO NEXT_LINE
 511 
 512 I_FILE_END      LINE_COUNT = LINE_NUMBER - NUM_1
 513                 PRINT #FILE_L, "Urbane Pass "; PASS; " Done, Lines = "; LINE_COUNT
 514                 PRINT          "Urbane Pass "; PASS; " Done, Lines = "; LINE_COUNT
 515 
 516                 IF PASS = NUM_2 GOTO ALL_DONE
 517 '               GOSUB DUMP_LINE_LABELS
 518 
 519                 PRINT #FILE_L, " MEM = " ; MEM
 520                 PRINT          " MEM = " ; MEM
 521 
 522 LOAD_KEYWORDS   DIM KEYWORD_TABLE$(UBN_MEM_KEYWORD_TABLE_MAX_COUNT)
 523                 KEYWORD_TABLE_MAX_COUNT = UBN_MEM_KEYWORD_TABLE_MAX_COUNT
 524                 KEYWORD_TABLE_START     = NUM_1
 525                 KEYWORD_TABLE_COUNT     = NUM_0
 526 
 527 LOOP_KEYWORDS   READ KEYWORD$
 528                 IF   KEYWORD$ = "\" GOTO END_OF_KEYWORDS
 529                 KEYWORD_TABLE_COUNT = KEYWORD_TABLE_COUNT + NUM_1
 530                 KEYWORD_TABLE$(KEYWORD_TABLE_COUNT) = KEYWORD$
 531                 GOTO LOOP_KEYWORDS
 532 
 533 END_OF_KEYWORDS DIM ILLEGAL_2CH_VARIABLE_TABLE$(UBN_MEM_ILLEGAL_2CH_VARIABLE_TABLE_MAX_COUNT)
 534                 ILLEGAL_2CH_VARIABLE_TABLE_MAX_COUNT = UBN_MEM_ILLEGAL_2CH_VARIABLE_TABLE_MAX_COUNT
 535                 ILLEGAL_2CH_VARIABLE_TABLE_START     =  NUM_1
 536                 ILLEGAL_2CH_VARIABLE_TABLE_COUNT     =  NUM_0
 537 
 538 LOOP_ILLEGAL_2CH_VARIABLES   READ ILLEGAL_2CH_VARIABLE$
 539                 IF ILLEGAL_2CH_VARIABLE$ = "\" GOTO END_OF_ILLEGAL_2CH_VARIABLES
 540                 ILLEGAL_2CH_VARIABLE_TABLE_COUNT = ILLEGAL_2CH_VARIABLE_TABLE_COUNT + NUM_1
 541                 ILLEGAL_2CH_VARIABLE_TABLE$(ILLEGAL_2CH_VARIABLE_TABLE_COUNT) = ILLEGAL_2CH_VARIABLE$
 542                 GOTO LOOP_ILLEGAL_2CH_VARIABLES
 543 
 544 END_OF_ILLEGAL_2CH_VARIABLES DIM VARIABLE_NAMES$(UBN_MEM_VARIABLE_NAMES_MAX_COUNT,NUM_2)
 545                 VARIABLE_NAMES_MAX_COUNT       = UBN_MEM_VARIABLE_NAMES_MAX_COUNT
 546                 VARIABLE_NAMES_START           = NUM_1
 547                 VARIABLE_NAMES_COUNT           = NUM_0
 548                 VARIABLE_NAMES_NAME            = NUM_1
 549                 VARIABLE_NAMES_2CH             = NUM_2
 550 
 551                 HIGH_2CH_VARIABLE = ASC_A_U
 552                 LOW_2CH_VARIABLE  = ASC_A_U
 553 
 554                 PASS        = NUM_2
 555                 LINE_NUMBER = NUM_1
 556                 I_EOF       = NUM_0
 557                 PRINT #FILE_L,  " ---------PASS 2 STARTING------"
 558                 PRINT           " ---------PASS 2 STARTING------"
 559                 CLOSE FILE_I
 560 
 561                 OPEN "I", #NUM_1, IN_FILE$
 562 
 563                 GOTO NEXT_LINE
 564 
 565 '               REM Startup code here so Basic does not have to search it each time it is looking for a line number
 566 UBN_START       FILES  UBN_MEM_FILES_COUNT, UBN_MEM_FILES_SPACE
 567                 PCLEAR UBN_MEM_PCLEAR
 568                 CLEAR  UBN_MEM_CLEAR
 569                 PRINT "Urbane Starting - Urbane XUBNVERSION$ "
 570                 PRINT " MEM = " ; MEM
 571 
 572                 PASS              = NUM_1
 573                 LINE_NUMBER       = NUM_1
 574 
 575                 ERRORS            = NUM_0
 576                 WARNINGS          = NUM_0
 577 
 578                 ASC_DOUBLE_QUOTE$ = CHR$(34)
 579 
 580                 OUTPUT_LISTING    = UBN_LIST_LIST_INITIAL
 581                 OUTPUT_XREF       = UBN_XREF_LIST_INITIAL
 582                 FILE_I = NUM_1
 583                 FILE_O = NUM_2
 584                 FILE_L = NUM_3
 585                 FILE_X = NUM_4
 586 
 587                 OPEN "I", #NUM_1, IN_FILE$
 588 
 589                 OPEN "O", #NUM_2, OUT_FILE$
 590 
 591                 OPEN "O", #NUM_3, LST_FILE$
 592 
 593                 OPEN "O", #NUM_4, XRF_FILE$
 594 
 595                 DIM  LINE_LABELS$(UBN_MEM_LINE_LABEL_MAX_COUNT,NUM_2)
 596                 LINE_LABEL_MAX_COUNT = UBN_MEM_LINE_LABEL_MAX_COUNT
 597                 LINE_LABEL_START     = NUM_1
 598                 LINE_LABEL_COUNT     = NUM_0
 599                 LINE_LABELS_NAME     = NUM_1
 600                 LINE_LABELS_NUMBER   = NUM_2
 601 
 602                 PRINT #FILE_L, " "; UBN_TITLE$
 603                 PRINT #FILE_X, " "; UBN_XRF_TITLE; " "; NUM_0; " "; UBN_TITLE$
 604 
 605                 PRINT #FILE_L, " MEM = " ; MEM
 606                 GOTO NEXT_LINE
 607 
 608 '               Keyword Table
 609                 DATA REM
 610                 DATA ATTR,AUDIO,BACKUP,CIRCLE,CLEAR,CLOAD,CLOADM,CLOSE,CLS,COLOR,CONSTANT,CONT,COPY,CSAVE
 611                 DATA CSAVEM,DATA,DEF,DEFUSR,DEL,DIM,DIR,DLOAD,DRAW,DRIVE,DSKI$,DSKINI,DSKO$,EDIT
 612                 DATA END,EXEC,FIELD,FILES,FN,FOR,GET,GOSUB
 613                 DATA GOTO,HBUFF,HCIRCLE,HCLS,HCOLOR,HDRAW,HGET,HLINE,HPAINT,HPRINT,HPUT,HRESET
 614                 DATA HSCREEN,HSET,HSTAT,IF,INPUT,KILL,LET,LINE,LIST,LLIST,LOCATE,LPOKE,LOAD,LOADM,LSET,MERGE
 615                 DATA MOTOR,NEW,NEXT,OLD,ON,OPEN,PAINT,PALETTE,PCLEAR,PCLS,PCOPY,PLAY,PMODE,POKE,PRESET,PRINT
 616                 DATA PSET,PUT,READ,RENAME,RENUM,RESET,RSET,RESTORE,RESUME,RETURN,RUN,SAVE,SAVEM,SCREEN
 617                 DATA SET,SKIPF,SOUND,STOP,TO,TROFF,TRON,WIDTH,WRITE,UNLOAD,VERIFY
 618                 DATA MEM,TIMER,AND,NOT,OR,ELSE,STEP,FREE,AS,BRK,ERR,CMP,RGB,USING
 619                 DATA ERROR,FREE,OFF,TAB,USING,THEN,TO,G,BF,B,R,A,"?"
 620                 DATA AS,BF,OR,PI
 621 
 622 '               Functions, keywords that require next character to be an open parentheses
 623                 DATA ABS,ASC,ATN,BUTTON,CHR$,COS,CVN,EOF,ERLIN,ERNO,EXP,FIX,HEX$,HPOINT,INKEY$,INSTR,INT
 624                 DATA JOYSTK,LEFT$,LEN,LOC,LOF,LOG,LPEEK,MID$,MKN$,PEEK,POINT,POS,PPOINT,RIGHT$,RND,SGN,SIN
 625                 DATA STRING$,STR$,SQR,TAN,USR,VAL,VARPTR
 626                 DATA "\"
 627 
 628 '               Illegal Two Character Variable Table    NOTE: "PI" is a variable that is NOT replaced
 629                 DATA AS,BF,FN,IF,ON,OR,PI,TO,"\"
 630 
 631 ALL_DONE        PRINT #FILE_L, " MEM = " ; MEM
 632                 PRINT          " MEM = " ; MEM
 633 '               GOSUB DUMP_VARIABLES
 634                 PRINT          "Urbane Done, Errors = " ; ERRORS ; " Warnings = "; WARNINGS ; " Lines = " ; LINE_COUNT ; "Line Label Count = " ; LINE_LABEL_COUNT ; " Variables Count = " ; VARIABLE_NAMES_COUNT
 635                 PRINT #FILE_L, "Urbane Done, Errors = " ; ERRORS ; " Warnings = "; WARNINGS ; " Lines = " ; LINE_COUNT ; "Line Label Count = " ; LINE_LABEL_COUNT ; " Variables Count = " ; VARIABLE_NAMES_COUNT
 636                 CLOSE FILE_I
 637                 CLOSE FILE_O
 638                 CLOSE FILE_L
 639                 CLOSE FILE_X
 640 
 641                 END
Urbane Pass  1  Done, Lines =  641 
 MEM =  8106 
 ---------PASS 2 STARTING------
Urbane Pass  2  Done, Lines =  641 
 MEM =  4477 
Urbane Done, Errors =  0  Warnings =  0  Lines =  641 Line Label Count =  65  Variables Count =  137