home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 2 / DATAFILE_PDCD2.iso / utilities2 / _bbc_gw / !BBC-GW / BBCGWNotes < prev    next >
Encoding:
Text File  |  1993-07-25  |  29.1 KB  |  885 lines

  1.  
  2. Notes on Coding of BBC BASIC and GW-BASIC Files - Martin Carradus July 1993
  3. ---------------------------------------------------------------------------
  4.  
  5. *** I do not guarantee the accuracy of the following information ***
  6.  
  7. These notes give details of the format of files produced with BBC BASIC
  8. and GW-BASIC when the BASIC program is saved to disc. 
  9.  
  10. (BASIC command SAVE"filename", where 'filename' is the name of the file 
  11. to be saved to).
  12.  
  13. Introduction
  14. ------------
  15.  
  16. In order to understand these notes, you will need to know something
  17. about the difference between compilers and interpreters. 
  18.  
  19. All computer languages need to be translated into the fundamental
  20. instructions of the particular computer (machine code). A compiler is
  21. presented with the complete program and translates the whole thing
  22. into machine code. The machine code is then run on the computer in
  23. a separate stage. An interpreter, however, translates the program and
  24. obeys it as it goes along. The advantage is that you do not need a
  25. preceding stage before you run the program. The disadvantage is that,
  26. since the whole program has not been 'seen', the final code is usually
  27. less efficient and runs more slowly than compiled code.
  28.  
  29. In order for an interpreter to obey the program efficiently, it is
  30. usually coded so that it makes it easier to work out parts of the
  31. program. The main 'trick' is to code the keywords (words like GOTO, or
  32. IF or PRINT) into only a couple of characters (bytes), known as a
  33. token. This means that they can be easily recognised every time the
  34. interpreter runs across them in the program.
  35.  
  36. At the beginning of each line of the program, the interpreter will
  37. need to know the line number of that line and where the next line is.
  38. Both are coded for greater efficiency.
  39.  
  40. All types of BASIC use an interpreter.
  41.  
  42. In these notes Hex is Hexadecimal, or counting to base 16, Octal is
  43. counting to base 8, and Binary is counting to base 2. A byte is enough
  44. storage to hold one character and is 8 bits long (bit is a 0 or 1).
  45. The low byte is the least significant part of a binary number (lower 8
  46. bits) and the high byte is the most significant (higher 8 bits). The
  47. file is assumed to come in from left to right, the earlier the byte,
  48. the more to the left it is. ASCII is a standard code for representing
  49. characters as bytes. 
  50.  
  51.  
  52. A. Coding of BBC BASIC files
  53.    -------------------------
  54.  
  55. This is basically pure ASCII text, apart from line numbers and tokens.
  56.  
  57. The program file begins with a return symbol and ends with ASCII code
  58. 255 (hex FF).
  59.  
  60. Each line has the following format:-
  61.  
  62. <Three bytes> <coded BASIC line> <return symbol - ASCII code 13>
  63.  
  64. The starting three bytes have the line number in the first two bytes
  65. (high byte first) and the length of the decoded line in the third
  66. byte.                                   -------
  67.  
  68. All the key words in BBC BASIC are coded in either one or two bytes,
  69. always starting with a byte with an ASCII value greater than or equal
  70. to 127 (decimal). Hence all the tokens apart from that for OTHERWISE
  71. (see below) have the top bit set and are unprintable ASCII characters.
  72.  
  73. Apart from that, the line numbers after GOTOs and GOSUBs are preceded
  74. by a byte with ASCII code 141 decimal (215 octal - 8D hex) and are
  75. coded in rather a strange way:-
  76.  
  77. Line Number: (After ASCII character 141)
  78. -----------
  79.   
  80.   Consists of three bytes, the bits of which are as follows (most
  81. right most bit is bit 0). (the 'is' Bits refer to the actual line
  82. number in binary).
  83.  
  84. Lowest Byte: (Right most)
  85.  
  86. Bit 0 is Bit 8, Bit 1 is Bit 9, Bit 2 is Bit 10, Bit 3 is Bit 11.          
  87. Bit 4 is Bit 12, Bit 5 is Bit 13, Bit 6 is always 0, Bit 7 is always 1.
  88.  
  89. Middle Byte:
  90.   
  91. Bit 0 is Bit 0, Bit 1 is Bit 2, Bit 2 is Bit 3, Bit 3 is Bit 3.          
  92. Bit 4 is Bit 4, Bit 5 is Bit 5, Bit 6 is always 0, Bit 7 is
  93. always 1.
  94.  
  95. Highest Byte: (Left Most)
  96.  
  97. Bit 0 is always 0, Bit 1 is always 0, Bit 2 is Bit 14, Bit 3 is 
  98. inverted bit 15.           
  99. Bit 4 is inverted Bit 6, Bit 5 is Bit 7, Bit 6 is always 0, Bit 7 is
  100. always 1.                                                              
  101.  
  102. So the middle byte basically codes the low byte of the line number,
  103. and the low byte codes the high byte of the line number with bits
  104. needed to be added in or inverted and added in from the highest byte
  105. of the coding.
  106.  
  107. I coded this conversion in C as follows:
  108.   
  109.   If c[0] is the highest byte of the coding (left most) , c[1] is the
  110. middle byte of the coding, c[2] is the lowest byte of the coding
  111. (right most) and lineno is the integer that is to hold the final
  112. decoded line number:
  113.   
  114.   c[0]=c[0]^0x14; /* Inverts extra bits (Bits 6 and 15) */
  115.  
  116.   c[1]=c[1]&0x3f; /* Masks off low byte of lineno */
  117.  
  118.   c[2]=c[2]&0x3f; /* Masks off high byte of lineno */
  119.  
  120.   c[1]=c[1] | ((c[0] & 0x30)<<2); /* Adds in Bits 6 and 7 to low byte */
  121.  
  122.   c[2]=c[2] | ((c[0] & 0x0c)<<4); /* Adds in Bits 14 and 15 to high byte */
  123.  
  124. lineno=(int)c[1] +((int)c[2]<<8); /* Combines low and high bytes of lineno */
  125.  
  126. Tokens
  127. ------ 
  128.  
  129. Herewith a complete list of tokens, both in alphabetical order and ASCII
  130. code order as held in a C structure:
  131.   
  132. struct list
  133. {
  134.   char bbc_keyword[10];
  135.   char bbc_token_hex[3];    
  136.   char bbc_token_octal[10];
  137. };
  138.    
  139. /* Alphabetical Order */   
  140.  
  141. struct list token_list[] = {  
  142.  
  143. "Line No",  "\x8d",     "\215",
  144. "ABS",      "\x94",     "\224",
  145. "ACS",      "\x95",     "\225",
  146. "ADVAL",    "\x96",     "\226",
  147. "AND",      "\x80",     "\200",
  148. "APPEND",   "\xc7\x8e", "\307\216",
  149. "ASC",      "\x97",     "\227",
  150. "ASN",      "\x98",     "\230",
  151. "ATN",      "\x99",     "\231",
  152. "AUTO",     "\xc7\x8f", "\307\217",
  153. "BEAT",     "\xc6\x8f", "\306\217",
  154. "BEATS",    "\xc8\x9e", "\310\236",
  155. "BGET",     "\x9a",     "\232",
  156. "BPUT",     "\xd5",     "\325",
  157. "CALL",     "\xd6",     "\326",
  158. "CASE",     "\xc8\x8e", "\310\216",
  159. "CHAIN",    "\xd7",     "\327",
  160. "CHR$",     "\xbd",     "\275",
  161. "CIRCLE",   "\xc8\x8f", "\310\217",
  162. "CLEAR",    "\xd8",     "\330",
  163. "CLG",      "\xda",     "\332",
  164. "CLOSE",    "\xd9",     "\331",
  165. "CLS",      "\xdb",     "\333",
  166. "COLOUR",   "\xfb",     "\373",
  167. "COS",      "\x9b",     "\233",
  168. "COUNT",    "\x9c",     "\234",
  169. "DATA",     "\xdc",     "\334",
  170. "DEF",      "\xdd",     "\335",
  171. "DEG",      "\x9d",     "\235",
  172. "DELETE",   "\xc7\x90", "\307\220",
  173. "DIM",      "\xde",     "\336",
  174. "DIV",      "\x81",     "\201",
  175. "DRAW",     "\xdf",     "\337",
  176. "EDIT",     "\xc7\x91", "\307\221",
  177. "ELLIPSE",  "\xc8\x9d", "\310\235",
  178. "ELSE",     "\xcc",     "\314",
  179. "ELSE",     "\x8b",     "\213",
  180. "END",      "\xe0",     "\340",
  181. "ENDCASE",  "\xcb",     "\313",
  182. "ENDIF",    "\xcd",     "\315",
  183. "ENDPROC",  "\xe1",     "\341",
  184. "ENDWHILE", "\xce",     "\316",
  185. "EOF",      "\xc5",     "\305",
  186. "EOR",      "\x82",     "\202",
  187. "ERL",      "\x9e",     "\236",
  188. "ERR",      "\x9f",     "\237",
  189. "ERROR",    "\x85",     "\205",
  190. "EVAL",     "\xa0",     "\240",
  191. "EXP",      "\xa1",     "\241",
  192. "EXT",      "\xa2",     "\242",
  193. "FALSE",    "\xa3",     "\243",
  194. "FILL",     "\xc8\x90", "\310\220",
  195. "FN",       "\xa4",     "\244",
  196. "FOR",      "\xe3",     "\343",
  197. "GCOL",     "\xe6",     "\346",
  198. "GET",      "\xa5",     "\245",
  199. "GET$",     "\xbe",     "\276",
  200. "GOSUB",    "\xe4",     "\344",
  201. "GOTO",     "\xe5",     "\345",
  202. "HELP",     "\xc7\x92", "\307\222",
  203. "HIMEM",    "\xd3",     "\323",
  204. "HIMEM",    "\x93",     "\223",
  205. "IF",       "\xe7",     "\347",
  206. "INKEY",    "\xa6",     "\246",
  207. "INKEY$",   "\xbf",     "\277",
  208. "INPUT",    "\xe8",     "\350",
  209. "INSTALL",  "\xc8\x9a", "\310\232",
  210. "INSTR(",   "\xa7",     "\247",
  211. "INT",      "\xa8",     "\250",
  212. "LEFT$(",   "\xc0",     "\300",
  213. "LEN",      "\xa9",     "\251",
  214. "LET",      "\xe9",     "\351",
  215. "LIBRARY",  "\xc8\x9b", "\310\233",
  216. "LINE",     "\x86",     "\206",
  217. "LIST",     "\xc7\x93", "\307\223",
  218. "LN",       "\xaa",     "\252",
  219. "LOAD",     "\xc7\x94", "\307\224",
  220. "LOCAL",    "\xea",     "\352",
  221. "LOG",      "\xab",     "\253",
  222. "LOMEM",    "\xd2",     "\322",
  223. "LOMEM",    "\x92",     "\222",
  224. "LVAR",     "\xc7\x95", "\307\225",
  225. "MID$(",    "\xc1",     "\301",
  226. "MOD",      "\x83",     "\203",
  227. "MODE",     "\xeb",     "\353",
  228. "MOUSE",    "\xc8\x97", "\310\227",
  229. "MOVE",     "\xec",     "\354",
  230. "NEW",      "\xc7\x96", "\307\226",
  231. "NEXT",     "\xed",     "\355",
  232. "NOT",      "\xac",     "\254",
  233. "OF",       "\xca",     "\312",
  234. "OFF",      "\x87",     "\207",
  235. "OLD",      "\xc7\x97", "\307\227",
  236. "ON",       "\xee",     "\356",
  237. "OPENIN",   "\x8e",     "\216",
  238. "OPENOUT",  "\xae",     "\256",
  239. "OPENUP",   "\xad",     "\255",
  240. "OR",       "\x84",     "\204",
  241. "ORIGIN",   "\xc8\x91", "\310\221",
  242. "OSCLI",    "\xff",     "\377",
  243. "OTHERWISE","\x7f",     "\177",
  244. "OVERLAY",  "\xc8\xa3", "\310\243",
  245. "PAGE",     "\xd0",     "\320",
  246. "PAGE",     "\x90",     "\220",
  247. "PI",       "\xaf",     "\257",
  248. "PLOT",     "\xf0",     "\360",
  249. "POINT",    "\xc8\x92", "\310\222",
  250. "POINT(",   "\xb0",     "\260",
  251. "POS",      "\xb1",     "\261",
  252. "PRINT",    "\xf1",     "\361",
  253. "PROC",     "\xf2",     "\362",
  254. "PTR",      "\xcf",     "\317",
  255. "PTR",      "\x8f",     "\217",
  256. "QUIT",     "\xc8\x98", "\310\230",
  257. "RAD",      "\xb2",     "\262",
  258. "READ",     "\xf3",     "\363",
  259. "RECTANGLE","\xc8\x93", "\310\223",
  260. "REM",      "\xf4",     "\364",
  261. "RENUMBER", "\xc7\x98", "\307\230",
  262. "REPEAT",   "\xf5",     "\365",
  263. "REPORT",   "\xf6",     "\366",
  264. "RESTORE",  "\xf7",     "\367",
  265. "RETURN",   "\xf8",     "\370",
  266. "RIGHT$(",  "\xc2",     "\302",
  267. "RND",      "\xb3",     "\263",
  268. "RUN",      "\xf9",     "\371",
  269. "SAVE",     "\xc7\x99", "\307\231",
  270. "SGN",      "\xb4",     "\264",
  271. "SIN",      "\xb5",     "\265",
  272. "SOUND",    "\xd4",     "\324",
  273. "SPC",      "\x89",     "\211",
  274. "SQR",      "\xb6",     "\266",
  275. "STEP",     "\x88",     "\210",
  276. "STEREO",   "\xc8\xa2", "\310\242",
  277. "STOP",     "\xfa",     "\372",
  278. "STR$",     "\xc3",     "\303",
  279. "STRING$(", "\xc4",     "\304",
  280. "SUM",      "\xc6\x8e", "\306\216",
  281. "SWAP",     "\xc8\x94", "\310\224",
  282. "SYS",      "\xc8\x99", "\310\231",
  283. "TAB(",     "\x8a",     "\212",
  284. "TAN",      "\xb7",     "\267",
  285. "TEMPO",    "\xc8\x9f", "\310\237",
  286. "THEN",     "\x8c",     "\214",
  287. "TIME",     "\xd1",     "\321",
  288. "TIME",     "\x91",     "\221",
  289. "TINT",     "\xc8\x9c", "\310\234",
  290. "TO",       "\xb8",     "\270",
  291. "TOP",      "\xb8P",    "\270P",
  292. "TRACE",    "\xfc",     "\374",
  293. "TRUE",     "\xb9",     "\271",
  294. "TWIN",     "\xc7\x9a", "\307\232",
  295. "TWINO",    "\xc7\x9b", "\307\233",
  296. "UNTIL",    "\xfd",     "\375",
  297. "USR",      "\xba",     "\272",
  298. "VAL",      "\xbb",     "\273",
  299. "VDU",      "\xef",     "\357",
  300. "VOICE",    "\xc8\xa1", "\310\241",
  301. "VOICES",   "\xc8\xa0", "\310\240",
  302. "VPOS",     "\xbc",     "\274",
  303. "WAIT",     "\xc8\x96", "\310\226",
  304. "WHEN",     "\xc9",     "\311",
  305. "WHILE",    "\xc8\x95", "\310\225",
  306. "WIDTH",    "\xfe",     "\376",
  307. "",         "",         ""};
  308.                         
  309. /* Sorted token value order */
  310.  
  311. struct list sort_token_list= {
  312.  
  313. "OTHERWISE","\x7f",     "\177",
  314. "AND",      "\x80",     "\200",
  315. "DIV",      "\x81",     "\201",
  316. "EOR",      "\x82",     "\202",
  317. "MOD",      "\x83",     "\203",
  318. "OR",       "\x84",     "\204",
  319. "ERROR",    "\x85",     "\205",
  320. "LINE",     "\x86",     "\206",
  321. "OFF",      "\x87",     "\207",
  322. "STEP",     "\x88",     "\210",
  323. "SPC",      "\x89",     "\211",
  324. "TAB(",     "\x8a",     "\212",
  325. "ELSE",     "\x8b",     "\213",
  326. "THEN",     "\x8c",     "\214",
  327. "Line No",  "\x8d",     "\215",
  328. "OPENIN",   "\x8e",     "\216",
  329. "PTR",      "\x8f",     "\217",
  330. "PAGE",     "\x90",     "\220",
  331. "TIME",     "\x91",     "\221",
  332. "LOMEM",    "\x92",     "\222",
  333. "HIMEM",    "\x93",     "\223",
  334. "ABS",      "\x94",     "\224",
  335. "ACS",      "\x95",     "\225",
  336. "ADVAL",    "\x96",     "\226",
  337. "ASC",      "\x97",     "\227",
  338. "ASN",      "\x98",     "\230",
  339. "ATN",      "\x99",     "\231",
  340. "BGET",     "\x9a",     "\232",
  341. "COS",      "\x9b",     "\233",
  342. "COUNT",    "\x9c",     "\234",
  343. "DEG",      "\x9d",     "\235",
  344. "ERL",      "\x9e",     "\236",
  345. "ERR",      "\x9f",     "\237",
  346. "EVAL",     "\xa0",     "\240",
  347. "EXP",      "\xa1",     "\241",
  348. "EXT",      "\xa2",     "\242",
  349. "FALSE",    "\xa3",     "\243",
  350. "FN",       "\xa4",     "\244",
  351. "GET",      "\xa5",     "\245",
  352. "INKEY",    "\xa6",     "\246",
  353. "INSTR(",   "\xa7",     "\247",
  354. "INT",      "\xa8",     "\250",
  355. "LEN",      "\xa9",     "\251",
  356. "LN",       "\xaa",     "\252",
  357. "LOG",      "\xab",     "\253",
  358. "NOT",      "\xac",     "\254",
  359. "OPENUP",   "\xad",     "\255",
  360. "OPENOUT",  "\xae",     "\256",
  361. "PI",       "\xaf",     "\257",
  362. "POINT(",   "\xb0",     "\260",
  363. "POS",      "\xb1",     "\261",
  364. "RAD",      "\xb2",     "\262",
  365. "RND",      "\xb3",     "\263",
  366. "SGN",      "\xb4",     "\264",
  367. "SIN",      "\xb5",     "\265",
  368. "SQR",      "\xb6",     "\266",
  369. "TAN",      "\xb7",     "\267",
  370. "TO",       "\xb8",     "\270",
  371. "TOP",      "\xb8P",    "\270P",
  372. "TRUE",     "\xb9",     "\271",
  373. "USR",      "\xba",     "\272",
  374. "VAL",      "\xbb",     "\273",
  375. "VPOS",     "\xbc",     "\274",
  376. "CHR$",     "\xbd",     "\275",
  377. "GET$",     "\xbe",     "\276",
  378. "INKEY$",   "\xbf",     "\277",
  379. "LEFT$(",   "\xc0",     "\300",
  380. "MID$(",    "\xc1",     "\301",
  381. "RIGHT$(",  "\xc2",     "\302",
  382. "STR$",     "\xc3",     "\303",
  383. "STRING$(", "\xc4",     "\304",
  384. "EOF",      "\xc5",     "\305",
  385. "SUM",      "\xc6\x8e", "\306\216",
  386. "BEAT",     "\xc6\x8f", "\306\217",
  387. "APPEND",   "\xc7\x8e", "\307\216",
  388. "AUTO",     "\xc7\x8f", "\307\217",
  389. "DELETE",   "\xc7\x90", "\307\220",
  390. "EDIT",     "\xc7\x91", "\307\221",
  391. "HELP",     "\xc7\x92", "\307\222",
  392. "LIST",     "\xc7\x93", "\307\223",
  393. "LOAD",     "\xc7\x94", "\307\224",
  394. "LVAR",     "\xc7\x95", "\307\225",
  395. "NEW",      "\xc7\x96", "\307\226",
  396. "OLD",      "\xc7\x97", "\307\227",
  397. "RENUMBER", "\xc7\x98", "\307\230",
  398. "SAVE",     "\xc7\x99", "\307\231",
  399. "TWIN",     "\xc7\x9a", "\307\232",
  400. "TWINO",    "\xc7\x9b", "\307\233",
  401. "CASE",     "\xc8\x8e", "\310\216",
  402. "CIRCLE",   "\xc8\x8f", "\310\217",
  403. "FILL",     "\xc8\x90", "\310\220",
  404. "ORIGIN",   "\xc8\x91", "\310\221",
  405. "POINT",    "\xc8\x92", "\310\222",
  406. "RECTANGLE","\xc8\x93", "\310\223",
  407. "SWAP",     "\xc8\x94", "\310\224",
  408. "WHILE",    "\xc8\x95", "\310\225",
  409. "WAIT",     "\xc8\x96", "\310\226",
  410. "MOUSE",    "\xc8\x97", "\310\227",
  411. "QUIT",     "\xc8\x98", "\310\230",
  412. "SYS",      "\xc8\x99", "\310\231",
  413. "INSTALL",  "\xc8\x9a", "\310\232",
  414. "LIBRARY",  "\xc8\x9b", "\310\233",
  415. "TINT",     "\xc8\x9c", "\310\234",
  416. "ELLIPSE",  "\xc8\x9d", "\310\235",
  417. "BEATS",    "\xc8\x9e", "\310\236",
  418. "TEMPO",    "\xc8\x9f", "\310\237",
  419. "VOICES",   "\xc8\xa0", "\310\240",
  420. "VOICE",    "\xc8\xa1", "\310\241",
  421. "STEREO",   "\xc8\xa2", "\310\242",
  422. "OVERLAY",  "\xc8\xa3", "\310\243",
  423. "WHEN",     "\xc9",     "\311",
  424. "OF",       "\xca",     "\312",
  425. "ENDCASE",  "\xcb",     "\313",
  426. "ELSE",     "\xcc",     "\314",
  427. "ENDIF",    "\xcd",     "\315",
  428. "ENDWHILE", "\xce",     "\316",
  429. "PTR",      "\xcf",     "\317",
  430. "PAGE",     "\xd0",     "\320",
  431. "TIME",     "\xd1",     "\321",
  432. "LOMEM",    "\xd2",     "\322",
  433. "HIMEM",    "\xd3",     "\323",
  434. "SOUND",    "\xd4",     "\324",
  435. "BPUT",     "\xd5",     "\325",
  436. "CALL",     "\xd6",     "\326",
  437. "CHAIN",    "\xd7",     "\327",
  438. "CLEAR",    "\xd8",     "\330",
  439. "CLOSE",    "\xd9",     "\331",
  440. "CLG",      "\xda",     "\332",
  441. "CLS",      "\xdb",     "\333",
  442. "DATA",     "\xdc",     "\334",
  443. "DEF",      "\xdd",     "\335",
  444. "DIM",      "\xde",     "\336",
  445. "DRAW",     "\xdf",     "\337",
  446. "END",      "\xe0",     "\340",
  447. "ENDPROC",  "\xe1",     "\341",
  448. "FOR",      "\xe3",     "\343",
  449. "GOSUB",    "\xe4",     "\344",
  450. "GOTO",     "\xe5",     "\345",
  451. "GCOL",     "\xe6",     "\346",
  452. "IF",       "\xe7",     "\347",
  453. "INPUT",    "\xe8",     "\350",
  454. "LET",      "\xe9",     "\351",
  455. "LOCAL",    "\xea",     "\352",
  456. "MODE",     "\xeb",     "\353",
  457. "MOVE",     "\xec",     "\354",
  458. "NEXT",     "\xed",     "\355",
  459. "ON",       "\xee",     "\356",
  460. "VDU",      "\xef",     "\357",
  461. "PLOT",     "\xf0",     "\360",
  462. "PRINT",    "\xf1",     "\361",
  463. "PROC",     "\xf2",     "\362",
  464. "READ",     "\xf3",     "\363",
  465. "REM",      "\xf4",     "\364",
  466. "REPEAT",   "\xf5",     "\365",
  467. "REPORT",   "\xf6",     "\366",
  468. "RESTORE",  "\xf7",     "\367",
  469. "RETURN",   "\xf8",     "\370",
  470. "RUN",      "\xf9",     "\371",
  471. "STOP",     "\xfa",     "\372",
  472. "COLOUR",   "\xfb",     "\373",
  473. "TRACE",    "\xfc",     "\374",
  474. "UNTIL",    "\xfd",     "\375",
  475. "WIDTH",    "\xfe",     "\376",
  476. "OSCLI",    "\xff",     "\377",
  477. "",         "",         ""};
  478.  
  479. NB   LOMEM, HIMEM, PAGE, PTR and TIME have different tokens depending
  480. --   on whether they are statement or function tokens (whether they
  481. are given or give a value). The token for ELSE has different values
  482. depending on whether it is part of an IF statement on one line or
  483. spread over several lines. Also the keyword 'BY' is not tokenised.
  484. Note the token for 'TOP', which is that for 'TO' with a 'P' after it.
  485.  
  486.  
  487. B. Coding of GW-BASIC Files
  488.    ------------------------
  489.  
  490. The format of a GW-BASIC file is as follows:
  491.   
  492.   <Hex FF> lines <Hex 00 00 FF FF 1A>
  493.   
  494.   or sometimes terminated with <Hex 00 00 FF 1A>
  495.   
  496. The lines are coded as follows:
  497.   
  498.   <Four bytes> coded line <Hex 00>
  499.   
  500. The first four bytes hold the following information:
  501.   
  502.   First two bytes: The position of the next line in the file.
  503.   
  504.   Second two bytes: The line number.
  505.   
  506.   The line number is coded as a binary number, the lowest byte first.
  507.   
  508.   The position of the next line is with an added offset. If the first
  509.   byte of the file is regarded as byte 0, then the position given is that
  510.   of the first of the next four bytes plus 4686 (decimal) (124E Hex). 
  511.                                       ----                            
  512.   The coded position is given low byte first, high byte second.
  513.   
  514.   Thus if the first line was line number ten and the second line begins
  515.   at file byte position 7, then the first four bytes of the file after 
  516.   the leading FF are:-
  517.   
  518.   Hex 55 12 0A 00
  519.                     
  520.   The Line
  521.   --------
  522.   The coded line has the following components:
  523.     
  524.     Line Numbers, Keyword Tokens, String Literals, Operators, Integers, 
  525.     Hex Literals, Octal Literals and Floating Point Literals.
  526.     
  527. 1.  Line Numbers (after GOTO or GOSUB)
  528.     ------------
  529.     
  530.     Are 'announced' by the character ASCII value 14 (Hex 0E, Octal 16)
  531.     
  532.     It is simply the binary value of the line number in two bytes, low
  533.     byte first.
  534.    
  535. 2.  String Literals (Strings of characters enclosed in double quotes)
  536.     ---------------
  537.     
  538.     Are entirely uncoded. Even characters that might be regarded as 
  539.     tokens are ignored by the BASIC interpreter.
  540.     
  541. 3.  Operators  (i.e. for addition, subtraction etc.)
  542.     ---------
  543.     
  544.     These are coded (they do not take their ASCII character value).
  545.     
  546.     They are:
  547.               
  548.      Operator    Hex Token    Octal Token
  549.      --------    ---------    ----------- 
  550.       
  551.      ">",        "\xe6",      "\346",
  552.      "=",        "\xe7",      "\347",
  553.      "<",        "\xe8",      "\350",
  554.      "+",        "\xe9",      "\351",
  555.      "-",        "\xea",      "\352",
  556.      "*",        "\xeb",      "\353",
  557.      "/",        "\xec",      "\354",
  558.      "^",        "\xed",      "\355",
  559.      "AND",      "\xee",      "\356",
  560.      "OR",       "\xef",      "\357",
  561.      "XOR",      "\xf0",      "\360",
  562.      "EQV",      "\xf1",      "\361",
  563.      "IMP",      "\xf2",      "\362",
  564.      "MOD",      "\xf3",      "\363",
  565.      "\\",       "\xf4",      "\364", (backslash)  
  566.      "NOT",      "\xd3",      "\323" 
  567.      
  568. 4.   Integer Literals (a sequence of numeric characters e.g. 259 )
  569.      ----------------
  570.      
  571.      These are coded in a different way depending on whether the number
  572.      is less than ten, greater than nine and less than 256, or greater 
  573.      than 255.
  574.      
  575.      Less than ten.
  576.      -------------
  577.                   
  578.     Coded as single byte which has the ASCII value of 17 + the numeric value,
  579.     hence:
  580.       
  581.       0 is coded as a byte with ASCII code 17 (decimal).
  582.       1  "  "     " "  "    "    "     "   18
  583.       2  "  "     " "  "    "    "     "   19
  584.       .....
  585.       9  "  "     " "  "    "    "     "   26
  586.       
  587.       Greater than 9 and less than 256
  588.       --------------------------------
  589.       
  590.       Coded as a single byte preceded by a byte with ASCII code 15
  591.       (Hex 0F Octal 17).
  592.       
  593.       The byte simply holds the numeric value.
  594.       
  595.       Greater than 255
  596.       ----------------
  597.       
  598.       Coded in two bytes preceded by a byte with ASCII code 28 (decimal)
  599.       (Hex 1C, Octal 34).
  600.       
  601.       The two bytes simply hold the numeric value, low byte first. 
  602.  
  603. 5.    Hex Literals (a string of hex characters preceded by &H e.g. &HF1)
  604.       ------------
  605.       
  606.       Converted to their binary representation, then coded in a similar
  607.       way to integers greater than 255 and preceded by a character with
  608.       ASCII code 12 (Hex 0C, Octal 14).
  609.        
  610. 6.    Octal Literals (a string of octal characters preceded by & or &O
  611.       --------------                                    e.g. &O801 )
  612.       
  613.       Converted to their binary representation, then as for hex literals
  614.       preceded by a character with ASCII value 11 (decimal) (Hex 0B, 
  615.       Octal 13).
  616.             
  617. 7.    Tokens (sustituted for the key words of the language)
  618.       ------
  619.       
  620.       A complete list of tokens in a C structure follows:
  621.  
  622. struct list
  623. {
  624.   char gw_keyword[10];
  625.   char gw_token_hex[3];
  626.   char gw_token_octal[3];
  627. };
  628.  
  629.  
  630. struct list token_list[]={
  631.   
  632. "END",      "\x81",      "\201",
  633. "FOR",      "\x82",      "\202",
  634. "NEXT",     "\x83",      "\203",
  635. "DATA",     "\x84",      "\204",
  636. "INPUT",    "\x85",      "\205",
  637. "DIM",      "\x86",      "\206",
  638. "READ",     "\x87",      "\207",
  639. "LET",      "\x88",      "\210",
  640. "GOTO",     "\x89",      "\211",
  641. "RUN",      "\x8a",      "\212",
  642. "IF",       "\x8b",      "\213",
  643. "RESTORE",  "\x8c",      "\214",
  644. "GOSUB",    "\x8d",      "\215",
  645. "RETURN",   "\x8e",      "\216",
  646. "REM",      "\x8f",      "\217",
  647. "STOP",     "\x90",      "\220",
  648. "PRINT",    "\x91",      "\221",
  649. "CLEAR",    "\x92",      "\222",
  650. "LIST",     "\x93",      "\223",
  651. "NEW",      "\x94",      "\224",
  652. "ON",       "\x95",      "\225",
  653. "WAIT",     "\x96",      "\226",
  654. "DEF",      "\x97",      "\227",
  655. "POKE",     "\x98",      "\230",
  656. "CONT",     "\x99",      "\231",
  657. "OUT",      "\x9c",      "\234",
  658. "LPRINT",   "\x9d",      "\235",
  659. "LLIST",    "\x9e",      "\236",
  660. "WIDTH",    "\xa0",      "\240",
  661. "ELSE",     ":\xa1",     ":\241",
  662. "TRON",     "\xa2",      "\242",
  663. "TROFF",    "\xa3",      "\243",
  664. "SWAP",     "\xa4",      "\244",
  665. "ERASE",    "\xa5",      "\245",
  666. "EDIT",     "\xa6",      "\246",
  667. "ERROR",    "\xa7",      "\247",
  668. "RESUME",   "\xa8",      "\250",
  669. "DELETE",   "\xa9",      "\251",    
  670. "AUTO",     "\xaa",      "\252",
  671. "RENUM",    "\xab",      "\253",
  672. "DEFSTR",   "\xac",      "\254",
  673. "DEFINT",   "\xad",      "\255",
  674. "DEFSNG",   "\xae",      "\256",
  675. "DEFDBL",   "\xaf",      "\257",
  676. "LINE",     "\xb0",      "\260",
  677. "WHILE",    "\xb1\xe9",  "\261\351",
  678. "WEND",     "\xb2",      "\262",
  679. "CALL",     "\xb3",      "\263",
  680. "WRITE",    "\xb7",      "\267",
  681. "OPTION",   "\xb8",      "\270",
  682. "RANDOMIZE","\xb9",      "\271",
  683. "OPEN",     "\xba",      "\272",
  684. "CLOSE",    "\xbb",      "\273",
  685. "LOAD",     "\xbc",      "\274",
  686. "MERGE",    "\xbd",      "\275",
  687. "SAVE",     "\xbe",      "\276",
  688. "COLOR",    "\xbf",      "\277",
  689. "CLS",      "\xc0",      "\300",
  690. "MOTOR",    "\xc1",      "\301",
  691. "BSAVE",    "\xc2",      "\302",
  692. "BLOAD",    "\xc3",      "\303",
  693. "SOUND",    "\xc4",      "\304",
  694. "BEEP",     "\xc5",      "\305",
  695. "PSET",     "\xc6",      "\306",
  696. "PRESET",   "\xc7",      "\307",
  697. "SCREEN",   "\xc8",      "\310",
  698. "KEY",      "\xc9",      "\311",
  699. "LOCATE",   "\xca",      "\312",
  700. "TO",       "\xcc",      "\314",
  701. "THEN",     "\xcd",      "\315",
  702. "TAB(",     "\xce",      "\316",
  703. "STEP",     "\xcf",      "\317",
  704. "USR",      "\xd0",      "\320",
  705. "FN",       "\xd1",      "\321",
  706. "NOT",      "\xd3",      "\323",
  707. "ERL",      "\xd4",      "\324",
  708. "ERR",      "\xd5",      "\325",
  709. "STRING$",  "\xd6",      "\326",
  710. "USING",    "\xd7",      "\327",
  711. "INSTR",    "\xd8",      "\330",
  712. "VARPTR",   "\xda",      "\332",
  713. "CSRLIN",   "\xdb",      "\333",
  714. "POINT",    "\xdc",      "\334",
  715. "OFF",      "\xdd",      "\335",
  716. "INKEY$",   "\xde",      "\336",
  717. ">",        "\xe6",      "\346",
  718. "=",        "\xe7",      "\347",
  719. "<",        "\xe8",      "\350",
  720. "+",        "\xe9",      "\351",
  721. "-",        "\xea",      "\352",
  722. "*",        "\xeb",      "\353",
  723. "/",        "\xec",      "\354",
  724. "^",        "\xed",      "\355",
  725. "AND",      "\xee",      "\356",
  726. "OR",       "\xef",      "\357",
  727. "XOR",      "\xf0",      "\360",
  728. "EQV",      "\xf1",      "\361",
  729. "IMP",      "\xf2",      "\362",
  730. "MOD",      "\xf3",      "\363",
  731. "\\",       "\xf4",      "\364",
  732. "CVI",      "\xfd\x81",  "\375\201",
  733. "CVS",      "\xfd\x82",  "\375\202",
  734. "CVD",      "\xfd\x83",  "\375\203",
  735. "MKI$",     "\xfd\x84",  "\375\204",
  736. "MKS$",     "\xfd\x85",  "\375\205",
  737. "MKD$",     "\xfd\x86",  "\375\206",
  738. "FILES",    "\xfe\x81",  "\376\201",
  739. "FIELD",    "\xfe\x82",  "\376\202",
  740. "SYSTEM",   "\xfe\x83",  "\376\203",
  741. "NAME",     "\xfe\x84",  "\376\204",
  742. "LSET",     "\xfe\x85",  "\376\205",
  743. "RSET",     "\xfe\x86",  "\376\206",
  744. "KILL",     "\xfe\x87",  "\376\207",
  745. "PUT",      "\xfe\x88",  "\376\210",
  746. "GET",      "\xfe\x89",  "\376\211",
  747. "RESET",    "\xfe\x8a",  "\376\212",
  748. "COMMON",   "\xfe\x8b",  "\376\213",
  749. "CHAIN",    "\xfe\x8c",  "\376\214",
  750. "DATE$",    "\xfe\x8d",  "\376\215",
  751. "TIME$",    "\xfe\x8e",  "\376\216",
  752. "PAINT",    "\xfe\x8f",  "\376\217",
  753. "COM",      "\xfe\x90",  "\376\220",
  754. "CIRCLE",   "\xfe\x91",  "\376\221",
  755. "DRAW",     "\xfe\x92",  "\376\222",
  756. "PLAY",     "\xfe\x93",  "\376\223",
  757. "TIMER",    "\xfe\x94",  "\376\224",
  758. "ERDEV",    "\xfe\x95",  "\376\225",
  759. "IOCTL",    "\xfe\x96",  "\376\226",
  760. "CHDIR",    "\xfe\x97",  "\376\227",
  761. "MKDIR",    "\xfe\x98",  "\376\230",
  762. "RMDIR",    "\xfe\x99",  "\376\231",
  763. "SHELL",    "\xfe\x9a",  "\376\232",
  764. "ENVIRON",  "\xfe\x9b",  "\376\233",
  765. "VIEW",     "\xfe\x9c",  "\376\234",
  766. "WINDOW",   "\xfe\x9d",  "\376\235",
  767. "PMAP",     "\xfe\x9e",  "\376\236",
  768. "PALETTE",  "\xfe\x9f",  "\376\237",
  769. "LCOPY",    "\xfe\xa0",  "\376\240",
  770. "CALLS",    "\xfe\xa1",  "\376\241",
  771. "PCOPY",    "\xfe\xa5",  "\376\245",
  772. "LOCK",     "\xfe\xa7",  "\376\247",
  773. "UNLOCK",   "\xfe\xa8",  "\376\250",
  774. "LEFT$",    "\xff\x81",  "\377\201",
  775. "RIGHT$",   "\xff\x82",  "\377\202",
  776. "MID$",     "\xff\x83",  "\377\203",
  777. "SGN",      "\xff\x84",  "\377\204",
  778. "INT",      "\xff\x85",  "\377\205",
  779. "ABS",      "\xff\x86",  "\377\206",
  780. "SQR",      "\xff\x87",  "\377\207",
  781. "RND",      "\xff\x88",  "\377\210",
  782. "SIN",      "\xff\x89",  "\377\211",
  783. "LOG",      "\xff\x8a",  "\377\212",
  784. "EXP",      "\xff\x8b",  "\377\213",
  785. "COS",      "\xff\x8c",  "\377\214",
  786. "TAN",      "\xff\x8d",  "\377\215",
  787. "ATN",      "\xff\x8e",  "\377\216",
  788. "FRE",      "\xff\x8f",  "\377\217",
  789. "INP",      "\xff\x90",  "\377\220",
  790. "POS",      "\xff\x91",  "\377\221",
  791. "LEN",      "\xff\x92",  "\377\222",
  792. "STR$",     "\xff\x93",  "\377\223",
  793. "VAL",      "\xff\x94",  "\377\224",
  794. "ASC",      "\xff\x95",  "\377\225",
  795. "CHR$",     "\xff\x96",  "\377\226",
  796. "PEEK",     "\xff\x97",  "\377\227",
  797. "SPACE$",   "\xff\x98",  "\377\230",
  798. "OCT$",     "\xff\x99",  "\377\231",
  799. "HEX$",     "\xff\x9a",  "\377\232",
  800. "LPOS",     "\xff\x9b",  "\377\233",
  801. "CINT",     "\xff\x9c",  "\377\234",
  802. "CSNG",     "\xff\x9d",  "\377\235",
  803. "CDBL",     "\xff\x9e",  "\377\236",
  804. "FIX",      "\xff\x9f",  "\377\237",
  805. "PEN",      "\xff\xa0",  "\377\240",
  806. "STICK",    "\xff\xa1",  "\377\241",
  807. "STRIG",    "\xff\xa2",  "\377\242",
  808. "EOF",      "\xff\xa3",  "\377\243",
  809. "LOC",      "\xff\xa4",  "\377\244",
  810. "LOF",      "\xff\xa5",  "\377\245",
  811. "","",""};
  812.                          
  813.   
  814. 8. Floating Point Literals (a fractional number e.g. 62.8 )
  815.    -----------------------
  816.    
  817.    The most difficult one of the lot!
  818.    
  819.    Coded in exponent and mantissa format, preceded by a character with ASCII
  820.    code 29 (Hex 1D, Octal 35).
  821.    
  822.    Consists of four bytes, the first three the mantissa, the last the
  823.    exponent. The mantissa is held lowest byte first, middle byte 
  824.    second, highest byte third.
  825.    
  826.    The mantissa is as would be expected, the successive bits of the
  827.    floating point number with the highest bit removed (it is always
  828.    1).
  829.    
  830.    The exponent is the power of two needed in order to shift the number
  831.    down until it is less than 1, however in the coding the highest bit
  832.    is inverted.
  833.    
  834.    Thus the floating point number 4.5 has an exponent of 3 (or -3 depending 
  835.    on how you look at it) and a mantissa of 1001 (in binary). Hence the 
  836.    coding would be:
  837.      
  838.      Hex 00 00 10 83  (Preceded by Hex 1D).
  839.      
  840.    I coded this in C as follows:
  841.      
  842. /* If dumnum is the double representation of the number then
  843.    charexp is the coded exponent and mant2 is the right most
  844.    byte, mant1 is the middle byte and mant0 is the left most
  845.    byte of the mantissa.  */
  846.   
  847.      
  848.    /* exponent                             */
  849.    iexp=(int)(log(dumnum)/log(2.0)); 
  850.    /* mantissa in lower three bytes        */
  851.    imant=(int)(dumnum*pow(2.0,23.0-(double)iexp));
  852.    imant=imant&0x007fffff;
  853.    /* convert to GW-BASIC representation   */
  854.    iexp++;
  855.    charexp=iexp^0x80;              
  856.    mant0=(imant>>16)&0xff;
  857.    mant1=(imant>>8)&0xff;
  858.    mant2=imant&0xff;
  859.    
  860. I have not investigated what happens for negative numbers, presumably
  861. the top bit of the mantissa is set to 1. And note that if dumnum is 
  862. negative the log(dumnum) will blow up!!
  863.      
  864. That's the lot!
  865.                                             
  866. Comments, queries, curses, praise to:-
  867.  
  868.           Martin Carradus,
  869.           3 Connaught Road,
  870.           Ilkley,
  871.           West Yorkshire,
  872.           LS29 8QW.
  873.           U.K.
  874.  
  875. If you write to me, please enclose an s.a.e.
  876.      
  877. P.S. On an Acorn Archimedes there is the operating system command:
  878.   
  879. *DUMP filename
  880.  
  881. which gives a hex and character dump of the file with the name 'filename'.
  882.  
  883. There is usually a similar command on other computers.
  884.  
  885.