mirror of
https://github.com/pkimpel/retro-220.git
synced 2026-02-18 13:27:46 +00:00
Commit updates to BALGOL DIRICHLET example.
1. Changes to DIRICHLET program that allow it to compile and run correctly. 2. Cosmetic changes to BALGOL-Main, BAC-Assembler, GEN-Assembler. 3. Commit software/tools/BALGOL-DumpAnalyzer.html script that does a parial analysis of a memory dump from a BALGOL compiler run. 4. Commit compiler tape image and generator deck configured to run on a system with 10000 words of memory.
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
* and their starting memory location may be pre-loaded into the assembler
|
||||
* before loading the source code.
|
||||
*
|
||||
* Output is a simulated line printer listing in the <iframe> of the web
|
||||
* Output is a simulated line printer listing in a text panel of the web
|
||||
* page from which the assembler is run. The output of Pass 1 is designed
|
||||
* to match the listing from which the compiler was transcribed, so that
|
||||
* it may be compared for proofing purposes. This listing is suppressed by
|
||||
|
||||
975
software/tools/BALGOL-DumpAnalyzer.html
Normal file
975
software/tools/BALGOL-DumpAnalyzer.html
Normal file
@@ -0,0 +1,975 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>BALGOL-DumpAnalyzer</title>
|
||||
<!--
|
||||
/***********************************************************************
|
||||
* 220/software/tools BALGOL-DumpAnalyzer.html
|
||||
************************************************************************
|
||||
* Copyright (c) 2018, Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* Memory dump analyzer for the 220 BALGOL compiler. Reads the text file of
|
||||
* a "Meatball" memory dump and analyzes certain data structures for the
|
||||
* BALGOL compiler, writing the result of the analysis to a text panel on
|
||||
* the browser window.
|
||||
*
|
||||
************************************************************************
|
||||
* 2018-05-31 P.Kimpel
|
||||
* Original version, cloned from retro-220 GEN-Assembler.html.
|
||||
***********************************************************************/
|
||||
-->
|
||||
<meta name="Author" content="Paul Kimpel">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
|
||||
<style>
|
||||
HTML {
|
||||
height: 100%}
|
||||
|
||||
BODY {
|
||||
position: relative;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
height: 100%;
|
||||
margin: 1ex}
|
||||
|
||||
DIV.heading {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 6px;
|
||||
font-weight: bold}
|
||||
|
||||
LABEL {
|
||||
font-size: smaller}
|
||||
|
||||
#DumpReaderPanel {
|
||||
position: relative;
|
||||
color: white;
|
||||
background-color: #666;
|
||||
width: 640px;
|
||||
border: 1px solid black;
|
||||
border-radius: 8px;
|
||||
font-size: smaller;
|
||||
padding: 8px}
|
||||
|
||||
#DumpReaderTable {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
width: 100%}
|
||||
#DumpReaderCol1 {
|
||||
width: 18ex}
|
||||
#DumpReaderCol2 {
|
||||
}
|
||||
#DumpReaderTable TD {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px}
|
||||
|
||||
#DumpFileSelector {
|
||||
width: 100%;
|
||||
border: 1px solid white}
|
||||
|
||||
#OptionsTable {
|
||||
position: relative;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
width: 640px}
|
||||
|
||||
#TextDiv {
|
||||
position: relative;
|
||||
height: 75%;
|
||||
width: 640px}
|
||||
|
||||
#TextPanel {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 8px;
|
||||
width: 100%;
|
||||
overflow: scroll;
|
||||
padding: 4px;
|
||||
border: 1px solid black;
|
||||
color: black;
|
||||
background-color: white;
|
||||
font-family: DejaVu Sans Mono, Consolas, Courier, monospace;
|
||||
font-size: 8pt;
|
||||
font-weight: normal}
|
||||
|
||||
#Spinner {
|
||||
position: absolute;
|
||||
top: 200px;
|
||||
left: 200px;
|
||||
z-index: 10}
|
||||
|
||||
.center {
|
||||
text-align: center}
|
||||
.rj {
|
||||
text-align: right}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class=heading>
|
||||
BALGOL Memory Dump Analyzer
|
||||
</div>
|
||||
|
||||
<div id=DumpReaderPanel>
|
||||
<table id=DumpReaderTable>
|
||||
<colgroup><col id=DumpReaderCol1><col id=DumpReaderCol2></colgroup>
|
||||
<tr><td>Load Dump & Go
|
||||
<td><input id=DumpFileSelector type=file size=90>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<table id=OptionsTable>
|
||||
<!--
|
||||
<thead>
|
||||
<tr>
|
||||
<th><label for=Pass1ListCheck>List Pass 1</label>
|
||||
<th><label for=Pass2ListCheck>List Pass 2</label>
|
||||
<th><label for=ChecksumCheck>Write Checksum</label>
|
||||
<th><label for=OutputModeSelect>Output Mode</label>
|
||||
<th>
|
||||
-->
|
||||
<tbody>
|
||||
<tr>
|
||||
<!--
|
||||
<td class=center>
|
||||
<input id=Pass1ListCheck type=checkbox value=1>
|
||||
<td class=center>
|
||||
<input id=Pass2ListCheck type=checkbox value=1 CHECKED>
|
||||
<td class=center>
|
||||
<input id=ChecksumCheck type=checkbox value=1>
|
||||
<td class=center>
|
||||
<select id=OutputModeSelect>
|
||||
<option value="" >No Object
|
||||
<option value=L SELECTED>Loadable Deck
|
||||
<option value=M >BALGOL ML Deck
|
||||
<option value=T >Object Tape
|
||||
</select>
|
||||
-->
|
||||
<td class=rj>
|
||||
<button id=SelectListing type=button>Select Listing</button>
|
||||
</table>
|
||||
|
||||
<div id=TextDiv><pre id=TextPanel></pre></div> <!-- Don't add any whitespace! -->
|
||||
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
|
||||
// Dump reader properties
|
||||
var buffer = "";
|
||||
var bufferLength = 0;
|
||||
var bufferOffset = 0;
|
||||
var sourceName = "?";
|
||||
|
||||
// Regular expressions
|
||||
var eolRex = /([^\n\r\f]*)((:?\r[\n\f]?)|\n|\f)?/g;
|
||||
var isNumericRex = /^[0-9]/;
|
||||
var isAlphaRex = /^[A-Z]/;
|
||||
var isLabelRex = /^[A-Z.0-9]/;
|
||||
var labelRex = /^([0-9]+|[A-Z][0-9.A-Z]*)(\-[0-9]+)? +/;
|
||||
var rTrimRex = /\s*$/;
|
||||
|
||||
var hashMod = 99; // compiler's hash modulus
|
||||
var MM = new Float64Array(10000); // main memory, 11-digit words
|
||||
var SCRTB = 4116; // address of compiler's scramble table
|
||||
var topAddr = 0; // top address in memory
|
||||
|
||||
var panel = $$("TextPanel");
|
||||
|
||||
var p10 = [ 1, // powers of 10 table
|
||||
10,
|
||||
100,
|
||||
1000,
|
||||
10000,
|
||||
100000,
|
||||
1000000,
|
||||
10000000,
|
||||
100000000,
|
||||
1000000000,
|
||||
10000000000,
|
||||
100000000000,
|
||||
1000000000000,
|
||||
10000000000000,
|
||||
100000000000000,
|
||||
1000000000000000,
|
||||
10000000000000000];
|
||||
|
||||
var xlateANSI220 = [ // translate ANSI to 220 internal character codes
|
||||
// 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-0F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10-1F
|
||||
0, 0, 0, 33, 13, 24, 10, 34, 24, 4, 14, 10, 23, 20, 3, 21, // 20-2F
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 13, 4, 33, 0, 0, // 30-3F
|
||||
34, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, // 40-4F
|
||||
57, 58, 59, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, // 50-5F
|
||||
0, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, // 60-6F
|
||||
57, 58, 59, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0]; // 70-7F
|
||||
|
||||
var xlate220ANSI = [ // translate internal B220 code to ANSI (Algol glyphs)
|
||||
// 00 01 02 03 04 05 06 07 08 09
|
||||
" ", "?", "9", ".", ")", "?", "?", "?", "?", "?", // 00-09
|
||||
"+", "?", "?", "$", "*", "*", "$", "?", "?", "?", // 10-19
|
||||
"-", "/", "?", ",", "(", "?", ",", "?", "?", "?", // 20-29
|
||||
"?", "?", "?", "=", "@", "\\", "?", "?", "?", "?", // 30-39
|
||||
"?", "A", "B", "C", "D", "E", "F", "G", "H", "I", // 40-49
|
||||
"?", "J", "K", "L", "M", "N", "O", "P", "Q", "R", // 50-59
|
||||
"?", "?", "S", "T", "U", "V", "W", "X", "Y", "Z", // 60-69
|
||||
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", // 70-79
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", // 80-89
|
||||
"?", "?", "?", "?", "?", "?", "?", "?", "?", "?"]; // 90-99
|
||||
|
||||
var signValues = { // numeric values of sign column
|
||||
" ": 0,
|
||||
"+": 0,
|
||||
"0": 0,
|
||||
"-": 1,
|
||||
"1": 1,
|
||||
"2": 2,
|
||||
"3": 3,
|
||||
"4": 4,
|
||||
"5": 5,
|
||||
"6": 6,
|
||||
"7": 7,
|
||||
"8": 8,
|
||||
"9": 9};
|
||||
|
||||
var symbolType = [
|
||||
"Undetermined", // 0
|
||||
"Variable", // 1
|
||||
"Literal?", // 2
|
||||
"Intrinsic?", // 3
|
||||
"Library Routine", // 4
|
||||
"Array", // 5
|
||||
"Symbol#6", // 6
|
||||
"Reserved Word", // 7
|
||||
"Procedure", // 8
|
||||
"Label"]; // 9
|
||||
|
||||
var variableType = [
|
||||
"Real", // 0
|
||||
"Integer", // 1
|
||||
"Type#2", // 2
|
||||
"Untyped?", // 3
|
||||
"Generic?", // 4
|
||||
"Type#5", // 5
|
||||
"Type#6", // 6
|
||||
"Type#7", // 7
|
||||
"Type#8", // 8
|
||||
"Type#9"]; // 9
|
||||
|
||||
var stackHeads = {
|
||||
AVAIL: {addr: 273, title: "FREED-UP LOCATIONS"},
|
||||
FUNS: {addr: 274, title: "CONTROL OF PROCEDURE,FUNCTION CALLS"},
|
||||
OP: {addr: 275, title: "OPERATORS WAITING TO BE USED"},
|
||||
ARAS: {addr: 276, title: "INCREMENT WORDS FOR ARRAY"},
|
||||
DIMS: {addr: 277, title: "ARRAY DIMENSIONS"},
|
||||
EXEC: {addr: 278, title: "FORWARD REFERENCES TO FOR LOOP"},
|
||||
FV: {addr: 279, title: "FOR VARIABLE"},
|
||||
MULS: {addr: 280, title: "DIMENSIONS"},
|
||||
MODE: {addr: 281, title: "MODE TRANSLATOR IS IN (INITIALLY NORMAL)"},
|
||||
MULT: {addr: 282, title: "MULS STACK BACKWARDS"},
|
||||
OPRND: {addr: 283, title: "OPERANDS WAITING TO BE USED"},
|
||||
PAREF: {addr: 284, title: "REFERENCE TO PROCEDURE PARAMETERS"},
|
||||
PR1: {addr: 285, title: "PREFIXES OUTSIDE OF PROCEDURES"},
|
||||
PR3: {addr: 286, title: "CURRENT PREFIXES"},
|
||||
RV: {addr: 287, title: "FOR VARIABLE (BACKWARDS)"},
|
||||
SAVET: {addr: 288, title: "TEMP STORAGE CELLS SAVED"},
|
||||
SETUP: {addr: 289, title: "REFERENCE TO A PROCEDURE PARAMETER"},
|
||||
TEMPS: {addr: 290, title: "TEMP STORAGE CELLS AVAILABLE"},
|
||||
XVP: {addr: 291, title: "ARRAYS IN MULTIPLE INDEXING"},
|
||||
DUMBS: {addr: 292, title: "LEVELS WHERE DUMP CARD APPEARS"}};
|
||||
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* Miscellaneous Utilities *
|
||||
*******************************************************************/
|
||||
|
||||
/**************************************/
|
||||
function $$(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function padTo(s, len) {
|
||||
/* Pads the string "s" on the right with spaces or truncates it as
|
||||
necessary to a length of "len" */
|
||||
var result = s;
|
||||
|
||||
if (result.length > len) {
|
||||
result = result.substring(0, len);
|
||||
} else {
|
||||
while (result.length-len > 8) {
|
||||
result += " ";
|
||||
}
|
||||
|
||||
while (result.length < len) {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function padLeft(s, len, fill) {
|
||||
/* Pads the string "s" on the left to length "len" with the filler character
|
||||
"fill". If fill is empty or missing, space is used. If the initial string is
|
||||
longer than "len", it is truncated on the left to that length */
|
||||
var pad = (fill || " ").charAt(0);
|
||||
var result = s.toString();
|
||||
var rLen = result.length;
|
||||
|
||||
if (rLen > len) {
|
||||
result = result.substring(rLen-len);
|
||||
} else {
|
||||
while (rLen < len) {
|
||||
result = pad + result;
|
||||
++rLen;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function padRight(s, len, fill) {
|
||||
/* Pads the string "s" on the right to length "len" with the filler character
|
||||
"fill". If fill is empty or missing, space is used. If the initial string is
|
||||
longer than "len", it is truncated on the right to that length */
|
||||
var pad = (fill || " ").charAt(0);
|
||||
var result = s.toString();
|
||||
var rLen = s.length;
|
||||
|
||||
if (rLen > len) {
|
||||
result = result.substring(0, len);
|
||||
} else {
|
||||
while (rLen < len) {
|
||||
result = result + pad;
|
||||
++rLen;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function rTrim(s) {
|
||||
/* Returns the string "s" stripped of any trailing whitespace */
|
||||
var x = s.search(rTrimRex);
|
||||
|
||||
if (x < 0 ) {
|
||||
return s;
|
||||
} else if (x < 1) {
|
||||
return "";
|
||||
} else {
|
||||
return s.substring(0, x);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function tensComp(value) {
|
||||
/* If "value" is algebraically negative, returns its 11-digit tens
|
||||
complement. Otherwise returns the 11-digit value */
|
||||
|
||||
if (value < 0) {
|
||||
return p10[11] + value%p10[11];
|
||||
} else {
|
||||
return value%p10[11];
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function getSign(word) {
|
||||
/* Extracts the sign digit from a word value and returns it */
|
||||
|
||||
return ((word - word%p10[10])/p10[10])%10;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function applySign(word, sign) {
|
||||
/* Applies an unsigned "sign" digit to a 220 "word" value. If the word
|
||||
value is algebraically negative, it is first converted to a 10-digit
|
||||
number with a 220 sign in the 11-th high-order digit. The low-order bit
|
||||
of "sign" and the low-order bit of the word's sign digit are XOR-ed so
|
||||
that each of those bits designates negation. Returns the new value as an
|
||||
11-digit unsigned 220 word in binary */
|
||||
var s = 0;
|
||||
var value = 0;
|
||||
|
||||
if (word < 0) {
|
||||
value = (-word)%p10[10];
|
||||
s = 1;
|
||||
} else {
|
||||
value = word%p10[10];
|
||||
s = (word%p10[11] - value)/p10[10];
|
||||
}
|
||||
|
||||
return (sign%10 ^ s)*p10[10] + value;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function getField(word, sL) {
|
||||
/* Extracts an n-digit value from an 11-digit "word" and returns it.
|
||||
"sL" is the same as for putField(). The word is a Javascript Number
|
||||
object, but is treated as if it represents an 11-digit decimal integer */
|
||||
var L = sL%10;
|
||||
var s = (sL%100 - L)/10;
|
||||
var result = applySign(word, 0);
|
||||
|
||||
s = (s == 0 ? 0 : 10-s);
|
||||
L = (L == 0 ? 10 : L);
|
||||
|
||||
if (sL < 0 || sL > 99 || s+L > 11) {
|
||||
result = -1;
|
||||
} else {
|
||||
result = (result%p10[s+L] - result%p10[s])/p10[s];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function putField(word, value, sL) {
|
||||
/* Inserts an n-digit "value" into designated digits of an 11-digit
|
||||
"word". "sL" is the partial-word field in standard 220 start-Length
|
||||
notation. Note that Javascript flags literal integers of the form "0n"
|
||||
as the old C-style octal literal notation is deprecated. This routine
|
||||
uses only the two low-order digits of "sL", however, so you can pass sL
|
||||
literal values like 104 (or even 57321604) for /04 without ill effect.
|
||||
The "value" and "word" are Javascript Number objects, but are treated as
|
||||
if they represent 11-digit decimal integers. If value is negative, it is
|
||||
converted to its 10s-complement value before insertion into word.
|
||||
Returns a new word with the inserted field */
|
||||
var L = sL%10;
|
||||
var s = (sL%100 - L)/10;
|
||||
var upperPart = 0;
|
||||
var lowerPart = 0;
|
||||
var result = applySign(word, 0);
|
||||
|
||||
s = (s == 0 ? 0 : 10-s);
|
||||
L = (L == 0 ? 10 : L);
|
||||
|
||||
if (sL < 0 || s+L > 11) {
|
||||
printError("INVALID /SL VALUE: ", sL);
|
||||
} else {
|
||||
upperPart = result%p10[11] - result%p10[s+L];
|
||||
if (s > 0) {
|
||||
lowerPart = result%p10[s];
|
||||
}
|
||||
|
||||
result = (tensComp(value)%p10[L])*p10[s] + upperPart + lowerPart;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* Memory Dump Input Module *
|
||||
*******************************************************************/
|
||||
|
||||
/**************************************/
|
||||
function readALine() {
|
||||
/* Reads one line image from the buffer. Returns the text of the line,
|
||||
or null if the buffer is exhausted */
|
||||
var bx = bufferOffset; // current buffer offset
|
||||
var line; // line image, padded/truncated to 80 columns
|
||||
var match; // regular expression match result
|
||||
|
||||
if (bx >= bufferLength) {
|
||||
return null;
|
||||
} else {
|
||||
eolRex.lastIndex = bx;
|
||||
match = eolRex.exec(buffer);
|
||||
if (!match) {
|
||||
line = "";
|
||||
} else {
|
||||
bx += match[0].length;
|
||||
line = match[1];
|
||||
}
|
||||
|
||||
bufferOffset = bx;
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* Output Listing Interface *
|
||||
*******************************************************************/
|
||||
|
||||
/**************************************/
|
||||
function clearPanel() {
|
||||
/* Clears the text panel */
|
||||
var kid;
|
||||
|
||||
while (kid = panel.firstChild) {
|
||||
panel.removeChild(kid);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function xlate220Word(word) {
|
||||
/* Translate 10 digits in a 220 word to five ANSI characters */
|
||||
var chars = ""; // translated characters
|
||||
var code = 0; // current 220 character code
|
||||
var count = 5; // chars/word
|
||||
|
||||
while (count > 0) {
|
||||
code = word%100;
|
||||
chars = xlate220ANSI[code] + chars;
|
||||
word = (word - code)/100;
|
||||
--count;
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function printLine(text) {
|
||||
/* Appends "text"+NL as a new text node to the panel DOM element */
|
||||
var e = document.createTextNode(rTrim(text) + "\n");
|
||||
|
||||
panel.appendChild(e);
|
||||
panel.scrollTop += 30
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function formatWord(word) {
|
||||
/* Formats the digits in a word and returns the resulting string */
|
||||
|
||||
return ((word - word%p10[10])/p10[10]).toString() + " " +
|
||||
padLeft((word%p10[10] - word%p10[ 6])/p10[ 6], 4, "0") + " " +
|
||||
padLeft((word%p10[ 6] - word%p10[ 4])/p10[ 4], 2, "0") + " " +
|
||||
padLeft((word%p10[ 4]), 4, "0");
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function parseInteger(text, token) {
|
||||
/* Parses a decimal number up to 11 digits in length starting at the
|
||||
current offset in "text". Returns the 11-digit decimal string in
|
||||
token.text and the arithmetic value as the function result */
|
||||
var c = ""; // current parse character
|
||||
var length = text.length; // length of operand string
|
||||
var raw = ""; // raw parsed token text
|
||||
var result = 0; // arithmetic result (binary)
|
||||
var x = token.offset; // current offset into operand string
|
||||
|
||||
token.type = tokInteger;
|
||||
while (x < length) {
|
||||
c = text.charAt(x);
|
||||
if (isNumericRex.test(c)) {
|
||||
++x;
|
||||
raw += c;
|
||||
} else {
|
||||
break; // out of while loop
|
||||
}
|
||||
}
|
||||
|
||||
token.newOffset = x;
|
||||
if (raw.length > 11) {
|
||||
printError("NUMERIC LITERAL LONGER THAN 11 DIGITS: " + raw);
|
||||
raw = raw.substring(raw.length-11);
|
||||
}
|
||||
|
||||
token.word = result = parseInt(raw, 10);
|
||||
token.text = padLeft(result, 11, "0");
|
||||
token.value = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* Analysis Routines *
|
||||
*******************************************************************/
|
||||
|
||||
/**************************************/
|
||||
function memDump(start, count) {
|
||||
/* Formats the words in a specified region of the memory array MM */
|
||||
var addr = start;
|
||||
var left = 0;
|
||||
var line = "";
|
||||
var word = 0;
|
||||
var x = 0;
|
||||
|
||||
while (count > 0) {
|
||||
line = padLeft(addr, 4, "0");
|
||||
left = Math.max(count, 5);
|
||||
for (x=0; x<left; ++x) {
|
||||
word = MM[addr+x];
|
||||
line += " " + getSign(word) + " " + padLeft(word, 10, "0");
|
||||
}
|
||||
|
||||
printLine(line);
|
||||
addr += 5;
|
||||
count -= left;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function dumpSymbolTable__ORIG() {
|
||||
/* Analyzes and formats the compiler's symbol table */
|
||||
var addr = 0;
|
||||
var count = hashMod;
|
||||
var hash = 0;
|
||||
var len = 0;
|
||||
var line = "";
|
||||
var symLink = 0;
|
||||
var word = 0;
|
||||
var x = 0;
|
||||
|
||||
printLine("\nSymbol Table:\n");
|
||||
while (hash < hashMod) {
|
||||
addr = SCRTB + hash;
|
||||
printLine("\nHash " + padLeft(hash, 2, "0"));
|
||||
word = MM[addr];
|
||||
if (word) {
|
||||
do {
|
||||
len = getField(word, 22);
|
||||
line = " " + padLeft(addr, 4, "0") + ": " + formatWord(word) + " -> ";
|
||||
symLink = getField(word, 64);
|
||||
addr = getField(word, 4);
|
||||
|
||||
word = MM[symLink];
|
||||
line += padLeft(symLink, 4, "0") + ": " + formatWord(word) + " \"";
|
||||
count = len;
|
||||
x = 1;
|
||||
while (count > 10) {
|
||||
line += xlate220Word(MM[symLink+x]);
|
||||
count -= 10;
|
||||
++x;
|
||||
} // while count
|
||||
|
||||
line += xlate220Word(MM[symLink+x]).substring(0, count/2) + "\"";
|
||||
printLine(line);
|
||||
|
||||
// Classify symbol
|
||||
x = getField(word, 11);
|
||||
line = padRight("", 16) + symbolType[x] + " @" + padLeft(getField(word, 64), 4, "0");
|
||||
switch (x) {
|
||||
case 1: // variable
|
||||
line += ", " + variableType[getField(word, 21)];
|
||||
break;
|
||||
case 3: // intrinsic
|
||||
line += ", " + variableType[getField(word, 21)];
|
||||
break;
|
||||
case 5: // array
|
||||
line += ", " + variableType[getField(word, 21)];
|
||||
break;
|
||||
case 8: // procedure/function
|
||||
line += ", " + variableType[getField(word, 21)] + ", Level=" + getField(word, 1);
|
||||
if (getSign(word) == 8) {
|
||||
line += ", External";
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
|
||||
printLine(line);
|
||||
word = MM[addr];
|
||||
} while (addr);
|
||||
}
|
||||
|
||||
++hash;
|
||||
} // while hash
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function dumpSymbolTable() {
|
||||
/* Analyzes and formats the compiler's symbol table */
|
||||
var addr = 0;
|
||||
var hash = 0;
|
||||
var len = 0;
|
||||
var line = "";
|
||||
var sym = [];
|
||||
var symLink = 0;
|
||||
var symType = 0;
|
||||
var word = 0;
|
||||
var x = 0;
|
||||
|
||||
function compare(a, b) {
|
||||
return (a.id < b.id ? -1 :
|
||||
a.id > b.id ? 1 :
|
||||
a.addr < b.addr ? -1 : 1);
|
||||
}
|
||||
|
||||
printLine("\nSymbol Table:\n");
|
||||
for (hash=0; hash<hashMod; ++hash) {
|
||||
addr = SCRTB + hash;
|
||||
word = MM[addr];
|
||||
if (word) {
|
||||
do {
|
||||
// Translate the symbol ID to ASCII
|
||||
symLink = getField(word, 64);
|
||||
len = getField(word, 22);
|
||||
line = "";
|
||||
x = 1;
|
||||
while (len > 10) {
|
||||
line += xlate220Word(MM[symLink+x]);
|
||||
len -= 10;
|
||||
++x;
|
||||
} // while len
|
||||
|
||||
line += xlate220Word(MM[symLink+x]).substring(0, len/2);
|
||||
|
||||
// Push the entry into the table for sorting
|
||||
sym.push({hash: hash, addr: addr, id: line});
|
||||
addr = getField(word, 4);
|
||||
word = MM[addr];
|
||||
} while (addr);
|
||||
}
|
||||
} // while hash
|
||||
|
||||
sym.sort(compare);
|
||||
|
||||
for (x=0; x<sym.length; ++x) {
|
||||
printLine(sym[x].id);
|
||||
addr = sym[x].addr;
|
||||
word = MM[addr];
|
||||
line = " " + padLeft(sym[x].hash, 2, "0") + " " + padLeft(addr, 4, "0") + ": " + formatWord(word) + " -> ";
|
||||
addr = getField(word, 4);
|
||||
symLink = getField(word, 64);
|
||||
word = MM[symLink];
|
||||
line += padLeft(symLink, 4, "0") + ": " + formatWord(word) + ", ";
|
||||
|
||||
// Classify symbol
|
||||
symType = getField(word, 11);
|
||||
line += symbolType[symType] + " @" + padLeft(getField(word, 64), 4, "0");
|
||||
switch (symType) {
|
||||
case 1: // variable
|
||||
line += ", " + variableType[getField(word, 21)];
|
||||
break;
|
||||
case 3: // intrinsic
|
||||
line += ", " + variableType[getField(word, 21)];
|
||||
break;
|
||||
case 5: // array
|
||||
line += ", " + variableType[getField(word, 21)];
|
||||
break;
|
||||
case 8: // procedure/function
|
||||
line += ", " + variableType[getField(word, 21)] + ", Level=" + getField(word, 1);
|
||||
if (getSign(word) == 8) {
|
||||
line += ", External";
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
|
||||
printLine(line);
|
||||
} // for x
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function dumpStacks() {
|
||||
/* Dumps all compiler stacks from associative memory */
|
||||
var addr = 0;
|
||||
var entry = null;
|
||||
var key = "";
|
||||
var line = "";
|
||||
var word = 0;
|
||||
|
||||
printLine("\nCompiler Stacks:");
|
||||
for (key in stackHeads) {
|
||||
printLine("");
|
||||
entry = stackHeads[key];
|
||||
addr = entry.addr;
|
||||
word = MM[addr];
|
||||
printLine(padRight(key + ":", 8) + padLeft(addr, 4, "0") + ": " +
|
||||
formatWord(word) + ", " + entry.title);
|
||||
addr = getField(word, 4);
|
||||
while (addr) {
|
||||
word = MM[addr];
|
||||
printLine(padRight("", 12) + padLeft(addr, 4, "0") + ": " + formatWord(word));
|
||||
addr = getField(word, 4);
|
||||
} // while addr
|
||||
} // for key
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function analyzeDump() {
|
||||
/* Analyzes and formats the data in the memory array MM */
|
||||
var addr = 0;
|
||||
var line = "";
|
||||
var word = 0;
|
||||
var x = 0;
|
||||
|
||||
dumpSymbolTable();
|
||||
dumpStacks();
|
||||
|
||||
$$("TextDiv").removeChild($$("Spinner")); // remove the spinner image
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function loadDumpFile() {
|
||||
/* Loads the memory dump text file, parsing the 11-digit words from the
|
||||
text, converting them to Number objects, and storing them in the MM
|
||||
array. Then calls analyzeDump() to begin the analysis */
|
||||
var addr = 0;
|
||||
var line = "";
|
||||
var nextAddr = 0;
|
||||
var text = "";
|
||||
var word = 0;
|
||||
var x = 0;
|
||||
|
||||
// Skip any initial empty lines
|
||||
do {
|
||||
line = readALine();
|
||||
} while (line !== null && rTrim(line).length == 0);
|
||||
|
||||
if (line) {
|
||||
// Check for a valid dump header
|
||||
if (line.indexOf("retro-220 Processor State and Memory Dump") != 0) {
|
||||
alert("Not a valid 220 Memory Dump file");
|
||||
} else {
|
||||
// Skip the processor-state lines after the header
|
||||
do {
|
||||
line = readALine();
|
||||
} while (line !== null && line.indexOf("Memory:") != 0);
|
||||
|
||||
// Parse the lines of the memory dump
|
||||
do {
|
||||
line = readALine();
|
||||
if (line) {
|
||||
text = line.substring(0, 4);
|
||||
if (text == "....") {
|
||||
// Ignore suppressed duplicate lines
|
||||
} else {
|
||||
addr = parseInt(text, 10);
|
||||
if (isNaN(addr)) {
|
||||
// Ignore lines that don't begin with a valid address
|
||||
} else {
|
||||
// Fill in words from any suppressed duplicate lines
|
||||
while (nextAddr < addr) {
|
||||
MM[nextAddr] = MM[nextAddr-5];
|
||||
++nextAddr;
|
||||
} // while nextAddr
|
||||
|
||||
// Parse the words of the dump and store in MM
|
||||
for (x=4; x<74; x+=14) {
|
||||
word = parseInt(line.substring(x+2, x+3) + line.substring(x+4, x+14), 10);
|
||||
if (isNaN(word)) {
|
||||
alert("Invalid word, addr=" + addr);
|
||||
break;
|
||||
} else {
|
||||
MM[addr] = word;
|
||||
++addr;
|
||||
}
|
||||
} // for x
|
||||
|
||||
nextAddr = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (line !== null && line.indexOf("End dump, memory size:") != 0);
|
||||
|
||||
topAddr = nextAddr-1;
|
||||
//alert("Memory dump loaded, topAddr=" + topAddr.toString());
|
||||
|
||||
analyzeDump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* Initialization and Termination *
|
||||
*******************************************************************/
|
||||
|
||||
/**************************************/
|
||||
function loadSourceFile(ev) {
|
||||
/* Handle the <input type=file> onchange event when a source file is
|
||||
selected */
|
||||
var e; // spinner image DOM element
|
||||
var f = ev.target.files[0];
|
||||
var reader = new FileReader();
|
||||
|
||||
function fileLoader_onLoad(ev) {
|
||||
/* Handles the onload event for a readAsText FileReader */
|
||||
|
||||
buffer = ev.target.result;
|
||||
bufferOffset = 0;
|
||||
bufferLength = buffer.length;
|
||||
setTimeout(loadDumpFile, 100);
|
||||
}
|
||||
|
||||
sourceName = f.name;
|
||||
/********************
|
||||
alert("Source file selected: " + f.name +
|
||||
"\nModified " + f.lastModifiedDate +
|
||||
"\nType=" + f.type + ", Size=" + f.size + " octets");
|
||||
********************/
|
||||
|
||||
// initiate the spinner to run while running
|
||||
e = document.createElement("img");
|
||||
e.src = "../../webUI/resources/ajax-spinner.gif";
|
||||
e.id = "Spinner";
|
||||
$$("TextDiv").appendChild(e);
|
||||
|
||||
reader.onload = fileLoader_onLoad;
|
||||
reader.readAsText(f);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function checkBrowser() {
|
||||
/* Checks whether this browser can support the necessary stuff */
|
||||
var missing = "";
|
||||
|
||||
if (!window.File ) {missing += ", File"}
|
||||
if (!window.FileReader ) {missing += ", FileReader"}
|
||||
if (!window.FileList ) {missing += ", FileList"}
|
||||
if (!window.DOMTokenList) {missing += ", DOMTokenList"}
|
||||
if (!window.ArrayBuffer ) {missing += ", ArrayBuffer"}
|
||||
if (!window.DataView ) {missing += ", DataView"}
|
||||
if (!window.Promise ) {missing += ", Promise"}
|
||||
if (!window.JSON ) {missing += ", JSON"}
|
||||
|
||||
if (missing.length == 0) {
|
||||
return false;
|
||||
} else {
|
||||
alert("No can do... your browser does not\n" +
|
||||
"support the following features:\n" + missing.substring(2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/******************** Start of window.onload() ********************/
|
||||
if (checkBrowser()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$$("DumpFileSelector").value = null; // clear any prior file selection
|
||||
$$("DumpFileSelector").addEventListener("change", loadSourceFile, false);
|
||||
|
||||
/********************
|
||||
pass1List = $$("Pass1ListCheck").checked;
|
||||
$$("Pass1ListCheck").addEventListener("click", function(ev) {
|
||||
pass1List = ev.target.checked;
|
||||
});
|
||||
|
||||
pass2List = $$("Pass2ListCheck").checked;
|
||||
$$("Pass2ListCheck").addEventListener("click", function(ev) {
|
||||
pass2List = ev.target.checked;
|
||||
});
|
||||
|
||||
outputChecksum = $$("ChecksumCheck").checked;
|
||||
$$("ChecksumCheck").addEventListener("click", function(ev) {
|
||||
outputChecksum = ev.target.checked;
|
||||
});
|
||||
********************/
|
||||
|
||||
$$("SelectListing").addEventListener("click", function(ev) {
|
||||
window.getSelection().selectAllChildren($$("TextPanel"));
|
||||
});
|
||||
|
||||
}, false);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -33,7 +33,7 @@
|
||||
* and their starting memory location may be pre-loaded into the assembler
|
||||
* before loading the source code.
|
||||
*
|
||||
* Output is a simulated line printer listing in the <iframe> of the web
|
||||
* Output is a simulated line printer listing in a text panel of the web
|
||||
* page from which the assembler is run. The output of Pass 2 is a
|
||||
* traditional assembler listing, with words of generated object code
|
||||
* and data. It is designed to match the listing from which the compiler
|
||||
@@ -2113,7 +2113,7 @@ window.addEventListener("load", function() {
|
||||
case "X": // copy zone half-column for sign
|
||||
emitBandDigits(1, 1);
|
||||
dx += 1;
|
||||
break;
|
||||
break;
|
||||
case "Y": // delete half-column (usually for overpunched sign)
|
||||
emitBandDigits(3, 1);
|
||||
colCount += 1;
|
||||
@@ -2208,7 +2208,7 @@ window.addEventListener("load", function() {
|
||||
case "X": // copy zone digit for sign
|
||||
emitBandDigits(1, 1);
|
||||
dx += 1;
|
||||
break;
|
||||
break;
|
||||
case "Y": // supply numeric half-column for standalone sign
|
||||
emitBandDigits(0, 1);
|
||||
colCount += 1;
|
||||
|
||||
Reference in New Issue
Block a user